ember-material-icons
Version:
Google Material icons for your ember-cli app
327 lines (276 loc) • 11.1 kB
text/typescript
import { Opaque, Option, Dict, Slice as ListSlice, initializeGuid, fillNulls } from '@glimmer/util';
import { RevisionTag, VersionedPathReference } from '@glimmer/reference';
import { VM, UpdatingVM } from './vm';
import { CompiledExpression, CompiledArgs } from './compiled/expressions';
import { NULL_REFERENCE, UNDEFINED_REFERENCE } from './references';
import { InlineBlock } from './scanner';
import { Opcode } from './environment';
export interface OpcodeJSON {
type: number | string;
guid?: Option<number>;
deopted?: boolean;
args?: string[];
details?: Dict<Option<string>>;
children?: OpcodeJSON[];
}
export function pretty(json: OpcodeJSON): string {
return `${json.type}(${json.args ? json.args.join(', ') : ''})`;
}
export const enum OpcodeName {
PushChildScope, // ()
PopScope, // ()
PushDynamicScope, // ()
PopDynamicScope, // ()
Put, // (ConstantReference)
EvaluatePut, // (ConstantExpression)
PutArgs, // (ConstantExpression)
BindPositionalArgs, //
BindNamedArgs, // (ConstantArray<string>, ConstantArray<number>)
BindBlocks, // (ConstantArray<string>, ConstantArray<number>)
BindPartialArgs, // (number)
BindCallerScope, // ()
BindDynamicScope, // (ConstantArray<string>)
Enter, // (ConstantSlice)
Exit, // ()
Evaluate, // (ConstantBlock)
Jump, // (number)
JumpIf, // (number)
JumpUnless, // (number)
Test, // (ConstantFunction)
OpenBlock, // (Other<CompiledGetBlock>, ConstantExpression)
CloseBlock, // ()
PutDynamicComponent, // ()
PutComponent, // (Other<ComponentDefinition>)
OpenComponent, // (ConstantExpression, ConstantBlock)
DidCreateElement, //
ShadowAttributes, // ()
DidRenderLayout, // ()
CloseComponent, // ()
Text, // (ConstantString)
Comment, // (ConstantString)
DynamicContent, // (Other<AppendDynamicOpcode>)
OpenElement, // (ConstantString)
PushRemoteElement, // ()
PopRemoteElement, // ()
OpenComponentElement, // (ConstantString)
OpenDynamicElement, // ()
FlushElement, // ()
CloseElement, // ()
PopElement, // ()
StaticAttr, // (ConstantString, ConstantString, ConstantString)
Modifier, // (ConstantString, ConstantOther<ModifierManager>, ConstantExpression)
DynamicAttrNS, // (ConstantString, ConstantString, number)
DynamicAttr, // (ConstantString, number)
PutIterator, // ()
EnterList, // (ConstantSlice)
ExitList, // ()
EnterWithKey, // (ConstantSlice)
NextIter, // (number)
PutDynamicPartial, // (Other<SymbolTable>)
PutPartial, // (Other<PartialDefinition>)
EvaluatePartial // (Other<SymbolTable>, Other<Dict<PartialBlock>>)
}
// export type OpcodeName =
// "PushChildScope" // ()
// | "PopScope" // ()
// | "PushDynamicScope" // ()
// | "PopDynamicScope" // ()
// | "Put" // (ConstantReference)
// | "EvaluatePut" // (ConstantExpression)
// | "PutArgs" // (ConstantExpression)
// | "BindPositionalArgs" //
// | "BindNamedArgs" // (ConstantArray<string>, ConstantArray<number>)
// | "BindBlocks" // (ConstantArray<string>, ConstantArray<number>)
// | "BindPartialArgs" // (number)
// | "BindCallerScope" // ()
// | "BindDynamicScope" // (ConstantArray<string>)
// | "Enter" // (ConstantSlice)
// | "Exit" // ()
// | "Evaluate" // (ConstantBlock)
// | "Jump" // (number)
// | "JumpIf" // (number)
// | "JumpUnless" // (number)
// | "Test" // (ConstantFunction)
// | "OpenBlock" // (Other<CompiledGetBlock>, ConstantExpression)
// | "CloseBlock" // ()
// | "PutDynamicComponent" // ()
// | "PutComponent" // (Other<ComponentDefinition>)
// | "OpenComponent" // (ConstantExpression, ConstantBlock)
// | "DidCreateElement" //
// | "ShadowAttributes" // ()
// | "DidRenderLayout" // ()
// | "CloseComponent" // ()
// | "Text" // (ConstantString)
// | "Comment" // (ConstantString)
// | "DynamicContent" // (Other<AppendDynamicOpcode>)
// | "OpenElement" // (ConstantString)
// | "PushRemoteElement" // ()
// | "PopRemoteElement" // ()
// | "OpenComponentElement" // (ConstantString)
// | "OpenDynamicElement" // ()
// | "FlushElement" // ()
// | "CloseElement" // ()
// | "PopElement" // ()
// | "StaticAttr" // (ConstantString, ConstantString, ConstantString)
// | "Modifier" // (ConstantString, ConstantOther<ModifierManager>, ConstantExpression)
// | "DynamicAttrNS" // (ConstantString, ConstantString, number)
// | "DynamicAttr" // (ConstantString, number)
// | "PutIterator" // ()
// | "EnterList" // (ConstantSlice)
// | "ExitList" // ()
// | "EnterWithKey" // (ConstantSlice)
// | "NextIter" // (number)
// | "PutDynamicPartial" // (Other<SymbolTable>)
// | "PutPartial" // (Other<PartialDefinition>)
// | "EvaluatePartial" // (Other<SymbolTable>, Other<Dict<PartialBlock>>)
// ;
export type ConstantType = 'slice' | 'block' | 'reference' | 'string' | 'number' | 'expression';
export type ConstantReference = number;
export type ConstantString = number;
export type ConstantExpression = number;
export type ConstantSlice = number;
export type ConstantBlock = number;
export type ConstantFunction = number;
export type ConstantArray = number;
export type ConstantOther = number;
export class Constants {
// `0` means NULL
private references: VersionedPathReference<Opaque>[] = [];
private strings: string[] = [];
private expressions: Opaque[] = [];
private arrays: number[][] = [];
private blocks: InlineBlock[] = [];
private functions: Function[] = [];
private others: Opaque[] = [];
public NULL_REFERENCE: number;
public UNDEFINED_REFERENCE: number;
constructor() {
this.NULL_REFERENCE = this.reference(NULL_REFERENCE);
this.UNDEFINED_REFERENCE = this.reference(UNDEFINED_REFERENCE);
}
getReference<T extends Opaque>(value: ConstantReference): VersionedPathReference<T> {
return this.references[value - 1] as VersionedPathReference<T>;
}
reference(value: VersionedPathReference<Opaque>): ConstantReference {
let index = this.references.length;
this.references.push(value);
return index + 1;
}
getString(value: ConstantString): string {
return this.strings[value - 1];
}
string(value: string): ConstantString {
let index = this.strings.length;
this.strings.push(value);
return index + 1;
}
getExpression<T>(value: ConstantExpression): T {
return this.expressions[value - 1] as T;
}
expression(value: CompiledExpression<Opaque> | CompiledArgs): ConstantExpression {
let index = this.expressions.length;
this.expressions.push(value);
return index + 1;
}
getArray(value: ConstantArray): number[] {
return this.arrays[value - 1];
}
array(values: number[]): ConstantArray {
let index = this.arrays.length;
this.arrays.push(values);
return index + 1;
}
getBlock(value: ConstantBlock): InlineBlock {
return this.blocks[value - 1];
}
block(block: InlineBlock): ConstantBlock {
let index = this.blocks.length;
this.blocks.push(block);
return index + 1;
}
getFunction<T extends Function>(value: ConstantFunction): T {
return this.functions[value - 1] as T;
}
function(f: Function): ConstantFunction {
let index = this.functions.length;
this.functions.push(f);
return index + 1;
}
getOther<T>(value: ConstantOther): T {
return this.others[value - 1] as T;
}
other(other: Opaque): ConstantOther {
let index = this.others.length;
this.others.push(other);
return index + 1;
}
}
export type Operand1 = number;
export type Operand2 = number;
export type Operand3 = number;
export type EvaluateOpcode = (vm: VM, opcode: Opcode) => void;
export class AppendOpcodes {
private evaluateOpcode: EvaluateOpcode[] = fillNulls<EvaluateOpcode>(OpcodeName.EvaluatePartial + 1);
add<Name extends OpcodeName>(name: Name, evaluate: EvaluateOpcode): void {
this.evaluateOpcode[name as number] = evaluate;
}
evaluate(vm: VM, opcode: Opcode) {
let func = this.evaluateOpcode[opcode.type];
func(vm, opcode);
}
}
export const APPEND_OPCODES = new AppendOpcodes();
export abstract class AbstractOpcode {
public type: string;
public _guid: number;
constructor() {
initializeGuid(this);
}
toJSON(): OpcodeJSON {
return { guid: this._guid, type: this.type };
}
}
export abstract class UpdatingOpcode extends AbstractOpcode {
public tag: RevisionTag;
next: Option<UpdatingOpcode> = null;
prev: Option<UpdatingOpcode> = null;
abstract evaluate(vm: UpdatingVM): void;
}
export type UpdatingOpSeq = ListSlice<UpdatingOpcode>;
export function inspect(opcodes: ReadonlyArray<AbstractOpcode>): string {
let buffer: string[] = [];
opcodes.forEach((opcode, i) => {
_inspect(opcode.toJSON(), buffer, 0, i);
});
return buffer.join('');
}
function _inspect(opcode: OpcodeJSON, buffer: string[], level: number, index: number) {
let indentation: string[] = [];
for (let i=0; i<level; i++) {
indentation.push(' ');
}
buffer.push(...indentation);
buffer.push(`${index}. ${opcode.type}`);
if (opcode.args || opcode.details) {
buffer.push('(');
if (opcode.args) {
buffer.push(opcode.args.join(', '));
}
if (opcode.details) {
let keys = Object.keys(opcode.details);
if (keys.length) {
if (opcode.args && opcode.args.length) {
buffer.push(', ');
}
buffer.push(keys.map(key => `${key}=${opcode.details && opcode.details[key]}`).join(', '));
}
}
buffer.push(')');
}
buffer.push('\n');
if (opcode.children && opcode.children.length) {
for (let i=0; i<opcode.children.length; i++) {
_inspect(opcode.children[i], buffer, level+1, i);
}
}
}