changeset 12752:71991b7a0f14

SL: Enhanced SimpleLanguage with support for if statements, function calls, function caching + inlining and builtins.
author Christian Humer <christian.humer@gmail.com>
date Mon, 11 Nov 2013 21:34:44 +0100
parents 882a0aadfed6
children 53f8adcbc474
files graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeChildTest.java graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/AddTest.java graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/BuiltinsTest.java graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/CallTest.java graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/ComparisonTest.java graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/DivTest.java graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/FibonacciTest.java graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/LoopPrintTest.java graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/MulTest.java graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SubTest.java graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/TernaryTest.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/NodeFactory.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLArguments.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLNodeFactory.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLScript.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLTypes.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SimpleLanguage.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/BuiltinNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/DefaultBuiltins.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/PrintBuiltin.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/TimeBuiltin.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ArgumentsNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/CallNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/FunctionBodyNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/FunctionDefinitionNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/FunctionRootNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/IfNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/NullLiteralNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/PrintLineNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/PrintNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ReadArgumentNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ReadFunctionNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ReadLocalNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ReadUninitializedNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/TimeNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/TypedNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.frame graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java.old graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/ParserUtils.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.frame graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.java.old graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLArguments.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLFunctionRegistry.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLNull.java
diffstat 49 files changed, 3377 insertions(+), 903 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeChildTest.java	Mon Nov 11 21:34:44 2013 +0100
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.api.dsl.test;
+
+import static com.oracle.truffle.api.dsl.test.TestHelper.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.IntFieldTestNodeFactory;
+import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode;
+
+public class NodeChildTest {
+
+    @Test
+    public void testIntField() {
+        assertEquals(42, createCallTarget(IntFieldTestNodeFactory.create(42)).call());
+    }
+
+    @NodeChild("child0")
+    abstract static class Base0Node extends ValueNode {
+
+    }
+
+    @NodeChild(value = "child1", type = ValueNode.class)
+    abstract static class Child0Node extends Base0Node {
+
+        @Specialization
+        int intField(int child0, int child1) {
+            return child0 + child1;
+        }
+    }
+
+    @NodeChildren({@NodeChild("child0")})
+    abstract static class Base1Node extends ValueNode {
+
+    }
+
+    @NodeChildren({@NodeChild(value = "child1", type = ValueNode.class)})
+    abstract static class Child1Node extends Base1Node {
+
+        @Specialization
+        int intField(int child0, int child1) {
+            return child0 + child1;
+        }
+    }
+
+    @NodeChildren({@NodeChild("child0"), @NodeChild("child1")})
+    abstract static class Base2Node extends ValueNode {
+
+    }
+
+    @NodeChildren({@NodeChild(value = "child2", type = ValueNode.class)})
+    abstract static class Child2Node extends Base1Node {
+
+        // TODO this is an error to fix
+        @ExpectError("Method signature (int, int, int) does not match to the expected signature:%")
+        @Specialization
+        int intField(int child0, int child1, int child2) {
+            return child0 + child1 + child2;
+        }
+    }
+
+    @NodeChildren({@NodeChild(value = "receiver", type = ValueNode.class), @NodeChild(value = "arguments", type = ValueNode[].class)})
+    abstract static class BaseNode extends ValueNode {
+        public abstract ValueNode getReceiver();
+
+        public abstract ValueNode[] getArguments();
+    }
+
+    abstract static class UnaryNode extends BaseNode {
+        @Specialization
+        public int doIt(int value) {
+            return value;
+        }
+    }
+
+    abstract static class BinaryNode extends BaseNode {
+        @Specialization
+        public int doIt(int value0, int value1) {
+            return value0 + value1;
+        }
+    }
+
+    abstract static class TernaryNode extends BaseNode {
+        @Specialization
+        public int doIt(int value0, int value1, int value2) {
+            return value0 + value1 + value2;
+        }
+    }
+
+}
--- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/AddTest.java	Thu Nov 07 20:55:13 2013 +0100
+++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/AddTest.java	Mon Nov 11 21:34:44 2013 +0100
@@ -29,13 +29,13 @@
 
     private static String[] INPUT = new String[] {
         "function main {  ",
-        "  print 3 + 4;  ",
-        "  print 3 + \"4\";  ",
-        "  print \"3\" + 4;  ",
-        "  print \"3\" + \"4\";  ",
-        "  print 3 + 4000000000000;  ",
-        "  print 3000000000000 + 4;  ",
-        "  print 3000000000000 + 4000000000000;  ",
+        "  print(3 + 4);  ",
+        "  print(3 + \"4\");  ",
+        "  print(\"3\" + 4);  ",
+        "  print(\"3\" + \"4\");  ",
+        "  print(3 + 4000000000000);  ",
+        "  print(3000000000000 + 4);  ",
+        "  print(3000000000000 + 4000000000000);  ",
         "}  ",
     };
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/BuiltinsTest.java	Mon Nov 11 21:34:44 2013 +0100
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.test;
+
+import org.junit.*;
+
+// @formatter:off
+public class BuiltinsTest extends AbstractTest {
+
+    private static String[] INPUT = new String[] {
+        "function main {  ",
+        "  print(\"Hello World!\");  ",
+        "  time();  ",
+        "}  ",
+    };
+
+    private static String[] OUTPUT = new String[] {
+        "Hello World!",
+    };
+
+    @Test
+    public void test() {
+        executeSL(INPUT, OUTPUT, false);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/CallTest.java	Mon Nov 11 21:34:44 2013 +0100
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.test;
+
+import org.junit.*;
+
+// @formatter:off
+public class CallTest extends AbstractTest {
+
+    private static String[] INPUT = new String[] {
+        "function ret(a) { return a; } ",
+        "function dub(a) { return a * 2; } ",
+        "function inc(a) { return a + 1; } ",
+        "function dec(a) { return a - 1; } ",
+        "function call(f, v) { return f(v); } ",
+        "function main {  ",
+        "  print(ret(42));",
+        "  print(dub(21));",
+        "  print(inc(41));",
+        "  print(dec(43));",
+        "  print(call(ret, 42));",
+        "  print(call(dub, 21));",
+        "  print(call(inc, 41));",
+        "  print(call(dec, 43));",
+        "}  ",
+    };
+
+    private static String[] OUTPUT = new String[] {
+        "42",
+        "42",
+        "42",
+        "42",
+        "42",
+        "42",
+        "42",
+        "42",
+    };
+
+    @Test
+    public void test() {
+        executeSL(INPUT, OUTPUT, false);
+    }
+}
--- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/ComparisonTest.java	Thu Nov 07 20:55:13 2013 +0100
+++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/ComparisonTest.java	Mon Nov 11 21:34:44 2013 +0100
@@ -29,13 +29,13 @@
 
     private static String[] INPUT = new String[] {
         "function main {  ",
-        "  print 4 < 20;  ",
-        "  print 4 < \"20\";  ",
-        "  print \"4\" < 20;  ",
-        "  print \"4\" < \"20\";  ",
-        "  print 4 < 20000000000000;  ",
-        "  print 4000000000000 < 20;  ",
-        "  print 4000000000000 < 20000000000000;  ",
+        "  print(4 < 20);  ",
+        "  print(4 < \"20\");  ",
+        "  print(\"4\" < 20);  ",
+        "  print(\"4\" < \"20\");  ",
+        "  print(4 < 20000000000000);  ",
+        "  print(4000000000000 < 20);  ",
+        "  print(4000000000000 < 20000000000000);  ",
         "}  ",
     };
 
--- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/DivTest.java	Thu Nov 07 20:55:13 2013 +0100
+++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/DivTest.java	Mon Nov 11 21:34:44 2013 +0100
@@ -29,10 +29,10 @@
 
     private static String[] INPUT = new String[] {
         "function main {  ",
-        "  print 4 / 2;  ",
-        "  print 4 / 4000000000000;  ",
-        "  print 3000000000000 / 3;  ",
-        "  print 3000000000000 / 3000000000000;  ",
+        "  print(4 / 2);  ",
+        "  print(4 / 4000000000000);  ",
+        "  print(3000000000000 / 3);  ",
+        "  print(3000000000000 / 3000000000000);  ",
         "}  ",
     };
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/FibonacciTest.java	Mon Nov 11 21:34:44 2013 +0100
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.test;
+
+import javax.script.*;
+
+import org.junit.*;
+
+import com.oracle.truffle.sl.*;
+import com.oracle.truffle.sl.runtime.*;
+
+// @formatter:off
+public class FibonacciTest extends AbstractTest{
+
+    private static String[] INPUT = new String[] {
+        "function fib(num) { ",
+        "  if (num < 1) {return 0;}",
+        "  n1 = 0;",
+        "  n2 = 1;",
+        "  i = 1;",
+        "  while (i < num) {",
+        "    next = n2 + n1;",
+        "    n1 = n2;",
+        "    n2 = next;",
+        "    i = i + 1;",
+        "  }",
+        "  return n2;",
+        "}",
+        "function main(num) {  ",
+        "  return fib(num);",
+        "}  ",
+    };
+
+    // java reference
+    private static int test(int num) {
+        if (num <= 0) {
+            return 0;
+        }
+        int n1 = 0;
+        int n2 = 1;
+        for (int i = 1; i < num; i++) {
+            final int next = n2 + n1;
+            n1 = n2;
+            n2 = next;
+        }
+        return n2;
+    }
+
+    private static final int TEST_VALUE = 42;
+    private static final int ITERATIONS = 5000;
+
+    @Test
+    public void test() throws ScriptException {
+        StringBuilder s = new StringBuilder();
+        for (String line : INPUT) {
+            s.append(line).append("\n");
+        }
+        SLScript script = SLScript.create(new SLContext(System.out), s.toString());
+        Integer reference = test(TEST_VALUE);
+        for (int i = 0; i < ITERATIONS; i++) {
+            if (!reference.equals(script.run(TEST_VALUE))) {
+                throw new AssertionError();
+            }
+        }
+    }
+}
--- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/LoopPrintTest.java	Thu Nov 07 20:55:13 2013 +0100
+++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/LoopPrintTest.java	Mon Nov 11 21:34:44 2013 +0100
@@ -33,7 +33,7 @@
         "  while (i < 1000) {  ",
         "    i = i + 1;  ",
         "  }  ",
-        "  print i;  ",
+        "  print(i);  ",
         "}  ",
     };
 
--- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/MulTest.java	Thu Nov 07 20:55:13 2013 +0100
+++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/MulTest.java	Mon Nov 11 21:34:44 2013 +0100
@@ -29,10 +29,10 @@
 
     private static String[] INPUT = new String[] {
         "function main {  ",
-        "  print 3 * 4;  ",
-        "  print 3 * 4000000000000;  ",
-        "  print 3000000000000 * 4;  ",
-        "  print 3000000000000 * 4000000000000;  ",
+        "  print(3 * 4);  ",
+        "  print(3 * 4000000000000);  ",
+        "  print(3000000000000 * 4);  ",
+        "  print(3000000000000 * 4000000000000);  ",
         "}  ",
     };
 
--- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SubTest.java	Thu Nov 07 20:55:13 2013 +0100
+++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SubTest.java	Mon Nov 11 21:34:44 2013 +0100
@@ -29,10 +29,10 @@
 
     private static String[] INPUT = new String[] {
         "function main {  ",
-        "  print 3 - 4;  ",
-        "  print 3 - 4000000000000;  ",
-        "  print 3000000000000 - 4;  ",
-        "  print 3000000000000 - 4000000000000;  ",
+        "  print(3 - 4);  ",
+        "  print(3 - 4000000000000);  ",
+        "  print(3000000000000 - 4);  ",
+        "  print(3000000000000 - 4000000000000);  ",
         "}  ",
     };
 
--- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/TernaryTest.java	Thu Nov 07 20:55:13 2013 +0100
+++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/TernaryTest.java	Mon Nov 11 21:34:44 2013 +0100
@@ -29,11 +29,11 @@
 
     private static String[] INPUT = new String[] {
         "function main {  " +
-        "  print #(1 < 2) ? 1 : 2;" +
-        "  print #(2 < 1) ? 100000000000000 : 1;  ",
-        "  print #(1 < 2) ? 100000000000000 : 1;  ",
-        "  print #(2 < 1) ? \"wrong\" : \"true\";",
-        "  print #(2 < 1) ? \"wrong\" : 1;",
+        "  print(#(1 < 2) ? 1 : 2);" +
+        "  print(#(2 < 1) ? 100000000000000 : 1);  ",
+        "  print(#(1 < 2) ? 100000000000000 : 1);  ",
+        "  print(#(2 < 1) ? \"wrong\" : \"true\");",
+        "  print(#(2 < 1) ? \"wrong\" : 1);",
         "}  ",
     };
 
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/NodeFactory.java	Thu Nov 07 20:55:13 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,137 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl;
-
-import java.io.*;
-import java.math.*;
-import java.util.*;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.sl.nodes.ArithmeticNodeFactory.AddNodeFactory;
-import com.oracle.truffle.sl.nodes.ArithmeticNodeFactory.DivNodeFactory;
-import com.oracle.truffle.sl.nodes.ArithmeticNodeFactory.MulNodeFactory;
-import com.oracle.truffle.sl.nodes.ArithmeticNodeFactory.SubNodeFactory;
-import com.oracle.truffle.sl.nodes.*;
-
-public class NodeFactory {
-
-    private final HashMap<String, FunctionDefinitionNode> functions;
-    private final PrintStream printOutput;
-
-    private FrameDescriptor frameDescriptor;
-    private TypedNode returnValue;
-
-    public NodeFactory(PrintStream printOutput) {
-        this.functions = new HashMap<>();
-        this.printOutput = printOutput;
-    }
-
-    public FunctionDefinitionNode findFunction(String name) {
-        return functions.get(name);
-    }
-
-    public void startFunction() {
-        frameDescriptor = new FrameDescriptor();
-    }
-
-    public void createFunction(StatementNode body, String name) {
-        functions.put(name, new FunctionDefinitionNode(body, frameDescriptor, name, returnValue));
-    }
-
-    public TypedNode createLocal(String name) {
-        return ReadLocalNodeFactory.create(frameDescriptor.findOrAddFrameSlot(name, FrameSlotKind.Int));
-    }
-
-    public TypedNode createStringLiteral(String value) {
-        return new StringLiteralNode(value);
-    }
-
-    public StatementNode createAssignment(String name, TypedNode right) {
-        return WriteLocalNodeFactory.create(frameDescriptor.findOrAddFrameSlot(name, FrameSlotKind.Int), right);
-    }
-
-    public StatementNode createPrint(List<TypedNode> expressions) {
-        if (expressions.size() >= 1) {
-            StatementNode[] nodes = new StatementNode[expressions.size() + 1];
-            for (int i = 0; i < expressions.size(); i++) {
-                nodes[i] = PrintNodeFactory.create(printOutput, expressions.get(i));
-            }
-            nodes[expressions.size()] = new PrintLineNode(printOutput);
-            return new BlockNode(nodes);
-        } else {
-            return new BlockNode(new StatementNode[]{new PrintLineNode(printOutput)});
-        }
-    }
-
-    public StatementNode createWhile(ConditionNode condition, StatementNode body) {
-        return new WhileNode(condition, body);
-    }
-
-    public StatementNode createBlock(List<StatementNode> statements) {
-        return new BlockNode(statements.toArray(new StatementNode[statements.size()]));
-    }
-
-    public TypedNode createBinary(String operation, TypedNode left, TypedNode right) {
-        switch (operation) {
-            case "+":
-                return AddNodeFactory.create(left, right);
-            case "*":
-                return MulNodeFactory.create(left, right);
-            case "/":
-                return DivNodeFactory.create(left, right);
-            case "-":
-                return SubNodeFactory.create(left, right);
-            case "<":
-                return LessThanNodeFactory.create(left, right);
-            case "&&":
-                return LogicalAndNodeFactory.create(left, right);
-            default:
-                throw new RuntimeException("unexpected operation: " + operation);
-        }
-    }
-
-    public TypedNode createNumericLiteral(String value) {
-        try {
-            return new IntegerLiteralNode(Integer.parseInt(value));
-        } catch (NumberFormatException ex) {
-            return new BigIntegerLiteralNode(new BigInteger(value));
-        }
-    }
-
-    public TypedNode createTime() {
-        return TimeNodeFactory.create();
-    }
-
-    public StatementNode createReturn(TypedNode value) {
-        FrameSlot slot = frameDescriptor.findOrAddFrameSlot("<retval>", FrameSlotKind.Int);
-        if (returnValue == null) {
-            returnValue = ReadLocalNodeFactory.create(slot);
-        }
-        StatementNode write = WriteLocalNodeFactory.create(slot, value);
-        return new ReturnNode(write);
-    }
-
-    public TypedNode createTernary(TypedNode condition, TypedNode thenPart, TypedNode elsePart) {
-        return TernaryNodeFactory.create(condition, thenPart, elsePart);
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLArguments.java	Thu Nov 07 20:55:13 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl;
-
-import com.oracle.truffle.api.*;
-
-public final class SLArguments extends Arguments {
-
-    public final Object[] arguments;
-
-    public SLArguments(Object[] arguments) {
-        this.arguments = arguments;
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLNode.java	Thu Nov 07 20:55:13 2013 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLNode.java	Mon Nov 11 21:34:44 2013 +0100
@@ -35,7 +35,7 @@
 
     @Override
     public String toString() {
-        return NodeUtil.printTreeToString(this);
+        return getEncapsulatingSourceSection() != null ? getEncapsulatingSourceSection().toString() : super.toString();
     }
 
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLNodeFactory.java	Mon Nov 11 21:34:44 2013 +0100
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl;
+
+import java.math.*;
+import java.util.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.sl.nodes.ArithmeticNodeFactory.AddNodeFactory;
+import com.oracle.truffle.sl.nodes.ArithmeticNodeFactory.DivNodeFactory;
+import com.oracle.truffle.sl.nodes.ArithmeticNodeFactory.MulNodeFactory;
+import com.oracle.truffle.sl.nodes.ArithmeticNodeFactory.SubNodeFactory;
+import com.oracle.truffle.sl.nodes.*;
+import com.oracle.truffle.sl.parser.*;
+import com.oracle.truffle.sl.runtime.*;
+
+public class SLNodeFactory {
+
+    private final SLContext context;
+
+    private Parser parser;
+    private FrameDescriptor frameDescriptor;
+    private TypedNode returnValue;
+
+    private Source source;
+    private String currentFunctionName;
+
+    public SLNodeFactory(SLContext context) {
+        this.context = context;
+    }
+
+    public void setSource(Source source) {
+        this.source = source;
+    }
+
+    public void setParser(Parser parser) {
+        this.parser = parser;
+    }
+
+    public CallTarget findFunction(String name) {
+        return context.getFunctionRegistry().lookup(name);
+    }
+
+    public void startFunction() {
+        frameDescriptor = new FrameDescriptor();
+    }
+
+    public void createFunction(StatementNode body, String name, String[] parameterNames) {
+        context.getFunctionRegistry().register(name, FunctionRootNode.createFunction(body, frameDescriptor, name, returnValue, parameterNames));
+        this.currentFunctionName = name;
+        this.returnValue = null;
+    }
+
+    private <T extends Node> T assignSource(T node) {
+        node.assignSourceSection(ParserUtils.createSourceSection(source, currentFunctionName, parser));
+        return node;
+    }
+
+    public TypedNode createLocal(String name) {
+        return assignSource(new ReadUninitializedNode(context, frameDescriptor.findOrAddFrameSlot(name, FrameSlotKind.Int)));
+    }
+
+    public TypedNode createStringLiteral(String value) {
+        return assignSource(new StringLiteralNode(value));
+    }
+
+    public TypedNode createAssignment(TypedNode read, TypedNode assignment) {
+        FrameSlot slot = ((ReadUninitializedNode) read).getSlot();
+        return assignSource(WriteLocalNodeFactory.create(slot, assignment));
+    }
+
+    public StatementNode createWhile(ConditionNode condition, StatementNode body) {
+        return assignSource(new WhileNode(condition, body));
+    }
+
+    public StatementNode createBlock(List<StatementNode> statements) {
+        return assignSource(new BlockNode(statements.toArray(new StatementNode[statements.size()])));
+    }
+
+    public TypedNode createCall(TypedNode function, TypedNode[] parameters) {
+        return assignSource(CallNode.create(function, parameters));
+    }
+
+    public TypedNode createBinary(String operation, TypedNode left, TypedNode right) {
+        TypedNode binary;
+        switch (operation) {
+            case "+":
+                binary = AddNodeFactory.create(left, right);
+                break;
+            case "*":
+                binary = MulNodeFactory.create(left, right);
+                break;
+            case "/":
+                binary = DivNodeFactory.create(left, right);
+                break;
+            case "-":
+                binary = SubNodeFactory.create(left, right);
+                break;
+            case "<":
+                binary = LessThanNodeFactory.create(left, right);
+                break;
+            case "&&":
+                binary = LogicalAndNodeFactory.create(left, right);
+                break;
+            default:
+                throw new RuntimeException("unexpected operation: " + operation);
+        }
+        return assignSource(binary);
+    }
+
+    public TypedNode createNumericLiteral(String value) {
+        try {
+            return assignSource(new IntegerLiteralNode(Integer.parseInt(value)));
+        } catch (NumberFormatException ex) {
+            return assignSource(new BigIntegerLiteralNode(new BigInteger(value)));
+        }
+    }
+
+    public StatementNode createReturn(TypedNode value) {
+        FrameSlot slot = frameDescriptor.findOrAddFrameSlot("<retval>", FrameSlotKind.Int);
+        if (returnValue == null) {
+            returnValue = ReadLocalNodeFactory.create(slot);
+        }
+        StatementNode write = WriteLocalNodeFactory.create(slot, value);
+        return assignSource(new ReturnNode(write));
+    }
+
+    public TypedNode createTernary(TypedNode condition, TypedNode thenPart, TypedNode elsePart) {
+        return assignSource(TernaryNodeFactory.create(condition, thenPart, elsePart));
+    }
+
+    public StatementNode createIf(ConditionNode condition, StatementNode then, StatementNode elseNode) {
+        return assignSource(IfNodeFactory.create(then, elseNode, condition));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLScript.java	Mon Nov 11 21:34:44 2013 +0100
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl;
+
+import java.io.*;
+
+import javax.script.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.sl.parser.*;
+import com.oracle.truffle.sl.runtime.*;
+
+public final class SLScript {
+
+    private final SLContext context;
+    private final CallTarget main;
+
+    private SLScript(SLContext context, CallTarget mainFunction) {
+        this.context = context;
+        this.main = mainFunction;
+    }
+
+    public SLContext getContext() {
+        return context;
+    }
+
+    public CallTarget getMain() {
+        return main;
+    }
+
+    public Object run(Object... arguments) {
+        return main.call(null, new SLArguments(arguments));
+    }
+
+    @Override
+    public String toString() {
+        return main.toString();
+    }
+
+    public static SLScript create(SLContext context, String input) throws ScriptException {
+        return create(context, new ByteArrayInputStream(input.getBytes()));
+
+    }
+
+    public static SLScript create(SLContext context, InputStream input) throws ScriptException {
+        SLNodeFactory factory = new SLNodeFactory(context);
+        Parser parser = new Parser(new Scanner(input), factory);
+        factory.setParser(parser);
+        factory.setSource(new Source() {
+            public String getName() {
+                return "Unknown";
+            }
+
+            public String getCode() {
+                return null;
+            }
+        });
+        String error = parser.ParseErrors();
+        if (!error.isEmpty()) {
+            throw new ScriptException(String.format("Error(s) parsing script: %s", error));
+        }
+
+        CallTarget main = context.getFunctionRegistry().lookup("main");
+        if (main == null) {
+            throw new ScriptException("No main function found.");
+        }
+        return new SLScript(context, main);
+    }
+}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLTypes.java	Thu Nov 07 20:55:13 2013 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLTypes.java	Mon Nov 11 21:34:44 2013 +0100
@@ -24,26 +24,22 @@
 
 import java.math.*;
 
+import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.sl.runtime.*;
 
-@TypeSystem({int.class, BigInteger.class, boolean.class, String.class})
+@TypeSystem({int.class, BigInteger.class, boolean.class, String.class, CallTarget.class, SLNull.class, Object[].class})
 public class SLTypes {
 
     @TypeCheck
-    public boolean isInteger(Object value) {
-        return value instanceof Integer || (value instanceof BigInteger && ((BigInteger) value).bitLength() < Integer.SIZE);
+    public boolean isSLNull(Object value) {
+        return SLNull.INSTANCE == value;
     }
 
     @TypeCast
-    public int asInteger(Object value) {
-        assert isInteger(value);
-        if (value instanceof Integer) {
-            return (int) value;
-        } else {
-            int result = ((BigInteger) value).intValue();
-            assert BigInteger.valueOf(result).equals(value) : "Losing precision";
-            return result;
-        }
+    public SLNull asSLNull(Object value) {
+        assert isSLNull(value);
+        return SLNull.INSTANCE;
     }
 
     @ImplicitCast
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SimpleLanguage.java	Thu Nov 07 20:55:13 2013 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SimpleLanguage.java	Mon Nov 11 21:34:44 2013 +0100
@@ -24,13 +24,17 @@
 
 import java.io.*;
 
+import javax.script.*;
+
 import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.impl.*;
 import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.sl.nodes.*;
-import com.oracle.truffle.sl.parser.*;
+import com.oracle.truffle.sl.runtime.*;
 
 public class SimpleLanguage {
 
+    private static final Object[] NO_ARGUMENTS = new Object[0];
+
     public static void main(String[] args) throws IOException {
         run(new FileInputStream(args[0]), System.out, 10, true);
     }
@@ -42,23 +46,22 @@
             // CheckStyle: resume system..print check
         }
 
-        NodeFactory factory = new NodeFactory(printOutput);
-
-        Parser parser = new Parser(new Scanner(input), factory);
-        parser.Parse();
-
-        FunctionDefinitionNode rootNode = factory.findFunction("main");
-        if (log) {
-            NodeUtil.printTree(System.out, rootNode);
+        SLContext context = new SLContext(printOutput);
+        SLScript script;
+        try {
+            script = SLScript.create(context, input);
+        } catch (ScriptException e) {
+            // TODO temporary hack
+            throw new RuntimeException(e);
         }
 
+        if (log) {
+            printScript(script);
+        }
         try {
-            CallTarget function = Truffle.getRuntime().createCallTarget(rootNode, rootNode.getFrameDescriptor());
             for (int i = 0; i < repeats; i++) {
-                Arguments arguments = new SLArguments(new Object[0]);
-
                 long start = System.nanoTime();
-                Object result = function.call(null, arguments);
+                Object result = script.run(NO_ARGUMENTS);
                 long end = System.nanoTime();
 
                 if (result != null) {
@@ -73,8 +76,12 @@
 
         } finally {
             if (log) {
-                NodeUtil.printTree(System.out, rootNode);
+                printScript(script);
             }
         }
     }
+
+    private static void printScript(SLScript script) {
+        NodeUtil.printTree(System.out, ((DefaultCallTarget) script.getMain()).getRootNode());
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/BuiltinNode.java	Mon Nov 11 21:34:44 2013 +0100
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.builtins;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.sl.nodes.*;
+import com.oracle.truffle.sl.runtime.*;
+
+@NodeField(name = "context", type = SLContext.class)
+@NodeChild(value = "arguments", type = TypedNode[].class)
+public abstract class BuiltinNode extends TypedNode {
+
+    public abstract SLContext getContext();
+
+    public abstract TypedNode[] getArguments();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/DefaultBuiltins.java	Mon Nov 11 21:34:44 2013 +0100
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.builtins;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.sl.nodes.*;
+import com.oracle.truffle.sl.runtime.*;
+
+public abstract class DefaultBuiltins {
+
+    public static void install(SLContext c) {
+        installBuiltin(c, PrintBuiltinFactory.getInstance(), "print");
+        installBuiltin(c, TimeBuiltinFactory.getInstance(), "time");
+    }
+
+    private static void installBuiltin(SLContext context, NodeFactory<? extends BuiltinNode> factory, String name) {
+        context.getFunctionRegistry().register(name, FunctionRootNode.createBuiltin(context, factory, name));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/PrintBuiltin.java	Mon Nov 11 21:34:44 2013 +0100
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.builtins;
+
+import com.oracle.truffle.api.dsl.*;
+
+public abstract class PrintBuiltin extends BuiltinNode {
+
+    @Specialization
+    public int doInt(int value) {
+        getContext().getPrintOutput().println(value);
+        return value;
+    }
+
+    @Specialization
+    public boolean doBoolean(boolean value) {
+        getContext().getPrintOutput().println(value);
+        return value;
+    }
+
+    @Specialization
+    public String doString(String value) {
+        getContext().getPrintOutput().println(value);
+        return value;
+    }
+
+    @Specialization
+    public Object doGeneric(Object value) {
+        getContext().getPrintOutput().println(value.toString());
+        return value;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/TimeBuiltin.java	Mon Nov 11 21:34:44 2013 +0100
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.builtins;
+
+import com.oracle.truffle.api.dsl.*;
+
+public abstract class TimeBuiltin extends BuiltinNode {
+
+    public static final long START_TIME = System.currentTimeMillis();
+
+    @Specialization
+    public int doInt() {
+        return (int) (System.currentTimeMillis() - START_TIME);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ArgumentsNode.java	Mon Nov 11 21:34:44 2013 +0100
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+public final class ArgumentsNode extends TypedNode {
+
+    @Children private final TypedNode[] arguments;
+
+    public ArgumentsNode(TypedNode[] arguments) {
+        this.arguments = adoptChildren(arguments);
+    }
+
+    public TypedNode[] getArguments() {
+        return arguments;
+    }
+
+    @Override
+    public Object[] executeGeneric(VirtualFrame frame) {
+        return executeArray(frame);
+    }
+
+    @Override
+    @ExplodeLoop
+    public Object[] executeArray(VirtualFrame frame) {
+        Object[] argumentValues = new Object[arguments.length];
+        for (int i = 0; i < arguments.length; i++) {
+            argumentValues[i] = arguments[i].executeGeneric(frame);
+        }
+        return argumentValues;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/CallNode.java	Mon Nov 11 21:34:44 2013 +0100
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.impl.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.sl.runtime.*;
+
+public abstract class CallNode extends TypedNode {
+
+    private static final int INLINE_CACHE_SIZE = 2;
+
+    @Child protected TypedNode functionNode;
+
+    private CallNode(TypedNode functionNode) {
+        this.functionNode = adoptChild(functionNode);
+    }
+
+    private CallTarget executeCallTargetNode(VirtualFrame frame) {
+        try {
+            return functionNode.executeCallTarget(frame);
+        } catch (UnexpectedResultException e) {
+            throw new UnsupportedOperationException("Call to " + e.getMessage() + " not supported.");
+        }
+    }
+
+    @Override
+    public final Object executeGeneric(VirtualFrame frame) {
+        return executeGeneric(frame, executeCallTargetNode(frame));
+    }
+
+    public abstract Object executeGeneric(VirtualFrame frame, CallTarget function);
+
+    public static CallNode create(TypedNode function, TypedNode[] arguments) {
+        return new UninitializedCallNode(function, new ArgumentsNode(arguments), 0);
+    }
+
+    private static final class CachedCallNode extends CallNode {
+
+        @Child protected CallNode nextNode;
+        @Child protected TypedNode currentNode;
+        private final CallTarget cachedFunction;
+
+        public CachedCallNode(TypedNode function, TypedNode current, CallNode next, CallTarget cachedFunction) {
+            super(function);
+            this.currentNode = adoptChild(current);
+            this.nextNode = adoptChild(next);
+            this.cachedFunction = cachedFunction;
+        }
+
+        @Override
+        public Object executeGeneric(VirtualFrame frame, CallTarget function) {
+            if (this.cachedFunction == function) {
+                return currentNode.executeGeneric(frame);
+            }
+            return nextNode.executeGeneric(frame, function);
+        }
+    }
+
+    private static final class UninitializedCallNode extends CallNode {
+
+        @Child protected ArgumentsNode uninitializedArgs;
+        protected final int depth;
+
+        UninitializedCallNode(TypedNode function, ArgumentsNode args, int depth) {
+            super(function);
+            this.uninitializedArgs = adoptChild(args);
+            this.depth = depth;
+        }
+
+        UninitializedCallNode(UninitializedCallNode copy) {
+            super(null);
+            this.uninitializedArgs = adoptChild(copy.uninitializedArgs);
+            this.depth = copy.depth + 1;
+        }
+
+        @Override
+        public Object executeGeneric(VirtualFrame frame, CallTarget function) {
+            CompilerDirectives.transferToInterpreter();
+            return specialize(function).executeGeneric(frame, function);
+        }
+
+        private CallNode specialize(CallTarget function) {
+            CompilerAsserts.neverPartOfCompilation();
+
+            if (depth < INLINE_CACHE_SIZE) {
+                TypedNode current = createCacheNode(function);
+                CallNode next = new UninitializedCallNode(this);
+                return replace(new CachedCallNode(this.functionNode, current, next, function));
+            } else {
+                CallNode topMost = (CallNode) getTopNode();
+                return topMost.replace(new GenericCallNode(topMost.functionNode, uninitializedArgs));
+            }
+        }
+
+        protected Node getTopNode() {
+            Node parentNode = this;
+            for (int i = 0; i < depth; i++) {
+                parentNode = parentNode.getParent();
+            }
+            return parentNode;
+        }
+
+        protected TypedNode createCacheNode(CallTarget function) {
+            ArgumentsNode clonedArgs = NodeUtil.cloneNode(uninitializedArgs);
+
+            if (function instanceof DefaultCallTarget) {
+                DefaultCallTarget defaultFunction = (DefaultCallTarget) function;
+                RootNode rootNode = defaultFunction.getRootNode();
+                if (rootNode instanceof FunctionRootNode) {
+                    FunctionRootNode root = (FunctionRootNode) rootNode;
+                    if (root.isAlwaysInline()) {
+                        TypedNode inlinedCall = root.inline(clonedArgs);
+                        if (inlinedCall != null) {
+                            return inlinedCall;
+                        }
+                    }
+                    return new InlinableCallNode((DefaultCallTarget) function, clonedArgs);
+                }
+            }
+
+            // got a call target that is not inlinable (should not occur for SL)
+            return new DispatchedCallNode(function, clonedArgs);
+        }
+    }
+
+    private static final class InlinableCallNode extends DispatchedCallNode implements InlinableCallSite {
+
+        private final DefaultCallTarget inlinableTarget;
+
+        @CompilationFinal private int callCount;
+
+        InlinableCallNode(DefaultCallTarget function, ArgumentsNode arguments) {
+            super(function, arguments);
+            this.inlinableTarget = function;
+        }
+
+        @Override
+        public int getCallCount() {
+            return callCount;
+        }
+
+        @Override
+        public void resetCallCount() {
+            callCount = 0;
+        }
+
+        @Override
+        public Node getInlineTree() {
+            RootNode root = inlinableTarget.getRootNode();
+            if (root instanceof FunctionRootNode) {
+                return ((FunctionRootNode) root).getUninitializedBody();
+            }
+            return null;
+        }
+
+        @Override
+        public boolean inline(FrameFactory factory) {
+            CompilerAsserts.neverPartOfCompilation();
+            TypedNode functionCall = null;
+
+            RootNode root = inlinableTarget.getRootNode();
+            if (root instanceof FunctionRootNode) {
+                functionCall = ((FunctionRootNode) root).inline(NodeUtil.cloneNode(args));
+            }
+            if (functionCall != null) {
+                this.replace(functionCall);
+                return true;
+            } else {
+                return false;
+            }
+        }
+
+        @Override
+        public Object executeGeneric(VirtualFrame frame) {
+            if (CompilerDirectives.inInterpreter()) {
+                callCount++;
+            }
+            return super.executeGeneric(frame);
+        }
+
+        @Override
+        public CallTarget getCallTarget() {
+            return inlinableTarget;
+        }
+
+    }
+
+    private static class DispatchedCallNode extends TypedNode {
+
+        @Child protected ArgumentsNode args;
+        protected final CallTarget function;
+
+        DispatchedCallNode(CallTarget function, ArgumentsNode arguments) {
+            this.args = adoptChild(arguments);
+            this.function = function;
+        }
+
+        @Override
+        public Object executeGeneric(VirtualFrame frame) {
+            SLArguments argsObject = new SLArguments(args.executeArray(frame));
+            return function.call(frame.pack(), argsObject);
+        }
+    }
+
+    private static final class GenericCallNode extends CallNode {
+
+        @Child protected ArgumentsNode args;
+
+        GenericCallNode(TypedNode functionNode, ArgumentsNode arguments) {
+            super(functionNode);
+            this.args = adoptChild(arguments);
+        }
+
+        @Override
+        public Object executeGeneric(VirtualFrame frame, CallTarget function) {
+            SLArguments argsObject = new SLArguments(args.executeArray(frame));
+            return function.call(frame.pack(), argsObject);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/FunctionBodyNode.java	Mon Nov 11 21:34:44 2013 +0100
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+
+public class FunctionBodyNode extends TypedNode {
+
+    @Child private StatementNode body;
+    @Child private TypedNode returnValue;
+    @Child private StatementNode writeArguments;
+
+    private FrameDescriptor frameDescriptor;
+
+    public FunctionBodyNode(FrameDescriptor frameDescriptor, StatementNode body, TypedNode returnValue, String[] parameterNames) {
+        this.frameDescriptor = frameDescriptor;
+        this.body = adoptChild(body);
+        this.returnValue = adoptChild(returnValue);
+        this.writeArguments = adoptChild(new BlockNode(createWriteArguments(parameterNames)));
+    }
+
+    @Override
+    public Object executeGeneric(VirtualFrame frame) {
+        writeArguments.executeVoid(frame);
+        try {
+            body.executeVoid(frame);
+        } catch (ReturnException ex) {
+            // Nothing to do, we just need to return.
+        }
+        if (returnValue != null) {
+            return returnValue.executeGeneric(frame);
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    public Node copy() {
+        FunctionBodyNode copy = (FunctionBodyNode) super.copy();
+        copy.frameDescriptor = frameDescriptor.shallowCopy();
+        return copy;
+    }
+
+    private StatementNode[] createWriteArguments(String[] parameterNames) {
+        StatementNode[] writeNodes = new StatementNode[parameterNames.length];
+        for (int i = 0; i < parameterNames.length; i++) {
+            FrameSlot frameSlot = frameDescriptor.findOrAddFrameSlot(parameterNames[i]);
+            writeNodes[i] = WriteLocalNodeFactory.create(frameSlot, new ReadArgumentNode(i));
+        }
+        return writeNodes;
+    }
+
+    public FrameDescriptor getFrameDescriptor() {
+        return frameDescriptor;
+    }
+
+}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/FunctionDefinitionNode.java	Thu Nov 07 20:55:13 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes;
-
-import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.nodes.*;
-
-public class FunctionDefinitionNode extends RootNode {
-
-    @Child private StatementNode body;
-
-    @Child private TypedNode returnValue;
-
-    private final FrameDescriptor frameDescriptor;
-    private final String name;
-
-    public FunctionDefinitionNode(StatementNode body, FrameDescriptor frameDescriptor, String name, TypedNode returnValue) {
-        super(null);
-        this.body = adoptChild(body);
-        this.frameDescriptor = frameDescriptor;
-        this.name = name;
-        this.returnValue = adoptChild(returnValue);
-    }
-
-    @Override
-    public Object execute(VirtualFrame frame) {
-        try {
-            body.executeVoid(frame);
-        } catch (ReturnException ex) {
-            // Nothing to do, we just need to return.
-        }
-        if (returnValue != null) {
-            return returnValue.executeGeneric(frame);
-        } else {
-            return null;
-        }
-    }
-
-    public FrameDescriptor getFrameDescriptor() {
-        return frameDescriptor;
-    }
-
-    @Override
-    public String toString() {
-        return "Function " + name;
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/FunctionRootNode.java	Mon Nov 11 21:34:44 2013 +0100
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.sl.builtins.*;
+import com.oracle.truffle.sl.runtime.*;
+
+public final class FunctionRootNode extends RootNode {
+
+    @Child private TypedNode body;
+
+    private final TypedNode uninitializedBody;
+    private final String name;
+    private final boolean alwaysInline;
+
+    private FunctionRootNode(TypedNode body, String name, boolean alwaysInline) {
+        super(null);
+        this.uninitializedBody = NodeUtil.cloneNode(body);
+        this.body = adoptChild(body);
+        this.name = name;
+        this.alwaysInline = alwaysInline;
+    }
+
+    public static CallTarget createBuiltin(SLContext context, NodeFactory<? extends BuiltinNode> factory, String name) {
+        int argumentCount = factory.getExecutionSignature().size();
+        TypedNode[] arguments = new TypedNode[argumentCount];
+        for (int i = 0; i < arguments.length; i++) {
+            arguments[i] = new ReadArgumentNode(i);
+        }
+        BuiltinNode buitinBody = factory.createNode(arguments, context);
+        FunctionRootNode root = new FunctionRootNode(buitinBody, name, true);
+        return Truffle.getRuntime().createCallTarget(root);
+    }
+
+    public static CallTarget createFunction(StatementNode body, FrameDescriptor frameDescriptor, String name, TypedNode returnValue, String[] parameterNames) {
+        FunctionBodyNode bodyContainer = new FunctionBodyNode(frameDescriptor, body, returnValue, parameterNames);
+        FunctionRootNode root = new FunctionRootNode(bodyContainer, name, false);
+        return Truffle.getRuntime().createCallTarget(root, frameDescriptor);
+    }
+
+    @Override
+    public Object execute(VirtualFrame frame) {
+        return body.executeGeneric(frame);
+    }
+
+    public boolean isAlwaysInline() {
+        return alwaysInline;
+    }
+
+    public TypedNode inline(ArgumentsNode clonedArgs) {
+        TypedNode clonedBody = NodeUtil.cloneNode(uninitializedBody);
+        if (clonedBody instanceof BuiltinNode) {
+            return inlineBuiltin(clonedArgs, (BuiltinNode) clonedBody);
+        } else if (clonedBody instanceof FunctionBodyNode) {
+            return inlineFunction(clonedArgs, (FunctionBodyNode) clonedBody);
+        } else {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    private InlinedFunctionNode inlineFunction(ArgumentsNode clonedArgs, FunctionBodyNode clonedBody) {
+        return new InlinedFunctionNode(getCallTarget(), clonedBody, clonedArgs);
+    }
+
+    private static TypedNode inlineBuiltin(ArgumentsNode clonedArgs, BuiltinNode builtin) {
+        TypedNode[] callerArgs = clonedArgs.getArguments();
+        TypedNode[] builtinArgs = builtin.getArguments();
+        for (int i = 0; i < builtinArgs.length; i++) {
+            if (i < callerArgs.length) {
+                builtinArgs[i].replace(callerArgs[i]);
+            } else {
+                builtinArgs[i].replace(new NullLiteralNode());
+            }
+        }
+        return builtin;
+    }
+
+    public Node getUninitializedBody() {
+        return uninitializedBody;
+    }
+
+    @Override
+    public String toString() {
+        return "function " + name;
+    }
+
+    private static final class InlinedFunctionNode extends TypedNode implements InlinedCallSite {
+
+        @Child private FunctionBodyNode body;
+        @Child private ArgumentsNode arguments;
+
+        private final CallTarget callTarget;
+        private final FrameDescriptor frameDescriptor;
+
+        public InlinedFunctionNode(CallTarget callTarget, FunctionBodyNode body, ArgumentsNode arguments) {
+            this.callTarget = callTarget;
+            this.body = adoptChild(body);
+            this.frameDescriptor = body.getFrameDescriptor();
+            this.arguments = adoptChild(arguments);
+        }
+
+        @Override
+        public Object executeGeneric(VirtualFrame frame) {
+            SLArguments args = new SLArguments(arguments.executeArray(frame));
+            VirtualFrame childFrame = Truffle.getRuntime().createVirtualFrame(frame.pack(), args, frameDescriptor);
+            return body.executeGeneric(childFrame);
+        }
+
+        public CallTarget getCallTarget() {
+            return callTarget;
+        }
+
+    }
+
+    public String getName() {
+        return name;
+    }
+
+}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/IfNode.java	Thu Nov 07 20:55:13 2013 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/IfNode.java	Mon Nov 11 21:34:44 2013 +0100
@@ -45,7 +45,9 @@
         if (condition) {
             thenPartNode.executeVoid(frame);
         } else {
-            elsePartNode.executeVoid(frame);
+            if (elsePartNode != null) {
+                elsePartNode.executeVoid(frame);
+            }
         }
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/NullLiteralNode.java	Mon Nov 11 21:34:44 2013 +0100
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.sl.runtime.*;
+
+public final class NullLiteralNode extends TypedNode {
+
+    @Override
+    public Object executeGeneric(VirtualFrame frame) {
+        return executeNull(frame);
+    }
+
+    @Override
+    public SLNull executeNull(VirtualFrame frame) {
+        return SLNull.INSTANCE;
+    }
+
+}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/PrintLineNode.java	Thu Nov 07 20:55:13 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes;
-
-import java.io.*;
-
-import com.oracle.truffle.api.frame.*;
-
-public class PrintLineNode extends StatementNode {
-
-    private final PrintStream output;
-
-    public PrintLineNode(PrintStream output) {
-        this.output = output;
-    }
-
-    @Override
-    public void executeVoid(VirtualFrame frame) {
-        output.println();
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/PrintNode.java	Thu Nov 07 20:55:13 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes;
-
-import java.io.*;
-
-import com.oracle.truffle.api.dsl.*;
-
-@NodeChild(type = TypedNode.class)
-public abstract class PrintNode extends StatementNode {
-
-    private final PrintStream output;
-
-    public PrintNode(PrintStream output) {
-        this.output = output;
-    }
-
-    public PrintNode(PrintNode node) {
-        this(node.output);
-    }
-
-    @Specialization
-    public void doInt(int value) {
-        output.print(value);
-    }
-
-    @Specialization
-    public void doBoolean(boolean value) {
-        output.print(value);
-    }
-
-    @Specialization
-    public void doString(String value) {
-        output.print(value);
-    }
-
-    @Specialization
-    public void doGeneric(Object value) {
-        output.print(value.toString());
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ReadArgumentNode.java	Mon Nov 11 21:34:44 2013 +0100
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.sl.runtime.*;
+
+public class ReadArgumentNode extends TypedNode {
+
+    private final int index;
+
+    public ReadArgumentNode(int index) {
+        this.index = index;
+    }
+
+    @Override
+    public Object executeGeneric(VirtualFrame frame) {
+        Object[] args = SLArguments.get(frame).arguments;
+        if (index < args.length) {
+            return args[index];
+        } else {
+            return SLNull.INSTANCE;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ReadFunctionNode.java	Mon Nov 11 21:34:44 2013 +0100
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.sl.runtime.*;
+
+public final class ReadFunctionNode extends TypedNode {
+
+    private final SLFunctionRegistry registry;
+    private final String name;
+
+    @CompilationFinal private boolean seenInvalidFunction;
+
+    public ReadFunctionNode(SLFunctionRegistry registry, String name) {
+        this.registry = registry;
+        this.name = name;
+    }
+
+    @Override
+    public Object executeGeneric(VirtualFrame frame) {
+        return executeCallTarget(frame);
+    }
+
+    @Override
+    public CallTarget executeCallTarget(VirtualFrame frame) {
+        CallTarget target = registry.lookup(name);
+        if (target != null) {
+            return target;
+        }
+        if (!seenInvalidFunction) {
+            CompilerDirectives.transferToInterpreter();
+            seenInvalidFunction = true;
+        }
+        if (seenInvalidFunction) {
+            throw new RuntimeException("Function with name '" + name + "' not found.");
+        }
+        return null;
+    }
+
+}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ReadLocalNode.java	Thu Nov 07 20:55:13 2013 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ReadLocalNode.java	Mon Nov 11 21:34:44 2013 +0100
@@ -25,6 +25,7 @@
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.frame.*;
 
+@PolymorphicLimit(1)
 public abstract class ReadLocalNode extends FrameSlotNode {
 
     public ReadLocalNode(FrameSlot slot) {
@@ -45,13 +46,14 @@
         return frame.getBoolean(slot);
     }
 
-    @Specialization
-    public Object doObject(VirtualFrame frame) {
-        try {
-            return frame.getObject(slot);
-        } catch (FrameSlotTypeException e) {
-            throw new IllegalStateException();
-        }
+    @Specialization(rewriteOn = {FrameSlotTypeException.class})
+    public Object doObject(VirtualFrame frame) throws FrameSlotTypeException {
+        return frame.getObject(slot);
+    }
+
+    @Generic
+    public Object doGeneric(VirtualFrame frame) {
+        return frame.getValue(slot);
     }
 
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ReadUninitializedNode.java	Mon Nov 11 21:34:44 2013 +0100
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.nodes;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.sl.runtime.*;
+
+public class ReadUninitializedNode extends TypedNode {
+
+    private final SLContext context;
+    private final FrameSlot slot;
+
+    public ReadUninitializedNode(SLContext context, FrameSlot slot) {
+        this.context = context;
+        this.slot = slot;
+    }
+
+    public FrameSlot getSlot() {
+        return slot;
+    }
+
+    @Override
+    public Object executeGeneric(VirtualFrame frame) {
+        CompilerDirectives.transferToInterpreter();
+        Object result = frame.getValue(slot);
+        String identifier = (String) slot.getIdentifier();
+        if (result == null) {
+            // function access
+            return replace(new ReadFunctionNode(context.getFunctionRegistry(), identifier)).executeGeneric(frame);
+        } else {
+            // local variable access
+            return replace(ReadLocalNodeFactory.create(slot)).executeGeneric(frame);
+        }
+    }
+}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/TimeNode.java	Thu Nov 07 20:55:13 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.sl.nodes;
-
-import com.oracle.truffle.api.dsl.*;
-
-public abstract class TimeNode extends TypedNode {
-
-    public static final long START_TIME = System.currentTimeMillis();
-
-    @Specialization
-    public int doInt() {
-        return (int) (System.currentTimeMillis() - START_TIME);
-    }
-}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/TypedNode.java	Thu Nov 07 20:55:13 2013 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/TypedNode.java	Mon Nov 11 21:34:44 2013 +0100
@@ -24,9 +24,11 @@
 
 import java.math.*;
 
+import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.sl.*;
+import com.oracle.truffle.sl.runtime.*;
 
 public abstract class TypedNode extends ConditionNode {
 
@@ -57,8 +59,20 @@
         return SLTypesGen.SLTYPES.expectString(executeGeneric(frame));
     }
 
+    public CallTarget executeCallTarget(VirtualFrame frame) throws UnexpectedResultException {
+        return SLTypesGen.SLTYPES.expectCallTarget(executeGeneric(frame));
+    }
+
+    public Object[] executeArray(VirtualFrame frame) throws UnexpectedResultException {
+        return SLTypesGen.SLTYPES.expectObjectArray(executeGeneric(frame));
+    }
+
+    public SLNull executeNull(VirtualFrame frame) throws UnexpectedResultException {
+        return SLTypesGen.SLTYPES.expectSLNull(executeGeneric(frame));
+    }
+
     @Override
-    public void executeVoid(VirtualFrame frame) {
+    public final void executeVoid(VirtualFrame frame) {
         executeGeneric(frame);
     }
 
@@ -66,19 +80,4 @@
         return a instanceof String || b instanceof String;
     }
 
-    @SuppressWarnings("unused")
-    public Object executeEvaluated(VirtualFrame frame, Object val1) {
-        return executeGeneric(frame);
-    }
-
-    @SuppressWarnings("unused")
-    public Object executeEvaluated(VirtualFrame frame, Object val1, Object val2) {
-        return executeEvaluated(frame, val1);
-    }
-
-    @SuppressWarnings("unused")
-    public Object executeEvaluated(VirtualFrame frame, Object val1, Object val2, Object val3) {
-        return executeEvaluated(frame, val1, val2);
-    }
-
 }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.frame	Thu Nov 07 20:55:13 2013 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.frame	Mon Nov 11 21:34:44 2013 +0100
@@ -26,6 +26,8 @@
 Coco/R itself) does not fall under the GNU General Public License.
 ------------------------------------------------------------------------*/
 -->begin
+package com.oracle.truffle.sl.parser;
+
 import java.util.*;
 
 import com.oracle.truffle.sl.*;
@@ -45,9 +47,9 @@
 
     public final Scanner scanner;
     public final Errors errors;
-    private final NodeFactory factory;
+    private final SLNodeFactory factory;
     -->declarations
-    public Parser(Scanner scanner, NodeFactory factory) {
+    public Parser(Scanner scanner, SLNodeFactory factory) {
         this.scanner = scanner;
         this.factory = factory;
         errors = new Errors();
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java	Thu Nov 07 20:55:13 2013 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java	Mon Nov 11 21:34:44 2013 +0100
@@ -21,7 +21,8 @@
  * questions.
  */
 
-// The content of this file is automatically generated. DO NOT EDIT.
+ // The content of this file is automatically generated. DO NOT EDIT.
+
 
 package com.oracle.truffle.sl.parser;
 
@@ -33,11 +34,11 @@
 // Checkstyle: stop
 // @formatter:off
 public class Parser {
-	public static final int _EOF = 0;
-	public static final int _identifier = 1;
-	public static final int _stringLiteral = 2;
-	public static final int _numericLiteral = 3;
-	public static final int maxT = 28;
+	public static final int _EOF = 0;
+	public static final int _identifier = 1;
+	public static final int _stringLiteral = 2;
+	public static final int _numericLiteral = 3;
+	public static final int maxT = 29;
 
     static final boolean T = true;
     static final boolean x = false;
@@ -49,9 +50,9 @@
 
     public final Scanner scanner;
     public final Errors errors;
-    private final NodeFactory factory;
+    private final SLNodeFactory factory;
     
-    public Parser(Scanner scanner, NodeFactory factory) {
+    public Parser(Scanner scanner, SLNodeFactory factory) {
         this.scanner = scanner;
         this.factory = factory;
         errors = new Errors();
@@ -121,255 +122,273 @@
         }
     }
 
-	void SimpleLanguage() {
-		Function();
-		while (la.kind == 4) {
-			Function();
-		}
-	}
-
-	void Function() {
-		Expect(4);
-		factory.startFunction(); 
-		Expect(1);
-		String name = t.val; 
-		StatementNode body = Block();
-		factory.createFunction(body, name); 
-	}
-
-	StatementNode  Block() {
-		StatementNode  result;
-		List<StatementNode> statements = new ArrayList<>(); 
-		Expect(5);
-		while (StartOf(1)) {
-			StatementNode statement = Statement();
-			statements.add(statement); 
-		}
-		Expect(6);
-		result = factory.createBlock(statements); 
-		return result;
-	}
-
-	StatementNode  Statement() {
-		StatementNode  result;
-		result = null; 
-		if (la.kind == 7) {
-			result = WhileStatement();
-		} else if (la.kind == 1) {
-			result = AssignmentStatement();
-		} else if (la.kind == 12) {
-			result = OutputStatement();
-		} else if (la.kind == 13) {
-			result = ReturnStatement();
-		} else SynErr(29);
-		return result;
-	}
-
-	StatementNode  WhileStatement() {
-		StatementNode  result;
-		Expect(7);
-		Expect(8);
-		ConditionNode condition = Expression();
-		Expect(9);
-		StatementNode body = Block();
-		result = factory.createWhile(condition, body); 
-		return result;
-	}
-
-	StatementNode  AssignmentStatement() {
-		StatementNode  result;
-		Expect(1);
-		String name = t.val; 
-		Expect(10);
-		TypedNode rvalue = Expression();
-		Expect(11);
-		result = factory.createAssignment(name, rvalue); 
-		return result;
-	}
-
-	StatementNode  OutputStatement() {
-		StatementNode  result;
-		List<TypedNode> expressions = new ArrayList<>(); 
-		Expect(12);
-		while (StartOf(2)) {
-			TypedNode value = Expression();
-			expressions.add(value); 
-		}
-		Expect(11);
-		result = factory.createPrint(expressions); 
-		return result;
-	}
-
-	StatementNode  ReturnStatement() {
-		StatementNode  result;
-		Expect(13);
-		TypedNode value = Expression();
-		Expect(11);
-		result = factory.createReturn(value); 
-		return result;
-	}
-
-	TypedNode  Expression() {
-		TypedNode  result;
-		result = ValueExpression();
-		if (StartOf(3)) {
-			switch (la.kind) {
-			case 14: {
-				Get();
-				break;
-			}
-			case 15: {
-				Get();
-				break;
-			}
-			case 16: {
-				Get();
-				break;
-			}
-			case 17: {
-				Get();
-				break;
-			}
-			case 18: {
-				Get();
-				break;
-			}
-			case 19: {
-				Get();
-				break;
-			}
-			}
-			String op = t.val; 
-			TypedNode right = ValueExpression();
-			result = factory.createBinary(op, result, right); 
-		}
-		return result;
-	}
-
-	TypedNode  ValueExpression() {
-		TypedNode  result;
-		result = Term();
-		while (la.kind == 20 || la.kind == 21) {
-			if (la.kind == 20) {
-				Get();
-			} else {
-				Get();
-			}
-			String op = t.val; 
-			TypedNode right = Term();
-			result = factory.createBinary(op, result, right); 
-		}
-		return result;
-	}
-
-	TypedNode  Term() {
-		TypedNode  result;
-		result = Factor();
-		while (la.kind == 22 || la.kind == 23) {
-			if (la.kind == 22) {
-				Get();
-			} else {
-				Get();
-			}
-			String op = t.val; 
-			TypedNode right = Factor();
-			result = factory.createBinary(op, result, right); 
-		}
-		return result;
-	}
-
-	TypedNode  Factor() {
-		TypedNode  result;
-		result = null; 
-		switch (la.kind) {
-		case 27: {
-			result = TimeRef();
-			break;
-		}
-		case 1: {
-			result = VariableRef();
-			break;
-		}
-		case 2: {
-			result = StringLiteral();
-			break;
-		}
-		case 3: {
-			result = NumericLiteral();
-			break;
-		}
-		case 24: {
-			result = Ternary();
-			break;
-		}
-		case 8: {
-			Get();
-			result = Expression();
-			Expect(9);
-			break;
-		}
-		default: SynErr(30); break;
-		}
-		return result;
-	}
-
-	TypedNode  TimeRef() {
-		TypedNode  result;
-		Expect(27);
-		result = factory.createTime(); 
-		return result;
-	}
-
-	TypedNode  VariableRef() {
-		TypedNode  result;
-		Expect(1);
-		result = factory.createLocal(t.val); 
-		return result;
-	}
-
-	TypedNode  StringLiteral() {
-		TypedNode  result;
-		Expect(2);
-		result = factory.createStringLiteral(t.val.substring(1, t.val.length() - 1)); 
-		return result;
-	}
-
-	TypedNode  NumericLiteral() {
-		TypedNode  result;
-		Expect(3);
-		result = factory.createNumericLiteral(t.val); 
-		return result;
-	}
-
-	TypedNode  Ternary() {
-		TypedNode  result;
-		TypedNode condition, thenPart, elsePart; 
-		Expect(24);
-		condition = Expression();
-		Expect(25);
-		thenPart = Expression();
-		Expect(26);
-		elsePart = Expression();
-		result = factory.createTernary(condition, thenPart, elsePart); 
-		return result;
-	}
-
+	void SimpleLanguage() {
+		Function();
+		while (la.kind == 4) {
+			Function();
+		}
+	}
+
+	void Function() {
+		Expect(4);
+		factory.startFunction(); 
+		Expect(1);
+		String name = t.val; 
+		List<String> parameterNames = new ArrayList<>(); 
+		if (la.kind == 5) {
+			Get();
+			if (la.kind == 1) {
+				Get();
+				parameterNames.add(t.val); 
+			}
+			while (la.kind == 6) {
+				Get();
+				Expect(1);
+				parameterNames.add(t.val); 
+			}
+			Expect(7);
+		}
+		StatementNode body = Block();
+		factory.createFunction(body, name, parameterNames.toArray(new String[parameterNames.size()])); 
+	}
+
+	StatementNode  Block() {
+		StatementNode  result;
+		List<StatementNode> statements = new ArrayList<>(); 
+		Expect(8);
+		while (StartOf(1)) {
+			StatementNode statement = Statement();
+			statements.add(statement); 
+		}
+		Expect(9);
+		result = factory.createBlock(statements); 
+		return result;
+	}
+
+	StatementNode  Statement() {
+		StatementNode  result;
+		result = null; 
+		if (la.kind == 13) {
+			result = WhileStatement();
+		} else if (la.kind == 11) {
+			result = IfStatement();
+		} else if (la.kind == 14) {
+			result = ReturnStatement();
+		} else if (StartOf(2)) {
+			result = Expression();
+			Expect(10);
+		} else SynErr(30);
+		return result;
+	}
+
+	StatementNode  WhileStatement() {
+		StatementNode  result;
+		Expect(13);
+		Expect(5);
+		ConditionNode condition = Expression();
+		Expect(7);
+		StatementNode body = Block();
+		result = factory.createWhile(condition, body); 
+		return result;
+	}
+
+	StatementNode  IfStatement() {
+		StatementNode  result;
+		Expect(11);
+		Expect(5);
+		ConditionNode condition = Expression();
+		Expect(7);
+		StatementNode thenNode = null; StatementNode elseNode = null; 
+		thenNode = Block();
+		if (la.kind == 12) {
+			Get();
+			elseNode = Block();
+		}
+		result = factory.createIf(condition, thenNode, elseNode); 
+		return result;
+	}
+
+	StatementNode  ReturnStatement() {
+		StatementNode  result;
+		Expect(14);
+		TypedNode value = Expression();
+		Expect(10);
+		result = factory.createReturn(value); 
+		return result;
+	}
+
+	TypedNode  Expression() {
+		TypedNode  result;
+		result = ValueExpression();
+		if (StartOf(3)) {
+			switch (la.kind) {
+			case 15: {
+				Get();
+				break;
+			}
+			case 16: {
+				Get();
+				break;
+			}
+			case 17: {
+				Get();
+				break;
+			}
+			case 18: {
+				Get();
+				break;
+			}
+			case 19: {
+				Get();
+				break;
+			}
+			case 20: {
+				Get();
+				break;
+			}
+			}
+			String op = t.val; 
+			TypedNode right = ValueExpression();
+			result = factory.createBinary(op, result, right); 
+		}
+		return result;
+	}
+
+	TypedNode  ValueExpression() {
+		TypedNode  result;
+		result = Term();
+		while (la.kind == 21 || la.kind == 22) {
+			if (la.kind == 21) {
+				Get();
+			} else {
+				Get();
+			}
+			String op = t.val; 
+			TypedNode right = Term();
+			result = factory.createBinary(op, result, right); 
+		}
+		return result;
+	}
+
+	TypedNode  Term() {
+		TypedNode  result;
+		result = Factor();
+		while (la.kind == 23 || la.kind == 24) {
+			if (la.kind == 23) {
+				Get();
+			} else {
+				Get();
+			}
+			String op = t.val; 
+			TypedNode right = Factor();
+			result = factory.createBinary(op, result, right); 
+		}
+		return result;
+	}
+
+	TypedNode  Factor() {
+		TypedNode  result;
+		result = null; 
+		if (la.kind == 1) {
+			result = VariableRefOrCall();
+		} else if (la.kind == 2) {
+			result = StringLiteral();
+		} else if (la.kind == 3) {
+			result = NumericLiteral();
+		} else if (la.kind == 25) {
+			result = Ternary();
+		} else if (la.kind == 5) {
+			Get();
+			result = Expression();
+			Expect(7);
+		} else SynErr(31);
+		return result;
+	}
+
+	TypedNode  VariableRefOrCall() {
+		TypedNode  result;
+		result = VariableRef();
+		if (la.kind == 5 || la.kind == 28) {
+			if (la.kind == 5) {
+				TypedNode[] parameters = Parameters();
+				result = factory.createCall(result, parameters); 
+			} else {
+				Get();
+				TypedNode assignment = Expression();
+				result = factory.createAssignment(result, assignment); 
+			}
+		}
+		return result;
+	}
+
+	TypedNode  StringLiteral() {
+		TypedNode  result;
+		Expect(2);
+		result = factory.createStringLiteral(t.val.substring(1, t.val.length() - 1)); 
+		return result;
+	}
+
+	TypedNode  NumericLiteral() {
+		TypedNode  result;
+		Expect(3);
+		result = factory.createNumericLiteral(t.val); 
+		return result;
+	}
+
+	TypedNode  Ternary() {
+		TypedNode  result;
+		TypedNode condition, thenPart, elsePart; 
+		Expect(25);
+		condition = Expression();
+		Expect(26);
+		thenPart = Expression();
+		Expect(27);
+		elsePart = Expression();
+		result = factory.createTernary(condition, thenPart, elsePart); 
+		return result;
+	}
+
+	TypedNode  VariableRef() {
+		TypedNode  result;
+		Expect(1);
+		result = factory.createLocal(t.val); 
+		return result;
+	}
+
+	TypedNode[]  Parameters() {
+		TypedNode[]  result;
+		Expect(5);
+		List<TypedNode> parameters = new ArrayList<>(); 
+		if (StartOf(2)) {
+			TypedNode e1 = Expression();
+			parameters.add(e1); 
+			while (la.kind == 6) {
+				Get();
+				TypedNode e2 = Expression();
+				parameters.add(e2); 
+			}
+		}
+		result = parameters.toArray(new TypedNode[parameters.size()]); 
+		Expect(7);
+		return result;
+	}
+
 
 
     public void Parse() {
         la = new Token();
         la.val = "";
         Get();
-		SimpleLanguage();
-		Expect(0);
+		SimpleLanguage();
+		Expect(0);
 
     }
 
     private static final boolean[][] set = {
-		{T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
-		{x,T,x,x, x,x,x,T, x,x,x,x, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
-		{x,T,T,T, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,T, x,x},
-		{x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,T,T, x,x,x,x, x,x,x,x, x,x}
+		{T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x},
+		{x,T,T,T, x,T,x,x, x,x,x,T, x,T,T,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,x},
+		{x,T,T,T, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,x},
+		{x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,T,T,T, T,x,x,x, x,x,x,x, x,x,x}
 
     };
 
@@ -417,38 +436,39 @@
 
     public void SynErr(int line, int col, int n) {
         String s;
-        switch (n) {
-			case 0: s = "EOF expected"; break;
-			case 1: s = "identifier expected"; break;
-			case 2: s = "stringLiteral expected"; break;
-			case 3: s = "numericLiteral expected"; break;
-			case 4: s = "\"function\" expected"; break;
-			case 5: s = "\"{\" expected"; break;
-			case 6: s = "\"}\" expected"; break;
-			case 7: s = "\"while\" expected"; break;
-			case 8: s = "\"(\" expected"; break;
-			case 9: s = "\")\" expected"; break;
-			case 10: s = "\"=\" expected"; break;
-			case 11: s = "\";\" expected"; break;
-			case 12: s = "\"print\" expected"; break;
-			case 13: s = "\"return\" expected"; break;
-			case 14: s = "\"<\" expected"; break;
-			case 15: s = "\">\" expected"; break;
-			case 16: s = "\"<=\" expected"; break;
-			case 17: s = "\">=\" expected"; break;
-			case 18: s = "\"==\" expected"; break;
-			case 19: s = "\"!=\" expected"; break;
-			case 20: s = "\"+\" expected"; break;
-			case 21: s = "\"-\" expected"; break;
-			case 22: s = "\"*\" expected"; break;
-			case 23: s = "\"/\" expected"; break;
-			case 24: s = "\"#\" expected"; break;
-			case 25: s = "\"?\" expected"; break;
-			case 26: s = "\":\" expected"; break;
-			case 27: s = "\"time\" expected"; break;
-			case 28: s = "??? expected"; break;
-			case 29: s = "invalid Statement"; break;
-			case 30: s = "invalid Factor"; break;
+        switch (n) {
+			case 0: s = "EOF expected"; break;
+			case 1: s = "identifier expected"; break;
+			case 2: s = "stringLiteral expected"; break;
+			case 3: s = "numericLiteral expected"; break;
+			case 4: s = "\"function\" expected"; break;
+			case 5: s = "\"(\" expected"; break;
+			case 6: s = "\",\" expected"; break;
+			case 7: s = "\")\" expected"; break;
+			case 8: s = "\"{\" expected"; break;
+			case 9: s = "\"}\" expected"; break;
+			case 10: s = "\";\" expected"; break;
+			case 11: s = "\"if\" expected"; break;
+			case 12: s = "\"else\" expected"; break;
+			case 13: s = "\"while\" expected"; break;
+			case 14: s = "\"return\" expected"; break;
+			case 15: s = "\"<\" expected"; break;
+			case 16: s = "\">\" expected"; break;
+			case 17: s = "\"<=\" expected"; break;
+			case 18: s = "\">=\" expected"; break;
+			case 19: s = "\"==\" expected"; break;
+			case 20: s = "\"!=\" expected"; break;
+			case 21: s = "\"+\" expected"; break;
+			case 22: s = "\"-\" expected"; break;
+			case 23: s = "\"*\" expected"; break;
+			case 24: s = "\"/\" expected"; break;
+			case 25: s = "\"#\" expected"; break;
+			case 26: s = "\"?\" expected"; break;
+			case 27: s = "\":\" expected"; break;
+			case 28: s = "\"=\" expected"; break;
+			case 29: s = "??? expected"; break;
+			case 30: s = "invalid Statement"; break;
+			case 31: s = "invalid Factor"; break;
             default:
                 s = "error " + n;
                 break;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java.old	Mon Nov 11 21:34:44 2013 +0100
@@ -0,0 +1,506 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+ // The content of this file is automatically generated. DO NOT EDIT.
+
+
+package com.oracle.truffle.sl.parser;
+
+import java.util.*;
+
+import com.oracle.truffle.sl.*;
+import com.oracle.truffle.sl.nodes.*;
+
+// Checkstyle: stop
+// @formatter:off
+public class Parser {
+	public static final int _EOF = 0;
+	public static final int _identifier = 1;
+	public static final int _stringLiteral = 2;
+	public static final int _numericLiteral = 3;
+	public static final int maxT = 29;
+
+    static final boolean T = true;
+    static final boolean x = false;
+    static final int minErrDist = 2;
+
+    public Token t; // last recognized token
+    public Token la; // lookahead token
+    int errDist = minErrDist;
+
+    public final Scanner scanner;
+    public final Errors errors;
+    private final SLNodeFactory factory;
+    
+    public Parser(Scanner scanner, SLNodeFactory factory) {
+        this.scanner = scanner;
+        this.factory = factory;
+        errors = new Errors();
+    }
+
+    void SynErr(int n) {
+        if (errDist >= minErrDist)
+            errors.SynErr(la.line, la.col, n);
+        errDist = 0;
+    }
+
+    public void SemErr(String msg) {
+        if (errDist >= minErrDist)
+            errors.SemErr(t.line, t.col, msg);
+        errDist = 0;
+    }
+
+    void Get() {
+        for (;;) {
+            t = la;
+            la = scanner.Scan();
+            if (la.kind <= maxT) {
+                ++errDist;
+                break;
+            }
+
+            la = t;
+        }
+    }
+
+    void Expect(int n) {
+        if (la.kind == n)
+            Get();
+        else {
+            SynErr(n);
+        }
+    }
+
+    boolean StartOf(int s) {
+        return set[s][la.kind];
+    }
+
+    void ExpectWeak(int n, int follow) {
+        if (la.kind == n)
+            Get();
+        else {
+            SynErr(n);
+            while (!StartOf(follow))
+                Get();
+        }
+    }
+
+    boolean WeakSeparator(int n, int syFol, int repFol) {
+        int kind = la.kind;
+        if (kind == n) {
+            Get();
+            return true;
+        } else if (StartOf(repFol))
+            return false;
+        else {
+            SynErr(n);
+            while (!(set[syFol][kind] || set[repFol][kind] || set[0][kind])) {
+                Get();
+                kind = la.kind;
+            }
+            return StartOf(syFol);
+        }
+    }
+
+	void SimpleLanguage() {
+		Function();
+		while (la.kind == 4) {
+			Function();
+		}
+	}
+
+	void Function() {
+		Expect(4);
+		factory.startFunction(); 
+		Expect(1);
+		String name = t.val; 
+		List<String> parameterNames = new ArrayList<>(); 
+		if (la.kind == 5) {
+			Get();
+			if (la.kind == 1) {
+				Get();
+				parameterNames.add(t.val); 
+			}
+			while (la.kind == 6) {
+				Get();
+				Expect(1);
+				parameterNames.add(t.val); 
+			}
+			Expect(7);
+		}
+		StatementNode body = Block();
+		factory.createFunction(body, name, parameterNames.toArray(new String[parameterNames.size()])); 
+	}
+
+	StatementNode  Block() {
+		StatementNode  result;
+		List<StatementNode> statements = new ArrayList<>(); 
+		Expect(8);
+		while (StartOf(1)) {
+			StatementNode statement = Statement();
+			statements.add(statement); 
+		}
+		Expect(9);
+		result = factory.createBlock(statements); 
+		return result;
+	}
+
+	StatementNode  Statement() {
+		StatementNode  result;
+		result = null; 
+		if (la.kind == 13) {
+			result = WhileStatement();
+		} else if (la.kind == 11) {
+			result = IfStatement();
+		} else if (la.kind == 14) {
+			result = ReturnStatement();
+		} else if (StartOf(2)) {
+			result = Expression();
+			Expect(10);
+		} else SynErr(30);
+		return result;
+	}
+
+	StatementNode  WhileStatement() {
+		StatementNode  result;
+		Expect(13);
+		Expect(5);
+		ConditionNode condition = Expression();
+		Expect(7);
+		StatementNode body = Block();
+		result = factory.createWhile(condition, body); 
+		return result;
+	}
+
+	StatementNode  IfStatement() {
+		StatementNode  result;
+		Expect(11);
+		Expect(5);
+		ConditionNode condition = Expression();
+		Expect(7);
+		StatementNode thenNode = null; StatementNode elseNode = null; 
+		thenNode = Block();
+		if (la.kind == 12) {
+			Get();
+			elseNode = Block();
+		}
+		result = factory.createIf(condition, thenNode, elseNode); 
+		return result;
+	}
+
+	StatementNode  ReturnStatement() {
+		StatementNode  result;
+		Expect(14);
+		TypedNode value = Expression();
+		Expect(10);
+		result = factory.createReturn(value); 
+		return result;
+	}
+
+	TypedNode  Expression() {
+		TypedNode  result;
+		result = ValueExpression();
+		if (StartOf(3)) {
+			switch (la.kind) {
+			case 15: {
+				Get();
+				break;
+			}
+			case 16: {
+				Get();
+				break;
+			}
+			case 17: {
+				Get();
+				break;
+			}
+			case 18: {
+				Get();
+				break;
+			}
+			case 19: {
+				Get();
+				break;
+			}
+			case 20: {
+				Get();
+				break;
+			}
+			}
+			String op = t.val; 
+			TypedNode right = ValueExpression();
+			result = factory.createBinary(op, result, right); 
+		}
+		return result;
+	}
+
+	TypedNode  ValueExpression() {
+		TypedNode  result;
+		result = Term();
+		while (la.kind == 21 || la.kind == 22) {
+			if (la.kind == 21) {
+				Get();
+			} else {
+				Get();
+			}
+			String op = t.val; 
+			TypedNode right = Term();
+			result = factory.createBinary(op, result, right); 
+		}
+		return result;
+	}
+
+	TypedNode  Term() {
+		TypedNode  result;
+		result = Factor();
+		while (la.kind == 23 || la.kind == 24) {
+			if (la.kind == 23) {
+				Get();
+			} else {
+				Get();
+			}
+			String op = t.val; 
+			TypedNode right = Factor();
+			result = factory.createBinary(op, result, right); 
+		}
+		return result;
+	}
+
+	TypedNode  Factor() {
+		TypedNode  result;
+		result = null; 
+		if (la.kind == 1) {
+			result = VariableRefOrCall();
+		} else if (la.kind == 2) {
+			result = StringLiteral();
+		} else if (la.kind == 3) {
+			result = NumericLiteral();
+		} else if (la.kind == 25) {
+			result = Ternary();
+		} else if (la.kind == 5) {
+			Get();
+			result = Expression();
+			Expect(7);
+		} else SynErr(31);
+		return result;
+	}
+
+	TypedNode  VariableRefOrCall() {
+		TypedNode  result;
+		result = VariableRef();
+		if (la.kind == 5 || la.kind == 28) {
+			if (la.kind == 5) {
+				TypedNode[] parameters = Parameters();
+				result = factory.createCall(result, parameters); 
+			} else {
+				Get();
+				TypedNode assignment = Expression();
+				result = factory.createAssignment(result, assignment); 
+			}
+		}
+		return result;
+	}
+
+	TypedNode  StringLiteral() {
+		TypedNode  result;
+		Expect(2);
+		result = factory.createStringLiteral(t.val.substring(1, t.val.length() - 1)); 
+		return result;
+	}
+
+	TypedNode  NumericLiteral() {
+		TypedNode  result;
+		Expect(3);
+		result = factory.createNumericLiteral(t.val); 
+		return result;
+	}
+
+	TypedNode  Ternary() {
+		TypedNode  result;
+		TypedNode condition, thenPart, elsePart; 
+		Expect(25);
+		condition = Expression();
+		Expect(26);
+		thenPart = Expression();
+		Expect(27);
+		elsePart = Expression();
+		result = factory.createTernary(condition, thenPart, elsePart); 
+		return result;
+	}
+
+	TypedNode  VariableRef() {
+		TypedNode  result;
+		Expect(1);
+		result = factory.createLocal(t.val); 
+		return result;
+	}
+
+	TypedNode[]  Parameters() {
+		TypedNode[]  result;
+		Expect(5);
+		List<TypedNode> parameters = new ArrayList<>(); 
+		if (StartOf(2)) {
+			TypedNode e1 = Expression();
+			parameters.add(e1); 
+			while (la.kind == 6) {
+				Get();
+				TypedNode e2 = Expression();
+				parameters.add(e2); 
+			}
+		}
+		result = parameters.toArray(new TypedNode[parameters.size()]); 
+		Expect(7);
+		return result;
+	}
+
+
+
+    public void Parse() {
+        la = new Token();
+        la.val = "";
+        Get();
+		SimpleLanguage();
+		Expect(0);
+
+    }
+
+    private static final boolean[][] set = {
+		{T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x},
+		{x,T,T,T, x,T,x,x, x,x,x,T, x,T,T,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,x},
+		{x,T,T,T, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,x},
+		{x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,T,T,T, T,x,x,x, x,x,x,x, x,x,x}
+
+    };
+
+    public String ParseErrors() {
+        java.io.PrintStream oldStream = System.out;
+
+        java.io.OutputStream out = new java.io.ByteArrayOutputStream();
+        java.io.PrintStream newStream = new java.io.PrintStream(out);
+
+        errors.errorStream = newStream;
+
+        Parse();
+
+        String errorStream = out.toString();
+        errors.errorStream = oldStream;
+
+        return errorStream;
+
+    }
+} // end Parser
+
+class Errors {
+
+    public int count = 0; // number of errors detected
+    public java.io.PrintStream errorStream = System.out; // error messages go to this stream
+    public String errMsgFormat = "-- line {0} col {1}: {2}"; // 0=line, 1=column, 2=text
+
+    protected void printMsg(int line, int column, String msg) {
+        StringBuffer b = new StringBuffer(errMsgFormat);
+        int pos = b.indexOf("{0}");
+        if (pos >= 0) {
+            b.delete(pos, pos + 3);
+            b.insert(pos, line);
+        }
+        pos = b.indexOf("{1}");
+        if (pos >= 0) {
+            b.delete(pos, pos + 3);
+            b.insert(pos, column);
+        }
+        pos = b.indexOf("{2}");
+        if (pos >= 0)
+            b.replace(pos, pos + 3, msg);
+        errorStream.println(b.toString());
+    }
+
+    public void SynErr(int line, int col, int n) {
+        String s;
+        switch (n) {
+			case 0: s = "EOF expected"; break;
+			case 1: s = "identifier expected"; break;
+			case 2: s = "stringLiteral expected"; break;
+			case 3: s = "numericLiteral expected"; break;
+			case 4: s = "\"function\" expected"; break;
+			case 5: s = "\"(\" expected"; break;
+			case 6: s = "\",\" expected"; break;
+			case 7: s = "\")\" expected"; break;
+			case 8: s = "\"{\" expected"; break;
+			case 9: s = "\"}\" expected"; break;
+			case 10: s = "\";\" expected"; break;
+			case 11: s = "\"if\" expected"; break;
+			case 12: s = "\"else\" expected"; break;
+			case 13: s = "\"while\" expected"; break;
+			case 14: s = "\"return\" expected"; break;
+			case 15: s = "\"<\" expected"; break;
+			case 16: s = "\">\" expected"; break;
+			case 17: s = "\"<=\" expected"; break;
+			case 18: s = "\">=\" expected"; break;
+			case 19: s = "\"==\" expected"; break;
+			case 20: s = "\"!=\" expected"; break;
+			case 21: s = "\"+\" expected"; break;
+			case 22: s = "\"-\" expected"; break;
+			case 23: s = "\"*\" expected"; break;
+			case 24: s = "\"/\" expected"; break;
+			case 25: s = "\"#\" expected"; break;
+			case 26: s = "\"?\" expected"; break;
+			case 27: s = "\":\" expected"; break;
+			case 28: s = "\"=\" expected"; break;
+			case 29: s = "??? expected"; break;
+			case 30: s = "invalid Statement"; break;
+			case 31: s = "invalid Factor"; break;
+            default:
+                s = "error " + n;
+                break;
+        }
+        printMsg(line, col, s);
+        count++;
+    }
+
+    public void SemErr(int line, int col, String s) {
+        printMsg(line, col, s);
+        count++;
+    }
+
+    public void SemErr(String s) {
+        errorStream.println(s);
+        count++;
+    }
+
+    public void Warning(int line, int col, String s) {
+        printMsg(line, col, s);
+    }
+
+    public void Warning(String s) {
+        errorStream.println(s);
+    }
+} // Errors
+
+class FatalError extends RuntimeException {
+
+    public static final long serialVersionUID = 1L;
+
+    public FatalError(String s) {
+        super(s);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/ParserUtils.java	Mon Nov 11 21:34:44 2013 +0100
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.truffle.sl.parser;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.impl.*;
+
+public class ParserUtils {
+
+    public static SourceSection createSourceSection(Source source, String identifier, Parser p) {
+        Token t = p.t;
+        if (t == null) {
+            t = p.la;
+        }
+        int startLine = -1;
+        int startColumn = -1;
+        int length = 0;
+        if (t != null) {
+            startLine = t.line;
+            startColumn = t.col;
+            length = t.val.length();
+        }
+        return new DefaultSourceSection(source, identifier, startLine, startColumn, 0, length);
+    }
+}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.frame	Thu Nov 07 20:55:13 2013 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.frame	Mon Nov 11 21:34:44 2013 +0100
@@ -26,6 +26,8 @@
 Coco/R itself) does not fall under the GNU General Public License.
 ------------------------------------------------------------------------*/
 -->begin
+package com.oracle.truffle.sl.parser;
+
 import java.io.InputStream;
 import java.io.IOException;
 import java.io.RandomAccessFile;
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.java	Thu Nov 07 20:55:13 2013 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.java	Mon Nov 11 21:34:44 2013 +0100
@@ -21,7 +21,8 @@
  * questions.
  */
 
-// The content of this file is automatically generated. DO NOT EDIT.
+ // The content of this file is automatically generated. DO NOT EDIT.
+
 
 package com.oracle.truffle.sl.parser;
 
@@ -311,8 +312,8 @@
 
     static final char EOL = '\n';
     static final int eofSym = 0;
-	static final int maxT = 28;
-	static final int noSym = 28;
+	static final int maxT = 29;
+	static final int noSym = 29;
 
 
     public Buffer buffer; // scanner buffer
@@ -336,33 +337,34 @@
     static {
         start = new StartStates();
         literals = new HashMap();
-		for (int i = 65; i <= 90; ++i) start.set(i, 1);
-		for (int i = 97; i <= 122; ++i) start.set(i, 1);
-		for (int i = 49; i <= 57; ++i) start.set(i, 4);
-		start.set(34, 2); 
-		start.set(48, 5); 
-		start.set(123, 6); 
-		start.set(125, 7); 
-		start.set(40, 8); 
-		start.set(41, 9); 
-		start.set(61, 23); 
-		start.set(59, 10); 
-		start.set(60, 24); 
-		start.set(62, 25); 
-		start.set(33, 14); 
-		start.set(43, 16); 
-		start.set(45, 17); 
-		start.set(42, 18); 
-		start.set(47, 19); 
-		start.set(35, 20); 
-		start.set(63, 21); 
-		start.set(58, 22); 
-		start.set(Buffer.EOF, -1);
-		literals.put("function", new Integer(4));
-		literals.put("while", new Integer(7));
-		literals.put("print", new Integer(12));
-		literals.put("return", new Integer(13));
-		literals.put("time", new Integer(27));
+		for (int i = 65; i <= 90; ++i) start.set(i, 1);
+		for (int i = 97; i <= 122; ++i) start.set(i, 1);
+		for (int i = 49; i <= 57; ++i) start.set(i, 4);
+		start.set(34, 2); 
+		start.set(48, 5); 
+		start.set(40, 6); 
+		start.set(44, 7); 
+		start.set(41, 8); 
+		start.set(123, 9); 
+		start.set(125, 10); 
+		start.set(59, 11); 
+		start.set(60, 24); 
+		start.set(62, 25); 
+		start.set(61, 26); 
+		start.set(33, 15); 
+		start.set(43, 17); 
+		start.set(45, 18); 
+		start.set(42, 19); 
+		start.set(47, 20); 
+		start.set(35, 21); 
+		start.set(63, 22); 
+		start.set(58, 23); 
+		start.set(Buffer.EOF, -1);
+		literals.put("function", new Integer(4));
+		literals.put("if", new Integer(11));
+		literals.put("else", new Integer(12));
+		literals.put("while", new Integer(13));
+		literals.put("return", new Integer(14));
 
     }
 
@@ -428,53 +430,53 @@
             tval = newBuf;
         }
         if (ch != Buffer.EOF) {
-			tval[tlen++] = (char)ch; 
+			tval[tlen++] = (char)ch; 
 
             NextCh();
         }
     }
 
-
-	boolean Comment0() {
-		int level = 1, pos0 = pos, line0 = line, col0 = col, charPos0 = charPos;
-		NextCh();
-		if (ch == '/') {
-			NextCh();
-			for(;;) {
-				if (ch == 10) {
-					level--;
-					if (level == 0) { oldEols = line - line0; NextCh(); return true; }
-					NextCh();
-				} else if (ch == Buffer.EOF) return false;
-				else NextCh();
-			}
-		} else {
-			buffer.setPos(pos0); NextCh(); line = line0; col = col0; charPos = charPos0;
-		}
-		return false;
-	}
-
-	boolean Comment1() {
-		int level = 1, pos0 = pos, line0 = line, col0 = col, charPos0 = charPos;
-		NextCh();
-		if (ch == '*') {
-			NextCh();
-			for(;;) {
-				if (ch == '*') {
-					NextCh();
-					if (ch == '/') {
-						level--;
-						if (level == 0) { oldEols = line - line0; NextCh(); return true; }
-						NextCh();
-					}
-				} else if (ch == Buffer.EOF) return false;
-				else NextCh();
-			}
-		} else {
-			buffer.setPos(pos0); NextCh(); line = line0; col = col0; charPos = charPos0;
-		}
-		return false;
-	}
+
+	boolean Comment0() {
+		int level = 1, pos0 = pos, line0 = line, col0 = col, charPos0 = charPos;
+		NextCh();
+		if (ch == '/') {
+			NextCh();
+			for(;;) {
+				if (ch == 10) {
+					level--;
+					if (level == 0) { oldEols = line - line0; NextCh(); return true; }
+					NextCh();
+				} else if (ch == Buffer.EOF) return false;
+				else NextCh();
+			}
+		} else {
+			buffer.setPos(pos0); NextCh(); line = line0; col = col0; charPos = charPos0;
+		}
+		return false;
+	}
+
+	boolean Comment1() {
+		int level = 1, pos0 = pos, line0 = line, col0 = col, charPos0 = charPos;
+		NextCh();
+		if (ch == '*') {
+			NextCh();
+			for(;;) {
+				if (ch == '*') {
+					NextCh();
+					if (ch == '/') {
+						level--;
+						if (level == 0) { oldEols = line - line0; NextCh(); return true; }
+						NextCh();
+					}
+				} else if (ch == Buffer.EOF) return false;
+				else NextCh();
+			}
+		} else {
+			buffer.setPos(pos0); NextCh(); line = line0; col = col0; charPos = charPos0;
+		}
+		return false;
+	}
 
 
     void CheckLiteral() {
@@ -516,69 +518,71 @@
                     t.kind = recKind;
                     break loop;
                 } // NextCh already done
-				case 1:
-					recEnd = pos; recKind = 1;
-					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') {AddCh(); state = 1; break;}
-					else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
-				case 2:
-					if (ch <= 9 || ch >= 11 && ch <= 12 || ch >= 14 && ch <= '!' || ch >= '#' && ch <= '[' || ch >= ']' && ch <= 65535) {AddCh(); state = 2; break;}
-					else if (ch == '"') {AddCh(); state = 3; break;}
-					else {state = 0; break;}
-				case 3:
-					{t.kind = 2; break loop;}
-				case 4:
-					recEnd = pos; recKind = 3;
-					if (ch >= '0' && ch <= '9') {AddCh(); state = 4; break;}
-					else {t.kind = 3; break loop;}
-				case 5:
-					{t.kind = 3; break loop;}
-				case 6:
-					{t.kind = 5; break loop;}
-				case 7:
-					{t.kind = 6; break loop;}
-				case 8:
-					{t.kind = 8; break loop;}
-				case 9:
-					{t.kind = 9; break loop;}
-				case 10:
-					{t.kind = 11; break loop;}
-				case 11:
-					{t.kind = 16; break loop;}
-				case 12:
-					{t.kind = 17; break loop;}
-				case 13:
-					{t.kind = 18; break loop;}
-				case 14:
-					if (ch == '=') {AddCh(); state = 15; break;}
-					else {state = 0; break;}
-				case 15:
-					{t.kind = 19; break loop;}
-				case 16:
-					{t.kind = 20; break loop;}
-				case 17:
-					{t.kind = 21; break loop;}
-				case 18:
-					{t.kind = 22; break loop;}
-				case 19:
-					{t.kind = 23; break loop;}
-				case 20:
-					{t.kind = 24; break loop;}
-				case 21:
-					{t.kind = 25; break loop;}
-				case 22:
-					{t.kind = 26; break loop;}
-				case 23:
-					recEnd = pos; recKind = 10;
-					if (ch == '=') {AddCh(); state = 13; break;}
-					else {t.kind = 10; break loop;}
-				case 24:
-					recEnd = pos; recKind = 14;
-					if (ch == '=') {AddCh(); state = 11; break;}
-					else {t.kind = 14; break loop;}
-				case 25:
-					recEnd = pos; recKind = 15;
-					if (ch == '=') {AddCh(); state = 12; break;}
-					else {t.kind = 15; break loop;}
+				case 1:
+					recEnd = pos; recKind = 1;
+					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') {AddCh(); state = 1; break;}
+					else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
+				case 2:
+					if (ch <= 9 || ch >= 11 && ch <= 12 || ch >= 14 && ch <= '!' || ch >= '#' && ch <= '[' || ch >= ']' && ch <= 65535) {AddCh(); state = 2; break;}
+					else if (ch == '"') {AddCh(); state = 3; break;}
+					else {state = 0; break;}
+				case 3:
+					{t.kind = 2; break loop;}
+				case 4:
+					recEnd = pos; recKind = 3;
+					if (ch >= '0' && ch <= '9') {AddCh(); state = 4; break;}
+					else {t.kind = 3; break loop;}
+				case 5:
+					{t.kind = 3; break loop;}
+				case 6:
+					{t.kind = 5; break loop;}
+				case 7:
+					{t.kind = 6; break loop;}
+				case 8:
+					{t.kind = 7; break loop;}
+				case 9:
+					{t.kind = 8; break loop;}
+				case 10:
+					{t.kind = 9; break loop;}
+				case 11:
+					{t.kind = 10; break loop;}
+				case 12:
+					{t.kind = 17; break loop;}
+				case 13:
+					{t.kind = 18; break loop;}
+				case 14:
+					{t.kind = 19; break loop;}
+				case 15:
+					if (ch == '=') {AddCh(); state = 16; break;}
+					else {state = 0; break;}
+				case 16:
+					{t.kind = 20; break loop;}
+				case 17:
+					{t.kind = 21; break loop;}
+				case 18:
+					{t.kind = 22; break loop;}
+				case 19:
+					{t.kind = 23; break loop;}
+				case 20:
+					{t.kind = 24; break loop;}
+				case 21:
+					{t.kind = 25; break loop;}
+				case 22:
+					{t.kind = 26; break loop;}
+				case 23:
+					{t.kind = 27; break loop;}
+				case 24:
+					recEnd = pos; recKind = 15;
+					if (ch == '=') {AddCh(); state = 12; break;}
+					else {t.kind = 15; break loop;}
+				case 25:
+					recEnd = pos; recKind = 16;
+					if (ch == '=') {AddCh(); state = 13; break;}
+					else {t.kind = 16; break loop;}
+				case 26:
+					recEnd = pos; recKind = 28;
+					if (ch == '=') {AddCh(); state = 14; break;}
+					else {t.kind = 28; break loop;}
 
             }
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.java.old	Mon Nov 11 21:34:44 2013 +0100
@@ -0,0 +1,650 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+ // The content of this file is automatically generated. DO NOT EDIT.
+
+
+package com.oracle.truffle.sl.parser;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.util.Map;
+import java.util.HashMap;
+
+// Checkstyle: stop
+// @formatter:off
+public class Token {
+
+    public int kind; // token kind
+    public int pos; // token position in bytes in the source text (starting at 0)
+    public int charPos; // token position in characters in the source text (starting at 0)
+    public int col; // token column (starting at 1)
+    public int line; // token line (starting at 1)
+    public String val; // token value
+    public Token next; // ML 2005-03-11 Peek tokens are kept in linked list
+}
+
+// -----------------------------------------------------------------------------------
+// Buffer
+// -----------------------------------------------------------------------------------
+class Buffer {
+
+    // This Buffer supports the following cases:
+    // 1) seekable stream (file)
+    // a) whole stream in buffer
+    // b) part of stream in buffer
+    // 2) non seekable stream (network, console)
+
+    public static final int EOF = Character.MAX_VALUE + 1;
+    private static final int MIN_BUFFER_LENGTH = 1024; // 1KB
+    private static final int MAX_BUFFER_LENGTH = MIN_BUFFER_LENGTH * 64; // 64KB
+    private byte[] buf; // input buffer
+    private int bufStart; // position of first byte in buffer relative to input stream
+    private int bufLen; // length of buffer
+    private int fileLen; // length of input stream (may change if stream is no file)
+    private int bufPos; // current position in buffer
+    private RandomAccessFile file; // input stream (seekable)
+    private InputStream stream; // growing input stream (e.g.: console, network)
+
+    public Buffer(InputStream s) {
+        stream = s;
+        fileLen = bufLen = bufStart = bufPos = 0;
+        buf = new byte[MIN_BUFFER_LENGTH];
+    }
+
+    public Buffer(String fileName) {
+        try {
+            file = new RandomAccessFile(fileName, "r");
+            fileLen = (int) file.length();
+            bufLen = Math.min(fileLen, MAX_BUFFER_LENGTH);
+            buf = new byte[bufLen];
+            bufStart = Integer.MAX_VALUE; // nothing in buffer so far
+            if (fileLen > 0)
+                setPos(0); // setup buffer to position 0 (start)
+            else
+                bufPos = 0; // index 0 is already after the file, thus setPos(0) is invalid
+            if (bufLen == fileLen)
+                Close();
+        } catch (IOException e) {
+            throw new FatalError("Could not open file " + fileName);
+        }
+    }
+
+    // don't use b after this call anymore
+    // called in UTF8Buffer constructor
+    protected Buffer(Buffer b) {
+        buf = b.buf;
+        bufStart = b.bufStart;
+        bufLen = b.bufLen;
+        fileLen = b.fileLen;
+        bufPos = b.bufPos;
+        file = b.file;
+        stream = b.stream;
+        // keep finalize from closing the file
+        b.file = null;
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        super.finalize();
+        Close();
+    }
+
+    protected void Close() {
+        if (file != null) {
+            try {
+                file.close();
+                file = null;
+            } catch (IOException e) {
+                throw new FatalError(e.getMessage());
+            }
+        }
+    }
+
+    public int Read() {
+        if (bufPos < bufLen) {
+            return buf[bufPos++] & 0xff; // mask out sign bits
+        } else if (getPos() < fileLen) {
+            setPos(getPos()); // shift buffer start to pos
+            return buf[bufPos++] & 0xff; // mask out sign bits
+        } else if (stream != null && ReadNextStreamChunk() > 0) {
+            return buf[bufPos++] & 0xff; // mask out sign bits
+        } else {
+            return EOF;
+        }
+    }
+
+    public int Peek() {
+        int curPos = getPos();
+        int ch = Read();
+        setPos(curPos);
+        return ch;
+    }
+
+    // beg .. begin, zero-based, inclusive, in byte
+    // end .. end, zero-based, exclusive, in byte
+    public String GetString(int beg, int end) {
+        int len = 0;
+        char[] buffer = new char[end - beg];
+        int oldPos = getPos();
+        setPos(beg);
+        while (getPos() < end)
+            buffer[len++] = (char) Read();
+        setPos(oldPos);
+        return new String(buffer, 0, len);
+    }
+
+    public int getPos() {
+        return bufPos + bufStart;
+    }
+
+    public void setPos(int value) {
+        if (value >= fileLen && stream != null) {
+            // Wanted position is after buffer and the stream
+            // is not seek-able e.g. network or console,
+            // thus we have to read the stream manually till
+            // the wanted position is in sight.
+            while (value >= fileLen && ReadNextStreamChunk() > 0) {
+                // nothing to do...
+            }
+        }
+
+        if (value < 0 || value > fileLen) {
+            throw new FatalError("buffer out of bounds access, position: " + value);
+        }
+
+        if (value >= bufStart && value < bufStart + bufLen) { // already in buffer
+            bufPos = value - bufStart;
+        } else if (file != null) { // must be swapped in
+            try {
+                file.seek(value);
+                bufLen = file.read(buf);
+                bufStart = value;
+                bufPos = 0;
+            } catch (IOException e) {
+                throw new FatalError(e.getMessage());
+            }
+        } else {
+            // set the position to the end of the file, Pos will return fileLen.
+            bufPos = fileLen - bufStart;
+        }
+    }
+
+    // Read the next chunk of bytes from the stream, increases the buffer
+    // if needed and updates the fields fileLen and bufLen.
+    // Returns the number of bytes read.
+    private int ReadNextStreamChunk() {
+        int free = buf.length - bufLen;
+        if (free == 0) {
+            // in the case of a growing input stream
+            // we can neither seek in the stream, nor can we
+            // foresee the maximum length, thus we must adapt
+            // the buffer size on demand.
+            byte[] newBuf = new byte[bufLen * 2];
+            System.arraycopy(buf, 0, newBuf, 0, bufLen);
+            buf = newBuf;
+            free = bufLen;
+        }
+
+        int read;
+        try {
+            read = stream.read(buf, bufLen, free);
+        } catch (IOException ioex) {
+            throw new FatalError(ioex.getMessage());
+        }
+
+        if (read > 0) {
+            fileLen = bufLen = (bufLen + read);
+            return read;
+        }
+        // end of stream reached
+        return 0;
+    }
+}
+
+// -----------------------------------------------------------------------------------
+// UTF8Buffer
+// -----------------------------------------------------------------------------------
+class UTF8Buffer extends Buffer {
+
+    UTF8Buffer(Buffer b) {
+        super(b);
+    }
+
+    @Override
+    public int Read() {
+        int ch;
+        do {
+            ch = super.Read();
+            // until we find a utf8 start (0xxxxxxx or 11xxxxxx)
+        } while ((ch >= 128) && ((ch & 0xC0) != 0xC0) && (ch != EOF));
+        if (ch < 128 || ch == EOF) {
+            // nothing to do, first 127 chars are the same in ascii and utf8
+            // 0xxxxxxx or end of file character
+        } else if ((ch & 0xF0) == 0xF0) {
+            // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+            int c1 = ch & 0x07;
+            ch = super.Read();
+            int c2 = ch & 0x3F;
+            ch = super.Read();
+            int c3 = ch & 0x3F;
+            ch = super.Read();
+            int c4 = ch & 0x3F;
+            ch = (((((c1 << 6) | c2) << 6) | c3) << 6) | c4;
+        } else if ((ch & 0xE0) == 0xE0) {
+            // 1110xxxx 10xxxxxx 10xxxxxx
+            int c1 = ch & 0x0F;
+            ch = super.Read();
+            int c2 = ch & 0x3F;
+            ch = super.Read();
+            int c3 = ch & 0x3F;
+            ch = (((c1 << 6) | c2) << 6) | c3;
+        } else if ((ch & 0xC0) == 0xC0) {
+            // 110xxxxx 10xxxxxx
+            int c1 = ch & 0x1F;
+            ch = super.Read();
+            int c2 = ch & 0x3F;
+            ch = (c1 << 6) | c2;
+        }
+        return ch;
+    }
+}
+
+// -----------------------------------------------------------------------------------
+// StartStates -- maps characters to start states of tokens
+// -----------------------------------------------------------------------------------
+class StartStates {
+
+    private static class Elem {
+
+        public int key, val;
+        public Elem next;
+
+        public Elem(int key, int val) {
+            this.key = key;
+            this.val = val;
+        }
+    }
+
+    private Elem[] tab = new Elem[128];
+
+    public void set(int key, int val) {
+        Elem e = new Elem(key, val);
+        int k = key % 128;
+        e.next = tab[k];
+        tab[k] = e;
+    }
+
+    public int state(int key) {
+        Elem e = tab[key % 128];
+        while (e != null && e.key != key)
+            e = e.next;
+        return e == null ? 0 : e.val;
+    }
+}
+
+// -----------------------------------------------------------------------------------
+// Scanner
+// -----------------------------------------------------------------------------------
+@SuppressWarnings({"rawtypes", "unchecked"})
+public class Scanner {
+
+    static final char EOL = '\n';
+    static final int eofSym = 0;
+	static final int maxT = 29;
+	static final int noSym = 29;
+
+
+    public Buffer buffer; // scanner buffer
+
+    Token t; // current token
+    int ch; // current input character
+    int pos; // byte position of current character
+    int charPos; // position by unicode characters starting with 0
+    int col; // column number of current character
+    int line; // line number of current character
+    int oldEols; // EOLs that appeared in a comment;
+    static final StartStates start; // maps initial token character to start state
+    static final Map literals; // maps literal strings to literal kinds
+
+    Token tokens; // list of tokens already peeked (first token is a dummy)
+    Token pt; // current peek token
+
+    char[] tval = new char[16]; // token text used in NextToken(), dynamically enlarged
+    int tlen; // length of current token
+
+    static {
+        start = new StartStates();
+        literals = new HashMap();
+		for (int i = 65; i <= 90; ++i) start.set(i, 1);
+		for (int i = 97; i <= 122; ++i) start.set(i, 1);
+		for (int i = 49; i <= 57; ++i) start.set(i, 4);
+		start.set(34, 2); 
+		start.set(48, 5); 
+		start.set(40, 6); 
+		start.set(44, 7); 
+		start.set(41, 8); 
+		start.set(123, 9); 
+		start.set(125, 10); 
+		start.set(59, 11); 
+		start.set(60, 24); 
+		start.set(62, 25); 
+		start.set(61, 26); 
+		start.set(33, 15); 
+		start.set(43, 17); 
+		start.set(45, 18); 
+		start.set(42, 19); 
+		start.set(47, 20); 
+		start.set(35, 21); 
+		start.set(63, 22); 
+		start.set(58, 23); 
+		start.set(Buffer.EOF, -1);
+		literals.put("function", new Integer(4));
+		literals.put("if", new Integer(11));
+		literals.put("else", new Integer(12));
+		literals.put("while", new Integer(13));
+		literals.put("return", new Integer(14));
+
+    }
+
+    public Scanner(String fileName) {
+        buffer = new Buffer(fileName);
+        Init();
+    }
+
+    public Scanner(InputStream s) {
+        buffer = new Buffer(s);
+        Init();
+    }
+
+    void Init() {
+        pos = -1;
+        line = 1;
+        col = 0;
+        charPos = -1;
+        oldEols = 0;
+        NextCh();
+        if (ch == 0xEF) { // check optional byte order mark for UTF-8
+            NextCh();
+            int ch1 = ch;
+            NextCh();
+            int ch2 = ch;
+            if (ch1 != 0xBB || ch2 != 0xBF) {
+                throw new FatalError("Illegal byte order mark at start of file");
+            }
+            buffer = new UTF8Buffer(buffer);
+            col = 0;
+            charPos = -1;
+            NextCh();
+        }
+        pt = tokens = new Token(); // first token is a dummy
+    }
+
+    void NextCh() {
+        if (oldEols > 0) {
+            ch = EOL;
+            oldEols--;
+        } else {
+            pos = buffer.getPos();
+            // buffer reads unicode chars, if UTF8 has been detected
+            ch = buffer.Read();
+            col++;
+            charPos++;
+            // replace isolated '\r' by '\n' in order to make
+            // eol handling uniform across Windows, Unix and Mac
+            if (ch == '\r' && buffer.Peek() != '\n')
+                ch = EOL;
+            if (ch == EOL) {
+                line++;
+                col = 0;
+            }
+        }
+
+    }
+
+    void AddCh() {
+        if (tlen >= tval.length) {
+            char[] newBuf = new char[2 * tval.length];
+            System.arraycopy(tval, 0, newBuf, 0, tval.length);
+            tval = newBuf;
+        }
+        if (ch != Buffer.EOF) {
+			tval[tlen++] = (char)ch; 
+
+            NextCh();
+        }
+    }
+
+
+	boolean Comment0() {
+		int level = 1, pos0 = pos, line0 = line, col0 = col, charPos0 = charPos;
+		NextCh();
+		if (ch == '/') {
+			NextCh();
+			for(;;) {
+				if (ch == 10) {
+					level--;
+					if (level == 0) { oldEols = line - line0; NextCh(); return true; }
+					NextCh();
+				} else if (ch == Buffer.EOF) return false;
+				else NextCh();
+			}
+		} else {
+			buffer.setPos(pos0); NextCh(); line = line0; col = col0; charPos = charPos0;
+		}
+		return false;
+	}
+
+	boolean Comment1() {
+		int level = 1, pos0 = pos, line0 = line, col0 = col, charPos0 = charPos;
+		NextCh();
+		if (ch == '*') {
+			NextCh();
+			for(;;) {
+				if (ch == '*') {
+					NextCh();
+					if (ch == '/') {
+						level--;
+						if (level == 0) { oldEols = line - line0; NextCh(); return true; }
+						NextCh();
+					}
+				} else if (ch == Buffer.EOF) return false;
+				else NextCh();
+			}
+		} else {
+			buffer.setPos(pos0); NextCh(); line = line0; col = col0; charPos = charPos0;
+		}
+		return false;
+	}
+
+
+    void CheckLiteral() {
+        String val = t.val;
+
+        Object kind = literals.get(val);
+        if (kind != null) {
+            t.kind = ((Integer) kind).intValue();
+        }
+    }
+
+    Token NextToken() {
+        while (ch == ' ' || 
+			ch >= 9 && ch <= 10 || ch == 13
+        ) NextCh();
+		if (ch == '/' && Comment0() ||ch == '/' && Comment1()) return NextToken();
+        int recKind = noSym;
+        int recEnd = pos;
+        t = new Token();
+        t.pos = pos;
+        t.col = col;
+        t.line = line;
+        t.charPos = charPos;
+        int state = start.state(ch);
+        tlen = 0;
+        AddCh();
+
+        loop: for (;;) {
+            switch (state) {
+                case -1: {
+                    t.kind = eofSym;
+                    break loop;
+                } // NextCh already done
+                case 0: {
+                    if (recKind != noSym) {
+                        tlen = recEnd - t.pos;
+                        SetScannerBehindT();
+                    }
+                    t.kind = recKind;
+                    break loop;
+                } // NextCh already done
+				case 1:
+					recEnd = pos; recKind = 1;
+					if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') {AddCh(); state = 1; break;}
+					else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
+				case 2:
+					if (ch <= 9 || ch >= 11 && ch <= 12 || ch >= 14 && ch <= '!' || ch >= '#' && ch <= '[' || ch >= ']' && ch <= 65535) {AddCh(); state = 2; break;}
+					else if (ch == '"') {AddCh(); state = 3; break;}
+					else {state = 0; break;}
+				case 3:
+					{t.kind = 2; break loop;}
+				case 4:
+					recEnd = pos; recKind = 3;
+					if (ch >= '0' && ch <= '9') {AddCh(); state = 4; break;}
+					else {t.kind = 3; break loop;}
+				case 5:
+					{t.kind = 3; break loop;}
+				case 6:
+					{t.kind = 5; break loop;}
+				case 7:
+					{t.kind = 6; break loop;}
+				case 8:
+					{t.kind = 7; break loop;}
+				case 9:
+					{t.kind = 8; break loop;}
+				case 10:
+					{t.kind = 9; break loop;}
+				case 11:
+					{t.kind = 10; break loop;}
+				case 12:
+					{t.kind = 17; break loop;}
+				case 13:
+					{t.kind = 18; break loop;}
+				case 14:
+					{t.kind = 19; break loop;}
+				case 15:
+					if (ch == '=') {AddCh(); state = 16; break;}
+					else {state = 0; break;}
+				case 16:
+					{t.kind = 20; break loop;}
+				case 17:
+					{t.kind = 21; break loop;}
+				case 18:
+					{t.kind = 22; break loop;}
+				case 19:
+					{t.kind = 23; break loop;}
+				case 20:
+					{t.kind = 24; break loop;}
+				case 21:
+					{t.kind = 25; break loop;}
+				case 22:
+					{t.kind = 26; break loop;}
+				case 23:
+					{t.kind = 27; break loop;}
+				case 24:
+					recEnd = pos; recKind = 15;
+					if (ch == '=') {AddCh(); state = 12; break;}
+					else {t.kind = 15; break loop;}
+				case 25:
+					recEnd = pos; recKind = 16;
+					if (ch == '=') {AddCh(); state = 13; break;}
+					else {t.kind = 16; break loop;}
+				case 26:
+					recEnd = pos; recKind = 28;
+					if (ch == '=') {AddCh(); state = 14; break;}
+					else {t.kind = 28; break loop;}
+
+            }
+        }
+        t.val = new String(tval, 0, tlen);
+        return t;
+    }
+
+    private void SetScannerBehindT() {
+        buffer.setPos(t.pos);
+        NextCh();
+        line = t.line;
+        col = t.col;
+        charPos = t.charPos;
+        for (int i = 0; i < tlen; i++)
+            NextCh();
+    }
+
+    // get the next token (possibly a token already seen during peeking)
+    public Token Scan() {
+        if (tokens.next == null) {
+            return NextToken();
+        } else {
+            pt = tokens = tokens.next;
+            return tokens;
+        }
+    }
+
+    // get the next token, ignore pragmas
+    public Token Peek() {
+        do {
+            if (pt.next == null) {
+                pt.next = NextToken();
+            }
+            pt = pt.next;
+        } while (pt.kind > maxT); // skip pragmas
+
+        return pt;
+    }
+
+    // make sure that peeking starts at current scan position
+    public void ResetPeek() {
+        pt = tokens;
+    }
+
+    // The following methods are used for the CLNG Editor and will be called with java.Reflection.
+    // If the editor won't be used these 3 functions are obsolete,
+    // otherwise changes within the signature of the methods will result in Syntax Highlighting not working properly
+// anymore.
+
+    // get the offset of the next Token
+    public int getPeekTokenOffset() {
+        return pt.pos;
+    }
+
+    // get the String value of the Token
+    public String getPeekTokenVal() {
+        return pt.val;
+    }
+
+    // get the Kind value of the Token
+    public int getPeekTokenKind() {
+        return pt.kind;
+    }
+
+} // end Scanner
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg	Thu Nov 07 20:55:13 2013 +0100
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg	Mon Nov 11 21:34:44 2013 +0100
@@ -35,8 +35,12 @@
 Function
 =
 "function"                                      (. factory.startFunction(); .)
-identifier                                      (. String name = t.val; .)
-Block<out StatementNode body>                   (. factory.createFunction(body, name); .)
+identifier                                      (. String name = t.val; 
+                                                   List<String> parameterNames = new ArrayList<>(); .)
+["(" [identifier                                (. parameterNames.add(t.val); .)
+] {"," identifier                               (. parameterNames.add(t.val); .)
+} ")"]
+Block<out StatementNode body>                   (. factory.createFunction(body, name, parameterNames.toArray(new String[parameterNames.size()])); .)
 .
 
 Block<out StatementNode result>
@@ -52,15 +56,22 @@
 =                                               (. result = null; .)
 (
     WhileStatement<out result>
-|
-    AssignmentStatement<out result>
-|
-    OutputStatement<out result>
+|   
+    IfStatement<out result>
 |
     ReturnStatement<out result>
+|
+    Expression<out result> ";"
 )
 .
 
+IfStatement<out StatementNode result>
+=
+"if" "(" Expression<out ConditionNode condition> ")"  (. StatementNode thenNode = null; StatementNode elseNode = null; .)
+Block<out thenNode>                             
+["else" Block<out elseNode>]                    (. result = factory.createIf(condition, thenNode, elseNode); .)
+.
+
 WhileStatement<out StatementNode result>
 =
 "while"
@@ -70,22 +81,6 @@
 Block<out StatementNode body>                   (. result = factory.createWhile(condition, body); .)
 .
 
-AssignmentStatement<out StatementNode result>
-=
-identifier                                      (. String name = t.val; .)
-"="
-Expression<out TypedNode rvalue>
-";"                                             (. result = factory.createAssignment(name, rvalue); .)
-.
-
-OutputStatement<out StatementNode result>
-=                                               (. List<TypedNode> expressions = new ArrayList<>(); .)
-"print"
-{
-    Expression<out TypedNode value>             (. expressions.add(value); .)
-}
-";"                                             (. result = factory.createPrint(expressions); .)
-.
 
 ReturnStatement<out StatementNode result>
 =
@@ -123,15 +118,13 @@
 Factor<out TypedNode result>
 =                                               (. result = null; .)
 (
-    TimeRef<out result>
-|
-    VariableRef<out result>
+    VariableRefOrCall<out result>
 |
     StringLiteral<out result>
 |
     NumericLiteral<out result>
 |
-    Ternary<out result>  
+    Ternary<out result>
 |
     "(" Expression<out result> ")"
 ) 
@@ -143,9 +136,23 @@
                                                 (. result = factory.createTernary(condition, thenPart, elsePart); .)
 .
 
-TimeRef<out TypedNode result> 
+VariableRefOrCall<out TypedNode result> 
 =
-"time"                                          (. result = factory.createTime(); .)
+VariableRef<out result>                  
+[
+  (Parameters<out TypedNode[] parameters>)      (. result = factory.createCall(result, parameters); .)
+| ("=" Expression<out TypedNode assignment>)    (. result = factory.createAssignment(result, assignment); .)
+]
+.
+
+Parameters<out TypedNode[] result> 
+=      
+"("                                         (. List<TypedNode> parameters = new ArrayList<>(); .)
+[Expression<out TypedNode e1>                   (. parameters.add(e1); .)
+{"," Expression<out TypedNode e2>               (. parameters.add(e2); .)
+}                                               
+]                                           (. result = parameters.toArray(new TypedNode[parameters.size()]); .) 
+")"
 .
 
 VariableRef<out TypedNode result>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLArguments.java	Mon Nov 11 21:34:44 2013 +0100
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.runtime;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.frame.*;
+
+public final class SLArguments extends Arguments {
+
+    public final Object[] arguments;
+
+    public SLArguments(Object[] arguments) {
+        this.arguments = arguments;
+    }
+
+    public static SLArguments get(VirtualFrame frame) {
+        return frame.getArguments(SLArguments.class);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java	Mon Nov 11 21:34:44 2013 +0100
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.runtime;
+
+import java.io.*;
+
+import com.oracle.truffle.sl.builtins.*;
+
+public final class SLContext {
+
+    private final PrintStream printOutput;
+    private final SLFunctionRegistry functionRegistry;
+
+    public SLContext(PrintStream print) {
+        this.printOutput = print;
+        this.functionRegistry = new SLFunctionRegistry();
+        DefaultBuiltins.install(this);
+    }
+
+    public PrintStream getPrintOutput() {
+        return printOutput;
+    }
+
+    public SLFunctionRegistry getFunctionRegistry() {
+        return functionRegistry;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLFunctionRegistry.java	Mon Nov 11 21:34:44 2013 +0100
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.runtime;
+
+import java.util.*;
+
+import com.oracle.truffle.api.*;
+
+public final class SLFunctionRegistry {
+
+    private Map<String, CallTarget> map = new HashMap<>();
+
+    public void register(String name, CallTarget target) {
+        if (map.containsKey(name)) {
+            throw new IllegalArgumentException(String.format("Function with name '%s' already exists.", name));
+        }
+        map.put(name, target);
+    }
+
+    public CallTarget lookup(String name) {
+        return map.get(name);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLNull.java	Mon Nov 11 21:34:44 2013 +0100
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.sl.runtime;
+
+public final class SLNull {
+
+    public static final SLNull INSTANCE = new SLNull();
+
+    private SLNull() {
+    }
+
+}