]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/Elaboration.java
(refs #7260) Added a new DerivedProperty to SCLValues
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / compilation / Elaboration.java
index 898f6c0a5680c88bad669e56c5395a5fe65d0164..7887ed717f032b7d29aed50782a69e0f6b42c916 100644 (file)
@@ -7,6 +7,7 @@ import java.util.List;
 import org.cojen.classfile.TypeDesc;
 import org.simantics.scl.compiler.common.datatypes.Constructor;
 import org.simantics.scl.compiler.common.names.Name;
+import org.simantics.scl.compiler.constants.Constant;
 import org.simantics.scl.compiler.constants.JavaTypeInstanceConstructor;
 import org.simantics.scl.compiler.constants.SCLConstructor;
 import org.simantics.scl.compiler.constants.StringConstant;
@@ -14,12 +15,14 @@ import org.simantics.scl.compiler.constants.generic.CallJava;
 import org.simantics.scl.compiler.constants.generic.ClassRef;
 import org.simantics.scl.compiler.constants.generic.ConvertToListFilter;
 import org.simantics.scl.compiler.constants.generic.MethodRef;
+import org.simantics.scl.compiler.constants.generic.MethodRef.FieldRef;
 import org.simantics.scl.compiler.constants.generic.OutputFilter;
 import org.simantics.scl.compiler.constants.generic.ParameterStackItem;
 import org.simantics.scl.compiler.constants.generic.Pop2OutputFilter;
 import org.simantics.scl.compiler.constants.generic.PopOutputFilter;
 import org.simantics.scl.compiler.constants.generic.StackItem;
 import org.simantics.scl.compiler.constants.generic.ThreadLocalStackItem;
+import org.simantics.scl.compiler.constants.singletons.SafeCoerce;
 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
 import org.simantics.scl.compiler.elaboration.contexts.TypeTranslationContext;
 import org.simantics.scl.compiler.elaboration.errors.NotPatternException;
@@ -36,6 +39,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;
@@ -159,6 +163,8 @@ public class Elaboration {
 
         module = new ConcreteModule(moduleName);
         compilationContext.module = module;
+        if(moduleHeader != null && moduleHeader.defaultLocalName != null)
+               module.setDefaultLocalName(moduleHeader.defaultLocalName);
         try {
             if(timer != null)
                 timer.suspendTimer();
@@ -314,6 +320,7 @@ public class Elaboration {
     }
     
     public void processDataTypes(ArrayList<DDataAst> dataTypesAst) {
+        ArrayList<Runnable> fieldAccessorGenerators = new ArrayList<Runnable>(); 
         for(DDataAst dataTypeAst : dataTypesAst) {
             TypeTranslationContext context = createTypeTranslationContext();
             TVar[] typeParameters = new TVar[dataTypeAst.parameters.length];
@@ -393,7 +400,34 @@ public class Elaboration {
                 constructors[j].fieldNames = fieldNames;
                 constructors[j].recordFieldNames = constructor.fieldNames;
             }
+            if(constructors.length == 1) {
+                Constructor constructor = constructors[0];
+                if(constructor.recordFieldNames != null) {
+                    fieldAccessorGenerators.add(new Runnable() {
+                        @Override
+                        public void run() {
+                            Type in = Types.apply(dataType.name, dataType.parameters);
+                            for(int i=0;i<constructor.recordFieldNames.length;++i) {
+                                Type out = constructor.parameterTypes[i];
+                                Constant accessor;
+                                if(trivialDataType)
+                                    accessor = new SafeCoerce(dataType.parameters, in, out);
+                                else
+                                    accessor = new CallJava(dataType.parameters, Types.NO_EFFECTS, out,
+                                            new Type[] {in}, new StackItem[] {new ParameterStackItem(0, in)},
+                                            new FieldRef(constructor.javaName, constructor.fieldNames != null ? constructor.fieldNames[i] : "c" + i,
+                                                    javaTypeTranslator.toTypeDesc(out)),
+                                            null);
+                                module.addFieldAccessor(constructor.recordFieldNames[i], accessor);
+                            }
+                        }
+                    });
+                }
+            }
         }
+        
+        for(Runnable fieldAccessorGenerator : fieldAccessorGenerators)
+            fieldAccessorGenerator.run();
     }
     
     public void processTypeClasses(ArrayList<ProcessedDClassAst> typeClassesAst) {
@@ -554,6 +588,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);
@@ -1065,7 +1100,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());
@@ -1110,6 +1146,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) {
@@ -1137,6 +1175,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 {
@@ -1154,11 +1200,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) {
@@ -1196,6 +1247,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")) {