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