Skip to content

Commit

Permalink
Make Object a common superclass of all classes.
Browse files Browse the repository at this point in the history
  • Loading branch information
skinny85 committed Apr 20, 2024
1 parent 01e830e commit a930017
Show file tree
Hide file tree
Showing 14 changed files with 243 additions and 105 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.endoflineblog.truffle.part_13.nodes.exprs.functions.built_in.BuiltInFunctionBodyExprNode;
import com.endoflineblog.truffle.part_13.nodes.exprs.functions.built_in.PowFunctionBodyExprNodeFactory;
import com.endoflineblog.truffle.part_13.nodes.exprs.functions.built_in.methods.CharAtMethodBodyExprNodeFactory;
import com.endoflineblog.truffle.part_13.nodes.exprs.functions.built_in.methods.HasOwnPropertyMethodBodyExprNodeFactory;
import com.endoflineblog.truffle.part_13.nodes.root.BuiltInFuncRootNode;
import com.endoflineblog.truffle.part_13.nodes.root.StmtBlockRootNode;
import com.endoflineblog.truffle.part_13.nodes.stmts.blocks.BlockStmtNode;
Expand All @@ -16,6 +17,7 @@
import com.endoflineblog.truffle.part_13.runtime.FunctionObject;
import com.endoflineblog.truffle.part_13.runtime.GlobalScopeObject;
import com.endoflineblog.truffle.part_13.runtime.JavaScriptObject;
import com.endoflineblog.truffle.part_13.runtime.ObjectPrototype;
import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.TruffleLanguage;
import com.oracle.truffle.api.dsl.NodeFactory;
Expand Down Expand Up @@ -75,12 +77,15 @@ public static EasyScriptTruffleLanguage get(Node node) {
*/
private final Shape rootShape = Shape.newBuilder().build();

private final ClassPrototypeObject functionPrototype = new ClassPrototypeObject(this.rootShape, "Function");
private final ObjectPrototype objectPrototype = new ObjectPrototype(this.rootShape);

private final ClassPrototypeObject functionPrototype = new ClassPrototypeObject(this.rootShape,
"Function", this.objectPrototype);

@Override
protected CallTarget parse(ParsingRequest request) throws Exception {
ParsingResult parsingResult = EasyScriptTruffleParser.parse(
request.getSource().getReader(), this.rootShape);
request.getSource().getReader(), this.rootShape, this.objectPrototype);
var programRootNode = new StmtBlockRootNode(this, parsingResult.topLevelFrameDescriptor,
parsingResult.programStmtBlock);
return programRootNode.getCallTarget();
Expand Down Expand Up @@ -110,14 +115,22 @@ protected Object getScope(EasyScriptLanguageContext context) {

private DynamicObject createGlobalScopeObject(DynamicObjectLibrary objectLibrary) {
var globalScopeObject = new GlobalScopeObject(this.rootShape);
// the 0 flag indicates Math is a variable, and can be reassigned
// the 0 flag indicates that these are variables, and can be reassigned
objectLibrary.putConstant(globalScopeObject, "Math",
this.createMathObject(objectLibrary), 0);

// initialize the Object prototype
objectLibrary.putConstant( this.objectPrototype, "hasOwnProperty",
this.defineBuiltInMethod(HasOwnPropertyMethodBodyExprNodeFactory.getInstance()),
0);
objectLibrary.putConstant(globalScopeObject, "Object",
this.objectPrototype, 0);

return globalScopeObject;
}

private Object createMathObject(DynamicObjectLibrary objectLibrary) {
var mathPrototype = new ClassPrototypeObject(this.rootShape, "Math");
var mathPrototype = new ClassPrototypeObject(this.rootShape, "Math", this.objectPrototype);
var mathObject = new JavaScriptObject(this.rootShape, mathPrototype);
objectLibrary.putConstant(mathObject, "abs",
this.defineBuiltInFunction(AbsFunctionBodyExprNodeFactory.getInstance()),
Expand All @@ -129,14 +142,14 @@ private Object createMathObject(DynamicObjectLibrary objectLibrary) {
}

private ShapesAndPrototypes createShapesAndPrototypes(DynamicObjectLibrary objectLibrary) {
var arrayPrototype = new ClassPrototypeObject(this.rootShape, "Array");
var arrayPrototype = new ClassPrototypeObject(this.rootShape, "Array", this.objectPrototype);
return new ShapesAndPrototypes(this.rootShape, this.arrayShape,
this.functionPrototype, arrayPrototype,
this.createStringPrototype(objectLibrary));
this.objectPrototype, this.functionPrototype,
arrayPrototype, this.createStringPrototype(objectLibrary));
}

private ClassPrototypeObject createStringPrototype(DynamicObjectLibrary objectLibrary) {
var stringPrototype = new ClassPrototypeObject(this.rootShape, "String");
var stringPrototype = new ClassPrototypeObject(this.rootShape, "String", this.objectPrototype);
objectLibrary.putConstant(stringPrototype, "charAt",
this.defineBuiltInMethod(CharAtMethodBodyExprNodeFactory.getInstance()),
0);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.endoflineblog.truffle.part_13.common;

import com.endoflineblog.truffle.part_13.runtime.ClassPrototypeObject;
import com.endoflineblog.truffle.part_13.runtime.ObjectPrototype;
import com.oracle.truffle.api.object.Shape;

/**
Expand All @@ -14,14 +15,17 @@
public final class ShapesAndPrototypes {
public final Shape rootShape;
public final Shape arrayShape;
public final ObjectPrototype objectPrototype;
public final ClassPrototypeObject functionPrototype;
public final ClassPrototypeObject arrayPrototype;
public final ClassPrototypeObject stringPrototype;

public ShapesAndPrototypes(Shape rootShape, Shape arrayShape, ClassPrototypeObject functionPrototype,
public ShapesAndPrototypes(Shape rootShape, Shape arrayShape,
ObjectPrototype objectPrototype, ClassPrototypeObject functionPrototype,
ClassPrototypeObject arrayPrototype, ClassPrototypeObject stringPrototype) {
this.rootShape = rootShape;
this.arrayShape = arrayShape;
this.objectPrototype = objectPrototype;
this.functionPrototype = functionPrototype;
this.arrayPrototype = arrayPrototype;
this.stringPrototype = stringPrototype;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.endoflineblog.truffle.part_13.nodes.exprs.functions.built_in.methods;

import com.endoflineblog.truffle.part_13.nodes.exprs.functions.built_in.BuiltInFunctionBodyExprNode;
import com.endoflineblog.truffle.part_13.nodes.exprs.strings.ReadTruffleStringPropertyNode;
import com.endoflineblog.truffle.part_13.runtime.EasyScriptTruffleStrings;
import com.oracle.truffle.api.dsl.Fallback;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.library.CachedLibrary;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.object.DynamicObjectLibrary;
import com.oracle.truffle.api.strings.TruffleString;

public abstract class HasOwnPropertyMethodBodyExprNode extends BuiltInFunctionBodyExprNode {
@Specialization(limit = "2")
protected boolean hasOwnPropertyDynamicObject(
DynamicObject self, Object property,
@CachedLibrary("self") DynamicObjectLibrary dynamicObjectLibrary) {
return dynamicObjectLibrary.containsKey(self, EasyScriptTruffleStrings.toString(property));
}

@Specialization
protected boolean hasOwnPropertyTruffleString(
@SuppressWarnings("unused") TruffleString self,
Object property) {
// strings only have the 'length' property
return ReadTruffleStringPropertyNode.LENGTH_PROP.equals(EasyScriptTruffleStrings.toString(property));
}

@Fallback
protected boolean hasOwnPropertyPrimitive(
@SuppressWarnings("unused") Object self,
@SuppressWarnings("unused") Object property) {
// primitives don't own any properties
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
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.AbstractClassPrototypeObject;
import com.endoflineblog.truffle.part_13.runtime.FunctionObject;
import com.endoflineblog.truffle.part_13.runtime.JavaScriptObject;
import com.oracle.truffle.api.dsl.Executed;
Expand Down Expand Up @@ -44,11 +44,11 @@ protected NewExprNode(EasyScriptExprNode constructorExpr, List<EasyScriptExprNod
}

/**
* The specialization for when the constructor expression evaluates to a
* {@link ClassPrototypeObject}.
* The specialization for when the constructor expression evaluates to an
* {@link AbstractClassPrototypeObject}.
*/
@Specialization(limit = "2")
protected Object instantiateObject(VirtualFrame frame, ClassPrototypeObject classPrototypeObject,
protected Object instantiateObject(VirtualFrame frame, AbstractClassPrototypeObject classPrototypeObject,
@CachedLibrary("classPrototypeObject") InteropLibrary interopPrototypeLibrary) {
var object = new JavaScriptObject(this.currentLanguageContext().shapesAndPrototypes.rootShape, classPrototypeObject);
Object constructor = null;
Expand All @@ -72,7 +72,7 @@ protected Object instantiateObject(VirtualFrame frame, ClassPrototypeObject clas

/**
* The specialization for when the constructor expression evaluates to something other than
* {@link ClassPrototypeObject}.
* {@link AbstractClassPrototypeObject}.
*/
@Fallback
protected Object instantiateNonConstructor(VirtualFrame frame, Object object) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import com.endoflineblog.truffle.part_13.exceptions.EasyScriptException;
import com.endoflineblog.truffle.part_13.nodes.exprs.EasyScriptExprNode;
import com.endoflineblog.truffle.part_13.runtime.ClassPrototypeChainObject;
import com.endoflineblog.truffle.part_13.runtime.ClassPrototypeObject;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.InteropLibrary;
Expand All @@ -13,7 +13,7 @@
* The Node implementing the 'super' expression.
*/
public final class SuperExprNode extends EasyScriptExprNode {
private final ClassPrototypeChainObject classPrototype;
private final ClassPrototypeObject classPrototype;

@SuppressWarnings("FieldMayBeFinal")
@Child
Expand All @@ -22,7 +22,7 @@ public final class SuperExprNode extends EasyScriptExprNode {
@Child
private InteropLibrary interopLibrary;

public SuperExprNode(ClassPrototypeChainObject classPrototype) {
public SuperExprNode(ClassPrototypeObject classPrototype) {
this.classPrototype = classPrototype;
this.thisExprNode = new ThisExprNode();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package com.endoflineblog.truffle.part_13.nodes.exprs.properties;

import com.endoflineblog.truffle.part_13.exceptions.EasyScriptException;
import com.endoflineblog.truffle.part_13.nodes.EasyScriptNode;
import com.endoflineblog.truffle.part_13.nodes.exprs.strings.ReadTruffleStringPropertyNode;
import com.endoflineblog.truffle.part_13.runtime.ClassPrototypeObject;
import com.endoflineblog.truffle.part_13.runtime.EasyScriptTruffleStrings;
import com.endoflineblog.truffle.part_13.runtime.ObjectPrototype;
import com.endoflineblog.truffle.part_13.runtime.Undefined;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Fallback;
Expand All @@ -11,14 +15,15 @@
import com.oracle.truffle.api.interop.UnsupportedMessageException;
import com.oracle.truffle.api.library.CachedLibrary;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.object.DynamicObjectLibrary;
import com.oracle.truffle.api.strings.TruffleString;

/**
* A Node for reading a property of a JavaScript object.
* Used by {@link PropertyReadExprNode} and {@link com.endoflineblog.truffle.part_13.nodes.exprs.arrays.ArrayIndexReadExprNode}.
* Identical to the class with the same name from part 12.
*/
public abstract class CommonReadPropertyNode extends Node {
public abstract class CommonReadPropertyNode extends EasyScriptNode {
public abstract Object executeReadProperty(Object target, Object property);

/**
Expand Down Expand Up @@ -56,12 +61,14 @@ protected Object readPropertyOfUndefined(@SuppressWarnings("unused") Object targ

/**
* Accessing a property of anything that is not {@code undefined}
* but doesn't have any members returns simply {@code undefined}
* in JavaScript.
* but doesn't have any members reads from the Object prototype.
*/
@Fallback
protected Object readPropertyOfNonUndefinedWithoutMembers(@SuppressWarnings("unused") Object target,
@SuppressWarnings("unused") Object property) {
return Undefined.INSTANCE;
@SuppressWarnings("unused") Object property,
@Cached("currentLanguageContext().shapesAndPrototypes.objectPrototype") ObjectPrototype objectPrototype,
@CachedLibrary(limit = "2") DynamicObjectLibrary dynamicObjectLibrary) {
return dynamicObjectLibrary.getOrDefault(objectPrototype,
EasyScriptTruffleStrings.toString(property), Undefined.INSTANCE);
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
package com.endoflineblog.truffle.part_13.nodes.exprs.strings;

import com.endoflineblog.truffle.part_13.exceptions.EasyScriptException;
import com.endoflineblog.truffle.part_13.nodes.EasyScriptNode;
import com.endoflineblog.truffle.part_13.runtime.ClassPrototypeObject;
import com.endoflineblog.truffle.part_13.runtime.EasyScriptTruffleStrings;
import com.endoflineblog.truffle.part_13.runtime.Undefined;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Fallback;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.interop.InteropLibrary;
import com.oracle.truffle.api.interop.UnknownIdentifierException;
import com.oracle.truffle.api.interop.UnsupportedMessageException;
import com.oracle.truffle.api.library.CachedLibrary;
import com.oracle.truffle.api.object.DynamicObjectLibrary;
import com.oracle.truffle.api.strings.TruffleString;

/**
Expand All @@ -21,7 +24,7 @@
* @see #readNonLengthProperty
*/
public abstract class ReadTruffleStringPropertyNode extends EasyScriptNode {
protected static final String LENGTH_PROP = "length";
public static final String LENGTH_PROP = "length";

/** The abstract {@code execute*()} method for this node. */
public abstract Object executeReadTruffleStringProperty(TruffleString truffleString, Object property);
Expand Down Expand Up @@ -59,8 +62,13 @@ protected Object readNonLengthProperty(
@SuppressWarnings("unused") TruffleString truffleString,
Object property,
@Cached("currentLanguageContext().shapesAndPrototypes.stringPrototype") ClassPrototypeObject stringPrototype,
@CachedLibrary(limit = "2") DynamicObjectLibrary stringPrototypeObjectLibrary) {
return stringPrototypeObjectLibrary.getOrDefault(stringPrototype, property,
Undefined.INSTANCE);
@CachedLibrary(limit = "2") InteropLibrary interopLibrary) {
try {
return interopLibrary.readMember(stringPrototype, property.toString());
} catch (UnknownIdentifierException e) {
return Undefined.INSTANCE;
} catch (UnsupportedMessageException e) {
throw new EasyScriptException(this, e.getMessage());
}
}
}
Loading

0 comments on commit a930017

Please sign in to comment.