/* * 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 x10cpp.types; /** * This class extends the X10 notion of Context to keep track of * the translation state for the C++ backend. * * @author igor * @author pvarma * @author nvk * @author Dave Cunningham * @see X10Context_c */ import java.util.ArrayList; import java.util.List; import java.util.Map; import polyglot.ast.ClassMember; import polyglot.ast.Stmt; import polyglot.types.Name; import polyglot.types.TypeSystem; import polyglot.types.VarInstance; import x10.ast.PropertyDecl; import x10.types.X10ClassDef; import x10.types.X10ClassType; import polyglot.types.Context; import x10.util.CollectionFactory; import x10.types.X10MethodDef; import x10.util.ClassifiedStream; import x10cpp.visit.ITable; public class X10CPPContext_c extends Context { // The global object is fresh for each brand new instance of the context, // but is aliased for each clone of the context (cloned via copy()). // The only thing that belongs in here is primitive data that needs a level // of indirection to allow aliasing after cloning. protected static class Global { public int closureId; } protected Global g = new Global(); public void advanceClosureId() { g.closureId++; } public int closureId() { return g.closureId; } /** * Every context has some arbitrary data, associated with string keys. * To get the data from the current context, use {@link #getData(String)}. * To find the data in the current or ancestor context, use {@link #findData(String)}. * To add data to the current context, use {@link #addData(String, Object)}. */ protected Map<String, Object> data = CollectionFactory.newHashMap(1, 1.0f); /** @see #data. */ public <T> void addData(String key, T value) { data.put(key, value); } /** @see #data. */ @SuppressWarnings("unchecked") // Casting to a generic type parameter public <T> T getData(String key) { return (T) data.get(key); } /** @see #data. */ public <T> T findData(String key) { T value = this.<T>getData(key); if (value == null && outer != null) return ((X10CPPContext_c) outer).<T>findData(key); return value; } protected ArrayList<ClassMember> pendingStaticDecls; protected ArrayList<PropertyDecl> classProperties; public List<PropertyDecl> classProperties() { return classProperties; } public List<ClassMember> pendingStaticDecls() { return pendingStaticDecls; } /** * For each new class reset the classProperties and pendingStaticDecls structures, * ready for fresh accumulation of data. * @param props the initial set of class properties */ public void resetStateForClass(List<PropertyDecl> props) { assert kind == SOURCE; pendingStaticDecls = new ArrayList<ClassMember>(); classProperties = new ArrayList<PropertyDecl>(props); } /** * Clear the classProperties and pendingStaticDecls structures, to avoid AST node * leakage. */ public void clearStateForClass() { assert kind == SOURCE; pendingStaticDecls = null; classProperties = null; } private String label; public String getLabel() { return label; } private Stmt stmt; public Stmt getLabeledStatement() { return stmt; } public void setLabel(String label, Stmt stmt) { this.label = label; this.stmt = stmt; } private String excVar; public void setExceptionVar(String var) { this.excVar = var; } public String getExceptionVar() { return excVar; } // used internally, shallow protected boolean inClosure; public void setInClosure() { inClosure = true; } // used externally, deep protected boolean insideClosure; public boolean isInsideClosure() { return insideClosure; } public void setInsideClosure(boolean b) { insideClosure = b; } // used internally, shallow public boolean stackAllocateClosure = false; public void setStackAllocateClosure(boolean val) { stackAllocateClosure = val; } // The outer context of the closure (if in closure) public X10CPPContext_c closureOuter = null; // used internally, shallow protected String stackAllocName = null; public String getStackAllocName() { return stackAllocName; } public void setStackAllocName(String s) { stackAllocName = s; } // used internally, shallow protected String embeddedFieldName = null; public String getEmbeddedFieldName() { return embeddedFieldName; } public void setEmbeddedFieldName(String s) { embeddedFieldName = s; } public ClassifiedStream genericFunctions = null; public ClassifiedStream genericFunctionClosures = null; public ClassifiedStream closures = null; public ClassifiedStream staticDefinitions = null; public ClassifiedStream staticClosureDefinitions = null; public ArrayList<VarInstance<?>> variables = new ArrayList<VarInstance<?>>(); private void putYourVariablesHere(ArrayList<VarInstance<?>> vars) { vars.addAll(variables); if (inClosure) return; ((X10CPPContext_c) outer).putYourVariablesHere(vars); } public ArrayList<VarInstance<?>> variables() { ArrayList<VarInstance<?>> r = new ArrayList<VarInstance<?>>(); putYourVariablesHere(r); return r; } private final Map<X10ClassType, ITable> cachedITables = CollectionFactory.newHashMap(); /** * Find or construct the ITable instance for the argument X10 interface type. */ public ITable getITable(X10ClassType interfaceType) { ITable ans = cachedITables.get(interfaceType); if (ans == null) { ans = new ITable(interfaceType); cachedITables.put(interfaceType, ans); } return ans; } public X10CPPContext_c(TypeSystem ts) { super(ts); } public boolean inTemplate() { X10ClassDef cd = (X10ClassDef)currentClassDef(); // following 2 lines are needed for constraints if (inSuperTypeDeclaration()) cd = supertypeDeclarationType(); X10MethodDef md = currentCode() instanceof X10MethodDef ? (X10MethodDef) currentCode() : null; boolean genericClass = cd.typeParameters().size() != 0; boolean staticMethod = md != null && md.flags().isStatic(); boolean genericMethod = md != null && md.typeParameters().size() != 0; //[DC] FIXME: what if we've in a static initialiser of a generic class //should return false, but does return true? //[IP] The above should also check for an initializer return (!staticMethod && genericClass) || genericMethod; } public X10MethodDef currentMethod() { if (currentCode() instanceof X10MethodDef) return (X10MethodDef) currentCode(); return null; } public void saveEnvVariableInfo(String name) { saveEnvVariableInfo(name, false); } public void saveEnvVariableInfo(String name, boolean lval) { VarInstance<?> vi = findVariableInThisScope(Name.make(name)); if (vi != null) { // found declaration // local variable (do nothing) } else if (inClosure) { addVar(name, lval); // local variable } else { // Captured Variable ((X10CPPContext_c) outer).saveEnvVariableInfo(name, lval); } } private VarInstance<?> lookup(String name, Context lookupContext) { VarInstance<?> vi = findVariableInThisScope(Name.make(name)); if (vi != null) return vi; else if (outer != null) return ((X10CPPContext_c) outer).lookup(name, lookupContext); else return null; } private void addVar(String name, boolean lval) { VarInstance<?> vi = lookup(name, this); if (vi==null) { System.out.println("Internal compiler error: this variable name could not be looked up: "+name); } assert vi != null : name.toString(); boolean contains = false; for (VarInstance<?> vi2 : variables) { // [DC]: what is wrong with vi2.equals(vi)? if (vi2.name().toString().equals(vi.name().toString())) { contains = true; break; } } if (lval) vi = vi.lval(lval); if (!contains) variables.add(vi); } public void finalizeClosureInstance() { // remove all from current context. Move those pertinent to an outer // closure to the outer closure. // for (int i = variables.size() - 1; i >= 0; i--) { // VarInstance v = (VarInstance) variables.remove(i); // ((X10Context_c) outer).saveEnvVariableInfo(v.name()); // } for (int i = 0; i < variables.size(); i++) { VarInstance<?> v = variables.get(i); VarInstance<?> cvi = findVariableInThisScope(v.name()); if (cvi == null) // declaration not found ((X10CPPContext_c) outer).saveEnvVariableInfo(v.name().toString(), v.lval()); } } public X10CPPContext_c shallowCopy() { X10CPPContext_c res = (X10CPPContext_c) super.shallowCopy(); res.variables = new ArrayList<VarInstance<?>>(); // or whatever the initial value is res.inClosure = false; res.stackAllocateClosure = false; res.closureOuter = null; res.data = CollectionFactory.newHashMap(1, 1.0f); return res; } } //vim:tabstop=4:shiftwidth=4:expandtab