/*
* 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.
*/
/*
* ApplicationInfo.java
* Created: Jun 3, 2003
* By: Bo Ilic
*/
package org.openquark.cal.compiler;
import java.util.Set;
/**
* Information on an application occurring within the definition of the function whose definition
* we are patching up to augment with a dictionary variable or dictionary literal value.
* Creation date: (April 9, 2001)
* @author Bo Ilic
*/
class ApplicationInfo {
/** entity of the function (or class method) being applied. */
private final FunctionalAgent functionalAgent;
/** parse tree of the applied function */
private final ParseTreeNode appliedFunctionNode;
/**
* (PolymorphicVar Set)
* the set of generic, type-class constrained, and uninstantiated type or record variables that occur within
* the type of the applied function ordered by their initial occurrence within the type.
*/
private Set<PolymorphicVar> genericClassConstrainedPolymorphicVars;
/**
* the type expression of the function that is being applied. The type variables
* will be those used in establishing the type of the function that is being defined (the enclosing
* function definition).
*/
private final TypeExpr typeExpr;
/**
* true if the function that is being applied has had its defining expression type checked, and all the defining
* expressions of the functions in its declaration group type checked. More concretely, this means if:
* let f1 x1 = e1; f2 x2 = e2; in e3, then this is true for f1 if e1 and e2 have been type checked.
* After this point, we know what the generic type and record variables in the type expression of the function are.
*/
private final boolean polymorphic;
/**
* Constructs an ApplicationInfo object.
*
* @param functionalAgent entity of the applied function
* @param appliedFunctionNode parse tree of the applied function
* @param typeExpr the type expression of the function that is being applied. The type variables
* will be those used in establishing the type of the function that is being defined (the enclosing
* function definition).
* @param nonGenericVars the non-generic type variables at the point at which this application is being used.
* @param polymorphic true if the function that is being applied has had its defining expression type checked, and all the defining
* expressions of the functions in its declaration group type checked. More concretely, this means if:
* let f1 x1 = e1; f2 x2 = e2; in e3, then this is true for f1 if e1 and e2 have been type checked.
* After this point, we know what the generic type and record variables in the type expression of the function are.
*/
ApplicationInfo(FunctionalAgent functionalAgent, ParseTreeNode appliedFunctionNode, TypeExpr typeExpr, NonGenericVars nonGenericVars, boolean polymorphic) {
if (functionalAgent == null || appliedFunctionNode == null || typeExpr == null) {
throw new NullPointerException();
}
this.functionalAgent = functionalAgent;
this.appliedFunctionNode = appliedFunctionNode;
this.typeExpr = typeExpr;
this.polymorphic = polymorphic;
if (polymorphic) {
finishedTypeCheckingFunction(nonGenericVars);
}
}
ParseTreeNode getAppliedFunctionNode() {
return appliedFunctionNode;
}
/**
* If the application function is "f" this can be called after the defining expressions of the declaration group involving f
* have been type checked.
* @param nonGenericVars
*/
void finishedTypeCheckingFunction(NonGenericVars nonGenericVars) {
if (genericClassConstrainedPolymorphicVars != null) {
throw new IllegalStateException();
}
genericClassConstrainedPolymorphicVars = typeExpr.getGenericClassConstrainedPolymorphicVars(nonGenericVars);
}
/**
* Should not be called until after the top-level declaration group in which this application function is defined has been
* type checked.
* @return Set (PolymorphicVar Set i.e. each element either a TypeVar or RecordVar) the generic, type-class
* constrained type and record variables occurring within the type expression. These are the ones for which
* dictionary variables or dictionary constants must be added to the application in order to call the overloaded function.
* The set is ordered by first occurrence of the type variable within the type.
*/
Set<PolymorphicVar> getGenericClassConstrainedPolymorphicVars() {
if (genericClassConstrainedPolymorphicVars == null) {
throw new IllegalStateException();
}
return genericClassConstrainedPolymorphicVars;
}
/**
* the level at which the function is defined at. 0 for top level functions. 1 for functions in
* a first level let definition etc.
*/
int getNestingLevel() {
return functionalAgent.getNestingLevel();
}
boolean isPolymorphic() {
return polymorphic;
}
/**
* @return boolean true if the function being applied is actually a class method.
*/
boolean isClassMethod() {
return functionalAgent.getForm() == FunctionalAgent.Form.CLASS_METHOD;
}
FunctionalAgent getAppliedFunctionalAgent() {
return functionalAgent;
}
}