ember-material-icons
Version:
Google Material icons for your ember-cli app
210 lines (171 loc) • 5.06 kB
text/typescript
import { Scope, Environment, Opcode } from '../environment';
import { Reference, PathReference, ReferenceIterator } from '@glimmer/reference';
import { Option, unwrap } from '@glimmer/util';
import { InlineBlock } from '../scanner';
import { EvaluatedArgs } from '../compiled/expressions/args';
import { Component, ComponentManager } from '../component/interfaces';
export class CapturedFrame {
constructor(
public operand: Option<PathReference<any>>,
public args: Option<EvaluatedArgs>,
public condition: Option<Reference<boolean>>
) {}
}
class Frame {
ip: number;
operand: Option<PathReference<any>> = null;
immediate: any = null;
args: Option<EvaluatedArgs> = null;
callerScope: Option<Scope> = null;
blocks: Option<Blocks> = null;
condition: Option<Reference<boolean>> = null;
iterator: Option<ReferenceIterator> = null;
key: Option<string> = null;
constructor(
public start: number,
public end: number,
public component = <Component>null,
public manager: Option<ComponentManager<Component>> = null,
public shadow: Option<InlineBlock> = null
) {
this.ip = start;
}
capture(): CapturedFrame {
return new CapturedFrame(this.operand, this.args, this.condition);
}
restore(frame: CapturedFrame) {
this.operand = frame.operand;
this.args = frame.args;
this.condition = frame.condition;
}
}
export interface Blocks {
default: Option<InlineBlock>;
inverse: Option<InlineBlock>;
}
export class FrameStack {
private frames: Frame[] = [];
private frame: number = -1;
private get currentFrame(): Frame {
return this.frames[this.frame];
}
push(start: number, end: number, component = <Component>null, manager: Option<ComponentManager<Component>> = null, shadow: Option<InlineBlock> = null) {
let pos = ++this.frame;
if (pos < this.frames.length) {
let frame = this.frames[pos];
frame.start = frame.ip = start;
frame.end = end;
frame.component = component;
frame.manager = manager;
frame.shadow = shadow;
frame.operand = null;
frame.immediate = null;
frame.args = null;
frame.callerScope = null;
frame.blocks = null;
frame.condition = null;
frame.iterator = null;
frame.key = null;
} else {
this.frames[pos] = new Frame(start, end, component, manager, shadow);
}
}
pop() {
this.frame--;
}
capture(): CapturedFrame {
return this.currentFrame.capture();
}
restore(frame: CapturedFrame) {
this.currentFrame.restore(frame);
}
getStart(): number {
return this.currentFrame.start;
}
getEnd(): number {
return this.currentFrame.end;
}
getCurrent(): number {
return this.currentFrame.ip;
}
setCurrent(ip: number): number {
return this.currentFrame.ip = ip;
}
getOperand<T>(): PathReference<T> {
return unwrap(this.currentFrame.operand);
}
setOperand<T>(operand: PathReference<T>): PathReference<T> {
return this.currentFrame.operand = operand;
}
getImmediate<T>(): T {
return this.currentFrame.immediate;
}
setImmediate<T>(value: T): T {
return this.currentFrame.immediate = value;
}
// FIXME: These options are required in practice by the existing code, but
// figure out why.
getArgs(): Option<EvaluatedArgs> {
return this.currentFrame.args;
}
setArgs(args: EvaluatedArgs): EvaluatedArgs {
return this.currentFrame.args = args;
}
getCondition(): Reference<boolean> {
return unwrap(this.currentFrame.condition);
}
setCondition(condition: Reference<boolean>): Reference<boolean> {
return this.currentFrame.condition = condition;
}
getIterator(): ReferenceIterator {
return unwrap(this.currentFrame.iterator);
}
setIterator(iterator: ReferenceIterator): ReferenceIterator {
return this.currentFrame.iterator = iterator;
}
getKey(): Option<string> {
return this.currentFrame.key;
}
setKey(key: string): string {
return this.currentFrame.key = key;
}
getBlocks(): Blocks {
return unwrap(this.currentFrame.blocks);
}
setBlocks(blocks: Blocks): Blocks {
return this.currentFrame.blocks = blocks;
}
getCallerScope(): Scope {
return unwrap(this.currentFrame.callerScope);
}
setCallerScope(callerScope: Scope): Scope {
return this.currentFrame.callerScope = callerScope;
}
getComponent(): Component {
return unwrap(this.currentFrame.component);
}
getManager(): ComponentManager<Component> {
return unwrap(this.currentFrame.manager);
}
getShadow(): Option<InlineBlock> {
return this.currentFrame.shadow;
}
goto(ip: number) {
this.setCurrent(ip);
}
nextStatement(env: Environment): Option<Opcode> {
while (this.frame !== -1) {
let frame = this.frames[this.frame];
let ip = frame.ip;
let end = frame.end;
if (ip < end) {
let program = env.program;
frame.ip += 4;
return program.opcode(ip);
} else {
this.pop();
}
}
return null;
}
}