/*
* Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package org.visage.tools.code;
import com.sun.tools.mjavac.code.Symtab;
import com.sun.tools.mjavac.code.Type;
import com.sun.tools.mjavac.code.Symbol;
import com.sun.tools.mjavac.code.Type.*;
import static com.sun.tools.mjavac.jvm.ByteCodes.*;
import com.sun.tools.mjavac.util.*;
import com.sun.tools.mjavac.code.Symbol.TypeSymbol;
import com.sun.tools.mjavac.code.TypeTags;
import org.visage.tools.comp.VisageDefs;
import com.sun.tools.mjavac.code.Flags;
/**
*
* @author Robert Field
*/
public class VisageSymtab extends Symtab {
private static final String anno = VisageDefs.annotation_PackageString;
public static final String privateAnnotationClassNameString = anno + ".Private";
public static final String protectedAnnotationClassNameString = anno + ".Protected";
public static final String packageAnnotationClassNameString = anno + ".Package";
public static final String publicAnnotationClassNameString = anno + ".Public";
public static final String scriptPrivateAnnotationClassNameString = anno + ".ScriptPrivate";
public static final String defaultAnnotationClassNameString = anno + ".Default";
public static final String publicInitAnnotationClassNameString = anno + ".PublicInitable";
public static final String publicReadAnnotationClassNameString = anno + ".PublicReadable";
public static final String bindeesAnnotationClassNameString = anno + ".VisageBindees";
public static final String signatureAnnotationClassNameString = anno + ".VisageSignature";
public static final String defAnnotationClassNameString = anno + ".Def";
public static final String staticAnnotationClassNameString = anno + ".Static";
public static final String inheritedAnnotationClassNameString = anno + ".Inherited";
public static final String sourceNameAnnotationClassNameString = anno + ".SourceName";
// Visage built-in(value) types
public final Type visage_BooleanType;
public final Type visage_CharacterType;
public final Type visage_ByteType;
public final Type visage_ShortType;
public final Type visage_IntegerType;
public final Type visage_LongType;
public final Type visage_FloatType;
public final Type visage_DoubleType;
public final Type visage_NumberType;
public final Type visage_StringType;
public final Type visage_DurationType;
public final Type visage_LengthType;
public final Type visage_LengthUnitType;
public final Type visage_AngleType;
public final Type visage_AngleUnitType;
public final Type visage_ColorType;
// Visage other types
public final Type visage_AnyType;
public final Type visage_UnspecifiedType;
public final Type visage_AutoImportRuntimeType;
public final Type visage_RuntimeType;
public final Type visage_VoidType;
public final Type visage_java_lang_VoidType;
public final Type visage_SequenceType;
public final Type visage_SequenceRefType;
public final Type visage_SequenceProxyType;
public final Type visage_ArraySequenceType;
public final Type visage_EmptySequenceType;
public final Type visage_SequenceTypeErasure;
public final Type visage_ShortArray;
public final Type visage_ObjectArray;
static public final int MAX_FIXED_PARAM_LENGTH = 8;
public final Type[] visage_FunctionTypes = new Type[MAX_FIXED_PARAM_LENGTH+1];
public final Type visage_ObjectType;
public final Type visage_MixinType;
public final Type visage_BaseType;
public final Type visage_SequencesType;
public final Type visage_KeyValueType;
public final Type visage_KeyFrameType;
public final Type visage_KeyValueTargetType;
public final Type visage_PointerType;
public final Type visage_ConstantType;
public final Type visage_BoundForOverSequenceType;
public final Type visage_BoundForOverNullableSingletonType;
public final Type visage_BoundForOverSingletonType;
public final Type visage_ForPartInterfaceType;
public final Type visage_NonLocalReturnExceptionType;
public final Type visage_NonLocalBreakExceptionType;
public final Type visage_NonLocalContinueExceptionType;
public final Type visage_protectedAnnotationType;
public final Type visage_packageAnnotationType;
public final Type visage_publicAnnotationType;
public final Type visage_scriptPrivateAnnotationType;
public final Type visage_defaultAnnotationType;
public final Type visage_publicInitAnnotationType;
public final Type visage_publicReadAnnotationType;
public final Type visage_signatureAnnotationType;
public final Type visage_defAnnotationType;
public final Type visage_staticAnnotationType;
public final Type visage_inheritedAnnotationType;
public final Type visage_sourceNameAnnotationType;
public final Name booleanTypeName;
public final Name charTypeName;
public final Name byteTypeName;
public final Name shortTypeName;
public final Name integerTypeName;
public final Name longTypeName;
public final Name floatTypeName;
public final Name doubleTypeName;
public final Name numberTypeName;
public final Name stringTypeName;
public final Name voidTypeName;
public final Name runMethodName;
/** The type of expressions that never returns a value to its parent.
* E.g. an expression that always throws an Exception.
* Likewise, a "return expression" returns from the outer function,
* which makes any following/surrounding code unreachable.
*/
public final Type unreachableType;
private VisageTypes types;
public static final String functionClassPrefix =
"org.visage.functions.Function";
public static void preRegister(final Context context) {
if (context.get(symtabKey) == null)
context.put(symtabKey, new Context.Factory<Symtab>() {
public Symtab make() {
return new VisageSymtab(context);
}
});
}
public static void preRegister(final Context context, Symtab syms) {
context.put(symtabKey, syms);
}
public static Symtab instance(Context context) {
Symtab instance = context.get(Symtab.symtabKey);
if (instance == null)
instance = new VisageSymtab(context);
return instance;
}
/** Creates a new instance of VisageSymtab */
VisageSymtab(Context context) {
super(context);
// FIXME It would be better to make 'names' in super-class be protected.
Name.Table names = Name.Table.instance(context);
types = VisageTypes.instance(context);
Options options = Options.instance(context);
String numberChoice = options.get("Number");
// Make the array length var symbol a Visage var symbol
VisageVarSymbol visageLengthVar = new VisageVarSymbol(
types,
names,
Flags.PUBLIC | Flags.FINAL ,
names.length,
intType,
arrayClass);
arrayClass.members().remove(lengthVar);
arrayClass.members().enter(visageLengthVar);
visage_BooleanType = booleanType;
visage_CharacterType = charType;
visage_ByteType = byteType;
visage_ShortType = shortType;
visage_IntegerType = intType;
visage_LongType = longType;
visage_FloatType = floatType;
visage_DoubleType = doubleType;
if (numberChoice == null) {
//default
visage_NumberType = floatType;
} else if (numberChoice.equals("Float")) {
visage_NumberType = floatType;
} else if (numberChoice.equals("Double")) {
visage_NumberType = doubleType;
} else {
throw new IllegalArgumentException("Bad argument for Number, must be Float pr Double");
}
visage_StringType = stringType;
visage_DurationType = enterClass("visage.lang.Duration");
visage_LengthType = enterClass("visage.lang.Length");
visage_LengthUnitType = enterClass("visage.lang.LengthUnit");
visage_AngleType = enterClass("visage.lang.Angle");
visage_AngleUnitType = enterClass("visage.lang.AngleUnit");
visage_ColorType = enterClass("visage.lang.Color");
visage_AnyType = objectType;
visage_UnspecifiedType = unknownType;
visage_VoidType = voidType;
visage_AutoImportRuntimeType = enterClass("visage.lang.Builtins");
visage_RuntimeType = enterClass("visage.lang.Visage");
unreachableType = new Type(TypeTags.VOID, null);
unreachableType.tsym = new TypeSymbol(0, names.fromString("<unreachable>"), Type.noType, rootPackage);
visage_java_lang_VoidType = types.boxedClass(voidType).type;
visage_SequenceType = enterClass(VisageDefs.cSequence);
visage_SequenceRefType = enterClass(VisageDefs.cSequenceRef);
visage_SequenceProxyType = enterClass(VisageDefs.cSequenceProxy);
visage_ArraySequenceType = enterClass(VisageDefs.cArraySequence);
visage_SequencesType = enterClass(VisageDefs.cSequences);
visage_EmptySequenceType = types.sequenceType(botType);
visage_SequenceTypeErasure = types.erasure(visage_SequenceType);
visage_ShortArray = new ArrayType(shortType, arrayClass);
visage_ObjectArray = new ArrayType(objectType, arrayClass);
visage_KeyValueType = enterClass("visage.animation.KeyValue");
visage_KeyFrameType = enterClass("visage.animation.KeyFrame");
visage_KeyValueTargetType = enterClass("visage.animation.KeyValueTarget");
visage_PointerType = enterClass("org.visage.runtime.Pointer");
visage_ConstantType = enterClass("org.visage.runtime.VisageConstant");
visage_BoundForOverSequenceType = enterClass(VisageDefs.cBoundForOverSequence);
visage_BoundForOverNullableSingletonType = enterClass(VisageDefs.cBoundForOverNullableSingleton);
visage_BoundForOverSingletonType = enterClass(VisageDefs.cBoundForOverSingleton);
visage_ForPartInterfaceType = enterClass(VisageDefs.cBoundForPartI);
visage_NonLocalReturnExceptionType = enterClass(VisageDefs.cNonLocalReturnException);
visage_NonLocalBreakExceptionType = enterClass(VisageDefs.cNonLocalBreakException);
visage_NonLocalContinueExceptionType = enterClass(VisageDefs.cNonLocalContinueException);
visage_protectedAnnotationType = enterClass(protectedAnnotationClassNameString);
visage_packageAnnotationType = enterClass(packageAnnotationClassNameString);
visage_publicAnnotationType = enterClass(publicAnnotationClassNameString);
visage_scriptPrivateAnnotationType = enterClass(scriptPrivateAnnotationClassNameString);
visage_defaultAnnotationType = enterClass(defaultAnnotationClassNameString);
visage_publicInitAnnotationType = enterClass(publicInitAnnotationClassNameString);
visage_publicReadAnnotationType = enterClass(publicReadAnnotationClassNameString);
visage_signatureAnnotationType = enterClass(signatureAnnotationClassNameString);
visage_defAnnotationType = enterClass(defAnnotationClassNameString);
visage_staticAnnotationType = enterClass(staticAnnotationClassNameString);
visage_inheritedAnnotationType = enterClass(inheritedAnnotationClassNameString);
visage_sourceNameAnnotationType = enterClass(sourceNameAnnotationClassNameString);
for (int i = MAX_FIXED_PARAM_LENGTH; i >= 0; i--) {
visage_FunctionTypes[i] = enterClass(functionClassPrefix+i);
}
booleanTypeName = names.fromString("Boolean");
charTypeName = names.fromString("Character");
byteTypeName = names.fromString("Byte");
shortTypeName = names.fromString("Short");
integerTypeName = names.fromString("Integer");
longTypeName = names.fromString("Long");
floatTypeName = names.fromString("Float");
doubleTypeName = names.fromString("Double");
numberTypeName = names.fromString("Number");
stringTypeName = names.fromString("String");
voidTypeName = names.fromString("Void");
runMethodName = names.fromString(VisageDefs.internalRunFunctionString);
visage_ObjectType = enterClass(VisageDefs.cObject);
visage_MixinType = enterClass(VisageDefs.cMixin);
visage_BaseType = enterClass(VisageDefs.cBase);
enterOperators();
}
@Override
public void enterOperators() {
super.enterOperators();
enterBinop("<>", objectType, objectType, booleanType, if_acmpne);
enterBinop("<>", booleanType, booleanType, booleanType, if_icmpne);
enterBinop("<>", doubleType, doubleType, booleanType, dcmpl, ifne);
enterBinop("<>", floatType, floatType, booleanType, fcmpl, ifne);
enterBinop("<>", longType, longType, booleanType, lcmp, ifne);
enterBinop("<>", intType, intType, booleanType, if_icmpne);
enterBinop("and", booleanType, booleanType, booleanType, bool_and);
enterBinop("or", booleanType, booleanType, booleanType, bool_or);
// Enter Visage operators.
enterUnop("sizeof", visage_SequenceType, visage_IntegerType, 0);
//TODO: I think these are ancient garbage, needs verification
enterUnop("lazy", doubleType, doubleType, 0);
enterUnop("lazy", intType, intType, 0);
enterUnop("lazy", booleanType, booleanType, 0);
enterUnop("lazy", objectType, objectType, 0);
enterUnop("bind", doubleType, doubleType, 0);
enterUnop("bind", intType, intType, 0);
enterUnop("bind", booleanType, booleanType, 0);
enterUnop("bind", objectType, objectType, 0);
}
public boolean isRunMethod(Symbol sym) {
return sym.name == runMethodName;
}
private Type boxedTypeOrType(Type elemType) {
if (elemType.isPrimitive() || elemType == voidType)
return types.boxedClass(elemType).type;
else
return elemType;
}
public FunctionType makeFunctionType(List<Type> typarams) {
ListBuffer<Type> argtypes = new ListBuffer<Type>();
Type restype = null;
for (List<Type> l = typarams; l.nonEmpty(); l = l.tail) {
Type a = l.head;
if (a instanceof WildcardType)
a = ((WildcardType) a).type;
if (restype == null) {
if (a.tsym.name == visage_java_lang_VoidType.tsym.name) {
a = voidType;
}
restype = a;
}
else
argtypes.append(a);
}
MethodType mtype = new MethodType(argtypes.toList(), restype, null, methodClass);
return makeFunctionType(typarams, mtype);
}
public FunctionType makeFunctionType(List<Type> typarams, MethodType mtype) {
int nargs = typarams.size()-1;
assert (nargs <= MAX_FIXED_PARAM_LENGTH);
Type funtype = visage_FunctionTypes[nargs];
return new FunctionType(funtype.getEnclosingType(), typarams, funtype.tsym, mtype);
}
/** Given a MethodType, create the corresponding FunctionType.
*/
public FunctionType makeFunctionType(MethodType mtype) {
Type rtype = mtype.restype;
ListBuffer<Type> typarams = new ListBuffer<Type>();
typarams.append(boxedTypeOrType(rtype));
for (List<Type> l = mtype.argtypes; l.nonEmpty(); l = l.tail) {
typarams.append(boxedTypeOrType(l.head));
}
return makeFunctionType(typarams.toList(), mtype);
}
/** Make public. */
@Override
public Type enterClass(String name) {
return super.enterClass(name);
}
}