/*
* Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Business Objects nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* NonGenericVars.java
* Creation date: (July 17, 2000)
* By: Bo Ilic
*/
package org.openquark.cal.compiler;
/**
* Lists of non-generic type variables. Non-generic variables are variables
* that are not free to be specialized independently. For example, a variable bound by a lambda
* abstraction. For example, in (\a -> a 2 + a True), a is non-generic, and the whole expression is
* ill typed.
*
* It is important to note that a type variable that occurs in an instantiation of a non-generic
* type variable are copied by CopyEnv in the same way as the official non-generic variables- i.e.
* by reference. The same applies to record variables.
*
* NonGenericVars is a persistent list in the sense that extending the list to add a new non-generic
* variable does not alter the old list. The null value is used to represent the empty list.
*
* Creation date: (July 17, 2000)
* @author Bo Ilic
*/
class NonGenericVars {
private final TypeVar head;
private final NonGenericVars tail;
/**
* Insert the method's description here.
* @param tail
* @param head
*/
private NonGenericVars(NonGenericVars tail, TypeVar head) {
if (head == null) {
throw new NullPointerException();
}
this.head = head;
this.tail = tail;
}
/**
* Extend nonGenericVars by the head type variable. This is a static in order to easily handle empty
* nonGenericVars lists which occur quite often.
*
* @return NonGenericVars
* @param tail
* @param head
*/
static NonGenericVars extend(NonGenericVars tail, TypeVar head) {
if (head == null) {
throw new NullPointerException();
}
return new NonGenericVars(tail, head);
}
/**
* Whether an uninstantiated type variable is generic w.r.t. a list of
* non-generic type variables. What this means is that typeVar is not one of the nonGenericVars,
* nor is it one of TypeVars occurring in any instantiation of the nonGenericVars
*
* Creation date: (7/17/00 4:47:59 PM)
* @return boolean
* @param uninstantiatedTypeVar
*/
boolean isGenericTypeVar(TypeVar uninstantiatedTypeVar) {
if (uninstantiatedTypeVar.getInstance() != null) {
throw new IllegalArgumentException();
}
for (NonGenericVars nonGenericVars = this; nonGenericVars != null; nonGenericVars = nonGenericVars.tail) {
if (nonGenericVars.head.containsUninstantiatedTypeVar(uninstantiatedTypeVar)) {
return false;
}
}
return true;
}
/**
* Returns false if the uninstantiated record var occurs somewhere in the TypeExpr of any of the
* non generic variables.
* @param uninstantiatedRecordVar
* @return boolean
*/
boolean isGenericRecordVar(RecordVar uninstantiatedRecordVar) {
if (uninstantiatedRecordVar.getInstance() != null) {
throw new IllegalArgumentException();
}
for (NonGenericVars nonGenericVars = this; nonGenericVars != null; nonGenericVars = nonGenericVars.tail) {
if (nonGenericVars.head.containsRecordVar(uninstantiatedRecordVar)) {
return false;
}
}
return true;
}
@Override
public String toString() {
StringBuilder result = new StringBuilder();
int i = 0;
PolymorphicVarContext pvc = PolymorphicVarContext.make();
for (NonGenericVars nonGenericVars = this; nonGenericVars != null; nonGenericVars = nonGenericVars.tail) {
result.append("var#").append(i).append(" = ");
result.append(nonGenericVars.head.toString(pvc, null));
result.append('\n');
++i;
}
return result.toString();
}
}