expression-evaluation
Version:
Expression Evaluation
56 lines (55 loc) • 2.34 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CallNode = void 0;
const Node_js_1 = require("../Node.js");
const ConstantNode_js_1 = require("./ConstantNode.js");
const Type_js_1 = require("../Type.js");
class CallNode extends Node_js_1.Node {
_fnode;
_subnodes;
_type;
constructor(frame, _fnode, _subnodes) {
super(frame);
this._fnode = _fnode;
this._subnodes = _subnodes;
this._type = _fnode.signature?.type ?? Type_js_1.typeUnknown;
}
get type() {
return this._type;
}
compile(type) {
this._fnode = this._fnode.compile(Type_js_1.typeFunction);
this._type = this._fnode.signature?.type ?? Type_js_1.typeUnknown;
this._type = this.reduceType(type);
const signature = this._fnode.signature;
if (signature) {
if (this._subnodes.length < signature.minArity) {
this.throwError(`insufficient number of arguments ${this._subnodes.length} is less than ${signature.minArity} that function requires`);
}
if (this._subnodes.length > signature.maxArity) {
this.throwError(`excessive number of arguments ${this._subnodes.length} is more than ${signature.maxArity} that function requires`);
}
}
let constant = signature?.pure;
for (let i = 0; i < this._subnodes.length; ++i) {
const argTypeInference = signature?.argTypeInference(this.type, i) ?? Type_js_1.typeUnknown;
if (!argTypeInference) {
this.throwTypeError(type);
}
this._subnodes[i] = this._subnodes[i].compile(argTypeInference);
constant &&= this._subnodes[i].constant;
}
return constant && this._fnode.constant
? new ConstantNode_js_1.ConstantNode(this, this._fnode.evaluate()(...this._subnodes.map((node) => node.evaluate())))
: this;
}
evaluate() {
return this._fnode.evaluate()(...this._subnodes.map((node) => node.evaluate()));
}
toString(ident = 0) {
return `${super.toString(ident)} call node`
+ `, fnode:${this._fnode.toString(ident + 1)}`
+ `, subnodes:\n${this._subnodes.map((s) => s.toString(ident + 1)).join('\n')}`;
}
}
exports.CallNode = CallNode;