ember-source
Version:
A JavaScript framework for creating ambitious web applications
1,526 lines (1,518 loc) • 29.8 kB
JavaScript
import '@glimmer/util';
import { Op, MachineOp } from '@glimmer/vm';
/* This file is generated by build/debug.js */
function opcodeMetadata(op, isMachine) {
let value = isMachine ? MACHINE_METADATA[op] : METADATA[op];
return value || null;
}
const METADATA = new Array(Op.Size).fill(null);
const MACHINE_METADATA = new Array(Op.Size).fill(null);
MACHINE_METADATA[MachineOp.PushFrame] = {
name: 'PushFrame',
mnemonic: 'pushf',
before: null,
stackChange: 2,
ops: [],
operands: 0,
check: true
};
MACHINE_METADATA[MachineOp.PopFrame] = {
name: 'PopFrame',
mnemonic: 'popf',
before: null,
stackChange: -2,
ops: [],
operands: 0,
check: false
};
MACHINE_METADATA[MachineOp.InvokeVirtual] = {
name: 'InvokeVirtual',
mnemonic: 'vcall',
before: null,
stackChange: -1,
ops: [],
operands: 0,
check: true
};
MACHINE_METADATA[MachineOp.InvokeStatic] = {
name: 'InvokeStatic',
mnemonic: 'scall',
before: null,
stackChange: 0,
ops: [{
name: 'offset',
type: 'u32'
}],
operands: 1,
check: true
};
MACHINE_METADATA[MachineOp.Jump] = {
name: 'Jump',
mnemonic: 'goto',
before: null,
stackChange: 0,
ops: [{
name: 'to',
type: 'u32'
}],
operands: 1,
check: true
};
MACHINE_METADATA[MachineOp.Return] = {
name: 'Return',
mnemonic: 'ret',
before: null,
stackChange: 0,
ops: [],
operands: 0,
check: false
};
MACHINE_METADATA[MachineOp.ReturnTo] = {
name: 'ReturnTo',
mnemonic: 'setra',
before: null,
stackChange: 0,
ops: [{
name: 'offset',
type: 'i32'
}],
operands: 1,
check: true
};
METADATA[Op.Helper] = {
name: 'Helper',
mnemonic: 'ncall',
before: null,
stackChange: null,
ops: [{
name: 'helper',
type: 'handle'
}],
operands: 1,
check: true
};
METADATA[Op.DynamicHelper] = {
name: 'DynamicHelper',
mnemonic: 'dynamiccall',
before: null,
stackChange: null,
ops: [],
operands: 0,
check: true
};
METADATA[Op.SetNamedVariables] = {
name: 'SetNamedVariables',
mnemonic: 'vsargs',
before: null,
stackChange: 0,
ops: [{
name: 'register',
type: 'u32'
}],
operands: 1,
check: true
};
METADATA[Op.SetBlocks] = {
name: 'SetBlocks',
mnemonic: 'vbblocks',
before: null,
stackChange: 0,
ops: [{
name: 'register',
type: 'u32'
}],
operands: 1,
check: true
};
METADATA[Op.SetVariable] = {
name: 'SetVariable',
mnemonic: 'sbvar',
before: null,
stackChange: -1,
ops: [{
name: 'symbol',
type: 'u32'
}],
operands: 1,
check: true
};
METADATA[Op.SetBlock] = {
name: 'SetBlock',
mnemonic: 'sblock',
before: null,
stackChange: -3,
ops: [{
name: 'symbol',
type: 'u32'
}],
operands: 1,
check: true
};
METADATA[Op.GetVariable] = {
name: 'GetVariable',
mnemonic: 'symload',
before: null,
stackChange: 1,
ops: [{
name: 'symbol',
type: 'u32'
}],
operands: 1,
check: true
};
METADATA[Op.GetProperty] = {
name: 'GetProperty',
mnemonic: 'getprop',
before: null,
stackChange: 0,
ops: [{
name: 'property',
type: 'str'
}],
operands: 1,
check: true
};
METADATA[Op.GetBlock] = {
name: 'GetBlock',
mnemonic: 'blockload',
before: null,
stackChange: 1,
ops: [{
name: 'block',
type: 'u32'
}],
operands: 1,
check: true
};
METADATA[Op.SpreadBlock] = {
name: 'SpreadBlock',
mnemonic: 'blockspread',
before: null,
stackChange: 2,
ops: [],
operands: 0,
check: true
};
METADATA[Op.HasBlock] = {
name: 'HasBlock',
mnemonic: 'hasblockload',
before: null,
stackChange: 0,
ops: [],
operands: 0,
check: true
};
METADATA[Op.HasBlockParams] = {
name: 'HasBlockParams',
mnemonic: 'hasparamsload',
before: null,
stackChange: -2,
ops: [],
operands: 0,
check: true
};
METADATA[Op.Concat] = {
name: 'Concat',
mnemonic: 'concat',
before: null,
stackChange: null,
ops: [{
name: 'count',
type: 'u32'
}],
operands: 1,
check: true
};
METADATA[Op.IfInline] = {
name: 'IfInline',
mnemonic: 'ifinline',
before: null,
stackChange: -2,
ops: [{
name: 'count',
type: 'u32'
}],
operands: 1,
check: true
};
METADATA[Op.Not] = {
name: 'Not',
mnemonic: 'not',
before: null,
stackChange: 0,
ops: [{
name: 'count',
type: 'u32'
}],
operands: 1,
check: true
};
METADATA[Op.Constant] = {
name: 'Constant',
mnemonic: 'rconstload',
before: null,
stackChange: 1,
ops: [{
name: 'constant',
type: 'unknown'
}],
operands: 1,
check: true
};
METADATA[Op.ConstantReference] = {
name: 'ConstantReference',
mnemonic: 'rconstrefload',
before: null,
stackChange: 1,
ops: [{
name: 'constant',
type: 'unknown'
}],
operands: 1,
check: true
};
METADATA[Op.Primitive] = {
name: 'Primitive',
mnemonic: 'pconstload',
before: null,
stackChange: 1,
ops: [{
name: 'constant',
type: 'primitive'
}],
operands: 1,
check: true
};
METADATA[Op.PrimitiveReference] = {
name: 'PrimitiveReference',
mnemonic: 'ptoref',
before: null,
stackChange: 0,
ops: [],
operands: 0,
check: true
};
METADATA[Op.ReifyU32] = {
name: 'ReifyU32',
mnemonic: 'reifyload',
before: null,
stackChange: 1,
ops: [],
operands: 0,
check: true
};
METADATA[Op.Dup] = {
name: 'Dup',
mnemonic: 'dup',
before: null,
stackChange: 1,
ops: [{
name: 'register',
type: 'u32'
}, {
name: 'offset',
type: 'u32'
}],
operands: 2,
check: true
};
METADATA[Op.Pop] = {
name: 'Pop',
mnemonic: 'pop',
before: null,
stackChange: 0,
ops: [{
name: 'count',
type: 'u32'
}],
operands: 1,
check: false
};
METADATA[Op.Load] = {
name: 'Load',
mnemonic: 'put',
before: null,
stackChange: -1,
ops: [{
name: 'register',
type: 'u32'
}],
operands: 1,
check: true
};
METADATA[Op.Fetch] = {
name: 'Fetch',
mnemonic: 'regload',
before: null,
stackChange: 1,
ops: [{
name: 'register',
type: 'u32'
}],
operands: 1,
check: true
};
METADATA[Op.RootScope] = {
name: 'RootScope',
mnemonic: 'rscopepush',
before: null,
stackChange: 0,
ops: [{
name: 'symbols',
type: 'u32'
}],
operands: 1,
check: true
};
METADATA[Op.VirtualRootScope] = {
name: 'VirtualRootScope',
mnemonic: 'vrscopepush',
before: null,
stackChange: 0,
ops: [{
name: 'register',
type: 'u32'
}],
operands: 1,
check: true
};
METADATA[Op.ChildScope] = {
name: 'ChildScope',
mnemonic: 'cscopepush',
before: null,
stackChange: 0,
ops: [],
operands: 0,
check: true
};
METADATA[Op.PopScope] = {
name: 'PopScope',
mnemonic: 'scopepop',
before: null,
stackChange: 0,
ops: [],
operands: 0,
check: true
};
METADATA[Op.Text] = {
name: 'Text',
mnemonic: 'apnd_text',
before: null,
stackChange: 0,
ops: [{
name: 'contents',
type: 'str'
}],
operands: 1,
check: true
};
METADATA[Op.Comment] = {
name: 'Comment',
mnemonic: 'apnd_comment',
before: null,
stackChange: 0,
ops: [{
name: 'contents',
type: 'str'
}],
operands: 1,
check: true
};
METADATA[Op.AppendHTML] = {
name: 'AppendHTML',
mnemonic: 'apnd_dynhtml',
before: null,
stackChange: -1,
ops: [],
operands: 0,
check: true
};
METADATA[Op.AppendSafeHTML] = {
name: 'AppendSafeHTML',
mnemonic: 'apnd_dynshtml',
before: null,
stackChange: -1,
ops: [],
operands: 0,
check: true
};
METADATA[Op.AppendDocumentFragment] = {
name: 'AppendDocumentFragment',
mnemonic: 'apnd_dynfrag',
before: null,
stackChange: -1,
ops: [],
operands: 0,
check: true
};
METADATA[Op.AppendNode] = {
name: 'AppendNode',
mnemonic: 'apnd_dynnode',
before: null,
stackChange: -1,
ops: [],
operands: 0,
check: true
};
METADATA[Op.AppendText] = {
name: 'AppendText',
mnemonic: 'apnd_dyntext',
before: null,
stackChange: -1,
ops: [],
operands: 0,
check: true
};
METADATA[Op.OpenElement] = {
name: 'OpenElement',
mnemonic: 'apnd_tag',
before: null,
stackChange: 0,
ops: [{
name: 'tag',
type: 'str'
}],
operands: 1,
check: true
};
METADATA[Op.OpenDynamicElement] = {
name: 'OpenDynamicElement',
mnemonic: 'apnd_dyntag',
before: null,
stackChange: -1,
ops: [],
operands: 0,
check: true
};
METADATA[Op.PushRemoteElement] = {
name: 'PushRemoteElement',
mnemonic: 'apnd_remotetag',
before: null,
stackChange: -3,
ops: [],
operands: 0,
check: true
};
METADATA[Op.StaticAttr] = {
name: 'StaticAttr',
mnemonic: 'apnd_attr',
before: null,
stackChange: 0,
ops: [{
name: 'name',
type: 'str'
}, {
name: 'value',
type: 'str'
}, {
name: 'namespace',
type: 'option-str'
}],
operands: 3,
check: true
};
METADATA[Op.DynamicAttr] = {
name: 'DynamicAttr',
mnemonic: 'apnd_dynattr',
before: null,
stackChange: -1,
ops: [{
name: 'name',
type: 'str'
}, {
name: 'trusting',
type: 'bool'
}, {
name: 'namespace',
type: 'option-str'
}],
operands: 3,
check: true
};
METADATA[Op.ComponentAttr] = {
name: 'ComponentAttr',
mnemonic: 'apnd_cattr',
before: null,
stackChange: -1,
ops: [{
name: 'name',
type: 'str'
}, {
name: 'trusting',
type: 'bool'
}, {
name: 'namespace',
type: 'option-str'
}],
operands: 3,
check: true
};
METADATA[Op.FlushElement] = {
name: 'FlushElement',
mnemonic: 'apnd_flushtag',
before: null,
stackChange: 0,
ops: [],
operands: 0,
check: true
};
METADATA[Op.CloseElement] = {
name: 'CloseElement',
mnemonic: 'apnd_closetag',
before: null,
stackChange: 0,
ops: [],
operands: 0,
check: true
};
METADATA[Op.PopRemoteElement] = {
name: 'PopRemoteElement',
mnemonic: 'apnd_closeremotetag',
before: null,
stackChange: 0,
ops: [],
operands: 0,
check: true
};
METADATA[Op.Modifier] = {
name: 'Modifier',
mnemonic: 'apnd_modifier',
before: null,
stackChange: -1,
ops: [{
name: 'helper',
type: 'handle'
}],
operands: 1,
check: true
};
METADATA[Op.BindDynamicScope] = {
name: 'BindDynamicScope',
mnemonic: 'setdynscope',
before: null,
stackChange: null,
ops: [{
name: 'names',
type: 'str-array'
}],
operands: 1,
check: true
};
METADATA[Op.PushDynamicScope] = {
name: 'PushDynamicScope',
mnemonic: 'dynscopepush',
before: null,
stackChange: 0,
ops: [],
operands: 0,
check: true
};
METADATA[Op.PopDynamicScope] = {
name: 'PopDynamicScope',
mnemonic: 'dynscopepop',
before: null,
stackChange: 0,
ops: [],
operands: 0,
check: true
};
METADATA[Op.CompileBlock] = {
name: 'CompileBlock',
mnemonic: 'cmpblock',
before: null,
stackChange: 0,
ops: [],
operands: 0,
check: true
};
METADATA[Op.PushBlockScope] = {
name: 'PushBlockScope',
mnemonic: 'scopeload',
before: null,
stackChange: 1,
ops: [{
name: 'scope',
type: 'scope'
}],
operands: 1,
check: true
};
METADATA[Op.PushSymbolTable] = {
name: 'PushSymbolTable',
mnemonic: 'dsymload',
before: null,
stackChange: 1,
ops: [{
name: 'table',
type: 'symbol-table'
}],
operands: 1,
check: true
};
METADATA[Op.InvokeYield] = {
name: 'InvokeYield',
mnemonic: 'invokeyield',
before: null,
stackChange: null,
ops: [],
operands: 0,
check: true
};
METADATA[Op.JumpIf] = {
name: 'JumpIf',
mnemonic: 'iftrue',
before: null,
stackChange: -1,
ops: [{
name: 'to',
type: 'u32'
}],
operands: 1,
check: true
};
METADATA[Op.JumpUnless] = {
name: 'JumpUnless',
mnemonic: 'iffalse',
before: null,
stackChange: -1,
ops: [{
name: 'to',
type: 'u32'
}],
operands: 1,
check: true
};
METADATA[Op.JumpEq] = {
name: 'JumpEq',
mnemonic: 'ifeq',
before: null,
stackChange: 0,
ops: [{
name: 'to',
type: 'i32'
}, {
name: 'comparison',
type: 'i32'
}],
operands: 2,
check: true
};
METADATA[Op.AssertSame] = {
name: 'AssertSame',
mnemonic: 'assert_eq',
before: null,
stackChange: 0,
ops: [],
operands: 0,
check: true
};
METADATA[Op.Enter] = {
name: 'Enter',
mnemonic: 'blk_start',
before: null,
stackChange: 0,
ops: [{
name: 'args',
type: 'u32'
}],
operands: 1,
check: true
};
METADATA[Op.Exit] = {
name: 'Exit',
mnemonic: 'blk_end',
before: null,
stackChange: 0,
ops: [],
operands: 0,
check: true
};
METADATA[Op.ToBoolean] = {
name: 'ToBoolean',
mnemonic: 'anytobool',
before: null,
stackChange: 0,
ops: [],
operands: 0,
check: true
};
METADATA[Op.EnterList] = {
name: 'EnterList',
mnemonic: 'list_start',
before: null,
stackChange: null,
ops: [{
name: 'address',
type: 'u32'
}, {
name: 'address',
type: 'u32'
}],
operands: 2,
check: true
};
METADATA[Op.ExitList] = {
name: 'ExitList',
mnemonic: 'list_end',
before: null,
stackChange: 0,
ops: [],
operands: 0,
check: true
};
METADATA[Op.Iterate] = {
name: 'Iterate',
mnemonic: 'iter',
before: null,
stackChange: 0,
ops: [{
name: 'end',
type: 'u32'
}],
operands: 1,
check: false
};
METADATA[Op.Main] = {
name: 'Main',
mnemonic: 'main',
before: null,
stackChange: -2,
ops: [{
name: 'state',
type: 'register'
}],
operands: 1,
check: true
};
METADATA[Op.ContentType] = {
name: 'ContentType',
mnemonic: 'ctload',
before: null,
stackChange: 1,
ops: [],
operands: 0,
check: true
};
METADATA[Op.DynamicContentType] = {
name: 'DynamicContentType',
mnemonic: 'dctload',
before: null,
stackChange: 1,
ops: [],
operands: 0,
check: true
};
METADATA[Op.Curry] = {
name: 'Curry',
mnemonic: 'curry',
before: null,
stackChange: null,
ops: [{
name: 'type',
type: 'u32'
}, {
name: 'is-strict',
type: 'bool'
}],
operands: 2,
check: true
};
METADATA[Op.PushComponentDefinition] = {
name: 'PushComponentDefinition',
mnemonic: 'cmload',
before: null,
stackChange: 1,
ops: [{
name: 'spec',
type: 'handle'
}],
operands: 1,
check: true
};
METADATA[Op.PushDynamicComponentInstance] = {
name: 'PushDynamicComponentInstance',
mnemonic: 'dciload',
before: null,
stackChange: 0,
ops: [],
operands: 0,
check: true
};
METADATA[Op.ResolveDynamicComponent] = {
name: 'ResolveDynamicComponent',
mnemonic: 'cdload',
before: null,
stackChange: 0,
ops: [{
name: 'owner',
type: 'owner'
}],
operands: 1,
check: true
};
METADATA[Op.PushArgs] = {
name: 'PushArgs',
mnemonic: 'argsload',
before: null,
stackChange: null,
ops: [{
name: 'names',
type: 'str-array'
}, {
name: 'block-names',
type: 'str-array'
}, {
name: 'flags',
type: 'u32'
}],
operands: 3,
check: true
};
METADATA[Op.PushEmptyArgs] = {
name: 'PushEmptyArgs',
mnemonic: 'emptyargsload',
before: null,
stackChange: 1,
ops: [],
operands: 0,
check: true
};
METADATA[Op.PopArgs] = {
name: 'PopArgs',
mnemonic: 'argspop',
before: null,
stackChange: null,
ops: [],
operands: 0,
check: true
};
METADATA[Op.PrepareArgs] = {
name: 'PrepareArgs',
mnemonic: 'argsprep',
before: null,
stackChange: 0,
ops: [{
name: 'state',
type: 'register'
}],
operands: 1,
check: false
};
METADATA[Op.CaptureArgs] = {
name: 'CaptureArgs',
mnemonic: 'argscapture',
before: null,
stackChange: 0,
ops: [],
operands: 0,
check: true
};
METADATA[Op.CreateComponent] = {
name: 'CreateComponent',
mnemonic: 'comp_create',
before: null,
stackChange: 0,
ops: [{
name: 'flags',
type: 'u32'
}, {
name: 'state',
type: 'register'
}],
operands: 2,
check: true
};
METADATA[Op.RegisterComponentDestructor] = {
name: 'RegisterComponentDestructor',
mnemonic: 'comp_dest',
before: null,
stackChange: 0,
ops: [{
name: 'state',
type: 'register'
}],
operands: 1,
check: true
};
METADATA[Op.PutComponentOperations] = {
name: 'PutComponentOperations',
mnemonic: 'comp_elops',
before: null,
stackChange: 0,
ops: [],
operands: 0,
check: true
};
METADATA[Op.GetComponentSelf] = {
name: 'GetComponentSelf',
mnemonic: 'comp_selfload',
before: null,
stackChange: 1,
ops: [{
name: 'state',
type: 'register'
}],
operands: 1,
check: true
};
METADATA[Op.GetComponentTagName] = {
name: 'GetComponentTagName',
mnemonic: 'comp_tagload',
before: null,
stackChange: 1,
ops: [{
name: 'state',
type: 'register'
}],
operands: 1,
check: true
};
METADATA[Op.GetComponentLayout] = {
name: 'GetComponentLayout',
mnemonic: 'comp_layoutload',
before: null,
stackChange: 2,
ops: [{
name: 'state',
type: 'register'
}],
operands: 1,
check: true
};
METADATA[Op.BindEvalScope] = {
name: 'BindEvalScope',
mnemonic: 'eval_scope',
before: null,
stackChange: 0,
ops: [{
name: 'state',
type: 'register'
}],
operands: 1,
check: true
};
METADATA[Op.SetupForEval] = {
name: 'SetupForEval',
mnemonic: 'eval_setup',
before: null,
stackChange: 0,
ops: [{
name: 'state',
type: 'register'
}],
operands: 1,
check: true
};
METADATA[Op.PopulateLayout] = {
name: 'PopulateLayout',
mnemonic: 'comp_layoutput',
before: null,
stackChange: -2,
ops: [{
name: 'state',
type: 'register'
}],
operands: 1,
check: true
};
METADATA[Op.InvokeComponentLayout] = {
name: 'InvokeComponentLayout',
mnemonic: 'comp_invokelayout',
before: null,
stackChange: 0,
ops: [{
name: 'state',
type: 'register'
}],
operands: 1,
check: true
};
METADATA[Op.BeginComponentTransaction] = {
name: 'BeginComponentTransaction',
mnemonic: 'comp_begin',
before: null,
stackChange: 0,
ops: [],
operands: 0,
check: true
};
METADATA[Op.CommitComponentTransaction] = {
name: 'CommitComponentTransaction',
mnemonic: 'comp_commit',
before: null,
stackChange: 0,
ops: [],
operands: 0,
check: true
};
METADATA[Op.DidCreateElement] = {
name: 'DidCreateElement',
mnemonic: 'comp_created',
before: null,
stackChange: 0,
ops: [{
name: 'state',
type: 'register'
}],
operands: 1,
check: true
};
METADATA[Op.DidRenderLayout] = {
name: 'DidRenderLayout',
mnemonic: 'comp_rendered',
before: null,
stackChange: 0,
ops: [{
name: 'state',
type: 'register'
}],
operands: 1,
check: true
};
METADATA[Op.ResolveMaybeLocal] = {
name: 'ResolveMaybeLocal',
mnemonic: 'eval_varload',
before: null,
stackChange: 1,
ops: [{
name: 'local',
type: 'str'
}],
operands: 1,
check: true
};
METADATA[Op.Debugger] = {
name: 'Debugger',
mnemonic: 'debugger',
before: null,
stackChange: 0,
ops: [{
name: 'symbols',
type: 'str-array'
}, {
name: 'debugInfo',
type: 'array'
}],
operands: 2,
check: true
};
function debugSlice(context, start, end) {
}
function logOpcode(type, params) {
}
function debug(c, op, isMachine) {
return undefined;
}
// TODO: How do these map onto constant and machine types?
const OPERAND_TYPES = ['u32', 'i32', 'owner', 'handle', 'str', 'option-str', 'array', 'str-array', 'bool', 'primitive', 'register', 'unknown', 'symbol-table', 'scope'];
function isOperandType(s) {
return OPERAND_TYPES.indexOf(s) !== -1;
}
function normalize(key, input) {
let name;
if (input.format === undefined) {
throw new Error(`Missing format in ${JSON.stringify(input)}`);
}
if (Array.isArray(input.format)) {
name = input.format[0];
} else {
name = input.format;
}
let ops = Array.isArray(input.format) ? operands(input.format.slice(1)) : [];
return {
name,
mnemonic: key,
before: null,
stackChange: stackChange(input['operand-stack']),
ops,
operands: ops.length,
check: input.skip === true ? false : true
};
}
function stackChange(stack) {
if (stack === undefined) {
return 0;
}
let before = stack[0];
let after = stack[1];
if (hasRest(before) || hasRest(after)) {
return null;
}
return after.length - before.length;
}
function hasRest(input) {
if (!Array.isArray(input)) {
throw new Error(`Unexpected stack entry: ${JSON.stringify(input)}`);
}
return input.some(s => s.slice(-3) === '...');
}
function operands(input) {
if (!Array.isArray(input)) {
throw new Error(`Expected operands array, got ${JSON.stringify(input)}`);
}
return input.map(op);
}
function op(input) {
let [name, type] = input.split(':');
if (isOperandType(type)) {
return {
name,
type
};
} else {
throw new Error(`Expected operand, found ${JSON.stringify(input)}`);
}
}
function normalizeAll(parsed) {
let machine = normalizeParsed(parsed.machine);
let syscall = normalizeParsed(parsed.syscall);
return {
machine,
syscall
};
}
function normalizeParsed(parsed) {
let out = Object.create(null);
for (const [key, value] of Object.entries(parsed)) {
out[key] = normalize(key, value);
}
return out;
}
function buildEnum(name, parsed, offset, max) {
let e = [`export enum ${name} {`];
let last;
Object.values(parsed).forEach((value, i) => {
e.push(` ${value.name} = ${offset + i},`);
last = i;
});
e.push(` Size = ${last + offset + 1},`);
e.push('}');
let enumString = e.join('\n');
let predicate;
if (max) {
predicate = strip`
export function is${name}(value: number): value is ${name} {
return value >= ${offset} && value <= ${max};
}
`;
} else {
predicate = strip`
export function is${name}(value: number): value is ${name} {
return value >= ${offset};
}
`;
}
return {
enumString,
predicate
};
}
function strip(strings, ...args) {
let out = '';
for (let i = 0; i < strings.length; i++) {
let string = strings[i];
let dynamic = args[i] !== undefined ? String(args[i]) : '';
out += `${string}${dynamic}`;
}
// eslint-disable-next-line regexp/no-super-linear-backtracking
out = /^\s*?\n?([\s\S]*?)\s*$/u.exec(out)[1];
let min = Number.MAX_SAFE_INTEGER;
for (let line of out.split('\n')) {
let leading = /^\s*/u.exec(line)[0].length;
min = Math.min(min, leading);
}
let stripped = '';
for (let line of out.split('\n')) {
stripped += line.slice(min) + '\n';
}
return stripped;
}
const META_KIND = ['METADATA', 'MACHINE_METADATA'];
function buildSingleMeta(kind, all, key) {
let e = kind === 'MACHINE_METADATA' ? 'MachineOp' : 'Op';
return `${kind}[${e}.${all[key].name}] = ${stringify(all[key], 0)};`;
}
function stringify(o, pad) {
if (typeof o !== 'object' || o === null) {
if (typeof o === 'string') {
return `'${o}'`;
}
return JSON.stringify(o);
}
if (Array.isArray(o)) {
return `[${o.map(v => stringify(v, pad)).join(', ')}]`;
}
let out = ['{'];
for (let key of Object.keys(o)) {
out.push(`${' '.repeat(pad + 2)}${key}: ${stringify(o[key], pad + 2)},`);
}
out.push(`${' '.repeat(pad)}}`);
return out.join('\n');
}
function buildMetas(kind, all) {
let out = [];
for (let key of Object.keys(all)) {
out.push(buildSingleMeta(kind, all, key));
}
return out.join('\n\n');
}
function wrap(checker) {
class Wrapped {
validate(value) {
return checker().validate(value);
}
expected() {
return checker().expected();
}
}
return new Wrapped();
}
class TypeofChecker {
constructor(expectedType) {
this.expectedType = expectedType;
}
validate(value) {
return typeof value === this.expectedType;
}
expected() {
return `typeof ${this.expectedType}`;
}
}
class PrimitiveChecker {
validate(value) {
return typeof value !== 'string' || typeof value === 'number' || typeof value === 'string' || value === undefined || value === null;
}
expected() {
return `a primitive`;
}
}
class NullChecker {
validate(value) {
return value === null;
}
expected() {
return `null`;
}
}
class UndefinedChecker {
validate(value) {
return value === undefined;
}
expected() {
return `undefined`;
}
}
class InstanceofChecker {
constructor(Class) {
this.Class = Class;
}
validate(value) {
return value ? value instanceof this.Class : false;
}
expected() {
return `an instance of ${this.Class.name}`;
}
}
class OptionChecker {
constructor(checker, emptyValue) {
this.checker = checker;
this.emptyValue = emptyValue;
}
validate(value) {
if (value === this.emptyValue) return true;
return this.checker.validate(value);
}
expected() {
return `${this.checker.expected()} or null`;
}
}
class MaybeChecker {
constructor(checker) {
this.checker = checker;
}
validate(value) {
if (value === null || value === undefined) return true;
return this.checker.validate(value);
}
expected() {
return `${this.checker.expected()} or null or undefined`;
}
}
class OrChecker {
constructor(left, right) {
this.left = left;
this.right = right;
}
validate(value) {
return this.left.validate(value) || this.right.validate(value);
}
expected() {
return `${this.left.expected()} or ${this.right.expected()}`;
}
}
class ExactValueChecker {
constructor(value, desc) {
this.value = value;
this.desc = desc;
}
validate(obj) {
return obj === this.value;
}
expected() {
return this.desc;
}
}
class PropertyChecker {
constructor(checkers) {
this.checkers = checkers;
}
validate(obj) {
if (typeof obj !== 'object') return false;
if (obj === null || obj === undefined) return false;
return Object.entries(this.checkers).every(([k, checker]) => k in obj ? checker.validate(obj[k]) : false);
}
expected() {
let pairs = Object.entries(this.checkers).map(([k, checker]) => {
return `${k}: ${checker.expected()}`;
});
return `{ ${pairs.join(',')} }`;
}
}
class ArrayChecker {
constructor(checker) {
this.checker = checker;
}
validate(obj) {
if (obj === null || obj === undefined) return false;
if (!Array.isArray(obj)) return false;
return obj.every(item => this.checker.validate(item));
}
expected() {
return `Array<${this.checker.expected()}>`;
}
}
class DictChecker {
constructor(checker) {
this.checker = checker;
}
validate(value) {
let isDict = typeof value === 'object' && value !== null && Object.getPrototypeOf(value) === null;
if (!isDict) return false;
let {
checker
} = this;
for (let key in value) {
if (!checker.validate(value[key])) {
return false;
}
}
return true;
}
expected() {
return `a primitive`;
}
}
class OpaqueChecker {
type;
validate(_obj) {
return true;
}
expected() {
return `any`;
}
}
class ObjectChecker {
validate(obj) {
return typeof obj === 'function' || typeof obj === 'object' && obj !== null;
}
expected() {
return `an object or function (valid WeakMap key)`;
}
}
class SafeStringChecker {
validate(value) {
return typeof value === 'object' && value !== null && typeof value.toHTML === 'function';
}
expected() {
return `SafeString`;
}
}
function CheckInstanceof(Class) {
return new InstanceofChecker(Class);
}
function CheckOption(checker) {
return new OptionChecker(checker, null);
}
function CheckMaybe(checker) {
return new MaybeChecker(checker);
}
function CheckInterface(obj) {
return new PropertyChecker(obj);
}
function CheckArray(obj) {
return new ArrayChecker(obj);
}
function CheckDict(obj) {
return new DictChecker(obj);
}
function defaultMessage(value, expected) {
return `Got ${value}, expected:\n${expected}`;
}
function check(value, checker, message = defaultMessage) {
if (typeof checker === 'function') {
checker(value);
return value;
}
if (checker.validate(value)) {
return value;
} else {
throw new Error(message(value, checker.expected()));
}
}
let size = 0;
function recordStackSize(sp) {
size = sp;
}
function expectStackChange(stack, expected, name) {
let actual = stack.sp - size;
if (actual === expected) return;
throw new Error(`Expected stack to change by ${expected}, but it changed by ${actual} in ${name}`);
}
const CheckPrimitive = new PrimitiveChecker();
const CheckFunction = new TypeofChecker('function');
const CheckNumber = new TypeofChecker('number');
const CheckBoolean = new TypeofChecker('boolean');
const CheckHandle = CheckNumber;
const CheckString = new TypeofChecker('string');
const CheckNull = new NullChecker();
const CheckUndefined = new UndefinedChecker();
const CheckUnknown = new OpaqueChecker();
const CheckSafeString = new SafeStringChecker();
const CheckObject = new ObjectChecker();
function CheckOr(left, right) {
return new OrChecker(left, right);
}
function CheckValue(value, desc = String(value)) {
return new ExactValueChecker(value, desc);
}
const CheckBlockSymbolTable = CheckInterface({
parameters: CheckArray(CheckNumber)
});
const CheckProgramSymbolTable = CheckInterface({
hasEval: CheckBoolean,
symbols: CheckArray(CheckString)
});
const CheckElement = CheckInterface({
nodeType: CheckValue(1),
tagName: CheckString,
nextSibling: CheckUnknown
});
const CheckDocumentFragment = CheckInterface({
nodeType: CheckValue(11),
nextSibling: CheckUnknown
});
const CheckNode = CheckInterface({
nodeType: CheckNumber,
nextSibling: CheckUnknown
});
export { CheckArray, CheckBlockSymbolTable, CheckBoolean, CheckDict, CheckDocumentFragment, CheckElement, CheckFunction, CheckHandle, CheckInstanceof, CheckInterface, CheckMaybe, CheckNode, CheckNull, CheckNumber, CheckObject, CheckOption, CheckOr, CheckPrimitive, CheckProgramSymbolTable, CheckSafeString, CheckString, CheckUndefined, CheckUnknown, CheckValue, META_KIND, OPERAND_TYPES, buildEnum, buildMetas, buildSingleMeta, check, debug, debugSlice, expectStackChange, logOpcode, normalize, normalizeAll, normalizeParsed, opcodeMetadata, recordStackSize, strip, wrap };