1 package org.simantics.scl.compiler.compilation;
3 import java.util.ArrayList;
4 import java.util.Iterator;
7 import org.cojen.classfile.TypeDesc;
8 import org.simantics.scl.compiler.common.datatypes.Constructor;
9 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
10 import org.simantics.scl.compiler.common.names.Name;
11 import org.simantics.scl.compiler.constants.Constant;
12 import org.simantics.scl.compiler.constants.JavaTypeInstanceConstructor;
13 import org.simantics.scl.compiler.constants.SCLConstructor;
14 import org.simantics.scl.compiler.constants.StringConstant;
15 import org.simantics.scl.compiler.constants.componentaccess.ComponentAccess;
16 import org.simantics.scl.compiler.constants.componentaccess.FieldComponentAccess;
17 import org.simantics.scl.compiler.constants.generic.CallJava;
18 import org.simantics.scl.compiler.constants.generic.ClassRef;
19 import org.simantics.scl.compiler.constants.generic.ConvertToListFilter;
20 import org.simantics.scl.compiler.constants.generic.MethodRef;
21 import org.simantics.scl.compiler.constants.generic.OutputFilter;
22 import org.simantics.scl.compiler.constants.generic.ParameterStackItem;
23 import org.simantics.scl.compiler.constants.generic.Pop2OutputFilter;
24 import org.simantics.scl.compiler.constants.generic.PopOutputFilter;
25 import org.simantics.scl.compiler.constants.generic.StackItem;
26 import org.simantics.scl.compiler.constants.generic.ThreadLocalStackItem;
27 import org.simantics.scl.compiler.constants.singletons.SafeCoerce;
28 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
29 import org.simantics.scl.compiler.elaboration.contexts.TypeTranslationContext;
30 import org.simantics.scl.compiler.elaboration.errors.NotPatternException;
31 import org.simantics.scl.compiler.elaboration.expressions.EApply;
32 import org.simantics.scl.compiler.elaboration.expressions.EGetConstraint;
33 import org.simantics.scl.compiler.elaboration.expressions.EIntegerLiteral;
34 import org.simantics.scl.compiler.elaboration.expressions.EListLiteral;
35 import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
36 import org.simantics.scl.compiler.elaboration.expressions.EPreCHRRulesetConstructor;
37 import org.simantics.scl.compiler.elaboration.expressions.EVar;
38 import org.simantics.scl.compiler.elaboration.expressions.Expression;
39 import org.simantics.scl.compiler.elaboration.expressions.Variable;
40 import org.simantics.scl.compiler.elaboration.expressions.annotations.AnnotationUtils;
41 import org.simantics.scl.compiler.elaboration.fundeps.Fundep;
42 import org.simantics.scl.compiler.elaboration.java.JavaMethodDeclaration;
43 import org.simantics.scl.compiler.elaboration.macros.StandardMacroRule;
44 import org.simantics.scl.compiler.elaboration.modules.DeprecatedProperty;
45 import org.simantics.scl.compiler.elaboration.modules.DerivedProperty;
46 import org.simantics.scl.compiler.elaboration.modules.InlineProperty;
47 import org.simantics.scl.compiler.elaboration.modules.MethodImplementation;
48 import org.simantics.scl.compiler.elaboration.modules.PrivateProperty;
49 import org.simantics.scl.compiler.elaboration.modules.SCLValue;
50 import org.simantics.scl.compiler.elaboration.modules.TypeAlias;
51 import org.simantics.scl.compiler.elaboration.modules.TypeClass;
52 import org.simantics.scl.compiler.elaboration.modules.TypeClassInstance;
53 import org.simantics.scl.compiler.elaboration.modules.TypeClassMethod;
54 import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;
55 import org.simantics.scl.compiler.elaboration.query.Query;
56 import org.simantics.scl.compiler.elaboration.query.pre.QPreGuard;
57 import org.simantics.scl.compiler.elaboration.relations.ConcreteRelation;
58 import org.simantics.scl.compiler.elaboration.rules.MappingRelation;
59 import org.simantics.scl.compiler.elaboration.rules.SectionName;
60 import org.simantics.scl.compiler.elaboration.rules.TransformationRule;
61 import org.simantics.scl.compiler.environment.AmbiguousNameException;
62 import org.simantics.scl.compiler.environment.Environment;
63 import org.simantics.scl.compiler.environment.EnvironmentFactory;
64 import org.simantics.scl.compiler.environment.Environments;
65 import org.simantics.scl.compiler.errors.CompilationError;
66 import org.simantics.scl.compiler.errors.ErrorLog;
67 import org.simantics.scl.compiler.errors.ErrorSeverity;
68 import org.simantics.scl.compiler.errors.Locations;
69 import org.simantics.scl.compiler.internal.codegen.effects.EffectConstructor;
70 import org.simantics.scl.compiler.internal.codegen.effects.ThreadLocalVariable;
71 import org.simantics.scl.compiler.internal.codegen.types.JavaReferenceValidator;
72 import org.simantics.scl.compiler.internal.codegen.types.JavaReferenceValidatorFactory;
73 import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator;
74 import org.simantics.scl.compiler.internal.codegen.types.StandardTypeConstructor;
75 import org.simantics.scl.compiler.internal.codegen.utils.Constants;
76 import org.simantics.scl.compiler.internal.codegen.utils.JavaNamingPolicy;
77 import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilderBase;
78 import org.simantics.scl.compiler.internal.deriving.InstanceDeriver;
79 import org.simantics.scl.compiler.internal.deriving.InstanceDerivers;
80 import org.simantics.scl.compiler.internal.elaboration.profiling.BranchPointInjector;
81 import org.simantics.scl.compiler.internal.elaboration.utils.StronglyConnectedComponents;
82 import org.simantics.scl.compiler.internal.header.ModuleHeader;
83 import org.simantics.scl.compiler.internal.parsing.declarations.ConstructorAst;
84 import org.simantics.scl.compiler.internal.parsing.declarations.DAnnotationAst;
85 import org.simantics.scl.compiler.internal.parsing.declarations.DClassAst;
86 import org.simantics.scl.compiler.internal.parsing.declarations.DDataAst;
87 import org.simantics.scl.compiler.internal.parsing.declarations.DDerivingInstanceAst;
88 import org.simantics.scl.compiler.internal.parsing.declarations.DEffectAst;
89 import org.simantics.scl.compiler.internal.parsing.declarations.DFixityAst;
90 import org.simantics.scl.compiler.internal.parsing.declarations.DInstanceAst;
91 import org.simantics.scl.compiler.internal.parsing.declarations.DMappingRelationAst;
92 import org.simantics.scl.compiler.internal.parsing.declarations.DRelationAst;
93 import org.simantics.scl.compiler.internal.parsing.declarations.DRuleAst;
94 import org.simantics.scl.compiler.internal.parsing.declarations.DRulesetAst;
95 import org.simantics.scl.compiler.internal.parsing.declarations.DTypeAst;
96 import org.simantics.scl.compiler.internal.parsing.declarations.DValueAst;
97 import org.simantics.scl.compiler.internal.parsing.declarations.DValueTypeAst;
98 import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorException;
99 import org.simantics.scl.compiler.internal.parsing.translation.ProcessedDClassAst;
100 import org.simantics.scl.compiler.internal.parsing.translation.ProcessedDInstanceAst;
101 import org.simantics.scl.compiler.internal.parsing.translation.RelationRepository;
102 import org.simantics.scl.compiler.internal.parsing.translation.ValueRepository;
103 import org.simantics.scl.compiler.internal.parsing.types.TypeAst;
104 import org.simantics.scl.compiler.module.ConcreteModule;
105 import org.simantics.scl.compiler.module.ImportDeclaration;
106 import org.simantics.scl.compiler.module.InvalidModulePathException;
107 import org.simantics.scl.compiler.module.ModuleUtils;
108 import org.simantics.scl.compiler.module.debug.ModuleDebugInfo;
109 import org.simantics.scl.compiler.module.repository.ImportFailure;
110 import org.simantics.scl.compiler.module.repository.ImportFailureException;
111 import org.simantics.scl.compiler.types.TCon;
112 import org.simantics.scl.compiler.types.TForAll;
113 import org.simantics.scl.compiler.types.TFun;
114 import org.simantics.scl.compiler.types.TPred;
115 import org.simantics.scl.compiler.types.TVar;
116 import org.simantics.scl.compiler.types.Type;
117 import org.simantics.scl.compiler.types.Types;
118 import org.simantics.scl.compiler.types.kinds.Kind;
119 import org.simantics.scl.compiler.types.kinds.Kinds;
120 import org.simantics.scl.compiler.types.util.MultiFunction;
121 import org.simantics.scl.runtime.profiling.BranchPoint;
123 import gnu.trove.list.array.TIntArrayList;
124 import gnu.trove.map.hash.THashMap;
125 import gnu.trove.map.hash.TObjectIntHashMap;
126 import gnu.trove.procedure.TObjectObjectProcedure;
127 import gnu.trove.set.hash.THashSet;
128 import gnu.trove.set.hash.TIntHashSet;
130 public class Elaboration {
132 private final CompilationContext compilationContext;
133 private final ErrorLog errorLog;
134 private final String moduleName;
135 private final ModuleHeader moduleHeader;
136 private final ArrayList<ImportDeclaration> importsAst;
137 private final JavaReferenceValidatorFactory jrvFactory;
138 final JavaReferenceValidator<Object, Object, Object, Object> javaReferenceValidator;
139 private final ValueRepository valueDefinitionsAst;
140 private final RelationRepository relationDefinitionsAst;
143 ConcreteModule module;
144 Environment importedEnvironment;
145 ArrayList<SupplementedValueType> supplementedTypeAnnotations = new ArrayList<SupplementedValueType>();
147 JavaTypeTranslator javaTypeTranslator;
148 ArrayList<StandardTypeConstructor> dataTypes = new ArrayList<StandardTypeConstructor>();
149 THashMap<String, ClassRef> classRefs = new THashMap<String, ClassRef>();
150 THashMap<String, BranchPoint[]> branchPoints;
152 THashMap<String, EVar> exportMap = null;
154 public Elaboration(CompilationContext compilationContext, CompilationTimer timer, EnvironmentFactory localEnvironmentFactory,
155 String moduleName, ModuleHeader moduleHeader, ArrayList<ImportDeclaration> importsAst,
156 JavaReferenceValidatorFactory jrvFactory,
157 ValueRepository valueDefinitionsAst,
158 RelationRepository relationDefinitionsAst) {
159 this.compilationContext = compilationContext;
160 this.errorLog = compilationContext.errorLog;
161 this.moduleName = moduleName;
162 this.moduleHeader = moduleHeader;
163 if(moduleName != null)
164 importsAst = processRelativeImports(compilationContext.errorLog, moduleName, importsAst);
165 this.importsAst = importsAst;
166 this.jrvFactory = jrvFactory;
167 this.javaReferenceValidator = moduleHeader == null || moduleHeader.classLoader == null
168 ? jrvFactory.getDefaultJavaReferenceValidator()
169 : jrvFactory.getJavaReferenceValidator(moduleHeader.classLoader);
170 if(javaReferenceValidator == null)
171 errorLog.log(moduleHeader.classLoaderLocation, "Didn't find the specified class loader.");
172 this.valueDefinitionsAst = valueDefinitionsAst;
173 this.relationDefinitionsAst = relationDefinitionsAst;
175 module = new ConcreteModule(moduleName);
176 compilationContext.module = module;
177 compilationContext.moduleRepository = localEnvironmentFactory.getModuleRepository();
178 if(moduleHeader != null) {
179 if(moduleHeader.defaultLocalName != null)
180 module.setDefaultLocalName(moduleHeader.defaultLocalName);
181 if(moduleHeader.deprecated != null)
182 module.setDeprecation(moduleHeader.deprecated);
186 timer.suspendTimer();
187 importedEnvironment = localEnvironmentFactory.createEnvironment(
189 importsAst.toArray(new ImportDeclaration[importsAst.size()]));
191 timer.continueTimer();
192 compilationContext.environment = new EnvironmentOfModule(importedEnvironment, module);
193 } catch (ImportFailureException e) {
194 for(ImportFailure failure : e.failures)
195 errorLog.log(new CompilationError(failure.location, failure.toString(),
196 failure.reason == ImportFailure.MODULE_DOES_NOT_EXIST_REASON ? ErrorSeverity.ERROR : ErrorSeverity.IMPORT_ERROR));
199 for(ImportDeclaration importAst : importsAst)
200 this.module.addDependency(new ImportDeclaration(
201 importAst.moduleName,
202 importAst.reexport ? importAst.localName : null,
205 localEnvironmentFactory.addBuiltinDependencies(module);
206 compilationContext.namingPolicy = new JavaNamingPolicy(moduleName);
209 public static ArrayList<ImportDeclaration> processRelativeImports(ErrorLog errorLog, String moduleName, ArrayList<ImportDeclaration> relativeImports) {
210 ArrayList<ImportDeclaration> absoluteImports = new ArrayList<ImportDeclaration>(relativeImports.size());
211 for(ImportDeclaration relativeImport : relativeImports) {
212 if(relativeImport.moduleName.startsWith(".")) {
214 String absoluteModuleName = ModuleUtils.resolveAbsolutePath(moduleName, relativeImport.moduleName);
215 ImportDeclaration absoluteImport = new ImportDeclaration(
216 relativeImport.location,
217 absoluteModuleName, relativeImport.localName,
218 relativeImport.reexport, relativeImport.spec);
219 absoluteImports.add(absoluteImport);
220 } catch (InvalidModulePathException e) {
222 errorLog.log(relativeImport.location, e.getMessage());
226 absoluteImports.add(relativeImport);
228 return absoluteImports;
231 public void addTypesToEnvironment(
232 ArrayList<DDataAst> dataTypesAst,
233 ArrayList<DTypeAst> typeAliasesAst,
234 ArrayList<DEffectAst> effectsAst,
235 ArrayList<DRulesetAst> rulesetsAst) {
236 for(DDataAst dataType : dataTypesAst) {
237 dataType.parameterKinds = new Kind[dataType.parameters.length];
238 Kind constructorKind = Kinds.STAR;
239 for(int i=dataType.parameters.length-1;i>=0;--i) {
240 Kind kind = Kinds.metaVar();
241 dataType.parameterKinds[i] = kind;
242 constructorKind = Kinds.arrow(kind, constructorKind);
245 StandardTypeConstructor typeConstructor = new StandardTypeConstructor(
246 Types.con(moduleName, dataType.name), constructorKind);
248 NameExistenceChecks.checkIfTypeExists(errorLog,
249 dataType.location, importedEnvironment, dataType.name);
250 addTypeDescriptor(dataType.location, dataType.name, typeConstructor);
251 dataType.typeConstructor = typeConstructor;
254 for(DTypeAst typeAlias : typeAliasesAst) {
255 TypeAlias alias = new TypeAlias(Types.con(moduleName, typeAlias.name), typeAlias.parameters.length);
256 NameExistenceChecks.checkIfTypeExists(errorLog,
257 typeAlias.location, importedEnvironment, typeAlias.name);
258 addTypeDescriptor(typeAlias.location, typeAlias.name, alias);
261 for(DEffectAst effect : effectsAst) {
262 EffectConstructor effectConstructor = new EffectConstructor(Types.con(moduleName, effect.name));
263 effectConstructor.addThreadLocalVariable(
264 new ThreadLocalVariable(
266 TypeDesc.forClass(effect.threadLocalType)
268 if(module.addEffectConstructor(effect.name, effectConstructor))
269 errorLog.log(effect.location, "Effect "+effect.name+" has already been defined in this module.");
271 for(DRulesetAst ruleset : rulesetsAst) {
272 ruleset.type = Types.con(moduleName, ruleset.name);
273 ruleset.className = compilationContext.namingPolicy.getDataTypeClassName(ruleset.name);
274 StandardTypeConstructor typeConstructor = new StandardTypeConstructor(ruleset.type, Kinds.STAR,
275 TypeDesc.forClass(ruleset.className), ruleset.documentation == null ? null : ruleset.documentation.documentation);
276 typeConstructor.external = true;
277 addTypeDescriptor(ruleset.location, ruleset.name, typeConstructor);
279 javaTypeTranslator = new JavaTypeTranslator(compilationContext.environment);
280 compilationContext.javaTypeTranslator = javaTypeTranslator;
283 private void addTypeDescriptor(long location, String name, TypeDescriptor typeDescriptor) {
284 if(module.addTypeDescriptor(name, typeDescriptor))
285 errorLog.log(location, "Type "+name+" has already been defined in this module.");
288 private static final int[] EMPTY_INT_ARRAY = new int[0];
290 public void processTypeAliases(ArrayList<DTypeAst> typeAliasesAst) {
291 TObjectIntHashMap<String> typeAliasMap = new TObjectIntHashMap<String>();
292 for(int i=0;i<typeAliasesAst.size();++i)
293 typeAliasMap.put(typeAliasesAst.get(i).name, i);
294 TIntHashSet tempIntSet = new TIntHashSet();
295 ArrayList<DTypeAst> orderedTypeAliases = new ArrayList<DTypeAst>(typeAliasesAst.size());
296 //for(int i=0;i<typeAliasesAst.size();++i)
297 // System.out.println(i + "# " + typeAliasesAst.get(i).name);
298 new StronglyConnectedComponents(typeAliasesAst.size()) {
300 protected int[] findDependencies(int u) {
301 typeAliasesAst.get(u).type.collectReferences(typeAliasMap, tempIntSet);
302 if(tempIntSet.isEmpty())
303 return EMPTY_INT_ARRAY;
304 if(tempIntSet.contains(u)) {
305 errorLog.log(typeAliasesAst.get(u).location, "Type alias has a self reference.");
306 tempIntSet.remove(u);
308 int[] result = tempIntSet.toArray();
310 //System.out.println(u + " -> " + Arrays.toString(result));
314 protected void reportComponent(int[] component) {
315 //System.out.println("component: " + Arrays.toString(component));
316 if(component.length > 1) {
317 StringBuilder b = new StringBuilder();
318 b.append("Recursively defined type alias (");
319 long minLocation = typeAliasesAst.get(component[0]).location;
320 boolean first = true;
321 for(int u : component) {
322 DTypeAst typeAlias = typeAliasesAst.get(u);
327 b.append(typeAlias.name);
328 if(Locations.beginOf(typeAlias.location) < Locations.beginOf(minLocation))
329 minLocation = typeAlias.location;
332 errorLog.log(minLocation, b.toString());
335 orderedTypeAliases.add(typeAliasesAst.get(component[0]));
339 if(errorLog.hasNoErrors()) {
340 for(DTypeAst typeAlias : orderedTypeAliases) {
341 TypeAlias alias = (TypeAlias)module.getTypeDescriptor(typeAlias.name);
342 TypeTranslationContext context = createTypeTranslationContext();
343 for(int i=0;i<typeAlias.parameters.length;++i)
344 context.pushTypeVar(typeAlias.parameters[i]);
345 alias.body = typeAlias.type.toType(context, Kinds.metaVar());
346 for(int i=0;i<typeAlias.parameters.length;++i)
347 alias.parameters[i] = context.popTypeVar(typeAlias.parameters[i], null);
352 public void processDataTypes(ArrayList<DDataAst> dataTypesAst) {
353 ArrayList<Runnable> fieldAccessorGenerators = new ArrayList<Runnable>();
354 for(DDataAst dataTypeAst : dataTypesAst) {
355 TypeTranslationContext context = createTypeTranslationContext();
356 TVar[] typeParameters = new TVar[dataTypeAst.parameters.length];
357 for(int i=0;i<dataTypeAst.parameters.length;++i)
358 typeParameters[i] = context.addTypeVar(dataTypeAst.parameters[i]);
359 Constructor[] constructors = new Constructor[dataTypeAst.constructors.length];
360 String className = null;
361 boolean external = false;
362 for(DAnnotationAst annotation : dataTypeAst.getAnnotations()) {
363 if(annotation.id.text.equals("@JavaType")) {
364 if(annotation.parameters.length != 1 ||
365 !(annotation.parameters[0] instanceof ELiteral) ||
366 !(((ELiteral)annotation.parameters[0]).getValue() instanceof StringConstant))
367 errorLog.log(annotation.location, "Invalid parameters. Expected @JavaType \"className\".");
369 className = ((StringConstant)((ELiteral)annotation.parameters[0]).getValue()).getValue().replace('.', '/');
376 boolean trivialDataType = dataTypeAst.constructors.length == 1 &&
377 dataTypeAst.constructors[0].parameters.length == 1 &&
379 if(className == null && !trivialDataType)
380 className = compilationContext.namingPolicy.getDataTypeClassName(dataTypeAst.name);
382 StandardTypeConstructor dataType = dataTypeAst.typeConstructor;
384 dataType.setType(Types.con(moduleName, dataTypeAst.name), typeParameters);
385 dataType.setConstructors(constructors);
387 dataType.setTypeDesc(TypeDesc.forClass(className));
388 if(!external || dataTypeAst.constructors.length > 0) {
389 dataType.isOpen = false;
391 dataType.external = external;
392 dataTypes.add(dataType);
393 for(int j=0;j<constructors.length;++j) {
394 ConstructorAst constructor = dataTypeAst.constructors[j];
395 String name = constructor.name.text;
396 Type[] parameterTypes = new Type[constructor.parameters.length];
397 for(int i=constructor.parameters.length-1;i>=0;--i)
398 parameterTypes[i] = context.toType(constructor.parameters[i]);
399 String javaName = constructors.length == 1 ? className
400 : compilationContext.namingPolicy.getConstructorClassName(name);
401 ComponentAccess[] componentAccesses = null;
402 for(DAnnotationAst annotation : constructor.annotations)
403 if(annotation.id.text.equals("@JavaType")) {
405 javaName = ((StringConstant)((ELiteral)annotation.parameters[0])
406 .getValue()).getValue();
407 } catch(Exception e) {
408 errorLog.log(annotation.parameters[0].location, "Invalid annotation parameter.");
411 else if(annotation.id.text.equals("@FieldNames")) {
413 EListLiteral literal = (EListLiteral)annotation.parameters[0];
414 componentAccesses = new ComponentAccess[literal.getComponents().length];
415 for(int i=0;i<componentAccesses.length;++i) {
416 Expression component = literal.getComponents()[i];
417 if(component instanceof EVar)
418 componentAccesses[i] = new FieldComponentAccess(((EVar)component).name);
419 else if(component instanceof ELiteral)
420 componentAccesses[i] = new FieldComponentAccess(((StringConstant)((ELiteral)component).getValue()).getValue());
422 } catch(Exception e) {
423 errorLog.log(annotation.parameters[0].location, "Invalid annotation parameter.");
424 componentAccesses = null;
428 constructors[j] = new Constructor(constructor.location, dataType,
429 Name.create(moduleName, name),
430 parameterTypes, javaName);
431 constructors[j].componentAccesses = componentAccesses;
432 constructors[j].recordFieldNames = constructor.fieldNames;
434 if(constructors.length == 1) {
435 Constructor constructor = constructors[0];
436 if(constructor.recordFieldNames != null) {
437 fieldAccessorGenerators.add(new Runnable() {
440 Type in = Types.apply(dataType.name, dataType.parameters);
442 ComponentAccess[] componentAccesses = constructor.componentAccesses != null
443 ? constructor.componentAccesses
444 : SCLConstructor.DEFAULT_FIELD_NAMES[constructor.recordFieldNames.length];
445 for(int i=0;i<constructor.recordFieldNames.length;++i) {
446 Type out = constructor.parameterTypes[i];
449 accessor = new SafeCoerce(dataType.parameters, in, out);
451 accessor = new CallJava(dataType.parameters, Types.NO_EFFECTS, out,
452 new Type[] {in}, new StackItem[] {new ParameterStackItem(0, in)},
453 componentAccesses[i].toMethodRef(constructor.javaName, javaTypeTranslator.toTypeDesc(out)),
455 module.addFieldAccessor(constructor.recordFieldNames[i], accessor);
463 for(Runnable fieldAccessorGenerator : fieldAccessorGenerators)
464 fieldAccessorGenerator.run();
467 public void processTypeClasses(ArrayList<ProcessedDClassAst> typeClassesAst) {
468 for(ProcessedDClassAst pClassAst : typeClassesAst) {
469 DClassAst classAst = pClassAst.orig;
471 if(module.getTypeClass(classAst.name) != null) {
472 errorLog.log(classAst.location, "Class "+classAst.name+" has already been defined in this module.");
476 TypeTranslationContext context = createTypeTranslationContext();
478 TPred[] classContext = new TPred[classAst.context.length];
479 for(int i=0;i<classContext.length;++i)
480 classContext[i] = context.toTFuncApply(classAst.context[i]);
482 TVar[] parameters = new TVar[classAst.parameters.length];
484 if(classAst.name.equals("Functor") || classAst.name.equals("Monad")) {
486 parameters[0] = context.resolveTypeVariable(pClassAst.orig.location, classAst.parameters[0], Kinds.STAR_TO_STAR);
489 for(int i=0;i<parameters.length;++i)
490 parameters[i] = context.resolveTypeVariable(pClassAst.orig.location, classAst.parameters[i], Kinds.metaVar());
493 TCon con = Types.con(moduleName, classAst.name);
494 TypeClass typeClass = new TypeClass(classAst.location,
497 compilationContext.namingPolicy.getTypeClassInterfaceName(con),
499 Fundep.mapFundeps(classAst.parameters, classAst.fundeps));
501 THashMap<String, TypeClassMethod> methods = typeClass.methods;
502 for(DValueTypeAst methodDecl : pClassAst.typeDeclarations) {
506 type = context.toType(methodDecl.type);
507 } catch(SCLSyntaxErrorException e) {
508 errorLog.log(e.location, e.getMessage());
511 for(EVar name : methodDecl.names) {
512 typeClass.methodNames.add(name.name);
513 methods.put(name.name,
514 new TypeClassMethod(typeClass, name.name,
515 compilationContext.namingPolicy.getMethodName(name.name),
516 type, Types.getArity(type),
520 } catch(RuntimeException e) {
521 errorLog.setExceptionPosition(methodDecl.location);
526 for(String methodName : pClassAst.defaultImplementations.getValueNames()) {
527 String fullName = "_" + classAst.name + "_default_" + methodName;
528 ArrayList<DValueAst> defs = pClassAst.defaultImplementations.getDefinition(methodName);
530 TypeClassMethod method = typeClass.methods.get(methodName);
532 errorLog.log(defs.get(0).location, "Method " + methodName + " is not defined in this class.");
535 method.setDefaultImplementation(Name.create(moduleName, fullName));
537 valueDefinitionsAst.addDefinitions(fullName, defs);
538 supplementedTypeAnnotations.add(new SupplementedValueType(defs.get(0).location, fullName, method.getType()));
539 valueDefinitionsAst.setDerived(fullName);
542 module.addTypeClass(classAst.name, typeClass);
546 private TypeTranslationContext createTypeTranslationContext() {
547 return new TypeTranslationContext(compilationContext);
550 public void processDerivingInstances(ArrayList<DDerivingInstanceAst> derivingInstancesAst,
551 ArrayList<ProcessedDInstanceAst> instancesAst) {
552 for(DDerivingInstanceAst derivingInstance : derivingInstancesAst) {
553 String name = derivingInstance.name.name;
556 con = Environments.getTypeClassName(compilationContext.environment, name);
557 } catch (AmbiguousNameException e) {
558 errorLog.log(derivingInstance.name.location, e.getMessage());
562 errorLog.log(derivingInstance.name.location, "Couldn't resolve class " + name + ".");
565 InstanceDeriver deriver = InstanceDerivers.get(con);
567 errorLog.log(derivingInstance.location, "Doesn't know how to derive " + name + ".");
569 deriver.derive(errorLog, compilationContext.environment, instancesAst, derivingInstance);
573 public void processInstances(ArrayList<ProcessedDInstanceAst> instancesAst) {
574 THashSet<TPred> instanceClashCheckSet = new THashSet<TPred>();
575 for(ProcessedDInstanceAst pInstanceAst : instancesAst) {
576 DInstanceAst instanceAst = pInstanceAst.orig;
578 TypeTranslationContext context = createTypeTranslationContext();
580 String name = instanceAst.name.name;
583 typeClassCon = Environments.getTypeClassName(compilationContext.environment, name);
584 } catch (AmbiguousNameException e) {
585 errorLog.log(instanceAst.name.location, e.getMessage());
588 if(typeClassCon == null) {
589 errorLog.log(instanceAst.name.location, "Couldn't resolve class " + name + ".");
592 TypeClass typeClass = compilationContext.environment.getTypeClass(typeClassCon);
593 pInstanceAst.typeClass = typeClass;
595 if(instanceAst.types.length != typeClass.parameters.length) {
596 errorLog.log(instanceAst.location, "Wrong number of parameters to type class " + typeClassCon.name + ".");
599 Type[] parameters = new Type[instanceAst.types.length];
600 for(int i=0;i<parameters.length;++i)
601 parameters[i] = context.toType(instanceAst.types[i], typeClass.parameters[i].getKind() /* FIXME */);
602 TPred instance = Types.pred(typeClassCon, parameters);
604 if(!instanceClashCheckSet.add(instance)) {
605 errorLog.log(instanceAst.location, "Duplicate definition of the instance " + instance + ".");
609 TPred[] instanceContext = new TPred[instanceAst.context.length];
610 for(int i=0;i<instanceContext.length;++i)
611 instanceContext[i] = context.toTFuncApply(instanceAst.context[i]);
613 String javaName = compilationContext.namingPolicy.getInstanceClassName(instance);
614 String instancePrefix = instance.toName() + "$";
616 ValueRepository valueDefs = pInstanceAst.valueDefs;
618 THashMap<String, MethodImplementation> methodImplementations =
619 new THashMap<String, MethodImplementation>();
620 for(String valueName : valueDefs.getValueNames()) {
621 String fullName = instancePrefix + valueName;
622 long loc = valueDefs.getDefinition(valueName).get(0).location;
623 valueDefinitionsAst.addFrom(valueDefs, valueName, fullName);
624 valueDefinitionsAst.setDerived(fullName);
625 /*valueDefinitionsAst.addAnnotation(fullName, new DAnnotationAst(new EVar("@private"),
626 Collections.<Expression>emptyList()));*/
627 TypeClassMethod method = typeClass.methods.get(valueName);
629 errorLog.log(loc, "Method " + valueName + " is not defined in the type class " + typeClass.name.name + ".");
632 Type type = method.getBaseType().replace(typeClass.parameters, parameters);
633 for(int i=instanceContext.length-1;i>=0;--i)
634 type = Types.constrained(instanceContext[i], type);
635 //System.out.println(valueName + " :: " + type);
636 supplementedTypeAnnotations.add(
637 new SupplementedValueType(loc, fullName, type));
638 methodImplementations.put(valueName,
639 new MethodImplementation(Name.create(moduleName, fullName), false));
642 // Are all necessary methods defined
643 for(String methodName : typeClass.methods.keySet())
644 if(!methodImplementations.containsKey(methodName)) {
645 Name defaultImplementation = typeClass.methods.get(methodName).getDefaultImplementation();
646 if(defaultImplementation == null)
647 errorLog.log(instanceAst.location, "Method " + methodName + " is not defined.");
649 methodImplementations.put(methodName,
650 new MethodImplementation(defaultImplementation, true));
653 JavaTypeInstanceConstructor generator = new JavaTypeInstanceConstructor(javaName, instance, instanceContext);
654 if(instanceContext.length == 0)
655 generator.setHasStaticInstance(true);
657 TypeClassInstance typeClassInstance =
658 new TypeClassInstance(instanceAst.location, typeClass, generator,
659 generator.getTypeParameters(),
660 instanceContext, instance, methodImplementations,
663 generator.setInstance(typeClassInstance);
665 module.addTypeClassInstance(typeClassCon, typeClassInstance);
666 } catch(RuntimeException e) {
667 errorLog.setExceptionPosition(instanceAst.location);
672 // Generate superclass functions
673 for(ArrayList<TypeClassInstance> instanceArray : module.getTypeInstances().values())
674 for(TypeClassInstance instance : instanceArray) {
676 TypeClass typeClass = instance.typeClass;
677 int superCount = typeClass.context.length;
679 instance.superExpressions = new SCLValue[superCount];
680 for(int i=0;i<superCount;++i) {
681 TPred type = (TPred)typeClass.context[i]
682 .replace(typeClass.parameters, instance.instance.parameters);
683 SCLValue value = new SCLValue(Name.create(moduleName,
684 instance.javaName.substring(instance.javaName.indexOf('$')+1) + "_super" + i));
685 //value.addProperty(PrivateProperty.INSTANCE);
686 module.addValue(value);
687 Expression expression = new EGetConstraint(instance.location, type);
688 value.setExpression(expression);
689 value.setType(Types.forAll(instance.generatorParameters, Types.constrained(instance.context, type)));
690 value.getProperties().add(new InlineProperty(instance.context.length, 0xffffffff));
691 //TypeUnparsingContext tuc = new TypeUnparsingContext();
692 // TODO error handling
693 instance.superExpressions[i] = value;
695 } catch(RuntimeException e) {
696 errorLog.setExceptionPosition(instance.getLocation());
702 public void processJavaMethods(ArrayList<JavaMethodDeclaration> javaMethodDeclarations) {
703 for(JavaMethodDeclaration javaMethod : javaMethodDeclarations) {
704 String name = javaMethod.methodName.name;
705 String javaName = name;
706 ArrayList<DAnnotationAst> annotations =
707 valueDefinitionsAst.getAnnotations(name);
708 boolean isPrivate = false;
709 if(annotations != null) {
710 for(DAnnotationAst annotation : annotations)
711 if(annotation.id.text.equals("@JavaName")) {
712 String temp = AnnotationUtils.processStringAnnotation(errorLog, annotation);
716 else if(annotation.id.text.equals("@private")) {
717 AnnotationUtils.processTagAnnotation(errorLog, annotation);
721 if(exportMap != null)
722 isPrivate = exportMap.remove(name) == null;
724 Type type = createTypeTranslationContext().toType(javaMethod.type);
726 CallJava callJava = resolveMethod(
728 javaMethod.className,
731 if(callJava != null) {
732 NameExistenceChecks.checkIfValueExists(errorLog, javaMethod.location,
733 importedEnvironment, module, name);
734 SCLValue value = module.addValue(name, callJava);
735 value.definitionLocation = javaMethod.methodName.location;
737 value.addProperty(PrivateProperty.INSTANCE);
742 public void processRulesets(ArrayList<DRulesetAst> rulesetsAst) {
743 for(DRulesetAst ruleset : rulesetsAst) {
744 String constructorName = "create" + ruleset.name;
745 supplementedTypeAnnotations.add(new SupplementedValueType(ruleset.location, constructorName, Types.functionE(Types.PUNIT, Types.PROC, ruleset.type)));
747 valueDefinitionsAst.add(new DValueAst(new EVar(constructorName), new EPreCHRRulesetConstructor(ruleset)));
748 } catch (NotPatternException e) {
749 throw new InternalCompilerError(ruleset.location, e);
755 * Convert a java class method into a {@link CallJava} instance.
756 * Compilation errors are logged for failures in finding the named class or in accessing the method.
757 * The return value for errors is {@code null}.
759 * @param loc SCL source location
760 * @param className Name of the class
761 * @param methodName Name of the method
762 * @param type The expected SCL type of the method
763 * @return A new JavaCall instance, or null if the given method can not be instantiated.
765 private CallJava resolveMethod(long loc,
766 String className, String methodName, Type type) {
768 ClassRef classRef = classRefs.get(className);
769 if(classRef == null) {
770 if(classRefs.containsKey(className))
772 classRef = javaReferenceValidator.getClassRef(className);
773 classRefs.put(className, classRef);
774 if(classRef == null) {
775 errorLog.log(loc, "Didn't find class " + className + ".");
778 if(!javaReferenceValidator.isPublic(classRef.getClass())) {
779 errorLog.log(loc, "Class " + className + " is not public.");
786 List<MethodRef> methodRefs = classRef.getMethodRefs(methodName);
787 if(methodRefs.isEmpty()) {
788 errorLog.log(loc, "Didn't find any public method or field with name '" + methodName + "' from class " + className + ".");
792 ArrayList<CallJava> candidates = new ArrayList<CallJava>(2);
793 for(MethodRef methodRef : methodRefs) {
794 CallJava candidate = matchType(methodRef, type);
795 if(candidate != null)
796 candidates.add(candidate);
799 if(candidates.isEmpty()) {
800 StringBuilder b = new StringBuilder();
801 b.append("Didn't find any public method or field matching the type " + type + ". The following methods and fields were tried:");
802 for(MethodRef methodRef : methodRefs) {
806 b.append("\nbut expected something like:");
808 MultiFunction mFun = Types.matchFunction(type);
809 b.append("\n public static ");
810 b.append(javaTypeTranslator.toTypeDesc(mFun.returnType).getFullName()).append(' ').append(methodName).append('(');
811 boolean first = true;
812 for(Type parameter : mFun.parameterTypes) {
817 b.append(javaTypeTranslator.toTypeDesc(parameter).getFullName());
821 errorLog.log(loc, b.toString());
824 else if(candidates.size() == 1)
825 return candidates.get(0);
827 // Try to find the best match
828 ArrayList<CallJava> bestCandidates = new ArrayList<CallJava>(candidates.size());
829 loop: for(CallJava candidate : candidates) {
830 Iterator<CallJava> it = bestCandidates.iterator();
831 while(it.hasNext()) {
832 CallJava b = it.next();
833 switch(candidate.compareTo(javaReferenceValidator, b)) {
837 case CallJava.GREATER:
840 case CallJava.INCOMPARABLE:
844 bestCandidates.add(candidate);
847 if(bestCandidates.size() == 1) {
848 // System.out.println("Choose: " + bestCandidates.get(0).getMethodRef());
849 return bestCandidates.get(0);
852 StringBuilder b = new StringBuilder();
853 b.append("Found more than one incomparable public methods the type " + type + ":");
854 for(CallJava callJava : bestCandidates) {
856 b.append(callJava.getMethodRef());
858 errorLog.log(loc, b.toString());
864 private CallJava matchType(MethodRef methodRef, Type type) {
865 //System.out.println("-----------------------------------------------------");
866 //System.out.println("method: " + methodRef);
867 //System.out.println("type: " + type);
869 type = Types.canonical(type);
870 while(type instanceof TForAll)
871 type = Types.canonical(((TForAll)type).type);
873 TypeDesc[] expectedParameterTypes = methodRef.getParameterTypes();
875 ArrayList<Type> parameterTypes = new ArrayList<Type>();
876 Type effect = Types.NO_EFFECTS;
877 Type returnType = type;
879 StackItem[] stackItems = new StackItem[expectedParameterTypes.length];
880 TIntArrayList unresolvedItems = new TIntArrayList();
883 for(int i=0;i<expectedParameterTypes.length;++i) {
885 TypeDesc providedParameterType;
887 if(effect != Types.NO_EFFECTS || !(returnType instanceof TFun)) {
888 while(i < expectedParameterTypes.length)
889 unresolvedItems.add(i++);
892 TFun fun = (TFun)returnType;
893 parameterType = Types.canonical(fun.domain);
894 parameterTypes.add(parameterType);
895 effect = Types.canonical(fun.effect);
896 returnType = Types.canonical(fun.range);
897 providedParameterType = javaTypeTranslator.toTypeDesc(parameterType);
898 } while(providedParameterType.equals(TypeDesc.VOID));
901 TypeDesc expectedParameterType = expectedParameterTypes[i];
902 if(javaReferenceValidator.isAssignableFrom(expectedParameterType,
903 providedParameterType)) {
904 stackItems[i] = new ParameterStackItem(
905 parameterTypes.size()-1,
910 unresolvedItems.add(i++);
911 if(i == expectedParameterTypes.length) {
912 parameterTypes.remove(parameterTypes.size()-1);
913 returnType = Types.functionE(parameterType, effect, returnType);
918 //System.out.println("returnType: " + returnType);
919 if(!unresolvedItems.isEmpty()) {
920 ArrayList<TCon> concreteEffects = new ArrayList<TCon>();
921 effect.collectConcreteEffects(concreteEffects);
923 for(TCon eff : concreteEffects) {
924 EffectConstructor effC = compilationContext.environment.getEffectConstructor(eff);
925 for(ThreadLocalVariable var : effC.getThreadLocalVariables()) {
926 for(int i=0;i<unresolvedItems.size();++i) {
927 int id = unresolvedItems.get(i);
928 if(!expectedParameterTypes[id].equals(TypeDesc.OBJECT) &&
929 javaReferenceValidator.isAssignableFrom(expectedParameterTypes[id], var.type)) {
930 stackItems[id] = new ThreadLocalStackItem(var.variableName, var.type);
931 unresolvedItems.removeAt(i);
938 if(!unresolvedItems.isEmpty())
940 /*System.out.print("Unresolved: ");
941 boolean first = true;
942 for(int i=0;i<unresolvedItems.size();++i) {
946 System.out.print(", ");
947 System.out.print(expectedParameterTypes[unresolvedItems.get(i)]);
949 System.out.println();*/
951 OutputFilter filter = null;
953 TypeDesc providedReturnType = methodRef.getReturnType();
954 if(!providedReturnType.equals(Constants.FUNCTION)) {
955 while(returnType instanceof TFun && effect == Types.NO_EFFECTS) {
956 TFun fun = (TFun)returnType;
957 Type parameterType = Types.canonical(fun.domain);
958 if(!javaTypeTranslator.toTypeDesc(parameterType).equals(TypeDesc.VOID))
960 parameterTypes.add(parameterType);
961 effect = Types.canonical(fun.effect);
962 returnType = Types.canonical(fun.range);
965 TypeDesc expectedReturnType =
966 javaTypeTranslator.toTypeDesc(returnType);
967 if(!javaReferenceValidator.isAssignableFrom(expectedReturnType,
968 providedReturnType)) {
969 if(expectedReturnType.equals(TypeDesc.VOID)) {
970 if(providedReturnType.equals(TypeDesc.DOUBLE) || providedReturnType.equals(TypeDesc.LONG))
971 filter = Pop2OutputFilter.INSTANCE;
973 filter = PopOutputFilter.INSTANCE;
975 else if(expectedReturnType.equals(Constants.LIST)
976 && providedReturnType.equals(Constants.COLLECTION))
977 filter = ConvertToListFilter.INSTANCE;
983 CallJava result = new CallJava(
984 Types.freeVarsArray(type),
987 parameterTypes.toArray(new Type[parameterTypes.size()]),
991 //System.out.println(result.getType());
995 public void processMappingRelations(ArrayList<DMappingRelationAst> mappingRelationsAst) {
996 for(DMappingRelationAst mappingRelation : mappingRelationsAst) {
997 TypeAst[] parameterTypesAst = mappingRelation.parameterTypes;
998 Type[] parameterTypes = new Type[parameterTypesAst.length];
999 TypeTranslationContext typeTranslationContext = createTypeTranslationContext();
1000 for(int i=0;i<parameterTypes.length;++i)
1001 parameterTypes[i] = parameterTypesAst[i].toType(typeTranslationContext, Kinds.STAR);
1002 MappingRelation mRel =
1003 new MappingRelation(Name.create(moduleName, mappingRelation.name), parameterTypes);
1004 mRel.location = mappingRelation.location;
1005 if(module.addMappingRelation(mRel))
1006 errorLog.log(mappingRelation.location, "Mapping relation " + mappingRelation.name +
1007 " has already been defined.");
1011 THashMap<String, DRuleAst> ruleAstMap = new THashMap<String, DRuleAst>();
1013 public void processRules(ArrayList<DRuleAst> rulesAst) {
1014 // Find implied mapping relations
1015 for(DRuleAst ruleA : rulesAst) {
1016 ArrayList<Query> whereSection = ruleA.getSections().get("where");
1017 if(whereSection != null)
1018 for(Query query : whereSection) {
1019 if(!(query instanceof QPreGuard))
1021 QPreGuard guard = (QPreGuard)query;
1022 if(!(guard.guard instanceof EApply))
1024 EApply apply = (EApply)guard.guard;
1025 if(!(apply.getFunction() instanceof EVar))
1028 String name = ((EVar)apply.getFunction()).name;
1029 if(module.getMappingRelation(name) != null)
1032 int arity = apply.getParameters().length;
1033 Type[] parameterTypes = new Type[arity];
1034 for(int i=0;i<arity;++i)
1035 parameterTypes[i] = Types.metaVar(Kinds.STAR);
1036 MappingRelation mRel =
1037 new MappingRelation(Name.create(moduleName, name), parameterTypes);
1038 mRel.location = query.location;
1039 module.addMappingRelation(mRel);
1041 if(ruleAstMap.put(ruleA.name, ruleA) != null)
1042 errorLog.log(ruleA.location, "Rule " + ruleA.name +
1043 " has already been defined.");
1047 for(String ruleName : ruleAstMap.keySet())
1048 processRule(ruleName);
1051 private TransformationRule processRule(String ruleName) {
1052 TransformationRule rule = module.getRule(ruleName);
1056 DRuleAst ruleAst = ruleAstMap.get(ruleName);
1057 if(ruleAst.alreadyProcessing) {
1058 errorLog.log(ruleAst.location, "Cyclic chain of rule extensions.");
1062 TransformationRule[] extendsRules;
1063 int length = ruleAst.extendsNames.length;
1065 extendsRules = TransformationRule.EMPTY_ARRAY;
1067 extendsRules = new TransformationRule[length];
1068 for(int i=0;i<length;++i) {
1070 String extendsName = ruleAst.extendsNames[i];
1071 TransformationRule extendsRule;
1072 if(ruleAstMap.containsKey(extendsName))
1073 extendsRule = processRule(extendsName);
1075 extendsRule = Environments.getRule(compilationContext.environment, extendsName);
1076 if(extendsRule == null)
1077 errorLog.log(ruleAst.location,
1078 "Couldn't resolve rule name " + extendsName + ".");
1080 extendsRules[i] = extendsRule;
1081 } catch(AmbiguousNameException e) {
1082 errorLog.log(ruleAst.location, e.getMessage());
1087 final THashMap<SectionName, Query[]> sections = new THashMap<SectionName, Query[]>();
1089 final TranslationContext context = createTranslationContext(ruleName);
1091 THashMap<String, Variable> variables = context.getVariables();
1092 for(TransformationRule extendsRule : extendsRules) {
1093 if(extendsRule == null)
1095 for(Variable var : extendsRule.variables)
1096 if(variables.put(var.getName(), var) != null) {
1097 errorLog.log(ruleAst.location,
1098 "Variable " + var.getName() + " is defined in more than one base rule, which is not currently allowed.");
1102 context.pushExistentialFrame();
1103 ruleAst.getSections().forEachEntry(new TObjectObjectProcedure<String, ArrayList<Query>>() {
1105 public boolean execute(String sectionNameString, ArrayList<Query> queries) {
1106 Query[] resolvedQueries = new Query[queries.size()];
1107 for(int i=0;i<resolvedQueries.length;++i)
1108 resolvedQueries[i] = queries.get(i).resolve(context);
1110 SectionName sectionName = SectionName.getSectionName(sectionNameString);
1111 if(sectionName == null)
1112 context.getErrorLog().log(queries.get(0).location,
1113 "Invalid section name " + sectionNameString + ".");
1115 sections.put(sectionName, resolvedQueries);
1120 Variable[] variables = context.getVariables().values().toArray(new Variable[context.getVariables().size()]);
1122 rule = new TransformationRule(ruleAst.isAbstract,
1123 Name.create(moduleName, ruleAst.name),
1125 sections, variables);
1126 rule.location = ruleAst.location;
1127 module.addRule(rule);
1131 public void addDataTypesToEnvironment() {
1132 for(StandardTypeConstructor dataType : dataTypes) {
1133 int constructorTag = 0;
1134 for(Constructor constructor : dataType.constructors) {
1135 SCLValue value = new SCLValue(constructor.name);
1136 value.parameterNames = constructor.recordFieldNames;
1137 value.definitionLocation = constructor.loc;
1138 SCLConstructor sclConstructor =
1140 constructor.name.name,
1141 constructor.javaName,
1142 constructor.getTypeVariables(),
1144 constructor.getReturnType(),
1145 constructor.componentAccesses == null
1146 ? SCLConstructor.DEFAULT_FIELD_NAMES[constructor.getParameterTypes().length]
1147 : constructor.componentAccesses,
1148 constructor.getParameterTypes());
1149 if(dataType.constructors.length == 1 && (
1150 dataType.getTypeDesc() == null ||
1151 (dataType.constructors[0].javaName != null &&
1152 dataType.constructors[0].javaName.equals(MethodBuilderBase.getClassName(dataType.getTypeDesc())))))
1153 sclConstructor.setOnlyConstructor(true);
1154 value.setValue(sclConstructor);
1155 value.setType(constructor.getType());
1157 NameExistenceChecks.checkIfValueExists(errorLog, constructor.loc,
1158 importedEnvironment, module, constructor.name.name);
1159 if(module.addValue(value)) {
1160 errorLog.log(constructor.loc,
1161 "Value " + constructor.name.name + " is already defined.");
1167 public void addTypeClassesToEnvironment() {
1168 for(TypeClass typeClass : module.getTypeClasses()) {
1169 for(TypeClassMethod method : typeClass.methods.values()) {
1170 SCLValue value = method.createValue();
1171 value.definitionLocation = method.location;
1172 NameExistenceChecks.checkIfValueExists(errorLog, Locations.NO_LOCATION,
1173 importedEnvironment, module, value.getName().name);
1175 if(module.addValue(value)) {
1176 String name = method.getName();
1177 long location = Locations.NO_LOCATION;
1178 ArrayList<DValueAst> definitions = valueDefinitionsAst.getDefinition(name);
1179 if(definitions != null && !definitions.isEmpty())
1180 location = definitions.get(0).location;
1181 errorLog.log(location, "Value " + name + " is already defined.");
1187 public void preprocessValueDefinitions(ArrayList<DValueTypeAst> typeAnnotationsAst) {
1188 for(String name : valueDefinitionsAst.getValueNames()) {
1189 SCLValue value = new SCLValue(Name.create(moduleName, name));
1191 long location = valueDefinitionsAst.getLocation(name);
1192 NameExistenceChecks.checkIfValueExists(errorLog, location,
1193 importedEnvironment, module, value.getName().name);
1194 value.definitionLocation = location;
1195 if(module.addValue(value))
1196 errorLog.log(location, "Value " + name + " is already defined.");
1197 if(valueDefinitionsAst.isDerived(name))
1198 value.addProperty(DerivedProperty.INSTANCE);
1200 for(DValueTypeAst valueTypeAst : typeAnnotationsAst)
1201 for(EVar name : valueTypeAst.names) {
1202 SCLValue value = module.getValue(name.name);
1204 errorLog.log(valueTypeAst.location, name.name + " is not defined.");
1205 value = new SCLValue(Name.create(moduleName, name.name));
1206 module.addValue(value);
1208 value.definitionLocation = name.location;
1210 for(String name : relationDefinitionsAst.getRelationNames()) {
1211 ConcreteRelation relation = new ConcreteRelation(name);
1212 module.addRelation(name, relation);
1216 public void addValueDefinitionsToEnvironment(ArrayList<DValueTypeAst> typeAnnotationsAst) {
1217 THashMap<String, DValueTypeAst> typeMap = new THashMap<String, DValueTypeAst>();
1218 for(DValueTypeAst valueTypeAst : typeAnnotationsAst)
1219 for(EVar name : valueTypeAst.names) {
1220 if(typeMap.containsKey(name.name))
1221 errorLog.log(valueTypeAst.location, "Type of "+name.name+" has already been declared in this module.");
1223 typeMap.put(name.name, valueTypeAst);
1226 for(String name : valueDefinitionsAst.getValueNames()) {
1227 ArrayList<DValueAst> defs = valueDefinitionsAst.getDefinition(name);
1228 if(defs.size() != 1 || !(defs.get(0).value instanceof EPreCHRRulesetConstructor))
1231 SCLValue value = module.getValue(name);
1232 TranslationContext context = createTranslationContext(name);
1233 Expression expression = context.translateCases2(defs);
1234 value.setExpression(expression);
1236 if(exportMap != null && exportMap.remove(name) == null)
1237 value.addProperty(PrivateProperty.INSTANCE);
1238 } catch(RuntimeException e) {
1239 errorLog.setExceptionPosition(defs.get(0).location);
1243 for(String name : valueDefinitionsAst.getValueNames()) {
1244 ArrayList<DValueAst> defs = valueDefinitionsAst.getDefinition(name);
1245 if(defs.size() == 1 && defs.get(0).value instanceof EPreCHRRulesetConstructor)
1248 SCLValue value = module.getValue(name);
1249 TranslationContext context = createTranslationContext(name);
1250 Expression expression = context.translateCases2(defs);
1251 value.setExpression(expression);
1253 DValueTypeAst valueTypeAst = typeMap.remove(name);
1254 if(valueTypeAst != null)
1255 value.setType(Types.closure(context.toType(valueTypeAst.type)));
1257 ArrayList<DAnnotationAst> annotations = valueDefinitionsAst.getAnnotations(name);
1258 if(annotations != null)
1259 for(DAnnotationAst annotation : annotations) {
1260 handleAnnotation(value, defs, annotation);
1262 if(exportMap != null && exportMap.remove(name) == null)
1263 value.addProperty(PrivateProperty.INSTANCE);
1264 } catch(RuntimeException e) {
1265 errorLog.setExceptionPosition(defs.get(0).location);
1269 for(String name : relationDefinitionsAst.getRelationNames()) {
1270 ArrayList<DRelationAst> definitions = relationDefinitionsAst.getDefinition(name);
1271 if(definitions.size() > 1) {
1272 errorLog.log(definitions.get(1).location,
1273 "Does not yet support definition of relations by more than one rule.");
1277 DRelationAst definition = definitions.get(0);
1278 ConcreteRelation relation = (ConcreteRelation)module.getRelation(name);
1279 relation.location = definition.location;
1280 TranslationContext context = createTranslationContext(name);
1281 definition.translateTo(context, relation);
1285 private TranslationContext createTranslationContext(String definitionName) {
1286 return new TranslationContext(compilationContext, null, definitionName);
1289 private void handleAnnotation(SCLValue value, ArrayList<DValueAst> defs, DAnnotationAst annotation) {
1290 if(annotation.id.text.equals("@macro")) {
1291 value.setMacroRule(new StandardMacroRule());
1293 else if(annotation.id.text.equals("@inline")) {
1295 int arity = defs.get(0).lhs.getFunctionDefinitionPatternArity();
1296 int phaseMask = 0xffffffff;
1297 if(annotation.parameters.length > 0) {
1298 phaseMask = Integer.parseInt(((EIntegerLiteral)annotation.parameters[0]).getValue());
1300 value.addProperty(new InlineProperty(arity, phaseMask));
1301 } catch(NotPatternException e) {
1302 errorLog.log(annotation.location, "Inline annotation is invalid: this is not a function.");
1305 else if(annotation.id.text.equals("@private")) {
1306 if(moduleHeader != null && moduleHeader.export != null)
1307 errorLog.log(annotation.location, "Annotation @private is not used when module header contains export property.");
1308 value.addProperty(PrivateProperty.INSTANCE);
1310 else if(annotation.id.text.equals("@deprecated")) {
1311 String description = "";
1312 if(annotation.parameters.length > 0) {
1313 if(annotation.parameters.length > 1)
1314 errorLog.log(annotation.location, "Invalid number of parameters, expected one string.");
1316 String temp = AnnotationUtils.extractString(annotation.parameters[0]);
1318 errorLog.log(annotation.location, "Invalid parameter, expected one string.");
1323 value.addProperty(new DeprecatedProperty(description));
1326 errorLog.log(annotation.location, "Unknown annotation.");
1329 public void addSupplementedTypeAnnotationsToEnvironment() {
1330 for(SupplementedValueType valueType : supplementedTypeAnnotations) {
1331 Type type = Types.closure(valueType.type);
1332 String name = valueType.name;
1333 SCLValue value = module.getValue(name);
1335 errorLog.log(valueType.position,
1336 name + " is not defined.");
1337 else if(value.getType()==null)
1338 value.setType(type);
1340 errorLog.log(valueType.position,
1341 "Type of "+name+" has already been declared in this module.");
1345 public void addFixityToEnvironment(ArrayList<DFixityAst> fixityAst) {
1346 for(DFixityAst fixity : fixityAst) {
1347 for(EVar symbol : fixity.symbols) {
1348 String name = symbol.name;
1349 SCLValue value = module.getValue(name);
1351 errorLog.log(symbol.location,
1352 name + " is not defined.");
1354 value.setPrecedence(fixity.precedence);
1359 public void addCoverageBranchPoints() {
1360 branchPoints = new THashMap<String, BranchPoint[]>();
1361 BranchPointInjector injector = new BranchPointInjector();
1362 for(String valueName : valueDefinitionsAst.getValueNames()) {
1363 for(DValueAst valueAst : valueDefinitionsAst.getDefinition(valueName))
1364 valueAst.value = injector.injectBranchPoint(valueAst.value);
1365 branchPoints.put(valueName, injector.getAndClearBranchPoints());
1369 public void collectDebugInfo() {
1370 module.moduleDebugInfo = compilationContext.moduleDebugInfo = new ModuleDebugInfo();
1373 public void prepareExports() {
1374 if(moduleHeader != null && moduleHeader.export != null) {
1375 exportMap = new THashMap<String, EVar>();
1376 for(EVar export : moduleHeader.export)
1377 if(exportMap.put(export.name, export) != null)
1378 errorLog.log(export.location, "The symbol " + export.name + " is exported multiple times.");
1382 public void checkExports() {
1383 if(exportMap != null)
1384 for(EVar export : exportMap.values())
1385 errorLog.log(export.location, "The symbol " + export.name + " is not defined in the module.");