/* * Copyright 2016 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.turbine.tree; import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.turbine.diag.SourceFile; import com.google.turbine.model.Const; import com.google.turbine.model.TurbineConstantTypeKind; import com.google.turbine.model.TurbineTyKind; import java.util.Set; /** An AST node. */ public abstract class Tree { public abstract Kind kind(); public abstract O accept(Visitor visitor, I input); private final int position; protected Tree(int position) { this.position = position; } public int position() { return position; } @Override public String toString() { return Pretty.pretty(this); } /** Tree kind. */ public enum Kind { WILD_TY, ARR_TY, PRIM_TY, VOID_TY, CLASS_TY, LITERAL, TYPE_CAST, UNARY, BINARY, CONST_VAR_NAME, CLASS_LITERAL, ASSIGN, CONDITIONAL, ARRAY_INIT, COMP_UNIT, IMPORT_DECL, VAR_DECL, METH_DECL, ANNO, ANNO_EXPR, TY_DECL, TY_PARAM, PKG_DECL } /** A type use. */ public abstract static class Type extends Tree { private final ImmutableList annos; public Type(int position, ImmutableList annos) { super(position); this.annos = annos; } public ImmutableList annos() { return annos; } } /** An expression. */ public abstract static class Expression extends Tree { public Expression(int position) { super(position); } } /** A wildcard type, possibly with an upper or lower bound. */ public static class WildTy extends Type { private final Optional upper; private final Optional lower; public WildTy( int position, ImmutableList annos, Optional upper, Optional lower) { super(position, annos); this.upper = upper; this.lower = lower; } @Override public Kind kind() { return Kind.WILD_TY; } @Override public O accept(Visitor visitor, I input) { return visitor.visitWildTy(this, input); } /** * An optional upper (extends) bound. * *

At most one of {@link #upper} and {@link #lower} will be set. */ public Optional upper() { return upper; } /** * An optional lower (super) bound. * *

At most one of {@link #upper} and {@link #lower} will be set. */ public Optional lower() { return lower; } } /** An array type. */ public static class ArrTy extends Type { private final Type elem; public ArrTy(int position, ImmutableList annos, Type elem) { super(position, annos); this.elem = elem; } @Override public Kind kind() { return Kind.ARR_TY; } @Override public O accept(Visitor visitor, I input) { return visitor.visitArrTy(this, input); } /** * The element type of the array. * *

Multi-dimensional arrays are represented as nested {@link ArrTy}s. */ public Type elem() { return elem; } } /** A primitive type. */ public static class PrimTy extends Type { private final TurbineConstantTypeKind tykind; public PrimTy(int position, ImmutableList annos, TurbineConstantTypeKind tykind) { super(position, annos); this.tykind = tykind; } @Override public Kind kind() { return Kind.PRIM_TY; } @Override public O accept(Visitor visitor, I input) { return visitor.visitPrimTy(this, input); } /** The primtiive type. */ public TurbineConstantTypeKind tykind() { return tykind; } } /** The void type, used only for void-returning methods. */ public static class VoidTy extends Type { @Override public Kind kind() { return Kind.VOID_TY; } @Override public O accept(Visitor visitor, I input) { return visitor.visitVoidTy(this, input); } public VoidTy(int position) { super(position, ImmutableList.of()); } } /** A class, enum, interface, or annotation {@link Type}. */ public static class ClassTy extends Type { private final Optional base; private final String name; private final ImmutableList tyargs; public ClassTy( int position, Optional base, String name, ImmutableList tyargs, ImmutableList annos) { super(position, annos); this.base = base; this.name = name; this.tyargs = tyargs; } @Override public Kind kind() { return Kind.CLASS_TY; } @Override public O accept(Visitor visitor, I input) { return visitor.visitClassTy(this, input); } /** * The base type, for qualified type uses. * *

For example, {@code Map.Entry}. */ public Optional base() { return base; } /** The simple name of the type. */ public String name() { return name; } /** A possibly empty list of type arguments. */ public ImmutableList tyargs() { return tyargs; } } /** A JLS 3.10 literal expression. */ public static class Literal extends Expression { private final TurbineConstantTypeKind tykind; private final Const value; public Literal(int position, TurbineConstantTypeKind tykind, Const value) { super(position); this.tykind = tykind; this.value = value; } @Override public Kind kind() { return Kind.LITERAL; } @Override public O accept(Visitor visitor, I input) { return visitor.visitLiteral(this, input); } public TurbineConstantTypeKind tykind() { return tykind; } public Const value() { return value; } } /** A JLS 15.16 cast expression. */ public static class TypeCast extends Expression { private final Type ty; private final Expression expr; public TypeCast(int position, Type ty, Expression expr) { super(position); this.ty = ty; this.expr = expr; } @Override public Kind kind() { return Kind.TYPE_CAST; } @Override public O accept(Visitor visitor, I input) { return visitor.visitTypeCast(this, input); } public Type ty() { return ty; } public Expression expr() { return expr; } } /** A JLS 15.14 - 14.15 unary expression. */ public static class Unary extends Expression { private final Expression expr; private final TurbineOperatorKind op; public Unary(int position, Expression expr, TurbineOperatorKind op) { super(position); this.expr = expr; this.op = op; } @Override public Kind kind() { return Kind.UNARY; } @Override public O accept(Visitor visitor, I input) { return visitor.visitUnary(this, input); } public Expression expr() { return expr; } public TurbineOperatorKind op() { return op; } } /** A JLS 15.17 - 14.24 binary expression. */ public static class Binary extends Expression { private final Expression lhs; private final Expression rhs; private final TurbineOperatorKind op; public Binary(int position, Expression lhs, Expression rhs, TurbineOperatorKind op) { super(position); this.lhs = lhs; this.rhs = rhs; this.op = op; } @Override public Kind kind() { return Kind.BINARY; } @Override public O accept(Visitor visitor, I input) { return visitor.visitBinary(this, input); } public Expression lhs() { return lhs; } public Expression rhs() { return rhs; } public TurbineOperatorKind op() { return op; } } /** A JLS 6.5.6.1 simple name that refers to a JSL 4.12.4 constant variable. */ public static class ConstVarName extends Expression { private final ImmutableList name; public ConstVarName(int position, ImmutableList name) { super(position); this.name = name; } @Override public Kind kind() { return Kind.CONST_VAR_NAME; } @Override public O accept(Visitor visitor, I input) { return visitor.visitConstVarName(this, input); } public ImmutableList name() { return name; } } /** A JLS 15.8.2 class literal. */ public static class ClassLiteral extends Expression { private final Type type; public ClassLiteral(int position, Type type) { super(position); this.type = type; } @Override public Kind kind() { return Kind.CLASS_LITERAL; } @Override public O accept(Visitor visitor, I input) { return visitor.visitClassLiteral(this, input); } public Type type() { return type; } } /** A JLS 15.26 assignment expression. */ public static class Assign extends Expression { private final String name; private final Expression expr; public Assign(int position, String name, Expression expr) { super(position); this.name = name; this.expr = expr; } @Override public Kind kind() { return Kind.ASSIGN; } @Override public O accept(Visitor visitor, I input) { return visitor.visitAssign(this, input); } public String name() { return name; } public Expression expr() { return expr; } } /** A JLS 15.25 conditional expression. */ public static class Conditional extends Expression { private final Expression cond; private final Expression iftrue; private final Expression iffalse; public Conditional(int position, Expression cond, Expression iftrue, Expression iffalse) { super(position); this.cond = cond; this.iftrue = iftrue; this.iffalse = iffalse; } @Override public Kind kind() { return Kind.CONDITIONAL; } @Override public O accept(Visitor visitor, I input) { return visitor.visitConditional(this, input); } public Expression cond() { return cond; } public Expression iftrue() { return iftrue; } public Expression iffalse() { return iffalse; } } /** JLS 10.6 array initializer. */ public static class ArrayInit extends Expression { private final ImmutableList exprs; public ArrayInit(int position, ImmutableList exprs) { super(position); this.exprs = exprs; } @Override public Kind kind() { return Kind.ARRAY_INIT; } @Override public O accept(Visitor visitor, I input) { return visitor.visitArrayInit(this, input); } public ImmutableList exprs() { return exprs; } } /** A JLS 7.3 compilation unit. */ public static class CompUnit extends Tree { private final Optional pkg; private final ImmutableList imports; private final ImmutableList decls; private final SourceFile source; public CompUnit( int position, Optional pkg, ImmutableList imports, ImmutableList decls, SourceFile source) { super(position); this.pkg = pkg; this.imports = imports; this.decls = decls; this.source = source; } @Override public Kind kind() { return Kind.COMP_UNIT; } @Override public O accept(Visitor visitor, I input) { return visitor.visitCompUnit(this, input); } public Optional pkg() { return pkg; } public ImmutableList imports() { return imports; } public ImmutableList decls() { return decls; } public SourceFile source() { return source; } } /** A JLS 7.5 import declaration. */ public static class ImportDecl extends Tree { private final ImmutableList type; private final boolean stat; private final boolean wild; public ImportDecl(int position, ImmutableList type, boolean stat, boolean wild) { super(position); this.type = type; this.stat = stat; this.wild = wild; } @Override public Kind kind() { return Kind.IMPORT_DECL; } @Override public O accept(Visitor visitor, I input) { return visitor.visitImportDecl(this, input); } public ImmutableList type() { return type; } /** Returns true for static member imports. */ public boolean stat() { return stat; } /** Returns true for wildcard imports. */ public boolean wild() { return wild; } } /** A JLS 8.3 field declaration, JLS 8.4.1 formal method parameter, or JLS 14.4 variable. */ public static class VarDecl extends Tree { private final ImmutableSet mods; private final ImmutableList annos; private final Tree ty; private final String name; private final Optional init; public VarDecl( int position, Set mods, ImmutableList annos, Tree ty, String name, Optional init) { super(position); this.mods = ImmutableSet.copyOf(mods); this.annos = annos; this.ty = ty; this.name = name; this.init = init; } @Override public Kind kind() { return Kind.VAR_DECL; } @Override public O accept(Visitor visitor, I input) { return visitor.visitVarDecl(this, input); } public ImmutableSet mods() { return mods; } public ImmutableList annos() { return annos; } public Tree ty() { return ty; } public String name() { return name; } public Optional init() { return init; } } /** A JLS 8.4 method declaration. */ public static class MethDecl extends Tree { private final ImmutableSet mods; private final ImmutableList annos; private final ImmutableList typarams; private final Optional ret; private final String name; private final ImmutableList params; private final ImmutableList exntys; private final Optional defaultValue; public MethDecl( int position, Set mods, ImmutableList annos, ImmutableList typarams, Optional ret, String name, ImmutableList params, ImmutableList exntys, Optional defaultValue) { super(position); this.mods = ImmutableSet.copyOf(mods); this.annos = annos; this.typarams = typarams; this.ret = ret; this.name = name; this.params = params; this.exntys = exntys; this.defaultValue = defaultValue; } @Override public Kind kind() { return Kind.METH_DECL; } @Override public O accept(Visitor visitor, I input) { return visitor.visitMethDecl(this, input); } public ImmutableSet mods() { return mods; } public ImmutableList annos() { return annos; } public ImmutableList typarams() { return typarams; } public Optional ret() { return ret; } public String name() { return name; } public ImmutableList params() { return params; } public ImmutableList exntys() { return exntys; } public Optional defaultValue() { return defaultValue; } } /** A JLS 9.7 annotation. */ public static class Anno extends Tree { private final ImmutableList name; private final ImmutableList args; public Anno(int position, ImmutableList name, ImmutableList args) { super(position); this.name = name; this.args = args; } @Override public Kind kind() { return Kind.ANNO; } @Override public O accept(Visitor visitor, I input) { return visitor.visitAnno(this, input); } public ImmutableList name() { return name; } public ImmutableList args() { return args; } } /** * An annotation in an expression context, e.g. an annotation literal nested inside another * annotation. */ public static class AnnoExpr extends Expression { private final Anno value; public AnnoExpr(int position, Anno value) { super(position); this.value = value; } /** The annotation. */ public Anno value() { return value; } @Override public Kind kind() { return Kind.ANNO_EXPR; } @Override public O accept(Visitor visitor, I input) { return visitor.visitAnno(value, input); } } /** A JLS 7.6 or 8.5 type declaration. */ public static class TyDecl extends Tree { private final ImmutableSet mods; private final ImmutableList annos; private final String name; private final ImmutableList typarams; private final Optional xtnds; private final ImmutableList impls; private final ImmutableList members; private final TurbineTyKind tykind; public TyDecl( int position, Set mods, ImmutableList annos, String name, ImmutableList typarams, Optional xtnds, ImmutableList impls, ImmutableList members, TurbineTyKind tykind) { super(position); this.mods = ImmutableSet.copyOf(mods); this.annos = annos; this.name = name; this.typarams = typarams; this.xtnds = xtnds; this.impls = impls; this.members = members; this.tykind = tykind; } @Override public Kind kind() { return Kind.TY_DECL; } @Override public O accept(Visitor visitor, I input) { return visitor.visitTyDecl(this, input); } public ImmutableSet mods() { return mods; } public ImmutableList annos() { return annos; } public String name() { return name; } public ImmutableList typarams() { return typarams; } public Optional xtnds() { return xtnds; } public ImmutableList impls() { return impls; } public ImmutableList members() { return members; } public TurbineTyKind tykind() { return tykind; } } /** A JLS 4.4. type variable declaration. */ public static class TyParam extends Tree { private final String name; private final ImmutableList bounds; private final ImmutableList annos; public TyParam( int position, String name, ImmutableList bounds, ImmutableList annos) { super(position); this.name = name; this.bounds = bounds; this.annos = annos; } @Override public Kind kind() { return Kind.TY_PARAM; } @Override public O accept(Visitor visitor, I input) { return visitor.visitTyParam(this, input); } public String name() { return name; } public ImmutableList bounds() { return bounds; } public ImmutableList annos() { return annos; } } /** A JLS 7.4 package declaration. */ public static class PkgDecl extends Tree { private final ImmutableList name; private final ImmutableList annos; public PkgDecl(int position, ImmutableList name, ImmutableList annos) { super(position); this.name = name; this.annos = annos; } @Override public Kind kind() { return Kind.PKG_DECL; } @Override public O accept(Visitor visitor, I input) { return visitor.visitPkgDecl(this, input); } public ImmutableList name() { return name; } public ImmutableList annos() { return annos; } } /** A visitor for {@link Tree}s. */ public interface Visitor { O visitWildTy(WildTy visitor, I input); O visitArrTy(ArrTy arrTy, I input); O visitPrimTy(PrimTy primTy, I input); O visitVoidTy(VoidTy primTy, I input); O visitClassTy(ClassTy visitor, I input); O visitLiteral(Literal literal, I input); O visitTypeCast(TypeCast typeCast, I input); O visitUnary(Unary unary, I input); O visitBinary(Binary binary, I input); O visitConstVarName(ConstVarName constVarName, I input); O visitClassLiteral(ClassLiteral classLiteral, I input); O visitAssign(Assign assign, I input); O visitConditional(Conditional conditional, I input); O visitArrayInit(ArrayInit arrayInit, I input); O visitCompUnit(CompUnit compUnit, I input); O visitImportDecl(ImportDecl importDecl, I input); O visitVarDecl(VarDecl varDecl, I input); O visitMethDecl(MethDecl methDecl, I input); O visitAnno(Anno anno, I input); O visitTyDecl(TyDecl tyDecl, I input); O visitTyParam(TyParam tyParam, I input); O visitPkgDecl(PkgDecl pkgDecl, I input); } }