nilang 0.4.1

A scripting language interpreter for Advent of Code
Documentation
use core::fmt::Display;

use sandpit::TraceLeaf;

pub type Reg = u8;

#[derive(TraceLeaf, Debug, Copy, Clone)]
pub enum ByteCode {
    Noop,
    Swap { r1: Reg, r2: Reg },
    Copy { dest: Reg, src: Reg },
    Print { src: Reg },
    Read { dest: Reg },
    LoadGlobal { dest: Reg, sym: Reg },
    StoreGlobal { src: Reg, sym: Reg },
    MemLoad { dest: Reg, store: Reg, key: Reg },
    MemStore { store: Reg, key: Reg, src: Reg },
    NewList { dest: Reg },
    NewMap { dest: Reg },
    LoadBool { dest: Reg, val: bool },
    LoadNull { dest: Reg },
    LoadInt { dest: Reg, val: i16 },
    LoadSym { dest: Reg, val: u16 },
    LoadLocal { dest: Reg, id: u16 },
    LoadUpvalue { dest: Reg, id: u16 },
    StoreUpvalue { func: Reg, src: Reg },
    Equality { dest: Reg, lhs: Reg, rhs: Reg },
    Inequality { dest: Reg, lhs: Reg, rhs: Reg },
    Gt { dest: Reg, lhs: Reg, rhs: Reg },
    Gte { dest: Reg, lhs: Reg, rhs: Reg },
    Lt { dest: Reg, lhs: Reg, rhs: Reg },
    Lte { dest: Reg, lhs: Reg, rhs: Reg },
    Div { dest: Reg, lhs: Reg, rhs: Reg },
    Mult { dest: Reg, lhs: Reg, rhs: Reg },
    Add { dest: Reg, lhs: Reg, rhs: Reg },
    Sub { dest: Reg, lhs: Reg, rhs: Reg },
    Modulo { dest: Reg, lhs: Reg, rhs: Reg },
    StoreArg { src: Reg },
    Call { dest: Reg, src: Reg },
    Return { src: Reg },
    Jump { offset: i16 },
    Jnt { src: Reg, offset: i16 },
    Jit { src: Reg, offset: i16 },
    Import { dest: Reg, path: Reg },
    Push { store: Reg, src: Reg },
    Pop { dest: Reg, src: Reg },
    Len { dest: Reg, src: Reg },
    Clone { dest: Reg, src: Reg },
    Type { dest: Reg, src: Reg },
    Delete { dest: Reg, store: Reg, key: Reg },
    Bind { dest: Reg, func: Reg, arg: Reg },
    BitFlip { dest: Reg, src: Reg },
    BitXor { dest: Reg, lhs: Reg, rhs: Reg },
    BitOr { dest: Reg, lhs: Reg, rhs: Reg },
    BitAnd { dest: Reg, lhs: Reg, rhs: Reg },
    BitShift { dest: Reg, lhs: Reg, rhs: Reg }
}

