use std::hash::Hash; use ecow::EcoString; use crate::ty::internal::{Const, Param}; type Slice = Box<[T]>; pub type ThunkIdx = usize; pub type ConstIdx = usize; pub type SymIdx = usize; pub type OpCodes = Slice; pub type Consts = Slice; pub type Thunks = Slice; #[derive(Debug, Clone)] pub struct Thunk { pub opcodes: OpCodes, } #[derive(Debug, Clone)] pub enum OpCode { /// load a constant onto stack Const { value: Const }, /// load a dynamic var onto stack LookUp { sym: EcoString }, /// load a thunk lazily onto stack LoadThunk { idx: ThunkIdx }, /// load a thunk onto stack and force its value LoadValue { idx: ThunkIdx }, /// force TOS to value ForceValue, /// [ .. func args @ .. ] consume (`arity` + 2) elements, call `func` with args` of length `arity` /// Example: __add 1 2 => [ LookUp("__add") Const(1) Const(2) Call(2) ] Call { arity: usize }, /// return a value Ret, /// make a function Func { param: Param, length: usize }, /// consume 1 element, assert TOS is true Assert, /// jump forward Jmp { step: usize }, /// [ .. cond ] consume 1 element, if `cond`` is true, then jump forward JmpIfTrue { step: usize }, /// [ .. cond ] consume 1 element, if `cond` is false, then jump forward JmpIfFalse { step: usize }, /// push an empty attribute set onto stack AttrSet, /// push an empty recursive attribute set onto stack RecAttrSet, /// [ .. set value ] consume 1 element, push a static kv pair (`name`, `value`) into `set` PushStaticAttr { name: EcoString }, /// [ .. set name value ] consume 2 elements, push a dynamic kv pair (`name`, `value`) in to `set` PushDynamicAttr, /// push an empty list onto stack List, /// [ .. list elem ] consume 1 element, push `elem` into `list` PushElem, /// convert the string as TOS to a path Path, /// [ .. a b ] consume 2 elements, perform a string concatenation `a` + `b` ConcatString, /// [ .. a b ] consume 2 elements, perform a binary operation `a` `op` `b` BinOp { op: BinOp }, /// [ .. a ] consume 1 element, perform a unary operation `op` `a` UnOp { op: UnOp }, /// set TOS to the bool value of whether TOS contains `sym` HasAttr { sym: EcoString }, /// [ .. set sym ] consume 2 elements, set TOS to the bool value of whether `set` contains `sym` HasDynamicAttr, /// [ .. set ] select `sym` from `set` Select { sym: EcoString }, /// [ .. set default ] select `sym` from `set` or `default` SelectOrDefault { sym: EcoString }, /// [ .. set sym ] select `sym` from `set` SelectDynamic, /// [ .. set sym default ] select `sym` from `set` or `default` SelectDynamicOrDefault, /// enter the environment of the attribute set at TOS EnterEnv, /// exit current envrironment LeaveEnv, /// no operation, used as termporary placeholder NoOp, } #[derive(Debug, Clone, Copy, Hash)] pub enum BinOp { Add, And, Or, Eq, Con, Upd, } #[derive(Debug, Clone, Copy, Hash)] pub enum UnOp { Not, } #[derive(Debug)] pub struct Program { pub top_level: OpCodes, pub thunks: Thunks, }