Skip to content

Commit

Permalink
Merge branch 'object_literals'
Browse files Browse the repository at this point in the history
  • Loading branch information
qmx committed Dec 29, 2011
2 parents 2ca3044 + 9d6f810 commit a6d1782
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 10 deletions.
2 changes: 1 addition & 1 deletion dynjs/src/main/antlr3/org/dynjs/parser/ES3Walker.g
Expand Up @@ -399,7 +399,7 @@ callExpression returns [Statement value]

memberExpression returns [Statement value]
: ^( BYINDEX leftHandSideExpression expression)
{ $value = executor.defineByIndex($leftHandSideExpression.value, $expression.value); }
{ $value = executor.resolveByIndex($leftHandSideExpression.value, $expression.value); }
| ^( BYFIELD leftHandSideExpression Identifier )
{ $value = executor.resolveByField($leftHandSideExpression.value, $Identifier.text); }
;
Expand Down
21 changes: 12 additions & 9 deletions dynjs/src/main/java/org/dynjs/parser/Executor.java
Expand Up @@ -30,17 +30,20 @@
import org.dynjs.parser.statement.FunctionStatement;
import org.dynjs.parser.statement.IfStatement;
import org.dynjs.parser.statement.LogicalOperationStatement;
import org.dynjs.parser.statement.NamedValueStatement;
import org.dynjs.parser.statement.NotEqualsOperationStatement;
import org.dynjs.parser.statement.NotOperationStatement;
import org.dynjs.parser.statement.NullLiteralStatement;
import org.dynjs.parser.statement.NumberLiteralStatement;
import org.dynjs.parser.statement.ObjectLiteralStatement;
import org.dynjs.parser.statement.OperationAssignmentStatement;
import org.dynjs.parser.statement.PostDecrementStatement;
import org.dynjs.parser.statement.PostIncrementStatement;
import org.dynjs.parser.statement.PreDecrementStatement;
import org.dynjs.parser.statement.PreIncrementStatement;
import org.dynjs.parser.statement.PrintStatement;
import org.dynjs.parser.statement.RelationalOperationStatement;
import org.dynjs.parser.statement.ResolveByIndexStatement;
import org.dynjs.parser.statement.ResolveIdentifierStatement;
import org.dynjs.parser.statement.ReturnStatement;
import org.dynjs.parser.statement.StringLiteralStatement;
Expand Down Expand Up @@ -323,12 +326,12 @@ public Statement executeNew(Statement leftHandSideExpression10) {
return null;
}

public Statement resolveByField(Statement lhs, String field) {
return null;
public Statement resolveByField(final Statement lhs, final String field) {
return new ResolveByIndexStatement(lhs, field);
}

public Statement defineByIndex(Statement lhs, Statement index) {
return null;
public Statement resolveByIndex(final Statement lhs, final Statement index) {
return new ResolveByIndexStatement(lhs, index);
}

public Statement ifStatement(Statement vbool, Statement vthen, Statement velse) {
Expand Down Expand Up @@ -412,23 +415,23 @@ public Statement labelledStatement(String label, Statement statement) {
}

public Statement objectValue(List<Statement> namedValues) {
return null;
return new ObjectLiteralStatement(namedValues);
}

public Statement propertyNameId(String id) {
return null;
return new StringLiteralStatement(id);
}

public Statement propertyNameString(String string) {
return null;
return new StringLiteralStatement(string);
}

public Statement propertyNameNumeric(Statement numericLiteral) {
return null;
}

public Statement namedValue(Statement propertyName, Statement expr) {
return null;
public Statement namedValue(final Statement propertyName, final Statement expr) {
return new NamedValueStatement(propertyName, expr);
}

public Statement arrayLiteral(List<Statement> exprs) {
Expand Down
@@ -0,0 +1,26 @@
package org.dynjs.parser.statement;

import me.qmx.jitescript.CodeBlock;
import org.dynjs.compiler.DynJSCompiler;
import org.dynjs.parser.Statement;

import static me.qmx.jitescript.util.CodegenUtils.sig;

public class NamedValueStatement implements Statement {

private final Statement propertyName;
private final Statement expr;

public NamedValueStatement(Statement propertyName, Statement expr) {
this.propertyName = propertyName;
this.expr = expr;
}

@Override
public CodeBlock getCodeBlock() {
return CodeBlock.newCodeBlock()
.append(propertyName.getCodeBlock())
.append(expr.getCodeBlock())
.invokeinterface(DynJSCompiler.Types.Scope, "define", sig(void.class, String.class, Object.class));
}
}
@@ -0,0 +1,34 @@
package org.dynjs.parser.statement;

import me.qmx.jitescript.CodeBlock;
import org.dynjs.parser.Statement;
import org.dynjs.runtime.DynObject;

import java.util.List;

import static me.qmx.jitescript.util.CodegenUtils.p;
import static me.qmx.jitescript.util.CodegenUtils.sig;

public class ObjectLiteralStatement implements Statement {

private final List<Statement> namedValues;

public ObjectLiteralStatement(List<Statement> namedValues) {
this.namedValues = namedValues;
}

@Override
public CodeBlock getCodeBlock() {
CodeBlock obj = CodeBlock.newCodeBlock()
.newobj(p(DynObject.class))
.dup()
.invokespecial(p(DynObject.class), "<init>", sig(void.class))
.astore(7);
for (Statement namedValue : namedValues) {

obj = obj.aload(7)
.append(namedValue.getCodeBlock());
}
return obj.aload(7);
}
}
@@ -0,0 +1,30 @@
package org.dynjs.parser.statement;

import me.qmx.jitescript.CodeBlock;
import org.dynjs.compiler.DynJSCompiler;
import org.dynjs.parser.Statement;

import static me.qmx.jitescript.util.CodegenUtils.sig;

public class ResolveByIndexStatement implements Statement {

private final Statement lhs;
private final Statement index;

public ResolveByIndexStatement(Statement lhs, String index) {
this(lhs, new StringLiteralStatement(index));

}
public ResolveByIndexStatement(Statement lhs, Statement index) {
this.lhs = lhs;
this.index = index;
}

@Override
public CodeBlock getCodeBlock() {
return CodeBlock.newCodeBlock()
.append(lhs.getCodeBlock())
.append(index.getCodeBlock())
.invokeinterface(DynJSCompiler.Types.Scope, "resolve", sig(Object.class, String.class));
}
}
25 changes: 25 additions & 0 deletions dynjs/src/test/java/org/dynjs/runtime/DynJSTest.java
Expand Up @@ -205,6 +205,31 @@ public void testLogicalOperators() {
check("var result = true && true;", true);
}

@Test
public void testEmptyObjectLiteral() {
dynJS.eval(context, "var result = {};");
assertThat(context.getScope().resolve("result"))
.isNotNull()
.isInstanceOf(DynObject.class);
}

@Test
public void testBasicObjectLiteral() {
dynJS.eval(context, "var result = {w:true};");
final Object result = context.getScope().resolve("result");
assertThat(result)
.isNotNull()
.isInstanceOf(DynObject.class);
assertThat(((DynObject) result).resolve("w")).isInstanceOf(Boolean.class).isEqualTo(Boolean.TRUE);
}

@Test
public void testObjectLiteralPropertyAccess() {
check("var x = {w:true}; var result = x.w;", true);
check("var x = {'y':false}; var result = x.y;", false);
check("var x = {'z':true}; var result = x['z'];", true);
}

private void check(String scriptlet) {
check(scriptlet, true);
}
Expand Down

0 comments on commit a6d1782

Please sign in to comment.