]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/deriving/IODeriver.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / internal / deriving / IODeriver.java
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/deriving/IODeriver.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/deriving/IODeriver.java
new file mode 100644 (file)
index 0000000..1726d7d
--- /dev/null
@@ -0,0 +1,187 @@
+package org.simantics.scl.compiler.internal.deriving;
+
+import java.util.ArrayList;
+
+import org.simantics.scl.compiler.common.datatypes.Constructor;
+import org.simantics.scl.compiler.common.names.Name;
+import org.simantics.scl.compiler.constants.ByteConstant;
+import org.simantics.scl.compiler.constants.IntegerConstant;
+import org.simantics.scl.compiler.elaboration.errors.NotPatternException;
+import org.simantics.scl.compiler.elaboration.expressions.Case;
+import org.simantics.scl.compiler.elaboration.expressions.EApply;
+import org.simantics.scl.compiler.elaboration.expressions.EBlock;
+import org.simantics.scl.compiler.elaboration.expressions.EConstant;
+import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
+import org.simantics.scl.compiler.elaboration.expressions.EMatch;
+import org.simantics.scl.compiler.elaboration.expressions.EPreLet;
+import org.simantics.scl.compiler.elaboration.expressions.EVar;
+import org.simantics.scl.compiler.elaboration.expressions.Expression;
+import org.simantics.scl.compiler.elaboration.expressions.block.LetStatement;
+import org.simantics.scl.compiler.elaboration.modules.SCLValue;
+import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;
+import org.simantics.scl.compiler.environment.AmbiguousNameException;
+import org.simantics.scl.compiler.environment.Environment;
+import org.simantics.scl.compiler.environment.Environments;
+import org.simantics.scl.compiler.errors.ErrorLog;
+import org.simantics.scl.compiler.internal.parsing.declarations.DDerivingInstanceAst;
+import org.simantics.scl.compiler.internal.parsing.declarations.DInstanceAst;
+import org.simantics.scl.compiler.internal.parsing.declarations.DValueAst;
+import org.simantics.scl.compiler.internal.parsing.expressions.Expressions;
+import org.simantics.scl.compiler.internal.parsing.translation.ProcessedDInstanceAst;
+import org.simantics.scl.compiler.internal.parsing.translation.ValueRepository;
+import org.simantics.scl.compiler.internal.parsing.types.TVarAst;
+import org.simantics.scl.compiler.types.TCon;
+
+class IODeriver implements InstanceDeriver {
+
+    private static final Name WRITE = Name.create("Serialization", "write");
+    private static final Name READ = Name.create("Serialization", "read");
+    private static final Name IO_SIZE = Name.create("Serialization", "ioSize");
+    
+    @Override
+    public void derive(
+            ErrorLog errorLog,
+            Environment environment,
+            ArrayList<ProcessedDInstanceAst> instancesAst,
+            DDerivingInstanceAst der) {
+        // Analyze
+        if(der.types.length != 1) {
+            errorLog.log(der.location, "Invalid number of parameters to " + der.name);
+            return;
+        }
+        TVarAst headType = DerivingUtils.getHeadType(der.types[0]);
+        if(headType == null) {
+            errorLog.log(der.types[0].location, "Cannot derive IO instance for the type " + headType + ".");
+            return;
+        }
+        TCon con;
+        try {
+            con = Environments.getTypeConstructorName(environment, headType.name);
+        } catch (AmbiguousNameException e1) {
+            errorLog.log(headType.location, e1.getMessage());
+            return;
+        }
+        if(con == null) {
+            errorLog.log(headType.location, "Couldn't resolve " + headType.name);
+            return;
+        }
+        TypeConstructor tcon = environment.getTypeConstructor(con);
+        if(tcon == null) {
+            errorLog.log(headType.location, "Didn't find type constructor for " + headType.name);
+            return;
+        }
+        if(tcon.isOpen) {
+            errorLog.log(headType.location, "Cannot derive instance for open data types.");
+            return;
+        }
+        
+        DInstanceAst instanceAst = new DInstanceAst(der.location, der.context, der.name, der.types);
+        ValueRepository valueDefs = new ValueRepository();
+        
+        SCLValue write = environment.getValue(WRITE);
+        SCLValue read = environment.getValue(READ);
+        SCLValue ioSize = environment.getValue(IO_SIZE);
+        
+        // Generate write
+        for(int id=0;id<tcon.constructors.length;++id) {
+            Constructor constructor = tcon.constructors[id];
+            int l = constructor.parameterTypes.length;
+            String[] par = new String[l];
+            for(int i=0;i<l;++i) {
+                par[i] = "v" + i;
+            }
+            Expression lhs = new EApply(
+                    new EVar("write"),
+                    new EVar("s"),
+                    new EApply(new EVar(constructor.name.name), Expressions.vars(par))
+                    );
+            ArrayList<Expression> statements = new ArrayList<Expression>();
+            statements.add(
+                    new EApply(new EConstant(write), new EVar("s"),
+                            new ELiteral(new ByteConstant((byte)id))));
+            for(int i=0;i<l;++i)
+                statements.add(new EApply(new EConstant(write), new EVar("s"), new EVar(par[i])));
+            
+            Expression rhs = EBlock.create(statements);
+            try {
+                DValueAst valueAst = new DValueAst(lhs, rhs);
+                valueAst.setLocationDeep(der.location);
+                valueDefs.add(valueAst);
+                /*valueDefs.addAnnotation("write", new DAnnotationAst(new EVar("@private"), 
+                        Collections.<Expression>emptyList()));*/
+            } catch (NotPatternException e) {
+                errorLog.log(e.getExpression().location, "Not a pattern.");
+            }
+        }
+        
+        // Generate read
+        {
+            Expression lhs = new EApply(
+                    new EVar("read"),
+                    new EVar("s")
+                    );
+            Case[] cases = new Case[tcon.constructors.length];
+            for(int id=0;id<tcon.constructors.length;++id) {
+                Constructor constructor = tcon.constructors[id];
+                int l = constructor.parameterTypes.length;
+                String[] par = new String[l];
+                for(int i=0;i<l;++i) {
+                    par[i] = "v" + i;
+                }
+                ArrayList<LetStatement> assignments = new ArrayList<LetStatement>(l);
+                for(int i=0;i<l;++i)
+                    assignments.add(new LetStatement(new EVar(par[i]), 
+                            new EApply(new EConstant(read), new EVar("s"))));
+                Expression in = new EApply(
+                        new EVar(constructor.name.name),
+                        Expressions.vars(par));
+                cases[id] = new Case(new ELiteral(new ByteConstant((byte)id)),
+                        new EPreLet(assignments, in));
+            }
+            Expression rhs =
+                    new EMatch(new EApply(new EConstant(read), new EVar("s")),
+                            cases);
+            try {
+                DValueAst valueAst = new DValueAst(lhs, rhs);
+                valueAst.setLocationDeep(der.location);
+                valueDefs.add(valueAst);
+                /*valueDefs.addAnnotation("read=", new DAnnotationAst(new EVar("@private"), 
+                        Collections.<Expression>emptyList()));*/
+            } catch (NotPatternException e) {
+                errorLog.log(e.getExpression().location, "Not a pattern.");
+            }
+        }
+        
+        // Generate ioSize
+        for(int id=0;id<tcon.constructors.length;++id) {
+            Constructor constructor = tcon.constructors[id];
+            int l = constructor.parameterTypes.length;
+            String[] par = new String[l];
+            for(int i=0;i<l;++i) {
+                par[i] = "v" + i;
+            }
+            Expression lhs = new EApply(
+                    new EVar("ioSize"),
+                    new EApply(new EVar(constructor.name.name), Expressions.vars(par))
+                    );
+            Expression rhs = new ELiteral(new IntegerConstant(1));
+            for(int i=0;i<l;++i)
+                rhs = new EApply(new EVar("+"),
+                        rhs,
+                        new EApply(new EConstant(ioSize), new EVar(par[i]))
+                        );
+            try {
+                DValueAst valueAst = new DValueAst(lhs, rhs);
+                valueAst.setLocationDeep(der.location);
+                valueDefs.add(valueAst);
+                /*valueDefs.addAnnotation("ioSize", new DAnnotationAst(new EVar("@private"), 
+                        Collections.<Expression>emptyList()));*/
+            } catch (NotPatternException e) {
+                errorLog.log(e.getExpression().location, "Not a pattern.");
+            }
+        }
+        
+        instancesAst.add(new ProcessedDInstanceAst(instanceAst, valueDefs));
+    }
+
+}