]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/Elaboration.java
(refs #6924) Support for record field access syntax.
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / compilation / Elaboration.java
index 5461d7a29a0c680bb2752dc4b20da355daa6b78b..9dbd94691a82cd27bab16a4a7be498e39fee2852 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;
@@ -92,6 +95,8 @@ import org.simantics.scl.compiler.internal.parsing.translation.ValueRepository;
 import org.simantics.scl.compiler.internal.parsing.types.TypeAst;
 import org.simantics.scl.compiler.module.ConcreteModule;
 import org.simantics.scl.compiler.module.ImportDeclaration;
+import org.simantics.scl.compiler.module.InvalidModulePathException;
+import org.simantics.scl.compiler.module.ModuleUtils;
 import org.simantics.scl.compiler.module.repository.ImportFailure;
 import org.simantics.scl.compiler.module.repository.ImportFailureException;
 import org.simantics.scl.compiler.types.TCon;
@@ -157,6 +162,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();
@@ -184,14 +191,16 @@ public class Elaboration {
         ArrayList<ImportDeclaration> absoluteImports = new ArrayList<ImportDeclaration>(relativeImports.size());
         for(ImportDeclaration relativeImport : relativeImports) {
             if(relativeImport.moduleName.startsWith(".")) {
-                String absoluteModuleName = convertRelativeModulePath(relativeImport.location, relativeImport.moduleName);
-                if(absoluteModuleName != null) {
+                               try {
+                                       String absoluteModuleName = ModuleUtils.resolveAbsolutePath(moduleName, relativeImport.moduleName);
                     ImportDeclaration absoluteImport = new ImportDeclaration(
                             absoluteModuleName, relativeImport.localName,
                             relativeImport.reexport, relativeImport.spec);
                     absoluteImport.location = relativeImport.location;
                     absoluteImports.add(absoluteImport);
-                }
+                               } catch (InvalidModulePathException e) {
+                                       errorLog.log(relativeImport.location, e.getMessage());
+                               }
             }
             else
                 absoluteImports.add(relativeImport);
@@ -199,31 +208,6 @@ public class Elaboration {
         return absoluteImports;
     }
 
-    private String convertRelativeModulePath(long location, String relativeModuleName) {
-        String originalRelativeModuleName = relativeModuleName;
-        int p = moduleName.lastIndexOf('/');
-        String parentPackage = p < 0 ? "" : moduleName.substring(0, p);
-        while(relativeModuleName.startsWith(".")) {
-            if(relativeModuleName.startsWith("./")) {
-                relativeModuleName = relativeModuleName.substring(2);
-            }
-            else if(relativeModuleName.startsWith("../")) {
-                relativeModuleName = relativeModuleName.substring(3);
-                if(parentPackage.isEmpty()) {
-                    errorLog.log(location, "Couldn't resolve the relative module name " + originalRelativeModuleName + " when the current module name is " + moduleName + ".");
-                    return null;
-                }
-                p = parentPackage.lastIndexOf('/');
-                parentPackage = p < 0 ? "" : parentPackage.substring(0, p);
-            }
-            else {
-                errorLog.log(location, "Couldn't resolve the relative module name " + originalRelativeModuleName + ". It has an invalid syntax.");
-                return null;
-            }
-        }
-        return parentPackage + "/" + relativeModuleName;
-    }
-
     public void addTypesToEnvironment(
             ArrayList<DDataAst> dataTypesAst,
             ArrayList<DTypeAst> typeAliasesAst,
@@ -335,6 +319,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];
@@ -414,7 +399,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) {