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