/*
* This file is part of the X10 project (http://x10-lang.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* (C) Copyright IBM Corporation 2006-2010.
*/
package x10.util;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import polyglot.ast.Assign;
import polyglot.ast.Binary;
import polyglot.ast.Block;
import polyglot.ast.Call;
import polyglot.ast.CanonicalTypeNode;
import polyglot.ast.ClassBody;
import polyglot.ast.ClassMember;
import polyglot.ast.Expr;
import polyglot.ast.Field;
import polyglot.ast.FieldAssign;
import polyglot.ast.FieldDecl;
import polyglot.ast.FlagsNode;
import polyglot.ast.FloatLit;
import polyglot.ast.For;
import polyglot.ast.ForInit;
import polyglot.ast.ForUpdate;
import polyglot.ast.Formal;
import polyglot.ast.Id;
import polyglot.ast.IntLit;
import polyglot.ast.Local;
import polyglot.ast.LocalDecl;
import polyglot.ast.MethodDecl;
import polyglot.ast.New;
import polyglot.ast.NodeFactory;
import polyglot.ast.Receiver;
import polyglot.ast.Special;
import polyglot.ast.Stmt;
import polyglot.ast.TypeNode;
import polyglot.ast.Typed;
import polyglot.ast.Unary;
import polyglot.frontend.Globals;
import polyglot.types.ClassDef;
import polyglot.types.ClassType;
import polyglot.types.ConstructorDef;
import polyglot.types.ConstructorInstance;
import polyglot.types.Def;
import polyglot.types.FieldDef;
import polyglot.types.FieldInstance;
import polyglot.types.Flags;
import polyglot.types.LocalDef;
import polyglot.types.LocalInstance;
import polyglot.types.MethodDef;
import polyglot.types.Name;
import polyglot.types.QName;
import polyglot.types.Ref;
import polyglot.types.SemanticException;
import polyglot.types.Type;
import polyglot.types.Types;
import polyglot.types.VarDef;
import polyglot.util.CollectionUtil; import x10.util.CollectionFactory;
import polyglot.util.InternalCompilerError;
import polyglot.util.Pair;
import polyglot.util.Position;
import polyglot.visit.ContextVisitor;
import polyglot.visit.TypeBuilder;
import polyglot.visit.TypeChecker;
import x10.ast.*;
import x10.constraint.XDisEquals;
import x10.constraint.XEQV;
import x10.constraint.XEquals;
import x10.constraint.XFailure;
import x10.constraint.XField;
import x10.constraint.XFormula;
import x10.constraint.XLit;
import x10.constraint.XLocal;
import x10.constraint.XNot;
import x10.constraint.XTerm;
import x10.types.constraints.ConstraintManager;
import x10.constraint.XUQV;
import x10.constraint.XVar;
import x10.extension.X10Del;
import x10.types.FunctionType;
import x10.types.ParameterType;
import x10.types.X10ClassDef;
import x10.types.X10ClassType;
import polyglot.types.Context;
import x10.types.X10Def;
import x10.types.X10FieldInstance;
import x10.types.X10MethodDef;
import x10.types.MethodInstance;
import polyglot.types.TypeSystem;
import x10.types.X10LocalDef;
import x10.types.X10FieldDef;
import x10.types.checker.PlaceChecker;
import x10.types.constraints.CConstraint;
import x10.types.constraints.CField;
import x10.types.constraints.CLit;
import x10.types.constraints.CLocal;
import x10.types.constraints.CQualifiedVar;
import x10.types.constraints.CSelf;
import x10.types.constraints.CThis;
import x10.visit.X10TypeBuilder;
import x10.visit.X10TypeChecker;
import x10.types.constants.StringValue;
/**
* A utility to help synthesize fragments of ASTs. Most of the methods on this class are intended to
* be used after an AST has been type-checked. These methods construct and add type-checked
* AST nodes.
* @author vj
*
*/
public class Synthesizer {
TypeSystem xts;
NodeFactory xnf;
public Synthesizer(NodeFactory nf, TypeSystem ts) {
xts = ts;
xnf = nf;
}
/**
* Create a synthetic MethodDecl from the given data and return
* a new Class with this MethodDecl added in. No duplicate method
* checks will be performed. It is up to the user to make sure
* the constructed method will not duplicate an existing method.
*
* Should be called after the class has been typechecked.
* @param ct -- The class to which this code has to be added
* @param flags -- The flags for the method
* @param typeParameters -- The type parameters of the method.
* @param name -- The name of the method
* @param fmls -- A list of LocalDefs specifying the parameters to the method.
* @param returnType -- The return type of this method.
* @param block -- The body of the method
* @return this, with the method added.
*
* TODO: Ensure that a guard can be supplied as well.
*/
public X10ClassDecl_c addSyntheticMethod(X10ClassDecl_c ct, Flags flags, List<ParameterType> typeParameters,
Name name, List<LocalDef> fmls, List<Type> throws_, Type returnType, Block block)
{
assert ct.classDef() != null;
MethodDecl result = makeSyntheticMethod(ct, flags, typeParameters,name, fmls, throws_, returnType, block);
ClassBody b = ct.body();
b = b.addMember(result);
ct.classDef().addMethod(result.methodDef());
return (X10ClassDecl_c) ct.body(b);
}
/**
* Create a synthetic MethodDecl from the given data and return
* the MethodDecl
* Should be called after the class has been type-checked.
*
* @param ct -- The class to which this code has to be added
* @param flags -- The flags for the method
* @param typeParameters -- The type parameters of the method.
* @param name -- The name of the method
* @param fmls -- A list of LocalDefs specifying the parameters to the method.
* @param returnType -- The return type of this method.
* @param block -- The body of the method
* @return the newly constructed method.
*
* TODO: Ensure that a guard can be supplied as well.
*/
public MethodDecl makeSyntheticMethod(X10ClassDecl_c ct, Flags flags, List<ParameterType> typeParameters,
Name name, List<LocalDef> fmls, List<Type> throws_, Type returnType, Block block)
{
Position CG = Position.compilerGenerated(ct.body().position());
List<TypeParamNode> typeParamNodes = new ArrayList<TypeParamNode>();
for (ParameterType pt : typeParameters) {
typeParamNodes.add(xnf.TypeParamNode(CG, xnf.Id(CG, pt.name())).type(pt));
}
List<Ref<? extends Type>> argTypes = new ArrayList<Ref<? extends Type>>();
List<Formal> formals = new ArrayList<Formal>(fmls.size());
List<LocalDef> formalNames = new ArrayList<LocalDef>(fmls.size());
for (LocalDef f : fmls) {
Id id = xnf.Id(CG, f.name());
Formal ff = xnf.Formal(CG,xnf.FlagsNode(CG, Flags.NONE),
xnf.CanonicalTypeNode(CG, f.type()), id);
LocalDef li = xts.localDef(CG, ff.flags().flags(), ff.type().typeRef(), id.id());
ff = ff.localDef(li);
formals.add(ff);
formalNames.add(li);
argTypes.add(li.type());
}
FlagsNode newFlags = xnf.FlagsNode(CG, flags);
TypeNode rt = xnf.CanonicalTypeNode(CG, returnType);
List<Ref<? extends Type>> throwTypes = new ArrayList<Ref<? extends Type>>();
for (Type t: throws_) {
Ref<Type> tref = Types.ref(t);
throwTypes.add(tref);
}
// Create the method declaration node and the CI.
MethodDecl result =
xnf.X10MethodDecl(CG, newFlags, rt, xnf.Id(CG,name), typeParamNodes, formals, null, null, Collections.<TypeNode>emptyList(), block);
MethodDef rmi = xts.methodDef(CG, CG, Types.ref(ct.classDef().asType()),
newFlags.flags(), rt.typeRef(), name, typeParameters, argTypes, throwTypes, ct.classDef().thisDef(), formalNames, null, null, null, null);
result = result.methodDef(rmi);
return result;
}
public static XTerm makeProperty(Type type, XVar receiver, String name) {
X10FieldInstance fi = Types.getProperty(type, Name.make(name));
if (fi == null)
return null;
return ConstraintManager.getConstraintSystem().makeField(receiver, fi.def());
}
public XTerm makePointRankTerm(XVar receiver) {
return makeProperty(xts.Point(), receiver, "rank");
}
public XTerm makeRegionRankTerm(XVar receiver) {
return makeProperty(xts.Region(), receiver, "rank");
}
public XTerm makeRectTerm(XVar receiver) {
return makeProperty(xts.Region(), receiver, "rect");
}
public Type addRectConstraint(Type type, XVar receiver) {
XTerm v = makeRectTerm(receiver);
return Types.addTerm(type, v);
}
public Type addRectConstraintToSelf(Type type) {
XVar receiver = Types.self(type);
if (receiver == null) {
CConstraint c = ConstraintManager.getConstraintSystem().makeCConstraint();
type = Types.xclause(type, c);
receiver = c.self();
}
XTerm v = makeRectTerm(receiver);
return Types.addTerm(type, v);
}
/*
public Type addRankConstraint(Type type, XVar receiver, int n, X10TypeSystem ts) {
XTerm v = makeRegionRankTerm(receiver);
XTerm rank = XTerms.makeLit(new Integer(n));
return X10TypeMixin.addBinding(type, v, rank);
}
public Type addRankConstraintToSelf(Type type, int n, X10TypeSystem ts) {
XVar receiver = X10TypeMixin.self(type);
if (receiver == null) {
CConstraint c = ConstraintManager.getConstraintSystem().makeCConstraint();
type = X10TypeMixin.xclause(type, c);
receiver = c.self();
}
XTerm v = makeRegionRankTerm(receiver);
XTerm rank = XTerms.makeLit(new Integer(n));
return X10TypeMixin.addBinding(type, v, rank);
}
*/
/**
* If formal = p(x) construct
* for|foreach|ateach ( var _gen = low; _gen <= high; _gen++) {
* val x = _gen;
* val p = [x] as Point;
* stm
* }
* If formal = (x) construct
* for|foreach|ateach (var _gen = low; _gen <= high; _gen ++) {
* val x = _gen;
* stm
* }
* If formal is null construct:
* for|foreach|ateach (var _gen = low; _gen <= high; _gen ++) {
* stm
* }
* @param pos
* @param kind
* @param formal
* @param low
* @param high
* @param stm
* @return
*/
public For makeForLoop(Position pos,
X10Formal formal, Expr low, Expr high, Stmt body,
Context context) {
Position CG = Position.compilerGenerated(pos);
List<Stmt> inits = new ArrayList<Stmt>();
// FIXME: use formal here directly, instead of local
Expr local = makeLocalVar(CG, null, low, inits, context);
Expr limit = makeLocalVar(CG, null, high, inits, context);
Expr test = xnf.Binary(CG, local, Binary.LE, limit).type(xts.Boolean());
Expr iters = xnf.Unary(CG, local, Unary.POST_INC).type(xts.Int());
Stmt formalInit = makeLocalVar(CG, formal.localDef(), local);
Block block = xnf.Block(CG, formalInit,body);
List<ForInit> inits2 = new ArrayList<ForInit>();
for (int i = 0; i < inits.size(); i++)
inits2.add((ForInit) inits.get(i));
List<ForUpdate> itersL = new ArrayList<ForUpdate>();
itersL.add(xnf.Eval(CG, iters));
For node = xnf.For(pos, inits2, test, itersL, block);
return node;
}
/**
* Create a new local variable declaration from the given LocalDef. The user is responsible
* for ensuring that the variable is not going to be defined elsewhere in the context.
* @param pos
* @param li
* @param e
* @param nf
* @return
*/
public Stmt makeLocalVar(Position pos, LocalDef li, Expr e) {
final TypeNode tn = xnf.CanonicalTypeNode(pos, li.type());
final LocalDecl ld = xnf.LocalDecl(pos, xnf.FlagsNode(pos, li.flags()), tn,
xnf.Id(pos,li.name()), e).localDef(li);
return ld;
}
/**
* Create a new local variable with the given flags, with initializer e.
* Return a Pair<LocalDecl, Local>, which includes the statement of the local variable and the reference to the variable
* @param pos
* @param flags
* @param initializer
* @param context
* @return
*/
public Pair<LocalDecl, Local> makeLocalVarWithAnnotation(Position pos, Flags flags, Expr initializer, List<AnnotationNode> annotations, Context context) {
LocalDecl localDecl = null;
Local ldRef = null;
if (flags == null) {
flags = Flags.NONE;
}
// has been converted to a variable reference.
final Type type = initializer.type();
if (!xts.typeEquals(type, xts.Void(), context)) {
final Name varName = Context.getNewVarName();
final TypeNode tn = xnf.CanonicalTypeNode(pos, type);
final LocalDef li = xts.localDef(pos, flags, Types.ref(type), varName);
final Id varId = xnf.Id(pos, varName);
localDecl = xnf.LocalDecl(pos, xnf.FlagsNode(pos, flags), tn, varId, initializer).localDef(li);
if(annotations != null && annotations.size() > 0){
localDecl = (LocalDecl)((X10Del) localDecl.del()).annotations(annotations);
}
ldRef = (Local) xnf.Local(pos, varId).localInstance(li.asInstance()).type(type);
}
return new Pair<LocalDecl, Local>(localDecl, ldRef);
}
/**
* Create a new local variable with the given flags, with initializer e. Add the variable declaration to stmtList.
* Return a reference to the variable.
*
* Returns null if the type is Void.
*
* @param pos
* @param e
* @param stmtList
* @param nf
* @param ts
* @param xc
* @return
*/
public Expr makeLocalVar(Position pos, Flags flags, Expr e, List<Stmt> stmtList, Context xc) {
Expr result = null;
if (flags == null) {
flags = Flags.NONE;
}
// has been converted to a variable reference.
final Type type = e.type();
if (! xts.typeEquals(type, xts.Void(), xc)) {
final Name varName = Context.getNewVarName();
final TypeNode tn = xnf.CanonicalTypeNode(pos,type);
final LocalDef li = xts.localDef(pos, flags, Types.ref(type), varName);
final Id varId = xnf.Id(pos, varName);
final LocalDecl ld = xnf.LocalDecl(pos, xnf.FlagsNode(pos, flags), tn, varId, e).localDef(li);
final Local ldRef = (Local) xnf.Local(pos, varId).localInstance(li.asInstance()).type(type);
stmtList.add(ld);
result=ldRef;
}
return result;
}
/**
* Create a local variable reference.
*
* @param pos the Position of the reference in the source code
* @param decl the declaration of the local variable
* @return the synthesized Local variable reference
*/
public Local createLocal(Position pos, LocalDecl decl) {
return createLocal(pos, decl.localDef().asInstance());
}
/**
* Create a local variable reference.
*
* @param pos the Position of the reference in the source code
* @param li a type system object representing this local variable
* @return the synthesized Local variable reference
*/
public Local createLocal(Position pos, LocalInstance li) {
return (Local) xnf.Local(pos, xnf.Id(pos, li.name())).localInstance(li).type(li.type());
}
/**
* Make an assignment whose left-hand-side is an expression.
*
* @param pos the Position of the assignment in the source code
* @param lhs the left-hand-side of the assignment
* @param op the assignment operator to use
* @param rhs the right-hand-side of the assignment
* @param xc the context
* @return the synthesized assignment
* @throws SemanticException
*/
public Assign makeAssign(Position pos, Expr lhs, Assign.Operator op, Expr rhs, Context xc) throws SemanticException {
Assign a = (Assign) xnf.Assign(pos, lhs, op, rhs).type(lhs.type());
if (a instanceof FieldAssign) {
assert (lhs instanceof Field);
assert ((Field) lhs).fieldInstance() != null;
a = ((FieldAssign) a).fieldInstance(((Field)lhs).fieldInstance());
} else if (a instanceof SettableAssign) {
assert (lhs instanceof InlinableCall);
InlinableCall call = (InlinableCall) lhs;
Receiver target = call.target();
MethodInstance ami = (MethodInstance) call.procedureInstance();
List<Type> argTypes = CollectionUtil.append(ami.formalTypes(), Collections.singletonList(ami.returnType()));
MethodInstance smi = xts.findMethod(target.type(),
xts.MethodMatcher(target.type(), SettableAssign.SET, argTypes, xc));
a = ((SettableAssign) a).methodInstance(smi);
a = ((SettableAssign) a).applyMethodInstance(ami);
}
return a;
}
/**
* Make a field access for r.name. Throw a SemanticException if such a field does not exist.
* @param pos
* @param r
* @param name
* @param context
* @return
* @throws SemanticException
*/
public Expr makeFieldAccess(Position pos, Receiver r, Name name, Context context) throws SemanticException {
FieldInstance fi = xts.findField(r.type(), r.type(), name, context);
Expr result = xnf.Field(pos, r, xnf.Id(pos, name)).fieldInstance(fi)
.type(fi.type());
return result;
}
/**
* Make a field access for ((SuperType)r).name
* Current X10 type system doesn't support find a field from its super type
* @param pos
* @param superType
* @param r
* @param name
* @param context
* @return
* @throws SemanticException
*/
public Expr makeSuperTypeFieldAccess(Position pos, Type superType, Receiver r, Name name, Context context) throws SemanticException {
FieldInstance fi = xts.findField(superType, superType, name, context);
Expr result = xnf.Field(pos, r, xnf.Id(pos, name)).fieldInstance(fi)
.type(fi.type());
return result;
}
/**
* Make a field assign, leftReceier.leftName = rightExpr;
* @param pos
* @param leftReceiver
* @param leftName
* @param rightExpr
* @param context
* @return
* @throws SemanticException
*/
public Expr makeFieldAssign(Position pos, Receiver leftReceiver, Name leftName, Expr rightExpr, Context context)
throws SemanticException {
Field field = makeStaticField(pos, leftReceiver.type(), leftName, xts.Int(), context);
// assign
Expr assign = xnf.FieldAssign(pos, leftReceiver, xnf.Id(pos, leftName), Assign.ASSIGN, rightExpr)
.fieldInstance(field.fieldInstance()).type(rightExpr.type());
return assign;
}
/**
* Make a field to field assign: leftReceiver.leftName = rightReceiver.rightName
* @param pos
* @param leftReceiver
* @param leftName
* @param rightReceiver
* @param rightName
* @param context
* @return
* @throws SemanticException
*/
public Expr makeFieldToFieldAssign(Position pos, Receiver leftReceiver, Name leftName,
Receiver rightReceiver, Name rightName, Context context) throws SemanticException{
Expr rightExpr = makeFieldAccess(pos, rightReceiver, rightName, context);
Field field = makeStaticField(pos, leftReceiver.type(),
leftName,
xts.Int(),
context);
// assign
Expr assign = xnf.FieldAssign(pos,
leftReceiver, xnf.Id(pos, leftName),
Assign.ASSIGN, rightExpr)
.fieldInstance(field.fieldInstance())
.type(rightExpr.type());
return assign;
}
/**
* Make a local to field assign: leftReceiver.leftName = local (localName/localType)
* @param pos
* @param leftReceiver
* @param leftName
* @param localName
* @param localType
* @param localFlags
* @param context
* @return
* @throws SemanticException
*/
public Expr makeLocalToFieldAssign(Position pos, Receiver leftReceiver, Name leftName,
Name localName, Type localType, Flags localFlags, Context context) throws SemanticException{
LocalDef ldef = xts.localDef(pos, localFlags, Types.ref(localType), localName);
Expr init = xnf.Local(pos, xnf.Id(pos, localName)).localInstance(ldef.asInstance()).type(localType);
Field field = makeStaticField(pos, leftReceiver.type(),
leftName,
xts.Int(),
context);
Expr assign = xnf.FieldAssign(pos, leftReceiver, xnf.Id(pos, leftName), Assign.ASSIGN, init)
.fieldInstance(field.fieldInstance())
.type(localType);
return assign;
}
/**
* Make a field to local assign: local(localName/localType) = rightReceiver.rightName
* @param pos
* @param localName
* @param localType
* @param rightReceiver
* @param rightName
* @param context
* @return
* @throws SemanticException
*/
public Expr makeFieldToLocalAssign(Position pos, Name localName, Type localType, Flags localFlags, Receiver rightReceiver, Name rightName
, Context context) throws SemanticException{
//FIXME: need check whether this method returns correct expr
//right
Expr rightExpr = makeFieldAccess(pos, rightReceiver, rightName, context);
//locals
LocalDef ldef = xts.localDef(pos, localFlags, Types.ref(localType), localName);
Local local = xnf.Local(pos, xnf.Id(pos, localName)).localInstance(ldef.asInstance());
//assign
Expr assign = xnf.LocalAssign(pos, local, Assign.ASSIGN, rightExpr).type(rightExpr.type());
return assign;
}
public Call makeStaticCall(Position pos,
Type receiver,
Name name,
Type returnType,
Context xc) throws SemanticException {
return makeStaticCall(pos, receiver, name, Collections.<TypeNode>emptyList(),
Collections.<Expr>emptyList(), returnType, xc);
}
public Call makeStaticCall(Position pos,
Type receiver,
Name name,
List<Expr> args,
Type returnType,
Context xc) throws SemanticException {
return makeStaticCall(pos, receiver, name, Collections.<TypeNode>emptyList(), args, returnType, xc);
}
public Call makeStaticCall(Position pos,
Type receiver,
Name name,
List<Expr> args,
Type returnType,
List<Type> argTypes,
Context xc) throws SemanticException {
return makeStaticCall(pos, receiver, name, Collections.<TypeNode>emptyList(), args,
returnType, argTypes, xc);
}
public Call makeStaticCall(Position pos, Type receiver, Name name,
List<TypeNode> typeArgsN,
List<Expr> args,
Type returnType,
Context xc) throws SemanticException {
List<Type> argT = new ArrayList<Type>();
for (Expr t: args) argT.add(t.type());
return makeStaticCall(pos, receiver, name, typeArgsN, args, returnType, argT, xc);
}
/**
* Return a static call constructed from the given data.
* @param pos
* @param receiver
* @param name
* @param typeArgsN
* @param args
* @param returnType
* @param argTypes
* @param xc
* @return
* @throws SemanticException if no method can be located with this data
*/
public Call makeStaticCall(Position pos,
Type receiver,
Name name,
List<TypeNode> typeArgsN,
List<Expr> args,
Type returnType,
List<Type> argTypes,
Context xc) throws SemanticException {
List<Type> typeArgs = new ArrayList<Type>();
for (TypeNode t : typeArgsN) typeArgs.add(t.type());
X10ClassType container = receiver.toClass();
MethodInstance mi = xts.findMethod(receiver,
xts.MethodMatcher(receiver, name, typeArgs, argTypes, xc.pushClass(container.def(), container)));
Call result= (Call) xnf.X10Call(pos,
xnf.CanonicalTypeNode(pos, receiver),
xnf.Id(pos, name),
typeArgsN,
args)
.methodInstance(mi)
.type(returnType);
return result;
}
/**
* Make a instance call: ((superType)receiver).name(args)
* It's different with the makeInstaceCall in the case the method is in super class, not in the receiver's type
* @param pos the position
* @param superType the super-type which contains the method
* @param receiver the instance it self
* @param name methodName
* @param typeArgsN type nodes for the method
* @param args arguments
* @param returnType return type
* @param argTypes arguments' type
* @param xc
* @return
* @throws SemanticException
*/
public Call makeSuperTypeInstanceCall(Position pos, Type superType, Receiver receiver, Name name, List<TypeNode> typeArgsN,
List<Expr> args, Type returnType, List<Type> argTypes, Context xc)
throws SemanticException {
List<Type> typeArgs = new ArrayList<Type>();
for (TypeNode t : typeArgsN)
typeArgs.add(t.type());
MethodInstance mi = xts.findMethod(superType, xts.MethodMatcher(superType, name, typeArgs,
argTypes, xc));
Call result = (Call) xnf.X10Call(pos, receiver, xnf.Id(pos, name), typeArgsN, args).methodInstance(mi)
.type(returnType);
return result;
}
public Call makeInstanceCall(Position pos,
Receiver receiver,
Name name,
List<TypeNode> typeArgsN,
List<Expr> args,
Type returnType,
List<Type> argTypes,
Context xc) throws SemanticException {
List<Type> typeArgs = new ArrayList<Type>();
for (TypeNode t : typeArgsN) typeArgs.add(t.type());
X10ClassType container = receiver.type().toClass();
MethodInstance mi = xts.findMethod(container,
xts.MethodMatcher(container, name, typeArgs, argTypes, xc.pushClass(container.def(), container)));
Call result= (Call) xnf.X10Call(pos,
receiver,
xnf.Id(pos, name),
typeArgsN,
args)
.methodInstance(mi)
.type(returnType);
return result;
}
/**
* Return a synthesized AST node for (parms):retType => body, at the given position and context.
* @param pos
* @param retType
* @param parms
* @param body
* @param context
* @return
*/
public Closure makeClosure(Position pos, Type retType, List<Formal> parms, Block body, Context context) {
return ClosureSynthesizer.makeClosure( xts, xnf, pos, retType, parms, body, context, null);
}
public Closure makeClosure(Position pos, Type retType, List<Formal> parms, Block body, Context context, List<X10ClassType> annotations) {
return ClosureSynthesizer.makeClosure( xts, xnf, pos, retType, parms, body, context, annotations);
}
/**
* Return a synthesized AST node for ():retType => body, at the given position and context.
* @param pos
* @param retType
* @param parms
* @param body
* @param context
* @return
*/
public Closure makeClosure(Position pos, Type retType, Block body, Context context, List<X10ClassType> annotations) {
return makeClosure(pos, retType, Collections.<Formal>emptyList(), body, context, annotations);
}
public Closure makeClosure(Position pos, Type retType, Block body, Context context) {
return makeClosure(pos, retType, Collections.<Formal>emptyList(), body, context);
}
public Block toBlock(Stmt body) {
return body instanceof Block ? (Block) body : xnf.Block(body.position(), body);
}
public Field firstPlace() {
CConstraint c = ConstraintManager.getConstraintSystem().makeCConstraint();
XTerm id = makeProperty(xts.Int(), c.self(), "id");
try {
c.addBinding(id, ConstraintManager.getConstraintSystem().makeLit(0, xts.Int()));
Type type = Types.xclause(xts.Place(), c);
assert Types.consistent(type);
return makeStaticField(Position.COMPILER_GENERATED, xts.Place(),
Name.make("FIRST_PLACE"), type, (Context) xts.emptyContext());
} catch (SemanticException z) {
// wont happen
}
return null;
}
public Field makeStaticField(Position pos,
Type receiver,
Name name,
Type returnType,
Context xc) throws SemanticException {
FieldInstance fi = xts.findField(receiver, receiver, name, xc);
Field result= (Field) xnf.Field(pos,
xnf.CanonicalTypeNode(pos, receiver),
xnf.Id(pos, name))
.fieldInstance(fi)
.type(returnType);
return result;
}
/**
* Return the number of annotation properties.
* @param def
* @param name
* @return
*/
public int getPropertyNum(X10Def def, String name) throws SemanticException {
Type t = xts.systemResolver().findOne(QName.make(name));
List<Type> ts = def.annotationsMatching(t);
for (Type at : ts) {
Type bt = Types.baseType(at);
if (bt instanceof X10ClassType) {
X10ClassType act = (X10ClassType) bt;
return act.propertyInitializers().size();
}
}
return 0;
}
/**
* Return the value of annotation properties for a given property and location index.
* @param def
* @param name
* @param index
* @return
*/
public String getPropertyValue(X10Def def, String name, int index) throws SemanticException {
Type t = xts.systemResolver().findOne(QName.make(name));
List<Type> ts = def.annotationsMatching(t);
for (Type at : ts) {
Type bt = Types.baseType(at);
if (bt instanceof X10ClassType) {
X10ClassType act = (X10ClassType) bt;
if (index < act.propertyInitializers().size()) {
Expr e = act.propertyInitializer(index);
if (e.isConstant() && e.constantValue() instanceof StringValue) {
return ((StringValue) e.constantValue()).value();
}
}
}
}
return null;
}
/**
* Add a field to a class.
* @param cDecl
* @param name
* @param flag
* @param t
* @param p
* @return
*/
public X10ClassDecl addClassField(Position p, X10ClassDecl cDecl, Name name, Flags flag, Type t) {
X10ClassDef cDef = (X10ClassDef) cDecl.classDef();
Id id = xnf.Id(p, name);
CanonicalTypeNode tnode = xnf.CanonicalTypeNode(p, t);
FlagsNode fnode = xnf.FlagsNode(p, flag);
FieldDef fDef = xts.fieldDef(p, Types.ref(cDef.asType()), flag, Types.ref(t), name);
FieldDecl fDecl = xnf.FieldDecl(p, fnode, tnode, id).fieldDef(fDef);
cDef.addField(fDef);
List<ClassMember> cm = new ArrayList<ClassMember>();
cm.addAll(cDecl.body().members());
cm.add(fDecl);
ClassBody cb = cDecl.body();
return (X10ClassDecl) cDecl.classDef(cDef).body(cb.members(cm));
}
/**
* Insert inner classes to the given x10 class. Return a new class with the inner classes added in.
*
* @param cDecl
* The original class with parallel methods
* @param innerClasses
* the inner classes to be inserted into the class
* @return A newly created class with inner classes as members
*/
public static X10ClassDecl addNestedClasses(X10ClassDecl cDecl, List<X10ClassDecl> innerClasses) {
List<ClassMember> cMembers = new ArrayList<ClassMember>();
ClassBody body = cDecl.body();
cMembers.addAll(body.members());
X10ClassDef cDef = (X10ClassDef) cDecl.classDef();
for (X10ClassDecl icDecl : innerClasses) {
X10ClassDef icDef = (X10ClassDef) icDecl.classDef();
// icDef.kind(ClassDef.MEMBER);
icDef.setPackage(cDef.package_());
// icDef.outer(Types.<ClassDef> ref(cDef));
cMembers.add(icDecl);
cDef.addMemberClass(Types.<ClassType> ref(icDef.asType()));
}
return (X10ClassDecl) cDecl.body(body.members(cMembers));
}
/**
* Insert methods to the given x10 class. Return a new class with the new methods added in.
* @param cDecl The original class with parallel methods
* @param methods The methods to be inserted in
* @return A newly created class with methods as members
*/
public static X10ClassDecl addMethods(X10ClassDecl cDecl, List<X10MethodDecl> methods){
List<ClassMember> cm = new ArrayList<ClassMember>();
cm.addAll(cDecl.body().members());
cm.addAll(methods);
ClassBody cb = cDecl.body();
return (X10ClassDecl) cDecl.body(cb.members(cm));
}
public FieldDef findFieldDef(ClassDef cDef, Name fName) throws SemanticException {
for (FieldDef df : cDef.fields()) {
if (fName.equals(df.name())) {
return df;
}
}
return null;
}
/**
* Create a copy constructor decl.
* @param cDecl
* @param name
* @param flag
* @param t
* @param p
* @param context
* @return X10ConstructorDec
* @throws SemanticException
*/
public X10ConstructorDecl makeClassCopyConstructor(Position p, Position errorP, X10ClassDecl cDecl, List<Name> fieldName,
List<Name> parmName, List<Type> parmType, List<Flags> parmFlags,
Context context) throws SemanticException {
X10ClassDef cDef = (X10ClassDef) cDecl.classDef();
// super constructor def (noarg)
ConstructorDef sDef = xts.findConstructor(
cDecl.superClass().type(),
xts.ConstructorMatcher(cDecl.superClass().type(), Collections
.<Type> emptyList(), context)).def();
Block block = xnf.Block(p, xnf.SuperCall(p, Collections.<Expr> emptyList())
.constructorInstance(sDef.asInstance()));
List<Formal> fList = new ArrayList<Formal>();
List<Ref<? extends Type>> ftList = new ArrayList<Ref<? extends Type>>();
// field assign
for (int i = 0; i < fieldName.size(); i++) {
Name fName = fieldName.get(i);
Name pName = parmName.get(i);
Type pType = parmType.get(i);
Flags pFlags = parmFlags.get(i);
Id fid = xnf.Id(p, fName);
// Field selector
Receiver receiver = xnf.This(p).type(cDef.asType());
// Field field = makeStaticField(p, special, fName, pType, context);
FieldDef fDef = findFieldDef(cDef, fName);
// Assign
LocalDef ldef = xts.localDef(p, pFlags, Types.ref(pType), pName);
Expr init = xnf.Local(p, xnf.Id(p, pName)).localInstance(ldef.asInstance()).type(pType);
Expr assign = xnf.FieldAssign(p, receiver, fid, Assign.ASSIGN, init).fieldInstance(fDef.asInstance())
.type(pType);
Formal f = xnf.Formal(p, xnf.FlagsNode(p, pFlags), xnf.CanonicalTypeNode(p, pType), xnf.Id(p, pName))
.localDef(ldef);
fList.add(f);
ftList.add(Types.ref(pType));
block = block.append(xnf.Eval(p, assign));
}
// constructor
X10ConstructorDecl xd = (X10ConstructorDecl) xnf.ConstructorDecl(p, xnf.FlagsNode(p, Flags.PRIVATE), cDecl
.name(), fList, block);
xd = xd.typeParameters(Collections.<TypeParamNode>emptyList());
xd = xd.returnType(xnf.CanonicalTypeNode(p, cDef.asType()));
ConstructorDef xDef = xts.constructorDef(p, errorP, Types.ref(cDef.asType()), Flags.PRIVATE, ftList, Collections.<Ref<? extends Type>>emptyList());
return (X10ConstructorDecl) xd.constructorDef(xDef);
}
/**
* Create a class's constructor with the input parameters. Return a new class with the new constructor.
*
* @param cDecl
* @param parmName
* @param parmtype
* @param parmFlags
* @param stmts Statements of the constructor. It should contains the call to super class's constructor.
* @param context
* @return X10ClassDecl
* @throws SemanticException
*/
public X10ClassDecl addClassConstructor(Position p, Position errorP,
X10ClassDecl cDecl,
List<Name> parmName,
List<Type> parmType,
List<Flags> parmFlags,
List<Stmt> stmts,
Context context) throws SemanticException {
X10ClassDef cDef = (X10ClassDef) cDecl.classDef();
ClassType cType = cDef.asType();
// reference to formal
List<Formal> fList = new ArrayList<Formal>();
List<Ref<? extends Type>> frList = new ArrayList<Ref<? extends Type>>();
for (int i=0; i<parmName.size(); i++) {
Name pName = parmName.get(i);
Type pType = parmType.get(i);
Flags pFlags = parmFlags.get(i);
// reference
LocalDef ldef = xts.localDef(p, pFlags, Types.ref(pType), pName);
Expr ref = xnf.Local(p, xnf.Id(p, pName)).localInstance(ldef.asInstance()).type(pType);
Formal f = xnf.Formal(p, xnf.FlagsNode(p, pFlags),
xnf.CanonicalTypeNode(p, pType),
xnf.Id(p, pName)).localDef(ldef);
fList.add(f);
frList.add(Types.ref(pType));
}
Block block = xnf.Block(p,
stmts);
// constructor
X10ConstructorDecl xd = (X10ConstructorDecl) xnf.ConstructorDecl(p,
xnf.FlagsNode(p, Flags.PUBLIC),
cDecl.name(),
fList, // formal types
block);
xd = xd.typeParameters(Collections.<TypeParamNode>emptyList());
xd = xd.returnType(xnf.CanonicalTypeNode(p, cDef.asType()));
ConstructorDef xDef = xts.constructorDef(p, errorP,
Types.ref(cDef.asType()),
Flags.PUBLIC,
frList, // formal types
Collections.<Ref<? extends Type>>emptyList()
); // throw types
List<ClassMember> cm = new ArrayList<ClassMember>();
ClassBody cb = cDecl.body();
cm.addAll(cb.members());
cm.add(xd.constructorDef(xDef));
cDef.addConstructor(xDef);
return (X10ClassDecl)cDecl.classDef(cDef).body(cb.members(cm));
}
/**
* According to the input parameters, create a new instance of the type classDef
*
* @param pos
* @param classDef The class def
* @param args expressions or values of the input parameters
* @param annotations annotation of the new instance, could be null
* @param context
* @return the expression of the new instance
* @throws SemanticException
*/
public Expr makeNewInstance(Position pos, X10ClassDef classDef, List<Type> formalTypes, List<Expr> args, List<AnnotationNode> annotations,
Context context) throws SemanticException {
//It's possible we need use formal types to look for the constructor
//not from the input expressions
// Prepare args' type
Type classType = classDef.asType();
ConstructorDef constructorDef = xts.findConstructor(classType, // receiver's
// type
xts.ConstructorMatcher(classType, formalTypes, context))
.def();
ConstructorInstance constructorIns = constructorDef.asInstance();
New aNew = xnf.New(pos, xnf.CanonicalTypeNode(pos, Types.ref(classType)), args);
// Add annotations to New
if (annotations != null && annotations.size() > 0) {
aNew = (New) ((X10Del) aNew.del()).annotations(annotations);
}
Expr construct = aNew.constructorInstance(constructorIns).type(classType);
return construct;
}
/**
* Create a formal from given type/name/flags
* @param pos
* @param formalType
* @param formalName
* @param formalFlags
* @return
*/
public Formal createFormal(Position pos, Type formalType, Name formalName, Flags formalFlags){
LocalDef ldef = xts.localDef(pos, formalFlags, Types.ref(formalType), formalName);
Formal f = xnf.Formal(pos, xnf.FlagsNode(pos, formalFlags),
xnf.CanonicalTypeNode(pos, formalType),
xnf.Id(pos, formalName)).localDef(ldef);
return f;
}
/**
* Create a formal from a given local def
* @param localDef the local def
* @return the formal corresponding to the local
*/
public Formal createFormal(LocalDef localDef){
Position pos = localDef.position();
Flags formalFlags = localDef.flags();
Type formalType = localDef.type().get();
Name formalName = localDef.name();
Formal f = xnf.Formal(pos,
xnf.FlagsNode(pos, formalFlags),
xnf.CanonicalTypeNode(pos, formalType),
xnf.Id(pos, formalName)).localDef(localDef);
return f;
}
/**
*
* Use the input parameters to generate the corresponding super call with all parameters
*
* @param p
* @param cDecl
* @param parmName
* @param parmType
* @param parmFlags
* @param context
* @return
* @throws SemanticException
*/
public Stmt makeSuperCallStatement(Position p, X10ClassDecl cDecl,
List<Name> parmName,
List<Type> parmType,
List<Flags> parmFlags,
Context context) throws SemanticException{
X10ClassDef cDef = (X10ClassDef) cDecl.classDef();
ClassType cType = cDef.asType();
// Find the right super constructor: def (args)
Type sType = cDecl.superClass().type();
Type scType = sType; // PlaceChecker.AddIsHereClause(sType, context);
ConstructorDef sDef = xts.findConstructor(sType, // receiver's type
xts.ConstructorMatcher(sType,
Collections.singletonList(scType), // constraint's type (!)
context)).def();
// reference to formal
List<Expr> eSuper = new ArrayList<Expr>();
//find the right
for (int i=0; i<parmName.size(); i++) {
Name pName = parmName.get(i);
Type pType = parmType.get(i);
Flags pFlags = parmFlags.get(i);
// reference
LocalDef ldef = xts.localDef(p, pFlags, Types.ref(pType), pName);
Expr ref = xnf.Local(p, xnf.Id(p, pName)).localInstance(ldef.asInstance()).type(pType);
eSuper.add(ref);
}
return xnf.SuperCall(p, eSuper).constructorInstance(sDef.asInstance());
}
/**
* Create a copy constructor decl.
* @param cDecl
* @param parmName
* @param parmtype
* @param parmFlags
* @param context
* @return X10ClassDecl
* @throws SemanticException
*/
public X10ClassDecl addClassSuperConstructor(Position p, Position errorP,
X10ClassDecl cDecl,
List<Name> parmName,
List<Type> parmType,
List<Flags> parmFlags,
Context context) throws SemanticException {
Stmt s = makeSuperCallStatement(p, cDecl, parmName, parmType, parmFlags, context);
return addClassConstructor(p, errorP, cDecl, parmName, parmType, parmFlags, Collections.singletonList(s), context);
}
/**
* Create a method def in a class def
* @param p
* @param classDef
* @param flag
* @param returnType
* @param name
* @param formals
* @param throwTypes
* @return
*/
public X10MethodDef createMethodDef(Position p, Position errorP, X10ClassDef classDef,
Flags flag,
Type returnType,
Name name,
List<Formal> formals,
List<Type> throwTypes
){
return createMethodDef(p, errorP, classDef, flag, returnType, name, formals, throwTypes, null);
}
public X10MethodDef createMethodDef(Position p, Position errorP, X10ClassDef classDef,
Flags flag,
Type returnType,
Name name,
List<Formal> formals,
List<Type> throwTypes,
Type offerType
){
// Method def
List<Ref<? extends Type>> formalTypeRefs = new ArrayList<Ref<? extends Type>>();
List<Ref<? extends Type>> throwTypeRefs = new ArrayList<Ref<? extends Type>>();
for (Formal f : formals) {
formalTypeRefs.add(f.type().typeRef());
}
for (Type t : throwTypes) {
throwTypeRefs.add(Types.ref(t));
}
X10MethodDef mDef = (X10MethodDef) xts.methodDef(p, errorP,
Types.ref(classDef.asType()),
flag,
Types.ref(returnType),
name,
formalTypeRefs,
throwTypeRefs,
Types.ref(offerType));
classDef.addMethod(mDef);
return mDef;
}
/**
* Create a method decl with a given mDef. The mDef is in cDecl.classDef() yet
* @param cDecl
* @param mDef
* @param formals
* @param body
* @return
* @throws SemanticException
*/
public X10ClassDecl addClassMethod(X10ClassDecl cDecl,
X10MethodDef mDef,
List<Formal> formals,
Block body) throws SemanticException {
X10ClassDef cDef = (X10ClassDef) cDecl.classDef();
Position p = mDef.position();
// Method Decl
FlagsNode flagNode = xnf.FlagsNode(p, mDef.flags());
TypeNode returnTypeNode = xnf.CanonicalTypeNode(p, mDef.returnType());
MethodDecl mDecl = xnf.MethodDecl(p, flagNode, returnTypeNode, xnf.Id(p, mDef.name()),
formals, body);
mDecl = mDecl.methodDef(mDef); //Need set the method def to the method instance
List<ClassMember> cm = new ArrayList<ClassMember>();
cm.addAll(cDecl.body().members());
cm.add(mDecl);
ClassBody cb = cDecl.body();
return (X10ClassDecl) cDecl.classDef(cDef).body(cb.members(cm));
}
/**
* Create a class decl, with no constructor
*
* @param p
* @param flag
* @param kind
* @param name
* @param interfaces
* @param context
* @return
* @throws SemanticException
*/
public X10ClassDecl createClass(Position p, X10ClassDef cDef,
Context context) throws SemanticException {
FlagsNode fNode = xnf.FlagsNode(p, cDef.flags());
Id id = xnf.Id(p, cDef.name());
TypeNode superTN = (TypeNode) xnf.CanonicalTypeNode(p, cDef.superType());
List<ClassMember> cmembers = new ArrayList<ClassMember>();
ClassBody body = xnf.ClassBody(p, cmembers);
List<TypeNode> interfaceTN = new ArrayList<TypeNode>();
for (Ref<? extends Type> t : cDef.interfaces()) {
interfaceTN.add((TypeNode) xnf.CanonicalTypeNode(p, t));
}
X10ClassDecl cDecl = (X10ClassDecl) xnf.ClassDecl(p, fNode, id, superTN, interfaceTN, body);
return (X10ClassDecl) cDecl.classDef(cDef);
}
/**
* Create a class def with the input parameters
* @param superType the superType for the class type
* @param interfaces interfaces of the class
* @param flag
* @param kind
* @param name
* @return
*/
public X10ClassDef createClassDef(Type superType, List<Type> interfaces, Flags flag, ClassDef.Kind kind, Name name){
X10ClassDef cDef = (X10ClassDef) xts.createClassDef();
cDef.superType(Types.ref(superType)); //And the super Type
List<Ref<? extends Type>> interfacesRef = new ArrayList<Ref<? extends Type>>();
for(Type t : interfaces){
interfacesRef.add(Types.ref(t));
}
cDef.setInterfaces(interfacesRef);
cDef.name(name);
cDef.setFlags(flag);
cDef.kind(kind); // important to set kind
return cDef;
}
/**
* Create a class decl, and add a default constructor to it.
* Return the class with the default constructor
* @param flag
* @param kind : TOP_LEVEL, LOCAL, MEMBER?
* @param name
* @param interfaces
* @return X10ClassDecl
* @throws SemanticException
*/
public X10ClassDecl createClassWithConstructor(Position p, Position errorP,
X10ClassDef cDef,
Context context) throws SemanticException
{
X10ClassDecl cDecl = createClass(p, cDef, context);
//add default constructor
X10ConstructorDecl xd = (X10ConstructorDecl) xnf.ConstructorDecl(p,
xnf.FlagsNode(p, Flags.PUBLIC),
cDecl.name(),
Collections.<Formal>emptyList(),
xnf.Block(p));
xd = xd.typeParameters(Collections.<TypeParamNode>emptyList());
xd = xd.returnType(xnf.CanonicalTypeNode(p, cDef.asType()));
ConstructorDef xDef = xts.constructorDef(p, errorP,
Types.ref(cDef.asType()),
Flags.PRIVATE,
Collections.<Ref<? extends Type>>emptyList(),
Collections.<Ref<? extends Type>>emptyList());
List<ClassMember> cm = new ArrayList<ClassMember>();
cm.add(xd.constructorDef(xDef));
ClassBody cb = cDecl.body();
cDef.addConstructor(xDef);
return (X10ClassDecl) cDecl.body(cb.members(cm));
}
/**
* Create a synthetic X10CanonicalTypeNode from the given Type. This node must have the property that if the type has a
* constraints clause c, then the depParameterExpr associated with the node must represent an AST that when translated to
* a constraint would yield c.
* @param pos
* @param type
* @param tc
* @return
* @throws SemanticException
*/
// TODO: This has to be made to work with nested types.
public X10CanonicalTypeNode makeCanonicalTypeNodeWithDepExpr(Position pos, Type type, ContextVisitor tc) {
NodeFactory nf = ((NodeFactory) tc.nodeFactory());
TypeSystem ts = ((TypeSystem) tc.typeSystem());
type = PlaceChecker.ReplacePlaceTermByHere(type, tc.context());
CConstraint c = Types.xclause(type);
if (c == null || c.valid())
return nf.X10CanonicalTypeNode(pos, type);
Type base = Types.baseType(type);
String typeName = base.toString();
List<Type> types = Collections.<Type>emptyList();
List<TypeNode> typeArgs = Collections.<TypeNode>emptyList();
if (base instanceof X10ClassType) {
X10ClassType xc = (X10ClassType) base;
types = xc.typeArguments();
if (types == null)
types = Collections.<Type>emptyList();
if (! types.isEmpty()) {
typeName = xc.def().toString();
typeArgs = new ArrayList<TypeNode>(types.size());
}
}
if (!types.isEmpty()) {
for (Type t : types)
typeArgs.add(nf.X10CanonicalTypeNode(pos, t));
}
DepParameterExpr dep = nf.DepParameterExpr(pos, makeExpr(c, Types.baseType(type), pos));
QName qName = QName.make(typeName);
QName qual = qName.qualifier();
TypeNode tn = nf.AmbDepTypeNode(pos, qual==null ? null : nf.PrefixFromQualifiedName(pos, qual),
nf.Id(pos, qName.name()), typeArgs, Collections.<Expr>emptyList(), dep);
TypeBuilder tb = new X10TypeBuilder(tc.job(), tc.typeSystem(), nf);
tn = (TypeNode) tn.visit(tb);
TypeChecker typeChecker = (TypeChecker) new X10TypeChecker(tc.job(), ts, nf,tc.job().nodeMemo()).context(tc.context());
tn = (TypeNode) tn.visit(typeChecker);
if (! (tn instanceof X10CanonicalTypeNode))
assert tn instanceof X10CanonicalTypeNode;
return (X10CanonicalTypeNode) tn;
}
// For the purpose of InitChecker and CheckEscapingThis:
// we need to extract from a constraint all the locals and fields of "this" and check they are definitely assigned.
public static java.util.Set<VarDef> getLocals(TypeNode n) {
java.util.Set<VarDef> res = CollectionFactory.newHashSet();
CConstraint c = Types.xclause(n.type());
if (c == null || c.valid()) {
// nothing to check
return res;
}
List<? extends XTerm> terms = c.extConstraints();
for (XTerm t : terms)
res.addAll(getLocals(t));
return res;
}
private static java.util.Set<VarDef> getLocals(XTerm t) {
java.util.Set<VarDef> res = CollectionFactory.newHashSet();
// FieldDef
if (t instanceof CField) {
final CField field = (CField) t;
final XVar receiver = field.receiver();
res.addAll(getLocals(receiver));
if (receiver instanceof CThis && field.def() instanceof VarDef) {
res.add((VarDef) field.def());
}
} else if (t instanceof CLocal) {
CLocal local = (CLocal) t;
res.add(local.localDef());
} else if (t instanceof XFormula<?>) {
final XFormula<?> xFormula = (XFormula<?>) t;
for (XTerm tt: xFormula.arguments())
res.addAll(getLocals(tt));
}
return res;
}
/**
* Return a synthesized AST for a constraint. Used when generating code from implicit casts.
* @param c the constraint
* @return the expression corresponding to the constraint
* @seeAlso X10TypeTranslator.constraint(...): it generates a constraint from an AST.
*/
Expr makeExpr(XTerm t, Type baseType, Position pos) {
if (t instanceof CField)
return makeExpr((CField) t, baseType, pos);
if (t instanceof XLit)
return makeExpr((XLit) t, baseType, pos);
if (t instanceof XEquals)
return makeExpr((XEquals) t, baseType, pos);
if (t instanceof XDisEquals)
return makeExpr((XDisEquals) t, baseType, pos);
if (t instanceof CSelf)
return makeExpr((CSelf) t, baseType, pos); // this must occur before XLocal_c
if (t instanceof CThis)
// If we were able to ensure that a CThis without an enclosing QVar
// always represents a non-qualified this, then we should pass null here.
// However, an occurrence of a qualified this in an arg to a macro call
// is treated as if it is not in a deptype, and for such a qualified this
// we get a CThis from XTypeTranslaor, not a QualifiedVar.
// So we pass ((CThis) t).type(). It is safe to do so.
return makeExpr((CThis) t, /*null,*/ ((CThis) t).type(), baseType, pos); // this must occur before XLocal_c
if (t instanceof XEQV)
return makeExpr((XEQV) t, baseType, pos); // this must occur before XLocal_c
if (t instanceof XUQV)
return makeExpr((XUQV) t, baseType, pos); // this must occur before XLocal_c
if (t instanceof CQualifiedVar) {
return makeExpr((CQualifiedVar) t, baseType, pos);
}
if (t instanceof CLocal)
return makeExpr((CLocal) t, baseType, pos);
if (t instanceof XNot)
return makeExpr((XNot) t, baseType, pos);
if (t instanceof XFormula<?>)
return makeExpr((XFormula<?>) t, baseType, pos);
// FIXME: warn about being unable to translate the term
return null;
}
TypeNode makeTypeNode(XVar receiver, Type baseType, Position pos) {
if (!(receiver instanceof XLit))
return null;
Object val = ((XLit) receiver).val();
if (!(val instanceof QName))
return null;
try {
return xnf.CanonicalTypeNode(pos, xts.forName((QName) val));
} catch (SemanticException e) {
throw new InternalCompilerError("Invalid type encountered in a constraint: "+val, e);
}
}
Expr makeExpr(CField t, Type baseType, Position pos) {
if (t.isHidden())
return null;
Receiver r = makeExpr(t.receiver(), baseType, pos);
if (r == null) {
r = makeTypeNode(t.receiver(), baseType, pos);
}
if (r == null)
return null;
Def fd = t.def();
if (fd instanceof FieldDef) {
Name n = ((FieldDef) fd).name();
return xnf.Field(pos, r, xnf.Id(pos, n));
}
if (fd instanceof MethodDef) {
Name n = ((MethodDef) fd).name();
return xnf.Call(pos, r, xnf.Id(pos, n));
}
return null;
}
// FIXME: merge with makeExpr(XLocal, Position)
Expr makeExpr(CSelf t, Type baseType, Position pos) {
return xnf.Special(pos, X10Special.SELF);
}
/* if (n instanceof Special){
// if it's an outer instance, then we need to access the outer field
Special special = (Special) n;
TypeNode qualifer = special.qualifier();
if (qualifer==null) return newReceiver;
// qualifer doesn't have type info because it was created in Synthesizer.makeExpr
qualifer = (TypeNode) qualifer.visit(builder).visit(checker);
ClassType ct = qualifer.type().toClass();
ClassType receiverType = Types.getClassType(newReceiver.type(), ts, context);
if (receiverType==null)
return newReceiver;
final ClassDef newReceiverDef = receiverType.def();
final ClassDef qualifierDef = ct.def();
if (newReceiverDef==qualifierDef)
return newReceiver;
return nf.Call(pos,newReceiver, nf.Id(pos,X10ClassDecl_c.getThisMethod(newReceiverDef.fullName(),ct.fullName())));
}*/
Expr makeExpr(CQualifiedVar v, Type baseType, Position pos) {
TypeNode tn = null;
ClassType ct = v.type().toClass();
XVar var = v.receiver();
if (var instanceof CThis) // use old code, but with type taken from v
return makeExpr((CThis) var, v.type(), baseType, pos);
if (! (var instanceof Typed || var instanceof CSelf))
// Unable to generate an expression for this term.
return null;
// Todo: Make self Typed.
Type varType;
if (var instanceof CSelf) {
varType = baseType;
} else {
varType = ((Typed) var).type();
}
ClassType varClassType = Types.getClassType(varType, xts);
ClassDef varDef = varClassType.def();
return xnf.Call(pos,
xnf.AmbExpr(pos, xnf.Id(pos,Name.make(var.toString()))),
xnf.Id(pos, X10ClassDecl_c.getThisMethod(varDef.fullName(),
ct.fullName())));
}
Expr makeExpr(CThis ct, Type type, Type baseType, Position pos) {
TypeNode tn = null;
if (type != null) {
tn = xnf.CanonicalTypeNode(pos, type);
}
return tn == null ? xnf.Special(pos, X10Special.THIS)
: xnf.Special(pos, X10Special.THIS, tn);
}
Expr makeExpr(XEQV t, Type baseType, Position pos) {
assert false;
return xnf.AmbExpr(pos, xnf.Id(pos,Name.make(t.toString())));
}
Expr makeExpr(XUQV t, Type baseType, Position pos) {
String str = t.toString();
// [DC] the following check doesn't always work -- we get 'here' that does match the 'global'
if (t == PlaceChecker.here())
return xnf.Here(pos);
// [DC] this seems like a reasonable hack at this point:
if (str.equals("here"))
return xnf.Here(pos);
return xnf.AmbExpr(pos, xnf.Id(pos,Name.make(t.toString())));
}
// FIXME: merge with makeExpr(XEQV, Position)
Expr makeExpr(CLocal t, Type baseType, Position pos) {
String str = t.name().toString();
return xnf.AmbExpr(pos, xnf.Id(pos,t.name().name()));
}
Expr makeExpr(XNot t, Type baseType, Position pos) {
Expr expr = makeExpr(t.arguments()[0], baseType, pos);
if (expr == null)
return null;
return xnf.Unary(pos, expr, Unary.NOT);
}
Expr makeExpr(XLit t, Type baseType, Position pos) {
if (t instanceof CLit) {
CLit l = (CLit) t;
if (baseType != null && !xts.isSubtype(l.type(), baseType)) {
throw new InternalCompilerError("Invalid expected literal type: "+baseType+" for "+l.type());
}
baseType = l.type();
}
Object val = t.val();
if (val == null)
return xnf.NullLit(pos);
if (val instanceof String)
return xnf.StringLit(pos, (String) val);
if (val instanceof Integer)
return xnf.IntLit(pos, ConstraintManager.getConstraintSystem().getIntLitKind(baseType), ((Integer) val).intValue());
if (val instanceof Long)
return xnf.IntLit(pos, ConstraintManager.getConstraintSystem().getIntLitKind(baseType), ((Long) val).longValue());
if (val instanceof Boolean)
return xnf.BooleanLit(pos, ((Boolean) val).booleanValue());
if (val instanceof Character)
return xnf.CharLit(pos, ((Character) val).charValue());
if (val instanceof Float)
return xnf.FloatLit(pos, FloatLit.FLOAT, ((Float) val).doubleValue());
if (val instanceof Double)
return xnf.FloatLit(pos, FloatLit.DOUBLE, ((Double) val).doubleValue());
if (val instanceof QName) // will get picked up later
return null;
// FIXME: warn about being unable to translate the literal
return null;
}
Expr makeExpr(XEquals t, Type baseType, Position pos) {
Expr left = makeExpr(t.arguments()[0], baseType, pos);
Expr right = makeExpr(t.arguments()[1], baseType, pos);
if (left == null || right == null)
return null;
return xnf.Binary(pos, left, Binary.EQ, right);
}
Expr makeExpr(XDisEquals t, Type baseType, Position pos) {
Expr left = makeExpr(t.arguments()[0], baseType, pos);
Expr right = makeExpr(t.arguments()[1], baseType, pos);
if (left == null || right == null)
return null;
return xnf.Binary(pos, left, Binary.NE, right);
}
Expr makeExpr(XFormula<?> t, Type baseType, Position pos) {
List<Expr> args = new ArrayList<Expr>();
for (XTerm a : t.arguments()) {
Expr e = makeExpr(a, baseType, pos);
if (e == null)
return null;
args.add(e);
}
String op = t.asExprOperator().toString();
if (op.equals(ConstraintManager.asExprAndName.toString())) {
return xnf.Binary(pos, args.get(0), Binary.COND_AND, args.get(1));
}
if (op.equals(ConstraintManager.asExprEqualsName.toString())) {
return xnf.Binary(pos, args.get(0), Binary.EQ, args.get(1));
}
if (op.equals(ConstraintManager.asExprDisEqualsName.toString())) {
return xnf.Binary(pos, args.get(0), Binary.NE, args.get(1));
}
if (op.equals(ConstraintManager.asExprNotName.toString())) {
return xnf.Unary(pos, Unary.NOT, args.get(0));
}
// FIXME: [IP] Hack to handle the "at" atom added by XTypeTranslator for structs
//if (n.toString().equals("at")) {
// Receiver r = args.remove(0);
// return xnf.Call(pos, r, xnf.Id(pos, n), args);
//} else {
return xnf.Call(pos, xnf.Id(pos, Name.make(op)), args);
//}
}
public List<Expr> makeExpr(CConstraint c, Type baseType, Position pos) {
List<Expr> es = new ArrayList<Expr>();
if (c == null)
return es;
List<? extends XTerm> terms = c.extConstraints();
for (XTerm term : terms) {
Expr e = makeExpr(term, null, pos);
if (e != null)
es.add(e);
}
return es;
}
//Some
/**
* Get an int value expression
* @param value
* @param pos
* @return
*/
public Expr intValueExpr(int value, Position pos){
return xnf.IntLit(pos, IntLit.INT, value).type(xts.Int());
}
/**
* Get an boolean value expression
* @param value true or false
* @param pos
* @return
*/
public Expr booleanValueExpr(boolean value, Position pos){
return xnf.BooleanLit(pos, value).type(xts.Boolean());
}
/**
* Get an string value expression
* @param value string
* @param pos
* @return
*/
public Expr stringValueExpr(String value, Position pos){
return xnf.StringLit(pos, value).type(xts.String());
}
/**
* Get this expression, ((ClassType)this)
* @param classType
* @param pos
* @return
*/
public Expr thisRef(Type classType, final Position pos){
return xnf.This(pos).type(classType);
}
/**
* Generate type of "()=> type"
* @param type
* @param pos
* @return
*/
public FunctionType simpleFunctionType(Type type, Position pos){
return xts.functionType(pos, Types.ref(type),
Collections.<ParameterType>emptyList(),
Collections.<Ref<? extends Type>>emptyList(),
Collections.<LocalDef>emptyList(), null
);
}
}