@neo-one/smart-contract-compiler
Version:
NEO•ONE TypeScript smart contract compiler.
122 lines (120 loc) • 5.76 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PropertyAccessExpressionCompiler = void 0;
const tslib_1 = require("tslib");
const ts_utils_1 = require("@neo-one/ts-utils");
const typescript_1 = tslib_1.__importDefault(require("typescript"));
const DiagnosticCode_1 = require("../../DiagnosticCode");
const DiagnosticMessage_1 = require("../../DiagnosticMessage");
const builtins_1 = require("../builtins");
const NodeCompiler_1 = require("../NodeCompiler");
class PropertyAccessExpressionCompiler extends NodeCompiler_1.NodeCompiler {
constructor() {
super(...arguments);
this.kind = typescript_1.default.SyntaxKind.PropertyAccessExpression;
}
visitNode(sb, expr, optionsIn) {
const isOptionalChain = typescript_1.default.isOptionalChain(expr);
const value = ts_utils_1.tsUtils.expression.getExpression(expr);
const valueType = sb.context.analysis.getType(value);
const name = ts_utils_1.tsUtils.node.getNameNode(expr);
const nameValue = ts_utils_1.tsUtils.node.getName(expr);
const handleBuiltin = (member, visited) => {
if (builtins_1.isBuiltinInstanceMemberValue(member)) {
member.emitValue(sb, expr, optionsIn, visited);
return;
}
if (builtins_1.isBuiltinMemberValue(member)) {
member.emitValue(sb, expr, optionsIn);
return;
}
if (optionsIn.setValue) {
sb.context.reportError(name, DiagnosticCode_1.DiagnosticCode.InvalidBuiltinModify, DiagnosticMessage_1.DiagnosticMessage.CannotModifyBuiltin);
}
else {
sb.context.reportError(name, DiagnosticCode_1.DiagnosticCode.InvalidBuiltinReference, DiagnosticMessage_1.DiagnosticMessage.CannotReferenceBuiltinProperty);
}
};
const builtin = sb.context.builtins.getMember(value, name);
if (builtin !== undefined) {
handleBuiltin(builtin, false);
return;
}
const throwTypeError = (innerOptions) => {
sb.emitOp(expr, 'DROP');
sb.emitHelper(expr, innerOptions, sb.helpers.throwTypeError);
};
const processUndefined = (innerOptions) => {
sb.emitOp(expr, 'DROP');
sb.emitHelper(expr, innerOptions, sb.helpers.wrapUndefined);
};
const throwTypeErrorUnlessOptionalChain = (innerOptions) => {
isOptionalChain ? processUndefined(innerOptions) : throwTypeError(innerOptions);
};
const createProcessBuiltin = (valueName) => {
const member = sb.context.builtins.getOnlyMember(valueName, nameValue);
if (member === undefined) {
return throwTypeError;
}
return () => {
handleBuiltin(member, true);
};
};
const processObject = (innerOptions) => {
sb.emitPushString(name, nameValue);
if (optionsIn.pushValue && optionsIn.setValue) {
sb.emitOp(expr, 'OVER');
sb.emitOp(expr, 'OVER');
sb.emitPushInt(expr, 4);
sb.emitOp(expr, 'ROLL');
sb.emitHelper(expr, innerOptions, sb.helpers.setPropertyObjectProperty);
sb.emitHelper(expr, innerOptions, sb.helpers.getPropertyObjectProperty);
}
else if (optionsIn.setValue) {
sb.emitOp(expr, 'ROT');
sb.emitHelper(expr, innerOptions, sb.helpers.setPropertyObjectProperty);
}
else {
sb.emitHelper(expr, innerOptions, sb.helpers.getPropertyObjectProperty);
if (!optionsIn.pushValue) {
sb.emitOp(expr, 'DROP');
}
}
};
const options = sb.pushValueOptions(sb.noSetValueOptions(optionsIn));
sb.visit(value, options);
sb.emitHelper(value, options, sb.helpers.forBuiltinType({
type: valueType,
array: createProcessBuiltin('Array'),
arrayStorage: createProcessBuiltin('ArrayStorage'),
boolean: createProcessBuiltin('Boolean'),
buffer: createProcessBuiltin('Buffer'),
null: throwTypeErrorUnlessOptionalChain,
number: createProcessBuiltin('Number'),
object: processObject,
string: createProcessBuiltin('String'),
symbol: createProcessBuiltin('Symbol'),
undefined: throwTypeErrorUnlessOptionalChain,
map: createProcessBuiltin('Map'),
mapStorage: createProcessBuiltin('MapStorage'),
set: createProcessBuiltin('Set'),
setStorage: createProcessBuiltin('SetStorage'),
error: createProcessBuiltin('Error'),
forwardValue: createProcessBuiltin('ForwardValue'),
iteratorResult: createProcessBuiltin('IteratorResult'),
iterable: createProcessBuiltin('Iterable'),
iterableIterator: createProcessBuiltin('IterableIterator'),
transaction: createProcessBuiltin('TransactionBase'),
output: createProcessBuiltin('Output'),
attribute: createProcessBuiltin('AttributeBase'),
input: createProcessBuiltin('Input'),
account: createProcessBuiltin('Account'),
asset: createProcessBuiltin('Asset'),
contract: createProcessBuiltin('Contract'),
header: createProcessBuiltin('Header'),
block: createProcessBuiltin('Block'),
}));
}
}
exports.PropertyAccessExpressionCompiler = PropertyAccessExpressionCompiler;
//# sourceMappingURL=PropertyAccessExpressionCompiler.js.map