duke@1: /* jjg@1492: * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. duke@1: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@1: * duke@1: * This code is free software; you can redistribute it and/or modify it duke@1: * under the terms of the GNU General Public License version 2 only, as ohair@554: * published by the Free Software Foundation. Oracle designates this duke@1: * particular file as subject to the "Classpath" exception as provided ohair@554: * by Oracle in the LICENSE file that accompanied this code. duke@1: * duke@1: * This code is distributed in the hope that it will be useful, but WITHOUT duke@1: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@1: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@1: * version 2 for more details (a copy is included in the LICENSE file that duke@1: * accompanied this code). duke@1: * duke@1: * You should have received a copy of the GNU General Public License version duke@1: * 2 along with this work; if not, write to the Free Software Foundation, duke@1: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@1: * ohair@554: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ohair@554: * or visit www.oracle.com if you need additional information or have any ohair@554: * questions. duke@1: */ duke@1: duke@1: package com.sun.tools.javac.code; duke@1: duke@1: import java.util.*; jjg@1357: jjg@1357: import javax.lang.model.element.ElementVisitor; jjg@900: import javax.lang.model.type.TypeVisitor; duke@1: duke@1: import com.sun.tools.javac.code.Symbol.*; duke@1: import com.sun.tools.javac.code.Type.*; duke@1: import com.sun.tools.javac.jvm.*; jjg@1357: import com.sun.tools.javac.util.*; jjg@1357: import com.sun.tools.javac.util.List; jjg@1357: import static com.sun.tools.javac.code.Flags.*; duke@1: import static com.sun.tools.javac.jvm.ByteCodes.*; jjg@1374: import static com.sun.tools.javac.code.TypeTag.*; duke@1: duke@1: /** A class that defines all predefined constants and operators duke@1: * as well as special classes such as java.lang.Object, which need duke@1: * to be known to the compiler. All symbols are held in instance duke@1: * fields. This makes it possible to work in multiple concurrent duke@1: * projects, which might use different class files for library classes. duke@1: * jjg@581: *

This is NOT part of any supported API. jjg@581: * If you write code that depends on this, you do so at your own risk. duke@1: * This code and its internal interfaces are subject to change or duke@1: * deletion without notice. duke@1: */ duke@1: public class Symtab { duke@1: /** The context key for the symbol table. */ duke@1: protected static final Context.Key symtabKey = duke@1: new Context.Key(); duke@1: duke@1: /** Get the symbol table instance. */ duke@1: public static Symtab instance(Context context) { duke@1: Symtab instance = context.get(symtabKey); duke@1: if (instance == null) duke@1: instance = new Symtab(context); duke@1: return instance; duke@1: } duke@1: duke@1: /** Builtin types. duke@1: */ jjg@1374: public final Type byteType = new Type(BYTE, null); jjg@1374: public final Type charType = new Type(CHAR, null); jjg@1374: public final Type shortType = new Type(SHORT, null); jjg@1374: public final Type intType = new Type(INT, null); jjg@1374: public final Type longType = new Type(LONG, null); jjg@1374: public final Type floatType = new Type(FLOAT, null); jjg@1374: public final Type doubleType = new Type(DOUBLE, null); jjg@1374: public final Type booleanType = new Type(BOOLEAN, null); duke@1: public final Type botType = new BottomType(); jjg@1374: public final JCNoType voidType = new JCNoType(VOID); duke@1: jjg@113: private final Names names; duke@1: private final ClassReader reader; jjg@86: private final Target target; duke@1: duke@1: /** A symbol for the root package. duke@1: */ duke@1: public final PackageSymbol rootPackage; duke@1: duke@1: /** A symbol for the unnamed package. duke@1: */ duke@1: public final PackageSymbol unnamedPackage; duke@1: duke@1: /** A symbol that stands for a missing symbol. duke@1: */ duke@1: public final TypeSymbol noSymbol; duke@1: duke@1: /** The error symbol. duke@1: */ duke@1: public final ClassSymbol errSymbol; duke@1: mcimadamore@676: /** The unknown symbol. mcimadamore@676: */ mcimadamore@676: public final ClassSymbol unknownSymbol; mcimadamore@676: jjg@110: /** A value for the errType, with a originalType of noType */ duke@1: public final Type errType; duke@1: duke@1: /** A value for the unknown type. */ duke@1: public final Type unknownType; duke@1: duke@1: /** The builtin type of all arrays. */ duke@1: public final ClassSymbol arrayClass; duke@1: public final MethodSymbol arrayCloneMethod; duke@1: duke@1: /** VGJ: The (singleton) type of all bound types. */ duke@1: public final ClassSymbol boundClass; duke@1: duke@1: /** The builtin type of all methods. */ duke@1: public final ClassSymbol methodClass; duke@1: duke@1: /** Predefined types. duke@1: */ duke@1: public final Type objectType; duke@1: public final Type classType; duke@1: public final Type classLoaderType; duke@1: public final Type stringType; duke@1: public final Type stringBufferType; duke@1: public final Type stringBuilderType; duke@1: public final Type cloneableType; duke@1: public final Type serializableType; jrose@267: public final Type methodHandleType; rfield@1380: public final Type methodHandleLookupType; mcimadamore@1336: public final Type methodTypeType; jjg@1230: public final Type nativeHeaderType; jjg@1407: public final Type nativeHeaderType_old; duke@1: public final Type throwableType; duke@1: public final Type errorType; mcimadamore@951: public final Type interruptedExceptionType; duke@1: public final Type illegalArgumentExceptionType; duke@1: public final Type exceptionType; duke@1: public final Type runtimeExceptionType; duke@1: public final Type classNotFoundExceptionType; duke@1: public final Type noClassDefFoundErrorType; duke@1: public final Type noSuchFieldErrorType; duke@1: public final Type assertionErrorType; duke@1: public final Type cloneNotSupportedExceptionType; duke@1: public final Type annotationType; duke@1: public final TypeSymbol enumSym; duke@1: public final Type listType; duke@1: public final Type collectionsType; duke@1: public final Type comparableType; duke@1: public final Type arraysType; duke@1: public final Type iterableType; duke@1: public final Type iteratorType; duke@1: public final Type annotationTargetType; duke@1: public final Type overrideType; duke@1: public final Type retentionType; duke@1: public final Type deprecatedType; duke@1: public final Type suppressWarningsType; duke@1: public final Type inheritedType; jjg@1569: public final Type profileType; duke@1: public final Type proprietaryType; jjg@86: public final Type systemType; darcy@609: public final Type autoCloseableType; mcimadamore@795: public final Type trustMeType; rfield@1380: public final Type lambdaMetafactory; jjg@1492: public final Type repeatableType; jfranck@1313: public final Type documentedType; jfranck@1313: public final Type elementTypeType; mcimadamore@1497: public final Type functionalInterfaceType; duke@1: duke@1: /** The symbol representing the length field of an array. duke@1: */ duke@1: public final VarSymbol lengthVar; duke@1: duke@1: /** The null check operator. */ duke@1: public final OperatorSymbol nullcheck; duke@1: duke@1: /** The symbol representing the final finalize method on enums */ duke@1: public final MethodSymbol enumFinalFinalize; duke@1: darcy@609: /** The symbol representing the close method on TWR AutoCloseable type */ darcy@609: public final MethodSymbol autoCloseableClose; darcy@609: duke@1: /** The predefined type that belongs to a tag. duke@1: */ jjg@1374: public final Type[] typeOfTag = new Type[TypeTag.getTypeTagCount()]; duke@1: duke@1: /** The name of the class that belongs to a basix type tag. duke@1: */ jjg@1374: public final Name[] boxedName = new Name[TypeTag.getTypeTagCount()]; duke@1: mcimadamore@1347: /** A set containing all operator names. mcimadamore@1347: */ mcimadamore@1347: public final Set operatorNames = new HashSet(); mcimadamore@1347: duke@1: /** A hashtable containing the encountered top-level and member classes, duke@1: * indexed by flat names. The table does not contain local classes. duke@1: * It should be updated from the outside to reflect classes defined duke@1: * by compiled source files. duke@1: */ duke@1: public final Map classes = new HashMap(); duke@1: duke@1: /** A hashtable containing the encountered packages. duke@1: * the table should be updated from outside to reflect packages defined duke@1: * by compiled source files. duke@1: */ duke@1: public final Map packages = new HashMap(); duke@1: duke@1: public void initType(Type type, ClassSymbol c) { duke@1: type.tsym = c; jjg@1374: typeOfTag[type.tag.ordinal()] = type; duke@1: } duke@1: duke@1: public void initType(Type type, String name) { duke@1: initType( duke@1: type, duke@1: new ClassSymbol( duke@1: PUBLIC, names.fromString(name), type, rootPackage)); duke@1: } duke@1: duke@1: public void initType(Type type, String name, String bname) { duke@1: initType(type, name); jjg@1374: boxedName[type.tag.ordinal()] = names.fromString("java.lang." + bname); duke@1: } duke@1: duke@1: /** The class symbol that owns all predefined symbols. duke@1: */ duke@1: public final ClassSymbol predefClass; duke@1: duke@1: /** Enter a constant into symbol table. duke@1: * @param name The constant's name. duke@1: * @param type The constant's type. duke@1: */ duke@1: private VarSymbol enterConstant(String name, Type type) { duke@1: VarSymbol c = new VarSymbol( duke@1: PUBLIC | STATIC | FINAL, duke@1: names.fromString(name), duke@1: type, duke@1: predefClass); duke@1: c.setData(type.constValue()); duke@1: predefClass.members().enter(c); duke@1: return c; duke@1: } duke@1: duke@1: /** Enter a binary operation into symbol table. duke@1: * @param name The name of the operator. duke@1: * @param left The type of the left operand. duke@1: * @param right The type of the left operand. duke@1: * @param res The operation's result type. duke@1: * @param opcode The operation's bytecode instruction. duke@1: */ duke@1: private void enterBinop(String name, duke@1: Type left, Type right, Type res, duke@1: int opcode) { duke@1: predefClass.members().enter( duke@1: new OperatorSymbol( mcimadamore@1347: makeOperatorName(name), duke@1: new MethodType(List.of(left, right), res, duke@1: List.nil(), methodClass), duke@1: opcode, duke@1: predefClass)); duke@1: } duke@1: duke@1: /** Enter a binary operation, as above but with two opcodes, jjg@1326: * which get encoded as jjg@1326: * {@code (opcode1 << ByteCodeTags.preShift) + opcode2 }. duke@1: * @param opcode1 First opcode. duke@1: * @param opcode2 Second opcode. duke@1: */ duke@1: private void enterBinop(String name, duke@1: Type left, Type right, Type res, duke@1: int opcode1, int opcode2) { duke@1: enterBinop( duke@1: name, left, right, res, (opcode1 << ByteCodes.preShift) | opcode2); duke@1: } duke@1: duke@1: /** Enter a unary operation into symbol table. duke@1: * @param name The name of the operator. duke@1: * @param arg The type of the operand. duke@1: * @param res The operation's result type. duke@1: * @param opcode The operation's bytecode instruction. duke@1: */ duke@1: private OperatorSymbol enterUnop(String name, duke@1: Type arg, duke@1: Type res, duke@1: int opcode) { duke@1: OperatorSymbol sym = mcimadamore@1347: new OperatorSymbol(makeOperatorName(name), duke@1: new MethodType(List.of(arg), duke@1: res, duke@1: List.nil(), duke@1: methodClass), duke@1: opcode, duke@1: predefClass); duke@1: predefClass.members().enter(sym); duke@1: return sym; duke@1: } duke@1: mcimadamore@1347: /** mcimadamore@1347: * Create a new operator name from corresponding String representation mcimadamore@1347: * and add the name to the set of known operator names. mcimadamore@1347: */ mcimadamore@1347: private Name makeOperatorName(String name) { mcimadamore@1347: Name opName = names.fromString(name); mcimadamore@1347: operatorNames.add(opName); mcimadamore@1347: return opName; mcimadamore@1347: } mcimadamore@1347: duke@1: /** Enter a class into symbol table. jjg@1358: * @param s The name of the class. duke@1: */ duke@1: private Type enterClass(String s) { duke@1: return reader.enterClass(names.fromString(s)).type; duke@1: } duke@1: jjg@86: public void synthesizeEmptyInterfaceIfMissing(final Type type) { jjg@86: final Completer completer = type.tsym.completer; jjg@86: if (completer != null) { jjg@86: type.tsym.completer = new Completer() { jjg@86: public void complete(Symbol sym) throws CompletionFailure { jjg@86: try { jjg@86: completer.complete(sym); jjg@86: } catch (CompletionFailure e) { jjg@86: sym.flags_field |= (PUBLIC | INTERFACE); jjg@86: ((ClassType) sym.type).supertype_field = objectType; jjg@86: } jjg@86: } jjg@86: }; jjg@86: } jjg@86: } jjg@86: jjg@86: public void synthesizeBoxTypeIfMissing(final Type type) { jjg@1374: ClassSymbol sym = reader.enterClass(boxedName[type.tag.ordinal()]); jjg@86: final Completer completer = sym.completer; jjg@86: if (completer != null) { jjg@86: sym.completer = new Completer() { jjg@86: public void complete(Symbol sym) throws CompletionFailure { jjg@86: try { jjg@86: completer.complete(sym); jjg@86: } catch (CompletionFailure e) { jjg@86: sym.flags_field |= PUBLIC; jjg@86: ((ClassType) sym.type).supertype_field = objectType; jjg@86: Name n = target.boxWithConstructors() ? names.init : names.valueOf; jjg@86: MethodSymbol boxMethod = jjg@86: new MethodSymbol(PUBLIC | STATIC, jjg@86: n, jjg@86: new MethodType(List.of(type), sym.type, jjg@86: List.nil(), methodClass), jjg@86: sym); jjg@86: sym.members().enter(boxMethod); jjg@86: MethodSymbol unboxMethod = jjg@86: new MethodSymbol(PUBLIC, jjg@86: type.tsym.name.append(names.Value), // x.intValue() jjg@86: new MethodType(List.nil(), type, jjg@86: List.nil(), methodClass), jjg@86: sym); jjg@86: sym.members().enter(unboxMethod); jjg@86: } jjg@86: } jjg@86: }; jjg@86: } jjg@86: jjg@86: } jjg@86: jjg@1569: // Enter a synthetic class that is used to mark classes in ct.sym. jjg@1569: // This class does not have a class file. jjg@1569: private Type enterSyntheticAnnotation(String name) { jjg@1569: ClassType type = (ClassType)enterClass(name); jjg@1569: ClassSymbol sym = (ClassSymbol)type.tsym; jjg@1569: sym.completer = null; jjg@1569: sym.flags_field = PUBLIC|ACYCLIC|ANNOTATION|INTERFACE; jjg@1569: sym.erasure_field = type; jjg@1569: sym.members_field = new Scope(sym); jjg@1569: type.typarams_field = List.nil(); jjg@1569: type.allparams_field = List.nil(); jjg@1569: type.supertype_field = annotationType; jjg@1569: type.interfaces_field = List.nil(); jjg@1569: return type; jjg@1569: } jjg@1569: duke@1: /** Constructor; enters all predefined identifiers and operators duke@1: * into symbol table. duke@1: */ duke@1: protected Symtab(Context context) throws CompletionFailure { duke@1: context.put(symtabKey, this); duke@1: jjg@113: names = Names.instance(context); jjg@86: target = Target.instance(context); duke@1: duke@1: // Create the unknown type jjg@1374: unknownType = new Type(UNKNOWN, null) { jjg@900: @Override jjg@900: public R accept(TypeVisitor v, P p) { jjg@900: return v.visitUnknown(this, p); jjg@900: } jjg@900: }; duke@1: duke@1: // create the basic builtin symbols duke@1: rootPackage = new PackageSymbol(names.empty, null); mcimadamore@136: final JavacMessages messages = JavacMessages.instance(context); duke@1: unnamedPackage = new PackageSymbol(names.empty, rootPackage) { duke@1: public String toString() { duke@1: return messages.getLocalizedString("compiler.misc.unnamed.package"); duke@1: } duke@1: }; jjg@900: noSymbol = new TypeSymbol(0, names.empty, Type.noType, rootPackage) { jjg@900: public R accept(ElementVisitor v, P p) { jjg@900: return v.visitUnknown(this, p); jjg@900: } jjg@900: }; duke@1: noSymbol.kind = Kinds.NIL; duke@1: duke@1: // create the error symbols duke@1: errSymbol = new ClassSymbol(PUBLIC|STATIC|ACYCLIC, names.any, null, rootPackage); jjg@900: errType = new ErrorType(errSymbol, Type.noType); jjg@900: mcimadamore@676: unknownSymbol = new ClassSymbol(PUBLIC|STATIC|ACYCLIC, names.fromString(""), null, rootPackage); jjg@900: unknownSymbol.members_field = new Scope.ErrorScope(unknownSymbol); jjg@900: unknownSymbol.type = unknownType; duke@1: duke@1: // initialize builtin types duke@1: initType(byteType, "byte", "Byte"); duke@1: initType(shortType, "short", "Short"); duke@1: initType(charType, "char", "Character"); duke@1: initType(intType, "int", "Integer"); duke@1: initType(longType, "long", "Long"); duke@1: initType(floatType, "float", "Float"); duke@1: initType(doubleType, "double", "Double"); duke@1: initType(booleanType, "boolean", "Boolean"); duke@1: initType(voidType, "void", "Void"); duke@1: initType(botType, ""); duke@1: initType(errType, errSymbol); mcimadamore@676: initType(unknownType, unknownSymbol); duke@1: duke@1: // the builtin class of all arrays duke@1: arrayClass = new ClassSymbol(PUBLIC|ACYCLIC, names.Array, noSymbol); duke@1: duke@1: // VGJ duke@1: boundClass = new ClassSymbol(PUBLIC|ACYCLIC, names.Bound, noSymbol); jjg@900: boundClass.members_field = new Scope.ErrorScope(boundClass); duke@1: duke@1: // the builtin class of all methods duke@1: methodClass = new ClassSymbol(PUBLIC|ACYCLIC, names.Method, noSymbol); jjg@900: methodClass.members_field = new Scope.ErrorScope(boundClass); duke@1: duke@1: // Create class to hold all predefined constants and operations. duke@1: predefClass = new ClassSymbol(PUBLIC|ACYCLIC, names.empty, rootPackage); mcimadamore@858: Scope scope = new Scope(predefClass); duke@1: predefClass.members_field = scope; duke@1: duke@1: // Enter symbols for basic types. duke@1: scope.enter(byteType.tsym); duke@1: scope.enter(shortType.tsym); duke@1: scope.enter(charType.tsym); duke@1: scope.enter(intType.tsym); duke@1: scope.enter(longType.tsym); duke@1: scope.enter(floatType.tsym); duke@1: scope.enter(doubleType.tsym); duke@1: scope.enter(booleanType.tsym); duke@1: scope.enter(errType.tsym); duke@1: jjg@110: // Enter symbol for the errSymbol jjg@110: scope.enter(errSymbol); jjg@110: duke@1: classes.put(predefClass.fullname, predefClass); duke@1: duke@1: reader = ClassReader.instance(context); duke@1: reader.init(this); duke@1: duke@1: // Enter predefined classes. duke@1: objectType = enterClass("java.lang.Object"); duke@1: classType = enterClass("java.lang.Class"); duke@1: stringType = enterClass("java.lang.String"); duke@1: stringBufferType = enterClass("java.lang.StringBuffer"); duke@1: stringBuilderType = enterClass("java.lang.StringBuilder"); duke@1: cloneableType = enterClass("java.lang.Cloneable"); duke@1: throwableType = enterClass("java.lang.Throwable"); duke@1: serializableType = enterClass("java.io.Serializable"); mcimadamore@857: methodHandleType = enterClass("java.lang.invoke.MethodHandle"); rfield@1380: methodHandleLookupType = enterClass("java.lang.invoke.MethodHandles$Lookup"); mcimadamore@1336: methodTypeType = enterClass("java.lang.invoke.MethodType"); duke@1: errorType = enterClass("java.lang.Error"); duke@1: illegalArgumentExceptionType = enterClass("java.lang.IllegalArgumentException"); mcimadamore@951: interruptedExceptionType = enterClass("java.lang.InterruptedException"); duke@1: exceptionType = enterClass("java.lang.Exception"); duke@1: runtimeExceptionType = enterClass("java.lang.RuntimeException"); duke@1: classNotFoundExceptionType = enterClass("java.lang.ClassNotFoundException"); duke@1: noClassDefFoundErrorType = enterClass("java.lang.NoClassDefFoundError"); duke@1: noSuchFieldErrorType = enterClass("java.lang.NoSuchFieldError"); duke@1: assertionErrorType = enterClass("java.lang.AssertionError"); duke@1: cloneNotSupportedExceptionType = enterClass("java.lang.CloneNotSupportedException"); duke@1: annotationType = enterClass("java.lang.annotation.Annotation"); duke@1: classLoaderType = enterClass("java.lang.ClassLoader"); duke@1: enumSym = reader.enterClass(names.java_lang_Enum); duke@1: enumFinalFinalize = duke@1: new MethodSymbol(PROTECTED|FINAL|HYPOTHETICAL, duke@1: names.finalize, duke@1: new MethodType(List.nil(), voidType, duke@1: List.nil(), methodClass), duke@1: enumSym); duke@1: listType = enterClass("java.util.List"); duke@1: collectionsType = enterClass("java.util.Collections"); duke@1: comparableType = enterClass("java.lang.Comparable"); duke@1: arraysType = enterClass("java.util.Arrays"); jjg@86: iterableType = target.hasIterable() duke@1: ? enterClass("java.lang.Iterable") duke@1: : enterClass("java.util.Collection"); duke@1: iteratorType = enterClass("java.util.Iterator"); duke@1: annotationTargetType = enterClass("java.lang.annotation.Target"); duke@1: overrideType = enterClass("java.lang.Override"); duke@1: retentionType = enterClass("java.lang.annotation.Retention"); duke@1: deprecatedType = enterClass("java.lang.Deprecated"); duke@1: suppressWarningsType = enterClass("java.lang.SuppressWarnings"); duke@1: inheritedType = enterClass("java.lang.annotation.Inherited"); jjg@1492: repeatableType = enterClass("java.lang.annotation.Repeatable"); jfranck@1313: documentedType = enterClass("java.lang.annotation.Documented"); jfranck@1313: elementTypeType = enterClass("java.lang.annotation.ElementType"); jjg@86: systemType = enterClass("java.lang.System"); darcy@609: autoCloseableType = enterClass("java.lang.AutoCloseable"); darcy@609: autoCloseableClose = new MethodSymbol(PUBLIC, darcy@609: names.close, darcy@609: new MethodType(List.nil(), voidType, darcy@609: List.of(exceptionType), methodClass), darcy@609: autoCloseableType.tsym); mcimadamore@795: trustMeType = enterClass("java.lang.SafeVarargs"); jjg@1407: nativeHeaderType = enterClass("java.lang.annotation.Native"); jjg@1407: nativeHeaderType_old = enterClass("javax.tools.annotation.GenerateNativeHeader"); rfield@1380: lambdaMetafactory = enterClass("java.lang.invoke.LambdaMetafactory"); mcimadamore@1497: functionalInterfaceType = enterClass("java.lang.FunctionalInterface"); jjg@86: mcimadamore@951: synthesizeEmptyInterfaceIfMissing(autoCloseableType); jjg@86: synthesizeEmptyInterfaceIfMissing(cloneableType); jjg@86: synthesizeEmptyInterfaceIfMissing(serializableType); rfield@1380: synthesizeEmptyInterfaceIfMissing(lambdaMetafactory); jjg@86: synthesizeBoxTypeIfMissing(doubleType); jjg@86: synthesizeBoxTypeIfMissing(floatType); mcimadamore@357: synthesizeBoxTypeIfMissing(voidType); duke@1: jjg@582: // Enter a synthetic class that is used to mark internal duke@1: // proprietary classes in ct.sym. This class does not have a duke@1: // class file. jjg@1569: proprietaryType = enterSyntheticAnnotation("sun.Proprietary+Annotation"); jjg@1569: jjg@1569: // Enter a synthetic class that is used to provide profile info for jjg@1569: // classes in ct.sym. This class does not have a class file. jjg@1569: profileType = enterSyntheticAnnotation("jdk.Profile+Annotation"); jjg@1569: MethodSymbol m = new MethodSymbol(PUBLIC | ABSTRACT, names.value, intType, profileType.tsym); jjg@1569: profileType.tsym.members().enter(m); duke@1: duke@1: // Enter a class for arrays. duke@1: // The class implements java.lang.Cloneable and java.io.Serializable. duke@1: // It has a final length field and a clone method. duke@1: ClassType arrayClassType = (ClassType)arrayClass.type; duke@1: arrayClassType.supertype_field = objectType; duke@1: arrayClassType.interfaces_field = List.of(cloneableType, serializableType); mcimadamore@858: arrayClass.members_field = new Scope(arrayClass); duke@1: lengthVar = new VarSymbol( duke@1: PUBLIC | FINAL, duke@1: names.length, duke@1: intType, duke@1: arrayClass); duke@1: arrayClass.members().enter(lengthVar); duke@1: arrayCloneMethod = new MethodSymbol( duke@1: PUBLIC, duke@1: names.clone, duke@1: new MethodType(List.nil(), objectType, duke@1: List.nil(), methodClass), duke@1: arrayClass); duke@1: arrayClass.members().enter(arrayCloneMethod); duke@1: duke@1: // Enter operators. duke@1: enterUnop("+", doubleType, doubleType, nop); duke@1: enterUnop("+", floatType, floatType, nop); duke@1: enterUnop("+", longType, longType, nop); duke@1: enterUnop("+", intType, intType, nop); duke@1: duke@1: enterUnop("-", doubleType, doubleType, dneg); duke@1: enterUnop("-", floatType, floatType, fneg); duke@1: enterUnop("-", longType, longType, lneg); duke@1: enterUnop("-", intType, intType, ineg); duke@1: duke@1: enterUnop("~", longType, longType, lxor); duke@1: enterUnop("~", intType, intType, ixor); duke@1: duke@1: enterUnop("++", doubleType, doubleType, dadd); duke@1: enterUnop("++", floatType, floatType, fadd); duke@1: enterUnop("++", longType, longType, ladd); duke@1: enterUnop("++", intType, intType, iadd); duke@1: enterUnop("++", charType, charType, iadd); duke@1: enterUnop("++", shortType, shortType, iadd); duke@1: enterUnop("++", byteType, byteType, iadd); duke@1: duke@1: enterUnop("--", doubleType, doubleType, dsub); duke@1: enterUnop("--", floatType, floatType, fsub); duke@1: enterUnop("--", longType, longType, lsub); duke@1: enterUnop("--", intType, intType, isub); duke@1: enterUnop("--", charType, charType, isub); duke@1: enterUnop("--", shortType, shortType, isub); duke@1: enterUnop("--", byteType, byteType, isub); duke@1: duke@1: enterUnop("!", booleanType, booleanType, bool_not); duke@1: nullcheck = enterUnop("<*nullchk*>", objectType, objectType, nullchk); duke@1: duke@1: // string concatenation duke@1: enterBinop("+", stringType, objectType, stringType, string_add); duke@1: enterBinop("+", objectType, stringType, stringType, string_add); duke@1: enterBinop("+", stringType, stringType, stringType, string_add); duke@1: enterBinop("+", stringType, intType, stringType, string_add); duke@1: enterBinop("+", stringType, longType, stringType, string_add); duke@1: enterBinop("+", stringType, floatType, stringType, string_add); duke@1: enterBinop("+", stringType, doubleType, stringType, string_add); duke@1: enterBinop("+", stringType, booleanType, stringType, string_add); duke@1: enterBinop("+", stringType, botType, stringType, string_add); duke@1: enterBinop("+", intType, stringType, stringType, string_add); duke@1: enterBinop("+", longType, stringType, stringType, string_add); duke@1: enterBinop("+", floatType, stringType, stringType, string_add); duke@1: enterBinop("+", doubleType, stringType, stringType, string_add); duke@1: enterBinop("+", booleanType, stringType, stringType, string_add); duke@1: enterBinop("+", botType, stringType, stringType, string_add); duke@1: duke@1: // these errors would otherwise be matched as string concatenation duke@1: enterBinop("+", botType, botType, botType, error); duke@1: enterBinop("+", botType, intType, botType, error); duke@1: enterBinop("+", botType, longType, botType, error); duke@1: enterBinop("+", botType, floatType, botType, error); duke@1: enterBinop("+", botType, doubleType, botType, error); duke@1: enterBinop("+", botType, booleanType, botType, error); duke@1: enterBinop("+", botType, objectType, botType, error); duke@1: enterBinop("+", intType, botType, botType, error); duke@1: enterBinop("+", longType, botType, botType, error); duke@1: enterBinop("+", floatType, botType, botType, error); duke@1: enterBinop("+", doubleType, botType, botType, error); duke@1: enterBinop("+", booleanType, botType, botType, error); duke@1: enterBinop("+", objectType, botType, botType, error); duke@1: duke@1: enterBinop("+", doubleType, doubleType, doubleType, dadd); duke@1: enterBinop("+", floatType, floatType, floatType, fadd); duke@1: enterBinop("+", longType, longType, longType, ladd); duke@1: enterBinop("+", intType, intType, intType, iadd); duke@1: duke@1: enterBinop("-", doubleType, doubleType, doubleType, dsub); duke@1: enterBinop("-", floatType, floatType, floatType, fsub); duke@1: enterBinop("-", longType, longType, longType, lsub); duke@1: enterBinop("-", intType, intType, intType, isub); duke@1: duke@1: enterBinop("*", doubleType, doubleType, doubleType, dmul); duke@1: enterBinop("*", floatType, floatType, floatType, fmul); duke@1: enterBinop("*", longType, longType, longType, lmul); duke@1: enterBinop("*", intType, intType, intType, imul); duke@1: duke@1: enterBinop("/", doubleType, doubleType, doubleType, ddiv); duke@1: enterBinop("/", floatType, floatType, floatType, fdiv); duke@1: enterBinop("/", longType, longType, longType, ldiv); duke@1: enterBinop("/", intType, intType, intType, idiv); duke@1: duke@1: enterBinop("%", doubleType, doubleType, doubleType, dmod); duke@1: enterBinop("%", floatType, floatType, floatType, fmod); duke@1: enterBinop("%", longType, longType, longType, lmod); duke@1: enterBinop("%", intType, intType, intType, imod); duke@1: duke@1: enterBinop("&", booleanType, booleanType, booleanType, iand); duke@1: enterBinop("&", longType, longType, longType, land); duke@1: enterBinop("&", intType, intType, intType, iand); duke@1: duke@1: enterBinop("|", booleanType, booleanType, booleanType, ior); duke@1: enterBinop("|", longType, longType, longType, lor); duke@1: enterBinop("|", intType, intType, intType, ior); duke@1: duke@1: enterBinop("^", booleanType, booleanType, booleanType, ixor); duke@1: enterBinop("^", longType, longType, longType, lxor); duke@1: enterBinop("^", intType, intType, intType, ixor); duke@1: duke@1: enterBinop("<<", longType, longType, longType, lshll); duke@1: enterBinop("<<", intType, longType, intType, ishll); duke@1: enterBinop("<<", longType, intType, longType, lshl); duke@1: enterBinop("<<", intType, intType, intType, ishl); duke@1: duke@1: enterBinop(">>", longType, longType, longType, lshrl); duke@1: enterBinop(">>", intType, longType, intType, ishrl); duke@1: enterBinop(">>", longType, intType, longType, lshr); duke@1: enterBinop(">>", intType, intType, intType, ishr); duke@1: duke@1: enterBinop(">>>", longType, longType, longType, lushrl); duke@1: enterBinop(">>>", intType, longType, intType, iushrl); duke@1: enterBinop(">>>", longType, intType, longType, lushr); duke@1: enterBinop(">>>", intType, intType, intType, iushr); duke@1: duke@1: enterBinop("<", doubleType, doubleType, booleanType, dcmpg, iflt); duke@1: enterBinop("<", floatType, floatType, booleanType, fcmpg, iflt); duke@1: enterBinop("<", longType, longType, booleanType, lcmp, iflt); duke@1: enterBinop("<", intType, intType, booleanType, if_icmplt); duke@1: duke@1: enterBinop(">", doubleType, doubleType, booleanType, dcmpl, ifgt); duke@1: enterBinop(">", floatType, floatType, booleanType, fcmpl, ifgt); duke@1: enterBinop(">", longType, longType, booleanType, lcmp, ifgt); duke@1: enterBinop(">", intType, intType, booleanType, if_icmpgt); duke@1: duke@1: enterBinop("<=", doubleType, doubleType, booleanType, dcmpg, ifle); duke@1: enterBinop("<=", floatType, floatType, booleanType, fcmpg, ifle); duke@1: enterBinop("<=", longType, longType, booleanType, lcmp, ifle); duke@1: enterBinop("<=", intType, intType, booleanType, if_icmple); duke@1: duke@1: enterBinop(">=", doubleType, doubleType, booleanType, dcmpl, ifge); duke@1: enterBinop(">=", floatType, floatType, booleanType, fcmpl, ifge); duke@1: enterBinop(">=", longType, longType, booleanType, lcmp, ifge); duke@1: enterBinop(">=", intType, intType, booleanType, if_icmpge); duke@1: duke@1: enterBinop("==", objectType, objectType, booleanType, if_acmpeq); duke@1: enterBinop("==", booleanType, booleanType, booleanType, if_icmpeq); duke@1: enterBinop("==", doubleType, doubleType, booleanType, dcmpl, ifeq); duke@1: enterBinop("==", floatType, floatType, booleanType, fcmpl, ifeq); duke@1: enterBinop("==", longType, longType, booleanType, lcmp, ifeq); duke@1: enterBinop("==", intType, intType, booleanType, if_icmpeq); duke@1: duke@1: enterBinop("!=", objectType, objectType, booleanType, if_acmpne); duke@1: enterBinop("!=", booleanType, booleanType, booleanType, if_icmpne); duke@1: enterBinop("!=", doubleType, doubleType, booleanType, dcmpl, ifne); duke@1: enterBinop("!=", floatType, floatType, booleanType, fcmpl, ifne); duke@1: enterBinop("!=", longType, longType, booleanType, lcmp, ifne); duke@1: enterBinop("!=", intType, intType, booleanType, if_icmpne); duke@1: duke@1: enterBinop("&&", booleanType, booleanType, booleanType, bool_and); duke@1: enterBinop("||", booleanType, booleanType, booleanType, bool_or); duke@1: } duke@1: }