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.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;
26 public class CodeWriter {
28 ModuleWriter moduleWriter;
31 CodeWriter(ModuleWriter moduleWriter, SSABlock block) {
32 this.moduleWriter = moduleWriter;
36 public IVal apply(int lineNumber, IVal function, IVal ... parameters) {
38 MultiFunction mfun = Types.matchFunction(function.getType(), parameters.length);
39 return applyWithEffect(lineNumber,
42 function, parameters);
43 } catch (MatchException e) {
44 throw new InternalCompilerError(e);
48 public IVal applyWithEffectChecked(int lineNumber, Type effect, Type returnType, IVal function, IVal ... parameters) {
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);
58 return applyWithEffect(lineNumber, effect, returnType, function, parameters);
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,
65 function.createOccurrence(),
66 ValRef.createOccurrences(parameters));
67 apply.location = location;
68 block.addStatement(apply);
72 public CodeWriter createBlock(Type ... parameterTypes) {
73 SSABlock newBlock = new SSABlock(parameterTypes);
74 block.getParent().addBlock(newBlock);
75 return new CodeWriter(moduleWriter, newBlock);
78 public CodeWriter createFunction(TVar[] typeParameters, Type effect, Type returnType, Type[] parameterTypes) {
79 if(SCLCompilerConfiguration.DEBUG)
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);
88 this.block.addStatement(new LetFunctions(function));
89 return new CodeWriter(moduleWriter, block);
92 public RecursiveDefinitionWriter createRecursiveDefinition() {
93 LetFunctions let = new LetFunctions();
94 block.addStatement(let);
95 return new RecursiveDefinitionWriter(moduleWriter, let);
98 public void continueAs(CodeWriter codeWriter) {
99 this.block = codeWriter.block;
100 codeWriter.block = null;
103 public IVal[] getParameters() {
104 return block.getParameters();
107 public ICont getContinuation() {
111 public void jump(ICont cont, IVal ... parameters) {
112 block.setExit(new Jump(cont.createOccurrence(),
113 ValRef.createOccurrences(parameters)));
117 public void if_(IVal condition, ICont thenTarget, ICont elseTarget) {
118 block.setExit(new If(condition.createOccurrence(),
119 thenTarget.createOccurrence(),
120 elseTarget.createOccurrence()));
124 public void return_(IVal val) {
125 jump(block.getParent().getReturnCont(), val);
128 public void switch_(IVal val, Branch[] branches) {
129 block.setExit(new Switch(val.createOccurrence(), BranchRef.toBranchRefs(branches)));
133 public void throw_(long location, TypeDesc exceptionClass, String description) {
134 Throw exit = new Throw(exceptionClass, description);
135 exit.location = location;
140 public ModuleWriter getModuleWriter() {
144 public SSAFunction getFunction() {
145 return block.getParent();