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