/*
* 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 x10c.visit;
import static x10cpp.visit.ASTQuery.assertNumberOfInitializers;
import static x10cpp.visit.ASTQuery.getStringPropertyInit;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import polyglot.ast.Assign;
import polyglot.ast.Block;
import polyglot.ast.CanonicalTypeNode;
import polyglot.ast.ClassBody;
import polyglot.ast.ClassDecl;
import polyglot.ast.ClassMember;
import polyglot.ast.Expr;
import polyglot.ast.Field;
import polyglot.ast.FieldAssign;
import polyglot.ast.FieldDecl;
import polyglot.ast.Formal;
import polyglot.ast.Id;
import polyglot.ast.Local;
import polyglot.ast.MethodDecl;
import polyglot.ast.NamedVariable;
import polyglot.ast.Node;
import polyglot.ast.NodeFactory;
import polyglot.ast.Receiver;
import polyglot.ast.Special;
import polyglot.ast.Special.Kind;
import polyglot.ast.TypeNode;
import polyglot.frontend.Job;
import polyglot.types.ClassDef;
import polyglot.types.ClassType;
import polyglot.types.Context;
import polyglot.types.FieldInstance;
import polyglot.types.Flags;
import polyglot.types.LocalDef;
import polyglot.types.LocalInstance;
import polyglot.types.Name;
import polyglot.types.Ref;
import polyglot.types.SemanticException;
import polyglot.types.Type;
import polyglot.types.TypeSystem;
import polyglot.types.Types;
import polyglot.types.VarDef;
import polyglot.types.VarInstance;
import polyglot.util.InternalCompilerError;
import polyglot.util.Position;
import polyglot.util.UniqueID;
import x10.ast.AnnotationNode;
import x10.extension.X10Ext_c;
import x10.util.AnnotationUtils;
import x10.util.CollectionFactory;
import polyglot.visit.ContextVisitor;
import polyglot.visit.NodeVisitor;
import x10.ast.Closure;
import x10.ast.ClosureCall;
import x10.ast.TypeParamNode;
import x10.ast.X10Call;
import x10.ast.X10ClassDecl;
import x10.ast.X10ConstructorDecl;
import x10.ast.X10Formal;
import x10.ast.X10MethodDecl;
import x10.types.ClosureDef;
import x10.types.ParameterType;
import x10.types.ThisInstance;
import x10.types.X10ClassDef;
import x10.types.X10ClassType;
import x10.types.X10CodeDef;
import x10.types.X10ConstructorDef;
import x10.types.X10FieldDef;
import x10.types.X10FieldInstance;
import x10.types.X10LocalDef;
import x10.types.X10LocalInstance;
import x10.types.X10MethodDef;
import x10.types.constraints.TypeConstraint;
import x10cpp.visit.ASTQuery;
public class ClosureRemover extends ContextVisitor {
public static final String STATIC_NESTED_CLASS_BASE_NAME = "$Closure";
private static final String STATIC_METHOD_BASE_NAME = "$closure_apply";
private static final Name OUTER_NAME = Name.make("out$$");
private final TypeSystem xts;
private final NodeFactory xnf;
public ClosureRemover(Job job, TypeSystem ts, NodeFactory nf) {
super(job, ts, nf);
xts = ts;
xnf = nf;
}
@Override
protected Node leaveCall(Node parent, Node old, Node n, NodeVisitor v) throws SemanticException {
if (n instanceof ClassDecl) {
ClassDecl cd = (ClassDecl) n;
final X10ClassDef def = (X10ClassDef) cd.classDef();
final List<ClassMember> nmembers = new ArrayList<ClassMember>();
// closure -> static method
cd = (ClassDecl) cd.visitChildren(createClosureToStaticMethodVisitor(def, nmembers));
// XTENLANG-3083
ClassBody body2 = cd.body();
nmembers.addAll(0, body2.members());
cd = cd.body(body2.members(nmembers));
nmembers.clear();
// closure -> static nested class
cd = (ClassDecl) cd.visitChildren(createClosureToStaticNestedClassVisitor(def, nmembers));
ClassBody body = cd.body();
nmembers.addAll(0, body.members());
return ((ClassDecl) n).body(body.members(nmembers));
}
return n;
}
private ContextVisitor createClosureToStaticMethodVisitor(final X10ClassDef def, final List<ClassMember> nmembers) {
return new ContextVisitor(job,ts,nf){
protected Node leaveCall(Node parent, Node old, Node n, NodeVisitor v) throws SemanticException {
if (n instanceof ClosureCall) {
ClosureCall cc = (ClosureCall) n;
Expr target = cc.target();
if (target instanceof Closure) {
final Position pos = Position.COMPILER_GENERATED;
Flags flags = Flags.STATIC.Final().Private();
Closure cl = (Closure) target;
ClosureDef cld = cl.closureDef();
Name name = Name.makeFresh(STATIC_METHOD_BASE_NAME);
List<VarInstance<? extends VarDef>> capturedEnv = cld.capturedEnvironment();
// DEBUG
// System.out.println(n.position() + " " + name + " " + cl);
// System.out.println(capturedEnv);
final List<NamedVariable> capturedVarsExThis = new ArrayList<NamedVariable>();
Map<String, X10LocalDef> nameToLocalDef = CollectionFactory.newHashMap();
Block body = rewriteClosureBody(cl.body(), capturedEnv, capturedVarsExThis, nameToLocalDef, cl.formals());
List<Ref<? extends Type>> argTypes = new ArrayList<Ref<? extends Type>>(cl.formals().size());
for (Formal f : cl.formals()) {
Type t = f.type().type();
argTypes.add(f.type().typeRef());
}
List<Expr> arguments = new ArrayList<Expr>(cc.arguments());
List<Formal> formals = new ArrayList<Formal>(cl.formals());
for (VarInstance<? extends VarDef> vi : capturedEnv) {
if (vi instanceof ThisInstance) {
// copy type parameters of def to type as a workaround for missing type arguments in the type of ThisInstance.
Type viType = null;
// viType = vi.type();
X10ClassType defType = def.asType();
List<ParameterType> defTypeParameters = def.typeParameters();
if (defTypeParameters != null && defTypeParameters.size() > 0) {
defType = defType.typeArguments(new ArrayList<Type>(defTypeParameters));
}
viType = defType;
arguments.add(xnf.This(pos).type(viType));
argTypes.add(Types.ref(viType));
X10LocalDef li = xts.localDef(pos, Flags.FINAL, Types.ref(viType), OUTER_NAME);
formals.add(xnf.Formal(pos, xnf.FlagsNode(pos, Flags.FINAL), xnf.CanonicalTypeNode(pos, Types.ref(viType)), xnf.Id(pos, OUTER_NAME)).localDef(li));
}
}
for (NamedVariable vn : capturedVarsExThis) {
Name name2 = vn.name().id();
X10LocalDef li;
if (vn instanceof Local) {
li = (X10LocalDef) vn.varInstance().def();
}
else {
li = nameToLocalDef.get(name2.toString());
}
arguments.add(vn);
argTypes.add(Types.ref(vn.type()));
formals.add(xnf.Formal(pos, xnf.FlagsNode(pos, Flags.FINAL), xnf.CanonicalTypeNode(pos, Types.ref(vn.type())), xnf.Id(pos, vn.name().id())).localDef(li));
}
List<ParameterType> rts = new ArrayList<ParameterType>();
List<TypeNode> tns = new ArrayList<TypeNode>();
List<TypeParamNode> tps = new ArrayList<TypeParamNode>();
if (!context.currentCode().staticContext()) {
List<ParameterType> mtps = context.currentClassDef().typeParameters();
if (mtps != null) {
for (ParameterType t : mtps) {
ParameterType pt = (ParameterType) t;
rts.add(pt);
tns.add(xnf.X10CanonicalTypeNode(pos, pt));
tps.add(xnf.TypeParamNode(pos, xnf.Id(pos, pt.name())).type(pt));
}
}
}
if (!(context.currentCode() instanceof X10ConstructorDef)) {
List<ParameterType> codeParam = getCurrentCodeParameterType(context);
for (ParameterType pt :codeParam) {
boolean contains = false;
for (ParameterType pt2: context.currentClassDef().typeParameters()) {
if (pt.def().equals(pt2.def())) {
contains = true;
break;
}
}
if (!contains) {
rts.add(pt);
tns.add(xnf.X10CanonicalTypeNode(pos, pt));
tps.add(xnf.TypeParamNode(pos, xnf.Id(pos, pt.name())).type(pt));
}
}
}
ClassType ct = def.asType();
X10MethodDef md = (X10MethodDef) xts.methodDef(pos, pos, Types.ref(ct), flags, cld.returnType(), name, rts, argTypes, Collections.<Ref<? extends Type>>emptyList(), ct.def().thisDef(), cld.formalNames(), cld.guard(), cld.typeGuard(), cld.offerType(), null);
X10MethodDecl mdcl = xnf.X10MethodDecl(pos, xnf.FlagsNode(pos, flags), cl.returnType(), xnf.Id(pos, name), tps, formals, null, null, Collections.<TypeNode>emptyList(), body);
nmembers.add(mdcl.methodDef(md));
X10Call x10call = (X10Call) xnf.Call(n.position(), xnf.CanonicalTypeNode(n.position(), ct), xnf.Id(n.position(), name), arguments).methodInstance(md.asInstance()).type(cl.returnType().type());
x10call = x10call.typeArguments(tns);
return x10call;
}
}
return n;
}
private Block rewriteClosureBody(Block closureBody,final List<VarInstance<? extends VarDef>> capturedEnv, final List<NamedVariable> capturedVarsExThis, final Map<String, X10LocalDef> nameToLocalDef, final List<Formal> formals) {
final Position pos = Position.COMPILER_GENERATED;
return (Block) closureBody.visit(new ContextVisitor(job, ts, nf){
public Node override(Node parent, Node n) {
if (n instanceof Closure) {
return n;
}
return null;
};
protected Node leaveCall(Node parent, Node old, Node n, NodeVisitor v) throws SemanticException {
if (n instanceof Field) {
Field field = (Field) n;
// XTENLANG-2927: Only fields of this, which is captured as out$, are captured and translated.
if (!(field.target() instanceof Field && ((Field) field.target()).name().id().equals(OUTER_NAME))) {
return n;
}
for (VarInstance<? extends VarDef> var : capturedEnv) {
if (!var.flags().isFinal()) {
continue;
}
// because of coming not the same VarInstance
if (var.def().equals(field.fieldInstance().def())) {
Receiver target = field.target();
if (target instanceof Local) {
for (Formal formal : formals) {
if (formal.name() != null && ((Local) target).name().id().equals(formal.name().id())) {
return n;
}
}
}
X10LocalDef li;
if (!contains(capturedVarsExThis, var.def())) {
capturedVarsExThis.add((NamedVariable) old);
li = xts.localDef(pos, Flags.FINAL, Types.ref(var.type()), var.name());
nameToLocalDef.put(var.name().toString(), li);
} else {
li = nameToLocalDef.get(var.name().toString());
}
return xnf.Local(pos, xnf.Id(pos, var.name())).localInstance(li.asInstance()).type(var.type());
}
}
return field.targetImplicit(false);
}
if (n instanceof Local) {
Local local = (Local) n;
for (VarInstance<? extends VarDef> var : capturedEnv) {
if (var.def().equals(local.localInstance().def())) {
if (!contains(capturedVarsExThis, var.def())) {
capturedVarsExThis.add((NamedVariable) old);
return n;
}
}
}
return n;
}
if (n instanceof Special) {
Special special = (Special) n;
if (special.kind() == Special.THIS) {
X10LocalDef li = xts.localDef(pos, Flags.FINAL, Types.ref(special.type()), OUTER_NAME);
return ((Local) xnf.Local(pos, xnf.Id(pos, OUTER_NAME)).type(special.type())).localInstance(li.asInstance());
}
}
return n;
};
}.context(context));
}
}.context(context);
}
private ContextVisitor createClosureToStaticNestedClassVisitor(final X10ClassDef def,final List<ClassMember> nmembers) {
return new ContextVisitor(job, ts, nf) {
@Override
public Node leaveCall(Node parent, Node old, Node n, NodeVisitor v) throws SemanticException {
// TODO handle "this" in type constraints
if (n instanceof Closure) {
Closure cl = (Closure) n;
ClosureDef cld = cl.closureDef();
final Position pos = Position.COMPILER_GENERATED;
Flags privateStatic = Flags.PRIVATE.Static().Final();
final List<VarInstance<? extends VarDef>> capturedEnv = cld.capturedEnvironment();
Block closureBody = (Block) cl.body();
List<X10ClassType> riAnnotations = AnnotationUtils.annotationsMatching(closureBody, xts.RemoteInvocation());
Id staticNestedClassName = null;
if (!riAnnotations.isEmpty()) {
assert riAnnotations.size() == 1;
String suffix = ASTQuery.getStringPropertyInit(riAnnotations.get(0), 0);
if (suffix != null) {
staticNestedClassName = xnf.Id(pos, STATIC_NESTED_CLASS_BASE_NAME + "_"+suffix);
}
}
if (null == staticNestedClassName) {
staticNestedClassName = xnf.Id(pos, UniqueID.newID(STATIC_NESTED_CLASS_BASE_NAME));
}
// DEBUG
// System.out.println(n.position() + " " + staticNestedClassName + " " + cl);
// System.out.println(capturedEnv);
// create class def for static nested
final X10ClassDef staticNestedClassDef = (X10ClassDef) xts.createClassDef();
//[DC] i assume simply not setting a supertype is OK. This is how Object was defined I think.
//staticNestedClassDef.superType(Types.ref(xts.Object()));
staticNestedClassDef.kind(ClassDef.MEMBER);
staticNestedClassDef.name(staticNestedClassName.id());
staticNestedClassDef.outer(Types.ref(def));
staticNestedClassDef.setPackage(Types.ref(context.package_()));
staticNestedClassDef.flags(privateStatic);
staticNestedClassDef.setInterfaces(cld.classDef().interfaces());
staticNestedClassDef.setThisDef(ts.thisDef(pos, Types.ref(staticNestedClassDef.asType())));
// TODO set method bounds?
if (context.currentCode().staticContext()) {
staticNestedClassDef.setTypeBounds(Types.ref(new TypeConstraint()));
}
else {
for (ParameterType pt :def.typeParameters()) {
staticNestedClassDef.addTypeParameter(pt, pt.getVariance());
}
staticNestedClassDef.setTypeBounds(def.typeBounds());
}
List<ParameterType> codeParam = null;
if (!(context.currentCode() instanceof X10ConstructorDef)) {
codeParam = getCurrentCodeParameterType(context);
for (ParameterType pt :codeParam) {
boolean contains = false;
for (ParameterType pt2: staticNestedClassDef.typeParameters()) {
if (pt.def().equals(pt2.def())) {
contains = true;
break;
}
}
if (!contains) {
staticNestedClassDef.addTypeParameter(pt, pt.getVariance());
}
}
}
// TODO handle "this" in type constraints
X10MethodDef closureMethodDef = xts.methodDef(pos, pos, Types.ref(staticNestedClassDef.asType()), Flags.PUBLIC, cld.returnType(), ClosureCall.APPLY, Collections.<ParameterType>emptyList(), cld.formalTypes(), Collections.<Ref<? extends Type>>emptyList(), staticNestedClassDef.thisDef(), cld.formalNames(), cld.guard(), cld.typeGuard(), cld.offerType(), null);
staticNestedClassDef.setMethods(Collections.singletonList(closureMethodDef));
// create class decl
List<TypeNode> interfaces = new ArrayList<TypeNode>();
List<Type> cint = cld.asType().interfaces();
for (Type it : cint) {
interfaces.add(xnf.X10CanonicalTypeNode(pos, it));
}
X10ClassDecl staticNestedClassDecl = (X10ClassDecl) xnf.ClassDecl(pos, xnf.FlagsNode(pos, privateStatic), staticNestedClassName, null, interfaces, xnf.ClassBody(pos, Collections.<ClassMember>emptyList()));
// Copy over the annotations from the closure. These annotations are needed for dealing with GENERAL asyncs and SIMPLE asyncs
X10Ext_c ext = (X10Ext_c) cl.ext();
List<AnnotationNode> annotations = ext.annotations();
staticNestedClassDecl = (X10ClassDecl) ((X10Ext_c) staticNestedClassDecl.ext()).annotations(annotations);
List<TypeParamNode> tpns = new ArrayList<TypeParamNode>();
for (ParameterType pt : staticNestedClassDef.typeParameters()) {
tpns.add(xnf.TypeParamNode(pos, xnf.Id(pos, pt.name()), pt.getVariance()).type(pt));
}
staticNestedClassDecl = staticNestedClassDecl.typeParameters(tpns);
final List<NamedVariable> capturedVarsExThis = new ArrayList<NamedVariable>();
Map<VarDef, X10FieldDef> nameToLocalDef = CollectionFactory.newHashMap();
// rewrite closure method body
closureBody = rewriteClosureBody(closureBody, staticNestedClassDef, capturedEnv, capturedVarsExThis, nameToLocalDef, cl.formals());
MethodDecl mdcl = xnf.MethodDecl(pos, xnf.FlagsNode(pos, Flags.PUBLIC), xnf.CanonicalTypeNode(pos, Types.baseType(cl.returnType().type())), xnf.Id(pos, ClosureCall.APPLY), cl.formals(), closureBody).methodDef(closureMethodDef);
mdcl = (MethodDecl) mdcl.body(closureBody);
mdcl = (MethodDecl) mdcl.typeCheck(this);
ClassBody body = xnf.ClassBody(pos, Collections.<ClassMember>singletonList(mdcl));
// Copy over the annotations from the closure body. These annotations are needed for dealing with GENERAL asyncs and SIMPLE asyncs
ext = (X10Ext_c) cl.body().ext();
annotations = ext.annotations();
body = (ClassBody) ((X10Ext_c)body.ext()).annotations(annotations);
staticNestedClassDecl = staticNestedClassDecl.body(body);
// add constructor
List<ClassMember> cm = new ArrayList<ClassMember>(staticNestedClassDecl.body().members());
List<Formal> formals = new ArrayList<Formal>(capturedEnv.size());
List<Ref<? extends Type>> argTypes = new ArrayList<Ref<? extends Type>>(capturedEnv.size());
List<LocalDef> formalNames = new ArrayList<LocalDef>(capturedEnv.size());
List<Expr> args = new ArrayList<Expr>(capturedEnv.size());
Block body2 = xnf.Block(pos);
for (VarInstance<? extends VarDef> vi : capturedEnv) {
if (vi instanceof ThisInstance || (vi instanceof FieldInstance && !vi.flags().isFinal())) { // the latter means the receiver fo vi should be this
Name name = OUTER_NAME;
X10FieldDef fi = nameToLocalDef.get(vi.def());
if (fi == null) { // "this" or a field of "this" is "captured", but never accessed -- skip
continue;
}
// copy type parameters of def to type as a workaround for missing type arguments in the type of ThisInstance.
Type viType = null;
if (vi instanceof ThisInstance) {
X10ClassType defType = def.asType();
List<ParameterType> defTypeParameters = def.typeParameters();
if (defTypeParameters != null && defTypeParameters.size() > 0) {
defType = defType.typeArguments(new ArrayList<Type>(defTypeParameters));
}
viType = defType;
} else {
viType = vi.type();
}
X10LocalDef li = xts.localDef(pos, Flags.FINAL, Types.ref(viType), name);
X10Formal formal = xnf.Formal(pos, xnf.FlagsNode(pos, Flags.FINAL), xnf.X10CanonicalTypeNode(pos, Types.baseType(viType)), xnf.Id(pos, name)).localDef(li);
formals.add(formal);
formalNames.add(li);
argTypes.add(Types.ref(viType));
args.add(createExpr(pos, vi));
staticNestedClassDef.addField(fi);
FieldDecl fdcl = xnf.FieldDecl(pos, xnf.FlagsNode(pos, Flags.FINAL.Private()), xnf.X10CanonicalTypeNode(pos, viType), xnf.Id(pos, name));
cm.add(fdcl.fieldDef(fi));
Expr fa = xnf.FieldAssign(pos, xnf.This(pos).type(staticNestedClassDef.asType()), xnf.Id(pos, name), Assign.ASSIGN, xnf.Local(pos, xnf.Id(pos, name)).localInstance(li.asInstance()).type(viType)).fieldInstance(fi.asInstance()).type(Types.get(fi.type()));
body2 = body2.append(xnf.Eval(pos, fa));
break;
}
}
for (NamedVariable vn : capturedVarsExThis) {
Name name = vn.name().id();
X10LocalDef li = xts.localDef(pos, Flags.FINAL, Types.ref(vn.type()), vn.name().id());
X10Formal formal = xnf.Formal(pos, xnf.FlagsNode(pos, Flags.FINAL), xnf.X10CanonicalTypeNode(pos, Types.baseType(vn.type())), xnf.Id(pos, name)).localDef(li);
formals.add(formal);
argTypes.add(li.type());
args.add(vn);
X10FieldDef fd = nameToLocalDef.get(vn.varInstance().def());
assert (fd != null);
staticNestedClassDef.addField(fd);
FieldDecl fdcl = xnf.FieldDecl(pos, xnf.FlagsNode(pos, fd.flags()), xnf.X10CanonicalTypeNode(pos, vn.type()), xnf.Id(pos, name));
cm.add(fdcl.fieldDef(fd));
Expr fa = xnf.FieldAssign(pos, xnf.This(pos).type(staticNestedClassDef.asType()), xnf.Id(pos, name), Assign.ASSIGN, xnf.Local(pos, xnf.Id(pos, name)).localInstance(li.asInstance()).type(vn.type())).fieldInstance(fd.asInstance()).type(Types.get(fd.type()));
body2 = body2.append(xnf.Eval(pos, fa));
}
X10ConstructorDecl consdcl = (X10ConstructorDecl) xnf.ConstructorDecl(pos, xnf.FlagsNode(pos, Flags.PRIVATE), staticNestedClassDecl.name(), formals, body2);
consdcl = consdcl.typeParameters(Collections.<TypeParamNode>emptyList());
CanonicalTypeNode typeNode = xnf.CanonicalTypeNode(pos, staticNestedClassDef.asType());
consdcl = consdcl.returnType(typeNode);
List<Type> typeArgs = new ArrayList<Type>(staticNestedClassDef.typeParameters());
X10ClassType staticNestedClassType = staticNestedClassDef.asType().typeArguments(typeArgs);
X10ConstructorDef consd = xts.constructorDef(pos, pos,
Types.ref(staticNestedClassType),
Flags.PRIVATE,
Types.ref(staticNestedClassType),
argTypes,
Collections.<Ref<? extends Type>>emptyList(),
staticNestedClassDef.thisDef(),
formalNames, null, null, null);
cm.add((ClassMember) consdcl.constructorDef(consd).typeCheck(this));
staticNestedClassDef.addConstructor(consd);
staticNestedClassDecl = staticNestedClassDecl.classDef(staticNestedClassDef);
ClassBody cb = staticNestedClassDecl.body();
nmembers.add((ClassMember) staticNestedClassDecl.body(cb.members(cm)).typeCheck(this));
return xnf.New(pos, xnf.CanonicalTypeNode(pos, Types.ref(staticNestedClassType)), args).constructorInstance(consd.asInstance()).type(staticNestedClassType);
}
return n;
}
private Block rewriteClosureBody(Block closureBody,
final X10ClassDef staticNestedClassDef,
final List<VarInstance<? extends VarDef>> capturedEnv,
final List<NamedVariable> capturedVarsExThis,
final Map<VarDef, X10FieldDef> nameToFieldDef,
final List<Formal> formals
) {
final Position pos = Position.COMPILER_GENERATED;
return (Block) closureBody.visit(new ContextVisitor(job, ts, nf){
protected Node leaveCall(Node parent, Node old, Node n, NodeVisitor v) throws SemanticException {
if (n instanceof Field) {
Field field = (Field) n;
// XTENLANG-2927: Only fields of this, which is captured as out$, are captured and translated.
if (!(field.target() instanceof Field && ((Field) field.target()).name().id().equals(OUTER_NAME))) {
return n;
}
for (VarInstance<? extends VarDef> var : capturedEnv) {
if (!var.flags().isFinal()) {
continue;
}
// because of coming not the same VarInstance
if (var.def().equals(field.fieldInstance().def())) {
Receiver target = field.target();
if (target instanceof Local) {
// XTENLANG-2359
// for (Formal formal : formals) {
// if (formal.name() != null && ((Local) target).name().id().equals(formal.name().id())) {
return n;
// }
// }
}
X10FieldDef fd;
if (!contains(capturedVarsExThis, var.def())) {
capturedVarsExThis.add((NamedVariable) old);
Flags ff = Flags.FINAL.Private();
if (field.flags().isTransient()) {
ff = ff.Transient();
}
fd = xts.fieldDef(pos, Types.ref(staticNestedClassDef.asType()), ff, Types.ref(field.type()), field.name().id());
nameToFieldDef.put(var.def(), fd);
} else {
fd = nameToFieldDef.get(var.def());
}
return xnf.Field(pos, xnf.This(pos).type(staticNestedClassDef.asType()), xnf.Id(pos, fd.name())).fieldInstance(fd.asInstance()).type(var.type());
}
}
return field.targetImplicit(false);
}
if (n instanceof Local) {
Local local = (Local) n;
for (VarInstance<? extends VarDef> var : capturedEnv) {
if (var.def().equals(local.localInstance().def())) {
X10FieldDef fd;
if (!contains(capturedVarsExThis, var.def())) {
capturedVarsExThis.add((NamedVariable) old);
Flags ff = Flags.FINAL.Private();
if (local.flags().isTransient()) {
ff = ff.Transient();
}
fd = xts.fieldDef(pos, Types.ref(staticNestedClassDef.asType()), ff, Types.ref(local.type()), local.name().id());
nameToFieldDef.put(var.def(), fd);
} else {
fd = nameToFieldDef.get(var.def());
}
return xnf.Field(pos, xnf.This(pos).type(staticNestedClassDef.asType()), xnf.Id(pos, fd.name())).fieldInstance(fd.asInstance()).type(var.type());
}
}
return n;
}
// this => out$
if (n instanceof Special) {
Special special = (Special) n;
if (special.kind() == Special.THIS) {
Type type = Types.baseType(special.type());
X10FieldDef fi = nameToFieldDef.get(special.type().toClass().def().thisDef());
if (fi == null) {
fi = xts.fieldDef(pos, Types.ref(staticNestedClassDef.asType()), Flags.PRIVATE.Final(), Types.ref(type), OUTER_NAME);
nameToFieldDef.put(special.type().toClass().def().thisDef(), fi);
}
return xnf.Field(pos, xnf.This(pos).type(staticNestedClassDef.asType()), xnf.Id(pos, OUTER_NAME)).fieldInstance(fi.asInstance()).type(type);
}
}
return n;
};
}.context(context));
}
}.context(context);
}
private static boolean contains(List<NamedVariable> capturedVars, VarDef def) {
for (NamedVariable nv : capturedVars) {
if (nv.varInstance().def().equals(def)) {
return true;
}
}
return false;
}
private List<ParameterType> getCurrentCodeParameterType(Context context) {
X10CodeDef codeDef = (X10CodeDef) context.currentCode();
if (!(codeDef instanceof ClosureDef)) {
return codeDef.typeParameters();
}
return getCurrentCodeParameterType(context.pop());
}
private Expr createExpr(Position pos, VarInstance<? extends VarDef> vi) {
if (vi instanceof X10LocalInstance) {
return xnf.Local(pos, xnf.Id(pos, vi.name())).localInstance((LocalInstance) vi.def().asInstance()).type(vi.type());
} else if (vi instanceof X10FieldInstance) {
return xnf.Field(pos, xnf.This(pos).type(((X10FieldInstance) vi).container()), xnf.Id(pos, vi.name())).fieldInstance((FieldInstance) vi.def().asInstance()).type(vi.type());
} else if (vi instanceof ThisInstance) {
return xnf.This(pos).type(vi.type());
}
throw new InternalCompilerError("");//TODO
}
}