impl Display for ByteCode {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        match self {
            ByteCode::Jump { offset } => write!(f, "JMP  {offset}"),
            ByteCode::Jnt { src, offset } => write!(f, "JNT  {offset}, {src}"),
            ByteCode::Jit { src, offset } => write!(f, "JIT  {offset}, {src}"),
            ByteCode::StoreArg { src } => write!(f, "ARG  {src }"),
            ByteCode::Call { dest, src } => write!(f, "CALL {dest}, {src }"),
            ByteCode::Return { src } => write!(f, "RTN  {src }"),
            ByteCode::LoadBool { dest, val } => write!(f, "BOOL {dest}, {val}"),
            ByteCode::LoadInt { dest, val } => write!(f, "INT  {dest}, {val}"),
            ByteCode::LoadSym { dest, val } => write!(f, "SYM  {dest}, #{val}"),
            ByteCode::LoadLocal { dest, id } => write!(f, "LOC  {dest}, {id}"),
            ByteCode::LoadNull { dest } => write!(f, "LDN  {dest}"),
            ByteCode::LoadUpvalue { dest, id } => write!(f, "LDUV {dest}, {id}"),
            ByteCode::StoreUpvalue { func, src } => write!(f, "STUV {func}, {src}"),
            ByteCode::Print { src } => write!(f, "OUT  {src }"),
            ByteCode::Read { dest } => write!(f, "READ {dest}"),
            ByteCode::Lt { dest, lhs, rhs } => write!(f, "LT   {dest}, {lhs}, {rhs}"),
            ByteCode::Lte { dest, lhs, rhs } => write!(f, "LTE  {dest}, {lhs}, {rhs}"),
            ByteCode::Gt { dest, lhs, rhs } => write!(f, "GT   {dest}, {lhs}, {rhs}"),
            ByteCode::Gte { dest, lhs, rhs } => write!(f, "GTE  {dest}, {lhs}, {rhs}"),
            ByteCode::Inequality { dest, lhs, rhs } => write!(f, "NEQ  {dest}, {lhs}, {rhs}"),
            ByteCode::Equality { dest, lhs, rhs } => write!(f, "EQ   {dest}, {lhs}, {rhs}"),
            ByteCode::Mult { dest, lhs, rhs } => write!(f, "MULT {dest}, {lhs}, {rhs}"),
            ByteCode::Div { dest, lhs, rhs } => write!(f, "DIV  {dest}, {lhs}, {rhs}"),
            ByteCode::Add { dest, lhs, rhs } => write!(f, "ADD  {dest}, {lhs}, {rhs}"),
            ByteCode::Sub { dest, lhs, rhs } => write!(f, "SUB  {dest}, {lhs}, {rhs}"),
            ByteCode::Modulo { dest, lhs, rhs } => write!(f, "MOD  {dest}, {lhs}, {rhs}"),
            ByteCode::Copy { dest, src } => write!(f, "COPY {dest}, {src}"),
            ByteCode::Swap { r1, r2 } => write!(f, "SWAP {r1  }, {r2 }"),
            ByteCode::NewList { dest } => write!(f, "LIST {dest}"),
            ByteCode::NewMap { dest } => write!(f, "MAP  {dest}"),
            ByteCode::MemLoad { dest, store, key } => write!(f, "MEML {dest}, {store}[{key}]"),
            ByteCode::MemStore { store, key, src } => write!(f, "MEMS {store}[{key}], {src}"),
            ByteCode::Push { store, src } => write!(f, "PUSH {store}, {src}"),
            ByteCode::Pop { dest, src } => write!(f, "POP {dest}, {src}"),
            ByteCode::Len { dest, src } => write!(f, "LEN {dest}, {src}"),
            ByteCode::Clone { dest, src } => write!(f, "CLONE {dest}, {src}"),
            ByteCode::Type { dest, src } => write!(f, "TYPE {dest}, {src}"),
            ByteCode::Delete { dest, store, key } => write!(f, "DEL {dest}, {store}[{key}]"),
            ByteCode::Bind { dest, func, arg } => write!(f, "BIND {dest}, {func}, {arg}]"),
            ByteCode::LoadGlobal { dest, sym } => write!(f, "LDGB {dest}, #{sym}"),
            ByteCode::StoreGlobal { sym, src } => write!(f, "STGB {src}, #{sym}"),
            ByteCode::Import { dest, path } => write!(f, "IMPO {dest}, {path}"),
            ByteCode::BitFlip { dest, src } => write!(f, "FLIP {dest}, {src}"),
            ByteCode::BitXor { dest, lhs, rhs } => write!(f, "XOR {dest}, {lhs}, {rhs}"),
            ByteCode::BitOr { dest, lhs, rhs } => write!(f, "OR {dest}, {lhs}, {rhs}"),
            ByteCode::BitAnd { dest, lhs, rhs } => write!(f, "AND {dest}, {lhs}, {rhs}"),
            ByteCode::BitShift { dest, lhs, rhs } => write!(f, "SHIF {dest}, {lhs}, {rhs}"),
            ByteCode::Noop => write!(f, "NOOP"),
        }
    }
}