From fc2cb126576a7d0f3e6e1d4812992e4e69e481cd Mon Sep 17 00:00:00 2001 From: =?utf8?q?Hannu=20Niemist=C3=B6?= Date: Fri, 20 Oct 2017 11:02:08 +0300 Subject: [PATCH] (refs #7567) Added throw function to builtins Change-Id: I273e5c85b4a842e0ce4dc1603800742f9fbb6ea5 --- .../scl/compiler/constants/FailFunction.java | 39 --------- .../constants/singletons/ThrowFunction.java | 52 ++++++++++++ .../compiler/elaboration/java/Builtins.java | 3 + .../internal/codegen/ssa/SSAStatement.java | 8 ++ .../internal/codegen/ssa/exits/Throw2.java | 82 +++++++++++++++++++ .../codegen/ssa/statements/LetStatement.java | 2 +- .../compiler/tests/ModuleRegressionTests.java | 1 + .../scl/compiler/tests/scl/Throw1.scl | 10 +++ 8 files changed, 157 insertions(+), 40 deletions(-) delete mode 100644 bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/FailFunction.java create mode 100644 bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/singletons/ThrowFunction.java create mode 100644 bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/Throw2.java create mode 100644 tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/Throw1.scl diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/FailFunction.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/FailFunction.java deleted file mode 100644 index 2a47c39a6..000000000 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/FailFunction.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.simantics.scl.compiler.constants; - -import org.cojen.classfile.TypeDesc; -import org.simantics.scl.compiler.internal.codegen.references.Val; -import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder; -import org.simantics.scl.compiler.types.TVar; -import org.simantics.scl.compiler.types.Type; -import org.simantics.scl.compiler.types.Types; -import org.simantics.scl.compiler.types.kinds.Kinds; - -public class FailFunction extends FunctionValue { - - private static final TVar A = Types.var(Kinds.STAR); - public static final FailFunction INSTANCE = - new FailFunction(); - - private FailFunction() { - super(new TVar[] {A}, Types.NO_EFFECTS, A, Types.STRING); - } - - private static final TypeDesc RuntimeException = - TypeDesc.forClass(RuntimeException.class); - - @Override - public Type applyExact(MethodBuilder mb, Val[] parameters) { - mb.newObject(RuntimeException); - mb.dup(); - mb.push(parameters, parameterTypes); - mb.invokeConstructor(RuntimeException, - new TypeDesc[] {TypeDesc.STRING}); - mb.throwObject(); - return getReturnType(); - } - - @Override - public String toString() { - return "fail"; - } -} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/singletons/ThrowFunction.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/singletons/ThrowFunction.java new file mode 100644 index 000000000..f98e635c2 --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/singletons/ThrowFunction.java @@ -0,0 +1,52 @@ +package org.simantics.scl.compiler.constants.singletons; + +import org.simantics.scl.compiler.constants.FunctionValue; +import org.simantics.scl.compiler.internal.codegen.references.Val; +import org.simantics.scl.compiler.internal.codegen.ssa.SSABlock; +import org.simantics.scl.compiler.internal.codegen.ssa.SSAStatement; +import org.simantics.scl.compiler.internal.codegen.ssa.exits.Throw2; +import org.simantics.scl.compiler.internal.codegen.ssa.statements.LetApply; +import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder; +import org.simantics.scl.compiler.internal.codegen.utils.SSASimplificationContext; +import org.simantics.scl.compiler.types.TVar; +import org.simantics.scl.compiler.types.Type; +import org.simantics.scl.compiler.types.Types; +import org.simantics.scl.compiler.types.kinds.Kinds; + +public class ThrowFunction extends FunctionValue { + + private static final TVar A = Types.var(Kinds.STAR); + private static final TVar B = Types.var(Kinds.STAR); + public static final ThrowFunction INSTANCE = + new ThrowFunction(); + + private ThrowFunction() { + super(new TVar[] {A, B}, Types.PROC, B, A); + } + + @Override + public Type applyExact(MethodBuilder mb, Val[] parameters) { + mb.pushBoxed(parameters[0]); + mb.throwObject(); + return getReturnType(); + } + + @Override + public String toString() { + return "throw"; + } + + @Override + public void inline(SSASimplificationContext context, LetApply apply) { + if(apply.getParameters().length != 1) + return; // shouldn't be possible + + SSABlock block = apply.getParent(); + for(SSAStatement statement=apply.getNext();statement != null;statement=statement.getNext()) + statement.destroy(); + apply.getFunction().remove(); + apply.detachThisAndSuccessors(); + block.getExit().destroy(); + block.setExit(new Throw2(apply.getParameters()[0])); + } +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/Builtins.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/Builtins.java index 45638c056..631ef2ddc 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/Builtins.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/Builtins.java @@ -18,6 +18,7 @@ import org.simantics.scl.compiler.constants.singletons.BindingConstant; import org.simantics.scl.compiler.constants.singletons.FailFunction; import org.simantics.scl.compiler.constants.singletons.JustConstant; import org.simantics.scl.compiler.constants.singletons.NothingConstant; +import org.simantics.scl.compiler.constants.singletons.ThrowFunction; import org.simantics.scl.compiler.constants.singletons.TypeOfConstant; import org.simantics.scl.compiler.constants.singletons.TypeOfProxyConstant; import org.simantics.scl.compiler.constants.singletons.TypeProxyConstant; @@ -209,6 +210,8 @@ public class Builtins extends ConcreteModule { addValue("fail", FailFunction.INSTANCE).documentation = "Throws a runtime exeception with the given string as a description."; + addValue("throw", ThrowFunction.INSTANCE).documentation = + "Throws a given exception."; // *** runProc *** diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSAStatement.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSAStatement.java index e957723d3..a5d0bdc9f 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSAStatement.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSAStatement.java @@ -125,4 +125,12 @@ public abstract class SSAStatement implements Printable { public abstract void forValRefs(ValRefVisitor visitor); public abstract void cleanup(); + + public void detachThisAndSuccessors() { + parent.lastStatement = prev; + if(prev == null) + parent.firstStatement = null; + else + prev.next = null; + } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/Throw2.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/Throw2.java new file mode 100644 index 000000000..78353b424 --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/Throw2.java @@ -0,0 +1,82 @@ +package org.simantics.scl.compiler.internal.codegen.ssa.exits; + +import java.util.ArrayList; + +import org.simantics.scl.compiler.internal.codegen.continuations.Cont; +import org.simantics.scl.compiler.internal.codegen.continuations.ContRef; +import org.simantics.scl.compiler.internal.codegen.references.Val; +import org.simantics.scl.compiler.internal.codegen.references.ValRef; +import org.simantics.scl.compiler.internal.codegen.ssa.SSABlock; +import org.simantics.scl.compiler.internal.codegen.ssa.SSAExit; +import org.simantics.scl.compiler.internal.codegen.ssa.SSAFunction; +import org.simantics.scl.compiler.internal.codegen.utils.CopyContext; +import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder; +import org.simantics.scl.compiler.internal.codegen.utils.PrintingContext; +import org.simantics.scl.compiler.internal.codegen.utils.SSAValidationContext; +import org.simantics.scl.compiler.internal.codegen.utils.ValRefVisitor; +import org.simantics.scl.compiler.types.TVar; +import org.simantics.scl.compiler.types.Type; + +public class Throw2 extends SSAExit { + + ValRef exception; + + public Throw2(ValRef exception) { + this.exception = exception; + } + + @Override + public void toString(PrintingContext context) { + context.append("throw "); + context.append(exception); + context.append('\n'); + } + + @Override + public void generateCode(MethodBuilder mb) { + mb.pushBoxed(exception.getBinding()); + mb.throwObject(); + } + + @Override + public void validate(SSAValidationContext context) { + } + + @Override + public void destroy() { + exception.remove(); + } + + @Override + public SSAExit copy(CopyContext context) { + return new Throw2(exception.copy()); + } + + @Override + public void replace(TVar[] vars, Type[] replacements) { + } + + @Override + public void collectFreeVariables(SSAFunction function, + ArrayList vars) { + } + + @Override + public Cont addParametersInFrontOf(ContRef contRef, Val[] newParameters, Val[] oldParameters, + Cont proxy) { + return proxy; + } + + @Override + public SSABlock[] getSuccessors() { + return SSABlock.EMPTY_ARRAY; + } + + @Override + public void forValRefs(ValRefVisitor visitor) { + } + + @Override + public void cleanup() { + } +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/statements/LetStatement.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/statements/LetStatement.java index 0ae6d8930..02d8977f6 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/statements/LetStatement.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/statements/LetStatement.java @@ -32,7 +32,7 @@ public abstract class LetStatement extends SSAStatement implements BoundVarBinde @Override public void addBoundVariablesTo(SSAValidationContext context) { - context.validBoundVariables.add(target); + context.validBoundVariables.add(target); } } diff --git a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/ModuleRegressionTests.java b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/ModuleRegressionTests.java index 2321a93f6..0e06e61e3 100644 --- a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/ModuleRegressionTests.java +++ b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/ModuleRegressionTests.java @@ -257,6 +257,7 @@ public class ModuleRegressionTests extends TestBase { @Test public void StringMatching1() { test(); } @Test public void SumOfInverses2() { test(); } @Test public void SwitchSimplification() { test(); } + @Test public void Throw1() { test(); } @Test public void TooManyParametersToSin() { test(); } @Test public void Transformation1() { test(); } @Test public void Transformation2() { test(); } diff --git a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/Throw1.scl b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/Throw1.scl new file mode 100644 index 000000000..bc758897b --- /dev/null +++ b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/Throw1.scl @@ -0,0 +1,10 @@ +import "Prelude" + +importJava "java.lang.Exception" where + @JavaName "" + createException :: String -> Exception + +main = throw (createException "Foo") `catch` \(e :: Exception) -> print e +-- +java.lang.Exception: Foo +() \ No newline at end of file -- 2.43.2