From cf569b5ad2af96f5ea6d0475244b41a5e810f78e Mon Sep 17 00:00:00 2001 From: tiye Date: Tue, 19 Jul 2022 21:17:53 +0800 Subject: [PATCH] extra stack check for block; tag 0.1.4 --- .github/workflows/publish.yaml | 2 ++ .github/workflows/test.yaml | 7 ++++++- Cargo.toml | 2 +- src/parser.rs | 10 ++++------ src/primes.rs | 20 ++++++++++++++++++-- src/vm.rs | 21 ++++++++++++++++----- 6 files changed, 47 insertions(+), 15 deletions(-) diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index ca98626..4f61872 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -18,6 +18,8 @@ jobs: - run: cargo run -- -S examples/sum.cirru - run: cargo run -- -S examples/assert.cirru - run: cargo run -- -S examples/nested.cirru + - run: cargo run -- -S examples/named.cirru + - run: cargo run -- --emit-binary target/a.calx examples/named.cirru && cargo run -- --eval-binary target/a.calx # - run: cargo test diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 0e1b575..22c729d 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -20,7 +20,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: - toolchain: stable + toolchain: nightly components: clippy override: true @@ -35,3 +35,8 @@ jobs: with: token: ${{ secrets.GITHUB_TOKEN }} args: --all-features + + - uses: actions-rs/clippy-check@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + args: --all-features diff --git a/Cargo.toml b/Cargo.toml index e2cb880..8bf22b4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "calx_vm" -version = "0.1.3" +version = "0.1.4" authors = ["jiyinyiyong "] edition = "2018" license = "MIT" diff --git a/src/parser.rs b/src/parser.rs index d435791..0bf26f6 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -271,9 +271,7 @@ fn parse_local_idx(x: &Cirru, collector: &mut LocalsCollector) -> Result Err(String::from("invalid empty name")), }, - Cirru::List(_) => { - return Err(format!("expected token, got {}", x)); - } + Cirru::List(_) => Err(format!("expected token, got {}", x)), } } @@ -358,7 +356,7 @@ pub fn parse_fn_types(xs: &Cirru, collector: &mut LocalsCollector) -> Result<(Ve if &**t == "->" { ret_mode = true; } else { - let ty = parse_type_name(&**t)?; + let ty = parse_type_name(t)?; if ret_mode { returns.push(ty); } else { @@ -382,7 +380,7 @@ pub fn parse_fn_types(xs: &Cirru, collector: &mut LocalsCollector) -> Result<(Ve Cirru::List(_) => return Err(format!("invalid syntax, expected name, got {:?}", x)), }; let ty = match &zs[1] { - Cirru::Leaf(s) => parse_type_name(&**s)?, + Cirru::Leaf(s) => parse_type_name(s)?, Cirru::List(_) => return Err(format!("invalid syntax, expected type, got {:?}", x)), }; collector.track(&name_str); @@ -410,7 +408,7 @@ pub fn parse_block_types(xs: &Cirru) -> Result<(Vec, Vec), S if &**t == "->" { ret_mode = true; } else { - let ty = parse_type_name(&**t)?; + let ty = parse_type_name(t)?; if ret_mode { returns.push(ty); } else { diff --git a/src/primes.rs b/src/primes.rs index c6bd547..2d48b9c 100644 --- a/src/primes.rs +++ b/src/primes.rs @@ -19,12 +19,28 @@ pub enum Calx { // Link(Box, Box, Box), } -#[derive(Debug, Clone, PartialEq, PartialOrd, Decode, Encode)] +impl Calx { + // for runtime type checking + pub fn typed_as(&self, t: CalxType) -> bool { + match self { + Calx::Nil => t == CalxType::Nil, + Calx::Bool(_) => t == CalxType::Bool, + Calx::I64(_) => t == CalxType::I64, + Calx::F64(_) => t == CalxType::F64, + Calx::Str(_) => t == CalxType::Str, + Calx::List(_) => t == CalxType::List, + // Calx::Link(_, _, _) => t == CalxType::Link, + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Decode, Encode)] pub enum CalxType { Nil, Bool, I64, F64, + Str, List, Link, } @@ -193,7 +209,7 @@ impl CalxError { } } -#[derive(Debug, Clone, PartialEq, PartialOrd)] +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd)] pub struct BlockData { pub looped: bool, pub ret_types: Vec, diff --git a/src/vm.rs b/src/vm.rs index 490d872..d2d0afa 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -1,4 +1,4 @@ -use crate::primes::{BlockData, Calx, CalxError, CalxFrame, CalxFunc, CalxInstr}; +use crate::primes::{BlockData, Calx, CalxError, CalxFrame, CalxFunc, CalxInstr, CalxType}; use std::collections::hash_map::HashMap; use std::fmt; use std::ops::Rem; @@ -118,7 +118,7 @@ impl CalxVM { to, initial_stack_size: self.stack.len() - params_types.len(), }); - println!("TODO check params type: {:?}", params_types); + self.check_stack_for_block(¶ms_types)?; } CalxInstr::BlockEnd(looped) => { if looped { @@ -391,9 +391,6 @@ impl CalxVM { ret_types: f.ret_types, }; - // TODO check params type - println!("TODO check args: {:?}", f.params_types); - // start in new frame continue; } @@ -579,6 +576,20 @@ impl CalxVM { Ok(()) } + /// checks is given parameters on stack top + fn check_stack_for_block(&self, params: &[CalxType]) -> Result<(), CalxError> { + if self.stack.len() < params.len() { + return Err(self.gen_err(format!("stack size does not match given params: {:?} {:?}", self.stack, params))); + } + for (idx, t) in params.iter().enumerate() { + if self.stack[self.stack.len() - params.len() - 1 + idx].typed_as(t.to_owned()) { + continue; + } + return Err(self.gen_err(format!("stack type does not match given params: {:?} {:?}", self.stack, params))); + } + Ok(()) + } + #[inline(always)] fn check_func_return(&mut self) -> Result<(), CalxError> { if self.stack.len() != self.top_frame.initial_stack_size + self.top_frame.ret_types.len() {