changeset 18411:dc2e000bed40

SL: add basic support for creating objects and accessing properties
author Andreas Woess <andreas.woess@jku.at>
date Tue, 18 Nov 2014 23:02:58 +0100
parents f444ef4684ec
children 997bc9764a9a
files graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestRunner.java graal/com.oracle.truffle.sl.test/tests/Object.output graal/com.oracle.truffle.sl.test/tests/Object.sl graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLNewObjectBuiltin.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLReadPropertyNode.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLWritePropertyNode.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/Scanner.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
diffstat 11 files changed, 375 insertions(+), 83 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestRunner.java	Tue Oct 21 15:11:32 2014 +0200
+++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/instrument/SLInstrumentTestRunner.java	Tue Nov 18 23:02:58 2014 +0100
@@ -213,7 +213,9 @@
 
                 for (SLFunction function : functionList) {
                     RootCallTarget rootCallTarget = function.getCallTarget();
-                    rootCallTarget.getRootNode().accept(new SLInstrumenter());
+                    if (rootCallTarget != null) {
+                        rootCallTarget.getRootNode().accept(new SLInstrumenter());
+                    }
                 }
 
                 // We iterate over all tags the SLInsturmenter tagged as assignments and attach our
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl.test/tests/Object.output	Tue Nov 18 23:02:58 2014 +0100
@@ -0,0 +1,6 @@
+null
+42
+42
+why
+zzz
+zzz
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl.test/tests/Object.sl	Tue Nov 18 23:02:58 2014 +0100
@@ -0,0 +1,24 @@
+function main() {  
+  obj1 = new();
+  println(obj1.x);
+  obj1.x = 42;
+  println(obj1.x);
+  
+  obj2 = new();
+  obj2.o = obj1;
+  println(obj2.o.x);
+  obj2.o.y = "why";
+  println(obj1.y);
+  
+  println(mkobj().z);
+  
+  obj3 = new();
+  obj3.fn = mkobj;
+  println(obj3.fn().z);
+}
+
+function mkobj() {
+  newobj = new();
+  newobj.z = "zzz";
+  return newobj;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/builtins/SLNewObjectBuiltin.java	Tue Nov 18 23:02:58 2014 +0100
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2014, 2014, 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 java.util.*;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.runtime.*;
+
+/**
+ * Builtin function to write a value to the {@link SLContext#getOutput() standard output}. The
+ * different specialization leverage the typed {@code println} methods available in Java, i.e.,
+ * primitive values are printed without converting them to a {@link String} first.
+ * <p>
+ * Printing involves a lot of Java code, so we need to tell the optimizing system that it should not
+ * unconditionally inline everything reachable from the println() method. This is done via the
+ * {@link TruffleBoundary} annotations.
+ */
+@NodeInfo(shortName = "new")
+public abstract class SLNewObjectBuiltin extends SLBuiltinNode {
+
+    public SLNewObjectBuiltin() {
+        super(new NullSourceSection("SL builtin", "new"));
+    }
+
+    @Specialization
+    public Object newObject() {
+        return new HashMap<>();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLReadPropertyNode.java	Tue Nov 18 23:02:58 2014 +0100
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2013, 2014, 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.access;
+
+import java.util.*;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.*;
+import com.oracle.truffle.sl.nodes.*;
+
+/**
+ * The node for accessing a property of an object. When executed, this node first evaluates the
+ * object expression on the left side of the dot operator and then reads the named property.
+ */
+@NodeInfo(shortName = ".")
+public final class SLReadPropertyNode extends SLExpressionNode {
+
+    public static SLReadPropertyNode create(SourceSection src, SLExpressionNode receiverNode, String propertyName) {
+        return new SLReadPropertyNode(src, receiverNode, propertyName);
+    }
+
+    @Child protected SLExpressionNode receiverNode;
+    protected final String propertyName;
+
+    private SLReadPropertyNode(SourceSection src, SLExpressionNode receiverNode, String propertyName) {
+        super(src);
+        this.receiverNode = receiverNode;
+        this.propertyName = propertyName;
+    }
+
+    @Override
+    public Object executeGeneric(VirtualFrame frame) {
+        Object object = receiverNode.executeGeneric(frame);
+        if (object instanceof Map) {
+            return ((Map<?, ?>) object).get(propertyName);
+        } else {
+            throw new SLException("unexpected receiver type");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/access/SLWritePropertyNode.java	Tue Nov 18 23:02:58 2014 +0100
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2013, 2014, 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.access;
+
+import java.util.*;
+
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.sl.*;
+import com.oracle.truffle.sl.nodes.*;
+
+/**
+ * The node for setting a property of an object. When executed, this node first evaluates the value
+ * expression on the right hand side of the equals operator, followed by the object expression on
+ * the left side of the dot operator, and then sets the named property of this object to the new
+ * value if the property already exists or adds a new property. Finally, it returns the new value.
+ */
+@NodeInfo(shortName = ".=")
+public final class SLWritePropertyNode extends SLExpressionNode {
+
+    public static SLWritePropertyNode create(SourceSection src, SLExpressionNode receiverNode, String propertyName, SLExpressionNode valueNode) {
+        return new SLWritePropertyNode(src, receiverNode, propertyName, valueNode);
+    }
+
+    @Child protected SLExpressionNode receiverNode;
+    protected final String propertyName;
+    @Child protected SLExpressionNode valueNode;
+
+    private SLWritePropertyNode(SourceSection src, SLExpressionNode receiverNode, String propertyName, SLExpressionNode valueNode) {
+        super(src);
+        this.receiverNode = receiverNode;
+        this.propertyName = propertyName;
+        this.valueNode = valueNode;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public Object executeGeneric(VirtualFrame frame) {
+        Object value = valueNode.executeGeneric(frame);
+        Object object = receiverNode.executeGeneric(frame);
+        if (object instanceof Map) {
+            ((Map<Object, Object>) object).put(propertyName, value);
+        } else {
+            throw new SLException("unexpected receiver type");
+        }
+        return value;
+    }
+}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java	Tue Oct 21 15:11:32 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java	Tue Nov 18 23:02:58 2014 +0100
@@ -39,7 +39,7 @@
 	public static final int _identifier = 1;
 	public static final int _stringLiteral = 2;
 	public static final int _numericLiteral = 3;
-	public static final int maxT = 30;
+	public static final int maxT = 31;
 
     static final boolean T = true;
     static final boolean x = false;
@@ -200,7 +200,7 @@
 			Expect(11);
 			break;
 		}
-		default: SynErr(31); break;
+		default: SynErr(32); break;
 		}
 		return result;
 	}
@@ -345,30 +345,10 @@
 		result = null;
 		if (la.kind == 1) {
 			Get();
-			Token nameToken = t;
-			if (la.kind == 5) {
-				Get();
-				List<SLExpressionNode> parameters = new ArrayList<>();
-				SLExpressionNode parameter;
-				if (StartOf(2)) {
-					parameter = Expression();
-					parameters.add(parameter);
-					while (la.kind == 6) {
-						Get();
-						parameter = Expression();
-						parameters.add(parameter);
-					}
-				}
-				Expect(7);
-				Token finalToken = t;
-				result = factory.createCall(nameToken, parameters, finalToken);
-			} else if (la.kind == 29) {
-				Get();
-				SLExpressionNode value = Expression();
-				result = factory.createAssignment(nameToken, value);
-			} else if (StartOf(4)) {
-				result = factory.createRead(nameToken);
-			} else SynErr(32);
+			result = factory.createRead(t);
+			if (la.kind == 5 || la.kind == 29 || la.kind == 30) {
+				result = MemberExpression(result, null, t);
+			}
 		} else if (la.kind == 2) {
 			Get();
 			result = factory.createStringLiteral(t);
@@ -387,6 +367,48 @@
 		return result;
 	}
 
+	SLExpressionNode  MemberExpression(SLExpressionNode receiver, SLExpressionNode assignmentReceiver, Token assignmentName) {
+		SLExpressionNode  result;
+		result = null;
+		Token nestedAssignmentName = null;
+		if (la.kind == 5) {
+			Get();
+			List<SLExpressionNode> parameters = new ArrayList<>();
+			SLExpressionNode parameter;
+			if (StartOf(2)) {
+				parameter = Expression();
+				parameters.add(parameter);
+				while (la.kind == 6) {
+					Get();
+					parameter = Expression();
+					parameters.add(parameter);
+				}
+			}
+			Expect(7);
+			Token finalToken = t;
+			result = factory.createCall(receiver, parameters, finalToken);
+		} else if (la.kind == 29) {
+			Get();
+			SLExpressionNode value = Expression();
+			if (assignmentName == null) {
+			   SemErr("invalid assignment target");
+			} else if (assignmentReceiver == null) {
+			   result = factory.createAssignment(assignmentName, value);
+			} else {
+			   result = factory.createWriteProperty(assignmentReceiver, assignmentName, value);
+			}
+		} else if (la.kind == 30) {
+			Get();
+			Expect(1);
+			result = factory.createReadProperty(receiver, t);
+			nestedAssignmentName = t;
+		} else SynErr(34);
+		if (la.kind == 5 || la.kind == 29 || la.kind == 30) {
+			result = MemberExpression(result, receiver, nestedAssignmentName);
+		}
+		return result;
+	}
+
 
 
     public void Parse() {
@@ -399,11 +421,10 @@
     }
 
     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},
-		{x,T,T,T, x,T,x,x, x,x,T,x, T,T,T,x, T,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,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,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,x, x,x,T,T, x,x,x,T, x,x,x,x, x,T,T,T, T,T,T,T, T,T,T,T, T,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, x},
+		{x,T,T,T, x,T,x,x, x,x,T,x, T,T,T,x, T,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,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,x,x,x, x,x,x,x, x,x,x,T, T,T,T,T, T,x,x,x, x,x,x,x, x}
 
     };
 
@@ -476,10 +497,11 @@
 			case 27: s = "\"*\" expected"; break;
 			case 28: s = "\"/\" expected"; break;
 			case 29: s = "\"=\" expected"; break;
-			case 30: s = "??? expected"; break;
-			case 31: s = "invalid Statement"; break;
-			case 32: s = "invalid Factor"; break;
+			case 30: s = "\".\" expected"; break;
+			case 31: s = "??? expected"; break;
+			case 32: s = "invalid Statement"; break;
 			case 33: s = "invalid Factor"; break;
+			case 34: s = "invalid MemberExpression"; break;
             default:
                 s = "error " + n;
                 break;
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java	Tue Oct 21 15:11:32 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java	Tue Nov 18 23:02:58 2014 +0100
@@ -29,6 +29,7 @@
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.sl.nodes.*;
+import com.oracle.truffle.sl.nodes.access.*;
 import com.oracle.truffle.sl.nodes.call.*;
 import com.oracle.truffle.sl.nodes.controlflow.*;
 import com.oracle.truffle.sl.nodes.expression.*;
@@ -265,16 +266,15 @@
     /**
      * Returns an {@link SLInvokeNode} for the given parameters.
      *
-     * @param nameToken The name of the function being called
+     * @param functionNode The function being called
      * @param parameterNodes The parameters of the function call
      * @param finalToken A token used to determine the end of the sourceSelection for this call
      * @return An SLInvokeNode for the given parameters.
      */
-    public SLExpressionNode createCall(Token nameToken, List<SLExpressionNode> parameterNodes, Token finalToken) {
-        final int startPos = nameToken.charPos;
+    public SLExpressionNode createCall(SLExpressionNode functionNode, List<SLExpressionNode> parameterNodes, Token finalToken) {
+        final int startPos = functionNode.getSourceSection().getCharIndex();
         final int endPos = finalToken.charPos + finalToken.val.length();
-        final SourceSection src = source.createSection(nameToken.val, startPos, endPos - startPos);
-        SLExpressionNode functionNode = createRead(nameToken);
+        final SourceSection src = source.createSection(functionNode.getSourceSection().getIdentifier(), startPos, endPos - startPos);
         return SLInvokeNode.create(src, functionNode, parameterNodes.toArray(new SLExpressionNode[parameterNodes.size()]));
     }
 
@@ -344,6 +344,35 @@
     }
 
     /**
+     * Returns an {@link SLReadPropertyNode} for the given parameters.
+     *
+     * @param receiverNode The receiver of the property access
+     * @param nameToken The name of the property being accessed
+     * @return An SLExpressionNode for the given parameters.
+     */
+    public SLExpressionNode createReadProperty(SLExpressionNode receiverNode, Token nameToken) {
+        final int startPos = receiverNode.getSourceSection().getCharIndex();
+        final int endPos = nameToken.charPos + nameToken.val.length();
+        final SourceSection src = source.createSection(".", startPos, endPos - startPos);
+        return SLReadPropertyNode.create(src, receiverNode, nameToken.val);
+    }
+
+    /**
+     * Returns an {@link SLWritePropertyNode} for the given parameters.
+     *
+     * @param receiverNode The receiver object of the property assignment
+     * @param nameToken The name of the property being assigned
+     * @param valueNode The value to be assigned
+     * @return An SLExpressionNode for the given parameters.
+     */
+    public SLExpressionNode createWriteProperty(SLExpressionNode receiverNode, Token nameToken, SLExpressionNode valueNode) {
+        final int start = receiverNode.getSourceSection().getCharIndex();
+        final int length = valueNode.getSourceSection().getCharEndIndex() - start;
+        SourceSection src = source.createSection("=", start, length);
+        return SLWritePropertyNode.create(src, receiverNode, nameToken.val, valueNode);
+    }
+
+    /**
      * Creates source description of a single token.
      */
     private SourceSection srcFromToken(Token token) {
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.java	Tue Oct 21 15:11:32 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.java	Tue Nov 18 23:02:58 2014 +0100
@@ -311,8 +311,8 @@
 
     static final char EOL = '\n';
     static final int eofSym = 0;
-	static final int maxT = 30;
-	static final int noSym = 30;
+	static final int maxT = 31;
+	static final int noSym = 31;
 
 
     public Buffer buffer; // scanner buffer
@@ -339,24 +339,25 @@
 		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(124, 12); 
-		start.set(38, 14); 
-		start.set(60, 25); 
-		start.set(62, 26); 
-		start.set(61, 27); 
-		start.set(33, 19); 
-		start.set(43, 21); 
-		start.set(45, 22); 
-		start.set(42, 23); 
-		start.set(47, 24); 
+		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(124, 12);
+		start.set(38, 14);
+		start.set(60, 26);
+		start.set(62, 27);
+		start.set(61, 28);
+		start.set(33, 19);
+		start.set(43, 21);
+		start.set(45, 22);
+		start.set(42, 23);
+		start.set(47, 24);
+		start.set(46, 25);
 		start.set(Buffer.EOF, -1);
 		literals.put("function", new Integer(4));
 		literals.put("break", new Integer(10));
@@ -430,7 +431,7 @@
             tval = newBuf;
         }
         if (ch != Buffer.EOF) {
-			tval[tlen++] = (char)ch; 
+			tval[tlen++] = (char)ch;
 
             NextCh();
         }
@@ -489,7 +490,7 @@
     }
 
     Token NextToken() {
-        while (ch == ' ' || 
+        while (ch == ' ' ||
 			ch >= 9 && ch <= 10 || ch == 13
         ) NextCh();
 		if (ch == '/' && Comment0() ||ch == '/' && Comment1()) return NextToken();
@@ -576,14 +577,16 @@
 				case 24:
 					{t.kind = 28; break loop;}
 				case 25:
+					{t.kind = 30; break loop;}
+				case 26:
 					recEnd = pos; recKind = 19;
 					if (ch == '=') {AddCh(); state = 16; break;}
 					else {t.kind = 19; break loop;}
-				case 26:
+				case 27:
 					recEnd = pos; recKind = 21;
 					if (ch == '=') {AddCh(); state = 17; break;}
 					else {t.kind = 21; break loop;}
-				case 27:
+				case 28:
 					recEnd = pos; recKind = 29;
 					if (ch == '=') {AddCh(); state = 18; break;}
 					else {t.kind = 29; break loop;}
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg	Tue Oct 21 15:11:32 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg	Tue Nov 18 23:02:58 2014 +0100
@@ -202,25 +202,10 @@
 Factor<out SLExpressionNode result>
 =                                               (. result = null; .)
 (
-    identifier                                  (. Token nameToken = t; .)
-    (
-        "("                                     (. List<SLExpressionNode> parameters = new ArrayList<>();
-                                                   SLExpressionNode parameter; .)
-        [
-            Expression<out parameter>           (. parameters.add(parameter); .)
-            {
-                ","
-                Expression<out parameter>       (. parameters.add(parameter); .)
-            }
-        ]
-        ")"                                     (. Token finalToken = t; .)
-                                                (. result = factory.createCall(nameToken, parameters, finalToken); .)
-    |
-        "="
-        Expression<out SLExpressionNode value>  (. result = factory.createAssignment(nameToken, value); .)
-    |
-                                                (. result = factory.createRead(nameToken); .)
-    )
+    identifier                                  (. result = factory.createRead(t); .)
+    [
+        MemberExpression<out result, result, null, t>
+    ]
 |
     stringLiteral                               (. result = factory.createStringLiteral(t); .)
 |
@@ -234,4 +219,40 @@
 .
 
 
+MemberExpression<out SLExpressionNode result, SLExpressionNode receiver, SLExpressionNode assignmentReceiver, Token assignmentName>
+=                                               (. result = null;
+                                                   Token nestedAssignmentName = null; .)
+(
+    "("                                         (. List<SLExpressionNode> parameters = new ArrayList<>();
+                                                   SLExpressionNode parameter; .)
+    [
+        Expression<out parameter>               (. parameters.add(parameter); .)
+        {
+            ","
+            Expression<out parameter>           (. parameters.add(parameter); .)
+        }
+    ]
+    ")"                                         (. Token finalToken = t; .)
+                                                (. result = factory.createCall(receiver, parameters, finalToken); .)
+|
+    "="
+    Expression<out SLExpressionNode value>      (. if (assignmentName == null) {
+                                                       SemErr("invalid assignment target");
+                                                   } else if (assignmentReceiver == null) {
+                                                       result = factory.createAssignment(assignmentName, value);
+                                                   } else {
+                                                       result = factory.createWriteProperty(assignmentReceiver, assignmentName, value);
+                                                   } .)
+|
+    "."
+    identifier
+                                                (. result = factory.createReadProperty(receiver, t); .)
+                                                (. nestedAssignmentName = t; .)
+)
+[
+    MemberExpression<out result, result, receiver, nestedAssignmentName>
+]
+.
+
+
 END SimpleLanguage.
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java	Tue Oct 21 15:11:32 2014 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java	Tue Nov 18 23:02:58 2014 +0100
@@ -111,6 +111,7 @@
         installBuiltin(SLHelloEqualsWorldBuiltinFactory.getInstance());
         installBuiltin(SLAssertTrueBuiltinFactory.getInstance());
         installBuiltin(SLAssertFalseBuiltinFactory.getInstance());
+        installBuiltin(SLNewObjectBuiltinFactory.getInstance());
     }
 
     public void installBuiltin(NodeFactory<? extends SLBuiltinNode> factory) {