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