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