UNPKG

@neo-one/smart-contract-compiler

Version:

NEO•ONE TypeScript smart contract compiler.

296 lines (294 loc) 15.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ObjectBindingHelper = 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 types_1 = require("../types"); class ObjectBindingHelper extends types_1.TypedHelper { constructor(options) { super(options); this.value = options.value; } emit(sb, node, optionsIn) { const restElement = node.elements.find((element) => ts_utils_1.tsUtils.node.getDotDotDotToken(element) !== undefined); const elements = restElement === undefined ? [...node.elements] : node.elements.slice(0, -1); const throwTypeError = (innerOptions) => { sb.emitOp(node, 'DROP'); sb.emitHelper(node, innerOptions, sb.helpers.throwTypeError); }; const throwInnerTypeError = (innerOptions) => { sb.emitOp(node, 'DROP'); throwTypeError(innerOptions); }; const handleBuiltin = (member, element, innerOptions) => { if (builtins_1.isBuiltinInstanceMemberValue(member)) { member.emitValue(sb, element, innerOptions, true); return; } if (builtins_1.isBuiltinMemberValue(member)) { member.emitValue(sb, element, innerOptions); return; } sb.context.reportError(element, DiagnosticCode_1.DiagnosticCode.InvalidBuiltinReference, DiagnosticMessage_1.DiagnosticMessage.CannotReferenceBuiltinProperty); }; const createProcessBuiltin = (builtinName, isBuiltinValue = false) => (innerOptions) => { if (restElement !== undefined) { sb.context.reportUnsupportedEfficiency(restElement); } elements.forEach((element) => { const nameNode = ts_utils_1.tsUtils.node.getNameNode(element); const propertyName = ts_utils_1.tsUtils.node.getPropertyNameNode(element); const initializer = ts_utils_1.tsUtils.initializer.getInitializer(element); const elementType = sb.context.analysis.getType(nameNode); if (typescript_1.default.isIdentifier(nameNode)) { sb.scope.add(ts_utils_1.tsUtils.node.getText(nameNode)); } if (!isBuiltinValue) { sb.emitOp(element, 'DUP'); } if (propertyName === undefined || typescript_1.default.isIdentifier(propertyName) || typescript_1.default.isStringLiteral(propertyName) || typescript_1.default.isNumericLiteral(propertyName)) { const memberName = propertyName === undefined ? ts_utils_1.tsUtils.node.getNameOrThrow(element) : typescript_1.default.isIdentifier(propertyName) ? ts_utils_1.tsUtils.node.getText(propertyName) : typescript_1.default.isStringLiteral(propertyName) ? ts_utils_1.tsUtils.literal.getLiteralValue(propertyName) : `${ts_utils_1.tsUtils.literal.getLiteralValue(propertyName)}`; const member = sb.context.builtins.getOnlyMember(builtinName, memberName); if (member === undefined) { throwInnerTypeError(innerOptions); } else { handleBuiltin(member, element, innerOptions); } } else { sb.context.reportUnsupported(element); } if (initializer !== undefined) { sb.emitHelper(node, innerOptions, sb.helpers.if({ condition: () => { sb.emitOp(node, 'DUP'); sb.emitHelper(node, innerOptions, sb.helpers.isUndefined); }, whenTrue: () => { sb.emitOp(node, 'DROP'); sb.visit(initializer, innerOptions); }, })); } if (typescript_1.default.isIdentifier(nameNode)) { sb.scope.set(sb, element, innerOptions, ts_utils_1.tsUtils.node.getText(nameNode)); } else if (typescript_1.default.isArrayBindingPattern(nameNode)) { sb.emitHelper(nameNode, innerOptions, sb.helpers.arrayBinding({ type: elementType })); } else { sb.emitHelper(nameNode, innerOptions, sb.helpers.objectBinding({ type: elementType })); } }); if (!isBuiltinValue) { sb.emitOp(node, 'DROP'); } }; const processObject = (innerOptions) => { let addSymbolProp = () => { }; let addStringProp = () => { }; if (restElement !== undefined) { sb.emitPushInt(node, 0); sb.emitOp(node, 'NEWARRAY'); sb.emitPushInt(node, 0); sb.emitOp(node, 'NEWARRAY'); sb.emitOp(node, 'ROT'); addSymbolProp = () => { sb.emitPushInt(restElement, 4); sb.emitOp(restElement, 'PICK'); sb.emitOp(node, 'OVER'); sb.emitOp(node, 'APPEND'); }; addStringProp = () => { sb.emitPushInt(restElement, 3); sb.emitOp(restElement, 'PICK'); sb.emitOp(node, 'OVER'); sb.emitOp(node, 'APPEND'); }; } elements.forEach((element) => { const nameNode = ts_utils_1.tsUtils.node.getNameNode(element); const propertyName = ts_utils_1.tsUtils.node.getPropertyNameNode(element); const initializer = ts_utils_1.tsUtils.initializer.getInitializer(element); const elementType = sb.context.analysis.getType(nameNode); if (typescript_1.default.isIdentifier(nameNode)) { sb.scope.add(ts_utils_1.tsUtils.node.getText(nameNode)); } sb.emitOp(element, 'DUP'); if (propertyName === undefined) { sb.emitPushString(element, ts_utils_1.tsUtils.node.getNameOrThrow(element)); addStringProp(); sb.emitHelper(element, innerOptions, sb.helpers.getPropertyObjectProperty); } else if (typescript_1.default.isIdentifier(propertyName)) { sb.emitPushString(element, ts_utils_1.tsUtils.node.getText(propertyName)); addStringProp(); sb.emitHelper(element, innerOptions, sb.helpers.getPropertyObjectProperty); } else if (typescript_1.default.isComputedPropertyName(propertyName)) { const expr = ts_utils_1.tsUtils.expression.getExpression(propertyName); const propertyNameType = sb.context.analysis.getType(expr); sb.visit(expr, innerOptions); const handleSymbol = () => { sb.emitHelper(element, innerOptions, sb.helpers.unwrapSymbol); addSymbolProp(); sb.emitHelper(element, innerOptions, sb.helpers.getSymbolObjectProperty); }; const handleStringBase = (innerInnerOptions) => { addStringProp(); sb.emitHelper(element, innerInnerOptions, sb.helpers.getPropertyObjectProperty); }; const handleString = (innerInnerOptions) => { sb.emitHelper(node, innerInnerOptions, sb.helpers.unwrapString); handleStringBase(innerInnerOptions); }; const handleNumber = (innerInnerOptions) => { sb.emitHelper(node, innerInnerOptions, sb.helpers.toString({ type: propertyNameType })); handleStringBase(innerInnerOptions); }; sb.emitHelper(element, innerOptions, sb.helpers.forBuiltinType({ type: propertyNameType, array: throwInnerTypeError, arrayStorage: throwInnerTypeError, boolean: throwInnerTypeError, buffer: throwInnerTypeError, null: throwInnerTypeError, number: handleNumber, object: throwInnerTypeError, string: handleString, symbol: handleSymbol, undefined: throwInnerTypeError, map: throwInnerTypeError, mapStorage: throwInnerTypeError, set: throwInnerTypeError, setStorage: throwInnerTypeError, error: throwInnerTypeError, forwardValue: throwInnerTypeError, iteratorResult: throwInnerTypeError, iterable: throwInnerTypeError, iterableIterator: throwInnerTypeError, transaction: throwInnerTypeError, output: throwInnerTypeError, attribute: throwInnerTypeError, input: throwInnerTypeError, account: throwInnerTypeError, asset: throwInnerTypeError, contract: throwInnerTypeError, header: throwInnerTypeError, block: throwInnerTypeError, })); } else { sb.emitPushString(propertyName, typescript_1.default.isStringLiteral(propertyName) ? ts_utils_1.tsUtils.literal.getLiteralValue(propertyName) : `${ts_utils_1.tsUtils.literal.getLiteralValue(propertyName)}`); addStringProp(); sb.emitHelper(element, innerOptions, sb.helpers.getPropertyObjectProperty); } if (initializer !== undefined) { sb.emitHelper(node, innerOptions, sb.helpers.if({ condition: () => { sb.emitOp(node, 'DUP'); sb.emitHelper(node, innerOptions, sb.helpers.isUndefined); }, whenTrue: () => { sb.emitOp(node, 'DROP'); sb.visit(initializer, innerOptions); }, })); } if (typescript_1.default.isIdentifier(nameNode)) { sb.scope.set(sb, element, innerOptions, ts_utils_1.tsUtils.node.getText(nameNode)); } else if (typescript_1.default.isArrayBindingPattern(nameNode)) { sb.emitHelper(nameNode, innerOptions, sb.helpers.arrayBinding({ type: elementType })); } else { sb.emitHelper(nameNode, innerOptions, sb.helpers.objectBinding({ type: elementType })); } }); if (restElement === undefined) { sb.emitOp(node, 'DROP'); } else { const name = ts_utils_1.tsUtils.node.getNameOrThrow(restElement); sb.scope.add(name); sb.emitOp(node, 'NEWMAP'); sb.emitOp(node, 'SWAP'); sb.emitOp(node, 'DUP'); sb.emitHelper(node, innerOptions, sb.helpers.getSymbolObject); sb.emitOp(node, 'SWAP'); sb.emitHelper(node, innerOptions, sb.helpers.getPropertyObject); sb.emitPushInt(node, 3); sb.emitHelper(node, innerOptions, sb.helpers.packObject); sb.emitPushInt(node, 3); sb.emitOp(node, 'XTUCK'); sb.emitOp(restElement, 'ROT'); sb.emitOp(restElement, 'ROT'); sb.emitHelper(restElement, innerOptions, sb.helpers.omitObjectProperties); sb.scope.set(sb, restElement, innerOptions, name); } }; const options = sb.pushValueOptions(optionsIn); if (this.value !== undefined) { const builtinInterface = sb.context.builtins.getValueInterface(this.value); if (builtinInterface === undefined) { sb.visit(this.value, options); } else { createProcessBuiltin(builtinInterface, true)(options); return; } } sb.emitHelper(node, options, sb.helpers.forBuiltinType({ type: this.type, knownType: this.knownType, array: createProcessBuiltin('Array'), arrayStorage: createProcessBuiltin('ArrayStorage'), boolean: createProcessBuiltin('Boolean'), buffer: createProcessBuiltin('Buffer'), null: throwTypeError, number: createProcessBuiltin('Number'), object: processObject, string: createProcessBuiltin('String'), symbol: createProcessBuiltin('Symbol'), undefined: throwTypeError, 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.ObjectBindingHelper = ObjectBindingHelper; //# sourceMappingURL=ObjectBindingHelper.js.map