119 lines
3.1 KiB
Rust
119 lines
3.1 KiB
Rust
use hashbrown::HashMap;
|
|
|
|
use ecow::EcoString;
|
|
|
|
use crate::ty::internal::{Const, Param};
|
|
|
|
type Slice<T> = Box<[T]>;
|
|
|
|
pub type OpCodes = Slice<OpCode>;
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
pub enum OpCode {
|
|
/// load a constant onto stack
|
|
Const { idx: usize },
|
|
/// load a dynamic var onto stack
|
|
LookUp { sym: usize },
|
|
/// load a thunk lazily onto stack
|
|
LoadThunk { idx: usize },
|
|
/// let TOS capture current environment
|
|
CaptureEnv,
|
|
/// force TOS to value
|
|
ForceValue,
|
|
|
|
/// [ .. func args @ .. ] consume (`arity` + 1) elements, call `func` with args` of length `arity`
|
|
/// Example: __add 1 2 => [ LookUp("__add") Const(1) Const(2) Call(2) ]
|
|
Call { arity: usize },
|
|
/// make a function
|
|
Func { idx: 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,
|
|
/// finalize the recursive attribute set at TOS
|
|
FinalizeRec,
|
|
/// [ .. set value ] consume 1 element, push a static kv pair (`name`, `value`) into `set`
|
|
PushStaticAttr { name: usize },
|
|
/// [ .. 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: usize },
|
|
/// [ .. set sym ] consume 2 elements, set TOS to the bool value of whether `set` contains `sym`
|
|
HasDynamicAttr,
|
|
/// [ .. set ] select `sym` from `set`
|
|
Select { sym: usize },
|
|
/// [ .. set default ] select `sym` from `set` or `default`
|
|
SelectOrDefault { sym: usize },
|
|
/// [ .. 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,
|
|
|
|
/// illegal operation, used as termporary placeholder
|
|
Illegal,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
pub enum BinOp {
|
|
Add,
|
|
Sub,
|
|
Mul,
|
|
Div,
|
|
And,
|
|
Or,
|
|
Eq,
|
|
Lt,
|
|
Con,
|
|
Upd,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
pub enum UnOp {
|
|
Neg,
|
|
Not,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct Func {
|
|
pub param: Param,
|
|
pub opcodes: OpCodes,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct Program {
|
|
pub top_level: OpCodes,
|
|
pub thunks: Slice<OpCodes>,
|
|
pub funcs: Slice<Func>,
|
|
pub symbols: Vec<EcoString>,
|
|
pub symmap: HashMap<EcoString, usize>,
|
|
pub consts: Box<[Const]>,
|
|
}
|