/*
* 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.ast;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import polyglot.ast.AmbTypeNode;
import polyglot.ast.CanonicalTypeNode;
import polyglot.ast.ClassBody;
import polyglot.ast.Expr;
import polyglot.ast.New;
import polyglot.ast.New_c;
import polyglot.ast.Node;
import polyglot.ast.NodeFactory;
import polyglot.ast.TypeNode;
import polyglot.ast.ProcedureCall;
import polyglot.types.ClassDef;
import polyglot.types.ClassType;
import polyglot.types.CodeDef;
import polyglot.types.ConstructorDef;
import polyglot.types.ConstructorInstance;
import polyglot.types.Context;
import polyglot.types.Flags;
import polyglot.types.Matcher;
import polyglot.types.Name;
import polyglot.types.QName;
import polyglot.types.Ref;
import polyglot.types.SemanticException;
import polyglot.types.Type;
import polyglot.types.TypeSystem;
import polyglot.types.Types;
import polyglot.util.CodeWriter;
import polyglot.util.CollectionUtil; import x10.util.CollectionFactory;
import polyglot.util.InternalCompilerError;
import polyglot.util.Pair;
import polyglot.util.Position;
import polyglot.util.TypedList;
import polyglot.visit.ContextVisitor;
import polyglot.visit.NodeVisitor;
import polyglot.visit.PrettyPrinter;
import polyglot.visit.TypeBuilder;
import polyglot.visit.TypeChecker;
import x10.types.constraints.ConstraintManager;
import x10.constraint.XVar;
import x10.errors.Errors;
import x10.errors.Warnings;
import x10.extension.X10Del;
import x10.extension.X10Del_c;
import x10.extension.X10Ext;
import x10.types.ConstrainedType;
import x10.types.ParameterType;
import x10.types.ThisDef;
import x10.types.TypeParamSubst;
import x10.types.X10ClassDef;
import x10.types.X10ClassType;
import x10.types.X10ConstructorInstance;
import x10.types.X10MemberDef;
import polyglot.types.Context;
import x10.types.X10ParsedClassType;
import polyglot.types.TypeSystem;
import polyglot.types.ProcedureDef;
import polyglot.types.ProcedureInstance;
import polyglot.types.TypeSystem_c;
import polyglot.types.NoMemberException;
import x10.types.checker.Converter;
import x10.types.checker.PlaceChecker;
import x10.types.constraints.CConstraint;
import x10.types.constraints.TypeConstraint;
import x10.visit.X10TypeChecker;
/**
* new C[T](e)
*
* @author nystrom
*/
public class X10New_c extends New_c implements X10New {
public X10New_c(Position pos, boolean newOmitted, Expr qualifier, TypeNode tn, List<TypeNode> typeArguments, List<Expr> arguments, ClassBody body) {
super(pos, qualifier, tn, arguments, body);
this.typeArguments = TypedList.copyAndCheck(typeArguments, TypeNode.class, true);
this.newOmitted = newOmitted;
}
private boolean newOmitted = false;
public boolean newOmitted() {
return newOmitted;
}
public X10New newOmitted(boolean val) {
X10New_c n = (X10New_c) copy();
n.newOmitted = val;
return n;
}
@Override
public Node visitChildren(NodeVisitor v) {
Expr qualifier = (Expr) visitChild(this.qualifier, v);
TypeNode tn = (TypeNode) visitChild(this.tn, v);
List<TypeNode> typeArguments = visitList(this.typeArguments, v);
List<Expr> arguments = visitList(this.arguments, v);
ClassBody body = (ClassBody) visitChild(this.body, v);
X10New_c n = (X10New_c) typeArguments(typeArguments);
Node result = n.reconstruct(qualifier, tn, arguments, body);
return result;
}
@Override
public X10New anonType(X10ClassDef anonType) {
return super.anonType(anonType);
}
@Override
public X10New arguments(List<Expr> arguments) {
return (X10New) super.arguments(arguments);
}
@Override
public X10New body(ClassBody body) {
return (X10New) super.body(body);
}
@Override
public X10New constructorInstance(ConstructorInstance ci) {
return (X10New) super.constructorInstance(ci);
}
@Override
public X10New objectType(TypeNode tn) {
return (X10New) super.objectType(tn);
}
@Override
public X10New qualifier(Expr qualifier) {
return (X10New) super.qualifier(qualifier);
}
@Override
public Node buildTypesOverride(TypeBuilder tb) {
X10New_c n = (X10New_c) super.buildTypesOverride(tb);
List<TypeNode> typeArgs = n.visitList(n.typeArguments(), tb);
n = (X10New_c) n.typeArguments(typeArgs);
n = (X10New_c) X10Del_c.visitAnnotations(n, tb);
return n;
}
List<TypeNode> typeArguments;
public List<TypeNode> typeArguments() {
return typeArguments;
}
public X10New typeArguments(List<TypeNode> args) {
if (args == this.typeArguments) return this;
X10New_c n = (X10New_c) copy();
n.typeArguments = new ArrayList<TypeNode>(args);
return n;
}
@Override
protected X10New_c typeCheckHeader(TypeChecker childtc) {
X10New_c n = (X10New_c) super.typeCheckHeader(childtc);
List<TypeNode> typeArguments = visitList(n.typeArguments(), childtc);
n = (X10New_c) n.typeArguments(typeArguments);
if (n.body() != null) {
Ref<? extends Type> ct = n.objectType().typeRef();
ClassDef anonType = n.anonType();
assert anonType != null;
TypeSystem ts = (TypeSystem) childtc.typeSystem();
Flags flags = ct.get().toClass().flags();
if (!flags.isInterface()) {
anonType.superType(ct);
}
else /*if (flags.isValue()) {
anonType.superType(Types.<Type> ref(ts.Value()));
anonType.setInterfaces(Collections.<Ref<? extends Type>> singletonList(ct));
}
else */{
// [DC] null means it's a new root in the object hierarchy (no more x10.lang.Object)
anonType.superType(null);
anonType.setInterfaces(Collections.<Ref<? extends Type>> singletonList(ct));
}
assert anonType.interfaces().size() <= 1;
}
return n;
}
@Override
public Node typeCheckOverride(Node parent, ContextVisitor tc) {
Node n = super.typeCheckOverride(parent, tc);
NodeVisitor childtc = tc.enter(parent, n);
List<AnnotationNode> oldAnnotations = ((X10Ext) ext()).annotations();
if (oldAnnotations == null || oldAnnotations.isEmpty()) {
return n;
}
List<AnnotationNode> newAnnotations = node().visitList(oldAnnotations, childtc);
if (! CollectionUtil.allEqual(oldAnnotations, newAnnotations)) {
return ((X10Del) n.del()).annotations(newAnnotations);
}
return n;
}
/**
* @param ar
* @param ct
*/
protected X10New findQualifier(TypeChecker ar, ClassType ct) {
// If we're instantiating a non-static member class, add a "this"
// qualifier.
NodeFactory nf = ar.nodeFactory();
TypeSystem ts = ar.typeSystem();
Context c = ar.context();
// Search for the outer class of the member. The outer class is
// not just ct.outer(); it may be a subclass of ct.outer().
Type outer = null;
Name name = ct.name();
ClassType t = c.currentClass();
// We're in one scope too many.
if (t == anonType) {
t = (ClassType) t.container();
}
// Search all enclosing classes for the type.
while (t != null) {
try {
Type mt = ts.findMemberType(t, name, c);
if (mt instanceof ClassType) {
ClassType cmt = (ClassType) mt;
if (cmt.def() == ct.def()) {
outer = t;
break;
}
}
}
catch (SemanticException e) {
}
t = t.outer();
}
if (outer == null) {
Errors.issue(ar.job(),
new Errors.CouldNotFindNonStaticMemberClass(name, position()));
outer = c.currentClass();
}
// Create the qualifier.
Expr q;
Position cg = Position.compilerGenerated(position());
if (outer.typeEquals(c.currentClass(), ar.context())) {
q = nf.This(cg);
}
else {
q = nf.This(cg, nf.CanonicalTypeNode(cg, outer));
}
q = q.type(outer);
return qualifier(q);
}
protected Name getName(TypeNode tn) {
if (tn instanceof CanonicalTypeNode) {
if (tn.type().isClass()) {
return tn.type().toClass().name();
} else {
return null;
}
}
if (tn instanceof AmbTypeNode) {
return ((AmbTypeNode) tn).name().id();
}
if (tn instanceof AmbDepTypeNode) {
return getName(((AmbDepTypeNode) tn).base());
}
return null;
}
public X10New_c typeCheckObjectType(TypeChecker childtc) {
NodeFactory nf = (NodeFactory) childtc.nodeFactory();
TypeSystem ts = childtc.typeSystem();
Context c = childtc.context();
X10New_c n = this;
// Override to associate the type args with the type rather than with
// the constructor.
Expr qualifier = n.qualifier;
TypeNode tn = n.tn;
List<Expr> arguments = n.arguments;
ClassBody body = n.body;
List<TypeNode> typeArguments = n.typeArguments;
typeArguments = n.visitList(typeArguments, childtc);
qualifier = (Expr) n.visitChild(qualifier, childtc);
if (!(tn instanceof CanonicalTypeNode)) {
Name name = getName(tn);
Type t;
if (qualifier == null) {
if (typeArguments.size() > 0) {
if (tn instanceof AmbTypeNode) {
AmbTypeNode atn = (AmbTypeNode) tn;
tn = nf.AmbDepTypeNode(atn.position(), atn.prefix(), atn.name(), typeArguments, Collections.<Expr>emptyList(), null);
tn = tn.typeRef(atn.typeRef());
}
}
tn = (TypeNode) n.visitChild(tn, childtc);
t = tn.type();
}
else {
if (!(tn instanceof AmbTypeNode) || ((AmbTypeNode) tn).prefix() != null) {
Errors.issue(childtc.job(),
new Errors.OnlySimplyNameMemberClassMayBeInstantiated(tn.position()));
}
if (!qualifier.type().isClass()) {
Errors.issue(childtc.job(),
new Errors.CannotInstantiateMemberClass(n.position()));
}
tn = nf.CanonicalTypeNode(tn.position(), tn.typeRef());
// We have to disambiguate the type node as if it were a member of
// the static type, outer, of the qualifier.
try {
t = ts.findMemberType(Types.baseType(qualifier.type()), name, c);
} catch (SemanticException e) {
t = ts.unknownType(tn.position());
if (!qualifier.type().isClass()) {
qualifier = null; // will fake it
}
}
}
t = ts.expandMacros(t);
CConstraint xc = Types.xclause(t);
t = Types.baseType(t);
if (!(t instanceof X10ClassType)) {
if (name == null)
name = Name.makeFresh();
QName outer = qualifier == null ? null : qualifier.type().toClass().fullName();
QName qname = QName.make(outer, name);
t = ts.createFakeClass(qname, new Errors.CannotInstantiateType(tn.type(), position()));
}
X10ClassType ct = (X10ClassType) t;
if (qualifier == null && ct.isMember() && !ct.flags().isStatic()) {
final X10New_c newC = (X10New_c) n.objectType(tn);
X10New k = newC.findQualifier(childtc, ct);
tn = k.objectType();
qualifier = (Expr) k.visitChild(k.qualifier(), childtc);
}
/*
if (typeArguments.size() > 0) {
List<Type> typeArgs = new ArrayList<Type>(typeArguments.size());
for (TypeNode tan : typeArguments) {
typeArgs.add(tan.type());
}
if (typeArgs.size() != ct.x10Def().typeParameters().size()) {
Errors.issue(childtc.job(),
new Errors.CannotInstantiateType(ct, n.position()));
// TODO: fake missing args or delete extra args
}
// [DC] this is where the problem is! XTENLANG-3133
ct = ct.typeArguments(typeArgs);
}
*/
t = Types.xclause(ct, xc);
((Ref<Type>) tn.typeRef()).update(t);
}
n = (X10New_c) n.reconstruct(qualifier, tn, arguments, body);
// [IP] Should retain the type argument nodes, even if the type is resolved.
//n = (X10New_c) n.typeArguments(Collections.EMPTY_LIST);
return n;
}
public static interface MatcherMaker<PI> {
public Matcher<PI> matcher(Type ct, List<Type> typeArgs, List<Type> argTypes);
}
public static Pair<ConstructorInstance, List<Expr>> tryImplicitConversions(X10ProcedureCall n, ContextVisitor tc,
Type targetType, List<Type> argTypes) throws SemanticException {
final TypeSystem_c ts = (TypeSystem_c) tc.typeSystem();
final Context context = tc.context();
List<ConstructorInstance> methods = ts.findAcceptableConstructors(targetType, ts.ConstructorMatcher(targetType, Collections.EMPTY_LIST,argTypes, context, true));
return Converter.tryImplicitConversions(n, tc, targetType, methods, new MatcherMaker<ConstructorInstance>() {
public Matcher<ConstructorInstance> matcher(Type ct, List<Type> typeArgs, List<Type> argTypes) {
return ts.ConstructorMatcher(ct, argTypes, context);
}
});
}
public Node typeCheck(ContextVisitor tc) {
final TypeSystem xts = (TypeSystem) tc.typeSystem();
// ///////////////////////////////////////////////////////////////////
// Inline the super call here and handle type arguments.
// ///////////////////////////////////////////////////////////////////
// [IP] The type arguments are retained for later use.
//assert (this.typeArguments().size() == 0) : position().toString();
SemanticException error = null;
List<Type> argTypes = new ArrayList<Type>(this.arguments.size());
for (Expr e : this.arguments) {
//Type argType = PlaceChecker.ReplaceHereByPlaceTerm((Type) e.type(), (X10Context) tc.context());
Type argType = e.type();
argTypes.add(argType);
}
Position pos = position();
try {
typeCheckFlags(tc);
} catch (SemanticException e) {
Errors.issue(tc.job(), e, this);
if (error == null) { error = e; }
}
try {
typeCheckNested(tc);
} catch (SemanticException e) {
Errors.issue(tc.job(), e, this);
if (error == null) { error = e; }
}
X10New_c result = this;
Type t = result.objectType().type();
X10ClassType ct = (X10ClassType) Types.baseType(t);
X10ConstructorInstance ci;
List<Expr> args;
Pair<ConstructorInstance, List<Expr>> p = findConstructor(tc, result, ct, argTypes, result.anonType());
ci = (X10ConstructorInstance) p.fst();
args = p.snd();
if (ci.error() != null) {
Errors.issue(tc.job(), ci.error(), this);
} else if (error != null) {
ci = ci.error(error);
}
X10ParsedClassType container = (X10ParsedClassType) ci.container();
if (!ct.x10Def().typeParameters().isEmpty() && (ct.typeArguments() == null || ct.typeArguments().isEmpty())) {
t = new TypeParamSubst(xts, container.typeArguments(), container.x10Def().typeParameters()).reinstantiate(t);
result = (X10New_c) result.objectType(result.objectType().typeRef(Types.ref(t)));
}
try {
Types.checkMissingParameters(result.objectType());
} catch (SemanticException e) {
Errors.issue(tc.job(), e, result.objectType());
}
TypeSystem ts = (TypeSystem) tc.typeSystem();
Type tp = ci.returnType();
final Context context = tc.context();
tp = PlaceChecker.ReplaceHereByPlaceTerm(tp, context);
Type tp1 = Types.instantiateTypeParametersExplicitly(tp);
Type t1 = Types.instantiateTypeParametersExplicitly(t);
if (ts.hasUnknown(tp1)) {
SemanticException e = new SemanticException("Inconsistent constructor return type", pos);
Errors.issue(tc.job(), e, this);
if (ci.error() == null) {
ci = ci.error(e);
}
}
boolean doCoercion = false;
if (!ts.hasUnknown(tp) && !ts.isSubtype(tp1, t1, context)) {
Expr newNewExpr = Converter.attemptCoercion(tc, result.type(tp1), t1);
if (newNewExpr != null) {
// I cann't keep newNewExpr, because result is still going to be modified (and I cannot do this check later because ci might be modified and it is stored in result)
// so, sadly, I have to call attemptCoercion twice.
doCoercion = true;
} else {
SemanticException e = Errors.NewIncompatibleType.make(result.type(tp1), t1, tc, pos);
Errors.issue(tc.job(), e, this);
if (ci.error() == null) {
ci = ci.error(e);
}
}
}
// Copy the method instance so we can modify it.
//tp = ((X10Type) tp).setFlags(X10Flags.ROOTED);
ci = ci.returnType(tp);
ci = result.adjustCI(ci, tc, qualifier());
try {
checkWhereClause(ci, pos, context);
} catch (SemanticException e) {
if (ci.error() == null) { ci = ci.error(e); }
}
result = (X10New_c) result.constructorInstance(ci);
result = (X10New_c) result.arguments(args);
Type type = ci.returnType();
if (result.body() != null) {
// If creating an anonymous class, we need to adjust the type
// to be based on anonType rather than on the supertype.
ClassDef anonTypeDef = result.anonType();
Type anonType = anonTypeDef.asType();
type = Types.xclause(Types.baseType(anonType), Types.xclause(type));
// Capture "this" for anonymous classes in a non-static context
if (!context.inStaticContext()) {
CodeDef code = context.currentCode();
if (code instanceof X10MemberDef) {
ThisDef thisDef = ((X10MemberDef) code).thisDef();
if (null == thisDef) {
throw new InternalCompilerError(position(), "X10New_c.typeCheck: thisDef is null for containing code " +code);
}
assert (thisDef != null);
context.recordCapturedVariable(thisDef.asInstance());
}
}
}
result = (X10New_c) result.type(type);
return doCoercion ?
Converter.attemptCoercion(tc, result, t1) :
result;
}
/**
* Looks up a constructor with given name and argument types.
*/
public static Pair<ConstructorInstance,List<Expr>> findConstructor(ContextVisitor tc, X10ProcedureCall n,
Type targetType, List<Type> actualTypes) {
return findConstructor(tc, n, targetType, actualTypes, null);
}
public static Pair<ConstructorInstance,List<Expr>> findConstructor(ContextVisitor tc, X10ProcedureCall n,
Type targetType, List<Type> actualTypes, X10ClassDef anonType) {
X10ConstructorInstance ci;
TypeSystem xts = tc.typeSystem();
Context context = (Context) tc.context();
boolean haveUnknown = xts.hasUnknown(targetType);
for (Type t : actualTypes) {
if (xts.hasUnknown(t)) haveUnknown = true;
}
SemanticException error = null;
try {
return findConstructor(tc, context, n, targetType, actualTypes, anonType);
} catch (SemanticException e) {
error = e;
}
// If not returned yet, fake the constructor instance.
Collection<X10ConstructorInstance> cis = null;
try {
cis = findConstructors(tc, targetType, actualTypes);
} catch (SemanticException e) {
if (error == null) error = e;
}
// See if all matches have the same return type, and save that to avoid losing information.
Type rt = null;
if (cis != null) {
for (X10ConstructorInstance xci : cis) {
if (rt == null) {
rt = xci.returnType();
} else if (!xts.typeEquals(rt, xci.returnType(), context)) {
if (xts.typeBaseEquals(rt, xci.returnType(), context)) {
rt = Types.baseType(rt);
} else {
rt = null;
break;
}
}
}
}
if (haveUnknown)
error = new SemanticException(); // null message
ci = xts.createFakeConstructor(targetType.toClass(), Flags.PUBLIC, actualTypes, error);
if (rt != null) ci = ci.returnType(rt);
return new Pair<ConstructorInstance, List<Expr>>(ci, n.arguments());
}
private static Pair<ConstructorInstance,List<Expr>> findConstructor(ContextVisitor tc, Context xc,
X10ProcedureCall n, Type targetType, List<Type> argTypes, X10ClassDef anonType) throws SemanticException {
X10ConstructorInstance ci = null;
TypeSystem xts = (TypeSystem) tc.typeSystem();
X10ClassType ct = (X10ClassType) targetType;
try {
if (!ct.flags().isInterface()) {
Context c = tc.context();
if (anonType != null) {
c = c.pushClass(anonType, anonType.asType());
}
List<Type> typeArgs = ct.typeArguments();
if (typeArgs == null) {
typeArgs = Collections.<Type>emptyList();
}
ci = xts.findConstructor(targetType, xts.ConstructorMatcher(targetType, typeArgs, argTypes, c));
}
else {
ConstructorDef dci = xts.defaultConstructor(n.position(), n.position(), Types.<ClassType> ref(ct));
ci = (X10ConstructorInstance) dci.asInstance();
}
// Force type inference when a constructor is invoked with no type arguments from an instance method of the same class
List<Type> tas = ct.typeArguments();
List<ParameterType> tps = ct.x10Def().typeParameters();
if (!tps.isEmpty() && (tas == null || tas.isEmpty())) {
throw new Errors.TypeIsMissingParameters(ct, tps, n.position());
}
return new Pair<ConstructorInstance, List<Expr>>(ci, n.arguments());
}
catch (SemanticException e) {
e.setPosition(n.position());
// only if we didn't find any methods, try coercions.
if (!(e instanceof NoMemberException)) {
throw e;
}
// Now, try to find the method with implicit conversions, making
// them explicit.
try {
Pair<ConstructorInstance, List<Expr>> p = tryImplicitConversions(n, tc, targetType, argTypes);
return p;
}
catch (SemanticException e2) {
throw e;
}
}
//TypeSystem_c.ConstructorMatcher matcher = xts.ConstructorMatcher(targetType, argTypes, xc);
//throw new Errors.MethodOrStaticConstructorNotFound(matcher, n.position());
}
private static Collection<X10ConstructorInstance> findConstructors(ContextVisitor tc, Type targetType,
List<Type> actualTypes) throws SemanticException {
TypeSystem xts = tc.typeSystem();
Context context = (Context) tc.context();
if (targetType == null) {
// TODO
return Collections.emptyList();
}
return xts.findConstructors(targetType, xts.ConstructorMatcher(targetType, actualTypes, context));
}
private static void checkWhereClause(X10ConstructorInstance ci, Position pos, Context context) throws SemanticException {
if (ci != null) {
CConstraint guard = ci.guard();
TypeConstraint tguard = ci.typeGuard();
if ((guard != null && !guard.consistent()) || (tguard != null && !tguard.consistent(context))) {
throw new SemanticException("Constructor guard not satisfied by caller.", pos);
}
}
}
/*
* Compute the new resulting type for the method call by replacing this and
* any argument variables that occur in the rettype depclause with new
* variables whose types are determined by the static type of the receiver
* and the actual arguments to the call.
*
* Also self.$$here==here.
* Add self!=null.
*/
private X10ConstructorInstance adjustCI(X10ConstructorInstance xci, ContextVisitor tc, Expr outer) {
if (xci == null)
return (X10ConstructorInstance) this.ci;
Type type = xci.returnType();
if (outer != null) {
type = Types.addInOuterClauses(type, outer.type());
} else {
// this could still be a local class, and the outer this has to be captured.
Type baseType = Types.baseType(type);
if (baseType instanceof X10ClassType) {
X10ClassType ct = (X10ClassType) baseType;
if (ct.isLocal()) {
Type outerT = ct.outer();
CConstraint c = ConstraintManager.getConstraintSystem().makeCConstraint();
Type outerTB = Types.baseType(outerT);
if (outerTB instanceof X10ClassType) {
X10ClassType outerct = (X10ClassType) outerTB;
c.addSelfBinding(outerct.def().thisVar());
outerT = Types.xclause(outerT, c);
type = Types.addInOuterClauses(type, outerT);
}
}
}
}
TypeSystem ts = (TypeSystem) tc.typeSystem();
if (ts.isStructType(type))
return xci;
// Add self.home == here to the return type.
// Add this even in 2.1 -- the place where this object is created
// is tracked in the type through a fake field "$$here".
// This field does not exist at runtime in the object -- but that does not
// prevent the compiler from imagining that it exists.
ConstrainedType type1 = Types.toConstrainedType(type);
type1 = (ConstrainedType) PlaceChecker.AddIsHereClause(type1, tc.context());
// Add self != null
type1 = (ConstrainedType) Types.addDisBinding(type1, Types.selfVar(type1), ConstraintManager.getConstraintSystem().xnull());
if (! Types.consistent(type1))
Errors.issue(tc.job(), new Errors.InconsistentType(type1, xci.position()));
xci = (X10ConstructorInstance) xci.returnType(type1);
return xci;
}
// TODO: Move down into New_c
public void dump(CodeWriter w) {
super.dump(w);
if (ci != null) {
w.allowBreak(4, " ");
w.begin(0);
w.write("(instance " + ci + ")");
w.end();
}
w.allowBreak(4, " ");
w.begin(0);
w.write("(arguments " + arguments + ")");
w.end();
}
public void prettyPrint(CodeWriter w, PrettyPrinter tr) {
for (Iterator<AnnotationNode> i = (((X10Ext) this.ext()).annotations()).iterator(); i.hasNext(); ) {
AnnotationNode an = i.next();
an.prettyPrint(w, tr);
w.allowBreak(0, " ");
}
super.prettyPrint(w, tr);
}
}