-
Notifications
You must be signed in to change notification settings - Fork 4
/
FunctionObject.java
96 lines (86 loc) · 3.81 KB
/
FunctionObject.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package com.endoflineblog.truffle.part_11.runtime;
import com.endoflineblog.truffle.part_11.EasyScriptTypeSystemGen;
import com.endoflineblog.truffle.part_11.exceptions.EasyScriptException;
import com.endoflineblog.truffle.part_11.nodes.exprs.functions.FunctionDispatchNode;
import com.endoflineblog.truffle.part_11.nodes.exprs.functions.FunctionDispatchNodeGen;
import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.interop.InteropLibrary;
import com.oracle.truffle.api.interop.TruffleObject;
import com.oracle.truffle.api.library.ExportLibrary;
import com.oracle.truffle.api.library.ExportMessage;
import com.oracle.truffle.api.strings.TruffleString;
/**
* The object that represents a function in EasyScript.
* Almost identical to the class with the same name from part 10,
* the only difference is the {@link #methodTarget} field,
* and the override of the {@link #toString()} method.
*
* @see #methodTarget
* @see #toString()
*/
@ExportLibrary(InteropLibrary.class)
public final class FunctionObject implements TruffleObject {
public final CallTarget callTarget;
public final int argumentCount;
/**
* The target of the method represented by this object.
* If this object represents a function,
* this will be {@code null}.
* If this object represents a method,
* this field will store the object that method was invoked on
* (in this part of the series, that will always be a {@link TruffleString},
* since we don't support methods on other objects yet).
* This field is read by the {@link FunctionDispatchNode function dispatch Node},
* and by the Node that reads properties of {@link TruffleString}s.
*
* @see FunctionDispatchNode
* @see com.endoflineblog.truffle.part_11.nodes.exprs.strings.ReadTruffleStringPropertyNode
*/
public final Object methodTarget;
private final FunctionDispatchNode functionDispatchNode;
public FunctionObject(CallTarget callTarget, int argumentCount) {
this(callTarget, argumentCount, null);
}
public FunctionObject(CallTarget callTarget, int argumentCount,
Object methodTarget) {
this.callTarget = callTarget;
this.argumentCount = argumentCount;
this.methodTarget = methodTarget;
this.functionDispatchNode = FunctionDispatchNodeGen.create();
}
/**
* Returns the string representation of a given function.
* In JavaScript, this returns the actual code of a given function (!).
* We'll simplify in EasyScript, and just return the string {@code "[object Function]"}.
*/
@Override
public String toString() {
return "[object Function]";
}
@ExportMessage
boolean isExecutable() {
return true;
}
@ExportMessage
Object execute(Object[] arguments) {
// we have to make sure the given arguments are valid EasyScript values,
// as this class can be invoked from other languages, like Java
for (Object argument : arguments) {
if (!this.isEasyScriptValue(argument)) {
throw new EasyScriptException("'" + argument + "' is not an EasyScript value");
}
}
return this.functionDispatchNode.executeDispatch(this, arguments);
}
private boolean isEasyScriptValue(Object argument) {
// as of this chapter, the only available types in EasyScript are
// numbers (ints and doubles), booleans, 'undefined', functions, and strings
return EasyScriptTypeSystemGen.isImplicitDouble(argument) ||
EasyScriptTypeSystemGen.isBoolean(argument) ||
argument == Undefined.INSTANCE ||
argument instanceof ArrayObject ||
argument instanceof TruffleString ||
argument instanceof String ||
argument instanceof FunctionObject;
}
}