diff options
| -rw-r--r-- | src/compiler.rs | 8 | ||||
| -rw-r--r-- | src/lib.rs | 21 | ||||
| -rw-r--r-- | src/tokenizer.rs | 3 | ||||
| -rw-r--r-- | src/vm.rs | 21 |
4 files changed, 47 insertions, 6 deletions
diff --git a/src/compiler.rs b/src/compiler.rs index 92bf3fc..b7fdce1 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -473,7 +473,8 @@ impl Compiler { let mut function_block = Block::new(&name, &self.current_file, self.line()); let block_id = self.blocks.len(); - self.blocks.push(Rc::new(RefCell::new(Block::new(&name, &self.current_file, self.line())))); + let new_block = Block::new(&name, &self.current_file, self.line()); + self.blocks.push(Rc::new(RefCell::new(new_block))); let _ret = push_frame!(self, function_block, { loop { @@ -888,6 +889,11 @@ impl Compiler { } } + (Token::Yield, ..) => { + self.eat(); + block.add(Op::Yield, self.line()); + } + (Token::Identifier(name), Token::ColonEqual, ..) => { self.eat(); self.eat(); @@ -21,6 +21,22 @@ pub fn run_file(path: &Path, print: bool, functions: Vec<(String, RustFunction)> run(tokenizer::file_to_tokens(path), path, print, functions) } +pub fn compile_file(path: &Path, + print: bool, + functions: Vec<(String, RustFunction)> + ) -> Result<vm::VM, Vec<Error>> { + let tokens = tokenizer::file_to_tokens(path); + match compiler::compile("main", path, tokens, &functions) { + Ok(prog) => { + let mut vm = vm::VM::new().print_blocks(print).print_ops(print); + vm.typecheck(&prog)?; + vm.init(&prog); + Ok(vm) + } + Err(errors) => Err(errors), + } +} + pub fn run_string(s: &str, print: bool, functions: Vec<(String, RustFunction)>) -> Result<(), Vec<Error>> { run(tokenizer::string_to_tokens(s), Path::new("builtin"), print, functions) } @@ -30,7 +46,8 @@ pub fn run(tokens: TokenStream, path: &Path, print: bool, functions: Vec<(String Ok(prog) => { let mut vm = vm::VM::new().print_blocks(print).print_ops(print); vm.typecheck(&prog)?; - if let Err(e) = vm.run(&prog) { + vm.init(&prog); + if let Err(e) = vm.run() { Err(vec![e]) } else { Ok(()) @@ -450,7 +467,9 @@ pub enum Op { Call(usize), Print, + Return, + Yield, } #[derive(Debug)] diff --git a/src/tokenizer.rs b/src/tokenizer.rs index 7bd0849..28172a3 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -35,6 +35,9 @@ pub enum Token { #[token("print")] Print, + #[token("yield")] + Yield, + #[token("ret")] Ret, @@ -42,7 +42,9 @@ pub struct VM { } -enum OpResult { +#[derive(Eq, PartialEq)] +pub enum OpResult { + Yield, Continue, Done, } @@ -139,6 +141,11 @@ impl VM { self.stack.pop().unwrap(); } + Op::Yield => { + self.frame_mut().ip += 1; + return Ok(OpResult::Yield); + } + Op::PopUpvalue => { let value = self.stack.pop().unwrap(); let slot = self.stack.len(); @@ -427,7 +434,7 @@ impl VM { self.frame().block.borrow().ops[self.frame().ip]); } - pub fn run(&mut self, prog: &Prog) -> Result<(), Error>{ + pub fn init(&mut self, prog: &Prog) { let block = Rc::clone(&prog.blocks[0]); self.blobs = prog.blobs.clone(); self.extern_functions = prog.functions.clone(); @@ -441,6 +448,9 @@ impl VM { block, ip: 0 }); + } + + pub fn run(&mut self) -> Result<OpResult, Error> { if self.print_blocks { println!("\n [[{}]]\n", "RUNNING".red()); @@ -452,8 +462,9 @@ impl VM { self.print_stack() } - if matches!(self.eval_op(self.op())?, OpResult::Done) { - return Ok(()); + let op = self.eval_op(self.op())?; + if matches!(op, OpResult::Done | OpResult::Yield) { + return Ok(op); } } } @@ -464,6 +475,8 @@ impl VM { Op::Jmp(_line) => {} + Op::Yield => {} + Op::Constant(ref value) => { match value.clone() { Value::Function(_, block) => { |
