]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/Elaboration.java
(refs #7386) Minor SCL tools improvements
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / compilation / Elaboration.java
index 9dbd94691a82cd27bab16a4a7be498e39fee2852..ff5ee3b2902fa0384258f246776d534dbed0d617 100644 (file)
@@ -6,6 +6,7 @@ import java.util.List;
 
 import org.cojen.classfile.TypeDesc;
 import org.simantics.scl.compiler.common.datatypes.Constructor;
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
 import org.simantics.scl.compiler.common.names.Name;
 import org.simantics.scl.compiler.constants.Constant;
 import org.simantics.scl.compiler.constants.JavaTypeInstanceConstructor;
@@ -31,6 +32,7 @@ import org.simantics.scl.compiler.elaboration.expressions.EGetConstraint;
 import org.simantics.scl.compiler.elaboration.expressions.EIntegerLiteral;
 import org.simantics.scl.compiler.elaboration.expressions.EListLiteral;
 import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
+import org.simantics.scl.compiler.elaboration.expressions.EPreCHRRulesetConstructor;
 import org.simantics.scl.compiler.elaboration.expressions.EVar;
 import org.simantics.scl.compiler.elaboration.expressions.Expression;
 import org.simantics.scl.compiler.elaboration.expressions.Variable;
@@ -39,6 +41,7 @@ import org.simantics.scl.compiler.elaboration.fundeps.Fundep;
 import org.simantics.scl.compiler.elaboration.java.JavaMethodDeclaration;
 import org.simantics.scl.compiler.elaboration.macros.StandardMacroRule;
 import org.simantics.scl.compiler.elaboration.modules.DeprecatedProperty;
+import org.simantics.scl.compiler.elaboration.modules.DerivedProperty;
 import org.simantics.scl.compiler.elaboration.modules.InlineProperty;
 import org.simantics.scl.compiler.elaboration.modules.MethodImplementation;
 import org.simantics.scl.compiler.elaboration.modules.PrivateProperty;
@@ -47,6 +50,7 @@ import org.simantics.scl.compiler.elaboration.modules.TypeAlias;
 import org.simantics.scl.compiler.elaboration.modules.TypeClass;
 import org.simantics.scl.compiler.elaboration.modules.TypeClassInstance;
 import org.simantics.scl.compiler.elaboration.modules.TypeClassMethod;
+import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;
 import org.simantics.scl.compiler.elaboration.query.Query;
 import org.simantics.scl.compiler.elaboration.query.pre.QPreGuard;
 import org.simantics.scl.compiler.elaboration.relations.ConcreteRelation;
@@ -57,7 +61,9 @@ import org.simantics.scl.compiler.environment.AmbiguousNameException;
 import org.simantics.scl.compiler.environment.Environment;
 import org.simantics.scl.compiler.environment.EnvironmentFactory;
 import org.simantics.scl.compiler.environment.Environments;
+import org.simantics.scl.compiler.errors.CompilationError;
 import org.simantics.scl.compiler.errors.ErrorLog;
+import org.simantics.scl.compiler.errors.ErrorSeverity;
 import org.simantics.scl.compiler.errors.Locations;
 import org.simantics.scl.compiler.internal.codegen.effects.EffectConstructor;
 import org.simantics.scl.compiler.internal.codegen.effects.ThreadLocalVariable;
@@ -84,6 +90,7 @@ import org.simantics.scl.compiler.internal.parsing.declarations.DInstanceAst;
 import org.simantics.scl.compiler.internal.parsing.declarations.DMappingRelationAst;
 import org.simantics.scl.compiler.internal.parsing.declarations.DRelationAst;
 import org.simantics.scl.compiler.internal.parsing.declarations.DRuleAst;
+import org.simantics.scl.compiler.internal.parsing.declarations.DRulesetAst;
 import org.simantics.scl.compiler.internal.parsing.declarations.DTypeAst;
 import org.simantics.scl.compiler.internal.parsing.declarations.DValueAst;
 import org.simantics.scl.compiler.internal.parsing.declarations.DValueTypeAst;
@@ -174,7 +181,7 @@ public class Elaboration {
             compilationContext.environment = new EnvironmentOfModule(importedEnvironment, module);
         } catch (ImportFailureException e) {
             for(ImportFailure failure : e.failures)
-                errorLog.log(failure.location, failure.toString());
+                errorLog.log(new CompilationError(failure.location, failure.toString(), ErrorSeverity.IMPORT_ERROR));
             return;
         }
         for(ImportDeclaration importAst : importsAst)
@@ -211,7 +218,8 @@ public class Elaboration {
     public void addTypesToEnvironment(
             ArrayList<DDataAst> dataTypesAst,
             ArrayList<DTypeAst> typeAliasesAst,
-            ArrayList<DEffectAst> effectsAst) {
+            ArrayList<DEffectAst> effectsAst,
+            ArrayList<DRulesetAst> rulesetsAst) {
         for(DDataAst dataType : dataTypesAst) {
             dataType.parameterKinds = new Kind[dataType.parameters.length];
             Kind constructorKind = Kinds.STAR;
@@ -226,8 +234,7 @@ public class Elaboration {
 
             NameExistenceChecks.checkIfTypeExists(errorLog,
                     dataType.location, importedEnvironment, dataType.name);
-            if(module.addTypeDescriptor(dataType.name, typeConstructor))
-                errorLog.log(dataType.location, "Type "+dataType.name+" has already been defined in this module.");
+            addTypeDescriptor(dataType.location, dataType.name, typeConstructor);
             dataType.typeConstructor = typeConstructor;
         }
         
@@ -235,9 +242,7 @@ public class Elaboration {
             TypeAlias alias = new TypeAlias(Types.con(moduleName, typeAlias.name), typeAlias.parameters.length);
             NameExistenceChecks.checkIfTypeExists(errorLog,
                     typeAlias.location, importedEnvironment, typeAlias.name);
-            if(module.addTypeDescriptor(typeAlias.name, alias)) {
-                errorLog.log(typeAlias.location, "Type alias "+typeAlias.name+" has already been defined in this module.");
-            }
+            addTypeDescriptor(typeAlias.location, typeAlias.name, alias);
         }
         
         for(DEffectAst effect : effectsAst) {
@@ -248,11 +253,24 @@ public class Elaboration {
                             TypeDesc.forClass(effect.threadLocalType)
                             ));
             if(module.addEffectConstructor(effect.name, effectConstructor))
-                errorLog.log(effect.location, "Type "+effect.name+" has already been defined in this module.");
-        }     
+                errorLog.log(effect.location, "Effect "+effect.name+" has already been defined in this module.");
+        }
+        for(DRulesetAst ruleset : rulesetsAst) {
+            ruleset.type = Types.con(moduleName, ruleset.name);
+            ruleset.className = compilationContext.namingPolicy.getDataTypeClassName(ruleset.name);
+            StandardTypeConstructor typeConstructor = new StandardTypeConstructor(ruleset.type, Kinds.STAR,
+                    TypeDesc.forClass(ruleset.className), ruleset.documentation == null ? null : ruleset.documentation.documentation);
+            typeConstructor.external = true;
+            addTypeDescriptor(ruleset.location, ruleset.name, typeConstructor);
+        }
         javaTypeTranslator = new JavaTypeTranslator(compilationContext.environment);
         compilationContext.javaTypeTranslator = javaTypeTranslator;
     }
+        
+    private void addTypeDescriptor(long location, String name, TypeDescriptor typeDescriptor) {
+        if(module.addTypeDescriptor(name, typeDescriptor))
+            errorLog.log(location, "Type "+name+" has already been defined in this module.");
+    }
     
     private static final int[] EMPTY_INT_ARRAY = new int[0];
     
@@ -360,7 +378,7 @@ public class Elaboration {
             dataTypes.add(dataType);
             for(int j=0;j<constructors.length;++j) {
                 ConstructorAst constructor = dataTypeAst.constructors[j];
-                String name = constructor.name;
+                String name = constructor.name.text;
                 Type[] parameterTypes = new Type[constructor.parameters.length];
                 for(int i=constructor.parameters.length-1;i>=0;--i)
                     parameterTypes[i] = context.toType(constructor.parameters[i]);
@@ -587,6 +605,7 @@ public class Elaboration {
                     String fullName = instancePrefix + valueName;
                     long loc = valueDefs.getDefinition(valueName).get(0).location;
                     valueDefinitionsAst.addFrom(valueDefs, valueName, fullName);
+                    valueDefinitionsAst.setDerived(fullName);
                     /*valueDefinitionsAst.addAnnotation(fullName, new DAnnotationAst(new EVar("@private"), 
                             Collections.<Expression>emptyList()));*/
                     TypeClassMethod method = typeClass.methods.get(valueName);
@@ -702,6 +721,18 @@ public class Elaboration {
         }
     }
     
+    public void processRulesets(ArrayList<DRulesetAst> rulesetsAst) {
+        for(DRulesetAst ruleset : rulesetsAst) {
+            String constructorName = "create" + ruleset.name;
+            supplementedTypeAnnotations.add(new SupplementedValueType(ruleset.location, constructorName, Types.functionE(Types.PUNIT, Types.PROC, ruleset.type)));
+            try {
+                valueDefinitionsAst.add(new DValueAst(new EVar(constructorName), new EPreCHRRulesetConstructor(ruleset)));
+            } catch (NotPatternException e) {
+                throw new InternalCompilerError(ruleset.location, e);
+            }
+        }
+    }
+    
     /**
      * Convert a java class method into a {@link CallJava} instance.
      * Compilation errors are logged for failures in finding the named class or in accessing the method.
@@ -1084,6 +1115,7 @@ public class Elaboration {
             int constructorTag = 0;
             for(Constructor constructor : dataType.constructors) {
                 SCLValue value = new SCLValue(constructor.name);
+                value.definitionLocation = constructor.loc;
                 SCLConstructor sclConstructor = 
                         new SCLConstructor(
                                 constructor.name.name,
@@ -1098,7 +1130,8 @@ public class Elaboration {
                                 constructor.getParameterTypes());
                 if(dataType.constructors.length == 1 && (
                         dataType.getTypeDesc() == null ||
-                        dataType.constructors[0].javaName.equals(MethodBuilderBase.getClassName(dataType.getTypeDesc()))))
+                        (dataType.constructors[0].javaName != null &&
+                        dataType.constructors[0].javaName.equals(MethodBuilderBase.getClassName(dataType.getTypeDesc())))))
                     sclConstructor.setOnlyConstructor(true);
                 value.setValue(sclConstructor);
                 value.setType(constructor.getType());
@@ -1143,6 +1176,8 @@ public class Elaboration {
             value.definitionLocation = location;
             if(module.addValue(value))
                 errorLog.log(location, "Value " + name + " is already defined.");
+            if(valueDefinitionsAst.isDerived(name))
+                value.addProperty(DerivedProperty.INSTANCE);
         }
         for(DValueTypeAst valueTypeAst : typeAnnotationsAst)
             for(EVar name : valueTypeAst.names) {
@@ -1170,6 +1205,14 @@ public class Elaboration {
                     typeMap.put(name.name, valueTypeAst);
             }
         
+        THashMap<String, EVar> exportMap = null;
+        if(moduleHeader != null && moduleHeader.export != null) {
+            exportMap = new THashMap<String, EVar>();
+            for(EVar export : moduleHeader.export)
+                if(exportMap.put(export.name, export) != null)
+                    errorLog.log(export.location, "The symbol " + export.name + " is exported multiple times.");
+        }
+        
         for(String name : valueDefinitionsAst.getValueNames()) {
             ArrayList<DValueAst> defs = valueDefinitionsAst.getDefinition(name);
             try {
@@ -1187,11 +1230,16 @@ public class Elaboration {
                     for(DAnnotationAst annotation : annotations) {
                         handleAnnotation(value, defs, annotation);
                     }
+                if(exportMap != null && exportMap.remove(name) == null)
+                    value.addProperty(PrivateProperty.INSTANCE);
             } catch(RuntimeException e) {
                 errorLog.setExceptionPosition(defs.get(0).location);
                 throw e;
             }
         }
+        if(exportMap != null)
+            for(EVar export : exportMap.values())
+                errorLog.log(export.location, "The symbol " + export.name + " is not defined in the module.");
         for(String name : relationDefinitionsAst.getRelationNames()) {
             ArrayList<DRelationAst> definitions = relationDefinitionsAst.getDefinition(name);
             if(definitions.size() > 1) {
@@ -1229,6 +1277,8 @@ public class Elaboration {
             }
         }
         else if(annotation.id.text.equals("@private")) {
+            if(moduleHeader != null && moduleHeader.export != null)
+                errorLog.log(annotation.location, "Annotation @private is not used when module header contains export property.");
             value.addProperty(PrivateProperty.INSTANCE);
         }
         else if(annotation.id.text.equals("@deprecated")) {