UNPKG

ember-legacy-class-transform

Version:
211 lines 6.82 kB
import { CONSTANT_TAG, isConst, isModified, ReferenceCache, ConstReference } from '@glimmer/reference'; import { initializeGuid } from '@glimmer/util'; import { APPEND_OPCODES, UpdatingOpcode } from '../../opcodes'; import { FALSE_REFERENCE, NULL_REFERENCE, PrimitiveReference, TRUE_REFERENCE, UNDEFINED_REFERENCE } from '../../references'; APPEND_OPCODES.add(20 /* ChildScope */, vm => vm.pushChildScope()); APPEND_OPCODES.add(21 /* PopScope */, vm => vm.popScope()); APPEND_OPCODES.add(39 /* PushDynamicScope */, vm => vm.pushDynamicScope()); APPEND_OPCODES.add(40 /* PopDynamicScope */, vm => vm.popDynamicScope()); APPEND_OPCODES.add(12 /* Immediate */, (vm, { op1: number }) => { vm.stack.push(number); }); APPEND_OPCODES.add(13 /* Constant */, (vm, { op1: other }) => { vm.stack.push(vm.constants.getOther(other)); }); APPEND_OPCODES.add(14 /* PrimitiveReference */, (vm, { op1: primitive }) => { let stack = vm.stack; let flag = (primitive & 3 << 30) >>> 30; let value = primitive & ~(3 << 30); switch (flag) { case 0: stack.push(PrimitiveReference.create(value)); break; case 1: stack.push(PrimitiveReference.create(vm.constants.getFloat(value))); break; case 2: stack.push(PrimitiveReference.create(vm.constants.getString(value))); break; case 3: switch (value) { case 0: stack.push(FALSE_REFERENCE); break; case 1: stack.push(TRUE_REFERENCE); break; case 2: stack.push(NULL_REFERENCE); break; case 3: stack.push(UNDEFINED_REFERENCE); break; } break; } }); APPEND_OPCODES.add(15 /* Dup */, (vm, { op1: register, op2: offset }) => { let position = vm.fetchValue(register) - offset; vm.stack.dup(position); }); APPEND_OPCODES.add(16 /* Pop */, (vm, { op1: count }) => vm.stack.pop(count)); APPEND_OPCODES.add(17 /* Load */, (vm, { op1: register }) => vm.load(register)); APPEND_OPCODES.add(18 /* Fetch */, (vm, { op1: register }) => vm.fetch(register)); APPEND_OPCODES.add(38 /* BindDynamicScope */, (vm, { op1: _names }) => { let names = vm.constants.getArray(_names); vm.bindDynamicScope(names); }); APPEND_OPCODES.add(47 /* PushFrame */, vm => vm.pushFrame()); APPEND_OPCODES.add(48 /* PopFrame */, vm => vm.popFrame()); APPEND_OPCODES.add(49 /* Enter */, (vm, { op1: args }) => vm.enter(args)); APPEND_OPCODES.add(50 /* Exit */, vm => vm.exit()); APPEND_OPCODES.add(41 /* CompileDynamicBlock */, vm => { let stack = vm.stack; let block = stack.pop(); stack.push(block ? block.compileDynamic(vm.env) : null); }); APPEND_OPCODES.add(42 /* InvokeStatic */, (vm, { op1: _block }) => { let block = vm.constants.getBlock(_block); let compiled = block.compileStatic(vm.env); vm.call(compiled.handle); }); APPEND_OPCODES.add(43 /* InvokeDynamic */, (vm, { op1: _invoker }) => { let invoker = vm.constants.getOther(_invoker); let block = vm.stack.pop(); invoker.invoke(vm, block); }); APPEND_OPCODES.add(44 /* Jump */, (vm, { op1: target }) => vm.goto(target)); APPEND_OPCODES.add(45 /* JumpIf */, (vm, { op1: target }) => { let reference = vm.stack.pop(); if (isConst(reference)) { if (reference.value()) { vm.goto(target); } } else { let cache = new ReferenceCache(reference); if (cache.peek()) { vm.goto(target); } vm.updateWith(new Assert(cache)); } }); APPEND_OPCODES.add(46 /* JumpUnless */, (vm, { op1: target }) => { let reference = vm.stack.pop(); if (isConst(reference)) { if (!reference.value()) { vm.goto(target); } } else { let cache = new ReferenceCache(reference); if (!cache.peek()) { vm.goto(target); } vm.updateWith(new Assert(cache)); } }); APPEND_OPCODES.add(22 /* Return */, vm => vm.return()); APPEND_OPCODES.add(23 /* ReturnTo */, (vm, { op1: relative }) => { vm.returnTo(relative); }); export const ConstTest = function (ref, _env) { return new ConstReference(!!ref.value()); }; export const SimpleTest = function (ref, _env) { return ref; }; export const EnvironmentTest = function (ref, env) { return env.toConditionalReference(ref); }; APPEND_OPCODES.add(51 /* Test */, (vm, { op1: _func }) => { let stack = vm.stack; let operand = stack.pop(); let func = vm.constants.getFunction(_func); stack.push(func(operand, vm.env)); }); export class Assert extends UpdatingOpcode { constructor(cache) { super(); this.type = 'assert'; this.tag = cache.tag; this.cache = cache; } evaluate(vm) { let { cache } = this; if (isModified(cache.revalidate())) { vm.throw(); } } toJSON() { let { type, _guid, cache } = this; let expected; try { expected = JSON.stringify(cache.peek()); } catch (e) { expected = String(cache.peek()); } return { args: [], details: { expected }, guid: _guid, type }; } } export class JumpIfNotModifiedOpcode extends UpdatingOpcode { constructor(tag, target) { super(); this.target = target; this.type = 'jump-if-not-modified'; this.tag = tag; this.lastRevision = tag.value(); } evaluate(vm) { let { tag, target, lastRevision } = this; if (!vm.alwaysRevalidate && tag.validate(lastRevision)) { vm.goto(target); } } didModify() { this.lastRevision = this.tag.value(); } toJSON() { return { args: [JSON.stringify(this.target.inspect())], guid: this._guid, type: this.type }; } } export class DidModifyOpcode extends UpdatingOpcode { constructor(target) { super(); this.target = target; this.type = 'did-modify'; this.tag = CONSTANT_TAG; } evaluate() { this.target.didModify(); } } export class LabelOpcode { constructor(label) { this.tag = CONSTANT_TAG; this.type = 'label'; this.label = null; this.prev = null; this.next = null; initializeGuid(this); this.label = label; } evaluate() {} inspect() { return `${this.label} [${this._guid}]`; } toJSON() { return { args: [JSON.stringify(this.inspect())], guid: this._guid, type: this.type }; } }