or
and and
are now reserved words
This commit is contained in:
parent
182b14e5f4
commit
82ac6744ca
152
src/compiler.rs
152
src/compiler.rs
|
@ -5,7 +5,6 @@ use chumsky::prelude::SimpleSpan;
|
||||||
use num_derive::{FromPrimitive, ToPrimitive};
|
use num_derive::{FromPrimitive, ToPrimitive};
|
||||||
use num_traits::FromPrimitive;
|
use num_traits::FromPrimitive;
|
||||||
use std::cell::OnceCell;
|
use std::cell::OnceCell;
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, FromPrimitive, ToPrimitive)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, FromPrimitive, ToPrimitive)]
|
||||||
|
@ -17,11 +16,13 @@ pub enum Op {
|
||||||
Constant,
|
Constant,
|
||||||
Jump,
|
Jump,
|
||||||
JumpIfFalse,
|
JumpIfFalse,
|
||||||
|
JumpIfTrue,
|
||||||
Pop,
|
Pop,
|
||||||
PopN,
|
PopN,
|
||||||
PushBinding,
|
PushBinding,
|
||||||
Store,
|
Store,
|
||||||
StoreAt,
|
StoreAt,
|
||||||
|
Stash,
|
||||||
Load,
|
Load,
|
||||||
ResetMatch,
|
ResetMatch,
|
||||||
MatchNil,
|
MatchNil,
|
||||||
|
@ -53,6 +54,8 @@ pub enum Op {
|
||||||
Truncate,
|
Truncate,
|
||||||
MatchDepth,
|
MatchDepth,
|
||||||
|
|
||||||
|
Call,
|
||||||
|
|
||||||
Eq,
|
Eq,
|
||||||
Add,
|
Add,
|
||||||
Sub,
|
Sub,
|
||||||
|
@ -63,6 +66,46 @@ pub enum Op {
|
||||||
Assert,
|
Assert,
|
||||||
Get,
|
Get,
|
||||||
At,
|
At,
|
||||||
|
|
||||||
|
Not,
|
||||||
|
// Inc,
|
||||||
|
// Dec,
|
||||||
|
// Gt,
|
||||||
|
// Gte,
|
||||||
|
// Lt,
|
||||||
|
// Lte,
|
||||||
|
// Mod,
|
||||||
|
// Round,
|
||||||
|
// Ceil,
|
||||||
|
// Floor,
|
||||||
|
// Random,
|
||||||
|
// Sqrt,
|
||||||
|
|
||||||
|
// Assoc,
|
||||||
|
// Concat,
|
||||||
|
// Conj,
|
||||||
|
// Count,
|
||||||
|
// Disj,
|
||||||
|
// Dissoc,
|
||||||
|
// Range,
|
||||||
|
// Rest,
|
||||||
|
// Slice,
|
||||||
|
|
||||||
|
// "atan_2" math/atan2
|
||||||
|
// "chars" chars
|
||||||
|
// "cos" math/cos
|
||||||
|
// "doc" doc
|
||||||
|
// "downcase" string/ascii-lower
|
||||||
|
// "pi" math/pi
|
||||||
|
// "show" show
|
||||||
|
// "sin" math/sin
|
||||||
|
// "split" string/split
|
||||||
|
// "str_slice" string/slice
|
||||||
|
// "tan" math/tan
|
||||||
|
// "trim" string/trim
|
||||||
|
// "triml" string/triml
|
||||||
|
// "trimr" string/trimr
|
||||||
|
// "upcase" string/ascii-upper
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for Op {
|
impl std::fmt::Display for Op {
|
||||||
|
@ -76,11 +119,13 @@ impl std::fmt::Display for Op {
|
||||||
Constant => "constant",
|
Constant => "constant",
|
||||||
Jump => "jump",
|
Jump => "jump",
|
||||||
JumpIfFalse => "jump_if_false",
|
JumpIfFalse => "jump_if_false",
|
||||||
|
JumpIfTrue => "jump_if_true",
|
||||||
Pop => "pop",
|
Pop => "pop",
|
||||||
PopN => "pop_n",
|
PopN => "pop_n",
|
||||||
PushBinding => "push_binding",
|
PushBinding => "push_binding",
|
||||||
Store => "store",
|
Store => "store",
|
||||||
StoreAt => "store_at",
|
StoreAt => "store_at",
|
||||||
|
Stash => "stash",
|
||||||
Load => "load",
|
Load => "load",
|
||||||
MatchNil => "match_nil",
|
MatchNil => "match_nil",
|
||||||
MatchTrue => "match_true",
|
MatchTrue => "match_true",
|
||||||
|
@ -122,6 +167,10 @@ impl std::fmt::Display for Op {
|
||||||
Assert => "assert",
|
Assert => "assert",
|
||||||
Get => "get",
|
Get => "get",
|
||||||
At => "at",
|
At => "at",
|
||||||
|
|
||||||
|
Not => "not",
|
||||||
|
|
||||||
|
Call => "call",
|
||||||
};
|
};
|
||||||
write!(f, "{rep}")
|
write!(f, "{rep}")
|
||||||
}
|
}
|
||||||
|
@ -147,10 +196,10 @@ impl Chunk {
|
||||||
let op = Op::from_u8(self.bytecode[i]).unwrap();
|
let op = Op::from_u8(self.bytecode[i]).unwrap();
|
||||||
use Op::*;
|
use Op::*;
|
||||||
match op {
|
match op {
|
||||||
Pop | Store | Load | Nil | True | False | MatchNil | MatchTrue | MatchFalse
|
Pop | Store | Stash | Load | Nil | True | False | MatchNil | MatchTrue | MatchFalse
|
||||||
| PanicIfNoMatch | MatchWord | ResetMatch | GetKey | PanicNoWhen | PanicNoMatch
|
| PanicIfNoMatch | MatchWord | ResetMatch | GetKey | PanicNoWhen | PanicNoMatch
|
||||||
| TypeOf | Duplicate | Decrement | Truncate | Noop | LoadTuple | LoadList | Eq
|
| TypeOf | Duplicate | Decrement | Truncate | Noop | LoadTuple | LoadList | Eq
|
||||||
| Add | Sub | Mult | Div | Unbox | BoxStore | Assert | Get | At => {
|
| Add | Sub | Mult | Div | Unbox | BoxStore | Assert | Get | At | Not => {
|
||||||
println!("{i:04}: {op}")
|
println!("{i:04}: {op}")
|
||||||
}
|
}
|
||||||
Constant | MatchConstant => {
|
Constant | MatchConstant => {
|
||||||
|
@ -159,8 +208,8 @@ impl Chunk {
|
||||||
println!("{i:04}: {:16} {next:04}: {value}", op.to_string());
|
println!("{i:04}: {:16} {next:04}: {value}", op.to_string());
|
||||||
}
|
}
|
||||||
PushBinding | MatchTuple | MatchList | MatchDict | LoadDictValue | PushTuple
|
PushBinding | MatchTuple | MatchList | MatchDict | LoadDictValue | PushTuple
|
||||||
| PushDict | PushList | PushBox | Jump | JumpIfFalse | JumpIfNoMatch | JumpIfMatch
|
| PushDict | PushList | PushBox | Jump | JumpIfFalse | JumpIfTrue | JumpIfNoMatch
|
||||||
| JumpBack | JumpIfZero | MatchDepth | PopN | StoreAt => {
|
| JumpIfMatch | JumpBack | JumpIfZero | MatchDepth | PopN | StoreAt | Call => {
|
||||||
let next = self.bytecode[i + 1];
|
let next = self.bytecode[i + 1];
|
||||||
println!("{i:04}: {:16} {next:04}", op.to_string());
|
println!("{i:04}: {:16} {next:04}", op.to_string());
|
||||||
}
|
}
|
||||||
|
@ -201,6 +250,8 @@ fn get_builtin(name: &str, arity: usize) -> Option<Op> {
|
||||||
("assert!", 1) => Some(Op::Assert),
|
("assert!", 1) => Some(Op::Assert),
|
||||||
("get", 2) => Some(Op::Get),
|
("get", 2) => Some(Op::Get),
|
||||||
("at", 2) => Some(Op::At),
|
("at", 2) => Some(Op::At),
|
||||||
|
("not", 1) => Some(Op::Not),
|
||||||
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -697,6 +748,46 @@ impl Compiler {
|
||||||
self.emit_op(Op::GetKey);
|
self.emit_op(Op::GetKey);
|
||||||
self.stack_depth -= 1;
|
self.stack_depth -= 1;
|
||||||
}
|
}
|
||||||
|
(Or, Arguments(args)) => {
|
||||||
|
let stack_depth = self.stack_depth;
|
||||||
|
let mut jump_idxes = vec![];
|
||||||
|
if !args.is_empty() {
|
||||||
|
for arg in args {
|
||||||
|
self.visit(arg);
|
||||||
|
self.emit_op(Op::Stash);
|
||||||
|
self.emit_op(Op::JumpIfTrue);
|
||||||
|
jump_idxes.push(self.len());
|
||||||
|
self.emit_byte(0xff);
|
||||||
|
}
|
||||||
|
for idx in jump_idxes {
|
||||||
|
self.chunk.bytecode[idx] = (self.len() - idx + 2) as u8;
|
||||||
|
}
|
||||||
|
self.emit_op(Op::Load);
|
||||||
|
} else {
|
||||||
|
self.emit_op(Op::False);
|
||||||
|
}
|
||||||
|
self.stack_depth = stack_depth + 1;
|
||||||
|
}
|
||||||
|
(And, Arguments(args)) => {
|
||||||
|
let stack_depth = self.stack_depth;
|
||||||
|
let mut jump_idxes = vec![];
|
||||||
|
if !args.is_empty() {
|
||||||
|
for arg in args {
|
||||||
|
self.visit(arg);
|
||||||
|
self.emit_op(Op::Stash);
|
||||||
|
self.emit_op(Op::JumpIfFalse);
|
||||||
|
jump_idxes.push(self.len());
|
||||||
|
self.emit_byte(0xff);
|
||||||
|
}
|
||||||
|
for idx in jump_idxes {
|
||||||
|
self.chunk.bytecode[idx] = (self.len() - idx + 2) as u8;
|
||||||
|
}
|
||||||
|
self.emit_op(Op::Load);
|
||||||
|
} else {
|
||||||
|
self.emit_op(Op::True);
|
||||||
|
}
|
||||||
|
self.stack_depth = stack_depth + 1;
|
||||||
|
}
|
||||||
(Word(fn_name), Arguments(args)) => match get_builtin(fn_name, args.len()) {
|
(Word(fn_name), Arguments(args)) => match get_builtin(fn_name, args.len()) {
|
||||||
Some(code) => {
|
Some(code) => {
|
||||||
for arg in args {
|
for arg in args {
|
||||||
|
@ -705,7 +796,28 @@ impl Compiler {
|
||||||
self.emit_op(code);
|
self.emit_op(code);
|
||||||
self.stack_depth -= args.len() - 1;
|
self.stack_depth -= args.len() - 1;
|
||||||
}
|
}
|
||||||
None => todo!(),
|
None => {
|
||||||
|
//algo
|
||||||
|
// visit all the args
|
||||||
|
// then store them
|
||||||
|
// then call the function
|
||||||
|
for (register_slot, arg) in args.iter().enumerate() {
|
||||||
|
self.visit(arg);
|
||||||
|
self.emit_op(Op::StoreAt);
|
||||||
|
self.emit_byte(register_slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.emit_op(Op::PushBinding);
|
||||||
|
self.stack_depth += 1;
|
||||||
|
let biter = self.bindings.iter().rev();
|
||||||
|
for binding in biter {
|
||||||
|
if binding.name == *fn_name {
|
||||||
|
self.emit_byte(binding.stack_pos);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.emit_op(Op::Call);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
@ -817,6 +929,21 @@ impl Compiler {
|
||||||
self.emit_constant(init_val);
|
self.emit_constant(init_val);
|
||||||
self.bind(name);
|
self.bind(name);
|
||||||
|
|
||||||
|
let FnBody(fn_body) = &body.as_ref().0 else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut chunks = vec![];
|
||||||
|
|
||||||
|
for clause in fn_body {
|
||||||
|
let MatchClause(pattern, guard, clause_body) = &clause.0 else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
let TuplePattern(pattern) = &pattern.0 else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
let arity = pattern.len();
|
||||||
|
}
|
||||||
// compile the function
|
// compile the function
|
||||||
let mut compiler = Compiler::new(body, self.name, self.src);
|
let mut compiler = Compiler::new(body, self.name, self.src);
|
||||||
compiler.compile();
|
compiler.compile();
|
||||||
|
@ -828,7 +955,7 @@ impl Compiler {
|
||||||
let lfn = crate::value::LFn {
|
let lfn = crate::value::LFn {
|
||||||
name,
|
name,
|
||||||
doc: *doc,
|
doc: *doc,
|
||||||
chunk: compiler.chunk,
|
chunks,
|
||||||
closed: vec![],
|
closed: vec![],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -976,6 +1103,7 @@ impl Compiler {
|
||||||
| InterpolatedPattern(..)
|
| InterpolatedPattern(..)
|
||||||
| AsPattern(..)
|
| AsPattern(..)
|
||||||
| Splattern(..) => todo!(),
|
| Splattern(..) => todo!(),
|
||||||
|
And | Or => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -987,10 +1115,11 @@ impl Compiler {
|
||||||
let op = Op::from_u8(*byte).unwrap();
|
let op = Op::from_u8(*byte).unwrap();
|
||||||
use Op::*;
|
use Op::*;
|
||||||
match op {
|
match op {
|
||||||
Noop | Pop | Store | Load | Nil | True | False | MatchNil | MatchTrue
|
Noop | Pop | Store | Stash | Load | Nil | True | False | MatchNil | MatchTrue
|
||||||
| MatchFalse | MatchWord | ResetMatch | PanicIfNoMatch | GetKey | PanicNoWhen
|
| MatchFalse | MatchWord | ResetMatch | PanicIfNoMatch | GetKey | PanicNoWhen
|
||||||
| PanicNoMatch | TypeOf | Duplicate | Truncate | Decrement | LoadTuple
|
| PanicNoMatch | TypeOf | Duplicate | Truncate | Decrement | LoadTuple
|
||||||
| LoadList | Eq | Add | Sub | Mult | Div | Unbox | BoxStore | Assert | Get | At => {
|
| LoadList | Eq | Add | Sub | Mult | Div | Unbox | BoxStore | Assert | Get | At
|
||||||
|
| Not => {
|
||||||
println!("{i:04}: {op}")
|
println!("{i:04}: {op}")
|
||||||
}
|
}
|
||||||
Constant | MatchConstant => {
|
Constant | MatchConstant => {
|
||||||
|
@ -999,8 +1128,9 @@ impl Compiler {
|
||||||
println!("{i:04}: {:16} {next:04}: {value}", op.to_string());
|
println!("{i:04}: {:16} {next:04}: {value}", op.to_string());
|
||||||
}
|
}
|
||||||
PushBinding | MatchTuple | MatchList | PushTuple | PushDict | PushList
|
PushBinding | MatchTuple | MatchList | PushTuple | PushDict | PushList
|
||||||
| MatchDict | LoadDictValue | PushBox | Jump | JumpIfFalse | JumpIfNoMatch
|
| MatchDict | LoadDictValue | PushBox | Jump | JumpIfFalse | JumpIfTrue
|
||||||
| JumpIfMatch | JumpBack | JumpIfZero | MatchDepth | PopN | StoreAt => {
|
| JumpIfNoMatch | JumpIfMatch | JumpBack | JumpIfZero | MatchDepth | PopN
|
||||||
|
| StoreAt | Call => {
|
||||||
let (_, next) = codes.next().unwrap();
|
let (_, next) = codes.next().unwrap();
|
||||||
println!("{i:04}: {:16} {next:04}", op.to_string());
|
println!("{i:04}: {:16} {next:04}", op.to_string());
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ pub fn lexer(
|
||||||
"nil" => Token::Nil,
|
"nil" => Token::Nil,
|
||||||
// todo: hard code these as type constructors
|
// todo: hard code these as type constructors
|
||||||
"as" | "box" | "do" | "else" | "fn" | "if" | "let" | "loop" | "match" | "panic!"
|
"as" | "box" | "do" | "else" | "fn" | "if" | "let" | "loop" | "match" | "panic!"
|
||||||
| "recur" | "repeat" | "then" | "when" | "with" => Token::Reserved(word),
|
| "recur" | "repeat" | "then" | "when" | "with" | "or" | "and" => Token::Reserved(word),
|
||||||
_ => Token::Word(word),
|
_ => Token::Word(word),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::env;
|
||||||
const DEBUG_COMPILE: bool = true;
|
const DEBUG_COMPILE: bool = true;
|
||||||
const DEBUG_RUN: bool = true;
|
const DEBUG_RUN: bool = true;
|
||||||
|
|
||||||
mod memory_sandbox;
|
// mod base;
|
||||||
|
|
||||||
mod spans;
|
mod spans;
|
||||||
use crate::spans::Spanned;
|
use crate::spans::Spanned;
|
||||||
|
@ -74,8 +74,7 @@ pub fn run(src: &'static str) {
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
env::set_var("RUST_BACKTRACE", "1");
|
env::set_var("RUST_BACKTRACE", "1");
|
||||||
let src = "
|
let src = "
|
||||||
let foo = #{:a 1, :b 2}
|
or (true, true, 42)
|
||||||
:a (foo)
|
|
||||||
";
|
";
|
||||||
run(src);
|
run(src);
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,6 +63,9 @@ pub enum Ast {
|
||||||
// may come in handy?
|
// may come in handy?
|
||||||
Error,
|
Error,
|
||||||
|
|
||||||
|
And,
|
||||||
|
Or,
|
||||||
|
|
||||||
// expression nodes
|
// expression nodes
|
||||||
Placeholder,
|
Placeholder,
|
||||||
Nil,
|
Nil,
|
||||||
|
@ -121,6 +124,8 @@ impl fmt::Display for Ast {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
use Ast::*;
|
use Ast::*;
|
||||||
match self {
|
match self {
|
||||||
|
And => write!(f, "And"),
|
||||||
|
Or => write!(f, "Or"),
|
||||||
Error => write!(f, "Error"),
|
Error => write!(f, "Error"),
|
||||||
Nil => write!(f, "nil"),
|
Nil => write!(f, "nil"),
|
||||||
String(s) => write!(f, "String: \"{}\"", s),
|
String(s) => write!(f, "String: \"{}\"", s),
|
||||||
|
@ -727,7 +732,11 @@ where
|
||||||
.delimited_by(just(Token::Punctuation("(")), just(Token::Punctuation(")")))
|
.delimited_by(just(Token::Punctuation("(")), just(Token::Punctuation(")")))
|
||||||
.map_with(|args, e| (Arguments(args), e.span()));
|
.map_with(|args, e| (Arguments(args), e.span()));
|
||||||
|
|
||||||
let synth_root = word.or(keyword);
|
let or = just(Token::Reserved("or")).map_with(|_, e| (Or, e.span()));
|
||||||
|
|
||||||
|
let and = just(Token::Reserved("and")).map_with(|_, e| (And, e.span()));
|
||||||
|
|
||||||
|
let synth_root = or.or(and).or(word).or(keyword);
|
||||||
|
|
||||||
let synth_term = keyword.or(args);
|
let synth_term = keyword.or(args);
|
||||||
|
|
||||||
|
|
|
@ -570,7 +570,7 @@ impl<'a> Validator<'a> {
|
||||||
}
|
}
|
||||||
PairPattern(_, patt) => self.visit(patt.as_ref()),
|
PairPattern(_, patt) => self.visit(patt.as_ref()),
|
||||||
// terminals can never be invalid
|
// terminals can never be invalid
|
||||||
Nil | Boolean(_) | Number(_) | Keyword(_) | String(_) => (),
|
Nil | Boolean(_) | Number(_) | Keyword(_) | String(_) | And | Or => (),
|
||||||
// terminal patterns can never be invalid
|
// terminal patterns can never be invalid
|
||||||
NilPattern | BooleanPattern(..) | NumberPattern(..) | StringPattern(..)
|
NilPattern | BooleanPattern(..) | NumberPattern(..) | StringPattern(..)
|
||||||
| KeywordPattern(..) | PlaceholderPattern => (),
|
| KeywordPattern(..) | PlaceholderPattern => (),
|
||||||
|
|
|
@ -13,7 +13,7 @@ pub struct LFn {
|
||||||
// pub has_run: bool,
|
// pub has_run: bool,
|
||||||
// pub input: &'static str,
|
// pub input: &'static str,
|
||||||
// pub src: &'static str,
|
// pub src: &'static str,
|
||||||
pub chunk: Chunk,
|
pub chunks: Vec<(u8, Chunk)>,
|
||||||
pub closed: Vec<Value>,
|
pub closed: Vec<Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
29
src/vm.rs
29
src/vm.rs
|
@ -34,7 +34,7 @@ pub struct Vm<'a> {
|
||||||
pub stack: Vec<Value>,
|
pub stack: Vec<Value>,
|
||||||
pub chunk: &'a Chunk,
|
pub chunk: &'a Chunk,
|
||||||
pub ip: usize,
|
pub ip: usize,
|
||||||
pub return_register: [Value; 8],
|
pub return_register: [Value; 7],
|
||||||
pub matches: bool,
|
pub matches: bool,
|
||||||
pub match_depth: u8,
|
pub match_depth: u8,
|
||||||
pub result: Option<Result<Value, Panic>>,
|
pub result: Option<Result<Value, Panic>>,
|
||||||
|
@ -54,7 +54,6 @@ impl<'a> Vm<'a> {
|
||||||
Value::Nothing,
|
Value::Nothing,
|
||||||
Value::Nothing,
|
Value::Nothing,
|
||||||
Value::Nothing,
|
Value::Nothing,
|
||||||
Value::Nothing,
|
|
||||||
],
|
],
|
||||||
matches: false,
|
matches: false,
|
||||||
match_depth: 0,
|
match_depth: 0,
|
||||||
|
@ -158,6 +157,18 @@ impl<'a> Vm<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
JumpIfTrue => {
|
||||||
|
let jump_len = self.chunk.bytecode[self.ip + 1];
|
||||||
|
let cond = self.pop();
|
||||||
|
match cond {
|
||||||
|
Value::Nil | Value::False => {
|
||||||
|
self.ip += 2;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
self.ip += jump_len as usize + 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
JumpIfZero => {
|
JumpIfZero => {
|
||||||
let jump_len = self.chunk.bytecode[self.ip + 1];
|
let jump_len = self.chunk.bytecode[self.ip + 1];
|
||||||
let cond = self.pop();
|
let cond = self.pop();
|
||||||
|
@ -198,6 +209,10 @@ impl<'a> Vm<'a> {
|
||||||
self.return_register[i] = self.pop();
|
self.return_register[i] = self.pop();
|
||||||
self.ip += 2;
|
self.ip += 2;
|
||||||
}
|
}
|
||||||
|
Stash => {
|
||||||
|
self.return_register[0] = self.peek().clone();
|
||||||
|
self.ip += 1;
|
||||||
|
}
|
||||||
Load => {
|
Load => {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < 8 && self.return_register[i] != Value::Nothing {
|
while i < 8 && self.return_register[i] != Value::Nothing {
|
||||||
|
@ -530,6 +545,16 @@ impl<'a> Vm<'a> {
|
||||||
self.stack.push(value);
|
self.stack.push(value);
|
||||||
self.ip += 1;
|
self.ip += 1;
|
||||||
}
|
}
|
||||||
|
Not => {
|
||||||
|
let value = self.pop();
|
||||||
|
let negated = match value {
|
||||||
|
Value::Nil | Value::False => Value::True,
|
||||||
|
_ => Value::False,
|
||||||
|
};
|
||||||
|
self.push(negated);
|
||||||
|
self.ip += 1;
|
||||||
|
}
|
||||||
|
Call => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user