]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/Elaboration.java
Merge "Re-enabled Acorn transaction cancellation support for testing"
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / compilation / Elaboration.java
1 package org.simantics.scl.compiler.compilation;
2
3 import java.util.ArrayList;
4 import java.util.Iterator;
5 import java.util.List;
6
7 import org.cojen.classfile.TypeDesc;
8 import org.simantics.scl.compiler.common.datatypes.Constructor;
9 import org.simantics.scl.compiler.common.names.Name;
10 import org.simantics.scl.compiler.constants.JavaTypeInstanceConstructor;
11 import org.simantics.scl.compiler.constants.SCLConstructor;
12 import org.simantics.scl.compiler.constants.StringConstant;
13 import org.simantics.scl.compiler.constants.generic.CallJava;
14 import org.simantics.scl.compiler.constants.generic.ClassRef;
15 import org.simantics.scl.compiler.constants.generic.ConvertToListFilter;
16 import org.simantics.scl.compiler.constants.generic.MethodRef;
17 import org.simantics.scl.compiler.constants.generic.OutputFilter;
18 import org.simantics.scl.compiler.constants.generic.ParameterStackItem;
19 import org.simantics.scl.compiler.constants.generic.Pop2OutputFilter;
20 import org.simantics.scl.compiler.constants.generic.PopOutputFilter;
21 import org.simantics.scl.compiler.constants.generic.StackItem;
22 import org.simantics.scl.compiler.constants.generic.ThreadLocalStackItem;
23 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
24 import org.simantics.scl.compiler.elaboration.contexts.TypeTranslationContext;
25 import org.simantics.scl.compiler.elaboration.errors.NotPatternException;
26 import org.simantics.scl.compiler.elaboration.expressions.EApply;
27 import org.simantics.scl.compiler.elaboration.expressions.EGetConstraint;
28 import org.simantics.scl.compiler.elaboration.expressions.EIntegerLiteral;
29 import org.simantics.scl.compiler.elaboration.expressions.EListLiteral;
30 import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
31 import org.simantics.scl.compiler.elaboration.expressions.EVar;
32 import org.simantics.scl.compiler.elaboration.expressions.Expression;
33 import org.simantics.scl.compiler.elaboration.expressions.Variable;
34 import org.simantics.scl.compiler.elaboration.fundeps.Fundep;
35 import org.simantics.scl.compiler.elaboration.java.JavaMethodDeclaration;
36 import org.simantics.scl.compiler.elaboration.macros.StandardMacroRule;
37 import org.simantics.scl.compiler.elaboration.modules.InlineProperty;
38 import org.simantics.scl.compiler.elaboration.modules.MethodImplementation;
39 import org.simantics.scl.compiler.elaboration.modules.PrivateProperty;
40 import org.simantics.scl.compiler.elaboration.modules.SCLValue;
41 import org.simantics.scl.compiler.elaboration.modules.TypeAlias;
42 import org.simantics.scl.compiler.elaboration.modules.TypeClass;
43 import org.simantics.scl.compiler.elaboration.modules.TypeClassInstance;
44 import org.simantics.scl.compiler.elaboration.modules.TypeClassMethod;
45 import org.simantics.scl.compiler.elaboration.query.Query;
46 import org.simantics.scl.compiler.elaboration.query.pre.QPreGuard;
47 import org.simantics.scl.compiler.elaboration.relations.ConcreteRelation;
48 import org.simantics.scl.compiler.elaboration.rules.MappingRelation;
49 import org.simantics.scl.compiler.elaboration.rules.SectionName;
50 import org.simantics.scl.compiler.elaboration.rules.TransformationRule;
51 import org.simantics.scl.compiler.environment.AmbiguousNameException;
52 import org.simantics.scl.compiler.environment.Environment;
53 import org.simantics.scl.compiler.environment.EnvironmentFactory;
54 import org.simantics.scl.compiler.environment.Environments;
55 import org.simantics.scl.compiler.errors.ErrorLog;
56 import org.simantics.scl.compiler.errors.Locations;
57 import org.simantics.scl.compiler.internal.codegen.effects.EffectConstructor;
58 import org.simantics.scl.compiler.internal.codegen.effects.ThreadLocalVariable;
59 import org.simantics.scl.compiler.internal.codegen.types.JavaReferenceValidator;
60 import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator;
61 import org.simantics.scl.compiler.internal.codegen.types.StandardTypeConstructor;
62 import org.simantics.scl.compiler.internal.codegen.utils.Constants;
63 import org.simantics.scl.compiler.internal.codegen.utils.JavaNamingPolicy;
64 import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilderBase;
65 import org.simantics.scl.compiler.internal.deriving.InstanceDeriver;
66 import org.simantics.scl.compiler.internal.deriving.InstanceDerivers;
67 import org.simantics.scl.compiler.internal.elaboration.profiling.BranchPointInjector;
68 import org.simantics.scl.compiler.internal.elaboration.utils.StronglyConnectedComponents;
69 import org.simantics.scl.compiler.internal.parsing.declarations.ConstructorAst;
70 import org.simantics.scl.compiler.internal.parsing.declarations.DAnnotationAst;
71 import org.simantics.scl.compiler.internal.parsing.declarations.DClassAst;
72 import org.simantics.scl.compiler.internal.parsing.declarations.DDataAst;
73 import org.simantics.scl.compiler.internal.parsing.declarations.DDerivingInstanceAst;
74 import org.simantics.scl.compiler.internal.parsing.declarations.DEffectAst;
75 import org.simantics.scl.compiler.internal.parsing.declarations.DFixityAst;
76 import org.simantics.scl.compiler.internal.parsing.declarations.DInstanceAst;
77 import org.simantics.scl.compiler.internal.parsing.declarations.DMappingRelationAst;
78 import org.simantics.scl.compiler.internal.parsing.declarations.DRelationAst;
79 import org.simantics.scl.compiler.internal.parsing.declarations.DRuleAst;
80 import org.simantics.scl.compiler.internal.parsing.declarations.DTypeAst;
81 import org.simantics.scl.compiler.internal.parsing.declarations.DValueAst;
82 import org.simantics.scl.compiler.internal.parsing.declarations.DValueTypeAst;
83 import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorException;
84 import org.simantics.scl.compiler.internal.parsing.translation.ProcessedDClassAst;
85 import org.simantics.scl.compiler.internal.parsing.translation.ProcessedDInstanceAst;
86 import org.simantics.scl.compiler.internal.parsing.translation.RelationRepository;
87 import org.simantics.scl.compiler.internal.parsing.translation.ValueRepository;
88 import org.simantics.scl.compiler.internal.parsing.types.TypeAst;
89 import org.simantics.scl.compiler.module.ConcreteModule;
90 import org.simantics.scl.compiler.module.ImportDeclaration;
91 import org.simantics.scl.compiler.module.repository.ImportFailure;
92 import org.simantics.scl.compiler.module.repository.ImportFailureException;
93 import org.simantics.scl.compiler.types.TCon;
94 import org.simantics.scl.compiler.types.TForAll;
95 import org.simantics.scl.compiler.types.TFun;
96 import org.simantics.scl.compiler.types.TPred;
97 import org.simantics.scl.compiler.types.TVar;
98 import org.simantics.scl.compiler.types.Type;
99 import org.simantics.scl.compiler.types.Types;
100 import org.simantics.scl.compiler.types.kinds.Kind;
101 import org.simantics.scl.compiler.types.kinds.Kinds;
102 import org.simantics.scl.compiler.types.util.MultiFunction;
103 import org.simantics.scl.runtime.profiling.BranchPoint;
104
105 import gnu.trove.list.array.TIntArrayList;
106 import gnu.trove.map.hash.THashMap;
107 import gnu.trove.map.hash.TObjectIntHashMap;
108 import gnu.trove.procedure.TObjectObjectProcedure;
109 import gnu.trove.set.hash.THashSet;
110 import gnu.trove.set.hash.TIntHashSet;
111
112 public class Elaboration {
113     // inputs
114     private final CompilationContext compilationContext;
115     private final ErrorLog errorLog;
116     private final String moduleName;
117     private final ArrayList<ImportDeclaration> importsAst;
118     final JavaReferenceValidator<Object, Object, Object, Object> javaReferenceValidator;
119     private final ValueRepository valueDefinitionsAst;
120     private final RelationRepository relationDefinitionsAst;
121
122     // creates
123     ConcreteModule module;
124     Environment importedEnvironment;
125     ArrayList<SupplementedValueType> supplementedTypeAnnotations = new ArrayList<SupplementedValueType>();
126     
127     JavaTypeTranslator javaTypeTranslator;
128     ArrayList<StandardTypeConstructor> dataTypes = new ArrayList<StandardTypeConstructor>();
129     THashMap<String, ClassRef> classRefs = new THashMap<String, ClassRef>();
130     THashMap<String, BranchPoint[]> branchPoints; 
131     
132     @SuppressWarnings("unchecked")
133     public Elaboration(CompilationContext compilationContext, CompilationTimer timer, EnvironmentFactory localEnvironmentFactory,
134             String moduleName, ArrayList<ImportDeclaration> importsAst,
135             JavaReferenceValidator<?, ?, ?, ?> javaReferenceValidator,
136             ValueRepository valueDefinitionsAst,
137             RelationRepository relationDefinitionsAst) {
138         this.compilationContext = compilationContext;
139         this.errorLog = compilationContext.errorLog;
140         this.moduleName = moduleName;
141         importsAst = processRelativeImports(importsAst);
142         this.importsAst = importsAst;
143         this.javaReferenceValidator = (JavaReferenceValidator<Object, Object, Object, Object>)javaReferenceValidator;
144         this.valueDefinitionsAst = valueDefinitionsAst;
145         this.relationDefinitionsAst = relationDefinitionsAst;
146
147         module = new ConcreteModule(moduleName);
148         compilationContext.module = module;
149         try {
150             if(timer != null)
151                 timer.suspendTimer();
152             importedEnvironment = localEnvironmentFactory.createEnvironment(
153                     importsAst.toArray(new ImportDeclaration[importsAst.size()]));
154             if(timer != null)
155                 timer.continueTimer();
156             compilationContext.environment = new EnvironmentOfModule(importedEnvironment, module);
157         } catch (ImportFailureException e) {
158             for(ImportFailure failure : e.failures)
159                 errorLog.log(failure.location, failure.toString());
160             return;
161         }
162         for(ImportDeclaration importAst : importsAst)
163             this.module.addDependency(new ImportDeclaration(
164                     importAst.moduleName,
165                     importAst.reexport ? importAst.localName : null,
166                     false,
167                     importAst.spec));
168         localEnvironmentFactory.addBuiltinDependencies(module);
169         compilationContext.namingPolicy = new JavaNamingPolicy(moduleName);
170     }
171     
172     private ArrayList<ImportDeclaration> processRelativeImports(ArrayList<ImportDeclaration> relativeImports) {
173         ArrayList<ImportDeclaration> absoluteImports = new ArrayList<ImportDeclaration>(relativeImports.size());
174         for(ImportDeclaration relativeImport : relativeImports) {
175             if(relativeImport.moduleName.startsWith(".")) {
176                 String absoluteModuleName = convertRelativeModulePath(relativeImport.location, relativeImport.moduleName);
177                 if(absoluteModuleName != null) {
178                     ImportDeclaration absoluteImport = new ImportDeclaration(
179                             absoluteModuleName, relativeImport.localName,
180                             relativeImport.reexport, relativeImport.spec);
181                     absoluteImport.location = relativeImport.location;
182                     absoluteImports.add(absoluteImport);
183                 }
184             }
185             else
186                 absoluteImports.add(relativeImport);
187         }
188         return absoluteImports;
189     }
190
191     private String convertRelativeModulePath(long location, String relativeModuleName) {
192         String originalRelativeModuleName = relativeModuleName;
193         int p = moduleName.lastIndexOf('/');
194         String parentPackage = p < 0 ? "" : moduleName.substring(0, p);
195         while(relativeModuleName.startsWith(".")) {
196             if(relativeModuleName.startsWith("./")) {
197                 relativeModuleName = relativeModuleName.substring(2);
198             }
199             else if(relativeModuleName.startsWith("../")) {
200                 relativeModuleName = relativeModuleName.substring(3);
201                 if(parentPackage.isEmpty()) {
202                     errorLog.log(location, "Couldn't resolve the relative module name " + originalRelativeModuleName + " when the current module name is " + moduleName + ".");
203                     return null;
204                 }
205                 p = parentPackage.lastIndexOf('/');
206                 parentPackage = p < 0 ? "" : parentPackage.substring(0, p);
207             }
208             else {
209                 errorLog.log(location, "Couldn't resolve the relative module name " + originalRelativeModuleName + ". It has an invalid syntax.");
210                 return null;
211             }
212         }
213         return parentPackage + "/" + relativeModuleName;
214     }
215
216     public void addTypesToEnvironment(
217             ArrayList<DDataAst> dataTypesAst,
218             ArrayList<DTypeAst> typeAliasesAst,
219             ArrayList<DEffectAst> effectsAst) {
220         for(DDataAst dataType : dataTypesAst) {
221             dataType.parameterKinds = new Kind[dataType.parameters.length];
222             Kind constructorKind = Kinds.STAR;
223             for(int i=dataType.parameters.length-1;i>=0;--i) {
224                 Kind kind = Kinds.metaVar();
225                 dataType.parameterKinds[i] = kind;
226                 constructorKind = Kinds.arrow(kind, constructorKind);
227             }
228             
229             StandardTypeConstructor typeConstructor = new StandardTypeConstructor(
230                     Types.con(moduleName, dataType.name), constructorKind);
231
232             NameExistenceChecks.checkIfTypeExists(errorLog,
233                     dataType.location, importedEnvironment, dataType.name);
234             if(module.addTypeDescriptor(dataType.name, typeConstructor))
235                 errorLog.log(dataType.location, "Type "+dataType.name+" has already been defined in this module.");
236             dataType.typeConstructor = typeConstructor;
237         }
238         
239         for(DTypeAst typeAlias : typeAliasesAst) {
240             TypeAlias alias = new TypeAlias(Types.con(moduleName, typeAlias.name), typeAlias.parameters.length);
241             NameExistenceChecks.checkIfTypeExists(errorLog,
242                     typeAlias.location, importedEnvironment, typeAlias.name);
243             if(module.addTypeDescriptor(typeAlias.name, alias)) {
244                 errorLog.log(typeAlias.location, "Type alias "+typeAlias.name+" has already been defined in this module.");
245             }
246         }
247         
248         for(DEffectAst effect : effectsAst) {
249             EffectConstructor effectConstructor = new EffectConstructor(Types.con(moduleName, effect.name));
250             effectConstructor.addThreadLocalVariable(
251                     new ThreadLocalVariable(
252                             effect.variableName,
253                             TypeDesc.forClass(effect.threadLocalType)
254                             ));
255             if(module.addEffectConstructor(effect.name, effectConstructor))
256                 errorLog.log(effect.location, "Type "+effect.name+" has already been defined in this module.");
257         }     
258         javaTypeTranslator = new JavaTypeTranslator(compilationContext.environment);
259         compilationContext.javaTypeTranslator = javaTypeTranslator;
260     }
261     
262     private static final int[] EMPTY_INT_ARRAY = new int[0];
263     
264     public void processTypeAliases(ArrayList<DTypeAst> typeAliasesAst) {
265         TObjectIntHashMap<String> typeAliasMap = new TObjectIntHashMap<String>();
266         for(int i=0;i<typeAliasesAst.size();++i)
267             typeAliasMap.put(typeAliasesAst.get(i).name, i); 
268         TIntHashSet tempIntSet = new TIntHashSet();
269         ArrayList<DTypeAst> orderedTypeAliases = new ArrayList<DTypeAst>(typeAliasesAst.size()); 
270         //for(int i=0;i<typeAliasesAst.size();++i)
271         //    System.out.println(i + "# " + typeAliasesAst.get(i).name);
272         new StronglyConnectedComponents(typeAliasesAst.size()) {
273             @Override
274             protected int[] findDependencies(int u) {
275                 typeAliasesAst.get(u).type.collectReferences(typeAliasMap, tempIntSet);
276                 if(tempIntSet.isEmpty())
277                     return EMPTY_INT_ARRAY;
278                 if(tempIntSet.contains(u)) {
279                     errorLog.log(typeAliasesAst.get(u).location, "Type alias has a self reference.");
280                     tempIntSet.remove(u);
281                 }
282                 int[] result = tempIntSet.toArray();
283                 tempIntSet.clear();
284                 //System.out.println(u + " -> " + Arrays.toString(result));
285                 return result; 
286             }
287             @Override
288             protected void reportComponent(int[] component) {
289                 //System.out.println("component: " + Arrays.toString(component));
290                 if(component.length > 1) {
291                     StringBuilder b = new StringBuilder();
292                     b.append("Recursively defined type alias (");
293                     long minLocation = typeAliasesAst.get(component[0]).location;
294                     boolean first = true;
295                     for(int u : component) {
296                         DTypeAst typeAlias = typeAliasesAst.get(u);
297                         if(first)
298                             first = false;
299                         else
300                             b.append(", ");
301                         b.append(typeAlias.name);
302                         if(Locations.beginOf(typeAlias.location) < Locations.beginOf(minLocation))
303                             minLocation = typeAlias.location;
304                     }
305                     b.append(").");
306                     errorLog.log(minLocation, b.toString());
307                 }
308                 else
309                     orderedTypeAliases.add(typeAliasesAst.get(component[0]));
310             }
311         }.findComponents();
312         
313         if(errorLog.isEmpty()) {
314             for(DTypeAst typeAlias : orderedTypeAliases) {
315                 TypeAlias alias = (TypeAlias)module.getTypeDescriptor(typeAlias.name);
316                 TypeTranslationContext context = createTypeTranslationContext();
317                 for(int i=0;i<typeAlias.parameters.length;++i)
318                     context.pushTypeVar(typeAlias.parameters[i]);
319                 alias.body = typeAlias.type.toType(context, Kinds.metaVar());
320                 for(int i=0;i<typeAlias.parameters.length;++i)
321                     alias.parameters[i] = context.popTypeVar(typeAlias.parameters[i], null);
322             }
323         }
324     }
325     
326     public void processDataTypes(ArrayList<DDataAst> dataTypesAst) {
327         for(DDataAst dataTypeAst : dataTypesAst) {
328             TypeTranslationContext context = createTypeTranslationContext();
329             TVar[] typeParameters = new TVar[dataTypeAst.parameters.length];
330             for(int i=0;i<dataTypeAst.parameters.length;++i)
331                 typeParameters[i] = context.addTypeVar(dataTypeAst.parameters[i]);
332             Constructor[] constructors = new Constructor[dataTypeAst.constructors.length];
333             String className = null;
334             boolean external = false;
335             for(DAnnotationAst annotation : dataTypeAst.getAnnotations()) {
336                 if(annotation.id.text.equals("@JavaType")) {
337                     if(annotation.parameters.length != 1 || 
338                             !(annotation.parameters[0] instanceof ELiteral) ||
339                             !(((ELiteral)annotation.parameters[0]).getValue() instanceof StringConstant))
340                         errorLog.log(annotation.location, "Invalid parameters. Expected @JavaType \"className\".");
341                     else {
342                         className = ((StringConstant)((ELiteral)annotation.parameters[0]).getValue()).getValue().replace('.', '/');
343                         external = true;                        
344                         break;
345                     }
346                 }
347             }
348             
349             boolean trivialDataType = dataTypeAst.constructors.length == 1 &&
350                     dataTypeAst.constructors[0].parameters.length == 1;
351             if(className == null && !trivialDataType)
352                 className = compilationContext.namingPolicy.getDataTypeClassName(dataTypeAst.name);
353             
354             StandardTypeConstructor dataType = dataTypeAst.typeConstructor;
355             
356             dataType.setType(Types.con(moduleName, dataTypeAst.name), typeParameters);
357             dataType.setConstructors(constructors);
358             if(!trivialDataType)
359                 dataType.setTypeDesc(TypeDesc.forClass(className));            
360             if(!external || dataTypeAst.constructors.length > 0) {
361                 dataType.isOpen = false;
362             }
363             dataType.external = external;
364             dataTypes.add(dataType);
365             for(int j=0;j<constructors.length;++j) {
366                 ConstructorAst constructor = dataTypeAst.constructors[j];
367                 String name = constructor.name;
368                 Type[] parameterTypes = new Type[constructor.parameters.length];
369                 for(int i=constructor.parameters.length-1;i>=0;--i)
370                     parameterTypes[i] = context.toType(constructor.parameters[i]);
371                 String javaName = constructors.length == 1 ? className 
372                         : compilationContext.namingPolicy.getConstructorClassName(name);
373                 String[] fieldNames = null;
374                 for(DAnnotationAst annotation : constructor.annotations)
375                     if(annotation.id.text.equals("@JavaType")) {
376                         try {
377                             javaName = ((StringConstant)((ELiteral)annotation.parameters[0])
378                                     .getValue()).getValue();
379                         } catch(Exception e) {
380                             errorLog.log(annotation.parameters[0].location, "Invalid annotation parameter.");
381                         }
382                     }
383                     else if(annotation.id.text.equals("@FieldNames")) {
384                         try {
385                             EListLiteral literal = (EListLiteral)annotation.parameters[0];
386                             fieldNames = new String[literal.getComponents().length];
387                             for(int i=0;i<fieldNames.length;++i) {
388                                 Expression component = literal.getComponents()[i];
389                                 if(component instanceof EVar)
390                                     fieldNames[i] = ((EVar)component).name;
391                                 else if(component instanceof ELiteral)
392                                     fieldNames[i] = ((StringConstant)((ELiteral)component).getValue()).getValue();
393                             }
394                         } catch(Exception e) {
395                             errorLog.log(annotation.parameters[0].location, "Invalid annotation parameter.");
396                             fieldNames = null;
397                         }
398                     }   
399                 
400                 constructors[j] = new Constructor(constructor.location, dataType,
401                         Name.create(moduleName, name), 
402                         parameterTypes, javaName);
403                 constructors[j].fieldNames = fieldNames;
404                 constructors[j].recordFieldNames = constructor.fieldNames;
405             }
406         }
407     }
408     
409     public void processTypeClasses(ArrayList<ProcessedDClassAst> typeClassesAst) {
410         for(ProcessedDClassAst pClassAst : typeClassesAst) {
411             DClassAst classAst = pClassAst.orig;
412             
413             if(module.getTypeClass(classAst.name) != null) {
414                 errorLog.log(classAst.location, "Class "+classAst.name+" has already been defined in this module.");
415                 continue;
416             }
417             
418             TypeTranslationContext context = createTypeTranslationContext();            
419             
420             TPred[] classContext = new TPred[classAst.context.length];
421             for(int i=0;i<classContext.length;++i)
422                 classContext[i] = context.toTFuncApply(classAst.context[i]);
423             
424             TVar[] parameters = new TVar[classAst.parameters.length];
425             
426             if(classAst.name.equals("Functor") || classAst.name.equals("Monad")) {
427                 // FIXME hack
428                 parameters[0] = context.resolveTypeVariable(pClassAst.orig.location, classAst.parameters[0], Kinds.STAR_TO_STAR);
429             }
430             else {
431                 for(int i=0;i<parameters.length;++i)
432                     parameters[i] = context.resolveTypeVariable(pClassAst.orig.location, classAst.parameters[i], Kinds.metaVar());
433             }
434                         
435             TCon con = Types.con(moduleName, classAst.name);
436             TypeClass typeClass = new TypeClass(classAst.location, 
437                     classContext, 
438                     con, 
439                     compilationContext.namingPolicy.getTypeClassInterfaceName(con),
440                     parameters,
441                     Fundep.mapFundeps(classAst.parameters, classAst.fundeps));
442             
443             THashMap<String, TypeClassMethod> methods = typeClass.methods;
444             for(DValueTypeAst methodDecl : pClassAst.typeDeclarations) {
445                 try {
446                     Type type;
447                     try {
448                         type = context.toType(methodDecl.type);
449                     } catch(SCLSyntaxErrorException e) {
450                         errorLog.log(e.location, e.getMessage());
451                         continue;
452                     }
453                     for(EVar name : methodDecl.names) {
454                         typeClass.methodNames.add(name.name);
455                         methods.put(name.name,
456                                 new TypeClassMethod(typeClass, name.name, 
457                                         compilationContext.namingPolicy.getMethodName(name.name),
458                                         type, Types.getArity(type),
459                                         name.location)
460                                 );
461                     }
462                 } catch(RuntimeException e) {
463                     errorLog.setExceptionPosition(methodDecl.location);
464                     throw e;
465                 }
466             }
467             
468             for(String methodName : pClassAst.defaultImplementations.getValueNames()) {
469                 String fullName = "_" + classAst.name + "_default_" + methodName;                
470                 ArrayList<DValueAst> defs = pClassAst.defaultImplementations.getDefinition(methodName);
471                 
472                 TypeClassMethod method = typeClass.methods.get(methodName);
473                 if(method == null) {
474                     errorLog.log(defs.get(0).location, "Method " + methodName + " is not defined in this class.");
475                     continue;
476                 }
477                 method.setDefaultImplementation(Name.create(moduleName, fullName));
478                 
479                 valueDefinitionsAst.addDefinitions(fullName, defs);
480                 /*valueDefinitionsAst.addAnnotation(fullName, new DAnnotationAst(new EVar("@private"), 
481                         Collections.<Expression>emptyList()));*/
482                 supplementedTypeAnnotations.add(new SupplementedValueType(defs.get(0).location, fullName, method.getType()));                
483             }
484             
485             module.addTypeClass(classAst.name, typeClass);
486         }
487     }
488
489     private TypeTranslationContext createTypeTranslationContext() {
490         return new TypeTranslationContext(compilationContext);
491     }
492     
493     public void processDerivingInstances(ArrayList<DDerivingInstanceAst> derivingInstancesAst,
494             ArrayList<ProcessedDInstanceAst> instancesAst) {
495         for(DDerivingInstanceAst derivingInstance : derivingInstancesAst) {
496             String name = derivingInstance.name.name;
497             TCon con;
498             try {
499                 con = Environments.getTypeClassName(compilationContext.environment, name);
500             } catch (AmbiguousNameException e) {
501                 errorLog.log(derivingInstance.name.location, e.getMessage());
502                 continue;
503             }
504             if(con == null) {
505                 errorLog.log(derivingInstance.name.location, "Couldn't resolve class " + name + ".");
506                 continue;
507             }
508             InstanceDeriver deriver = InstanceDerivers.get(con);
509             if(deriver == null)
510                 errorLog.log(derivingInstance.location, "Doesn't know how to derive " + name + ".");
511             else
512                 deriver.derive(errorLog, compilationContext.environment, instancesAst, derivingInstance);
513         }
514     }
515     
516     public void processInstances(ArrayList<ProcessedDInstanceAst> instancesAst) {
517         THashSet<TPred> instanceClashCheckSet = new THashSet<TPred>(); 
518         for(ProcessedDInstanceAst pInstanceAst : instancesAst) {
519             DInstanceAst instanceAst = pInstanceAst.orig;
520             try {
521                 TypeTranslationContext context = createTypeTranslationContext();
522                 
523                 String name = instanceAst.name.name;
524                 TCon typeClassCon;
525                 try {
526                     typeClassCon = Environments.getTypeClassName(compilationContext.environment, name);
527                 } catch (AmbiguousNameException e) {
528                     errorLog.log(instanceAst.name.location, e.getMessage());
529                     continue;
530                 }
531                 if(typeClassCon == null) {
532                     errorLog.log(instanceAst.name.location, "Couldn't resolve class " + name + ".");
533                     continue;
534                 }
535                 TypeClass typeClass = compilationContext.environment.getTypeClass(typeClassCon);
536                 pInstanceAst.typeClass = typeClass;
537                 
538                 if(instanceAst.types.length != typeClass.parameters.length) {
539                     errorLog.log(instanceAst.location, "Wrong number of parameters to type class " + typeClassCon.name + ".");
540                     continue;
541                 }
542                 Type[] parameters = new Type[instanceAst.types.length];
543                 for(int i=0;i<parameters.length;++i)
544                     parameters[i] = context.toType(instanceAst.types[i], typeClass.parameters[i].getKind() /* FIXME */);
545                 TPred instance = Types.pred(typeClassCon, parameters);
546                 
547                 if(!instanceClashCheckSet.add(instance)) {
548                     errorLog.log(instanceAst.location, "Duplicate definition of the instance " + instance + ".");
549                     continue;
550                 }
551                 
552                 TPred[] instanceContext = new TPred[instanceAst.context.length];
553                 for(int i=0;i<instanceContext.length;++i)
554                     instanceContext[i] = context.toTFuncApply(instanceAst.context[i]);
555                 
556                 String javaName = compilationContext.namingPolicy.getInstanceClassName(instance);
557                 String instancePrefix = instance.toName() + "$";
558     
559                 ValueRepository valueDefs = pInstanceAst.valueDefs;
560     
561                 THashMap<String, MethodImplementation> methodImplementations =
562                         new THashMap<String, MethodImplementation>();
563                 for(String valueName : valueDefs.getValueNames()) {
564                     String fullName = instancePrefix + valueName;
565                     long loc = valueDefs.getDefinition(valueName).get(0).location;
566                     valueDefinitionsAst.addFrom(valueDefs, valueName, fullName);
567                     /*valueDefinitionsAst.addAnnotation(fullName, new DAnnotationAst(new EVar("@private"), 
568                             Collections.<Expression>emptyList()));*/
569                     TypeClassMethod method = typeClass.methods.get(valueName);
570                     if(method == null) {
571                         errorLog.log(loc, "Method " + valueName + " is not defined in the type class " + typeClass.name.name + ".");
572                         continue;
573                     }
574                     Type type = method.getBaseType().replace(typeClass.parameters, parameters);
575                     for(int i=instanceContext.length-1;i>=0;--i)
576                         type = Types.constrained(instanceContext[i], type);
577                     //System.out.println(valueName + " :: " + type);
578                     supplementedTypeAnnotations.add(
579                             new SupplementedValueType(loc, fullName, type));
580                     methodImplementations.put(valueName,
581                             new MethodImplementation(Name.create(moduleName, fullName), false));
582                 }
583                 
584                 // Are all necessary methods defined
585                 for(String methodName : typeClass.methods.keySet())
586                     if(!methodImplementations.containsKey(methodName)) {
587                         Name defaultImplementation = typeClass.methods.get(methodName).getDefaultImplementation();
588                         if(defaultImplementation == null)
589                             errorLog.log(instanceAst.location, "Method " + methodName + " is not defined.");
590                         else
591                             methodImplementations.put(methodName, 
592                                     new MethodImplementation(defaultImplementation, true));
593                     }
594                 
595                 JavaTypeInstanceConstructor generator = new JavaTypeInstanceConstructor(javaName, instance, instanceContext);
596                 if(instanceContext.length == 0)
597                     generator.setHasStaticInstance(true);
598                 
599                 TypeClassInstance typeClassInstance = 
600                         new TypeClassInstance(instanceAst.location, typeClass, generator,
601                                 generator.getTypeParameters(),
602                                 instanceContext, instance, methodImplementations,
603                                 javaName);
604                 
605                 generator.setInstance(typeClassInstance);
606                 
607                 module.addTypeClassInstance(typeClassCon, typeClassInstance);
608             } catch(RuntimeException e) {
609                 errorLog.setExceptionPosition(instanceAst.location);
610                 throw e;
611             }
612         }
613         
614         // Generate superclass functions
615         for(ArrayList<TypeClassInstance> instanceArray : module.getTypeInstances().values())
616             for(TypeClassInstance instance : instanceArray) {
617                 try {
618                     TypeClass typeClass = instance.typeClass;
619                     int superCount = typeClass.context.length;
620                     
621                     instance.superExpressions = new SCLValue[superCount];
622                     for(int i=0;i<superCount;++i) {
623                         TPred type = (TPred)typeClass.context[i]
624                                 .replace(typeClass.parameters, instance.instance.parameters);
625                         SCLValue value = new SCLValue(Name.create(moduleName, 
626                                 instance.javaName.substring(instance.javaName.indexOf('$')+1) + "_super" + i));
627                         //value.addProperty(PrivateProperty.INSTANCE);
628                         module.addValue(value);
629                         Expression expression = new EGetConstraint(instance.location, type);
630                         value.setExpression(expression);
631                         value.setType(Types.forAll(instance.generatorParameters, Types.constrained(instance.context, type)));
632                         value.getProperties().add(new InlineProperty(instance.context.length, 0xffffffff));
633                         //TypeUnparsingContext tuc = new TypeUnparsingContext();
634                         // TODO error handling
635                         instance.superExpressions[i] = value;
636                     }
637                 } catch(RuntimeException e) {
638                     errorLog.setExceptionPosition(instance.getLocation());
639                     throw e;
640                 }
641             }
642     }
643     
644     public void processJavaMethods(ArrayList<JavaMethodDeclaration> javaMethodDeclarations) {
645         for(JavaMethodDeclaration javaMethod : javaMethodDeclarations) {
646             String name = javaMethod.methodName.name;
647             String javaName = name;
648             ArrayList<DAnnotationAst> annotations = 
649                     valueDefinitionsAst.getAnnotations(name);
650             boolean isPrivate = false;
651             if(annotations != null) {
652                 for(DAnnotationAst annotation : annotations)
653                     if(annotation.id.text.equals("@JavaName")) {
654                         Expression p0 = annotation.parameters[0];
655                         if(p0 instanceof EVar)
656                             javaName = ((EVar)p0).name;
657                         else if(p0 instanceof ELiteral) {
658                             ELiteral lit = (ELiteral)p0;
659                             javaName = ((StringConstant)lit.getValue()).getValue();
660                         }
661                     }
662                     else if(annotation.id.text.equals("@private")) {
663                         isPrivate = true;
664                     }
665             }
666             
667             Type type = createTypeTranslationContext().toType(javaMethod.type);
668
669             CallJava callJava = resolveMethod(
670                     javaMethod.location,
671                     javaMethod.className,
672                     javaName,
673                     type);
674             if(callJava != null) {
675                 NameExistenceChecks.checkIfValueExists(errorLog, javaMethod.location,
676                         importedEnvironment, name);
677                 SCLValue value = module.addValue(name, callJava);
678                 value.definitionLocation = javaMethod.methodName.location;
679                 if(isPrivate)
680                     value.addProperty(PrivateProperty.INSTANCE);
681             }
682         }
683     }
684     
685     /**
686      * Convert a java class method into a {@link CallJava} instance.
687      * Compilation errors are logged for failures in finding the named class or in accessing the method.
688      * The return value for errors is {@code null}.
689      * 
690      * @param loc  SCL source location
691      * @param className  Name of the class
692      * @param methodName  Name of the method
693      * @param type  The expected SCL type of the method 
694      * @return  A new JavaCall instance, or null if the given method can not be instantiated.
695      */
696     private CallJava resolveMethod(long loc,
697             String className, String methodName, Type type) {
698         // Resolve class
699         ClassRef classRef = classRefs.get(className);
700         if(classRef == null) {
701             if(classRefs.containsKey(className))
702                 return null;
703             classRef = javaReferenceValidator.getClassRef(className);
704             classRefs.put(className, classRef);
705             if(classRef == null) {
706                 errorLog.log(loc, "Didn't find class " + className + ".");
707                 return null;
708             }
709             if(!javaReferenceValidator.isPublic(classRef.getClass())) {
710                 errorLog.log(loc, "Class " + className + " is not public.");
711                 return null;
712             }
713             
714         }
715         
716         // Resolve method
717         List<MethodRef> methodRefs = classRef.getMethodRefs(methodName);
718         if(methodRefs.isEmpty()) {
719             errorLog.log(loc, "Didn't find any public method or field with name '" + methodName + "' from class " + className + ".");
720             return null;
721         }
722         
723         ArrayList<CallJava> candidates = new ArrayList<CallJava>(2); 
724         for(MethodRef methodRef : methodRefs) {
725             CallJava candidate = matchType(methodRef, type);
726             if(candidate != null)
727                 candidates.add(candidate);
728         }
729
730         if(candidates.isEmpty()) {
731             StringBuilder b = new StringBuilder();
732             b.append("Didn't find any public method or field matching the type " + type + ". The following methods and fields were tried:");
733             for(MethodRef methodRef : methodRefs) {
734                 b.append("\n    ");
735                 b.append(methodRef);
736             }
737             b.append("\nbut expected something like:");
738             {
739                 MultiFunction mFun = Types.matchFunction(type);
740                 b.append("\n    public static ");
741                 b.append(javaTypeTranslator.toTypeDesc(mFun.returnType).getFullName()).append(' ').append(methodName).append('(');
742                 boolean first = true;
743                 for(Type parameter : mFun.parameterTypes) {
744                     if(first)
745                         first = false;
746                     else
747                         b.append(", ");
748                     b.append(javaTypeTranslator.toTypeDesc(parameter).getFullName());
749                 }
750                 b.append(')');
751             }
752             errorLog.log(loc, b.toString());
753             return null;
754         }
755         else if(candidates.size() == 1)
756             return candidates.get(0);
757         else {
758             // Try to find the best match
759             ArrayList<CallJava> bestCandidates = new ArrayList<CallJava>(candidates.size());
760             loop: for(CallJava candidate : candidates) {
761                 Iterator<CallJava> it = bestCandidates.iterator();
762                 while(it.hasNext()) {
763                     CallJava b = it.next();
764                     switch(candidate.compareTo(javaReferenceValidator, b)) {
765                     case CallJava.LESS:
766                     case CallJava.EQUAL:
767                         continue loop;
768                     case CallJava.GREATER:
769                         it.remove();
770                         break;
771                     case CallJava.INCOMPARABLE:
772                         break;
773                     }
774                 }
775                 bestCandidates.add(candidate);
776             }
777             
778             if(bestCandidates.size() == 1) {
779                 // System.out.println("Choose: " + bestCandidates.get(0).getMethodRef());
780                 return bestCandidates.get(0);
781             }
782             else { 
783                 StringBuilder b = new StringBuilder();
784                 b.append("Found more than one incomparable public methods the type " + type + ":");
785                 for(CallJava callJava : bestCandidates) {
786                     b.append("\n    ");
787                     b.append(callJava.getMethodRef());
788                 }
789                 errorLog.log(loc, b.toString());
790                 return null;
791             }
792         }
793     }
794
795     private CallJava matchType(MethodRef methodRef, Type type) {
796         //System.out.println("-----------------------------------------------------");
797         //System.out.println("method: " + methodRef);
798         //System.out.println("type: " + type);
799
800         type = Types.canonical(type);
801         while(type instanceof TForAll)
802             type = Types.canonical(((TForAll)type).type);
803             
804         TypeDesc[] expectedParameterTypes = methodRef.getParameterTypes();
805         
806         ArrayList<Type> parameterTypes = new ArrayList<Type>();
807         Type effect = Types.NO_EFFECTS;
808         Type returnType = type;
809         
810         StackItem[] stackItems = new StackItem[expectedParameterTypes.length];
811         TIntArrayList unresolvedItems = new TIntArrayList();
812         
813         loop:
814         for(int i=0;i<expectedParameterTypes.length;++i) {
815             Type parameterType;
816             TypeDesc providedParameterType;
817             do {
818                 if(effect != Types.NO_EFFECTS || !(returnType instanceof TFun)) {
819                     while(i < expectedParameterTypes.length)
820                         unresolvedItems.add(i++);
821                     break loop;
822                 }
823                 TFun fun = (TFun)returnType;
824                 parameterType = Types.canonical(fun.domain);
825                 parameterTypes.add(parameterType);
826                 effect = Types.canonical(fun.effect);
827                 returnType = Types.canonical(fun.range);
828                 providedParameterType = javaTypeTranslator.toTypeDesc(parameterType);
829             } while(providedParameterType.equals(TypeDesc.VOID));
830             
831             while(true) {
832                 TypeDesc expectedParameterType = expectedParameterTypes[i];
833                 if(javaReferenceValidator.isAssignableFrom(expectedParameterType,
834                         providedParameterType)) {
835                     stackItems[i] = new ParameterStackItem(
836                             parameterTypes.size()-1, 
837                             parameterType);
838                     break;
839                 }
840                 else
841                     unresolvedItems.add(i++);
842                 if(i == expectedParameterTypes.length) {
843                     parameterTypes.remove(parameterTypes.size()-1);
844                     returnType = Types.functionE(parameterType, effect, returnType);
845                     break;
846                 }
847             } 
848         }
849         //System.out.println("returnType: " + returnType);
850         if(!unresolvedItems.isEmpty()) {
851             ArrayList<TCon> concreteEffects = new ArrayList<TCon>();
852             effect.collectConcreteEffects(concreteEffects);
853             
854             for(TCon eff : concreteEffects) {
855                 EffectConstructor effC = compilationContext.environment.getEffectConstructor(eff);
856                 for(ThreadLocalVariable var : effC.getThreadLocalVariables()) {
857                     for(int i=0;i<unresolvedItems.size();++i) {
858                         int id = unresolvedItems.get(i);
859                         if(!expectedParameterTypes[id].equals(TypeDesc.OBJECT) &&
860                                 javaReferenceValidator.isAssignableFrom(expectedParameterTypes[id], var.type)) {
861                             stackItems[id] = new ThreadLocalStackItem(var.variableName, var.type);
862                             unresolvedItems.removeAt(i);
863                             --i;
864                         }
865                     }
866                 }
867             }
868             
869             if(!unresolvedItems.isEmpty())
870                 return null;
871             /*System.out.print("Unresolved: ");
872             boolean first = true;
873             for(int i=0;i<unresolvedItems.size();++i) {
874                 if(first)
875                     first = false;
876                 else
877                     System.out.print(", ");
878                 System.out.print(expectedParameterTypes[unresolvedItems.get(i)]);
879             }
880             System.out.println();*/            
881         }   
882         OutputFilter filter = null;
883         {
884             TypeDesc providedReturnType = methodRef.getReturnType();
885             if(!providedReturnType.equals(Constants.FUNCTION)) {
886                 while(returnType instanceof TFun && effect == Types.NO_EFFECTS) {
887                     TFun fun = (TFun)returnType;
888                     Type parameterType = Types.canonical(fun.domain);
889                     if(!javaTypeTranslator.toTypeDesc(parameterType).equals(TypeDesc.VOID))
890                         return null;                    
891                     parameterTypes.add(parameterType);
892                     effect = Types.canonical(fun.effect);
893                     returnType = Types.canonical(fun.range);
894                 }
895             }
896             TypeDesc expectedReturnType = 
897                     javaTypeTranslator.toTypeDesc(returnType);
898             if(!javaReferenceValidator.isAssignableFrom(expectedReturnType,
899                     providedReturnType)) {
900                 if(expectedReturnType.equals(TypeDesc.VOID)) {
901                     if(providedReturnType.equals(TypeDesc.DOUBLE) || providedReturnType.equals(TypeDesc.LONG))
902                         filter = Pop2OutputFilter.INSTANCE;
903                     else
904                         filter = PopOutputFilter.INSTANCE;
905                 }
906                 else if(expectedReturnType.equals(Constants.LIST)
907                         && providedReturnType.equals(Constants.COLLECTION))
908                     filter = ConvertToListFilter.INSTANCE;
909                 else
910                     return null;
911             }
912         }
913         
914         CallJava result = new CallJava(
915                 Types.freeVarsArray(type),
916                 effect,
917                 returnType,
918                 parameterTypes.toArray(new Type[parameterTypes.size()]),
919                 stackItems, 
920                 methodRef,
921                 filter);
922         //System.out.println(result.getType());
923         return result;
924     }
925
926     public void processMappingRelations(ArrayList<DMappingRelationAst> mappingRelationsAst) {
927         for(DMappingRelationAst mappingRelation : mappingRelationsAst) {
928             TypeAst[] parameterTypesAst = mappingRelation.parameterTypes;
929             Type[] parameterTypes = new Type[parameterTypesAst.length];
930             TypeTranslationContext typeTranslationContext = createTypeTranslationContext();
931             for(int i=0;i<parameterTypes.length;++i)
932                 parameterTypes[i] = parameterTypesAst[i].toType(typeTranslationContext, Kinds.STAR);
933             MappingRelation mRel = 
934                     new MappingRelation(Name.create(moduleName, mappingRelation.name), parameterTypes);
935             mRel.location = mappingRelation.location;
936             if(module.addMappingRelation(mRel))
937                 errorLog.log(mappingRelation.location, "Mapping relation " + mappingRelation.name + 
938                         " has already been defined.");
939         }
940     }
941
942     THashMap<String, DRuleAst> ruleAstMap = new THashMap<String, DRuleAst>();
943     
944     public void processRules(ArrayList<DRuleAst> rulesAst) {
945         // Find implied mapping relations
946         for(DRuleAst ruleA : rulesAst) {
947             ArrayList<Query> whereSection = ruleA.getSections().get("where");
948             if(whereSection != null)
949                 for(Query query : whereSection) {
950                     if(!(query instanceof QPreGuard))
951                         continue;
952                     QPreGuard guard = (QPreGuard)query;
953                     if(!(guard.guard instanceof EApply))
954                         continue;
955                     EApply apply = (EApply)guard.guard;
956                     if(!(apply.getFunction() instanceof EVar))
957                         continue;
958
959                     String name = ((EVar)apply.getFunction()).name;
960                     if(module.getMappingRelation(name) != null)
961                         continue;
962
963                     int arity = apply.getParameters().length;
964                     Type[] parameterTypes = new Type[arity];
965                     for(int i=0;i<arity;++i)
966                         parameterTypes[i] = Types.metaVar(Kinds.STAR);
967                     MappingRelation mRel = 
968                             new MappingRelation(Name.create(moduleName, name), parameterTypes);
969                     mRel.location = query.location;
970                     module.addMappingRelation(mRel);
971                 }
972             if(ruleAstMap.put(ruleA.name, ruleA) != null)
973                 errorLog.log(ruleA.location, "Rule " + ruleA.name + 
974                         " has already been defined.");
975         }
976         
977         // 
978         for(String ruleName : ruleAstMap.keySet())
979             processRule(ruleName);
980     }
981     
982     private TransformationRule processRule(String ruleName) {
983         TransformationRule rule = module.getRule(ruleName);
984         if(rule != null)
985             return rule;
986         
987         DRuleAst ruleAst = ruleAstMap.get(ruleName);
988         if(ruleAst.alreadyProcessing) {
989             errorLog.log(ruleAst.location, "Cyclic chain of rule extensions.");
990             return null;
991         }
992         
993         TransformationRule[] extendsRules;
994         int length = ruleAst.extendsNames.length;
995         if(length == 0)
996             extendsRules = TransformationRule.EMPTY_ARRAY;
997         else {
998             extendsRules = new TransformationRule[length];
999             for(int i=0;i<length;++i) {
1000                 try {
1001                     String extendsName = ruleAst.extendsNames[i];
1002                     TransformationRule extendsRule;
1003                     if(ruleAstMap.containsKey(extendsName))
1004                         extendsRule = processRule(extendsName);
1005                     else {
1006                         extendsRule = Environments.getRule(compilationContext.environment, extendsName);
1007                         if(extendsRule == null)
1008                             errorLog.log(ruleAst.location,
1009                                     "Couldn't resolve rule name " + extendsName + ".");
1010                     }
1011                     extendsRules[i] = extendsRule;
1012                 } catch(AmbiguousNameException e) {
1013                     errorLog.log(ruleAst.location, e.getMessage());
1014                 }
1015             }
1016         }
1017         
1018         final THashMap<SectionName, Query[]> sections = new THashMap<SectionName, Query[]>();
1019
1020         final TranslationContext context = createTranslationContext();
1021         if(length > 0) {
1022             THashMap<String, Variable> variables = context.getVariables();
1023             for(TransformationRule extendsRule : extendsRules) {
1024                 if(extendsRule == null)
1025                     continue;
1026                 for(Variable var : extendsRule.variables)
1027                     if(variables.put(var.getName(), var) != null) {
1028                         errorLog.log(ruleAst.location, 
1029                                 "Variable " + var.getName() + " is defined in more than one base rule, which is not currently allowed.");
1030                     }
1031             }
1032         }
1033         context.pushExistentialFrame();
1034         ruleAst.getSections().forEachEntry(new TObjectObjectProcedure<String, ArrayList<Query>>() {
1035             @Override
1036             public boolean execute(String sectionNameString, ArrayList<Query> queries) {
1037                 Query[] resolvedQueries = new Query[queries.size()];
1038                 for(int i=0;i<resolvedQueries.length;++i)
1039                     resolvedQueries[i] = queries.get(i).resolve(context);
1040
1041                 SectionName sectionName = SectionName.getSectionName(sectionNameString);
1042                 if(sectionName == null)
1043                     context.getErrorLog().log(queries.get(0).location,
1044                             "Invalid section name " + sectionNameString + ".");
1045                 else
1046                     sections.put(sectionName, resolvedQueries);
1047                 return true;
1048             }
1049         });
1050         
1051         Variable[] variables = context.getVariables().values().toArray(new Variable[context.getVariables().size()]);
1052
1053         rule = new TransformationRule(ruleAst.isAbstract,
1054                 Name.create(moduleName, ruleAst.name),
1055                 extendsRules,
1056                 sections, variables);
1057         rule.location = ruleAst.location;
1058         module.addRule(rule);
1059         return rule;
1060     }
1061
1062     public void addDataTypesToEnvironment() {
1063         for(StandardTypeConstructor dataType : dataTypes) {
1064             int constructorTag = 0;
1065             for(Constructor constructor : dataType.constructors) {
1066                 SCLValue value = new SCLValue(constructor.name);
1067                 SCLConstructor sclConstructor = 
1068                         new SCLConstructor(
1069                                 constructor.name.name,
1070                                 constructor.javaName, 
1071                                 constructor.getTypeVariables(),
1072                                 constructorTag++,
1073                                 constructor.getReturnType(),
1074                                 constructor.fieldNames == null 
1075                                         ? SCLConstructor.DEFAULT_FIELD_NAMES[constructor.getParameterTypes().length] 
1076                                         : constructor.fieldNames,
1077                                 constructor.recordFieldNames,
1078                                 constructor.getParameterTypes());
1079                 if(dataType.constructors.length == 1 && (
1080                         dataType.getTypeDesc() == null ||
1081                         dataType.constructors[0].javaName.equals(MethodBuilderBase.getClassName(dataType.getTypeDesc()))))
1082                     sclConstructor.setOnlyConstructor(true);
1083                 value.setValue(sclConstructor);
1084                 value.setType(constructor.getType());
1085                 
1086                 NameExistenceChecks.checkIfValueExists(errorLog, constructor.loc,
1087                         importedEnvironment, constructor.name.name);
1088                 if(module.addValue(value)) {
1089                     errorLog.log(constructor.loc,
1090                             "Value " + constructor.name.name + " is already defined.");
1091                 }
1092             }
1093         }
1094     }
1095     
1096     public void addTypeClassesToEnvironment() {
1097         for(TypeClass typeClass : module.getTypeClasses()) {
1098             for(TypeClassMethod method : typeClass.methods.values()) {
1099                 SCLValue value = method.createValue();
1100                 value.definitionLocation = method.location;
1101                 NameExistenceChecks.checkIfValueExists(errorLog, Locations.NO_LOCATION,
1102                         importedEnvironment, value.getName().name);
1103
1104                 if(module.addValue(value)) {
1105                     String name = method.getName();
1106                     long location = Locations.NO_LOCATION;
1107                     ArrayList<DValueAst> definitions = valueDefinitionsAst.getDefinition(name);
1108                     if(definitions != null && !definitions.isEmpty())
1109                         location = definitions.get(0).location;
1110                     errorLog.log(location, "Value " + name + " is already defined.");
1111                 }
1112             }
1113         }
1114     }
1115     
1116     public void preprocessValueDefinitions(ArrayList<DValueTypeAst> typeAnnotationsAst) {
1117         for(String name : valueDefinitionsAst.getValueNames()) {
1118             SCLValue value = new SCLValue(Name.create(moduleName, name));
1119             
1120             long location = valueDefinitionsAst.getLocation(name);
1121             NameExistenceChecks.checkIfValueExists(errorLog, location,
1122                     importedEnvironment, value.getName().name);
1123             value.definitionLocation = location;
1124             if(module.addValue(value))
1125                 errorLog.log(location, "Value " + name + " is already defined.");
1126         }
1127         for(DValueTypeAst valueTypeAst : typeAnnotationsAst)
1128             for(EVar name : valueTypeAst.names) {
1129                 SCLValue value = module.getValue(name.name); 
1130                 if(value == null) {
1131                     errorLog.log(valueTypeAst.location, name.name + " is not defined.");
1132                     value = new SCLValue(Name.create(moduleName, name.name));
1133                     module.addValue(value);
1134                 }
1135                 value.definitionLocation = name.location;
1136             }
1137         for(String name : relationDefinitionsAst.getRelationNames()) {
1138             ConcreteRelation relation = new ConcreteRelation(name);
1139             module.addRelation(name, relation);
1140         }
1141     }
1142     
1143     public void addValueDefinitionsToEnvironment(ArrayList<DValueTypeAst> typeAnnotationsAst) {
1144         THashMap<String, DValueTypeAst> typeMap = new THashMap<String, DValueTypeAst>();
1145         for(DValueTypeAst valueTypeAst : typeAnnotationsAst)
1146             for(EVar name : valueTypeAst.names) {
1147                 if(typeMap.containsKey(name.name))
1148                     errorLog.log(valueTypeAst.location, "Type of "+name.name+" has already been declared in this module.");
1149                 else
1150                     typeMap.put(name.name, valueTypeAst);
1151             }
1152         
1153         for(String name : valueDefinitionsAst.getValueNames()) {
1154             ArrayList<DValueAst> defs = valueDefinitionsAst.getDefinition(name);
1155             try {
1156                 SCLValue value = module.getValue(name);
1157                 TranslationContext context = createTranslationContext();
1158                 Expression expression = context.translateCases2(defs);
1159                 value.setExpression(expression);
1160                 
1161                 DValueTypeAst valueTypeAst = typeMap.remove(name);
1162                 if(valueTypeAst != null)
1163                     value.setType(Types.closure(context.toType(valueTypeAst.type)));
1164                 
1165                 ArrayList<DAnnotationAst> annotations = valueDefinitionsAst.getAnnotations(name);
1166                 if(annotations != null)
1167                     for(DAnnotationAst annotation : annotations) {
1168                         handleAnnotation(value, defs, annotation);
1169                     }
1170             } catch(RuntimeException e) {
1171                 errorLog.setExceptionPosition(defs.get(0).location);
1172                 throw e;
1173             }
1174         }
1175         for(String name : relationDefinitionsAst.getRelationNames()) {
1176             ArrayList<DRelationAst> definitions = relationDefinitionsAst.getDefinition(name);
1177             if(definitions.size() > 1) {
1178                 errorLog.log(definitions.get(1).location,
1179                         "Does not yet support definition of relations by more than one rule.");
1180                 continue;
1181             }
1182             
1183             DRelationAst definition = definitions.get(0);
1184             ConcreteRelation relation = (ConcreteRelation)module.getRelation(name);
1185             relation.location = definition.location;
1186             TranslationContext context = createTranslationContext();
1187             definition.translateTo(context, relation);
1188         }
1189     }
1190     
1191     private TranslationContext createTranslationContext() {
1192         return new TranslationContext(compilationContext, null);
1193     }
1194     
1195     private void handleAnnotation(SCLValue value, ArrayList<DValueAst> defs, DAnnotationAst annotation) {
1196         if(annotation.id.text.equals("@macro")) {
1197             value.setMacroRule(new StandardMacroRule());
1198         }
1199         else if(annotation.id.text.equals("@inline")) {
1200             try {
1201                 int arity = defs.get(0).lhs.getFunctionDefinitionArity();
1202                 int phaseMask = 0xffffffff;
1203                 if(annotation.parameters.length > 0) {
1204                     phaseMask = Integer.parseInt(((EIntegerLiteral)annotation.parameters[0]).getValue());
1205                 }
1206                 value.addProperty(new InlineProperty(arity, phaseMask));
1207             } catch(NotPatternException e) {
1208                 errorLog.log(annotation.location, "Inline annotation is invalid: this is not a function.");
1209             }
1210         }
1211         else if(annotation.id.text.equals("@private")) {
1212             value.addProperty(PrivateProperty.INSTANCE);
1213         }
1214         else if(annotation.id.text.equals("@deprecated")) {
1215             // TODO
1216         }
1217         else
1218             errorLog.log(annotation.location, "Unknown annotation.");
1219     }
1220
1221     public void addSupplementedTypeAnnotationsToEnvironment() {
1222         for(SupplementedValueType valueType : supplementedTypeAnnotations) {
1223             Type type = Types.closure(valueType.type);
1224             String name = valueType.name;
1225             SCLValue value = module.getValue(name);
1226             if(value == null)
1227                 errorLog.log(valueType.position,
1228                         name + " is not defined.");
1229             else if(value.getType()==null)
1230                 value.setType(type);
1231             else
1232                 errorLog.log(valueType.position, 
1233                         "Type of "+name+" has already been declared in this module.");
1234         }
1235     }
1236     
1237     public void addFixityToEnvironment(ArrayList<DFixityAst> fixityAst) {
1238         for(DFixityAst fixity : fixityAst) {
1239             for(EVar symbol : fixity.symbols) {
1240                 String name = symbol.name;
1241                 SCLValue value = module.getValue(name);
1242                 if(value == null)
1243                     errorLog.log(symbol.location,
1244                             name + " is not defined.");
1245                 else
1246                     value.setPrecedence(fixity.precedence);
1247             }
1248         }
1249     }
1250
1251     public void addCoverageBranchPoints() {
1252         branchPoints = new THashMap<String, BranchPoint[]>();
1253         BranchPointInjector injector = new BranchPointInjector(); 
1254         for(String valueName : valueDefinitionsAst.getValueNames()) {
1255             for(DValueAst valueAst : valueDefinitionsAst.getDefinition(valueName))
1256                 valueAst.value = injector.injectBranchPoint(valueAst.value);
1257             branchPoints.put(valueName, injector.getAndClearBranchPoints());
1258         }
1259     }
1260 }