1 package org.simantics.scl.compiler.internal.codegen.writer;
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;
27 public class CodeWriter {
29 ModuleWriter moduleWriter;
32 public CodeWriter(ModuleWriter moduleWriter, SSABlock block) {
33 this.moduleWriter = moduleWriter;
37 public IVal apply(long lineNumber, IVal function, IVal ... parameters) {
39 MultiFunction mfun = Types.matchFunction(function.getType(), parameters.length);
40 return applyWithEffect(lineNumber,
43 function, parameters);
44 } catch (MatchException e) {
45 throw new InternalCompilerError(e);
49 public IVal applyWithEffectChecked(long lineNumber, Type effect, Type returnType, IVal function, IVal ... parameters) {
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);
59 return applyWithEffect(lineNumber, effect, returnType, function, parameters);
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,
66 function.createOccurrence(),
67 ValRef.createOccurrences(parameters));
68 apply.location = location;
69 block.addStatement(apply);
73 public CodeWriter createBlock() {
74 SSABlock newBlock = new SSABlock(Type.EMPTY_ARRAY);
75 block.getParent().addBlock(newBlock);
76 return new CodeWriter(moduleWriter, newBlock);
79 public CodeWriter createBlock(Type ... parameterTypes) {
80 SSABlock newBlock = new SSABlock(parameterTypes);
81 block.getParent().addBlock(newBlock);
82 return new CodeWriter(moduleWriter, newBlock);
85 public CodeWriter createFunction(TVar[] typeParameters, Type effect, Type returnType, Type[] parameterTypes) {
86 if(SCLCompilerConfiguration.DEBUG)
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);
95 this.block.addStatement(new LetFunctions(function));
96 return new CodeWriter(moduleWriter, block);
99 public RecursiveDefinitionWriter createRecursiveDefinition() {
100 LetFunctions let = new LetFunctions();
101 block.addStatement(let);
102 return new RecursiveDefinitionWriter(moduleWriter, let);
105 public void continueAs(CodeWriter codeWriter) {
106 this.block = codeWriter.block;
107 codeWriter.block = null;
110 public IVal[] getParameters() {
111 return block.getParameters();
114 public ICont getContinuation() {
118 public void jump(ICont cont, IVal ... parameters) {
119 block.setExit(new Jump(cont.createOccurrence(),
120 ValRef.createOccurrences(parameters)));
124 public void if_(IVal condition, ICont thenTarget, ICont elseTarget) {
125 block.setExit(new If(condition.createOccurrence(),
126 thenTarget.createOccurrence(),
127 elseTarget.createOccurrence()));
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;
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;
149 public void return_(IVal val) {
150 jump(block.getParent().getReturnCont(), val);
153 public void switch_(IVal val, Branch[] branches) {
154 block.setExit(new Switch(val.createOccurrence(), BranchRef.toBranchRefs(branches)));
158 public void throw_(long location, TypeDesc exceptionClass, String description) {
159 Throw exit = new Throw(exceptionClass, description);
160 exit.location = location;
165 public ModuleWriter getModuleWriter() {
169 public SSAFunction getFunction() {
170 return block.getParent();
173 public boolean isUnfinished() {
174 return block != null;
177 public void defineObject(SSAObject object) {
178 this.block.addStatement(new LetFunctions(object));