diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 9d4af94..19d0bf5 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -16,4 +16,5 @@ jobs: with: toolchain: stable - - run: cargo run + - run: cargo run examples/hello.cirru + - run: cargo run examples/sum.cirru diff --git a/Cargo.toml b/Cargo.toml index 070e207..4cae47a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ edition = "2018" cirru_parser = "0.1.1" regex = "1" lazy_static = "1.4.0" +clap = "3.0.0-beta.4" [profile.release] debug = true \ No newline at end of file diff --git a/README.md b/README.md index 1b21f57..f58becd 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,18 @@ ### Usages -TODO +```bash +cargo install calx-vm +calx hello.cirru +``` + +it starts with a `main` function: + +```cirru +fn main () + const "|hello world" + echo +``` ### Instructions diff --git a/examples/hello.cirru b/examples/hello.cirru new file mode 100644 index 0000000..b68cadb --- /dev/null +++ b/examples/hello.cirru @@ -0,0 +1,4 @@ + +fn main () + const "|hello world" + echo diff --git a/examples/demo.cirru b/examples/sum.cirru similarity index 97% rename from examples/demo.cirru rename to examples/sum.cirru index 0609ee0..0c33ade 100644 --- a/examples/demo.cirru +++ b/examples/sum.cirru @@ -17,7 +17,7 @@ fn demo (-> i64) const 0 local.set 0 const 0 - loop (i64 -> i64) + loop (i64) const 1 i.add dup diff --git a/src/bin/calx.rs b/src/bin/calx.rs index 5aa5b38..0db1577 100644 --- a/src/bin/calx.rs +++ b/src/bin/calx.rs @@ -3,16 +3,35 @@ use std::fs; use std::time::Instant; use cirru_parser::{parse, Cirru}; +use clap::{App, Arg}; use calx_vm::{parse_function, Calx, CalxFunc, CalxImportsDict, CalxVM}; -fn log2_calx_value(xs: Vec) -> Result { - println!("log: {:?}", xs); - Ok(Calx::Nil) -} - fn main() -> Result<(), String> { - let contents = fs::read_to_string("examples/demo.cirru").expect("Cirru file for instructions"); + let matches = App::new("Calx VM") + .version("0.1.0") + .author("Jon Chen ") + .about("A toy VM") + .arg( + Arg::new("SHOW_CODE") + .short('S') + .long("show-code") + .value_name("show-code") + .about("Sets a custom config file") + .takes_value(false), + ) + .arg( + Arg::new("SOURCE") + .about("A *.cirru file for loading code") + .required(true) + .index(1), + ) + .get_matches(); + + let source = matches.value_of("SOURCE").unwrap(); + let show_code = matches.is_present("SHOW_CODE"); + + let contents = fs::read_to_string(source).expect("Cirru file for instructions"); let code = parse(&contents).expect("Some Cirru content"); if let Cirru::List(xs) = code { @@ -30,10 +49,11 @@ fn main() -> Result<(), String> { imports.insert(String::from("log2"), (log2_calx_value, 2)); let mut vm = CalxVM::new(fns, vec![], imports); - - // for func in vm.funcs.to_owned() { - // println!("loaded fn: {}", func); - // } + if show_code { + for func in vm.funcs.to_owned() { + println!("loaded fn: {}", func); + } + } let now = Instant::now(); match vm.run() { @@ -53,3 +73,8 @@ fn main() -> Result<(), String> { Err(String::from("TODO not cirru code")) } } + +fn log2_calx_value(xs: Vec) -> Result { + println!("log: {:?}", xs); + Ok(Calx::Nil) +} diff --git a/src/parser.rs b/src/parser.rs index 7bc1d61..ae9d218 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -327,6 +327,11 @@ pub fn parse_block(ptr_base: usize, xs: &[Cirru], looped: bool) -> Result { - if self.top_frame.blocks_track.len() <= size { - return Err(format!( - "stack size {} eq/smaller than br size {}", - self.top_frame.blocks_track.len(), - size - )); - } - - self.shrink_blocks_by(size); + self.shrink_blocks_by(size)?; let last_idx = self.top_frame.blocks_track.len() - 1; if self.top_frame.blocks_track[last_idx].looped { @@ -83,15 +75,7 @@ impl CalxVM { CalxInstr::BrIf(size) => { let v = self.stack_pop()?; if v == Calx::Bool(true) || v == Calx::I64(1) { - if self.top_frame.blocks_track.len() <= size { - return Err(format!( - "stack size {} eq/smaller than br size {}", - self.top_frame.blocks_track.len(), - size - )); - } - - self.shrink_blocks_by(size); + self.shrink_blocks_by(size)?; let last_idx = self.top_frame.blocks_track.len() - 1; if self.top_frame.blocks_track[last_idx].looped { @@ -514,12 +498,22 @@ impl CalxVM { /// assumed that the size already checked #[inline(always)] - fn shrink_blocks_by(&mut self, size: usize) { + fn shrink_blocks_by(&mut self, size: usize) -> Result<(), String> { + if self.top_frame.blocks_track.len() <= size { + return Err(format!( + "stack size {} eq/smaller than br size {}", + self.top_frame.blocks_track.len(), + size + )); + } + let mut i = size; while i > 0 { self.top_frame.blocks_track.pop(); i -= 1; } + + Ok(()) } }