Skip to content

Commit

Permalink
Add support for constructors.
Browse files Browse the repository at this point in the history
  • Loading branch information
skinny85 committed Feb 18, 2024
1 parent 9ff5126 commit 51b591e
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ public class CounterThisBenchmark extends TruffleBenchmark {

private static final String COUNTER_CLASS = "" +
"class Counter { " +
" setCount(count) { " +
" this.count = count; " +
" constructor() { " +
" this.count = 0; " +
" } " +
" increment() { " +
" this.count = this.count + 1; " +
" } " +
" getCount() { " +
" return this.count; " +
Expand All @@ -29,8 +32,8 @@ public void setup() {
private static final String COUNT_WITH_THIS_IN_FOR = "" +
"function countWithThisInFor(n) { " +
" const counter = new Counter(); " +
" for (let i = 1; i <= n; i = i + 1) { " +
" counter['setCount'](i); " +
" for (let i = 0; i < n; i = i + 1) { " +
" counter['increment'](); " +
" } " +
" return counter['getCount'](); " +
"}";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@

import com.endoflineblog.truffle.part_13.exceptions.EasyScriptException;
import com.endoflineblog.truffle.part_13.nodes.exprs.EasyScriptExprNode;
import com.endoflineblog.truffle.part_13.nodes.exprs.functions.FunctionDispatchNode;
import com.endoflineblog.truffle.part_13.nodes.exprs.functions.FunctionDispatchNodeGen;
import com.endoflineblog.truffle.part_13.runtime.ClassPrototypeObject;
import com.endoflineblog.truffle.part_13.runtime.FunctionObject;
import com.endoflineblog.truffle.part_13.runtime.JavaScriptObject;
import com.oracle.truffle.api.dsl.Executed;
import com.oracle.truffle.api.dsl.Fallback;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.library.CachedLibrary;
import com.oracle.truffle.api.nodes.ExplodeLoop;
import com.oracle.truffle.api.object.Shape;
import com.oracle.truffle.api.object.DynamicObjectLibrary;

import java.util.List;

Expand All @@ -24,19 +28,33 @@ public abstract class NewExprNode extends EasyScriptExprNode {
@Children
private final EasyScriptExprNode[] args;

@SuppressWarnings("FieldMayBeFinal")
@Child
private FunctionDispatchNode constructorDispatchNode;

protected NewExprNode(EasyScriptExprNode constructorExpr, List<EasyScriptExprNode> args) {
this.constructorExpr = constructorExpr;
this.args = args.toArray(EasyScriptExprNode[]::new);
this.constructorDispatchNode = FunctionDispatchNodeGen.create();
}

/**
* The specialization for when the constructor expression evaluates to a
* {@link ClassPrototypeObject}.
*/
@Specialization
protected Object instantiateObject(VirtualFrame frame, ClassPrototypeObject classPrototypeObject) {
this.consumeArguments(frame);
return new JavaScriptObject(this.currentLanguageContext().shapesAndPrototypes.rootShape, classPrototypeObject);
@Specialization(limit = "2")
protected Object instantiateObject(VirtualFrame frame, ClassPrototypeObject classPrototypeObject,
@CachedLibrary("classPrototypeObject") DynamicObjectLibrary dynamicObjectLibrary) {
var object = new JavaScriptObject(this.currentLanguageContext().shapesAndPrototypes.rootShape, classPrototypeObject);
var constructor = dynamicObjectLibrary.getOrDefault(classPrototypeObject, "constructor", null);
if (constructor == null) {
this.consumeArguments(frame);
} else {
var args = this.executeArguments(frame);
FunctionObject boundConstructor = (FunctionObject) constructor;
this.constructorDispatchNode.executeDispatch(boundConstructor, args, object);
}
return object;
}

/**
Expand All @@ -60,4 +78,13 @@ private void consumeArguments(VirtualFrame frame) {
this.args[i].executeGeneric(frame);
}
}

@ExplodeLoop
private Object[] executeArguments(VirtualFrame frame) {
var args = new Object[this.args.length];
for (int i = 0; i < this.args.length; i++) {
args[i] = this.args[i].executeGeneric(frame);
}
return args;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -170,17 +170,20 @@ public void benchmark_returns_its_input() {
var input = 100;
Value result = this.context.eval("ezs", "" +
"class Counter { " +
" setCount(count) { " +
" this.count = count; " +
" constructor() { " +
" this.count = 0; " +
" } " +
" increment() { " +
" this.count = this.count + 1; " +
" } " +
" getCount() { " +
" return this.count; " +
" } " +
"} " +
"function countWithThisInFor(n) { " +
" const counter = new Counter(); " +
" for (let i = 1; i <= n; i = i + 1) { " +
" counter['setCount'](i); " +
" for (let i = 0; i < n; i = i + 1) { " +
" counter['increment'](); " +
" } " +
" return counter['getCount'](); " +
"} " +
Expand Down Expand Up @@ -266,4 +269,18 @@ public void negative_array_indexes_are_converted_to_strings() {
);
assertEquals(45, result.asInt());
}

@Test
public void constructors_are_invoked_through_new() {
Value result = this.context.eval("ezs", "" +
"class A { " +
" constructor(x) { " +
" this.x = x; " +
" } " +
"} " +
"let a = new A(13); " +
"a.x"
);
assertEquals(13, result.asInt());
}
}

0 comments on commit 51b591e

Please sign in to comment.