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.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;
28 public class CodeWriter {
30 ModuleWriter moduleWriter;
33 public CodeWriter(ModuleWriter moduleWriter, SSABlock block) {
34 this.moduleWriter = moduleWriter;
38 private int lineNumber(long location) {
39 if(location == Locations.NO_LOCATION)
42 int position = Locations.beginOf(location);
43 int line = moduleWriter.lineLocator.lineNumberFromPosition(position);
44 //System.out.println("location=" + location + ", position=" + position + ", line=" + line);
49 public IVal apply(long location, IVal function, IVal ... parameters) {
51 MultiFunction mfun = Types.matchFunction(function.getType(), parameters.length);
52 return applyWithEffect(location,
55 function, parameters);
56 } catch (MatchException e) {
57 throw new InternalCompilerError(e);
61 public IVal applyWithEffectChecked(long location, Type effect, Type returnType, IVal function, IVal ... parameters) {
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);
71 return applyWithEffect(location, effect, returnType, function, parameters);
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,
78 function.createOccurrence(),
79 ValRef.createOccurrences(parameters));
80 apply.lineNumber = lineNumber(location);
81 block.addStatement(apply);
85 public CodeWriter createBlock() {
86 SSABlock newBlock = new SSABlock(Type.EMPTY_ARRAY);
87 block.getParent().addBlock(newBlock);
88 return new CodeWriter(moduleWriter, newBlock);
91 public CodeWriter createBlock(Type ... parameterTypes) {
92 SSABlock newBlock = new SSABlock(parameterTypes);
93 block.getParent().addBlock(newBlock);
94 return new CodeWriter(moduleWriter, newBlock);
97 public CodeWriter createFunction(TVar[] typeParameters, Type effect, Type returnType, Type[] parameterTypes) {
98 if(SCLCompilerConfiguration.DEBUG)
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);
107 this.block.addStatement(new LetFunctions(function));
108 return new CodeWriter(moduleWriter, block);
111 public RecursiveDefinitionWriter createRecursiveDefinition() {
112 LetFunctions let = new LetFunctions();
113 block.addStatement(let);
114 return new RecursiveDefinitionWriter(moduleWriter, let);
117 public void continueAs(CodeWriter codeWriter) {
118 this.block = codeWriter.block;
119 codeWriter.block = null;
122 public IVal[] getParameters() {
123 return block.getParameters();
126 public ICont getContinuation() {
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)));
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()));
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;
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;
169 public void return_(long location, IVal val) {
170 jump(lineNumber(location), block.getParent().getReturnCont(), val);
173 public void switch_(long location, IVal val, Branch[] branches) {
174 block.setExit(new Switch(lineNumber(location), val.createOccurrence(), BranchRef.toBranchRefs(branches)));
178 public void throw_(long location, TypeDesc exceptionClass, String description) {
179 Throw exit = new Throw(lineNumber(location), exceptionClass, description);
184 public ModuleWriter getModuleWriter() {
188 public SSAFunction getFunction() {
189 return block.getParent();
192 public boolean isUnfinished() {
193 return block != null;
196 public void defineObject(SSAObject object) {
197 this.block.addStatement(new LetFunctions(object));