]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/deriving/IODeriver.java
Merge "List the unsatisfied dependencies in CanvasContext"
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / internal / deriving / IODeriver.java
1 package org.simantics.scl.compiler.internal.deriving;
2
3 import java.util.ArrayList;
4
5 import org.simantics.scl.compiler.common.datatypes.Constructor;
6 import org.simantics.scl.compiler.common.names.Names;
7 import org.simantics.scl.compiler.constants.ByteConstant;
8 import org.simantics.scl.compiler.constants.IntegerConstant;
9 import org.simantics.scl.compiler.elaboration.errors.NotPatternException;
10 import org.simantics.scl.compiler.elaboration.expressions.Case;
11 import org.simantics.scl.compiler.elaboration.expressions.EApply;
12 import org.simantics.scl.compiler.elaboration.expressions.EBlock;
13 import org.simantics.scl.compiler.elaboration.expressions.EConstant;
14 import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
15 import org.simantics.scl.compiler.elaboration.expressions.EMatch;
16 import org.simantics.scl.compiler.elaboration.expressions.EPreLet;
17 import org.simantics.scl.compiler.elaboration.expressions.EVar;
18 import org.simantics.scl.compiler.elaboration.expressions.Expression;
19 import org.simantics.scl.compiler.elaboration.expressions.block.LetStatement;
20 import org.simantics.scl.compiler.elaboration.modules.SCLValue;
21 import org.simantics.scl.compiler.elaboration.modules.TypeAlias;
22 import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;
23 import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;
24 import org.simantics.scl.compiler.environment.AmbiguousNameException;
25 import org.simantics.scl.compiler.environment.Environment;
26 import org.simantics.scl.compiler.environment.Environments;
27 import org.simantics.scl.compiler.errors.ErrorLog;
28 import org.simantics.scl.compiler.internal.parsing.declarations.DDerivingInstanceAst;
29 import org.simantics.scl.compiler.internal.parsing.declarations.DInstanceAst;
30 import org.simantics.scl.compiler.internal.parsing.declarations.DValueAst;
31 import org.simantics.scl.compiler.internal.parsing.expressions.Expressions;
32 import org.simantics.scl.compiler.internal.parsing.translation.ProcessedDInstanceAst;
33 import org.simantics.scl.compiler.internal.parsing.translation.ValueRepository;
34 import org.simantics.scl.compiler.internal.parsing.types.TVarAst;
35 import org.simantics.scl.compiler.types.TCon;
36
37 class IODeriver implements InstanceDeriver {
38     
39     @Override
40     public void derive(
41             ErrorLog errorLog,
42             Environment environment,
43             ArrayList<ProcessedDInstanceAst> instancesAst,
44             DDerivingInstanceAst der) {
45         // Analyze
46         if(der.types.length != 1) {
47             errorLog.log(der.location, "Invalid number of parameters to " + der.name);
48             return;
49         }
50         TVarAst headType = DerivingUtils.getHeadType(der.types[0]);
51         if(headType == null) {
52             errorLog.log(der.types[0].location, "Cannot derive IO instance for the type " + headType + ".");
53             return;
54         }
55         TCon con;
56         try {
57             con = Environments.getTypeDescriptorName(environment, headType.name);
58         } catch (AmbiguousNameException e1) {
59             errorLog.log(headType.location, e1.getMessage());
60             return;
61         }
62         if(con == null) {
63             errorLog.log(headType.location, "Couldn't resolve " + headType.name);
64             return;
65         }
66         TypeDescriptor tdesc = environment.getTypeDescriptor(con);
67         if(tdesc == null) {
68             errorLog.log(headType.location, "Didn't find type constructor for " + headType.name);
69             return;
70         }
71         if(tdesc instanceof TypeAlias) {
72             errorLog.log(headType.location, "Cannot derive instance for a type alias.");
73             return;
74         }
75         TypeConstructor tcon = (TypeConstructor)tdesc;
76         if(tcon.isOpen) {
77             errorLog.log(headType.location, "Cannot derive instance for open data types.");
78             return;
79         }
80         
81         DInstanceAst instanceAst = new DInstanceAst(der.location, der.context, der.name, der.types);
82         ValueRepository valueDefs = new ValueRepository();
83         
84         SCLValue write = environment.getValue(Names.Serialization_write);
85         SCLValue read = environment.getValue(Names.Serialization_read);
86         SCLValue ioSize = environment.getValue(Names.Serialization_ioSize);
87         
88         // Generate write
89         for(int id=0;id<tcon.constructors.length;++id) {
90             Constructor constructor = tcon.constructors[id];
91             int l = constructor.parameterTypes.length;
92             String[] par = new String[l];
93             for(int i=0;i<l;++i) {
94                 par[i] = "v" + i;
95             }
96             Expression lhs = new EApply(
97                     new EVar("write"),
98                     new EVar("s"),
99                     new EApply(new EVar(constructor.name.name), Expressions.vars(par))
100                     );
101             ArrayList<Expression> statements = new ArrayList<Expression>();
102             statements.add(
103                     new EApply(new EConstant(write), new EVar("s"),
104                             new ELiteral(new ByteConstant((byte)id))));
105             for(int i=0;i<l;++i)
106                 statements.add(new EApply(new EConstant(write), new EVar("s"), new EVar(par[i])));
107             
108             Expression rhs = EBlock.create(statements);
109             try {
110                 DValueAst valueAst = new DValueAst(lhs, rhs);
111                 valueAst.setLocationDeep(der.location);
112                 valueDefs.add(valueAst);
113                 /*valueDefs.addAnnotation("write", new DAnnotationAst(new EVar("@private"), 
114                         Collections.<Expression>emptyList()));*/
115             } catch (NotPatternException e) {
116                 errorLog.log(e.getExpression().location, "Not a pattern.");
117             }
118         }
119         
120         // Generate read
121         {
122             Expression lhs = new EApply(
123                     new EVar("read"),
124                     new EVar("s")
125                     );
126             Case[] cases = new Case[tcon.constructors.length];
127             for(int id=0;id<tcon.constructors.length;++id) {
128                 Constructor constructor = tcon.constructors[id];
129                 int l = constructor.parameterTypes.length;
130                 String[] par = new String[l];
131                 for(int i=0;i<l;++i) {
132                     par[i] = "v" + i;
133                 }
134                 ArrayList<LetStatement> assignments = new ArrayList<LetStatement>(l);
135                 for(int i=0;i<l;++i)
136                     assignments.add(new LetStatement(new EVar(par[i]), 
137                             new EApply(new EConstant(read), new EVar("s"))));
138                 Expression in = new EApply(
139                         new EVar(constructor.name.name),
140                         Expressions.vars(par));
141                 cases[id] = new Case(new ELiteral(new ByteConstant((byte)id)),
142                         new EPreLet(assignments, in));
143             }
144             Expression rhs =
145                     new EMatch(new EApply(new EConstant(read), new EVar("s")),
146                             cases);
147             try {
148                 DValueAst valueAst = new DValueAst(lhs, rhs);
149                 valueAst.setLocationDeep(der.location);
150                 valueDefs.add(valueAst);
151                 /*valueDefs.addAnnotation("read=", new DAnnotationAst(new EVar("@private"), 
152                         Collections.<Expression>emptyList()));*/
153             } catch (NotPatternException e) {
154                 errorLog.log(e.getExpression().location, "Not a pattern.");
155             }
156         }
157         
158         // Generate ioSize
159         for(int id=0;id<tcon.constructors.length;++id) {
160             Constructor constructor = tcon.constructors[id];
161             int l = constructor.parameterTypes.length;
162             String[] par = new String[l];
163             for(int i=0;i<l;++i) {
164                 par[i] = "v" + i;
165             }
166             Expression lhs = new EApply(
167                     new EVar("ioSize"),
168                     new EApply(new EVar(constructor.name.name), Expressions.vars(par))
169                     );
170             Expression rhs = new ELiteral(new IntegerConstant(1));
171             for(int i=0;i<l;++i)
172                 rhs = new EApply(new EVar("+"),
173                         rhs,
174                         new EApply(new EConstant(ioSize), new EVar(par[i]))
175                         );
176             try {
177                 DValueAst valueAst = new DValueAst(lhs, rhs);
178                 valueAst.setLocationDeep(der.location);
179                 valueDefs.add(valueAst);
180                 /*valueDefs.addAnnotation("ioSize", new DAnnotationAst(new EVar("@private"), 
181                         Collections.<Expression>emptyList()));*/
182             } catch (NotPatternException e) {
183                 errorLog.log(e.getExpression().location, "Not a pattern.");
184             }
185         }
186         
187         instancesAst.add(new ProcessedDInstanceAst(instanceAst, valueDefs));
188     }
189
190 }