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