]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/writer/CodeWriter.java
bb774bd24e798b10cbd3ce1d58cf4bdc8c85fb6a
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / internal / codegen / writer / CodeWriter.java
1 package org.simantics.scl.compiler.internal.codegen.writer;
2
3 import org.cojen.classfile.TypeDesc;
4 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
5 import org.simantics.scl.compiler.errors.Locations;
6 import org.simantics.scl.compiler.internal.codegen.continuations.Branch;
7 import org.simantics.scl.compiler.internal.codegen.continuations.BranchRef;
8 import org.simantics.scl.compiler.internal.codegen.continuations.ICont;
9 import org.simantics.scl.compiler.internal.codegen.references.BoundVar;
10 import org.simantics.scl.compiler.internal.codegen.references.IVal;
11 import org.simantics.scl.compiler.internal.codegen.references.ValRef;
12 import org.simantics.scl.compiler.internal.codegen.ssa.SSABlock;
13 import org.simantics.scl.compiler.internal.codegen.ssa.SSAFunction;
14 import org.simantics.scl.compiler.internal.codegen.ssa.SSAObject;
15 import org.simantics.scl.compiler.internal.codegen.ssa.exits.If;
16 import org.simantics.scl.compiler.internal.codegen.ssa.exits.Jump;
17 import org.simantics.scl.compiler.internal.codegen.ssa.exits.Switch;
18 import org.simantics.scl.compiler.internal.codegen.ssa.exits.Throw;
19 import org.simantics.scl.compiler.internal.codegen.ssa.statements.LetApply;
20 import org.simantics.scl.compiler.internal.codegen.ssa.statements.LetFunctions;
21 import org.simantics.scl.compiler.top.SCLCompilerConfiguration;
22 import org.simantics.scl.compiler.types.TVar;
23 import org.simantics.scl.compiler.types.Type;
24 import org.simantics.scl.compiler.types.Types;
25 import org.simantics.scl.compiler.types.exceptions.MatchException;
26 import org.simantics.scl.compiler.types.util.MultiFunction;
27
28 public class CodeWriter {
29
30     ModuleWriter moduleWriter;
31     SSABlock block;
32     
33     public CodeWriter(ModuleWriter moduleWriter, SSABlock block) {
34         this.moduleWriter = moduleWriter;
35         this.block = block;
36     }
37     
38     private int lineNumber(long location) {
39         if(location == Locations.NO_LOCATION)
40             return -1;
41         else {
42             int position = Locations.beginOf(location);
43             int line = moduleWriter.lineLocator.lineNumberFromPosition(position);
44             //System.out.println("location=" + location + ", position=" + position + ", line=" + line);
45             return line + 1;
46         }
47     }
48
49     public IVal apply(long location, IVal function, IVal ... parameters) {
50         try {
51             MultiFunction mfun = Types.matchFunction(function.getType(), parameters.length);
52             return applyWithEffect(location,
53                     mfun.effect,
54                     mfun.returnType,
55                     function, parameters);
56         } catch (MatchException e) {
57             throw new InternalCompilerError(e);
58         }
59     }
60     
61     public IVal applyWithEffectChecked(long location, Type effect, Type returnType, IVal function, IVal ... parameters) {
62         try {
63             MultiFunction mfun = Types.matchFunction(function.getType(), parameters.length);
64             if(!Types.equals(effect, mfun.effect))
65                 throw new InternalCompilerError();
66             if(!Types.equals(returnType, mfun.returnType))
67                 throw new InternalCompilerError();
68         } catch (MatchException e) {
69             throw new InternalCompilerError(e);
70         }            
71         return applyWithEffect(location, effect, returnType, function, parameters);
72     }
73     
74     public IVal applyWithEffect(long location, Type effect, Type returnType, IVal function, IVal ... parameters) {
75         BoundVar var = new BoundVar(returnType);
76         LetApply apply = new LetApply(var,
77                 effect,
78                 function.createOccurrence(), 
79                 ValRef.createOccurrences(parameters));
80         apply.lineNumber = lineNumber(location);
81         block.addStatement(apply);
82         return var;
83     }
84     
85     public CodeWriter createBlock() {
86         SSABlock newBlock = new SSABlock(Type.EMPTY_ARRAY);
87         block.getParent().addBlock(newBlock);
88         return new CodeWriter(moduleWriter, newBlock);
89     }
90     
91     public CodeWriter createBlock(Type ... parameterTypes) {
92         SSABlock newBlock = new SSABlock(parameterTypes);
93         block.getParent().addBlock(newBlock);
94         return new CodeWriter(moduleWriter, newBlock);
95     }
96     
97     public CodeWriter createFunction(TVar[] typeParameters, Type effect, Type returnType, Type[] parameterTypes) {
98         if(SCLCompilerConfiguration.DEBUG)
99             if(effect == null)
100                 throw new InternalCompilerError();
101         SSAFunction function = new SSAFunction(typeParameters, effect, returnType);
102         SSABlock block = new SSABlock(parameterTypes);
103         function.addBlock(block);
104         BoundVar target = new BoundVar(function.getType());
105         function.setTarget(target);
106         
107         this.block.addStatement(new LetFunctions(function));
108         return new CodeWriter(moduleWriter, block);
109     }
110     
111     public RecursiveDefinitionWriter createRecursiveDefinition() {
112         LetFunctions let = new LetFunctions();
113         block.addStatement(let);
114         return new RecursiveDefinitionWriter(moduleWriter, let);
115     }
116     
117     public void continueAs(CodeWriter codeWriter) {
118         this.block = codeWriter.block;
119         codeWriter.block = null;
120     }
121     
122     public IVal[] getParameters() {
123         return block.getParameters();
124     }
125     
126     public ICont getContinuation() {
127         return block;
128     }
129     
130     public void jump(long location, ICont cont, IVal ... parameters) {
131         block.setExit(new Jump(
132                 lineNumber(location),
133                 cont.createOccurrence(), 
134                 ValRef.createOccurrences(parameters)));
135         block = null;
136     }
137     
138     public void if_(long location, IVal condition, ICont thenTarget, ICont elseTarget) {
139         block.setExit(new If(
140                 lineNumber(location),
141                 condition.createOccurrence(), 
142                 thenTarget.createOccurrence(), 
143                 elseTarget.createOccurrence()));
144         block = null;
145     }
146     
147     public void branchAwayIf(long location, IVal condition, ICont target) {
148         SSABlock newBlock = new SSABlock(Type.EMPTY_ARRAY);
149         block.getParent().addBlock(newBlock);
150         block.setExit(new If(
151                 lineNumber(location),
152                 condition.createOccurrence(), 
153                 target.createOccurrence(), 
154                 newBlock.createOccurrence()));
155         this.block = newBlock;
156     }
157     
158     public void branchAwayUnless(long location, IVal condition, ICont target) {
159         SSABlock newBlock = new SSABlock(Type.EMPTY_ARRAY);
160         block.getParent().addBlock(newBlock);
161         block.setExit(new If(
162                 lineNumber(location),
163                 condition.createOccurrence(), 
164                 newBlock.createOccurrence(),
165                 target.createOccurrence()));
166         this.block = newBlock;
167     }
168
169     public void return_(long location, IVal val) {
170         jump(lineNumber(location), block.getParent().getReturnCont(), val);
171     }
172
173     public void switch_(long location, IVal val, Branch[] branches) {
174         block.setExit(new Switch(lineNumber(location), val.createOccurrence(), BranchRef.toBranchRefs(branches)));
175         block = null;
176     }
177
178     public void throw_(long location, TypeDesc exceptionClass, String description) {
179         Throw exit = new Throw(lineNumber(location), exceptionClass, description);
180         block.setExit(exit);
181         block = null;
182     }
183     
184     public ModuleWriter getModuleWriter() {
185                 return moduleWriter;
186         }
187
188     public SSAFunction getFunction() {
189         return block.getParent();
190     }
191
192     public boolean isUnfinished() {
193         return block != null;
194     }
195
196     public void defineObject(SSAObject object) {
197         this.block.addStatement(new LetFunctions(object));
198     }
199 }