UNPKG

@neo-one/smart-contract-compiler

Version:

NEO•ONE TypeScript smart contract compiler.

117 lines (115 loc) 5.33 kB
import { tsUtils } from '@neo-one/ts-utils'; import ts from 'typescript'; import { DiagnosticCode } from '../../DiagnosticCode'; import { DiagnosticMessage } from '../../DiagnosticMessage'; import { isBuiltinInstanceMemberValue, isBuiltinMemberValue } from '../builtins'; import { NodeCompiler } from '../NodeCompiler'; export class PropertyAccessExpressionCompiler extends NodeCompiler { constructor() { super(...arguments); this.kind = ts.SyntaxKind.PropertyAccessExpression; } visitNode(sb, expr, optionsIn) { const isOptionalChain = ts.isOptionalChain(expr); const value = tsUtils.expression.getExpression(expr); const valueType = sb.context.analysis.getType(value); const name = tsUtils.node.getNameNode(expr); const nameValue = tsUtils.node.getName(expr); const handleBuiltin = (member, visited) => { if (isBuiltinInstanceMemberValue(member)) { member.emitValue(sb, expr, optionsIn, visited); return; } if (isBuiltinMemberValue(member)) { member.emitValue(sb, expr, optionsIn); return; } if (optionsIn.setValue) { sb.context.reportError(name, DiagnosticCode.InvalidBuiltinModify, DiagnosticMessage.CannotModifyBuiltin); } else { sb.context.reportError(name, DiagnosticCode.InvalidBuiltinReference, 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'), })); } } //# sourceMappingURL=PropertyAccessExpressionCompiler.js.map