--- /dev/null
+package org.simantics.scl.compiler.internal.codegen.writer;\r
+\r
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
+import org.simantics.scl.compiler.internal.codegen.continuations.Branch;\r
+import org.simantics.scl.compiler.internal.codegen.continuations.BranchRef;\r
+import org.simantics.scl.compiler.internal.codegen.continuations.ICont;\r
+import org.simantics.scl.compiler.internal.codegen.references.BoundVar;\r
+import org.simantics.scl.compiler.internal.codegen.references.IVal;\r
+import org.simantics.scl.compiler.internal.codegen.references.ValRef;\r
+import org.simantics.scl.compiler.internal.codegen.ssa.SSABlock;\r
+import org.simantics.scl.compiler.internal.codegen.ssa.SSAFunction;\r
+import org.simantics.scl.compiler.internal.codegen.ssa.exits.If;\r
+import org.simantics.scl.compiler.internal.codegen.ssa.exits.Jump;\r
+import org.simantics.scl.compiler.internal.codegen.ssa.exits.Switch;\r
+import org.simantics.scl.compiler.internal.codegen.ssa.exits.Throw;\r
+import org.simantics.scl.compiler.internal.codegen.ssa.statements.LetApply;\r
+import org.simantics.scl.compiler.internal.codegen.ssa.statements.LetFunctions;\r
+import org.simantics.scl.compiler.top.SCLCompilerConfiguration;\r
+import org.simantics.scl.compiler.types.TVar;\r
+import org.simantics.scl.compiler.types.Type;\r
+import org.simantics.scl.compiler.types.Types;\r
+import org.simantics.scl.compiler.types.exceptions.MatchException;\r
+import org.simantics.scl.compiler.types.util.MultiFunction;\r
+\r
+public class CodeWriter {\r
+\r
+ ModuleWriter moduleWriter;\r
+ SSABlock block;\r
+ \r
+ CodeWriter(ModuleWriter moduleWriter, SSABlock block) {\r
+ this.moduleWriter = moduleWriter;\r
+ this.block = block;\r
+ }\r
+\r
+ public IVal apply(int lineNumber, IVal function, IVal ... parameters) {\r
+ try {\r
+ MultiFunction mfun = Types.matchFunction(function.getType(), parameters.length);\r
+ return applyWithEffect(lineNumber,\r
+ mfun.effect,\r
+ mfun.returnType,\r
+ function, parameters);\r
+ } catch (MatchException e) {\r
+ throw new InternalCompilerError(e);\r
+ }\r
+ }\r
+ \r
+ public IVal applyWithEffectChecked(int lineNumber, Type effect, Type returnType, IVal function, IVal ... parameters) {\r
+ try {\r
+ MultiFunction mfun = Types.matchFunction(function.getType(), parameters.length);\r
+ if(!Types.equals(effect, mfun.effect))\r
+ throw new InternalCompilerError();\r
+ if(!Types.equals(returnType, mfun.returnType))\r
+ throw new InternalCompilerError();\r
+ } catch (MatchException e) {\r
+ throw new InternalCompilerError(e);\r
+ } \r
+ return applyWithEffect(lineNumber, effect, returnType, function, parameters);\r
+ }\r
+ \r
+ public IVal applyWithEffect(long location, Type effect, Type returnType, IVal function, IVal ... parameters) {\r
+ BoundVar var = new BoundVar(returnType);\r
+ LetApply apply = new LetApply(var,\r
+ effect,\r
+ function.createOccurrence(), \r
+ ValRef.createOccurrences(parameters));\r
+ apply.location = location;\r
+ block.addStatement(apply);\r
+ return var;\r
+ }\r
+ \r
+ public CodeWriter createBlock(Type ... parameterTypes) {\r
+ SSABlock newBlock = new SSABlock(parameterTypes);\r
+ block.getParent().addBlock(newBlock);\r
+ return new CodeWriter(moduleWriter, newBlock);\r
+ }\r
+ \r
+ public CodeWriter createFunction(TVar[] typeParameters, Type effect, Type returnType, Type[] parameterTypes) {\r
+ if(SCLCompilerConfiguration.DEBUG)\r
+ if(effect == null)\r
+ throw new InternalCompilerError();\r
+ SSAFunction function = new SSAFunction(typeParameters, effect, returnType);\r
+ SSABlock block = new SSABlock(parameterTypes);\r
+ function.addBlock(block);\r
+ BoundVar target = new BoundVar(function.getType());\r
+ function.setTarget(target);\r
+ \r
+ this.block.addStatement(new LetFunctions(function));\r
+ return new CodeWriter(moduleWriter, block);\r
+ }\r
+ \r
+ public RecursiveDefinitionWriter createRecursiveDefinition() {\r
+ LetFunctions let = new LetFunctions();\r
+ block.addStatement(let);\r
+ return new RecursiveDefinitionWriter(moduleWriter, let);\r
+ }\r
+ \r
+ public void continueAs(CodeWriter codeWriter) {\r
+ this.block = codeWriter.block;\r
+ codeWriter.block = null;\r
+ }\r
+ \r
+ public IVal[] getParameters() {\r
+ return block.getParameters();\r
+ }\r
+ \r
+ public ICont getContinuation() {\r
+ return block;\r
+ }\r
+ \r
+ public void jump(ICont cont, IVal ... parameters) {\r
+ block.setExit(new Jump(cont.createOccurrence(), \r
+ ValRef.createOccurrences(parameters)));\r
+ block = null;\r
+ }\r
+ \r
+ public void if_(IVal condition, ICont thenTarget, ICont elseTarget) {\r
+ block.setExit(new If(condition.createOccurrence(), \r
+ thenTarget.createOccurrence(), \r
+ elseTarget.createOccurrence()));\r
+ block = null;\r
+ }\r
+\r
+ public void return_(IVal val) {\r
+ jump(block.getParent().getReturnCont(), val);\r
+ }\r
+\r
+ public void switch_(IVal val, Branch[] branches) {\r
+ block.setExit(new Switch(val.createOccurrence(), BranchRef.toBranchRefs(branches)));\r
+ block = null;\r
+ }\r
+\r
+ public void throw_(long location, String description) {\r
+ Throw exit = new Throw(description);\r
+ exit.location = location;\r
+ block.setExit(exit);\r
+ block = null;\r
+ }\r
+ \r
+ public ModuleWriter getModuleWriter() {\r
+ return moduleWriter;\r
+ }\r
+\r
+ public SSAFunction getFunction() {\r
+ return block.getParent();\r
+ } \r
+}\r