Skip to content

Commit

Permalink
Change hierarchy of objects to unify JavaScriptObject and ClassProtot…
Browse files Browse the repository at this point in the history
…ypeObject.
  • Loading branch information
skinny85 committed May 4, 2024
1 parent 61e1e9b commit edaea19
Show file tree
Hide file tree
Showing 11 changed files with 107 additions and 143 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ Object readMember(String member,

@ExportMessage
Object getMembers(@SuppressWarnings("unused") boolean includeInternal,
@CachedLibrary("this") DynamicObjectLibrary dynamicObjectLibrary) {
return new MemberNamesObject(dynamicObjectLibrary.getKeyArray(this));
@CachedLibrary("this") DynamicObjectLibrary instanceObjectLibrary) {
return new MemberNamesObject(instanceObjectLibrary.getKeyArray(this));
}

@ExportMessage
Expand Down
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.AbstractClassPrototypeObject;
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;
Expand Down Expand Up @@ -48,7 +48,7 @@ protected NewExprNode(EasyScriptExprNode constructorExpr, List<EasyScriptExprNod
* {@link AbstractClassPrototypeObject}.
*/
@Specialization(limit = "2")
protected Object instantiateObject(VirtualFrame frame, AbstractClassPrototypeObject classPrototypeObject,
protected Object instantiateObject(VirtualFrame frame, ClassPrototypeObject classPrototypeObject,
@CachedLibrary("classPrototypeObject") InteropLibrary interopPrototypeLibrary) {
var object = new JavaScriptObject(this.currentLanguageContext().shapesAndPrototypes.rootShape, classPrototypeObject);
Object constructor = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public Object evaluateAsFunction(VirtualFrame frame, Object receiver) {
}
try {
return this.interopLibrary.readMember(
this.classPrototype.superClassPrototype, "constructor");
this.classPrototype.prototype, "constructor");
} catch (UnknownIdentifierException e) {
return this.currentLanguageContext().emptyFunction;
} catch (UnsupportedMessageException e) {
Expand All @@ -61,6 +61,6 @@ public Object evaluateAsFunction(VirtualFrame frame, Object receiver) {
public Object readParentPrototype() {
// this method is called from the property access Nodes
// to find the parent prototype
return this.classPrototype.superClassPrototype;
return this.classPrototype.prototype;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@
import com.endoflineblog.truffle.part_13.nodes.stmts.variables.GlobalVarDeclStmtNodeGen;
import com.endoflineblog.truffle.part_13.parsing.antlr.EasyScriptLexer;
import com.endoflineblog.truffle.part_13.parsing.antlr.EasyScriptParser;
import com.endoflineblog.truffle.part_13.runtime.AbstractClassPrototypeObject;
import com.endoflineblog.truffle.part_13.runtime.ClassPrototypeObject;
import com.endoflineblog.truffle.part_13.runtime.ObjectPrototype;
import com.oracle.truffle.api.frame.FrameDescriptor;
Expand Down Expand Up @@ -132,9 +131,9 @@ private static final class LocalVariable extends FrameMember {
}
}
private static final class ClassPrototypeMember extends FrameMember {
public final AbstractClassPrototypeObject classPrototypeObject;
public final ClassPrototypeObject classPrototypeObject;

ClassPrototypeMember(AbstractClassPrototypeObject classPrototypeObject) {
ClassPrototypeMember(ClassPrototypeObject classPrototypeObject) {
this.classPrototypeObject = classPrototypeObject;
}
}
Expand Down Expand Up @@ -354,7 +353,7 @@ private EasyScriptStmtNode parseClassDeclStmt(EasyScriptParser.ClassDeclStmtCont
ClassPrototypeObject classPrototype;
FrameMember frameMember = this.localScopes.get(0).get(superClass);
if (frameMember instanceof ClassPrototypeMember) {
AbstractClassPrototypeObject superClassPrototype = ((ClassPrototypeMember) frameMember).classPrototypeObject;
ClassPrototypeObject superClassPrototype = ((ClassPrototypeMember) frameMember).classPrototypeObject;
classPrototype = new ClassPrototypeObject(this.objectShape, className, superClassPrototype);
} else {
throw new EasyScriptException("class '" + className + "' extends unknown class '" + superClass + "'");
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,34 +1,34 @@
package com.endoflineblog.truffle.part_13.runtime;

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.library.ExportLibrary;
import com.oracle.truffle.api.library.ExportMessage;
import com.oracle.truffle.api.object.DynamicObjectLibrary;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.object.Shape;

/**
* A {@link DynamicObject} that represents the prototype of class.
* That can be a user-defined class, or a built-in class,
* like for functions, or arrays.
* Identical to the class with the same name from part 12.
*/
@ExportLibrary(InteropLibrary.class)
public final class ClassPrototypeObject extends AbstractClassPrototypeObject {
public final AbstractClassPrototypeObject superClassPrototype;
public class ClassPrototypeObject extends JavaScriptObject {
public final String className;

public ClassPrototypeObject(Shape shape, String className,
AbstractClassPrototypeObject superClassPrototype) {
super(shape, className);
public ClassPrototypeObject(Shape shape, String className, DynamicObject prototype) {
super(shape, prototype);

this.superClassPrototype = superClassPrototype;
this.className = className;
}

@Override
public String toString() {
return "[class " + this.className + "]";
}

@ExportMessage
Object readMember(String member,
@CachedLibrary("this") DynamicObjectLibrary instanceObjectLibrary,
@CachedLibrary("this.superClassPrototype") InteropLibrary superClassInteropLibrary)
throws UnknownIdentifierException, UnsupportedMessageException {
Object value = instanceObjectLibrary.getOrDefault(this, member, null);
if (value == null) {
return superClassInteropLibrary.readMember(this.superClassPrototype, member);
}
return value;
Object toDisplayString(@SuppressWarnings("unused") boolean allowSideEffects) {
return this.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import com.oracle.truffle.api.interop.InteropLibrary;
import com.oracle.truffle.api.library.ExportLibrary;
import com.oracle.truffle.api.library.ExportMessage;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.object.Shape;
import com.oracle.truffle.api.strings.TruffleString;

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.oracle.truffle.api.library.CachedLibrary;
import com.oracle.truffle.api.library.ExportLibrary;
import com.oracle.truffle.api.library.ExportMessage;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.object.DynamicObjectLibrary;
import com.oracle.truffle.api.object.Shape;

Expand All @@ -19,14 +20,13 @@
* that is invoked in {@link com.endoflineblog.truffle.part_13.nodes.exprs.properties.CommonWritePropertyNode}.
*/
@ExportLibrary(InteropLibrary.class)
public class JavaScriptObject extends InteropDynamicObject {
// this can't be private, because it's used in specialization guard expressions
final AbstractClassPrototypeObject classPrototypeObject;
public class JavaScriptObject extends DynamicObject {
public final DynamicObject prototype;

public JavaScriptObject(Shape shape, AbstractClassPrototypeObject classPrototypeObject) {
public JavaScriptObject(Shape shape, DynamicObject prototype) {
super(shape);

this.classPrototypeObject = classPrototypeObject;
this.prototype = prototype;
}

@Override
Expand All @@ -39,38 +39,54 @@ Object toDisplayString(@SuppressWarnings("unused") boolean allowSideEffects) {
return this.toString();
}

@ExportMessage
boolean hasMembers() {
return true;
}

@ExportMessage
boolean isMemberReadable(String member,
@CachedLibrary("this") DynamicObjectLibrary instanceObjectLibrary,
@CachedLibrary("this.classPrototypeObject") DynamicObjectLibrary prototypeObjectLibrary) {
@CachedLibrary("this.prototype") InteropLibrary prototypeInteropLibrary) {
return instanceObjectLibrary.containsKey(this, member) ||
prototypeObjectLibrary.containsKey(this.classPrototypeObject, member);
prototypeInteropLibrary.isMemberReadable(this.prototype, member);
}

@ExportMessage
Object readMember(String member,
@CachedLibrary("this") DynamicObjectLibrary instanceObjectLibrary,
@CachedLibrary("this.classPrototypeObject") InteropLibrary prototypeInteropLibrary)
@CachedLibrary("this.prototype") InteropLibrary prototypeInteropLibrary)
throws UnknownIdentifierException, UnsupportedMessageException {
// since ClassInstanceObject is mutable, we need to check it first, before the prototype
Object value = instanceObjectLibrary.getOrDefault(this, member, null);
if (value == null) {
return prototypeInteropLibrary.readMember(this.classPrototypeObject, member);
return prototypeInteropLibrary.readMember(this.prototype, member);
}
return value;
}

@ExportMessage
Object getMembers(@SuppressWarnings("unused") boolean includeInternal,
@CachedLibrary("this") DynamicObjectLibrary instanceObjectLibrary) {
return new MemberNamesObject(instanceObjectLibrary.getKeyArray(this));
}

@ExportMessage
boolean isMemberModifiable(String member,
@CachedLibrary("this") DynamicObjectLibrary instanceObjectLibrary,
@CachedLibrary("this.classPrototypeObject") DynamicObjectLibrary prototypeObjectLibrary) {
return this.isMemberReadable(member, instanceObjectLibrary, prototypeObjectLibrary);
@CachedLibrary("this.prototype") InteropLibrary prototypeInteropLibrary) {
return this.isMemberReadable(member, instanceObjectLibrary, prototypeInteropLibrary);
}

@ExportMessage
boolean isMemberInsertable(String member,
@CachedLibrary("this") DynamicObjectLibrary instanceObjectLibrary,
@CachedLibrary("this.classPrototypeObject") DynamicObjectLibrary prototypeObjectLibrary) {
return !this.isMemberModifiable(member, instanceObjectLibrary, prototypeObjectLibrary);
@CachedLibrary("this.prototype") InteropLibrary prototypeInteropLibrary) {
return !this.isMemberModifiable(member, instanceObjectLibrary, prototypeInteropLibrary);
}

@ExportMessage
void writeMember(String member, Object value,
@CachedLibrary("this") DynamicObjectLibrary instanceObjectLibrary) {
instanceObjectLibrary.put(this, member, value);
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,47 @@
package com.endoflineblog.truffle.part_13.runtime;

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.library.ExportLibrary;
import com.oracle.truffle.api.library.ExportMessage;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.object.DynamicObjectLibrary;
import com.oracle.truffle.api.object.Shape;

@ExportLibrary(InteropLibrary.class)
public final class ObjectPrototype extends AbstractClassPrototypeObject {
public final class ObjectPrototype extends ClassPrototypeObject {
public ObjectPrototype(Shape shape) {
super(shape, "Object");
super(shape, "Object", new DynamicObject(shape) {});
}

@ExportMessage
boolean isMemberReadable(String member,
@CachedLibrary("this") DynamicObjectLibrary instanceObjectLibrary) {
return instanceObjectLibrary.containsKey(this, member);
}

@ExportMessage
Object readMember(String member,
@CachedLibrary("this") DynamicObjectLibrary instanceObjectLibrary)
throws UnknownIdentifierException, UnsupportedMessageException {
Object value = instanceObjectLibrary.getOrDefault(this, member, null);
if (value == null) {
throw UnknownIdentifierException.create(member);
}
return value;
}

@ExportMessage
boolean isMemberModifiable(String member,
@CachedLibrary("this") DynamicObjectLibrary instanceObjectLibrary) {
return this.isMemberReadable(member, instanceObjectLibrary);
}

@ExportMessage
boolean isMemberInsertable(String member,
@CachedLibrary("this") DynamicObjectLibrary instanceObjectLibrary) {
return !this.isMemberModifiable(member, instanceObjectLibrary);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,18 @@ void methods_are_inherited() {
assertEquals("A", result.toString());
}

@Test
void class_instances_have_members_of_parent_prototypes() {
Value obj = this.context.eval("ezs", "" +
"class A { " +
" a() { } " +
"} " +
"class B extends A { } " +
"new B; "
);
assertTrue(obj.hasMember("a"));
}

@Test
void super_reads_property_of_parent_prototype() {
Value result = this.context.eval("ezs", "" +
Expand Down

0 comments on commit edaea19

Please sign in to comment.