changeset 13836:64c77f0577bb

More documentation and improvements of Simple Language
author Christian Wimmer <christian.wimmer@oracle.com>
date Thu, 30 Jan 2014 17:53:27 -0800
parents 67e4e7f56911
children ed3a1471e133
files graal/com.oracle.truffle.sl.test/tests/Break.output graal/com.oracle.truffle.sl.test/tests/Break.sl graal/com.oracle.truffle.sl.test/tests/LoopCall.output graal/com.oracle.truffle.sl.test/tests/LoopCall.sl graal/com.oracle.truffle.sl.test/tests/LoopPolymorphic.output graal/com.oracle.truffle.sl.test/tests/LoopPolymorphic.sl graal/com.oracle.truffle.sl.test/tests/LoopPrint.sl graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLBuiltinNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLBinaryNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLAbstractDispatchNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLDirectDispatchNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLUninitializedDispatchNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBlockNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBreakException.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBreakNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLContinueException.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLContinueNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLFunctionBodyNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLIfNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLReturnException.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLReturnNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLWhileNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLAddNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLBigIntegerLiteralNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLDivNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLEqualNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLFunctionLiteralNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLessOrEqualNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLessThanNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLogicalAndNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLogicalNotNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLogicalOrNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLongLiteralNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLMulNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLStringLiteralNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLSubNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLReadArgumentNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLReadLocalVariableNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLWriteLocalVariableNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLFunction.java
diffstat 45 files changed, 433 insertions(+), 51 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl.test/tests/Break.output	Thu Jan 30 17:53:27 2014 -0800
@@ -0,0 +1,1 @@
+942
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl.test/tests/Break.sl	Thu Jan 30 17:53:27 2014 -0800
@@ -0,0 +1,10 @@
+function main() {  
+  i = 0;  
+  while (i < 1000) {
+    if (i >= 942) {
+      break;
+    }  
+    i = i + 1;  
+  }
+  return i;  
+}  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl.test/tests/LoopCall.output	Thu Jan 30 17:53:27 2014 -0800
@@ -0,0 +1,1 @@
+1000
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl.test/tests/LoopCall.sl	Thu Jan 30 17:53:27 2014 -0800
@@ -0,0 +1,15 @@
+function add(a, b) {
+  return a + b;
+}
+
+function loop(n) {
+  i = 0;  
+  while (i < n) {  
+    i = add(i, 1);  
+  }  
+  return i;
+}  
+
+function main() {
+  println(loop(1000));  
+}  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl.test/tests/LoopPolymorphic.output	Thu Jan 30 17:53:27 2014 -0800
@@ -0,0 +1,1 @@
+1000
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl.test/tests/LoopPolymorphic.sl	Thu Jan 30 17:53:27 2014 -0800
@@ -0,0 +1,16 @@
+function add(a, b) {
+  return a + b;
+}
+
+function loop(n) {
+  i = 0;  
+  while (i < n) {  
+    i = add(i, 1);  
+  }  
+  return i;
+}  
+
+function main() {
+  add("a", "b");
+  println(loop(1000));  
+}  
--- a/graal/com.oracle.truffle.sl.test/tests/LoopPrint.sl	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl.test/tests/LoopPrint.sl	Thu Jan 30 17:53:27 2014 -0800
@@ -1,7 +1,11 @@
-function main() {  
+function loop(n) {
   i = 0;  
-  while (i < 1000) {  
+  while (i < n) {  
     i = i + 1;  
   }  
-  println(i);  
+  return i;
 }  
+
+function main() {
+  println(loop(1000));  
+}  
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLMain.java	Thu Jan 30 17:53:27 2014 -0800
@@ -116,18 +116,21 @@
     /**
      * The main entry point. Use the mx command "mx sl" to run it with the correct class path setup.
      */
-    public static void main(String[] args) {
+    public static void main(String[] args) throws IOException {
+        SourceManager sourceManager = new SourceManager();
+
+        Source source;
         if (args.length == 0) {
-            throw new SLException("SL source file must be specified as the first argument");
+            source = sourceManager.get("stdin", System.in);
+        } else {
+            source = sourceManager.get(args[0]);
         }
-        String fileName = args[0];
+
         int repeats = 1;
         if (args.length >= 2) {
             repeats = Integer.parseInt(args[1]);
         }
 
-        SourceManager sourceManager = new SourceManager();
-        Source source = sourceManager.get(fileName);
         SLContext context = new SLContext(sourceManager, new BufferedReader(new InputStreamReader(System.in)), System.out);
         run(context, source, System.out, repeats);
     }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLBuiltinNode.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLBuiltinNode.java	Thu Jan 30 17:53:27 2014 -0800
@@ -33,7 +33,7 @@
  * and setting it in a constructor, we use the Truffle DSL annotation {@link NodeField} that
  * generates the field and constructor automatically.
  * <p>
- * The builitin functions are registered in {@link SLContext#installBuiltins}. Every builtin node
+ * The builtin functions are registered in {@link SLContext#installBuiltins}. Every builtin node
  * subclass is instantiated there, wrapped into a function, and added to the
  * {@link SLFunctionRegistry}. This ensures that builtin functions can be called like user-defined
  * functions; there is no special function lookup or call node for builtin functions.
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLBinaryNode.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLBinaryNode.java	Thu Jan 30 17:53:27 2014 -0800
@@ -26,8 +26,8 @@
 
 /**
  * Utility base class for operations that take two arguments (per convention called "left" and
- * "right). For concrete subclassses of this class, the Truffle DSL creates two child fields, and
- * the necessary constructors and logic to set them.
+ * "right). For concrete subclasses of this class, the Truffle DSL creates two child fields, and the
+ * necessary constructors and logic to set them.
  */
 @NodeChildren({@NodeChild("leftNode"), @NodeChild("rightNode")})
 public abstract class SLBinaryNode extends SLExpressionNode {
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLAbstractDispatchNode.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLAbstractDispatchNode.java	Thu Jan 30 17:53:27 2014 -0800
@@ -28,7 +28,7 @@
 
 /**
  * Before a call is executed the first time, the dispatch node is a
- * {@link SLUninitializedDispatchNode}. During execution, the call is optimized using a polymprphic
+ * {@link SLUninitializedDispatchNode}. During execution, the call is optimized using a polymorphic
  * inline cache, i.e., a chain of {@link SLDirectDispatchNode}s. The chain is terminated by a
  * {@link SLUninitializedDispatchNode}. If the chain gets too long (longer than
  * {@link #INLINE_CACHE_SIZE}), i.e., if the call is too polymorphic, the whole chain is replaced by
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLDirectDispatchNode.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLDirectDispatchNode.java	Thu Jan 30 17:53:27 2014 -0800
@@ -96,7 +96,7 @@
 
             } catch (InvalidAssumptionException ex) {
                 /*
-                 * The function has been redefined. Remove ourselfs from the polymorphic inline
+                 * The function has been redefined. Remove ourself from the polymorphic inline
                  * cache, so that we fail the check only once. Note that this replacement has subtle
                  * semantics: we are changing a node in the tree that is currently executed. This is
                  * only safe because we know that after the call to replace(), there is no more code
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLUninitializedDispatchNode.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/call/SLUninitializedDispatchNode.java	Thu Jan 30 17:53:27 2014 -0800
@@ -65,13 +65,13 @@
             /* Extend the inline cache. Allocate the new cache entry, and the new end of the cache. */
             SLAbstractDispatchNode next = new SLUninitializedDispatchNode();
             SLAbstractDispatchNode direct = new SLDirectDispatchNode(next, function);
-            /* Replace ourselfs with the new cache entry. */
+            /* Replace ourself with the new cache entry. */
             specialized = replace(direct);
 
         } else {
             /* Cache size exceeded, fall back to a single generic dispatch node. */
             SLAbstractDispatchNode generic = new SLGenericDispatchNode();
-            /* Replace the whole chain, not just ourselfs, with the new generic node. */
+            /* Replace the whole chain, not just ourself, with the new generic node. */
             specialized = callNode.dispatchNode.replace(generic);
         }
 
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBlockNode.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBlockNode.java	Thu Jan 30 17:53:27 2014 -0800
@@ -26,15 +26,32 @@
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.sl.nodes.*;
 
+/**
+ * A statement node that just executes a list of other statements.
+ */
 @NodeInfo(shortName = "block")
 public class SLBlockNode extends SLStatementNode {
 
+    /**
+     * The array of child nodes. The annotation {@link com.oracle.truffle.api.nodes.Node.Children
+     * Children} informs Truffle that the field contains multiple children. It is a Truffle
+     * requirement that the field is {@code final} and an array of nodes.
+     */
     @Children private final SLStatementNode[] bodyNodes;
 
     public SLBlockNode(SLStatementNode[] bodyNodes) {
+        /*
+         * It is a Truffle requirement to call adoptChildren(), which performs all the necessary
+         * steps to add the new children to the node tree.
+         */
         this.bodyNodes = adoptChildren(bodyNodes);
     }
 
+    /**
+     * Execute all child statements. The annotation {@link ExplodeLoop} triggers full unrolling of
+     * the loop during compilation. This allows the {@link SLStatementNode#executeVoid} method of
+     * all children to be inlined.
+     */
     @Override
     @ExplodeLoop
     public void executeVoid(VirtualFrame frame) {
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBreakException.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBreakException.java	Thu Jan 30 17:53:27 2014 -0800
@@ -24,12 +24,18 @@
 
 import com.oracle.truffle.api.nodes.*;
 
+/**
+ * Exception thrown by the {@link SLBreakNode break statement} and caught by the {@link SLWhileNode
+ * loop statement}. Since the exception is stateless, i.e., has no instance fields, we can use a
+ * {@link #SINGLETON} to avoid memory allocation during interpretation.
+ */
 public final class SLBreakException extends ControlFlowException {
 
     public static final SLBreakException SINGLETON = new SLBreakException();
 
     private static final long serialVersionUID = -91013036379258890L;
 
+    /* Prevent instantiation from outside. */
     private SLBreakException() {
     }
 }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBreakNode.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLBreakNode.java	Thu Jan 30 17:53:27 2014 -0800
@@ -26,6 +26,12 @@
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.sl.nodes.*;
 
+/**
+ * Implementation of the SL break statement. We need to unwind an unknown number of interpreter
+ * frames that are between this {@link SLBreakNode} and the {@link SLWhileNode} of the loop we are
+ * breaking out. This is done by throwing an {@link SLBreakException exception} that is caught by
+ * the {@link SLWhileNode#executeVoid loop node}.
+ */
 @NodeInfo(shortName = "break")
 public final class SLBreakNode extends SLStatementNode {
 
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLContinueException.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLContinueException.java	Thu Jan 30 17:53:27 2014 -0800
@@ -24,12 +24,18 @@
 
 import com.oracle.truffle.api.nodes.*;
 
+/**
+ * Exception thrown by the {@link SLContinueNode continue statement} and caught by the
+ * {@link SLWhileNode loop statement}. Since the exception is stateless, i.e., has no instance
+ * fields, we can use a {@link #SINGLETON} to avoid memory allocation during interpretation.
+ */
 public final class SLContinueException extends ControlFlowException {
 
     public static final SLContinueException SINGLETON = new SLContinueException();
 
     private static final long serialVersionUID = 5329687983726237188L;
 
+    /* Prevent instantiation from outside. */
     private SLContinueException() {
     }
 }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLContinueNode.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLContinueNode.java	Thu Jan 30 17:53:27 2014 -0800
@@ -26,6 +26,12 @@
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.sl.nodes.*;
 
+/**
+ * Implementation of the SL continue statement. We need to unwind an unknown number of interpreter
+ * frames that are between this {@link SLContinueNode} and the {@link SLWhileNode} of the loop we
+ * are continuing. This is done by throwing an {@link SLContinueException exception} that is caught
+ * by the {@link SLWhileNode#executeVoid loop node}.
+ */
 @NodeInfo(shortName = "continue")
 public final class SLContinueNode extends SLStatementNode {
 
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLFunctionBodyNode.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLFunctionBodyNode.java	Thu Jan 30 17:53:27 2014 -0800
@@ -28,27 +28,57 @@
 import com.oracle.truffle.sl.nodes.*;
 import com.oracle.truffle.sl.runtime.*;
 
+/**
+ * The body of a user-defined SL function. This is the node references by a {@link SLRootNode} for
+ * user-defined functions. It handles the return value of a function: the {@link SLReturnNode return
+ * statement} throws an {@link SLReturnException exception} with the return value. This node catches
+ * the exception. If the method ends without an explicit {@code return}, return the
+ * {@link SLNull#SINGLETON default null value}.
+ */
 @NodeInfo(shortName = "body")
 public class SLFunctionBodyNode extends SLExpressionNode {
 
+    /** The body of the function. */
     @Child private SLStatementNode bodyNode;
 
+    /**
+     * Profiling information, collected by the interpreter, capturing whether the function had an
+     * {@link SLReturnNode explicit return statement}. This allows the compiler to generate better
+     * code.
+     */
     private final BranchProfile exceptionTaken = new BranchProfile();
     private final BranchProfile nullTaken = new BranchProfile();
 
     public SLFunctionBodyNode(SLStatementNode bodyNode) {
+        /*
+         * It is a Truffle requirement to call adoptChild(), which performs all the necessary steps
+         * to add the new child to the node tree.
+         */
         this.bodyNode = adoptChild(bodyNode);
     }
 
     @Override
     public Object executeGeneric(VirtualFrame frame) {
         try {
+            /* Execute the function body. */
             bodyNode.executeVoid(frame);
+
         } catch (SLReturnException ex) {
+            /*
+             * In the interpreter, record profiling information that the function has an explicit
+             * return.
+             */
             exceptionTaken.enter();
+            /* The exception transports the actual return value. */
             return ex.getResult();
         }
+
+        /*
+         * In the interpreter, record profiling information that the function ends without an
+         * explicit return.
+         */
         nullTaken.enter();
+        /* Return the default null value. */
         return SLNull.SINGLETON;
     }
 }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLIfNode.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLIfNode.java	Thu Jan 30 17:53:27 2014 -0800
@@ -30,14 +30,33 @@
 
 @NodeInfo(shortName = "if")
 public class SLIfNode extends SLStatementNode {
+
+    /**
+     * The condition of the {@code if}. This in a {@link SLExpressionNode} because we require a
+     * result value. We do not have a node type that can only return a {@code boolean} value, so
+     * {@link #evaluateCondition executing the condition} can lead to a type error.
+     */
     @Child private SLExpressionNode conditionNode;
+
+    /** Statement (or {@SLBlockNode block}) executed when the condition is true. */
     @Child private SLStatementNode thenPartNode;
+
+    /** Statement (or {@SLBlockNode block}) executed when the condition is false. */
     @Child private SLStatementNode elsePartNode;
 
+    /**
+     * Profiling information, collected by the interpreter, capturing whether the then-branch was
+     * used (analogously for the {@link #elseTaken else-branch}). This allows the compiler to
+     * generate better code for conditions that are always true or always false.
+     */
     private final BranchProfile thenTaken = new BranchProfile();
     private final BranchProfile elseTaken = new BranchProfile();
 
     public SLIfNode(SLExpressionNode conditionNode, SLStatementNode thenPartNode, SLStatementNode elsePartNode) {
+        /*
+         * It is a Truffle requirement to call adoptChild(), which performs all the necessary steps
+         * to add the new child to the node tree.
+         */
         this.conditionNode = adoptChild(conditionNode);
         this.thenPartNode = adoptChild(thenPartNode);
         this.elsePartNode = adoptChild(elsePartNode);
@@ -46,11 +65,15 @@
     @Override
     public void executeVoid(VirtualFrame frame) {
         if (evaluateCondition(frame)) {
+            /* In the interpreter, record profiling information that the then-branch was used. */
             thenTaken.enter();
+            /* Execute the then-branch. */
             thenPartNode.executeVoid(frame);
         } else {
+            /* In the interpreter, record profiling information that the else-branch was used. */
+            elseTaken.enter();
+            /* Execute the else-branch (which is optional according to the SL syntax). */
             if (elsePartNode != null) {
-                elseTaken.enter();
                 elsePartNode.executeVoid(frame);
             }
         }
@@ -59,8 +82,8 @@
     private boolean evaluateCondition(VirtualFrame frame) {
         try {
             /*
-             * The condition must evaluate to a boolean value, so we call boolean-specialized
-             * method.
+             * The condition must evaluate to a boolean value, so we call the boolean-specialized
+             * execute method.
              */
             return conditionNode.executeBoolean(frame);
         } catch (UnexpectedResultException ex) {
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLReturnException.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLReturnException.java	Thu Jan 30 17:53:27 2014 -0800
@@ -24,6 +24,11 @@
 
 import com.oracle.truffle.api.nodes.*;
 
+/**
+ * Exception thrown by the {@link SLReturnNode return statement} and caught by the
+ * {@link SLFunctionBodyNode function body}. The exception transports the return value in its
+ * {@link #result} field.
+ */
 public final class SLReturnException extends ControlFlowException {
 
     private static final long serialVersionUID = 4073191346281369231L;
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLReturnNode.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLReturnNode.java	Thu Jan 30 17:53:27 2014 -0800
@@ -27,6 +27,13 @@
 import com.oracle.truffle.sl.nodes.*;
 import com.oracle.truffle.sl.runtime.*;
 
+/**
+ * Implementation of the SL return statement. We need to unwind an unknown number of interpreter
+ * frames that are between this {@link SLReturnNode} and the {@link SLFunctionBodyNode} of the
+ * method we are exiting. This is done by throwing an {@link SLReturnException exception} that is
+ * caught by the {@link SLFunctionBodyNode#executeGeneric function body}. The exception transports
+ * the return value.
+ */
 @NodeInfo(shortName = "return")
 public class SLReturnNode extends SLStatementNode {
 
@@ -42,6 +49,7 @@
         if (valueNode != null) {
             result = valueNode.executeGeneric(frame);
         } else {
+            /* Return statement that was not followed by an expression, so return the SL null value. */
             result = SLNull.SINGLETON;
         }
         throw new SLReturnException(result);
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLWhileNode.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/controlflow/SLWhileNode.java	Thu Jan 30 17:53:27 2014 -0800
@@ -32,13 +32,29 @@
 @NodeInfo(shortName = "while")
 public class SLWhileNode extends SLStatementNode {
 
+    /**
+     * The condition of the loop. This in a {@link SLExpressionNode} because we require a result
+     * value. We do not have a node type that can only return a {@code boolean} value, so
+     * {@link #evaluateCondition executing the condition} can lead to a type error.
+     */
     @Child private SLExpressionNode conditionNode;
+
+    /** Statement (or {@SLBlockNode block}) executed as long as the condition is true. */
     @Child private SLStatementNode bodyNode;
 
+    /**
+     * Profiling information, collected by the interpreter, capturing whether a {@code continue}
+     * statement was used in this loop. This allows the compiler to generate better code for loops
+     * without a {@code continue}.
+     */
     private final BranchProfile continueTaken = new BranchProfile();
     private final BranchProfile breakTaken = new BranchProfile();
 
     public SLWhileNode(SLExpressionNode conditionNode, SLStatementNode bodyNode) {
+        /*
+         * It is a Truffle requirement to call adoptChild(), which performs all the necessary steps
+         * to add the new child to the node tree.
+         */
         this.conditionNode = adoptChild(conditionNode);
         this.bodyNode = adoptChild(bodyNode);
     }
@@ -49,28 +65,31 @@
         try {
             while (evaluateCondition(frame)) {
                 try {
+                    /* Execute the loop body. */
                     bodyNode.executeVoid(frame);
+
                     if (CompilerDirectives.inInterpreter()) {
+                        /* In the interpreter, profile the the number of loop iteration. */
                         count++;
                     }
                 } catch (SLContinueException ex) {
+                    /* In the interpreter, record profiling information that the loop uses continue. */
                     continueTaken.enter();
                     /* Fall through to next loop iteration. */
                 }
             }
         } catch (SLBreakException ex) {
+            /* In the interpreter, record profiling information that the loop uses break. */
             breakTaken.enter();
             /* Done executing this loop, exit method to execute statement following the loop. */
+
         } finally {
             if (CompilerDirectives.inInterpreter()) {
                 /*
-                 * Report the loop count to the Truffle system. It is used for compilation and
-                 * inlining decisions.
+                 * In the interpreter, report the loop count to the Truffle system. It is used for
+                 * compilation and inlining decisions.
                  */
-                RootNode root = getRootNode();
-                if (root.getCallTarget() instanceof LoopCountReceiver) {
-                    ((LoopCountReceiver) root.getCallTarget()).reportLoopCount(count);
-                }
+                getRootNode().reportLoopCount(count);
             }
         }
     }
@@ -78,8 +97,8 @@
     private boolean evaluateCondition(VirtualFrame frame) {
         try {
             /*
-             * The condition must evaluate to a boolean value, so we call boolean-specialized
-             * method.
+             * The condition must evaluate to a boolean value, so we call the boolean-specialized
+             * execute method.
              */
             return conditionNode.executeBoolean(frame);
         } catch (UnexpectedResultException ex) {
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLAddNode.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLAddNode.java	Thu Jan 30 17:53:27 2014 -0800
@@ -29,29 +29,81 @@
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.sl.nodes.*;
 
+/**
+ * SL node that performs the "+" operation, which performs addition on arbitrary precision numbers,
+ * as well as String concatenation if one of the operands is a String.
+ * <p>
+ * Type specialization on the input values is essential for the performance. This is achieved via
+ * node rewriting: specialized subclasses handle just a single type, so that the generic node that
+ * can handle all types is used only in cases where different types were encountered. The subclasses
+ * are automatically generated by the Truffle DSL. In addition, a {@link SLAddNodeFactory factory
+ * class} is generated that provides, e.g., {@link SLAddNodeFactory#create node creation}.
+ */
 @NodeInfo(shortName = "+")
 public abstract class SLAddNode extends SLBinaryNode {
 
+    /**
+     * Specialization for primitive {@code long} values. This is the fast path of the
+     * arbitrary-precision arithmetic. We need to check for overflows of the addition, and switch to
+     * the {@link #add(BigInteger, BigInteger) slow path}. Therefore, we use an
+     * {@link ExactMath#addExact(long, long) addition method that throws an exception on overflow}.
+     * The {@code rewriteOn} attribute on the {@link Specialization} annotation automatically
+     * triggers the node rewriting on the exception.
+     * <p>
+     * In compiled code, {@link ExactMath#addExact(long, long) addExact} is compiled to efficient
+     * machine code that uses the processor's overflow flag. Therefore, this method is compiled to
+     * only two machine code instructions on the fast path.
+     * <p>
+     * This specialization is automatically selected by the Truffle DSL if both the left and right
+     * operand are {@code long} values.
+     */
     @Specialization(rewriteOn = ArithmeticException.class)
     protected long add(long left, long right) {
         return ExactMath.addExact(left, right);
     }
 
+    /**
+     * This is the slow path of the arbitrary-precision arithmetic. The {@link BigInteger} type of
+     * Java is doing everything we need.
+     * <p>
+     * This specialization is automatically selected by the Truffle DSL if both the left and right
+     * operand are {@link BigInteger} values. Because the type system defines an
+     * {@link ImplicitCast implicit conversion} from {@code long} to {@link BigInteger} in
+     * {@link SLTypes#castBigInteger(long)}, this specialization is also taken if the left or the
+     * right operand is a {@code long} value.
+     */
     @Specialization
     protected BigInteger add(BigInteger left, BigInteger right) {
         return left.add(right);
     }
 
+    /**
+     * Specialization for String concatenation. This specialization is not strictly necessary, since
+     * {@link #add(Object, Object)} covers this case too. But it leads to slightly better code,
+     * since we do not require the {@link Object#toString()} calls in this specialization.
+     */
     @Specialization
     protected String add(String left, String right) {
         return left + right;
     }
 
+    /**
+     * Specialization for String concatenation. The SL specification says that String concatenation
+     * works if either the left or the right operand is a String. The non-string operand is
+     * converted then automatically converted to a String.
+     * <p>
+     * To implement these semantics, we tell the Truffle DSL to use a custom guard. The guard
+     * function is defined in {@link #isString this class}, but could also be in any superclass.
+     */
     @Specialization(guards = "isString")
     protected String add(Object left, Object right) {
         return left.toString() + right.toString();
     }
 
+    /**
+     * Guard for String concatenation: returns true if either the left or the right operand is a
+     * {@link String}.
+     */
     protected boolean isString(Object a, Object b) {
         return a instanceof String || b instanceof String;
     }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLBigIntegerLiteralNode.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLBigIntegerLiteralNode.java	Thu Jan 30 17:53:27 2014 -0800
@@ -28,6 +28,10 @@
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.sl.nodes.*;
 
+/**
+ * Constant literal for a arbitrary-precision number that exceeds the range of
+ * {@link SLLongLiteralNode}.
+ */
 @NodeInfo(shortName = "const")
 public final class SLBigIntegerLiteralNode extends SLExpressionNode {
 
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLDivNode.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLDivNode.java	Thu Jan 30 17:53:27 2014 -0800
@@ -28,6 +28,9 @@
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.sl.nodes.*;
 
+/**
+ * This class is similar to the extensively documented {@link SLAddNode}.
+ */
 @NodeInfo(shortName = "/")
 public abstract class SLDivNode extends SLBinaryNode {
 
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLEqualNode.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLEqualNode.java	Thu Jan 30 17:53:27 2014 -0800
@@ -29,6 +29,16 @@
 import com.oracle.truffle.sl.nodes.*;
 import com.oracle.truffle.sl.runtime.*;
 
+/**
+ * The {@code ==} operator of SL is defined on all types. Therefore, we need a (@link
+ * {@link #equal(Object, Object) generic implementation} that can handle all possible types. But
+ * since {@code ==} can only return {@code true} when the type of the left and right operand are the
+ * same, the specializations already cover all possible cases that can return {@code true} and the
+ * generic case is trivial.
+ * <p>
+ * Note that we do not need the analogous {@code =!} operator, because we can just
+ * {@link SLLogicalNotNode negate} the {@code ==} operator.
+ */
 @NodeInfo(shortName = "==")
 public abstract class SLEqualNode extends SLBinaryNode {
 
@@ -67,6 +77,11 @@
         return left == right;
     }
 
+    /**
+     * The {@link Generic} annotation informs that Truffle DSL that this method should be executed
+     * when no {@link Specialization specialized method} matches. The operand types must be
+     * {@link Object}.
+     */
     @Generic
     protected boolean equal(Object left, Object right) {
         /*
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLFunctionLiteralNode.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLFunctionLiteralNode.java	Thu Jan 30 17:53:27 2014 -0800
@@ -22,11 +22,18 @@
  */
 package com.oracle.truffle.sl.nodes.expression;
 
+import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.sl.nodes.*;
 import com.oracle.truffle.sl.runtime.*;
 
+/**
+ * Constant literal for a {@link SLFunction function} value, created when a function name occurs as
+ * a literal in SL source code. Note that function redefinition can change the {@link CallTarget
+ * call target} that is executed when calling the function, but the {@link SLFunction} for a name
+ * never changes. This is guaranteed by the {@link SLFunctionRegistry}.
+ */
 @NodeInfo(shortName = "func")
 public final class SLFunctionLiteralNode extends SLExpressionNode {
 
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLessOrEqualNode.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLessOrEqualNode.java	Thu Jan 30 17:53:27 2014 -0800
@@ -28,6 +28,9 @@
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.sl.nodes.*;
 
+/**
+ * This class is similar to the {@link SLLessThanNode}.
+ */
 @NodeInfo(shortName = "<=")
 public abstract class SLLessOrEqualNode extends SLBinaryNode {
 
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLessThanNode.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLessThanNode.java	Thu Jan 30 17:53:27 2014 -0800
@@ -28,6 +28,10 @@
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.sl.nodes.*;
 
+/**
+ * This class is similar to the extensively documented {@link SLAddNode}. The only difference: the
+ * specialized methods return {@code boolean} instead of the input types.
+ */
 @NodeInfo(shortName = "<")
 public abstract class SLLessThanNode extends SLBinaryNode {
 
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLogicalAndNode.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLogicalAndNode.java	Thu Jan 30 17:53:27 2014 -0800
@@ -26,15 +26,32 @@
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.sl.nodes.*;
 
+/**
+ * This class declares specializations similar to the extensively documented {@link SLAddNode}. It
+ * uses one additional feature of the Truffle DSL: {@link ShortCircuit}.
+ * <p>
+ * Logical operations in SL use short circuit evaluation: if the evaluation of the left operand
+ * already decides the result of the operation, the right operand must not be executed. This is
+ * expressed in the Truffle DSL via a method annotated with {@link ShortCircuit}, which returns
+ * whether a child needs to be executed based on the result of already executed children.
+ */
 @NodeInfo(shortName = "&&")
 @SuppressWarnings("unused")
 public abstract class SLLogicalAndNode extends SLBinaryNode {
 
+    /**
+     * This method is called after the left child was evaluated, but before the right child is
+     * evaluated. The right child is only evaluated when the return value is {code true}.
+     */
     @ShortCircuit("rightNode")
     protected boolean needsRightNode(boolean left) {
         return left;
     }
 
+    /**
+     * Similar to {@link #needsRightNode(boolean)}, but for generic cases where the type of the left
+     * child is not known.
+     */
     @ShortCircuit("rightNode")
     protected boolean needsRightNode(Object left) {
         return left instanceof Boolean && needsRightNode(((Boolean) left).booleanValue());
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLogicalNotNode.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLogicalNotNode.java	Thu Jan 30 17:53:27 2014 -0800
@@ -26,6 +26,10 @@
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.sl.nodes.*;
 
+/**
+ * Example of a simple unary node that uses type specialization. See {@link SLAddNode} for
+ * information on specializations.
+ */
 @NodeChild("valueNode")
 @NodeInfo(shortName = "!")
 public abstract class SLLogicalNotNode extends SLExpressionNode {
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLogicalOrNode.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLogicalOrNode.java	Thu Jan 30 17:53:27 2014 -0800
@@ -26,6 +26,9 @@
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.sl.nodes.*;
 
+/**
+ * This class is similar to the {@link SLLogicalAndNode}.
+ */
 @NodeInfo(shortName = "||")
 @SuppressWarnings("unused")
 public abstract class SLLogicalOrNode extends SLBinaryNode {
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLongLiteralNode.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLLongLiteralNode.java	Thu Jan 30 17:53:27 2014 -0800
@@ -26,6 +26,11 @@
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.sl.nodes.*;
 
+/**
+ * Constant literal for a primitive {@code long} value. The unboxed value can be returned when the
+ * parent expects a long value and calls {@link SLLongLiteralNode#executeLong}. In the generic case,
+ * the primitive value is automatically boxed by Java.
+ */
 @NodeInfo(shortName = "const")
 public final class SLLongLiteralNode extends SLExpressionNode {
 
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLMulNode.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLMulNode.java	Thu Jan 30 17:53:27 2014 -0800
@@ -29,6 +29,9 @@
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.sl.nodes.*;
 
+/**
+ * This class is similar to the extensively documented {@link SLAddNode}.
+ */
 @NodeInfo(shortName = "*")
 public abstract class SLMulNode extends SLBinaryNode {
 
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLStringLiteralNode.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLStringLiteralNode.java	Thu Jan 30 17:53:27 2014 -0800
@@ -26,6 +26,9 @@
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.sl.nodes.*;
 
+/**
+ * Constant literal for a String value.
+ */
 @NodeInfo(shortName = "const")
 public final class SLStringLiteralNode extends SLExpressionNode {
 
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLSubNode.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLSubNode.java	Thu Jan 30 17:53:27 2014 -0800
@@ -29,6 +29,9 @@
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.sl.nodes.*;
 
+/**
+ * This class is similar to the extensively documented {@link SLAddNode}.
+ */
 @NodeInfo(shortName = "-")
 public abstract class SLSubNode extends SLBinaryNode {
 
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLReadArgumentNode.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLReadArgumentNode.java	Thu Jan 30 17:53:27 2014 -0800
@@ -22,15 +22,31 @@
  */
 package com.oracle.truffle.sl.nodes.local;
 
+import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.utilities.*;
 import com.oracle.truffle.sl.nodes.*;
+import com.oracle.truffle.sl.parser.*;
 import com.oracle.truffle.sl.runtime.*;
 
+/**
+ * Reads a function argument. Arguments are passed in as a {@link SLArguments} object, which
+ * encapsulates an {@link SLArguments#getFromFrame Object[] array}. Language-defined subclasses of
+ * {@link Arguments} are the standard Truffle way to pass values between function.
+ * <p>
+ * Arguments are not type-specialized. To ensure that repeated accesses within a method are
+ * specialized and can, e.g., accessed without unboxing, all arguments are loaded into local
+ * variables {@link SLNodeFactory#addFormalParameter in the method prologue}.
+ */
 public class SLReadArgumentNode extends SLExpressionNode {
 
+    /** The argument number, i.e., the index into the array of arguments. */
     private final int index;
 
+    /**
+     * Profiling information, collected by the interpreter, capturing whether the function was
+     * called with fewer actual arguments than formal arguments.
+     */
     private final BranchProfile outOfBoundsTaken = new BranchProfile();
 
     public SLReadArgumentNode(int index) {
@@ -43,7 +59,9 @@
         if (index < args.length) {
             return args[index];
         } else {
+            /* In the interpreter, record profiling information that the branch was used. */
             outOfBoundsTaken.enter();
+            /* Use the default null value. */
             return SLNull.SINGLETON;
         }
     }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLReadLocalVariableNode.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLReadLocalVariableNode.java	Thu Jan 30 17:53:27 2014 -0800
@@ -26,10 +26,21 @@
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.sl.nodes.*;
 
+/**
+ * Node to read a local variable from a function's {@link VirtualFrame frame}. The Truffle frame API
+ * allows to store primitive values of all Java primitive types, and Object values. This means that
+ * all SL types that are objects are handled by the {@link #readObject} method. When a local
+ * variable changes its type, the frame access method throws an {@link FrameSlotTypeException},
+ * which causes not rewriting. The rewriting code is generated by the Truffle DSL.
+ */
 @PolymorphicLimit(1)
 @NodeField(name = "slot", type = FrameSlot.class)
 public abstract class SLReadLocalVariableNode extends SLExpressionNode {
 
+    /**
+     * Returns the descriptor of the accessed local variable. The implementation of this method is
+     * created by the Truffle DSL based on the {@link NodeField} annotation on the class.
+     */
     protected abstract FrameSlot getSlot();
 
     @Specialization(rewriteOn = {FrameSlotTypeException.class})
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLWriteLocalVariableNode.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/local/SLWriteLocalVariableNode.java	Thu Jan 30 17:53:27 2014 -0800
@@ -27,12 +27,25 @@
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.sl.nodes.*;
 
+/**
+ * Node to write a local variable to a function's {@link VirtualFrame frame}. The Truffle frame API
+ * allows to store primitive values of all Java primitive types, and Object values.
+ */
 @NodeChild(value = "valueNode")
 @NodeField(name = "slot", type = FrameSlot.class)
 public abstract class SLWriteLocalVariableNode extends SLExpressionNode {
 
+    /**
+     * Returns the descriptor of the accessed local variable. The implementation of this method is
+     * created by the Truffle DSL based on the {@link NodeField} annotation on the class.
+     */
     protected abstract FrameSlot getSlot();
 
+    /**
+     * Specialized method to write a primitive {@code long} value}. This is only possible if the
+     * local variable also has currently the type {@code long}, therefore a Truffle DSL
+     * {@link #isLongKind() custom guard} is specified.
+     */
     @Specialization(guards = "isLongKind")
     protected long write(VirtualFrame frame, long value) {
         frame.setLong(getSlot(), value);
@@ -45,9 +58,24 @@
         return value;
     }
 
+    /**
+     * Generic write method that works for all possible types.
+     * <p>
+     * Why is this method annotated with {@link Specialization} and not {@link Generic}? For a
+     * {@link Generic} method, the Truffle DSL generated code would try all other specializations
+     * first before calling this method. We know that all these specializations would fail their
+     * guards, so there is no point in calling them. Since this method takes a value of type
+     * {@link Object}, it is guaranteed to never fail, i.e., once we are in this specialization the
+     * node will never be re-specialized.
+     */
     @Specialization
     protected Object write(VirtualFrame frame, Object value) {
         if (getSlot().getKind() != FrameSlotKind.Object) {
+            /*
+             * The local variable has still a primitive type, we need to change it to Object. Since
+             * the variable type is important when the compiler optimizes a method, we also discard
+             * compiled code.
+             */
             CompilerDirectives.transferToInterpreterAndInvalidate();
             getSlot().setKind(FrameSlotKind.Object);
         }
@@ -55,6 +83,9 @@
         return value;
     }
 
+    /**
+     * Guard function that the local variable has the type {@code long}.
+     */
     protected boolean isLongKind() {
         return isKind(FrameSlotKind.Long);
     }
@@ -65,12 +96,22 @@
 
     private boolean isKind(FrameSlotKind kind) {
         if (getSlot().getKind() == kind) {
+            /* Success: the frame slot has the expected kind. */
             return true;
         } else if (getSlot().getKind() == FrameSlotKind.Illegal) {
+            /*
+             * This is the first write to this local variable. We can set the type to the one we
+             * expect. Since the variable type is important when the compiler optimizes a method, we
+             * also discard compiled code.
+             */
             CompilerDirectives.transferToInterpreterAndInvalidate();
             getSlot().setKind(kind);
             return true;
         } else {
+            /*
+             * Failure: the frame slot has the wrong kind, the Truffle DSL generated code will
+             * choose a different specialization.
+             */
             return false;
         }
     }
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java	Thu Jan 30 17:53:27 2014 -0800
@@ -145,17 +145,17 @@
 			}
 		}
 		Expect(7);
-		SLStatementNode body = Block();
+		SLStatementNode body = Block(false);
 		factory.finishFunction(body); 
 	}
 
-	SLStatementNode  Block() {
+	SLStatementNode  Block(boolean inLoop) {
 		SLStatementNode  result;
 		factory.startBlock();
 		List<SLStatementNode> body = new ArrayList<>(); 
 		Expect(8);
 		while (StartOf(1)) {
-			SLStatementNode s = Statement();
+			SLStatementNode s = Statement(inLoop);
 			body.add(s); 
 		}
 		Expect(9);
@@ -163,7 +163,7 @@
 		return result;
 	}
 
-	SLStatementNode  Statement() {
+	SLStatementNode  Statement(boolean inLoop) {
 		SLStatementNode  result;
 		result = null; 
 		switch (la.kind) {
@@ -173,18 +173,18 @@
 		}
 		case 10: {
 			Get();
-			result = factory.createBreak(t); 
+			if (inLoop) { result = factory.createBreak(t); } else { SemErr("break used outside of loop"); } 
 			Expect(11);
 			break;
 		}
 		case 12: {
 			Get();
-			result = factory.createContinue(t); 
+			if (inLoop) { result = factory.createContinue(t); } else { SemErr("continue used outside of loop"); } 
 			Expect(11);
 			break;
 		}
 		case 14: {
-			result = IfStatement();
+			result = IfStatement(inLoop);
 			break;
 		}
 		case 16: {
@@ -208,23 +208,23 @@
 		Token whileToken = t; 
 		SLExpressionNode condition = Expression();
 		Expect(7);
-		SLStatementNode body = Block();
+		SLStatementNode body = Block(true);
 		result = factory.createWhile(whileToken, condition, body); 
 		return result;
 	}
 
-	SLStatementNode  IfStatement() {
+	SLStatementNode  IfStatement(boolean inLoop) {
 		SLStatementNode  result;
 		Expect(14);
 		Expect(5);
 		Token ifToken = t; 
 		SLExpressionNode condition = Expression();
 		Expect(7);
-		SLStatementNode thenPart = Block();
+		SLStatementNode thenPart = Block(inLoop);
 		SLStatementNode elsePart = null; 
 		if (la.kind == 15) {
 			Get();
-			elsePart = Block();
+			elsePart = Block(inLoop);
 		}
 		result = factory.createIf(ifToken, condition, thenPart, elsePart); 
 		return result;
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java	Thu Jan 30 17:53:27 2014 -0800
@@ -36,8 +36,17 @@
 import com.oracle.truffle.sl.nodes.local.*;
 import com.oracle.truffle.sl.runtime.*;
 
+/**
+ * Helper class used by the SL {@link Parser} to create nodes. The code is factored out of the
+ * automatically generated parser to keep the attributed grammar of SL small.
+ */
 public class SLNodeFactory {
 
+    /**
+     * Local variable names that are visible in the current block. Variables are not visible outside
+     * of their defining block, to prevent the usage of undefined variables. Because of that, we can
+     * decide during parsing if a name references a local variable or is a function name.
+     */
     static class LexicalScope {
         protected final LexicalScope outer;
         protected final Map<String, FrameSlot> locals;
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg	Thu Jan 30 17:53:27 2014 -0800
@@ -70,34 +70,34 @@
     }    
 ]
 ")"
-Block<out SLStatementNode body>                 (. factory.finishFunction(body); .)
+Block<out SLStatementNode body, false>          (. factory.finishFunction(body); .)
 .
 
 
 
-Block<out SLStatementNode result>
+Block<out SLStatementNode result, boolean inLoop>
 =                                               (. factory.startBlock();
                                                    List<SLStatementNode> body = new ArrayList<>(); .)
 "{" 
 {
-    Statement<out SLStatementNode s>            (. body.add(s); .)
+    Statement<out SLStatementNode s, inLoop>    (. body.add(s); .)
 }
 "}"                                             (. result = factory.finishBlock(body); .)
 .
 
 
-Statement<out SLStatementNode result>
+Statement<out SLStatementNode result, boolean inLoop>
 =                                               (. result = null; .)
 (
     WhileStatement<out result>
 |
-    "break"                                     (. result = factory.createBreak(t); .)
+    "break"                                     (. if (inLoop) { result = factory.createBreak(t); } else { SemErr("break used outside of loop"); } .)
     ";"
 |
-    "continue"                                  (. result = factory.createContinue(t); .)
+    "continue"                                  (. if (inLoop) { result = factory.createContinue(t); } else { SemErr("continue used outside of loop"); } .)
     ";"
 |   
-    IfStatement<out result>
+    IfStatement<out result, inLoop>
 |
     ReturnStatement<out result>
 |
@@ -112,20 +112,20 @@
 "("                                             (. Token whileToken = t; .)
 Expression<out SLExpressionNode condition>
 ")" 
-Block<out SLStatementNode body>                 (. result = factory.createWhile(whileToken, condition, body); .)
+Block<out SLStatementNode body, true>           (. result = factory.createWhile(whileToken, condition, body); .)
 .
 
 
-IfStatement<out SLStatementNode result>
+IfStatement<out SLStatementNode result, boolean inLoop>
 =
 "if" 
 "("                                             (. Token ifToken = t; .)
 Expression<out SLExpressionNode condition> 
 ")"
-Block<out SLStatementNode thenPart>             (. SLStatementNode elsePart = null; .)                             
+Block<out SLStatementNode thenPart, inLoop>     (. SLStatementNode elsePart = null; .)                             
 [
     "else" 
-    Block<out elsePart>
+    Block<out elsePart, inLoop>
 ]                                               (. result = factory.createIf(ifToken, condition, thenPart, elsePart); .)
 .
 
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java	Thu Jan 30 17:53:27 2014 -0800
@@ -89,7 +89,7 @@
     }
 
     /**
-     * Adds all builitin functions to the {@link SLFunctionRegistry}. This method lists all
+     * Adds all builtin functions to the {@link SLFunctionRegistry}. This method lists all
      * {@link SLBuiltinNode builtin implementation classes}.
      */
     private void installBuiltins() {
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLFunction.java	Thu Jan 30 17:52:24 2014 -0800
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLFunction.java	Thu Jan 30 17:53:27 2014 -0800
@@ -27,12 +27,12 @@
 
 /**
  * Represents a SL function. On the Truffle level, a callable element is represented by a
- * {@link RootCallTarget call target}. This class encapsulates a call target, and adds versioning
+ * {@link RootCallTarget call target}. This class encapsulates a call target, and adds version
  * support: functions in SL can be redefined, i.e. changed at run time. When a function is
  * redefined, the call target managed by this function object is changed (and {@link #callTarget} is
  * therefore not a final field).
  * <p>
- * Function redefinition is expected to be rare, therefore optimzied call nodes want to speculate
+ * Function redefinition is expected to be rare, therefore optimized call nodes want to speculate
  * that the call target is stable. This is possible with the help of a Truffle {@link Assumption}: a
  * call node can keep the call target returned by {@link #getCallTarget()} cached until the
  * assumption returned by {@link #getCallTargetStable()} is valid.