/* * This file is part of the OpenJML project. * Author: David R. Cok */ package org.jmlspecs.openjml; import static com.sun.tools.javac.code.Flags.UNATTRIBUTED; import java.io.StringWriter; import java.util.Map; import javax.tools.JavaFileObject; import org.jmlspecs.annotation.Nullable; import org.jmlspecs.openjml.esc.Label; import com.sun.source.tree.ExpressionTree; import com.sun.source.tree.TreeVisitor; import com.sun.tools.javac.code.JmlType; import com.sun.tools.javac.code.Scope.ImportScope; import com.sun.tools.javac.code.Scope.StarImportScope; import com.sun.tools.javac.code.Symbol.ClassSymbol; import com.sun.tools.javac.code.Symbol.MethodSymbol; import com.sun.tools.javac.code.Symbol.PackageSymbol; import com.sun.tools.javac.code.Symbol.VarSymbol; import com.sun.tools.javac.code.Type; import com.sun.tools.javac.code.TypeTag; import com.sun.tools.javac.comp.AttrContext; import com.sun.tools.javac.comp.Env; import com.sun.tools.javac.parser.Tokens.ITokenKind; import com.sun.tools.javac.parser.Tokens.TokenKind; import com.sun.tools.javac.tree.*; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCArrayAccess; import com.sun.tools.javac.tree.JCTree.JCBlock; import com.sun.tools.javac.tree.JCTree.JCDoWhileLoop; import com.sun.tools.javac.tree.JCTree.JCEnhancedForLoop; import com.sun.tools.javac.tree.JCTree.JCExpression; import com.sun.tools.javac.tree.JCTree.JCExpressionStatement; import com.sun.tools.javac.tree.JCTree.JCFieldAccess; import com.sun.tools.javac.tree.JCTree.JCForLoop; import com.sun.tools.javac.tree.JCTree.JCIdent; import com.sun.tools.javac.tree.JCTree.JCMethodInvocation; import com.sun.tools.javac.tree.JCTree.JCModifiers; import com.sun.tools.javac.tree.JCTree.JCStatement; import com.sun.tools.javac.tree.JCTree.JCTypeParameter; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.tree.JCTree.JCWhileLoop; import com.sun.tools.javac.tree.JCTree.Tag; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Log; import com.sun.tools.javac.util.Name; import com.sun.tools.javac.util.Names; import com.sun.tools.javac.util.Position; // FIXME - review that getTag and getKind are appropriately used; check toString is where it is needed // FIXME - review and fix the else branches of all the accept statements // FIXME - the start and end positions are gotten from TreeInfo, which does not work for JML nodes /** This class simply holds the classes which are JML-specific nodes of parse trees. */ public class JmlTree implements IJmlTree { /** Convert a tree to a pretty-printed string using the JmlPrettyPrinter; note that * this is not inherited by anyone, it is here as a utility method and needs * to be called by nodes of JmlTree. */ static public String toString(JCTree node) { StringWriter sw = new StringWriter(); JmlPretty p = new JmlPretty(sw,true); p.width = 2; node.accept(p); return sw.toString(); } static boolean isJML(long flags) { return (flags & Utils.JMLBIT) != 0; } public static interface IInJML { boolean isJML(); } /** This interface extends the node factory for Java parse tree nodes by adding factory * methods for all of the JML nodes. All these methods create the AST nodes; * the pos field is set using other methods on the factory. */ public interface JmlFactory extends JCTree.Factory { JmlAnnotation Annotation(JCTree type, List<JCExpression> args); JmlBinary JmlBinary(JmlTokenKind t, JCTree.JCExpression left, JCTree.JCExpression right); JmlBlock Block(long flags, List<JCStatement> stats); JmlChoose JmlChoose(JmlTokenKind token, List<JCBlock> orBlocks, /*@Nullable*/JCBlock elseBlock); JmlMethodSig JmlConstraintMethodSig(JCExpression expr, List<JCExpression> argtypes); JmlDoWhileLoop JmlDoWhileLoop(JCDoWhileLoop loop, List<JmlStatementLoop> loopSpecs); JmlEnhancedForLoop JmlEnhancedForLoop(JCEnhancedForLoop loop, List<JmlStatementLoop> loopSpecs); JmlStatementExpr JmlExpressionStatement(JmlTokenKind t, Label label, JCTree.JCExpression e); JmlStatementHavoc JmlHavocStatement(List<JCTree.JCExpression> e); JmlForLoop JmlForLoop(JCForLoop loop, List<JmlStatementLoop> loopSpecs); JmlGroupName JmlGroupName(JCExpression selection); JmlImport JmlImport(JCTree qualid, boolean staticImport, boolean isModel); JmlLabeledStatement JmlLabeledStatement(Name label, ListBuffer<JCStatement> extra, JCStatement block); JmlLblExpression JmlLblExpression(int labelPosition, JmlTokenKind token, Name label, JCTree.JCExpression expr); JmlMethodClauseGroup JmlMethodClauseGroup(List<JmlSpecificationCase> cases); JmlMethodClauseDecl JmlMethodClauseDecl(JmlTokenKind t, List<JCTree.JCVariableDecl> decls); JmlMethodClauseExpr JmlMethodClauseExpr(JmlTokenKind t, JCTree.JCExpression e); JmlMethodClauseCallable JmlMethodClauseCallable(JmlStoreRefKeyword keyword); JmlMethodClauseCallable JmlMethodClauseCallable(List<JmlMethodSig> methodSignatures); JmlMethodClauseConditional JmlMethodClauseConditional(JmlTokenKind t, JCTree.JCExpression e, JCTree.JCExpression predicate); JmlMethodClauseSignals JmlMethodClauseSignals(JmlTokenKind t, JCTree.JCVariableDecl var, JCTree.JCExpression e); JmlMethodClauseSignalsOnly JmlMethodClauseSignalsOnly(JmlTokenKind t, List<JCTree.JCExpression> e); JmlMethodClause JmlMethodClauseStoreRef(JmlTokenKind t, List<JCExpression> list); JmlMethodInvocation JmlMethodInvocation(JmlTokenKind token, List<JCExpression> args); JmlMethodSpecs JmlMethodSpecs(List<JmlSpecificationCase> cases); JmlModelProgramStatement JmlModelProgramStatement(JCTree item); JmlPrimitiveTypeTree JmlPrimitiveTypeTree(JmlTokenKind jt); JmlQuantifiedExpr JmlQuantifiedExpr(JmlTokenKind token, List<JCVariableDecl> decls, JCTree.JCExpression range, JCTree.JCExpression predicate); JmlSetComprehension JmlSetComprehension(JCTree.JCExpression type, JCTree.JCVariableDecl v, JCTree.JCExpression predicate); JmlSingleton JmlSingleton(JmlTokenKind jt); JmlSpecificationCase JmlSpecificationCase(JCModifiers mods, boolean code, JmlTokenKind t, JmlTokenKind also, List<JmlMethodClause> clauses); JmlSpecificationCase JmlSpecificationCase(JmlSpecificationCase sc, List<JmlMethodClause> clauses); JmlSpecificationCase JmlSpecificationCase(JCModifiers mods, boolean code, JmlTokenKind t, JmlTokenKind also, JCBlock block); JmlStatement JmlStatement(JmlTokenKind t, JCTree.JCExpressionStatement e); JmlStatementDecls JmlStatementDecls(List<JCTree.JCStatement> list); JmlStatementLoop JmlStatementLoop(JmlTokenKind t, JCTree.JCExpression e); JmlStatementSpec JmlStatementSpec(JmlMethodSpecs specs); JmlStoreRefArrayRange JmlStoreRefArrayRange(JCExpression expr, JCExpression lo, JCExpression hi); JmlStoreRefKeyword JmlStoreRefKeyword(JmlTokenKind t); JmlStoreRefListExpression JmlStoreRefListExpression(JmlTokenKind t, List<JCExpression> list); JmlTypeClauseConditional JmlTypeClauseConditional(JCModifiers mods, JmlTokenKind token, JCTree.JCIdent ident, JCTree.JCExpression p); JmlTypeClauseConstraint JmlTypeClauseConstraint(JCModifiers mods, JCExpression e, List<JmlMethodSig> sigs); JmlTypeClauseDecl JmlTypeClauseDecl(JCTree decl); JmlTypeClauseExpr JmlTypeClauseExpr(JCModifiers mods, JmlTokenKind token, JCTree.JCExpression e); JmlTypeClauseIn JmlTypeClauseIn(List<JmlGroupName> list); JmlTypeClauseInitializer JmlTypeClauseInitializer(JmlTokenKind token, JCModifiers mods); JmlTypeClauseMaps JmlTypeClauseMaps(JCExpression e, List<JmlGroupName> list); JmlTypeClauseMonitorsFor JmlTypeClauseMonitorsFor(JCModifiers mods, JCTree.JCIdent ident, List<JCTree.JCExpression> list); JmlTypeClauseRepresents JmlTypeClauseRepresents(JCModifiers mods, JCTree.JCExpression ident, boolean suchThat, JCTree.JCExpression e); JmlWhileLoop JmlWhileLoop(JCWhileLoop loop, List<JmlStatementLoop> loopSpecs); JCExpression Type(Type t); } /** This class is a factory for JML parse tree nodes, and by extension, all * the Java parse tree nodes as well. */ public static class Maker extends TreeMaker implements JmlFactory { /** The factory keeps a reference to the context in which it was * created, for handy use later on. */ protected Context context; /** A constructor for the factory * @param context the compilation context with which to associate this factory */ public Maker(Context context) { super(context); this.context = context; } /** A method with which to register this factory with the compilation * unit context * @param context the compilation context to be associated with */ public static void preRegister(final Context context) { context.put(treeMakerKey, new Context.Factory<TreeMaker>() { @Override public Maker make(Context context) { return new Maker(context); } }); } /** The public method for obtaining a JmlTree.Maker instance. */ public static JmlTree.Maker instance(Context context) { JmlTree.Maker instance = (JmlTree.Maker)context.get(treeMakerKey); if (instance == null) instance = new JmlTree.Maker(context); // registers itself return instance; } /** Sets the preferred token position to be used for subsequent * factory produced nodes, typically used like this, for example: * maker.at(pos).JmlPrimitiveTypeTree(token); overridden simply to * return the derived type * @param pos the 0-based character position from the beginning of the input file */ @Override public Maker at(int pos) { super.at(pos); return this; } @Override public Maker at(DiagnosticPosition pos) { this.pos = (pos == null ? Position.NOPOS : pos.getPreferredPosition()); // FIXME - decide on preferred or start position //super.at(pos); return this; } /** Creates a JmlCompilationUnit */ @Override public JmlCompilationUnit TopLevel(List<JCAnnotation> packageAnnotations, JCExpression pid, List<JCTree> defs) { JmlCompilationUnit t = new JmlCompilationUnit(packageAnnotations, pid, defs, null,null,null,null); t.pos = this.pos; return t; } public JmlBlock Block(long flags, List<JCStatement> stats) { JmlBlock t = new JmlBlock(flags,stats); t.pos = this.pos; return t; } /** Convenience method to create a qualified identifier - either a * JCIdent or a JCFieldAccess; this is used for field names and * for qualified type names. * @param names the identifiers that are dot-separated * @return the resulting JCIdent of JCFieldAccess */ public JCExpression QualIdent(Name... names) { JCExpression t = Ident(names[0]); for (int i = 1; i < names.length; i++) { t = Select(t,names[i]); } return t; } /** Convenience method to create a qualified identifier - either a * JCIdent or a JCFieldAccess; this is used for field names and * for qualified type names. * @param names the identifiers that are dot-separated * @return the resulting JCIdent of JCFieldAccess */ public JCExpression QualIdent(String... names) { Names n = Names.instance(context); JCExpression t = Ident(n.fromString(names[0])); for (int i = 1; i < names.length; i++) { t = Select(t,n.fromString(names[i])); } return t; } public JmlAnnotation Annotation(JCTree type, List<JCExpression> args) { JmlAnnotation a = new JmlAnnotation(JCTree.Tag.ANNOTATION,type,args); a.pos = pos; return a; } /** Convenience method to create a JCIdent from a string * (use a Name if you have one, since this method creates a Name). * @param name the string to convert to wrap as an identifier * @return the resulting JCIdent */ public JCIdent Ident(String name) { Names n = Names.instance(context); return Ident(n.fromString(name)); } /** Convenience method to create a Name from a string * @param name the string to wrap as a Name * @return the resulting Name */ public Name Name(String name) { Names n = Names.instance(context); return n.fromString(name); } /** Creates a class declaration from its components, overridden * in order to produce a JmlClassDecl; the new object keeps a * reference to the current sourcefile in the log */ @Override public JmlClassDecl ClassDef(JCModifiers mods, Name name, List<JCTypeParameter> typarams, JCExpression extending, List<JCExpression> implementing, List<JCTree> defs) { JmlClassDecl tree = new JmlClassDecl(mods,name,typarams,extending,implementing,defs,null); tree.pos = pos; tree.sourcefile = Log.instance(context).currentSourceFile(); // In the normal course of things, context is never null, but there is a circular dependency of // instantiating tools that can occur in the constructors of the various tools. In particular // TreeMaker -> Symtab -> ClassReader -> Annotate -> Attr -> MemberEnter -> Enter which calls // TreeMaker.ClassDef before TreeMaker has completed construction // where A -> B means A constructs B during A's construction. This results in TreeMaker.ClassDef // being called with a null context during TreeMaker's construction // if (context != null) // tree.toplevel.sourcefile = Log.instance(context).currentSourceFile(); // else { if (context == null) { String msg = ("INTERNAL ERROR: JmlTree.ClassDef called with a null context, indicating a problem with circular dependencies in constructors."); System.err.println(msg); new Exception().printStackTrace(System.err); throw new JmlInternalError(msg); } return tree; } /** Creates a method declaration from its components, overridden * in order to produce a JmlMethodDecl; the new object keeps a * reference to the current sourcefile in the log */ @Override public JmlMethodDecl MethodDef(JCModifiers mods, Name name, JCExpression restype, List<JCTypeParameter> typarams, JCVariableDecl receiver, List<JCVariableDecl> params, List<JCExpression> thrown, JCBlock body, JCExpression defaultValue) { JmlMethodDecl tree = new JmlMethodDecl(mods,name,restype,typarams,receiver,params,thrown,body,defaultValue,null); // DRC Introduced null parameter to deal with new/evolved signature. tree.pos = pos; tree.sourcefile = Log.instance(context).currentSourceFile(); return tree; } /** Creates a method declaration from a method symbol and a method type */ @Override public JmlMethodDecl MethodDef(MethodSymbol m, Type mtype, JCBlock body) { JmlMethodDecl tree = (JmlMethodDecl) new JmlMethodDecl( Modifiers(m.flags(), Annotations(m.getAnnotationMirrors())), m.name, Type(mtype.getReturnType()), TypeParams(mtype.getTypeArguments()), null, // FIXME - receiver parameter Params(mtype.getParameterTypes(), m), Types(mtype.getThrownTypes()), body, null, m).setPos(pos).setType(mtype); tree.sourcefile = Log.instance(context).currentSourceFile(); return tree; } /** Creates a variable declaration with symbol and type filled in from its components; * sourcefile set from current log */ @Override public JmlVariableDecl VarDef(VarSymbol v, /*@Nullable*/ JCExpression init) { JmlVariableDecl tree = new JmlVariableDecl( Modifiers(v.flags(), Annotations(v.getAnnotationMirrors())), v.name, Type(v.type), init, v); tree.pos = pos; tree.setType(v.type); tree.sourcefile = Log.instance(context).currentSourceFile(); // Not filled in: docComment, fieldSpecs, fieldSpecsCombined, specsDecl return tree; } /** Creates a variable declaration from its components; captures the sourcefile * from the current value in the log; no symbol created. */ @Override public JmlVariableDecl VarDef(JCModifiers mods, Name name, /*@ nullable */ JCExpression vartype, // null if we are in a lambda expression JCExpression init) { JmlVariableDecl tree = new JmlVariableDecl(mods,name,vartype,init,null); tree.pos = pos; if (vartype != null) tree.type = vartype.type; // attribute if the type is known tree.sourcefile = Log.instance(context).currentSourceFile(); // Not filled in: symbol, docComment, fieldSpecs, fieldSpecsCombined, specsDecl return tree; } /** Creates an expression for a JML type (such as \TYPE or \real or \bigint).*/ @Override public JmlPrimitiveTypeTree JmlPrimitiveTypeTree(JmlTokenKind jt) { return new JmlPrimitiveTypeTree(pos,jt); } @Override public JCExpression Type(Type t) { if (!(t instanceof JmlType)) return super.Type(t); return new JmlPrimitiveTypeTree(pos,((JmlType)t).jmlTypeTag()); } /** Creates JML expressions from tokens without arguments (e.g. \result)*/ @Override public JmlSingleton JmlSingleton(JmlTokenKind jt) { return new JmlSingleton(pos,jt); } /** Creates a JML import statement (possibly a model import) */ @Override public JmlImport JmlImport(JCTree qualid, boolean staticImport, boolean isModel) { return (JmlImport)new JmlImport(qualid, staticImport,isModel).setPos(pos); } /** Creates a regular import, but using a JmlImport AST node */ @Override public JmlImport Import(JCTree qualid, boolean staticImport) { return (JmlImport)new JmlImport(qualid,staticImport,false).setPos(pos); } /** Creates a JML binary operation */ @Override public JmlBinary JmlBinary(JmlTokenKind t, JCTree.JCExpression left, JCTree.JCExpression right) { return new JmlBinary(pos,t,left,right); } /** Creates a JML method invocation (e.g. for JmlTokens with arguments, such as \typeof) */ @Override public JmlMethodInvocation JmlMethodInvocation(JmlTokenKind token, List<JCExpression> args) { return new JmlMethodInvocation(pos,token,args); } /** Creates a method invocation from a method name expression (e.g. o.name) */ public JmlMethodInvocation JmlMethodInvocation(JCExpression method, List<JCExpression> args) { return new JmlMethodInvocation(pos,method,args); } /** Creates a JML method invocation for the special case of one argument (e.g. for JmlTokens with arguments, such as \typeof) */ public JmlMethodInvocation JmlMethodInvocation(JmlTokenKind token, JCExpression arg) { return new JmlMethodInvocation(pos,token,List.<JCExpression>of(arg)); } /** Creates a JML method invocation for the special case of two arguments */ public JmlMethodInvocation JmlMethodInvocation(JmlTokenKind token, JCExpression arg, JCExpression arg2) { return new JmlMethodInvocation(pos,token,List.<JCExpression>of(arg,arg2)); } /** Creates a JML quantified expression */ @Override public JmlQuantifiedExpr JmlQuantifiedExpr(JmlTokenKind t, List<JCTree.JCVariableDecl> decls, JCTree.JCExpression range, JCTree.JCExpression value) { return new JmlQuantifiedExpr(pos,t,decls,range,value); } /** Creates a JML set-comprehension expression */ @Override public JmlSetComprehension JmlSetComprehension(JCTree.JCExpression type, JCTree.JCVariableDecl varDecl, JCTree.JCExpression value) { return new JmlSetComprehension(pos,type,varDecl,value); } /** Creates a JML labeled statement */ @Override public JmlLabeledStatement JmlLabeledStatement(Name label, ListBuffer<JCStatement> extra, JCStatement body) { JmlLabeledStatement p = new JmlLabeledStatement(label,body); p.pos = pos; if (extra == null) extra = new ListBuffer<JCStatement>(); p.extraStatements = extra; return p; } /** Creates a JML labeled expression */ @Override public JmlLblExpression JmlLblExpression(int labelPosition, JmlTokenKind token, Name label, JCTree.JCExpression expr) { JmlLblExpression p = new JmlLblExpression(pos,labelPosition,token,label,expr); return p; } /** Creates a JML expression statement (e.g. assert) */ @Override public JmlStatementExpr JmlExpressionStatement(JmlTokenKind t, Label label, JCTree.JCExpression e) { return new JmlStatementExpr(pos,t,label,e); } /** Creates a JML havoc statement */ @Override public JmlStatementHavoc JmlHavocStatement(List<JCTree.JCExpression> e) { return new JmlStatementHavoc(pos,e); } /** This creates a pseudo-statement in a method body that is actually a block of method specifications */ @Override public JmlStatementSpec JmlStatementSpec(JmlMethodSpecs specs) { return new JmlStatementSpec(pos,specs); } /** Creates a JML loop specification statement (e.g. loop_invariant, decreases, ... )*/ @Override public JmlStatementLoop JmlStatementLoop(JmlTokenKind t, JCTree.JCExpression e) { return new JmlStatementLoop(pos,t,e); } /** Creates a JML do-while loop node that wraps a Java loop statement and a set of loop specifications */ @Override public JmlDoWhileLoop JmlDoWhileLoop(JCDoWhileLoop loop, List<JmlStatementLoop> loopSpecs) { return new JmlDoWhileLoop(loop,loopSpecs); // pos set from loop argument } /** Creates a regular for-loop with no specifications */ @Override public JmlForLoop ForLoop(List<JCStatement> init, JCExpression cond, List<JCExpressionStatement> step, JCStatement body) { JCForLoop tree = super.ForLoop(init, cond, step, body); tree.pos = pos; return JmlForLoop(tree,null); } /** Creates a regular foreach-loop with no specifications */ @Override public JCEnhancedForLoop ForeachLoop(JCVariableDecl var, JCExpression expr, JCStatement body) { JCEnhancedForLoop tree = super.ForeachLoop(var, expr, body); tree.pos = pos; return JmlEnhancedForLoop(tree,null); } /** Creates a regular do-loop with no specifications */ @Override public JmlDoWhileLoop DoLoop(JCStatement body, JCExpression cond) { JCDoWhileLoop tree = super.DoLoop(body, cond); tree.pos = pos; return JmlDoWhileLoop(tree,null); } /** Creates a regular while-loop with no specifications */ @Override public JmlWhileLoop WhileLoop(JCExpression cond, JCStatement body) { JCWhileLoop tree = super.WhileLoop(cond, body); tree.pos = pos; return JmlWhileLoop(tree,null); } /** Creates a for-loop with specifications */ @Override public JmlForLoop JmlForLoop(JCForLoop loop, List<JmlStatementLoop> loopSpecs) { return new JmlForLoop(loop,loopSpecs); } /** Creates a foreach-loop with specifications */ @Override public JmlEnhancedForLoop JmlEnhancedForLoop(JCEnhancedForLoop loop, List<JmlStatementLoop> loopSpecs) { return new JmlEnhancedForLoop(loop,loopSpecs); } /** Creates a while-loop with specifications */ @Override public JmlWhileLoop JmlWhileLoop(JCWhileLoop loop, List<JmlStatementLoop> loopSpecs) { return new JmlWhileLoop(loop,loopSpecs); // pos and type set from loop } /** Creates a JML statement such as ghost declarations */ @Override public JmlStatementDecls JmlStatementDecls(List<JCTree.JCStatement> list) { return new JmlStatementDecls(pos,list); } /** Creates JML statements such as set and debug */ @Override public JmlStatement JmlStatement(JmlTokenKind t, JCTree.JCExpressionStatement e) { return new JmlStatement(pos,t,e); } @Override public JmlStoreRefListExpression JmlStoreRefListExpression(JmlTokenKind t, List<JCExpression> list) { return new JmlStoreRefListExpression(pos,t,list); } @Override public JmlStoreRefKeyword JmlStoreRefKeyword(JmlTokenKind t) { return new JmlStoreRefKeyword(pos,t); } @Override public JmlStoreRefArrayRange JmlStoreRefArrayRange(JCExpression expr, JCExpression lo, JCExpression hi) { return new JmlStoreRefArrayRange(pos,expr,lo,hi); } @Override public JmlTypeClauseExpr JmlTypeClauseExpr(JCModifiers mods, JmlTokenKind token, JCTree.JCExpression e) { JmlTypeClauseExpr t = new JmlTypeClauseExpr(pos,mods,token,e); t.source = Log.instance(context).currentSourceFile(); return t; } @Override public JmlTypeClauseDecl JmlTypeClauseDecl(JCTree decl) { JmlTypeClauseDecl t = new JmlTypeClauseDecl(pos,decl); t.source = Log.instance(context).currentSourceFile(); return t; } @Override public JmlTypeClauseInitializer JmlTypeClauseInitializer(JmlTokenKind token, JCModifiers mods) { JmlTypeClauseInitializer t = new JmlTypeClauseInitializer(pos, token, mods); t.source = Log.instance(context).currentSourceFile(); return t; } @Override public JmlTypeClauseConstraint JmlTypeClauseConstraint(JCModifiers mods, JCTree.JCExpression e, List<JmlMethodSig> sigs) { JmlTypeClauseConstraint t = new JmlTypeClauseConstraint(pos,mods,e,sigs); t.source = Log.instance(context).currentSourceFile(); return t; } @Override public JmlChoose JmlChoose(JmlTokenKind token, List<JCBlock> orBlocks, /*@Nullable*/JCBlock elseBlock) { return new JmlChoose(pos,token,orBlocks,elseBlock); } @Override public JmlMethodSig JmlConstraintMethodSig(JCExpression expr, List<JCExpression> argtypes) { return new JmlMethodSig(pos,expr,argtypes); } @Override public JmlTypeClauseRepresents JmlTypeClauseRepresents(JCModifiers mods, JCTree.JCExpression ident, boolean suchThat, JCTree.JCExpression e) { JmlTypeClauseRepresents t = new JmlTypeClauseRepresents(pos, mods, ident,suchThat,e); t.source = Log.instance(context).currentSourceFile(); return t; } @Override public JmlTypeClauseConditional JmlTypeClauseConditional(JCModifiers mods, JmlTokenKind token, JCTree.JCIdent ident, JCTree.JCExpression p) { JmlTypeClauseConditional t = new JmlTypeClauseConditional(pos, mods, token,ident,p); t.source = Log.instance(context).currentSourceFile(); return t; } @Override public JmlTypeClauseMonitorsFor JmlTypeClauseMonitorsFor(JCModifiers mods, JCTree.JCIdent ident, List<JCTree.JCExpression> list) { JmlTypeClauseMonitorsFor t = new JmlTypeClauseMonitorsFor(pos, mods, ident, list); t.source = Log.instance(context).currentSourceFile(); return t; } @Override public JmlMethodClauseGroup JmlMethodClauseGroup(List<JmlSpecificationCase> list) { return new JmlMethodClauseGroup(pos,list); } @Override public JmlMethodClauseDecl JmlMethodClauseDecl(JmlTokenKind t, List<JCTree.JCVariableDecl> decls) { return new JmlMethodClauseDecl(pos,t,decls); } @Override public JmlMethodClauseExpr JmlMethodClauseExpr(JmlTokenKind t, JCTree.JCExpression e) { return new JmlMethodClauseExpr(pos,t,e); } @Override public JmlMethodClauseCallable JmlMethodClauseCallable(JmlStoreRefKeyword keyword) { return new JmlMethodClauseCallable(pos,keyword,null); } @Override public JmlMethodClauseCallable JmlMethodClauseCallable(List<JmlMethodSig> methodSignatures) { return new JmlMethodClauseCallable(pos,null,methodSignatures); } @Override public JmlMethodClauseConditional JmlMethodClauseConditional(JmlTokenKind t, JCTree.JCExpression e, JCTree.JCExpression p) { return new JmlMethodClauseConditional(pos,t,e,p); } @Override public JmlMethodClauseSignals JmlMethodClauseSignals(JmlTokenKind t, JCTree.JCVariableDecl var, JCTree.JCExpression e) { return new JmlMethodClauseSignals(pos,t,var,e); } @Override public JmlMethodClauseSignalsOnly JmlMethodClauseSignalsOnly(JmlTokenKind t, List<JCTree.JCExpression> e) { return new JmlMethodClauseSignalsOnly(pos,t,e); } @Override public JmlMethodClauseStoreRef JmlMethodClauseStoreRef(JmlTokenKind t, List<JCExpression> list) { return new JmlMethodClauseStoreRef(pos, t, list); } @Override public JmlModelProgramStatement JmlModelProgramStatement(JCTree item) { return new JmlModelProgramStatement(pos, item); } @Override public JmlSpecificationCase JmlSpecificationCase(JCModifiers mods, boolean code, JmlTokenKind t, JmlTokenKind also, List<JmlMethodClause> clauses) { JmlSpecificationCase jcase = new JmlSpecificationCase(pos,mods,code,t,also,clauses); jcase.sourcefile = Log.instance(context).currentSourceFile(); return jcase; } @Override public JmlSpecificationCase JmlSpecificationCase(JCModifiers mods, boolean code, JmlTokenKind t, JmlTokenKind also, JCBlock block) { JmlSpecificationCase jcase = new JmlSpecificationCase(pos,mods,code,t,also,block); jcase.sourcefile = Log.instance(context).currentSourceFile(); return jcase; } @Override public JmlSpecificationCase JmlSpecificationCase(JmlSpecificationCase sc, List<JmlMethodClause> clauses) { return new JmlSpecificationCase(sc,clauses); } @Override public JmlMethodSpecs JmlMethodSpecs(List<JmlSpecificationCase> cases) { return new JmlMethodSpecs(pos,cases); } @Override public JmlGroupName JmlGroupName(JCExpression selection) { return new JmlGroupName(pos,selection); } @Override public JmlTypeClauseIn JmlTypeClauseIn(List<JmlGroupName> list) { JmlTypeClauseIn r = new JmlTypeClauseIn(pos,list); r.source = Log.instance(context).currentSourceFile(); return r; } @Override public JmlTypeClauseMaps JmlTypeClauseMaps(JCExpression e, List<JmlGroupName> list) { JmlTypeClauseMaps r = new JmlTypeClauseMaps(pos,e,list); r.source = Log.instance(context).currentSourceFile(); return r; } } // IMPLEMENTATION NOTES: // The getTag method returns an int value that identifies the sort of node. // It is supposed to be used in preference to instanceof to determine subtypes. // Here we just expand on the numbers used in JCTree. // // The getKind method appears to have the same purpose, except that it is // an Enum, which cannot be expanded. getKind is used only a few occasions. // Here, the getKind method is implemented to return Kind.OTHER. This is because // this method returns a Kind of node, but Kind is an enum of Java node kinds // and cannot be extended. We use OTHER, despite the warning in Tree.java, // because there is no other option, besides null. For JML nodes we don't // use this anyway (because of this problem). // These numbers used for getTag(); public static final int JMLFUNCTION = 1000; // The 1000 used to be enough to be higher than the JCTree tags, but those are enums now public static final int JMLBINARY = JMLFUNCTION + 1; public static final int JMLSTATEMENT = JMLBINARY + 1; public static final int JMLSTATEMENTSPEC = JMLBINARY + 1; public static final int JMLSTATEMENTLOOP = JMLSTATEMENTSPEC + 1; public static final int JMLSTATEMENTEXPR = JMLSTATEMENTLOOP + 1; public static final int JMLSTATEMENTHAVOC = JMLSTATEMENTEXPR + 1; public static final int JMLSTATEMENTDECLS = JMLSTATEMENTHAVOC + 1; public static final int JMLMETHODCLAUSEGROUP = JMLSTATEMENTDECLS + 1; public static final int JMLMETHODCLAUSECALLABLE = JMLMETHODCLAUSEGROUP + 1; public static final int JMLMETHODCLAUSEDECL = JMLMETHODCLAUSECALLABLE + 1; public static final int JMLMETHODCLAUSEEXPR = JMLMETHODCLAUSEDECL + 1; public static final int JMLMETHODCLAUSECONDITIONAL = JMLMETHODCLAUSEEXPR + 1; public static final int JMLMETHODCLAUSESIGNALS = JMLMETHODCLAUSECONDITIONAL + 1; public static final int JMLMETHODCLAUSESIGNALSONLY = JMLMETHODCLAUSESIGNALS + 1; public static final int JMLMETHODCLAUSEASSIGNABLE = JMLMETHODCLAUSESIGNALSONLY + 1; public static final int JMLMETHODSPECS = JMLMETHODCLAUSEASSIGNABLE + 1; public static final int JMLSPECIFICATIONCASE = JMLMETHODSPECS + 1; public static final int JMLPRIMITIVETYPETREE = JMLSPECIFICATIONCASE + 1; public static final int JMLQUANTIFIEDEXPR = JMLPRIMITIVETYPETREE + 1; public static final int JMLSETCOMPREHENSION = JMLQUANTIFIEDEXPR + 1; public static final int JMLLBLEXPR = JMLSETCOMPREHENSION + 1; public static final int JMLSINGLETON = JMLLBLEXPR + 1; public static final int JMLTYPECLAUSEEXPR = JMLSINGLETON + 1; public static final int JMLTYPECLAUSEDECL = JMLTYPECLAUSEEXPR + 1; public static final int JMLTYPECLAUSEREPRESENTS = JMLTYPECLAUSEDECL + 1; public static final int JMLTYPECLAUSECONSTRAINT = JMLTYPECLAUSEREPRESENTS + 1; public static final int JMLCONSTRAINTMETHODSIG = JMLTYPECLAUSECONSTRAINT + 1; public static final int JMLTYPECLAUSEINITIALIZER = JMLCONSTRAINTMETHODSIG + 1; public static final int JMLTYPECLAUSECONDITIONAL = JMLTYPECLAUSEINITIALIZER + 1; public static final int JMLTYPECLAUSEMONITORSFOR = JMLTYPECLAUSECONDITIONAL + 1; public static final int JMLGROUPNAME = JMLTYPECLAUSEMONITORSFOR + 1; public static final int JMLTYPECLAUSEIN = JMLGROUPNAME + 1; public static final int JMLTYPECLAUSEMAPS = JMLTYPECLAUSEIN + 1; public static final int JMLSTOREREFKEYWORD = JMLTYPECLAUSEMAPS + 1; public static final int JMLSTOREREFLISTEXPR = JMLSTOREREFKEYWORD + 1; public static final int JMLSTOREREFIDENT = JMLSTOREREFLISTEXPR + 1; public static final int JMLSTOREREFFIELD = JMLSTOREREFIDENT + 1; public static final int JMLSTOREREFARRAYRANGE = JMLSTOREREFFIELD + 1; public static final int JMLLASTTAG = JMLSTOREREFARRAYRANGE; /** The system-defined end of line character string */ static public final String eol = System.getProperty("line.separator"); static public void unexpectedVisitor(JCTree t, Object visitor) { // FIXME - a better error System.out.println("A " + t.getClass() + " expects an IJmlVisitor, not a " + visitor.getClass()); } public abstract class JCTreeX extends JCTree { @Override public Tag getTag() { return null; } @Override public Kind getKind() { // TODO Auto-generated method stub return null; } } /** This is an interface for any node that contains source file information. */ public interface JmlSource { /** Returns the file object containing the source code for the AST node */ @Nullable JavaFileObject source(); } /** This class adds some JML specific information to the JCCompilationUnit toplevel node. */ public static class JmlCompilationUnit extends JCTree.JCCompilationUnit { /** This list contains the parse tree of the specification file, if any, for this compilation unit. * This field may point to 'this' if the compilation unit is its own specs file. */ public /*@ nullable */ JmlCompilationUnit specsCompilationUnit = null; // /** This list contains the top-level model types declared in this compilation unit; this // * is not necessarily all or even part of the top-level model types that the CUs specifications // * specify, since (a) other spec files may contribute top-level model types // * and (b) this CU may not be part of its own spec sequence. // */ // public ListBuffer<JmlClassDecl> parsedTopLevelModelTypes = new ListBuffer<JmlClassDecl>(); // // /** This list is the set of top-level model types specified by the // * CUs specifications. It is assembled when types are entered in JmlEnter. // */ // public java.util.List<JmlClassDecl> specsTopLevelModelTypes = new java.util.LinkedList<JmlClassDecl>(); // FIXME - review the use of this value /** The use to be made of this parse tree - one of the int constants below. */ public int mode = 0; // init to an unknown value public Env<AttrContext> topLevelEnv; /** An unspecified value. */ public static final int UNKNOWN = 0; // FIXME - the whole use of this mode needs reviewing // Properties are encoded as bits: // Note that a specification file can be .java or not .java // 1-bit this is a file that can contain source code (i.e. has a .java suffix) // 2-bit this is a specification file // 4-bit the implementation is in a binary file, not a source file // 8-bit full typechecking is desired - FIXME - do away with this I think /** Process the java source fully, including method bodies and field initializers. */ public static final int JAVA_SOURCE_FULL = 1; /** Process the java source for signatures and specifications only. */ public static final int JAVA_SOURCE_PARTIAL = 9; /** Process the java source for signatures and specifications only. */ public static final int JAVA_AS_SPEC_FOR_SOURCE = 3; /** Process the java source for signatures and specifications only. */ public static final int JAVA_AS_SPEC_FOR_BINARY = 7; /** This is a specification file for Java source */ public static final int SPEC_FOR_SOURCE = 2; /** This is a specification file, belonging to a Java class file (no java source) */ public static final int SPEC_FOR_BINARY = 6; /** This is a specification file but there is no Java source or binary file */ //public static final int SPEC_ALONE = ?; // static public boolean isJava(int mode) { return (mode & 1) != 0; } // // static public boolean isSpec(int mode) { return (mode & 2) != 0; } static public boolean isForSource(int mode) { return (mode & 4) == 0; } static public boolean isForBinary(int mode) { return (mode & 4) != 0; } // static public boolean isFull(int mode) { return (mode & 8) == 0; } /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlCompilationUnit(List<JCAnnotation> packageAnnotations, JCExpression pid, List<JCTree> defs, JavaFileObject sourcefile, PackageSymbol packge, ImportScope namedImportScope, StarImportScope starImportScope) { super(packageAnnotations,pid,defs,sourcefile,packge,namedImportScope,starImportScope); } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlCompilationUnit(this); } else { // unexpectedVisitor(this,v); super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlCompilationUnit(this, d); } else { // unexpectedVisitor(this,v); return super.accept(v,d); } } @Override public String toString() { return JmlTree.toString(this); } } public static class JmlImport extends JCTree.JCImport { public boolean isModel = false; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlImport(JCTree qualid, boolean importStatic, boolean isModel) { super(qualid,importStatic); this.isModel = isModel; } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlImport(this); } else { // unexpectedVisitor(this,v); super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlImport(this, d); } else { // unexpectedVisitor(this,v); return super.accept(v,d); } } @Override public String toString() { return JmlTree.toString(this); } } /** This class represents model program choose and choose_if statements. */ public static class JmlChoose extends JmlAbstractStatement { public JmlTokenKind token; public List<JCBlock> orBlocks; /*@Nullable*/ public JCBlock elseBlock; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlChoose(int pos, JmlTokenKind token, List<JCBlock> orBlocks, /*@Nullable*/ JCBlock elseBlock) { this.pos = pos; this.token = token; this.orBlocks = orBlocks; this.elseBlock = elseBlock; } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlChoose(this); } else { // unexpectedVisitor(this,v); super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlChoose(this, d); } else { // unexpectedVisitor(this,v); return super.accept(v,d); } } @Override public String toString() { return JmlTree.toString(this); } } /** This class adds some JML specific information to the JCClassDecl toplevel node. */ public static class JmlClassDecl extends JCTree.JCClassDecl implements JmlSource, IInJML { /** This is the class declaration that holds the specifications for the * containing class. It may be the same as the containing class, or a different AST * (e.g., from a .jml file), or null if there are no specifications for this class. * A class declaration in a .jml file will have a null value for this field. */ public /*@Nullable*/ JmlClassDecl specsDecl; /** This field holds the class-level specifications for the type corresponding * to this declaration; it is an alias for the specs that are found in the JmlSpecs database */ public JmlSpecs.TypeSpecs typeSpecs; /** The top-level tree that this class declaration belongs to; for specification * declarations this is the compilation unit containing the spec declaration, which * may be different than the compilation unit containing the java class declaration. * Note that the sourcefile for this class declaration can be obtained from * toplevel.sourcefile*/ public JmlCompilationUnit toplevel; // FIXME - is this used; why would it not be in JCClassDecl? public String docComment = null; /** The scope environment for this class declaration. * For a source file, this is the same as typeEnvs.get() * but for a specifications file it may be different. */ public Env<AttrContext> env; /** Set during attribution, used during RAC - the value in Enter is * removed by then. */ public VarSymbol thisSymbol; public VarSymbol superSymbol; public JCBlock initializerBlock; public Env<AttrContext> initializerBlockEnv; public JCBlock staticInitializerBlock; public Env<AttrContext> staticInitializerBlockEnv; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlClassDecl(JCModifiers mods, Name name, List<JCTypeParameter> typarams, JCExpression extending, List<JCExpression> implementing, List<JCTree> defs, ClassSymbol sym) { super(mods, name, typarams, extending, implementing, defs, sym); specsDecl = null; typeSpecs = null; } /** The source this class was declared int - may be different than the top-level compilation * unit after model classes are moved around, etc. */ public JavaFileObject sourcefile; /** The source this class was declared in (model classes may be declared * in a source file different than the class that owns the model class) */ @Override public JavaFileObject source() { return sourcefile; } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlClassDecl(this); } else { // unexpectedVisitor(this,v); super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlClassDecl(this, d); } else { // unexpectedVisitor(this,v); return super.accept(v,d); } } @Override public String toString() { return JmlTree.toString(this); } @Override public boolean isJML() { return JmlTree.isJML(mods.flags); } public boolean isTypeChecked() { ClassSymbol c = sym; if (c == null) return false; return ((c.flags_field & UNATTRIBUTED) == 0); } } /** This class adds some JML specific information to the JCMethodDecl node. */ public static class JmlMethodDecl extends JCTree.JCMethodDecl implements JmlSource, IInJML { /** The file containing this declaration */ public JavaFileObject sourcefile; /** The declaration in the jml file, * or null if there is a jml file but no declaration of this method in it, * or the same as the java declaration if there is no jml file * (set in JmlMemberEnter); set to self in the parser for * methods in anonymous classes. */ @Nullable public JmlMethodDecl specsDecl; /** The final, combined specs from all sources (set in JmlMemberEnter); * set to self in parser for methods in anonymous classes */ public JmlSpecs.MethodSpecs methodSpecsCombined; public JmlMethodSpecs cases; // FIXME - change to JmlSpecificationCase? public String docComment = null; // FIXME - clarify why needed public VarSymbol _this = null; // The Symbol for 'this' inside the method, if not static; // valid after attribution /** The constructor for the AST node - but use the factory to get new nodes, not this */ public JmlMethodDecl(JCModifiers mods, Name name, JCExpression restype, // FIXME - backdoor use - should not be public List<JCTypeParameter> typarams, JCVariableDecl recvparam, List<JCVariableDecl> params, List<JCExpression> thrown, JCBlock body, JCExpression defaultValue, MethodSymbol sym) { super(mods, name, restype, typarams, recvparam, params, thrown, body, defaultValue, sym); specsDecl = null; sourcefile = null; } /** The source this method was declared in (model methods may be declared * in a source file different than the class that owns the model method) */ @Override public JavaFileObject source() { return sourcefile; } @Override public boolean isJML() { return JmlTree.isJML(mods.flags); } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlMethodDecl(this); } else { // unexpectedVisitor(this,v); super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlMethodDecl(this, d); } else { // unexpectedVisitor(this,v); return super.accept(v,d); } } @Override public String toString() { return JmlTree.toString(this); } } /** This class adds some JML specific information to the JCMethodDecl node. */ public static class JmlBlock extends JCTree.JCBlock implements JmlSource, IInJML { /** The file containing this declaration */ public JavaFileObject sourcefile; /** The declaration in the jml file, * or null if there is a jml file but no declaration of this method in it, * or the same as the java declaration if there is no jml file * (set in JmlMemberEnter); set to self in the parser for * methods in anonymous classes. */ @Nullable public JmlMethodDecl specsDecl; /** The final, combined specs from all sources (set in JmlMemberEnter); * set to self in parser for methods in anonymous classes */ public JmlSpecs.MethodSpecs methodSpecsCombined; public JmlMethodSpecs cases; // FIXME - change to JmlSpecificationCase? public String docComment = null; // FIXME - clarify why needed public VarSymbol _this = null; // The Symbol for 'this' inside the method, if not static; // valid after attribution /** The constructor for the AST node - but use the factory to get new nodes, not this */ public JmlBlock(long flags, List<JCStatement> stats) { super(flags, stats); specsDecl = null; sourcefile = null; } /** The source this method was declared in (model methods may be declared * in a source file different than the class that owns the model method) */ @Override public JavaFileObject source() { return sourcefile; } @Override public boolean isJML() { return JmlTree.isJML(flags); } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlBlock(this); } else { // unexpectedVisitor(this,v); super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlBlock(this, d); } else { // unexpectedVisitor(this,v); return super.accept(v,d); } } @Override public String toString() { return JmlTree.toString(this); } } /** This class adds some JML specific information to the JCVariableDecl node. */ public static class JmlVariableDecl extends JCTree.JCVariableDecl implements JmlSource, IInJML { // FIXME - need some documentation of these fields public JmlVariableDecl specsDecl; public JmlSpecs.FieldSpecs fieldSpecs; public JmlSpecs.FieldSpecs fieldSpecsCombined; public JavaFileObject sourcefile; public String docComment = null; // FIXME - why? /** A fixed ident used in ESC */ public JCIdent ident = null; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlVariableDecl(JCModifiers mods, Name name, /*@ nullable */ JCExpression vartype, JCExpression init, VarSymbol sym) { super(mods, name, vartype, init, sym); specsDecl = null; fieldSpecs = null; fieldSpecsCombined = null; sourcefile = null; } /** The source this variable was declared in (model variable may be declared * in a source file different than the class that owns the model variable) */ @Override public JavaFileObject source() { return sourcefile; } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlVariableDecl(this); } else { // unexpectedVisitor(this,v); super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlVariableDecl(this, d); } else { // unexpectedVisitor(this,v); return super.accept(v,d); } } @Override public String toString() { return JmlTree.toString(this); } @Override public boolean isJML() { return JmlTree.isJML(mods.flags); } } /** An abstract class that parents any Jml expression classes (that are not * special cases of other specific Java expressions) */ abstract public static class JmlExpression extends JCTree.JCExpression { @Override public String toString() { return JmlTree.toString(this); } @Override public int getStartPosition() { return pos; } } /** This class is simply a superclass for all AST classes representing * statements within the body of a method. From a Java perspective, these * need to behave like Skip statements. */ public static abstract class JmlAbstractStatement extends JCTree.JCSkip { public String toString() { return JmlTree.toString(this); } public int getStartPosition() { return pos; } } /** This class represents binary expressions with JML operators */ public static class JmlBinary extends JmlExpression implements IJmlBinary { public JmlTokenKind op; public JCExpression lhs; public JCExpression rhs; @Override public ExpressionTree getLeftOperand() { return lhs; } @Override public JmlTokenKind getOp() { return op; } @Override public ExpressionTree getRightOperand() {return rhs; } /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlBinary(int pos, JmlTokenKind op, JCExpression lhs, JCExpression rhs) { this.pos = pos; this.op = op; this.lhs = lhs; this.rhs = rhs; } /** A shallow copy constructor */ protected JmlBinary(JmlBinary that) { this.op = that.op; this.lhs = that.lhs; this.rhs = that.rhs; this.pos = that.pos; this.type = that.type; } // public Symbol getOperator() { // return null; // FIXME // } @Override public Kind getKind() { return Kind.OTHER; // See note above } @Override public Tag getTag() { // This is used in determining start and end positions return null; } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlBinary(this); } else { lhs.accept(v); rhs.accept(v); //unexpectedVisitor(this,v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlBinary(this, d); } else { unexpectedVisitor(this,v); return null; } } @Override public int getStartPosition() { return lhs.getStartPosition(); } @Override public int getEndPosition(EndPosTable table) { return rhs.getEndPosition(table); } } /** This class represents the method signatures in the constraint type * specification clause or the callable method specification clause. * @author David Cok */ public static class JmlMethodSig extends JCTree { public JCExpression expression; public List<JCExpression> argtypes; public MethodSymbol methodSymbol; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlMethodSig(int pos, JCExpression expr, List<JCExpression> argtypes) { this.pos = pos; this.expression = expr; this.argtypes = argtypes; this.methodSymbol = null; } @Override public Kind getKind() { return Kind.OTHER; // See note above } @Override public Tag getTag() { return null; } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlMethodSig(this); } else { unexpectedVisitor(this,v); //super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlConstraintMethodSig(this, d); } else { unexpectedVisitor(this,v); return null; //return super.accept(v,d); } } @Override public String toString() { return JmlTree.toString(this); } @Override public int getStartPosition() { return pos; } } /** This class wraps a Java do while loop just so it can attach some specs * to it. */ public static class JmlDoWhileLoop extends JCDoWhileLoop implements IJmlLoop { public List<JmlStatementLoop> loopSpecs; public List<JmlStatementLoop> loopSpecs() { return loopSpecs; } public void setLoopSpecs(List<JmlStatementLoop> loopSpecs) { this.loopSpecs = loopSpecs; } /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlDoWhileLoop(JCDoWhileLoop loop, List<JmlStatementLoop> loopSpecs) { super(loop.body,loop.cond); this.pos = loop.pos; this.type = loop.type; // copied for completeness, in case a loop ever has a type this.loopSpecs = loopSpecs; } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlDoWhileLoop(this); } else { // unexpectedVisitor(this,v); super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlDoWhileLoop(this, d); } else { //System.out.println("A JmlDoWhileLoop expects an JmlTreeVisitor, not a " + v.getClass()); return super.accept(v,d); } } @Override public String toString() { return JmlTree.toString(this); } @Override public int getStartPosition() { return -1; } @Override public int getEndPosition(EndPosTable table) { return -1; } } /** This class wraps a Java enhanced loop just so it can attach some specs * to it. */ public static class JmlEnhancedForLoop extends JCEnhancedForLoop implements IJmlLoop { public List<JmlStatementLoop> loopSpecs; public List<JmlStatementLoop> loopSpecs() { return loopSpecs; } public void setLoopSpecs(List<JmlStatementLoop> loopSpecs) { this.loopSpecs = loopSpecs; } /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlEnhancedForLoop(JCEnhancedForLoop loop, List<JmlStatementLoop> loopSpecs) { super(loop.var, loop.expr, loop.body); this.pos = loop.pos; this.type = loop.type; // copied for completeness, in case a loop ever has a type this.loopSpecs = loopSpecs; } // These are used for rewriting the loop in JmlAttr public JCVariableDecl indexDecl; public JCVariableDecl valuesDecl; public JCVariableDecl iterDecl; public JCBlock implementation; public JmlForLoop internalForLoop; @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlEnhancedForLoop(this); } else { //System.out.println("A JmlEnhancedForLoop expects an IJmlVisitor, not a " + v.getClass()); super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlEnhancedForLoop(this, d); } else { //System.out.println("A JmlEnhancedForLoop expects an JmlTreeVisitor, not a " + v.getClass()); return super.accept(v,d); } } @Override public String toString() { return JmlTree.toString(this); } } public static interface IJmlLoop { List<JmlStatementLoop> loopSpecs(); void setLoopSpecs(List<JmlStatementLoop> loopSpecs); } /** This class wraps a Java for loop just so it can attach some specs * to it. */ public static class JmlForLoop extends JCForLoop implements IJmlLoop { public List<JmlStatementLoop> loopSpecs; public List<JmlStatementLoop> loopSpecs() { return loopSpecs; } public void setLoopSpecs(List<JmlStatementLoop> loopSpecs) { this.loopSpecs = loopSpecs; } /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlForLoop(JCForLoop loop, List<JmlStatementLoop> loopSpecs) { super(loop.init,loop.cond,loop.step,loop.body); this.pos = loop.pos; this.type = loop.type; // copied for completeness, in case a loop ever has a type this.loopSpecs = loopSpecs; } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlForLoop(this); } else { //System.out.println("A JmlForLoop expects an IJmlVisitor, not a " + v.getClass()); super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlForLoop(this, d); } else { //System.out.println("A JmlForLoop expects an JmlTreeVisitor, not a " + v.getClass()); return super.accept(v,d); } } @Override public String toString() { return JmlTree.toString(this); } } /** This class wraps a Java while loop just so it can attach some specs * to it. */ public static class JmlWhileLoop extends JCWhileLoop implements IJmlLoop { /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlWhileLoop(JCWhileLoop loop, List<JmlStatementLoop> loopSpecs) { super(loop.cond,loop.body); this.pos = loop.pos; this.type = loop.type; // copied for completeness, in case a loop ever has a type this.loopSpecs = loopSpecs; } public List<JmlStatementLoop> loopSpecs; public List<JmlStatementLoop> loopSpecs() { return loopSpecs; } public void setLoopSpecs(List<JmlStatementLoop> loopSpecs) { this.loopSpecs = loopSpecs; } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlWhileLoop(this); } else { //System.out.println("A JmlWhileLoop expects an IJmlVisitor, not a " + v.getClass()); super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlWhileLoop(this, d); } else { //System.out.println("A JmlWhileLoop expects an JmlTreeVisitor, not a " + v.getClass()); return super.accept(v,d); } } @Override public String toString() { return JmlTree.toString(this); } } /** This class represents a group in an "in" or "maps" type clause in a class specification */ public static class JmlGroupName extends JCTree { public JCExpression selection; public VarSymbol sym; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlGroupName(int pos, JCExpression selection) { this.pos = pos; this.selection = selection; } @Override public Kind getKind() { return Kind.OTHER; // See note above } @Override public int getStartPosition() { return pos; } @Override public Tag getTag() { return null; } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlGroupName(this); } else { System.out.println("A JmlGroupName expects an IJmlVisitor, not a " + v.getClass()); //super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlGroupName(this, d); } else { System.out.println("A JmlGroupName expects an JmlTreeVisitor, not a " + v.getClass()); return null; //return super.accept(v,d); } } @Override public String toString() { return JmlTree.toString(this); } } public static class JmlLabeledStatement extends JCTree.JCLabeledStatement { public ListBuffer<JCStatement> extraStatements = new ListBuffer<>(); protected JmlLabeledStatement(Name label, JCStatement body) { super(label,body); } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlLabeledStatement(this); } else { //System.out.println("A JmlLblExpression expects an IJmlVisitor, not a " + v.getClass()); v.visitLabelled(this); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlLabeledStatement(this, d); } else { System.out.println("A JmlLblExpression expects an JmlTreeVisitor, not a " + v.getClass()); return null; // return super.accept(v,d); } } } /** This class represents JML LBL expressions */ public static class JmlLblExpression extends JmlExpression { /** The kind of label (BSLBLANY, BSLBLPOS, BSLBLNEG) */ public JmlTokenKind token; /** The name given by the label*/ public Name label; /** The expression that is labelled */ public JCExpression expression; public int labelPosition; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlLblExpression(int pos, int labelPosition, JmlTokenKind token, Name label, JCTree.JCExpression expr) { this.pos = pos; this.token = token; this.label = label; this.expression = expr; this.labelPosition = labelPosition; } /*@ pure */ public int getLabelPosition() { return labelPosition; } @Override public Kind getKind() { return Kind.OTHER; // See note above } @Override public Tag getTag() { return null; } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlLblExpression(this); } else { //System.out.println("A JmlLblExpression expects an IJmlVisitor, not a " + v.getClass()); expression.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlLblExpression(this, d); } else { System.out.println("A JmlLblExpression expects an JmlTreeVisitor, not a " + v.getClass()); return null; // return super.accept(v,d); } } } /** This is an abstract class that is a parent to any type of clause in * a method specification (e.g. requires). */ abstract public static class JmlMethodClause extends JmlAbstractStatement implements JmlSource { public JmlTokenKind token; public JavaFileObject sourcefile; // FIXME - don't think this belongs here public JavaFileObject source() { return sourcefile; } } /** This class represents a method specification clause that has an * expression, but also a conditional when it is enabled. (FIXME - examples?) */ public static class JmlMethodClauseConditional extends JmlMethodClause { public JCTree.JCExpression expression; /*@ nullable */ public JCTree.JCExpression predicate; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlMethodClauseConditional(int pos, JmlTokenKind token, JCTree.JCExpression expression, /*@ nullable*/ JCTree.JCExpression predicate) { this.pos = pos; this.token = token; this.expression = expression; this.predicate = predicate; } @Override public Tag getTag() { return null; } @Override public Kind getKind() { return Kind.OTHER; // See note above } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlMethodClauseConditional(this); } else { //System.out.println("A JmlMethodClauseConditional expects an IJmlVisitor, not a " + v.getClass()); super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlMethodClauseConditional(this, d); } else { System.out.println("A JmlMethodClauseCOnditional expects an JmlTreeVisitor, not a " + v.getClass()); return super.accept(v,d); } } } /** This class represents JML function invocations (e.g. \typeof, \old, ...); * note that the method expression may be null if the JML token is present. */ public static class JmlMethodInvocation extends JCMethodInvocation { public int startpos; public JmlTokenKind token; public Label label = null; // FIXME - explain this public boolean javaType = false; // FIXME - this is a hack /** Creates a method invocation for a JML specific construct (e.g. \typeof) - * no type arguments and no expression for the method name, just a token. - but use the factory to get new nodes, not this */ protected JmlMethodInvocation(int pos, JmlTokenKind token, List<JCExpression> args) { super(List.<JCExpression>nil(),null,args); this.token = token; this.pos = pos; // preferred position this.startpos = pos; } /** Creates a method invocation like a Java method invocation, except without type qualifiers */ protected JmlMethodInvocation(int pos, JCExpression method, List<JCExpression> args) { super(List.<JCExpression>nil(),method,args); this.token = null; this.pos = pos; // preferred position this.startpos = pos; } @Override public int getStartPosition() { return meth == null ? startpos : super.getStartPosition(); } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlMethodInvocation(this); } else { //System.out.println("A JmlVariableDecl expects an IJmlVisitor, not a " + v.getClass()); super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlMethodInvocation(this, d); } else { //System.out.println("A JmlVariableDecl expects a JmlTreeVisitor, not a " + v.getClass()); return super.accept(v,d); } } // @Override -- FIXME - do we want this? // public Tag getTag() { // return JMLFUNCTION; // } // } /** This class represents a method specification clause that has just an * expression (e.g. requires, ensures). */ public static class JmlMethodClauseCallable extends JmlMethodClause { public JmlStoreRefKeyword keyword; public List<JmlMethodSig> methodSignatures; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlMethodClauseCallable(int pos, JmlStoreRefKeyword keyword, List<JmlMethodSig> methodSignatures) { this.token = JmlTokenKind.CALLABLE; this.pos = pos; this.keyword = keyword; this.methodSignatures = methodSignatures; } @Override public Tag getTag() { return null; } @Override public Kind getKind() { return Kind.OTHER; // See note above } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlMethodClauseCallable(this); } else { //System.out.println("A JmlMethodClauseExpr expects an IJmlVisitor, not a " + v.getClass()); super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlMethodClauseCallable(this, d); } else { System.out.println("A JmlMethodClauseCallable expects an JmlTreeVisitor, not a " + v.getClass()); return super.accept(v,d); } } } /** This class represents a forall or old method specification clause.*/ public static class JmlMethodClauseDecl extends JmlMethodClause { public List<JCTree.JCVariableDecl> decls; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlMethodClauseDecl(int pos, JmlTokenKind token, List<JCTree.JCVariableDecl> decls) { this.pos = pos; this.token = token; this.decls = decls; } @Override public Tag getTag() { return null; } @Override public Kind getKind() { return Kind.OTHER; // See note above } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlMethodClauseDecl(this); } else { //System.out.println("A JmlMethodClauseDecl expects an IJmlVisitor, not a " + v.getClass()); super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlMethodClauseDecl(this, d); } else { System.out.println("A JmlMethodClauseDecl expects an JmlTreeVisitor, not a " + v.getClass()); return super.accept(v,d); } } } /** This class represents a method specification clause that has just an * expression (e.g. requires, ensures). */ public static class JmlMethodClauseExpr extends JmlMethodClause { public JCTree.JCExpression expression; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlMethodClauseExpr(int pos, JmlTokenKind token, JCTree.JCExpression expression) { this.pos = pos; this.token = token; this.expression = expression; } @Override public Tag getTag() { return null; } @Override public Kind getKind() { return Kind.OTHER; // See note above } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlMethodClauseExpr(this); } else { //System.out.println("A JmlMethodClauseExpr expects an IJmlVisitor, not a " + v.getClass()); super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlMethodClauseExpr(this, d); } else { System.out.println("A JmlMethodClauseExpr expects an JmlTreeVisitor, not a " + v.getClass()); return super.accept(v,d); } } @Override public int getStartPosition() { return pos; } } /** This represents the sequence of method specs lists that are the sequence * of nested specs */ public static class JmlMethodClauseGroup extends JmlMethodClause { public List<JmlSpecificationCase> cases; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlMethodClauseGroup(int pos, List<JmlSpecificationCase> cases) { this.pos = pos; this.token = JmlTokenKind.SPEC_GROUP_START; this.cases = cases; } @Override public Tag getTag() { return null; } @Override public Kind getKind() { return Kind.OTHER; // See note above } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlMethodClauseGroup(this); } else { //System.out.println("A JmlMethodClauseGroup expects an IJmlVisitor, not a " + v.getClass()); super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlMethodClauseGroup(this, d); } else { //System.out.println("A JmlMethodClauseGroup expects an JmlTreeVisitor, not a " + v.getClass()); return super.accept(v,d); } } } /** This class represents a signals clause in a method specification. */ public static class JmlMethodClauseSignals extends JmlMethodClause { public JCTree.JCVariableDecl vardef; public JCTree.JCExpression expression; // NOTE: the ident in the variable declaration may be null /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlMethodClauseSignals(int pos, JmlTokenKind token, JCTree.JCVariableDecl var, JCTree.JCExpression expression) { this.pos = pos; this.token = token; this.vardef = var; this.expression = expression; } @Override public Tag getTag() { return null; } @Override public Kind getKind() { return Kind.OTHER; // See note above } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlMethodClauseSignals(this); } else { //System.out.println("A JmlMethodClauseSignals expects an IJmlVisitor, not a " + v.getClass()); super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlMethodClauseSignals(this, d); } else { System.out.println("A JmlMethodClauseSignals expects an JmlTreeVisitor, not a " + v.getClass()); return super.accept(v,d); } } } /** This class represents a signals_only clause in a method specification */ public static class JmlMethodClauseSignalsOnly extends JmlMethodClause { /** The list of names of exceptions - either JCIdent or JCFieldAccess */ // FIXME - why not Names? public List<JCTree.JCExpression> list; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlMethodClauseSignalsOnly(int pos, JmlTokenKind token, List<JCTree.JCExpression> list) { this.pos = pos; this.token = token; this.list = list; } @Override public Tag getTag() { return null; } @Override public Kind getKind() { return Kind.OTHER; // See note above } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlMethodClauseSigOnly(this); } else { //System.out.println("A JmlMethodClauseSignalsOnly expects an IJmlVisitor, not a " + v.getClass()); super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlMethodClauseSigOnly(this, d); } else { System.out.println("A JmlMethodClauseSignalsOnly expects an JmlTreeVisitor, not a " + v.getClass()); return super.accept(v,d); } } } /** This class represents an assignable clause in a method specification */ public static class JmlMethodClauseStoreRef extends JmlMethodClause { /** The list of store-ref expressions in the clause */ public List<JCExpression> list; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlMethodClauseStoreRef(int pos, JmlTokenKind token, List<JCExpression> list) { this.pos = pos; this.token = token; this.list = list; } @Override public Tag getTag() { return null; } @Override public Kind getKind() { return Kind.OTHER; // See note above } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlMethodClauseStoreRef(this); } else { //System.out.println("A JmlMethodClauseAssignable expects an IJmlVisitor, not a " + v.getClass()); super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlMethodClauseStoreRef(this, d); } else { //System.out.println("A JmlMethodClauseAssignable expects an JmlTreeVisitor, not a " + v.getClass()); return super.accept(v,d); } } } /** This class represents the specifications of a method (a list of * specification cases); it may be the combined set of cases across multiple * compilation units. */ public static class JmlMethodSpecs extends JmlAbstractStatement { /** This is a reference to a parent declaration, in order to have access * to the parameter and result modifiers */ public JmlMethodDecl decl = null; /** The standard specification cases */ public List<JmlSpecificationCase> cases; /** The implies-that specification cases */ public List<JmlSpecificationCase> impliesThatCases; /** The for-example specification cases */ public List<JmlSpecificationCase> forExampleCases; public JmlMethodSpecs deSugared = null; // FIXME - should this be here? // FIXME - should these constructors be public? /** Creates an instance with only regular cases (no impliesThat or example cases)*/ public JmlMethodSpecs(int pos, List<JmlSpecificationCase> cases) { this.pos = pos; this.cases = cases; this.impliesThatCases = List.<JmlSpecificationCase>nil(); this.forExampleCases = List.<JmlSpecificationCase>nil(); } public JmlMethodSpecs() { this.pos = Position.NOPOS; this.cases = List.<JmlSpecificationCase>nil();; this.impliesThatCases = List.<JmlSpecificationCase>nil(); this.forExampleCases = List.<JmlSpecificationCase>nil(); } @Override public Tag getTag() { return null; } @Override public Kind getKind() { return Kind.OTHER; // See note above } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlMethodSpecs(this); } else { //System.out.println("A JmlMethodSpecs expects an IJmlVisitor, not a " + v.getClass()); super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlMethodSpecs(this, d); } else { //System.out.println("A JmlMethodSpecs expects an JmlTreeVisitor, not a " + v.getClass()); return super.accept(v,d); } } } /** This class represents JML statements within the body of a model * program that are not statements themselves, such as * invariants, specification cases */ public static class JmlModelProgramStatement extends JmlAbstractStatement { // FIXME - nthis needs filling out with various kinds of model program statements public JCTree item; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlModelProgramStatement(int pos, JCTree item) { this.pos = pos; this.item = item; } @Override public Tag getTag() { return item.getTag(); } @Override public Kind getKind() { return Kind.OTHER; // See note above } @Override public void accept(Visitor v) { // Simply delegate to the wrapped construct item.accept(v); } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { return item.accept(v,d); } } /** This class represents JML primitive types */ static public class JmlPrimitiveTypeTree extends JCTree.JCPrimitiveTypeTree { public JmlTokenKind token; /** The representation of this JML type when used in RAC */ public JCExpression repType; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlPrimitiveTypeTree(int pos, JmlTokenKind token) { super(TypeTag.NONE); this.pos = pos; this.token = token; } @Override public String toString() { return token != null ? token.internedName() : super.toString(); } @Override public Kind getKind() { return Kind.OTHER; // See note above } @Override public Tag getTag() { return null; } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlPrimitiveTypeTree(this); } else { //System.out.println("A JmlPrimitiveTypeTree expects an IJmlVisitor, not a " + v.getClass()); // super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlPrimitiveTypeTree(this, d); } else { System.out.println("A JmlPrimitiveTypeTree expects an JmlTreeVisitor, not a " + v.getClass()); return null; // return super.accept(v,d); } } @Override public int getStartPosition() { return pos; } } /** This class represents JML quantified expressions */ public static class JmlQuantifiedExpr extends JmlExpression { // Current JML allows multiple bound variables in a quantified expression, // but requires them all to have the same type. However, in anticipation of // relaxing this requirement and for use elsewhere (i.e. in ESC) this // class permits different types. /** The operation, e.g \\forall, \\exists, \\let, ... */ public JmlTokenKind op; /** The declarations over which the expressions are quantified */ public List<JCVariableDecl> decls; /** The predicate restricting the range of iteration */ public JCExpression range; /** The value - e.g. a predicate for forall, a numeric value for sum, etc. */ public JCExpression value; /** A (partial) expression used in RAC, but constructed here for convenience */ public JCExpression racexpr; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlQuantifiedExpr(int pos, JmlTokenKind op, List<JCVariableDecl> decls, JCExpression range, JCExpression value) { this.pos = pos; this.op = op; this.decls = decls; this.range = range; this.value = value; this.racexpr = null; } @Override public Kind getKind() { return Kind.OTHER; // See note above } @Override public Tag getTag() { return null; } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlQuantifiedExpr(this); } else { // FIXME - this does get visited during type entering and annotation // by TypeAnnotate and Attr - should make JML versions of these //System.out.println("A JmlQuantifiedExpr expects an IJmlVisitor, not a " + v.getClass()); // super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlQuantifiedExpr(this, d); } else { System.out.println("A JmlQuantifiedExpr expects an JmlTreeVisitor, not a " + v.getClass()); return null; // return super.accept(v,d); } } } /** This class represents JML expression constructs which do not have arguments (syntactically). */ public static class JmlSingleton extends JmlExpression { /** The kind of singleton expression */ public JmlTokenKind token; /** Used for additional information, such as the comment string of an informal expression */ public Object info = null; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlSingleton(int pos, JmlTokenKind token) { this.pos = pos; this.token = token; } @Override public Kind getKind() { return Kind.OTHER; // See note above } @Override public Tag getTag() { return null; } @Override public String toString() { return token.internedName(); } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlSingleton(this); } else { //System.out.println("A JmlSingleton expects an IJmlVisitor, not a " + v.getClass()); //super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlSingleton(this,d); } else { System.out.println("A JmlSingleton expects a JmlTreeVisitor, not a " + v.getClass()); return null; //return super.accept(v,d); } } } /** This class represents JML set comprehension expressions */ public static class JmlSetComprehension extends JmlExpression { public JCExpression newtype; public JCVariableDecl variable; public JCExpression predicate; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlSetComprehension(int pos, JCExpression type, JCVariableDecl var, JCExpression predicate) { this.pos = pos; this.newtype = type; this.variable = var; this.predicate = predicate; } @Override public Kind getKind() { return Kind.OTHER; // See note above } @Override public Tag getTag() { return null; } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlSetComprehension(this); } else { //System.out.println("A JmlSetComprehension expects an IJmlVisitor, not a " + v.getClass()); // super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlSetComprehension(this, d); } else { System.out.println("A JmlSetComprehension expects an JmlTreeVisitor, not a " + v.getClass()); return null; // return super.accept(v,d); } } } /** This class represents a specification case in a method specification */ public static class JmlSpecificationCase extends JmlAbstractStatement implements JmlSource { public JCModifiers modifiers; public JmlTokenKind token; public JmlTokenKind also; public boolean code; public List<JmlMethodClause> clauses; // A behavior spec case has clauses but no block of statements public JCBlock block; // A model program has a block (of statements) but no clauses public JavaFileObject sourcefile; // FIXME - public constructors - use facctory? public JmlSpecificationCase(int pos, JCModifiers mods, boolean code, JmlTokenKind token, JmlTokenKind also, List<JmlMethodClause> clauses) { this.pos = pos; this.modifiers = mods; this.code = code; this.token = token; this.also = also; this.clauses = clauses; this.block = null; } public JmlSpecificationCase(int pos, JCModifiers mods, boolean code, JmlTokenKind token, JmlTokenKind also, JCBlock block) { this.pos = pos; this.modifiers = mods; this.code = code; this.token = token; this.also = also; this.clauses = null; this.block = block; } public JmlSpecificationCase(JmlSpecificationCase old, List<JmlMethodClause> clauses) { this.pos = old.pos; this.modifiers = old.modifiers; this.code = old.code; this.token = old.token; this.also = old.also; this.sourcefile = old.sourcefile; this.clauses = clauses; } @Override public JavaFileObject source() { return sourcefile; } @Override public Tag getTag() { return null; } @Override public Kind getKind() { return Kind.OTHER; // See note above } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlSpecificationCase(this); } else { //System.out.println("A JmlSpecificationCase expects an IJmlVisitor, not a " + v.getClass()); super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlSpecificationCase(this, d); } else { //System.out.println("A JmlSpecificationCase expects an JmlTreeVisitor, not a " + v.getClass()); return super.accept(v,d); } } } /** This class represents JML statements within the body of a method * that take a statement, such as set and debug */ public static class JmlStatement extends JmlAbstractStatement { public JmlTokenKind token; public JCTree.JCExpressionStatement statement; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlStatement(int pos, JmlTokenKind token, JCTree.JCExpressionStatement statement) { this.pos = pos; this.token = token; this.statement = statement; } @Override public Tag getTag() { return null; } @Override public Kind getKind() { return Kind.OTHER; // See note above } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlStatement(this); } else { //System.out.println("A JmlStatement expects an IJmlVisitor, not a " + v.getClass()); super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlStatement(this, d); } else { //System.out.println("A JmlStatement expects an JmlTreeVisitor, not a " + v.getClass()); return super.accept(v,d); } } } /** This class represents JML ghost declarations and model local class * declarations (FIXME _ local class?) */ public static class JmlStatementDecls extends JmlAbstractStatement { public JmlTokenKind token; public List<JCTree.JCStatement> list; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlStatementDecls(int pos, List<JCTree.JCStatement> list) { this.pos = pos; this.token = JmlTokenKind.GHOST; this.list = list; } @Override public Tag getTag() { return null; } @Override public Kind getKind() { return Kind.OTHER; // See note above } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlStatementDecls(this); } else { //System.out.println("A JmlStatementDecls expects an IJmlVisitor, not a " + v.getClass()); for (JCStatement s: list) s.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlStatementDecls(this, d); } else { System.out.println("A JmlStatementDecls expects an JmlTreeVisitor, not a " + v.getClass()); //for (JCStatement s: list) s.accept(v,d); return super.accept(v,d); } } } /** This class represents JML statements within the body of a method * that take an expression, such as assert, assume, unreachable, reachable */ public static class JmlStatementExpr extends JmlAbstractStatement implements JmlSource { /** The kind of statement - e.g. ASSERT, ASSUME, COMMENT, ... */ public JmlTokenKind token; /** The associated expression (e.g. the asserted condition) */ public JCTree.JCExpression expression; /** An associated optional expression (e.g. such as the one that * can come with a Java assert statement). */ public JCTree.JCExpression optionalExpression = null; /** The source file in which the statement sits (and the file to which pos and line correspond) */ public JavaFileObject source; @Override public JavaFileObject source() { return associatedSource; } /** A Label that gives detail about the kind of assertion or assumption */ public Label label; /** A String just used to distinguish assertions for reporting purposes */ public String id = null; /** A descriptive string for reporting purposes */ public String description = null; /** The file containing the specification (e.g. clause) from which this * assertion or assumption arises; if null then is the same as source. * (source and pos are the location in * the code where the assertion or assumption is being stated.) */ public JavaFileObject associatedSource = null; /** The position within associatedSource */ public int associatedPos; // TODO - change to DiagnosticPosition /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlStatementExpr(int pos, JmlTokenKind token, Label label, JCTree.JCExpression expression) { this.pos = pos; this.token = token; this.expression = expression; this.label = label; this.associatedPos = pos; } @Override public Tag getTag() { return null; } @Override public int getStartPosition() { return expression != null ? expression.getStartPosition() : this.pos; } @Override public int getEndPosition(EndPosTable table) { return optionalExpression != null ? optionalExpression.getEndPosition(table) : expression != null ? expression.getEndPosition(table) : this.pos; } @Override public Kind getKind() { return Kind.OTHER; // See note above } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlStatementExpr(this); } else { //System.out.println("A JmlStatementExpr expects an IJmlVisitor, not a " + v.getClass()); super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlStatementExpr(this, d); } else { //System.out.println("A JmlStatementExpr expects an JmlTreeVisitor, not a " + v.getClass()); return super.accept(v,d); } } } /** This class represents a JML havoc statement, which declares that * the specified variables (store-refs) have unknown values. */ public static class JmlStatementHavoc extends JmlAbstractStatement { /** Should always be HAVOC */ public JmlTokenKind token; /** The store-refs whose values are unknown */ public List<JCTree.JCExpression> storerefs; /** The source file in which the statement sits (and the file to which pos and line correspond) */ public JavaFileObject source; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlStatementHavoc(int pos, List<JCTree.JCExpression> storerefs) { this.pos = pos; this.token = JmlTokenKind.HAVOC; this.storerefs = storerefs; } @Override public Tag getTag() { return null; } @Override public Kind getKind() { return Kind.OTHER; // See note above } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlStatementHavoc(this); } else { //System.out.println("A JmlStatementExpr expects an IJmlVisitor, not a " + v.getClass()); super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlStatementHavoc(this, d); } else { //System.out.println("A JmlStatementHavoc expects an JmlTreeVisitor, not a " + v.getClass()); return super.accept(v,d); } } } /** This is a special kind of assume statement, one that is defining a new variable; * it does not occur in source code, but is created upon transforming declarations and * assignments into assume statements. Some provers are able to deal differently with * declarations/definitions rather than simple logical assumptions. */ // FIXME - not yet used anywhere - use a factory - protected constructor public static class JmlDefinition extends JmlStatementExpr { public JCIdent id; public JCExpression value; public JmlDefinition(int pos, JCIdent id, JCExpression value, JCExpression expr) { super(pos,JmlTokenKind.ASSUME,null,expr); this.id = id; this.value = value; } } /** This class represents JML method specifications within the body of a method * that then apply to the next statement */ public static class JmlStatementSpec extends JmlAbstractStatement { public JmlMethodSpecs statementSpecs; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlStatementSpec(int pos, JmlMethodSpecs statementSpecs) { this.pos = pos; this.statementSpecs = statementSpecs; } @Override public Tag getTag() { return null; } @Override public Kind getKind() { return Kind.OTHER; // See note above } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlStatementSpec(this); } else { //System.out.println("A JmlStatementSpec expects an IJmlVisitor, not a " + v.getClass()); super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlStatementSpec(this, d); } else { //System.out.println("A JmlStatementSpec expects an JmlTreeVisitor, not a " + v.getClass()); return super.accept(v,d); } } } /** This class represents JML statements within the body of a method * that apply to a following loop statement (decreases, loop_invariant) */ public static class JmlStatementLoop extends JmlAbstractStatement { public JmlTokenKind token; public JCTree.JCExpression expression; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlStatementLoop(int pos, JmlTokenKind token, JCTree.JCExpression expression) { this.pos = pos; this.token = token; this.expression = expression; } @Override public Tag getTag() { return null; } @Override public Kind getKind() { return Kind.OTHER; // See note above } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlStatementLoop(this); } else { //System.out.println("A JmlStatementLoop expects an IJmlVisitor, not a " + v.getClass()); super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlStatementLoop(this, d); } else { //System.out.println("A JmlStatementLoop expects an JmlTreeVisitor, not a " + v.getClass()); return super.accept(v,d); } } } /** This node represents a store-ref expression denoting an array range: * a[*] or a[1 .. 2] or a[1 .. ] FIXME - or is that a[1 .. *] * @author David Cok */ public static class JmlStoreRefArrayRange extends JmlExpression { public JCExpression expression; public @Nullable JCExpression lo; public @Nullable JCExpression hi; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlStoreRefArrayRange(int pos, JCExpression expr, @Nullable JCExpression lo, @Nullable JCExpression hi) { this.pos = pos; this.expression = expr; this.lo = lo; this.hi = hi; } @Override public Kind getKind() { return Kind.OTHER; // See note above } @Override public Tag getTag() { return null; } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlStoreRefArrayRange(this); } else { System.out.println("A JmlStoreRefArrayRange expects an IJmlVisitor, not a " + v.getClass()); //super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlStoreRefArrayRange(this, d); } else { System.out.println("A JmlStoreRefArrayRange expects an JmlTreeVisitor, not a " + v.getClass()); return null; //return super.accept(v,d); } } } /** Represents a nothing, everything or informal comment token */ // FIXME - is the content of the informal comment stored somewhere? JmlExpression??? public static class JmlStoreRefKeyword extends JmlExpression { public JmlTokenKind token; // nothing or everything or informal comment /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlStoreRefKeyword(int pos, JmlTokenKind token) { this.pos = pos; this.token = token; } @Override public Kind getKind() { return Kind.OTHER; // See note above } @Override public Tag getTag() { return null; } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlStoreRefKeyword(this); } else { System.out.println("A JmlStoreRefKeyword expects an IJmlVisitor, not a " + v.getClass()); //super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlStoreRefKeyword(this, d); } else { System.out.println("A JmlStoreRefKeyword expects an JmlTreeVisitor, not a " + v.getClass()); return null; //return super.accept(v,d); } } } /** This class represents JML functions that take a list of store-refs as arguments. */ public static class JmlStoreRefListExpression extends JmlExpression { public JmlTokenKind token; public List<JCExpression> list; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlStoreRefListExpression(int pos, JmlTokenKind token, List<JCExpression> list) { this.pos = pos; this.token = token; this.list = list; } @Override public Kind getKind() { return Kind.OTHER; // See note above } @Override public Tag getTag() { return null; } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlStoreRefListExpression(this); } else { //System.out.println("A JmlStoreRefListExpression expects an IJmlVisitor, not a " + v.getClass()); //super.accept(v); for (JCTree t: list) t.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlStoreRefListExpression(this, d); } else { //System.out.println("A JmlStoreRefListExpression expects a JmlTreeVisitor, not a " + v.getClass()); return null; //return super.accept(v,d); } } } /** This class represents type clauses (e.g. invariant, constraint,...) in a class specification */ abstract public static class JmlTypeClause extends JCTree implements JmlSource, IInJML { /** The token identifying the kind of clause this represents */ public JmlTokenKind token; /** The source of this clause, since it might be from a different compilation unit. */ public JavaFileObject source; /** The modifiers for the clause */ public JCModifiers modifiers; /** Returns the source file for the clause */ public JavaFileObject source() { return source; } public boolean isJML() { return true; } /** This implements toString() for all the type clause nodes */ public String toString() { return JmlTree.toString(this); } public int getStartPosition() { return pos; } @Override public Tag getTag() { return Tag.NO_TAG; } } /** This class represents 'represents' type clauses in a class specification */ public static class JmlTypeClauseConstraint extends JmlTypeClause { /** The constraint expression */ public JCTree.JCExpression expression; /** The list of method signatures to which the constraint applies */ public @Nullable List<JmlMethodSig> sigs; /** If true then the list is the method signatures to which the constraint does not apply (a JML extension)*/ public boolean notlist = false; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlTypeClauseConstraint(int pos, JCModifiers mods, JCExpression expression, List<JmlMethodSig> sigs) { this.pos = pos; this.modifiers = mods; this.token = JmlTokenKind.CONSTRAINT; this.expression = expression; this.sigs = sigs; // Method signatures } @Override public Kind getKind() { return Kind.OTHER; // See note above } @Override public Tag getTag() { return null; } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlTypeClauseConstraint(this); } else { //System.out.println("A JmlTypeClauseConstraint expects an IJmlVisitor, not a " + v.getClass()); //super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlTypeClauseConstraint(this, d); } else { System.out.println("A JmlTypeClauseConstraint expects an JmlTreeVisitor, not a " + v.getClass()); return null; //return super.accept(v,d); } } } /** This class represents readable_if and writable_if type clauses */ public static class JmlTypeClauseConditional extends JmlTypeClause { public JCTree.JCIdent identifier; public JCTree.JCExpression expression; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlTypeClauseConditional(int pos, JCModifiers mods, JmlTokenKind token, JCTree.JCIdent ident, JCTree.JCExpression expression) { this.pos = pos; this.modifiers = mods; this.token = token; this.identifier = ident; this.expression = expression; } @Override public Kind getKind() { return Kind.OTHER; // See note above } @Override public Tag getTag() { return null; } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlTypeClauseConditional(this); } else { //System.out.println("A JmlTypeClauseConditional expects an IJmlVisitor, not a " + v.getClass()); //super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlTypeClauseConditional(this, d); } else { System.out.println("A JmlTypeClauseConditional expects an JmlTreeVisitor, not a " + v.getClass()); return null; //return super.accept(v,d); } } } /** This class represents type clauses that are declarations (ghost and model) */ public static class JmlTypeClauseDecl extends JmlTypeClause { public JCTree decl; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlTypeClauseDecl(int pos, JCTree decl) { this.pos = pos; this.token = JmlTokenKind.JMLDECL; this.modifiers = decl instanceof JCVariableDecl ? ((JCVariableDecl)decl).mods : decl instanceof JCMethodDecl ? ((JCMethodDecl)decl).mods : decl instanceof JCClassDecl ? ((JCClassDecl)decl).mods : null; // FIXME - something wrong if this is null this.decl = decl; } @Override public Kind getKind() { return Kind.OTHER; // See note above } // @Override // public Tag getTag() { // return null; // } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlTypeClauseDecl(this); } else { //System.out.println("A JmlTypeClauseDecl expects an IJmlVisitor, not a " + v.getClass()); //decl.accept(v); // FIXME - if this is in then JML decls that are part of the AST get processed when they should not } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlTypeClauseDecl(this, d); } else { //System.out.println("A JmlTypeClauseDecl expects an JmlTreeVisitor, not a " + v.getClass()); return decl.accept(v,d); } } } /** This class represents type clauses (e.g. invariant, axiom, * ...) in a class specification */ public static class JmlTypeClauseExpr extends JmlTypeClause { /** The expression that is part of the clause */ public JCTree.JCExpression expression; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlTypeClauseExpr(int pos, JCModifiers mods, JmlTokenKind token, JCTree.JCExpression expression) { this.pos = pos; this.modifiers = mods; this.token = token; this.expression = expression; } @Override public Kind getKind() { return Kind.OTHER; // See note above } // @Override // public Tag getTag() { // return null; // } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlTypeClauseExpr(this); } else { //System.out.println("A JmlTypeClauseExpr expects an IJmlVisitor, not a " + v.getClass()); //super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlTypeClauseExpr(this, d); } else { System.out.println("A JmlTypeClauseExpr expects an JmlTreeVisitor, not a " + v.getClass()); return null; //return super.accept(v,d); } } public int getStartPosition() { return pos; } } /** This class represents an "in" type clause in a class specification */ public static class JmlTypeClauseIn extends JmlTypeClause { /** The list of names that is the target of the in clause */ public List<JmlGroupName> list; /** The variable declaration that this clause is associated with * (this is a reference to a parent node, not a subtree) */ public JmlVariableDecl parentVar; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlTypeClauseIn(int pos, List<JmlGroupName> list) { this.pos = pos; this.token = JmlTokenKind.IN; this.list = list; this.parentVar = null; } @Override public Kind getKind() { return Kind.OTHER; // See note above } // @Override // public Tag getTag() { // return null; // } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlTypeClauseIn(this); } else { //System.out.println("A JmlTypeClauseIn expects an IJmlVisitor, not a " + v.getClass()); //super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlTypeClauseIn(this, d); } else { System.out.println("A JmlTypeClauseIn expects an JmlTreeVisitor, not a " + v.getClass()); return null; //return super.accept(v,d); } } } /** This class represents initializer and static_initializer clauses in a class specification */ public static class JmlTypeClauseInitializer extends JmlTypeClause { /** The specifications that go with a JML initializer declaration */ public JmlMethodSpecs specs; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlTypeClauseInitializer(int pos, JmlTokenKind token, JCModifiers mods) { this.pos = pos; this.token = token; this.source = null; this.modifiers = mods; } @Override public Kind getKind() { return Kind.OTHER; // See note above } // @Override // public Tag getTag() { // return null; // } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlTypeClauseInitializer(this); } else { //System.out.println("A JmlTypeClauseInitializer expects an IJmlVisitor, not a " + v.getClass()); //super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlTypeClauseInitializer(this, d); } else { System.out.println("A JmlTypeClauseInitializer expects an JmlTreeVisitor, not a " + v.getClass()); return null; //return super.accept(v,d); } } } /** This class represents type clauses (e.g. invariant, constraint,...) in a class specification */ public static class JmlTypeClauseMaps extends JmlTypeClause { /** The maps store-ref expression */ public JCExpression expression; /** The list of datagroup targets */ public List<JmlGroupName> list; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlTypeClauseMaps(int pos, JCExpression e, List<JmlGroupName> list) { this.pos = pos; this.expression = e; this.modifiers = null; this.token = JmlTokenKind.MAPS; this.list = list; } @Override public Kind getKind() { return Kind.OTHER; // See note above } // @Override // public Tag getTag() { // return null; // } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlTypeClauseMaps(this); } else { //System.out.println("A JmlTypeClauseMaps expects an IJmlVisitor, not a " + v.getClass()); //super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlTypeClauseMaps(this, d); } else { System.out.println("A JmlTypeClauseMaps expects an JmlTreeVisitor, not a " + v.getClass()); return null; //return super.accept(v,d); } } } /** This class represents monitors_for type clauses */ public static class JmlTypeClauseMonitorsFor extends JmlTypeClause { public JCTree.JCIdent identifier; public List<JCTree.JCExpression> list; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlTypeClauseMonitorsFor(int pos, JCModifiers mods, JCIdent ident, List<JCTree.JCExpression> list) { this.pos = pos; this.modifiers = mods; this.identifier = ident; this.token = JmlTokenKind.MONITORS_FOR; this.list = list; } @Override public Kind getKind() { return Kind.OTHER; // See note above } // @Override // public Tag getTag() { // return null; // } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlTypeClauseMonitorsFor(this); } else { //System.out.println("A JmlTypeClauseMonitorsFor expects an IJmlVisitor, not a " + v.getClass()); //super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlTypeClauseMonitorsFor(this, d); } else { System.out.println("A JmlTypeClauseMonitorsFor expects an JmlTreeVisitor, not a " + v.getClass()); return null; //return super.accept(v,d); } } } /** This class represents 'represents' type clauses in a class specification */ public static class JmlTypeClauseRepresents extends JmlTypeClause { /** The identifier or store-ref expression that is the target of the represents clause */ public JCTree.JCExpression ident; // a store-ref expression // FIXME - doesn't this need to be a simple name? /** true if this is a such-that rather than an equality represents clause */ public boolean suchThat; /** The representing expression or boolean predicate */ public JCTree.JCExpression expression; /** The constructor for the AST node - but use the factory to get new nodes, not this */ protected JmlTypeClauseRepresents(int pos, JCModifiers mods, JCTree.JCExpression ident, boolean suchThat, JCTree.JCExpression expression) { this.pos = pos; this.modifiers = mods; this.token = JmlTokenKind.REPRESENTS; this.ident = ident; this.expression = expression; this.suchThat = suchThat; } @Override public Kind getKind() { return Kind.OTHER; // See note above } // @Override // public Tag getTag() { // return null; // } @Override public void accept(Visitor v) { if (v instanceof IJmlVisitor) { ((IJmlVisitor)v).visitJmlTypeClauseRepresents(this); } else { //System.out.println("A JmlTypeClauseRepresents expects an IJmlVisitor, not a " + v.getClass()); //super.accept(v); } } @Override public <R,D> R accept(TreeVisitor<R,D> v, D d) { if (v instanceof JmlTreeVisitor) { return ((JmlTreeVisitor<R,D>)v).visitJmlTypeClauseRepresents(this, d); } else { System.out.println("A JmlTypeClauseRepresents expects an JmlTreeVisitor, not a " + v.getClass()); return null; //return super.accept(v,d); } } } // FIXME - the following do not have factory methods - do not set pos, do not have accept, getKind, getTag, toString methods, or documentation public static class JmlBBArrayAssignment extends JCMethodInvocation { public JmlBBArrayAssignment(JCIdent newarrs, JCIdent oldarrs, JCExpression arr, JCExpression index, JCExpression rhs) { super(null,null,null); ListBuffer<JCExpression> list = new ListBuffer<JCExpression>(); list.append(newarrs); list.append(oldarrs); list.append(arr); if (index != null) list.append(index); if (rhs != null) list.append(rhs); args = list.toList(); } @Override public int getStartPosition() { return args.get(0).getStartPosition(); // newarrs } @Override public int getEndPosition(EndPosTable table) { return args.get(args.length()-1).getEndPosition(table); // rhs } } public static class JmlBBArrayHavoc extends JCMethodInvocation { public JmlBBArrayHavoc(JCIdent newarrs, JCIdent oldarrs, JCExpression arr, JCExpression indexlo, JCExpression indexhi, JCExpression precondition, boolean above) { super(null,null,null); ListBuffer<JCExpression> list = new ListBuffer<JCExpression>(); list.append(newarrs); list.append(oldarrs); list.append(arr); list.append(indexlo); list.append(indexhi); list.append(precondition); this.above = above; args = list.toList(); } public boolean above; } public static class JmlBBFieldAssignment extends JCMethodInvocation { public JmlBBFieldAssignment(JCIdent newfield, JCIdent oldfield, JCExpression selected, JCExpression rhs) { super(null,null,null); ListBuffer<JCExpression> list = new ListBuffer<JCExpression>(); list.append(newfield); list.append(oldfield); list.append(selected); list.append(rhs); args = list.toList(); } @Override public int getStartPosition() { return args.get(0).getStartPosition(); // newfield } @Override public int getEndPosition(EndPosTable table) { return args.get(3).getEndPosition(table); // rhs } } public static class JmlBBArrayAccess extends JCArrayAccess { public JCIdent arraysId; public JmlBBArrayAccess(JCIdent arraysId, JCExpression arr, JCExpression index) { super(arr,index); this.arraysId = arraysId; } public JmlBBArrayAccess(JCIdent arraysId, JCExpression arr, JCExpression index, int pos, Type type) { super(arr,index); this.arraysId = arraysId; this.pos = pos; this.type = type; } } public static class JmlBBFieldAccess extends JCFieldAccess { public JCIdent arraysId; public JCIdent fieldId; public JmlBBFieldAccess(JCIdent fieldId, JCExpression selected) { super(selected,fieldId.name,fieldId.sym); this.fieldId = fieldId; this.type = fieldId.type; } } public static class JmlAnnotation extends JCAnnotation { public JmlAnnotation(Tag tag, JCTree annotationType, List<JCExpression> args) { super(tag,annotationType,args); } /** The origin of the annotation, which may not be the same as the item being annotated; * if null, the annotation is inserted to make a default explicit. */ @Nullable public JavaFileObject sourcefile; } }