aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEdvard Thörnros <edvard.thornros@gmail.com>2021-01-30 23:17:49 +0100
committerEdvard Thörnros <edvard.thornros@gmail.com>2021-01-30 23:17:49 +0100
commitd2fd074370d829d3d1dfbc6279f1fcbde769eeb3 (patch)
treeecd4e350205eb1bfece02f2baaac1282897f4ecb
parent6b5e59311511b1462c7a10ba1389782f640e77a0 (diff)
downloadsylt-d2fd074370d829d3d1dfbc6279f1fcbde769eeb3.tar.gz
Add in the yield keyword
-rw-r--r--src/compiler.rs8
-rw-r--r--src/lib.rs21
-rw-r--r--src/tokenizer.rs3
-rw-r--r--src/vm.rs21
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();
diff --git a/src/lib.rs b/src/lib.rs
index bdd4ae4..42f24bd 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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,
diff --git a/src/vm.rs b/src/vm.rs
index e2b9e57..60f723b 100644
--- a/src/vm.rs
+++ b/src/vm.rs
@@ -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) => {