From 7f21946126a24c27a324779823a3413679f177a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustav=20S=C3=B6rn=C3=A4s?= Date: Sat, 30 Jan 2021 20:19:27 +0100 Subject: add pong --- pong/Cargo.toml | 14 ++++++++++ pong/pong.tdy | 63 ++++++++++++++++++++++++++++++++++++++++++ pong/src/main.rs | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 161 insertions(+) create mode 100644 pong/Cargo.toml create mode 100644 pong/pong.tdy create mode 100644 pong/src/main.rs diff --git a/pong/Cargo.toml b/pong/Cargo.toml new file mode 100644 index 0000000..8e8cace --- /dev/null +++ b/pong/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "pong" +version = "0.1.0" +authors = ["Gustav Sörnäs "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +tihdy = { path = ".."} +tihdy_derive = { path = "../tihdy_derive" } + +macroquad = "0.2" +tokio = { version = "1", features = ["rt", "rt-multi-thread"] } diff --git a/pong/pong.tdy b/pong/pong.tdy new file mode 100644 index 0000000..9405a5c --- /dev/null +++ b/pong/pong.tdy @@ -0,0 +1,63 @@ +blob Paddle { + x: float + y: float +} + +blob Player { + paddle: Paddle +} + +blob State { + p1: Player + p2: Player +} + +update := fn state: State { + delta := get_delta() + + if key_down("w") { + state.p1.paddle.y = state.p1.paddle.y + delta + } + if key_down("s") { + state.p1.paddle.y = state.p1.paddle.y - delta + } + + if key_down("i") { + state.p2.paddle.y = state.p2.paddle.y + delta + } + if key_down("i") { + state.p2.paddle.y = state.p2.paddle.y - delta + } +} + +draw := fn state: State { + clear() + draw_rectangle(state.p1.paddle.x, state.p1.paddle.y, 0.2, 1.) + draw_rectangle(state.p2.paddle.x, state.p2.paddle.y, 0.2, 1.) + next_frame() +} + +init := fn { + running := true + + state := State() + state.p1 = Player() + state.p1.paddle = Paddle() + state.p1.paddle.x = 1. + state.p1.paddle.y = 10. + + state.p2 = Player() + state.p2.paddle = Paddle() + state.p2.paddle.x = 19. + state.p2.paddle.y = 10. + + for i := 0, i < 5, i = i + 1 { + log(state.p1.paddle.x, state.p1.paddle.y) + log(state.p2.paddle.x, state.p2.paddle.y) + + update(state) + draw(state) + } +} + +init() diff --git a/pong/src/main.rs b/pong/src/main.rs new file mode 100644 index 0000000..b29136b --- /dev/null +++ b/pong/src/main.rs @@ -0,0 +1,84 @@ +use macroquad::{Camera2D, DARKPURPLE, KeyCode, SKYBLUE, clear_background, draw_rectangle, get_frame_time, is_key_down, next_frame, set_camera, vec2}; +use std::path::Path; +use tihdy::{Type, Value}; +use tihdy_derive::extern_function; + +const SCREEN_WIDTH: f32 = 20.0; +const SCREEN_HEIGHT: f32 = 20.0; + +extern_function!(log + [Value::Float(f1), Value::Float(f2)] -> Type::Void => { + println!("({}, {})", f1, f2); + Ok(Value::Nil) + }, +); + +extern_function!(get_delta + [] -> Type::Float => { + Ok(Value::Float(get_frame_time() as f64)) + }, +); + +extern_function!(key_down + [Value::String(s)] -> Type::Bool => { + let s: &str = s; + Ok(Value::Bool(match s { + "w" => is_key_down(KeyCode::W), + "s" => is_key_down(KeyCode::S), + "i" => is_key_down(KeyCode::I), + "k" => is_key_down(KeyCode::K), + _ => false, + })) + }, +); + +extern_function!(my_next_frame + [] -> Type::Void => { + tokio::spawn(async { + next_frame().await + }); + Ok(Value::Nil) + }, +); + +extern_function!(my_draw_rectangle + [Value::Float(x), Value::Float(y), Value::Float(w), Value::Float(h)] -> Type::Void => { + println!("Drawing rectangle {} {} {} {}", x, y, w, h); + draw_rectangle(*x as f32, *y as f32, *w as f32, *h as f32, DARKPURPLE); + Ok(Value::Nil) + }, +); + +extern_function!(clear + [] -> Type::Void => { + clear_background(SKYBLUE); + Ok(Value::Nil) + }, +); + +#[macroquad::main("Pong")] +async fn main() { + set_camera(Camera2D { + zoom: vec2(1. / SCREEN_WIDTH * 2., -1. / SCREEN_HEIGHT * 2.), + target: vec2(SCREEN_WIDTH / 2., SCREEN_HEIGHT / 2.), + ..Default::default() + }); + + let rt = tokio::runtime::Runtime::new().unwrap(); + + let functions: Vec<(String, tihdy::RustFunction)> = vec![ + ("log".to_string(), log), + ("get_delta".to_string(), get_delta), + ("key_down".to_string(), key_down), + ("next_frame".to_string(), my_next_frame), + ("draw_rectangle".to_string(), my_draw_rectangle), + ("clear".to_string(), clear), + ]; + + let _guard = rt.enter(); // so we can async { next_frame().await } + if let Err(errs) = tihdy::run_file(Path::new("pong.tdy"), false, functions) { + for err in errs { + println!("{}", err); + } + } +} -- cgit v1.2.1 From 0ee58ee676945f9a652690f490936080ab5a0623 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Sat, 30 Jan 2021 09:57:50 +0100 Subject: fix closures in closure bug --- src/compiler.rs | 5 ++++- src/vm.rs | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 347abe6..92bf3fc 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -472,6 +472,9 @@ impl Compiler { let mut return_type = Type::Void; 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 _ret = push_frame!(self, function_block, { loop { match self.peek() { @@ -538,8 +541,8 @@ impl Compiler { let func = Op::Constant(Value::Function(Vec::new(), Rc::clone(&function_block))); + self.blocks[block_id] = function_block; block.add(func, self.line()); - self.blocks.push(function_block); } fn variable_expression(&mut self, block: &mut Block) { diff --git a/src/vm.rs b/src/vm.rs index 849aaa1..e2b9e57 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -470,9 +470,9 @@ impl VM { self.stack.push(Value::Function(Vec::new(), block.clone())); let mut types = Vec::new(); - for (slot, is_up, _) in block.borrow().ups.iter() { + for (slot, is_up, ty) in block.borrow().ups.iter() { if *is_up { - types.push(Type::Void); + types.push(ty.clone()); } else { types.push(self.stack[*slot].as_type()); } -- cgit v1.2.1 From 6b5e59311511b1462c7a10ba1389782f640e77a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Sat, 30 Jan 2021 23:17:17 +0100 Subject: Yield --- pong/pong.tdy | 3 ++- pong/src/main.rs | 20 +++++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/pong/pong.tdy b/pong/pong.tdy index 9405a5c..d27a2f5 100644 --- a/pong/pong.tdy +++ b/pong/pong.tdy @@ -51,12 +51,13 @@ init := fn { state.p2.paddle.x = 19. state.p2.paddle.y = 10. - for i := 0, i < 5, i = i + 1 { + for i := 0, i == i, i = i + 1 { log(state.p1.paddle.x, state.p1.paddle.y) log(state.p2.paddle.x, state.p2.paddle.y) update(state) draw(state) + yield } } diff --git a/pong/src/main.rs b/pong/src/main.rs index b29136b..449fee1 100644 --- a/pong/src/main.rs +++ b/pong/src/main.rs @@ -1,6 +1,7 @@ use macroquad::{Camera2D, DARKPURPLE, KeyCode, SKYBLUE, clear_background, draw_rectangle, get_frame_time, is_key_down, next_frame, set_camera, vec2}; use std::path::Path; use tihdy::{Type, Value}; +use tihdy::vm::OpResult; use tihdy_derive::extern_function; const SCREEN_WIDTH: f32 = 20.0; @@ -76,9 +77,26 @@ async fn main() { ]; let _guard = rt.enter(); // so we can async { next_frame().await } - if let Err(errs) = tihdy::run_file(Path::new("pong.tdy"), false, functions) { + let vm = tihdy::compile_file(Path::new("pong.tdy"), false, functions); + if let Err(errs) = vm { for err in errs { println!("{}", err); } + return; + } + let mut vm = vm.unwrap(); + loop { + match vm.run() { + Err(e) => { + println!("{:?}", e); + break; + } + Ok(OpResult::Yield) => { + next_frame().await + } + _ => { + break; + } + } } } -- cgit v1.2.1 From d2fd074370d829d3d1dfbc6279f1fcbde769eeb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Sat, 30 Jan 2021 23:17:49 +0100 Subject: Add in the yield keyword --- src/compiler.rs | 8 +++++++- src/lib.rs | 21 ++++++++++++++++++++- src/tokenizer.rs | 3 +++ 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(); 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> { + 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> { 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 { 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) => { -- cgit v1.2.1 From 43ba4b48e4f849fd7ef288a6ca27213ed7f4904d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustav=20S=C3=B6rn=C3=A4s?= Date: Sat, 30 Jan 2021 23:20:25 +0100 Subject: move second paddle --- pong/pong.tdy | 13 +++++-------- pong/src/main.rs | 1 - 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/pong/pong.tdy b/pong/pong.tdy index d27a2f5..7088f2e 100644 --- a/pong/pong.tdy +++ b/pong/pong.tdy @@ -16,18 +16,18 @@ update := fn state: State { delta := get_delta() if key_down("w") { - state.p1.paddle.y = state.p1.paddle.y + delta + state.p1.paddle.y = state.p1.paddle.y - delta } if key_down("s") { - state.p1.paddle.y = state.p1.paddle.y - delta + state.p1.paddle.y = state.p1.paddle.y + delta } - if key_down("i") { - state.p2.paddle.y = state.p2.paddle.y + delta - } if key_down("i") { state.p2.paddle.y = state.p2.paddle.y - delta } + if key_down("k") { + state.p2.paddle.y = state.p2.paddle.y + delta + } } draw := fn state: State { @@ -52,9 +52,6 @@ init := fn { state.p2.paddle.y = 10. for i := 0, i == i, i = i + 1 { - log(state.p1.paddle.x, state.p1.paddle.y) - log(state.p2.paddle.x, state.p2.paddle.y) - update(state) draw(state) yield diff --git a/pong/src/main.rs b/pong/src/main.rs index 449fee1..6382e92 100644 --- a/pong/src/main.rs +++ b/pong/src/main.rs @@ -44,7 +44,6 @@ extern_function!(my_next_frame extern_function!(my_draw_rectangle [Value::Float(x), Value::Float(y), Value::Float(w), Value::Float(h)] -> Type::Void => { - println!("Drawing rectangle {} {} {} {}", x, y, w, h); draw_rectangle(*x as f32, *y as f32, *w as f32, *h as f32, DARKPURPLE); Ok(Value::Nil) }, -- cgit v1.2.1 From 349055ef2533bf3268f37d3c04e5adb84814f50a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustav=20S=C3=B6rn=C3=A4s?= Date: Sat, 30 Jan 2021 23:24:05 +0100 Subject: remove tokio from pong --- pong/Cargo.toml | 1 - pong/pong.tdy | 1 - pong/src/main.rs | 13 ------------- 3 files changed, 15 deletions(-) diff --git a/pong/Cargo.toml b/pong/Cargo.toml index 8e8cace..99b2d36 100644 --- a/pong/Cargo.toml +++ b/pong/Cargo.toml @@ -11,4 +11,3 @@ tihdy = { path = ".."} tihdy_derive = { path = "../tihdy_derive" } macroquad = "0.2" -tokio = { version = "1", features = ["rt", "rt-multi-thread"] } diff --git a/pong/pong.tdy b/pong/pong.tdy index 7088f2e..24886c8 100644 --- a/pong/pong.tdy +++ b/pong/pong.tdy @@ -34,7 +34,6 @@ draw := fn state: State { clear() draw_rectangle(state.p1.paddle.x, state.p1.paddle.y, 0.2, 1.) draw_rectangle(state.p2.paddle.x, state.p2.paddle.y, 0.2, 1.) - next_frame() } init := fn { diff --git a/pong/src/main.rs b/pong/src/main.rs index 6382e92..c3cc0bf 100644 --- a/pong/src/main.rs +++ b/pong/src/main.rs @@ -33,15 +33,6 @@ extern_function!(key_down }, ); -extern_function!(my_next_frame - [] -> Type::Void => { - tokio::spawn(async { - next_frame().await - }); - Ok(Value::Nil) - }, -); - extern_function!(my_draw_rectangle [Value::Float(x), Value::Float(y), Value::Float(w), Value::Float(h)] -> Type::Void => { draw_rectangle(*x as f32, *y as f32, *w as f32, *h as f32, DARKPURPLE); @@ -64,18 +55,14 @@ async fn main() { ..Default::default() }); - let rt = tokio::runtime::Runtime::new().unwrap(); - let functions: Vec<(String, tihdy::RustFunction)> = vec![ ("log".to_string(), log), ("get_delta".to_string(), get_delta), ("key_down".to_string(), key_down), - ("next_frame".to_string(), my_next_frame), ("draw_rectangle".to_string(), my_draw_rectangle), ("clear".to_string(), clear), ]; - let _guard = rt.enter(); // so we can async { next_frame().await } let vm = tihdy::compile_file(Path::new("pong.tdy"), false, functions); if let Err(errs) = vm { for err in errs { -- cgit v1.2.1 From 40b9ec3f0f1273440d4405b531cd3290dd259b78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Sun, 31 Jan 2021 09:55:09 +0100 Subject: Add a ball, that kinda moves --- pong/pong.tdy | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- pong/src/main.rs | 12 ++++++---- 2 files changed, 72 insertions(+), 9 deletions(-) diff --git a/pong/pong.tdy b/pong/pong.tdy index 24886c8..e1eb210 100644 --- a/pong/pong.tdy +++ b/pong/pong.tdy @@ -3,6 +3,14 @@ blob Paddle { y: float } +blob Ball { + x: float + y: float + + vx: float + vy: float +} + blob Player { paddle: Paddle } @@ -10,36 +18,89 @@ blob Player { blob State { p1: Player p2: Player + ball: Ball +} + +ball_speed := 2.0 +SPEED := 10.0 + +abs := fn a: float -> float { + if a < 0.0 { + ret -a + } + ret a +} + +and := fn a: bool, b: bool -> bool { + if a { + ret b + } + ret false +} + +or := fn a: bool, b: bool -> bool { + if a { + ret true + } + ret b +} + +rect_overlap := fn ax: float, ay: float, aw: float, ah: float, bx: float, by: float, bw: float, bh: float -> bool { + dx := abs(ax - bx) + (-aw - bw) / 2. + dy := abs(ay - by) + (-ah - bh) / 2. + ret and(dx < 0., dy < 0.) +} + +ball_and_paddle_check := fn pad: Paddle, ball: Ball { + if rect_overlap(ball.x, ball.y, 0.2, 0.2, pad.x, pad.y, 0.2, 1.) { + ball.vx = -ball.vx + } } update := fn state: State { delta := get_delta() + speed := delta * SPEED if key_down("w") { - state.p1.paddle.y = state.p1.paddle.y - delta + state.p1.paddle.y = state.p1.paddle.y - speed } if key_down("s") { - state.p1.paddle.y = state.p1.paddle.y + delta + state.p1.paddle.y = state.p1.paddle.y + speed } if key_down("i") { - state.p2.paddle.y = state.p2.paddle.y - delta + state.p2.paddle.y = state.p2.paddle.y - speed } if key_down("k") { - state.p2.paddle.y = state.p2.paddle.y + delta + state.p2.paddle.y = state.p2.paddle.y + speed } + + state.ball.x = state.ball.x + delta * state.ball.vx + state.ball.y = state.ball.y + delta * state.ball.vy + + + ball_and_paddle_check(state.p1.paddle, state.ball) + ball_and_paddle_check(state.p2.paddle, state.ball) } draw := fn state: State { clear() draw_rectangle(state.p1.paddle.x, state.p1.paddle.y, 0.2, 1.) draw_rectangle(state.p2.paddle.x, state.p2.paddle.y, 0.2, 1.) + + draw_rectangle(state.ball.x, state.ball.y, 0.2, 0.2) } init := fn { running := true state := State() + state.ball = Ball() + state.ball.x = 10.0 + state.ball.y = 10.0 + state.ball.vx = 1.0 + state.ball.vy = 0.0 + state.p1 = Player() state.p1.paddle = Paddle() state.p1.paddle.x = 1. diff --git a/pong/src/main.rs b/pong/src/main.rs index c3cc0bf..2ab4b4a 100644 --- a/pong/src/main.rs +++ b/pong/src/main.rs @@ -49,11 +49,6 @@ extern_function!(clear #[macroquad::main("Pong")] async fn main() { - set_camera(Camera2D { - zoom: vec2(1. / SCREEN_WIDTH * 2., -1. / SCREEN_HEIGHT * 2.), - target: vec2(SCREEN_WIDTH / 2., SCREEN_HEIGHT / 2.), - ..Default::default() - }); let functions: Vec<(String, tihdy::RustFunction)> = vec![ ("log".to_string(), log), @@ -70,6 +65,13 @@ async fn main() { } return; } + + set_camera(Camera2D { + zoom: vec2(1. / SCREEN_WIDTH * 2., -1. / SCREEN_HEIGHT * 2.), + target: vec2(SCREEN_WIDTH / 2., SCREEN_HEIGHT / 2.), + ..Default::default() + }); + let mut vm = vm.unwrap(); loop { match vm.run() { -- cgit v1.2.1 From a23e8c074efdde39ba0e284cc27f1aa41b4efce7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Sun, 31 Jan 2021 10:04:41 +0100 Subject: Add correct collisions --- pong/pong.tdy | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/pong/pong.tdy b/pong/pong.tdy index e1eb210..9778dfc 100644 --- a/pong/pong.tdy +++ b/pong/pong.tdy @@ -46,8 +46,14 @@ or := fn a: bool, b: bool -> bool { } rect_overlap := fn ax: float, ay: float, aw: float, ah: float, bx: float, by: float, bw: float, bh: float -> bool { - dx := abs(ax - bx) + (-aw - bw) / 2. - dy := abs(ay - by) + (-ah - bh) / 2. + acx := ax + aw / 2. + acy := ay + ah / 2. + + bcx := bx + bw / 2. + bcy := by + bh / 2. + + dx := abs(acx - bcx) + (-aw - bw) / 2. + dy := abs(acy - bcy) + (-ah - bh) / 2. ret and(dx < 0., dy < 0.) } @@ -85,6 +91,7 @@ update := fn state: State { draw := fn state: State { clear() + draw_rectangle(state.p1.paddle.x, state.p1.paddle.y, 0.2, 1.) draw_rectangle(state.p2.paddle.x, state.p2.paddle.y, 0.2, 1.) -- cgit v1.2.1 From ef62c52f4ef990c5f51dd3a3d38c90757890b898 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Sun, 31 Jan 2021 10:14:22 +0100 Subject: Fix edge case --- pong/pong.tdy | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/pong/pong.tdy b/pong/pong.tdy index 9778dfc..cb861f9 100644 --- a/pong/pong.tdy +++ b/pong/pong.tdy @@ -45,6 +45,13 @@ or := fn a: bool, b: bool -> bool { ret b } +sign := fn a: float -> float { + if a < 0.0 { + ret -1.0 + } + ret 1.0 +} + rect_overlap := fn ax: float, ay: float, aw: float, ah: float, bx: float, by: float, bw: float, bh: float -> bool { acx := ax + aw / 2. acy := ay + ah / 2. @@ -59,7 +66,11 @@ rect_overlap := fn ax: float, ay: float, aw: float, ah: float, bx: float, by: fl ball_and_paddle_check := fn pad: Paddle, ball: Ball { if rect_overlap(ball.x, ball.y, 0.2, 0.2, pad.x, pad.y, 0.2, 1.) { - ball.vx = -ball.vx + if ball.x < pad.x { + ball.vx = -abs(ball.vx) + } else { + ball.vx = abs(ball.vx) + } } } -- cgit v1.2.1 From 2f32aa0f1848f937992254fd9a610264784aefbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustav=20S=C3=B6rn=C3=A4s?= Date: Sun, 31 Jan 2021 09:55:40 +0100 Subject: thin lto --- pong/Cargo.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pong/Cargo.toml b/pong/Cargo.toml index 99b2d36..acf7d67 100644 --- a/pong/Cargo.toml +++ b/pong/Cargo.toml @@ -6,6 +6,9 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[profile.release] +lto = "thin" + [dependencies] tihdy = { path = ".."} tihdy_derive = { path = "../tihdy_derive" } -- cgit v1.2.1 From 837492e247eb9f50ba7837ff3565157a5542e32c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustav=20S=C3=B6rn=C3=A4s?= Date: Sun, 31 Jan 2021 10:23:40 +0100 Subject: ball bouncy sideways --- pong/pong.tdy | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pong/pong.tdy b/pong/pong.tdy index cb861f9..5d9b277 100644 --- a/pong/pong.tdy +++ b/pong/pong.tdy @@ -66,11 +66,16 @@ rect_overlap := fn ax: float, ay: float, aw: float, ah: float, bx: float, by: fl ball_and_paddle_check := fn pad: Paddle, ball: Ball { if rect_overlap(ball.x, ball.y, 0.2, 0.2, pad.x, pad.y, 0.2, 1.) { + ballcy := ball.y + 0.1 + padcy := pad.y + 0.5 if ball.x < pad.x { ball.vx = -abs(ball.vx) + ball.vy = (ballcy - padcy) * 3. } else { ball.vx = abs(ball.vx) + ball.vy = (ballcy - padcy) * 3. } + log(ball.vx, ball.vy) } } @@ -116,7 +121,7 @@ init := fn { state.ball = Ball() state.ball.x = 10.0 state.ball.y = 10.0 - state.ball.vx = 1.0 + state.ball.vx = 3.0 state.ball.vy = 0.0 state.p1 = Player() -- cgit v1.2.1 From 4aa801b6b17e1c34c05d94850b9450c05f6c60d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Sun, 31 Jan 2021 10:16:53 +0100 Subject: roof and floor --- pong/pong.tdy | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/pong/pong.tdy b/pong/pong.tdy index 5d9b277..fc54e36 100644 --- a/pong/pong.tdy +++ b/pong/pong.tdy @@ -100,6 +100,14 @@ update := fn state: State { state.ball.x = state.ball.x + delta * state.ball.vx state.ball.y = state.ball.y + delta * state.ball.vy + if state.ball.y < 0. { + state.ball.vy = abs(state.ball.vy) + } + + if state.ball.y > 20. - 0.2 { + state.ball.vy = -abs(state.ball.vy) + } + ball_and_paddle_check(state.p1.paddle, state.ball) ball_and_paddle_check(state.p2.paddle, state.ball) @@ -121,8 +129,8 @@ init := fn { state.ball = Ball() state.ball.x = 10.0 state.ball.y = 10.0 - state.ball.vx = 3.0 - state.ball.vy = 0.0 + state.ball.vx = 1.0 + state.ball.vy = 2.0 state.p1 = Player() state.p1.paddle = Paddle() -- cgit v1.2.1 From 62ed092e7cdb70cb97d36736605428457f948fae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Sun, 31 Jan 2021 10:17:30 +0100 Subject: remove unused --- pong/pong.tdy | 3 --- 1 file changed, 3 deletions(-) diff --git a/pong/pong.tdy b/pong/pong.tdy index fc54e36..d79175d 100644 --- a/pong/pong.tdy +++ b/pong/pong.tdy @@ -108,7 +108,6 @@ update := fn state: State { state.ball.vy = -abs(state.ball.vy) } - ball_and_paddle_check(state.p1.paddle, state.ball) ball_and_paddle_check(state.p2.paddle, state.ball) } @@ -123,8 +122,6 @@ draw := fn state: State { } init := fn { - running := true - state := State() state.ball = Ball() state.ball.x = 10.0 -- cgit v1.2.1 From 13d2bbb024ebc52b42045b7002c396bc90ee9193 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Sun, 31 Jan 2021 10:27:07 +0100 Subject: add score and stuff --- pong/pong.tdy | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/pong/pong.tdy b/pong/pong.tdy index d79175d..3d7f3f4 100644 --- a/pong/pong.tdy +++ b/pong/pong.tdy @@ -13,6 +13,7 @@ blob Ball { blob Player { paddle: Paddle + score: int } blob State { @@ -108,6 +109,22 @@ update := fn state: State { state.ball.vy = -abs(state.ball.vy) } + if state.ball.x < 0.0 { + state.ball.x = 10.0 + state.ball.y = 10.0 + state.ball.vx = -10. + state.ball.vy = 0. + state.p1.score = state.p1.score + 1 + } + + if state.ball.x > 20.0 { + state.ball.x = 10.0 + state.ball.y = 10.0 + state.ball.vx = 10. + state.ball.vy = 0. + state.p2.score = state.p2.score + 1 + } + ball_and_paddle_check(state.p1.paddle, state.ball) ball_and_paddle_check(state.p2.paddle, state.ball) } @@ -130,11 +147,13 @@ init := fn { state.ball.vy = 2.0 state.p1 = Player() + state.p1.score = 0 state.p1.paddle = Paddle() state.p1.paddle.x = 1. state.p1.paddle.y = 10. state.p2 = Player() + state.p2.score = 0 state.p2.paddle = Paddle() state.p2.paddle.x = 19. state.p2.paddle.y = 10. -- cgit v1.2.1 From 32158bc19333fbfc7affefc5ef6ff5e34c0109f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustav=20S=C3=B6rn=C3=A4s?= Date: Sun, 31 Jan 2021 10:38:05 +0100 Subject: variable ball and paddle size. also add dv instead of set on paddle collision --- pong/pong.tdy | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/pong/pong.tdy b/pong/pong.tdy index 3d7f3f4..8727d50 100644 --- a/pong/pong.tdy +++ b/pong/pong.tdy @@ -1,8 +1,13 @@ +PADDLE_W := 0.5 +PADDLE_H := 3.0 + blob Paddle { x: float y: float } +BALL_S := 0.4 + blob Ball { x: float y: float @@ -66,17 +71,16 @@ rect_overlap := fn ax: float, ay: float, aw: float, ah: float, bx: float, by: fl } ball_and_paddle_check := fn pad: Paddle, ball: Ball { - if rect_overlap(ball.x, ball.y, 0.2, 0.2, pad.x, pad.y, 0.2, 1.) { - ballcy := ball.y + 0.1 - padcy := pad.y + 0.5 + if rect_overlap(ball.x, ball.y, BALL_S, BALL_S, pad.x, pad.y, PADDLE_W, PADDLE_H) { + ballcy := ball.y + BALL_S / 2. + padcy := pad.y + PADDLE_H / 2. if ball.x < pad.x { ball.vx = -abs(ball.vx) - ball.vy = (ballcy - padcy) * 3. + ball.vy = ball.vy + (ballcy - padcy) * 3. } else { ball.vx = abs(ball.vx) - ball.vy = (ballcy - padcy) * 3. + ball.vy = ball.vy + (ballcy - padcy) * 3. } - log(ball.vx, ball.vy) } } @@ -132,10 +136,10 @@ update := fn state: State { draw := fn state: State { clear() - draw_rectangle(state.p1.paddle.x, state.p1.paddle.y, 0.2, 1.) - draw_rectangle(state.p2.paddle.x, state.p2.paddle.y, 0.2, 1.) + draw_rectangle(state.p1.paddle.x, state.p1.paddle.y, PADDLE_W, PADDLE_H) + draw_rectangle(state.p2.paddle.x, state.p2.paddle.y, PADDLE_W, PADDLE_H) - draw_rectangle(state.ball.x, state.ball.y, 0.2, 0.2) + draw_rectangle(state.ball.x, state.ball.y, BALL_S, BALL_S) } init := fn { @@ -143,8 +147,8 @@ init := fn { state.ball = Ball() state.ball.x = 10.0 state.ball.y = 10.0 - state.ball.vx = 1.0 - state.ball.vy = 2.0 + state.ball.vx = 3.0 + state.ball.vy = 0.0 state.p1 = Player() state.p1.score = 0 -- cgit v1.2.1 From 585d2e88a8066a78dcb9ebc764b3042ec970cc46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Sun, 31 Jan 2021 10:36:56 +0100 Subject: Add paddle edges --- pong/pong.tdy | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/pong/pong.tdy b/pong/pong.tdy index 8727d50..ab1459b 100644 --- a/pong/pong.tdy +++ b/pong/pong.tdy @@ -88,6 +88,8 @@ update := fn state: State { delta := get_delta() speed := delta * SPEED + paddle_height := 1.0 + if key_down("w") { state.p1.paddle.y = state.p1.paddle.y - speed } @@ -95,6 +97,14 @@ update := fn state: State { state.p1.paddle.y = state.p1.paddle.y + speed } + if state.p1.paddle.y < 0.0 { + state.p1.paddle.y = 0.0 + } + + if state.p1.paddle.y > 20.0 - paddle_height { + state.p1.paddle.y = 20.0 - paddle_height + } + if key_down("i") { state.p2.paddle.y = state.p2.paddle.y - speed } @@ -102,6 +112,15 @@ update := fn state: State { state.p2.paddle.y = state.p2.paddle.y + speed } + if state.p2.paddle.y < 0.0 { + state.p2.paddle.y = 0.0 + } + + if state.p2.paddle.y > 20.0 - paddle_height { + state.p2.paddle.y = 20.0 - paddle_height + } + + state.ball.x = state.ball.x + delta * state.ball.vx state.ball.y = state.ball.y + delta * state.ball.vy -- cgit v1.2.1 From ae2db9a668df875e5a3e76982a54e455ec080749 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Sun, 31 Jan 2021 10:48:30 +0100 Subject: SOME BLANCE --- pong/pong.tdy | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/pong/pong.tdy b/pong/pong.tdy index ab1459b..e1803d6 100644 --- a/pong/pong.tdy +++ b/pong/pong.tdy @@ -7,6 +7,7 @@ blob Paddle { } BALL_S := 0.4 +BALL_STARTV := 5.0 blob Ball { x: float @@ -71,14 +72,16 @@ rect_overlap := fn ax: float, ay: float, aw: float, ah: float, bx: float, by: fl } ball_and_paddle_check := fn pad: Paddle, ball: Ball { + if rect_overlap(ball.x, ball.y, BALL_S, BALL_S, pad.x, pad.y, PADDLE_W, PADDLE_H) { + SPEEDUP := 0.5 ballcy := ball.y + BALL_S / 2. padcy := pad.y + PADDLE_H / 2. if ball.x < pad.x { - ball.vx = -abs(ball.vx) + ball.vx = -abs(ball.vx) - SPEEDUP ball.vy = ball.vy + (ballcy - padcy) * 3. } else { - ball.vx = abs(ball.vx) + ball.vx = abs(ball.vx) + SPEEDUP ball.vy = ball.vy + (ballcy - padcy) * 3. } } @@ -88,8 +91,6 @@ update := fn state: State { delta := get_delta() speed := delta * SPEED - paddle_height := 1.0 - if key_down("w") { state.p1.paddle.y = state.p1.paddle.y - speed } @@ -101,8 +102,8 @@ update := fn state: State { state.p1.paddle.y = 0.0 } - if state.p1.paddle.y > 20.0 - paddle_height { - state.p1.paddle.y = 20.0 - paddle_height + if state.p1.paddle.y > 20.0 - PADDLE_H { + state.p1.paddle.y = 20.0 - PADDLE_H } if key_down("i") { @@ -116,11 +117,10 @@ update := fn state: State { state.p2.paddle.y = 0.0 } - if state.p2.paddle.y > 20.0 - paddle_height { - state.p2.paddle.y = 20.0 - paddle_height + if state.p2.paddle.y > 20.0 - PADDLE_H { + state.p2.paddle.y = 20.0 - PADDLE_H } - state.ball.x = state.ball.x + delta * state.ball.vx state.ball.y = state.ball.y + delta * state.ball.vy @@ -135,7 +135,7 @@ update := fn state: State { if state.ball.x < 0.0 { state.ball.x = 10.0 state.ball.y = 10.0 - state.ball.vx = -10. + state.ball.vx = -BALL_STARTV state.ball.vy = 0. state.p1.score = state.p1.score + 1 } @@ -143,7 +143,7 @@ update := fn state: State { if state.ball.x > 20.0 { state.ball.x = 10.0 state.ball.y = 10.0 - state.ball.vx = 10. + state.ball.vx = BALL_STARTV state.ball.vy = 0. state.p2.score = state.p2.score + 1 } @@ -166,7 +166,7 @@ init := fn { state.ball = Ball() state.ball.x = 10.0 state.ball.y = 10.0 - state.ball.vx = 3.0 + state.ball.vx = BALL_STARTV state.ball.vy = 0.0 state.p1 = Player() -- cgit v1.2.1 From 4ce6fb5d2ceead254ee7ed32d2845234a1c195fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Sun, 31 Jan 2021 10:55:54 +0100 Subject: Add score! --- pong/pong.tdy | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/pong/pong.tdy b/pong/pong.tdy index e1803d6..15998f3 100644 --- a/pong/pong.tdy +++ b/pong/pong.tdy @@ -19,7 +19,7 @@ blob Ball { blob Player { paddle: Paddle - score: int + score: float } blob State { @@ -137,7 +137,7 @@ update := fn state: State { state.ball.y = 10.0 state.ball.vx = -BALL_STARTV state.ball.vy = 0. - state.p1.score = state.p1.score + 1 + state.p1.score = state.p1.score + 1.0 } if state.ball.x > 20.0 { @@ -145,7 +145,7 @@ update := fn state: State { state.ball.y = 10.0 state.ball.vx = BALL_STARTV state.ball.vy = 0. - state.p2.score = state.p2.score + 1 + state.p2.score = state.p2.score + 1.0 } ball_and_paddle_check(state.p1.paddle, state.ball) @@ -158,6 +158,14 @@ draw := fn state: State { draw_rectangle(state.p1.paddle.x, state.p1.paddle.y, PADDLE_W, PADDLE_H) draw_rectangle(state.p2.paddle.x, state.p2.paddle.y, PADDLE_W, PADDLE_H) + for y := 0.0, y < state.p1.score, y = y + 1.0 { + draw_rectangle(15.0, y * 0.5, 0.5, 0.5) + } + + for y := 0.0, y < state.p2.score, y = y + 1.0 { + draw_rectangle(5.0, y * 0.5, 0.5, 0.5) + } + draw_rectangle(state.ball.x, state.ball.y, BALL_S, BALL_S) } @@ -170,13 +178,13 @@ init := fn { state.ball.vy = 0.0 state.p1 = Player() - state.p1.score = 0 + state.p1.score = 0.0 state.p1.paddle = Paddle() state.p1.paddle.x = 1. state.p1.paddle.y = 10. state.p2 = Player() - state.p2.score = 0 + state.p2.score = 0.0 state.p2.paddle = Paddle() state.p2.paddle.x = 19. state.p2.paddle.y = 10. -- cgit v1.2.1 From 7b2d04a92e3c3a7cee1eced3c7f1e14983a3534d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustav=20S=C3=B6rn=C3=A4s?= Date: Sun, 31 Jan 2021 19:17:18 +0100 Subject: add post jam readme --- pong/README | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 pong/README diff --git a/pong/README b/pong/README new file mode 100644 index 0000000..be718ec --- /dev/null +++ b/pong/README @@ -0,0 +1,37 @@ +PONG +==== + +Made for Global Game Jam 2021 at LiU Game Jam's site. + +The language wasn't really ready for a normal game so we wanted to make Pong +(the easiest game we could think of) while fixing what we needed to make it +work. + +Building +-------- + +Clone the entire tihdy-repo, cd into the pong-directory and then cargo run. + +Modifying +--------- + +All game logic is located in pong.tdy. Most of the configuration should be +straight forward. If you want to modify the controls, you need to change both +the string passed from pong.tdy as well as the respective function in src/main.rs +(key_down). + +If you want to add more rust functions (for example, to draw text to the screen) +you need to add it like the already existing functions. All functions need a +return type and a return value, even if it is a Type::Void and Value::Nil. (See +e.g. clear for an example.) For a draw_text you probably want to take a +Value::String(s), Value::Float(x), Value::Float(y) and so on. Inside the block +you then write your normal Rusty code. + +After writing your function you also need to link it so you can use it from the +game file. Add it to 'functions' like the other linked functions inside main() +in src/main.rs. + +After linking, the only thing left to do is call it from the game logic. You'll +get a type error if you pass the wrong parameters. Additional parameter +combinations can be set (much like normal function overloading) should you have +the need by adding more "arms" to the extern_function!(). -- cgit v1.2.1 From e3b2b1af21b2bdf2adfff62f652cb3cf8ab74e36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Sun, 31 Jan 2021 21:13:25 +0100 Subject: pop_twice -> poppop() --- src/vm.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/vm.rs b/src/vm.rs index 60f723b..0470efb 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -92,7 +92,7 @@ impl VM { self.stack.pop().unwrap() } - fn pop_twice(&mut self) -> (Value, Value) { + fn poppop(&mut self) -> (Value, Value) { let (a, b) = (self.stack.remove(self.stack.len() - 1), self.stack.remove(self.stack.len() - 1)); (b, a) // this matches the order they were on the stack @@ -207,7 +207,7 @@ impl VM { } Op::Add => { - match self.pop_twice() { + match self.poppop() { (Value::Float(a), Value::Float(b)) => self.stack.push(Value::Float(a + b)), (Value::Int(a), Value::Int(b)) => self.stack.push(Value::Int(a + b)), (Value::String(a), Value::String(b)) => { @@ -218,7 +218,7 @@ impl VM { } Op::Sub => { - match self.pop_twice() { + match self.poppop() { (Value::Float(a), Value::Float(b)) => self.stack.push(Value::Float(a - b)), (Value::Int(a), Value::Int(b)) => self.stack.push(Value::Int(a - b)), (a, b) => error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])), @@ -226,7 +226,7 @@ impl VM { } Op::Mul => { - match self.pop_twice() { + match self.poppop() { (Value::Float(a), Value::Float(b)) => self.stack.push(Value::Float(a * b)), (Value::Int(a), Value::Int(b)) => self.stack.push(Value::Int(a * b)), (a, b) => error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])), @@ -234,7 +234,7 @@ impl VM { } Op::Div => { - match self.pop_twice() { + match self.poppop() { (Value::Float(a), Value::Float(b)) => self.stack.push(Value::Float(a / b)), (Value::Int(a), Value::Int(b)) => self.stack.push(Value::Int(a / b)), (a, b) => error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])), @@ -242,7 +242,7 @@ impl VM { } Op::Equal => { - match self.pop_twice() { + match self.poppop() { (Value::Float(a), Value::Float(b)) => self.stack.push(Value::Bool(a == b)), (Value::Int(a), Value::Int(b)) => self.stack.push(Value::Bool(a == b)), (Value::String(a), Value::String(b)) => self.stack.push(Value::Bool(a == b)), @@ -252,7 +252,7 @@ impl VM { } Op::Less => { - match self.pop_twice() { + match self.poppop() { (Value::Float(a), Value::Float(b)) => self.stack.push(Value::Bool(a < b)), (Value::Int(a), Value::Int(b)) => self.stack.push(Value::Bool(a < b)), (Value::String(a), Value::String(b)) => self.stack.push(Value::Bool(a < b)), @@ -262,7 +262,7 @@ impl VM { } Op::Greater => { - match self.pop_twice() { + match self.poppop() { (Value::Float(a), Value::Float(b)) => self.stack.push(Value::Bool(a > b)), (Value::Int(a), Value::Int(b)) => self.stack.push(Value::Bool(a > b)), (Value::String(a), Value::String(b)) => self.stack.push(Value::Bool(a > b)), @@ -272,14 +272,14 @@ impl VM { } Op::And => { - match self.pop_twice() { + match self.poppop() { (Value::Bool(a), Value::Bool(b)) => self.stack.push(Value::Bool(a && b)), (a, b) => error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])), } } Op::Or => { - match self.pop_twice() { + match self.poppop() { (Value::Bool(a), Value::Bool(b)) => self.stack.push(Value::Bool(a || b)), (a, b) => error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])), } -- cgit v1.2.1 From 16a80551298c91e516b813ec205761e7fed2328b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Sun, 31 Jan 2021 21:18:22 +0100 Subject: use the pop method don't interact with the stack --- src/vm.rs | 62 +++++++++++++++++++++++++++++++------------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/src/vm.rs b/src/vm.rs index 0470efb..7fe9c23 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -138,7 +138,7 @@ impl VM { } Op::Pop => { - self.stack.pop().unwrap(); + self.pop(); } Op::Yield => { @@ -147,7 +147,7 @@ impl VM { } Op::PopUpvalue => { - let value = self.stack.pop().unwrap(); + let value = self.pop(); let slot = self.stack.len(); self.drop_upvalue(slot, value); } @@ -178,28 +178,28 @@ impl VM { } Op::Get(field) => { - let inst = self.stack.pop(); - if let Some(Value::BlobInstance(ty, values)) = inst { + let inst = self.pop(); + if let Value::BlobInstance(ty, values) = inst { let slot = self.blobs[ty].name_to_field.get(&field).unwrap().0; self.stack.push(values.borrow()[slot].clone()); } else { - error!(self, ErrorKind::RuntimeTypeError(Op::Get(field.clone()), vec![inst.unwrap()])); + error!(self, ErrorKind::RuntimeTypeError(Op::Get(field.clone()), vec![inst])); } } Op::Set(field) => { - let value = self.stack.pop().unwrap(); - let inst = self.stack.pop(); - if let Some(Value::BlobInstance(ty, values)) = inst { + let value = self.pop(); + let inst = self.pop(); + if let Value::BlobInstance(ty, values) = inst { let slot = self.blobs[ty].name_to_field.get(&field).unwrap().0; values.borrow_mut()[slot] = value; } else { - error!(self, ErrorKind::RuntimeTypeError(Op::Get(field.clone()), vec![inst.unwrap()])); + error!(self, ErrorKind::RuntimeTypeError(Op::Get(field.clone()), vec![inst])); } } Op::Neg => { - match self.stack.pop().unwrap() { + match self.pop() { Value::Float(a) => self.stack.push(Value::Float(-a)), Value::Int(a) => self.stack.push(Value::Int(-a)), a => error!(self, ErrorKind::RuntimeTypeError(op, vec![a])), @@ -286,7 +286,7 @@ impl VM { } Op::Not => { - match self.stack.pop().unwrap() { + match self.pop() { Value::Bool(a) => self.stack.push(Value::Bool(!a)), a => error!(self, ErrorKind::RuntimeTypeError(op, vec![a])), } @@ -298,14 +298,14 @@ impl VM { } Op::JmpFalse(line) => { - if matches!(self.stack.pop(), Some(Value::Bool(false))) { + if matches!(self.pop(), Value::Bool(false)) { self.frame_mut().ip = line; return Ok(OpResult::Continue); } } Op::Assert => { - if matches!(self.stack.pop(), Some(Value::Bool(false))) { + if matches!(self.pop(), Value::Bool(false)) { error!(self, ErrorKind::Assert); } self.stack.push(Value::Bool(true)); @@ -324,7 +324,7 @@ impl VM { Op::AssignUpvalue(slot) => { let offset = self.frame().stack_offset; - let value = self.stack.pop().unwrap(); + let value = self.pop(); let slot = match &self.stack[offset] { Value::Function(ups, _) => Rc::clone(&ups[slot]), _ => unreachable!(), @@ -339,7 +339,7 @@ impl VM { Op::AssignLocal(slot) => { let slot = self.frame().stack_offset + slot; - self.stack[slot] = self.stack.pop().unwrap(); + self.stack[slot] = self.pop(); } Op::Define(_) => {} @@ -355,7 +355,7 @@ impl VM { values.push(Value::Nil); } - self.stack.pop(); + self.pop(); self.stack.push(Value::BlobInstance(blob_id, Rc::new(RefCell::new(values)))); } Value::Function(_, block) => { @@ -394,7 +394,7 @@ impl VM { } Op::Print => { - println!("PRINT: {:?}", self.stack.pop().unwrap()); + println!("PRINT: {:?}", self.pop()); } Op::Return => { @@ -402,7 +402,7 @@ impl VM { if self.frames.is_empty() { return Ok(OpResult::Done); } else { - self.stack[last.stack_offset] = self.stack.pop().unwrap(); + self.stack[last.stack_offset] = self.pop(); for slot in last.stack_offset+1..self.stack.len() { if self.upvalues.contains_key(&slot) { let value = self.stack[slot].clone(); @@ -515,31 +515,31 @@ impl VM { } Op::Get(field) => { - let inst = self.stack.pop(); - if let Some(Value::BlobInstance(ty, _)) = inst { + let inst = self.pop(); + if let Value::BlobInstance(ty, _) = inst { let value = self.blobs[ty].name_to_field.get(&field).unwrap().1.as_value(); self.stack.push(value); } else { self.stack.push(Value::Nil); - error!(self, ErrorKind::RuntimeTypeError(Op::Get(field.clone()), vec![inst.unwrap()])); + error!(self, ErrorKind::RuntimeTypeError(Op::Get(field.clone()), vec![inst])); } } Op::Set(field) => { - let value = self.stack.pop().unwrap(); - let inst = self.stack.pop(); - if let Some(Value::BlobInstance(ty, _)) = inst { + let value = self.pop(); + let inst = self.pop(); + if let Value::BlobInstance(ty, _) = inst { let ty = &self.blobs[ty].name_to_field.get(&field).unwrap().1; if ty != &Type::from(&value) { - error!(self, ErrorKind::RuntimeTypeError(Op::Set(field.clone()), vec![inst.unwrap()])); + error!(self, ErrorKind::RuntimeTypeError(Op::Set(field.clone()), vec![inst])); } } else { - error!(self, ErrorKind::RuntimeTypeError(Op::Set(field.clone()), vec![inst.unwrap()])); + error!(self, ErrorKind::RuntimeTypeError(Op::Set(field.clone()), vec![inst])); } } Op::PopUpvalue => { - self.stack.pop().unwrap(); + self.pop(); } Op::ReadUpvalue(slot) => { @@ -549,7 +549,7 @@ impl VM { Op::AssignUpvalue(slot) => { let var = self.frame().block.borrow().ups[slot].2.clone(); - let up = self.stack.pop().unwrap().as_type(); + let up = self.pop().as_type(); if var != up { error!(self, ErrorKind::TypeError(op, vec![var, up]), "Incorrect type for upvalue.".to_string()); @@ -557,7 +557,7 @@ impl VM { } Op::Return => { - let a = self.stack.pop().unwrap(); + let a = self.pop(); let inner = self.frame().block.borrow(); let ret = inner.ret(); if a.as_type() != *ret { @@ -603,7 +603,7 @@ impl VM { values[*slot] = ty.as_value(); } - self.stack.pop(); + self.pop(); self.stack.push(Value::BlobInstance(blob_id, Rc::new(RefCell::new(values)))); } Value::Function(_, block) => { @@ -702,7 +702,7 @@ impl VM { } if !self.stack.is_empty() { - let ident = self.stack.pop().unwrap().identity(); + let ident = self.pop().identity(); self.stack.push(ident); } } -- cgit v1.2.1 From 906e4946a54e8ae70dab3a5ab9d2ca5a3c34d0f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Sun, 31 Jan 2021 21:29:52 +0100 Subject: add noisy error on invalid stack --- src/vm.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/vm.rs b/src/vm.rs index 7fe9c23..562bed9 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -89,7 +89,10 @@ impl VM { } fn pop(&mut self) -> Value { - self.stack.pop().unwrap() + match self.stack.pop() { + Some(x) => x, + None => self.crash_and_burn(), + } } fn poppop(&mut self) -> (Value, Value) { @@ -117,6 +120,17 @@ impl VM { self.frame().block.borrow().ops[ip].clone() } + fn crash_and_burn(&self) -> ! { + println!("\n\n !!!POPING EMPTY STACK - DUMPING EVERYTHING!!!\n"); + self.print_stack(); + println!("\n"); + self.frame().block.borrow().debug_print(); + println!(" ip: {}, line: {}\n", + self.frame().ip.blue(), + self.frame().block.borrow().line(self.frame().ip).blue()); + unreachable!(); + } + fn error(&self, kind: ErrorKind, message: Option) -> Error { let frame = self.frames.last().unwrap(); Error { -- cgit v1.2.1 From 200f6bfe2e4bddbbcc1a7545d780b7c1d640ba42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Sun, 31 Jan 2021 21:33:04 +0100 Subject: self.stack.push -> self.push --- src/vm.rs | 94 +++++++++++++++++++++++++++++++++------------------------------ 1 file changed, 49 insertions(+), 45 deletions(-) diff --git a/src/vm.rs b/src/vm.rs index 562bed9..b7fa318 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -88,6 +88,10 @@ impl VM { Rc::new(RefCell::new(UpValue::new(slot)))) } + fn push(&mut self, value: Value) { + self.stack.push(value); + } + fn pop(&mut self) -> Value { match self.stack.pop() { Some(x) => x, @@ -188,14 +192,14 @@ impl VM { }, _ => value.clone(), }; - self.stack.push(value); + self.push(value); } Op::Get(field) => { let inst = self.pop(); if let Value::BlobInstance(ty, values) = inst { let slot = self.blobs[ty].name_to_field.get(&field).unwrap().0; - self.stack.push(values.borrow()[slot].clone()); + self.push(values.borrow()[slot].clone()); } else { error!(self, ErrorKind::RuntimeTypeError(Op::Get(field.clone()), vec![inst])); } @@ -214,18 +218,18 @@ impl VM { Op::Neg => { match self.pop() { - Value::Float(a) => self.stack.push(Value::Float(-a)), - Value::Int(a) => self.stack.push(Value::Int(-a)), + Value::Float(a) => self.push(Value::Float(-a)), + Value::Int(a) => self.push(Value::Int(-a)), a => error!(self, ErrorKind::RuntimeTypeError(op, vec![a])), } } Op::Add => { match self.poppop() { - (Value::Float(a), Value::Float(b)) => self.stack.push(Value::Float(a + b)), - (Value::Int(a), Value::Int(b)) => self.stack.push(Value::Int(a + b)), + (Value::Float(a), Value::Float(b)) => self.push(Value::Float(a + b)), + (Value::Int(a), Value::Int(b)) => self.push(Value::Int(a + b)), (Value::String(a), Value::String(b)) => { - self.stack.push(Value::String(Rc::from(format!("{}{}", a, b)))) + self.push(Value::String(Rc::from(format!("{}{}", a, b)))) } (a, b) => error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])), } @@ -233,75 +237,75 @@ impl VM { Op::Sub => { match self.poppop() { - (Value::Float(a), Value::Float(b)) => self.stack.push(Value::Float(a - b)), - (Value::Int(a), Value::Int(b)) => self.stack.push(Value::Int(a - b)), + (Value::Float(a), Value::Float(b)) => self.push(Value::Float(a - b)), + (Value::Int(a), Value::Int(b)) => self.push(Value::Int(a - b)), (a, b) => error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])), } } Op::Mul => { match self.poppop() { - (Value::Float(a), Value::Float(b)) => self.stack.push(Value::Float(a * b)), - (Value::Int(a), Value::Int(b)) => self.stack.push(Value::Int(a * b)), + (Value::Float(a), Value::Float(b)) => self.push(Value::Float(a * b)), + (Value::Int(a), Value::Int(b)) => self.push(Value::Int(a * b)), (a, b) => error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])), } } Op::Div => { match self.poppop() { - (Value::Float(a), Value::Float(b)) => self.stack.push(Value::Float(a / b)), - (Value::Int(a), Value::Int(b)) => self.stack.push(Value::Int(a / b)), + (Value::Float(a), Value::Float(b)) => self.push(Value::Float(a / b)), + (Value::Int(a), Value::Int(b)) => self.push(Value::Int(a / b)), (a, b) => error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])), } } Op::Equal => { match self.poppop() { - (Value::Float(a), Value::Float(b)) => self.stack.push(Value::Bool(a == b)), - (Value::Int(a), Value::Int(b)) => self.stack.push(Value::Bool(a == b)), - (Value::String(a), Value::String(b)) => self.stack.push(Value::Bool(a == b)), - (Value::Bool(a), Value::Bool(b)) => self.stack.push(Value::Bool(a == b)), + (Value::Float(a), Value::Float(b)) => self.push(Value::Bool(a == b)), + (Value::Int(a), Value::Int(b)) => self.push(Value::Bool(a == b)), + (Value::String(a), Value::String(b)) => self.push(Value::Bool(a == b)), + (Value::Bool(a), Value::Bool(b)) => self.push(Value::Bool(a == b)), (a, b) => error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])), } } Op::Less => { match self.poppop() { - (Value::Float(a), Value::Float(b)) => self.stack.push(Value::Bool(a < b)), - (Value::Int(a), Value::Int(b)) => self.stack.push(Value::Bool(a < b)), - (Value::String(a), Value::String(b)) => self.stack.push(Value::Bool(a < b)), - (Value::Bool(a), Value::Bool(b)) => self.stack.push(Value::Bool(a < b)), + (Value::Float(a), Value::Float(b)) => self.push(Value::Bool(a < b)), + (Value::Int(a), Value::Int(b)) => self.push(Value::Bool(a < b)), + (Value::String(a), Value::String(b)) => self.push(Value::Bool(a < b)), + (Value::Bool(a), Value::Bool(b)) => self.push(Value::Bool(a < b)), (a, b) => error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])), } } Op::Greater => { match self.poppop() { - (Value::Float(a), Value::Float(b)) => self.stack.push(Value::Bool(a > b)), - (Value::Int(a), Value::Int(b)) => self.stack.push(Value::Bool(a > b)), - (Value::String(a), Value::String(b)) => self.stack.push(Value::Bool(a > b)), - (Value::Bool(a), Value::Bool(b)) => self.stack.push(Value::Bool(a > b)), + (Value::Float(a), Value::Float(b)) => self.push(Value::Bool(a > b)), + (Value::Int(a), Value::Int(b)) => self.push(Value::Bool(a > b)), + (Value::String(a), Value::String(b)) => self.push(Value::Bool(a > b)), + (Value::Bool(a), Value::Bool(b)) => self.push(Value::Bool(a > b)), (a, b) => error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])), } } Op::And => { match self.poppop() { - (Value::Bool(a), Value::Bool(b)) => self.stack.push(Value::Bool(a && b)), + (Value::Bool(a), Value::Bool(b)) => self.push(Value::Bool(a && b)), (a, b) => error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])), } } Op::Or => { match self.poppop() { - (Value::Bool(a), Value::Bool(b)) => self.stack.push(Value::Bool(a || b)), + (Value::Bool(a), Value::Bool(b)) => self.push(Value::Bool(a || b)), (a, b) => error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])), } } Op::Not => { match self.pop() { - Value::Bool(a) => self.stack.push(Value::Bool(!a)), + Value::Bool(a) => self.push(Value::Bool(!a)), a => error!(self, ErrorKind::RuntimeTypeError(op, vec![a])), } } @@ -322,7 +326,7 @@ impl VM { if matches!(self.pop(), Value::Bool(false)) { error!(self, ErrorKind::Assert); } - self.stack.push(Value::Bool(true)); + self.push(Value::Bool(true)); } Op::ReadUpvalue(slot) => { @@ -333,7 +337,7 @@ impl VM { } _ => unreachable!(), }; - self.stack.push(value); + self.push(value); } Op::AssignUpvalue(slot) => { @@ -348,7 +352,7 @@ impl VM { Op::ReadLocal(slot) => { let slot = self.frame().stack_offset + slot; - self.stack.push(self.stack[slot].clone()); + self.push(self.stack[slot].clone()); } Op::AssignLocal(slot) => { @@ -370,7 +374,7 @@ impl VM { } self.pop(); - self.stack.push(Value::BlobInstance(blob_id, Rc::new(RefCell::new(values)))); + self.push(Value::BlobInstance(blob_id, Rc::new(RefCell::new(values)))); } Value::Function(_, block) => { let inner = block.borrow(); @@ -399,7 +403,7 @@ impl VM { Err(ek) => error!(self, ek, "Wrong arguments to external function".to_string()), }; self.stack.truncate(new_base); - self.stack.push(res); + self.push(res); } _ => { unreachable!() @@ -455,7 +459,7 @@ impl VM { self.stack.clear(); self.frames.clear(); - self.stack.push(Value::Function(Vec::new(), Rc::clone(&block))); + self.push(Value::Function(Vec::new(), Rc::clone(&block))); self.frames.push(Frame { stack_offset: 0, @@ -494,7 +498,7 @@ impl VM { Op::Constant(ref value) => { match value.clone() { Value::Function(_, block) => { - self.stack.push(Value::Function(Vec::new(), block.clone())); + self.push(Value::Function(Vec::new(), block.clone())); let mut types = Vec::new(); for (slot, is_up, ty) in block.borrow().ups.iter() { @@ -523,7 +527,7 @@ impl VM { }; }, _ => { - self.stack.push(value.clone()); + self.push(value.clone()); } } } @@ -532,9 +536,9 @@ impl VM { let inst = self.pop(); if let Value::BlobInstance(ty, _) = inst { let value = self.blobs[ty].name_to_field.get(&field).unwrap().1.as_value(); - self.stack.push(value); + self.push(value); } else { - self.stack.push(Value::Nil); + self.push(Value::Nil); error!(self, ErrorKind::RuntimeTypeError(Op::Get(field.clone()), vec![inst])); } } @@ -558,7 +562,7 @@ impl VM { Op::ReadUpvalue(slot) => { let value = self.frame().block.borrow().ups[slot].2.as_value(); - self.stack.push(value); + self.push(value); } Op::AssignUpvalue(slot) => { @@ -618,7 +622,7 @@ impl VM { } self.pop(); - self.stack.push(Value::BlobInstance(blob_id, Rc::new(RefCell::new(values)))); + self.push(Value::BlobInstance(blob_id, Rc::new(RefCell::new(values)))); } Value::Function(_, block) => { let inner = block.borrow(); @@ -649,12 +653,12 @@ impl VM { Ok(value) => value, Err(ek) => { self.stack.truncate(new_base); - self.stack.push(Value::Nil); + self.push(Value::Nil); error!(self, ek, "Wrong arguments to external function".to_string()) } }; self.stack.truncate(new_base); - self.stack.push(res); + self.push(res); } _ => { error!(self, @@ -683,9 +687,9 @@ impl VM { self.stack.clear(); self.frames.clear(); - self.stack.push(Value::Function(Vec::new(), Rc::clone(&block))); + self.push(Value::Function(Vec::new(), Rc::clone(&block))); for arg in block.borrow().args() { - self.stack.push(arg.as_value()); + self.push(arg.as_value()); } self.frames.push(Frame { @@ -717,7 +721,7 @@ impl VM { if !self.stack.is_empty() { let ident = self.pop().identity(); - self.stack.push(ident); + self.push(ident); } } errors -- cgit v1.2.1 From d089b4a0f86b16adf23b99b8205ca7af1d586dc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Mon, 1 Feb 2021 10:21:09 +0100 Subject: Update src/vm.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Gustav Sörnäs --- src/vm.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vm.rs b/src/vm.rs index b7fa318..fd8eb73 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -125,7 +125,7 @@ impl VM { } fn crash_and_burn(&self) -> ! { - println!("\n\n !!!POPING EMPTY STACK - DUMPING EVERYTHING!!!\n"); + println!("\n\n !!!POPPING EMPTY STACK - DUMPING EVERYTHING!!!\n"); self.print_stack(); println!("\n"); self.frame().block.borrow().debug_print(); -- cgit v1.2.1 From afc4a3fe1618239017e15cabc664dd70abc1d75b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Sun, 31 Jan 2021 22:28:48 +0100 Subject: add assignment ops --- src/compiler.rs | 82 ++++++++++++++++++++++++++++++++++++++++++++++----------- src/lib.rs | 21 +++++++++++++++ src/vm.rs | 16 +++++++---- 3 files changed, 98 insertions(+), 21 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index b7fdce1..69bf6eb 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -621,9 +621,38 @@ impl Compiler { } } - fn assign(&mut self, name: &str, block: &mut Block) { + fn assign(&mut self, block: &mut Block) { + let name = match self.eat() { + Token::Identifier(name) => name, + _ => { + error!(self, format!("Expected identifier in assignment")); + return; + } + }; + + let op = match self.eat() { + Token::Equal => None, + + Token::PlusEqual => Some(Op::Add), + Token::MinusEqual => Some(Op::Sub), + Token::StarEqual => Some(Op::Mul), + Token::SlashEqual => Some(Op::Div), + + _ => { + error!(self, format!("Expected '=' in assignment")); + return; + } + }; + if let Some(var) = self.find_variable(&name) { - self.expression(block); + if let Some(op) = op { + block.add(Op::Copy, self.line()); + self.expression(block); + block.add(op, self.line()); + } else { + self.expression(block); + } + if var.upvalue { block.add(Op::AssignUpvalue(var.slot), self.line()); } else { @@ -832,14 +861,31 @@ impl Compiler { return Err(()); }; - if self.peek() == Token::Equal { - self.eat(); - self.expression(block); - block.add(Op::Set(field), self.line()); - return Ok(()); - } else { - block.add(Op::Get(field), self.line()); - } + let op = match self.peek() { + Token::Equal => { + self.eat(); + self.expression(block); + block.add(Op::Set(field), self.line()); + return Ok(()); + } + + Token::PlusEqual => Op::Add, + Token::MinusEqual => Op::Sub, + Token::StarEqual => Op::Mul, + Token::SlashEqual => Op::Div, + + _ => { + block.add(Op::Get(field), self.line()); + continue; + } + }; + block.add(Op::Copy, self.line()); + block.add(Op::Get(field.clone()), self.line()); + self.eat(); + self.expression(block); + block.add(op, self.line()); + block.add(Op::Set(field), self.line()); + return Ok(()); } Token::LeftParen => { self.call(block); @@ -867,6 +913,16 @@ impl Compiler { block.add(Op::Print, self.line()); } + (Token::Identifier(_), Token::Equal, ..) | + (Token::Identifier(_), Token::PlusEqual, ..) | + (Token::Identifier(_), Token::MinusEqual, ..) | + (Token::Identifier(_), Token::SlashEqual, ..) | + (Token::Identifier(_), Token::StarEqual, ..) + + => { + self.assign(block); + } + (Token::Identifier(_), Token::Dot, ..) => { let block_length = block.ops.len(); let token_length = self.curr; @@ -900,12 +956,6 @@ impl Compiler { self.definition_statement(&name, Type::UnknownType, block); } - (Token::Identifier(name), Token::Equal, ..) => { - self.eat(); - self.eat(); - self.assign(&name, block); - } - (Token::Blob, Token::Identifier(_), ..) => { self.blob_statement(block); } diff --git a/src/lib.rs b/src/lib.rs index 42f24bd..453d6ce 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -325,6 +325,26 @@ a() <=> 4 test_file!(scoping, "tests/scoping.tdy"); test_file!(for_, "tests/for.tdy"); + + test_multiple!( + op_assign, + add: "a := 1\na += 1\na <=> 2", + sub: "a := 2\na -= 1\na <=> 1", + mul: "a := 2\na *= 2\na <=> 4", + div: "a := 2\na /= 2\na <=> 1", + cluster: " +blob A { a: int } +a := A() +a.a = 0 +a.a += 1 +a.a <=> 1 +a.a *= 2 +a.a <=> 2 +a.a /= 2 +a.a <=> 1 +a.a -= 1 +a.a <=> 0" + ); } #[derive(Clone)] @@ -431,6 +451,7 @@ pub enum Op { Pop, PopUpvalue, + Copy, Constant(Value), Get(String), diff --git a/src/vm.rs b/src/vm.rs index fd8eb73..6ff7b65 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -159,17 +159,23 @@ impl VM { self.pop(); } - Op::Yield => { - self.frame_mut().ip += 1; - return Ok(OpResult::Yield); - } - Op::PopUpvalue => { let value = self.pop(); let slot = self.stack.len(); self.drop_upvalue(slot, value); } + Op::Copy => { + let v = self.pop(); + self.push(v.clone()); + self.push(v); + } + + Op::Yield => { + self.frame_mut().ip += 1; + return Ok(OpResult::Yield); + } + Op::Constant(value) => { let offset = self.frame().stack_offset; let value = match value { -- cgit v1.2.1 From 43d93e4b681004198c82935e11c89d7299938a80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Mon, 1 Feb 2021 11:05:27 +0100 Subject: Create rust.yml --- .github/workflows/rust.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .github/workflows/rust.yml diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml new file mode 100644 index 0000000..d09f364 --- /dev/null +++ b/.github/workflows/rust.yml @@ -0,0 +1,21 @@ +name: Rust + +on: + push: + branches: [ main ] + pull_request: + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Build + run: cargo build --verbose + - name: Run tests + run: cargo test --verbose -- cgit v1.2.1