Skip to content

Commit

Permalink
Merge pull request #11 from calcit-lang/binary
Browse files Browse the repository at this point in the history
initial support for generating binary and evaluating from binary
  • Loading branch information
NoEgAm authored Jul 18, 2022
2 parents 997bc85 + 4c3ea6c commit 66b1f6c
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 29 deletions.
11 changes: 6 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "calx_vm"
version = "0.1.2"
version = "0.1.3"
authors = ["jiyinyiyong <[email protected]>"]
edition = "2018"
license = "MIT"
Expand All @@ -16,10 +16,11 @@ exclude = [
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
cirru_parser = "0.1.17"
regex = "1.5.4"
cirru_parser = "0.1.23"
regex = "1.6.0"
lazy_static = "1.4.0"
clap = "3.1.5"
clap = "3.2.12"
bincode = "2.0.0-rc.1"

[profile.release]
debug = true
debug = true
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ calx -S hello.cirru
calx -D hello.cirru
```

`--emit-binary filename` for encode functions into a binary file.

`--eval-binary` for reading a binary input file to run.

### Syntax Sugar

Code of:
Expand Down
61 changes: 52 additions & 9 deletions src/bin/calx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,26 +28,69 @@ fn main() -> Result<(), String> {
.help("disabled preprocess")
.takes_value(false),
)
.arg(
Arg::new("EMIT_BINARY")
.long("emit-binary")
.value_name("emit-binary")
.help("emit binary, rather than running")
.takes_value(true),
)
.arg(
Arg::new("EVALUATE_BINARY")
.long("eval-binary")
.value_name("eval-binary")
.help("evaluate program from binary")
.takes_value(false),
)
.arg(Arg::new("SOURCE").help("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 disable_pre = matches.is_present("DISABLE_PRE");

let contents = fs::read_to_string(source).expect("Cirru file for instructions");
let xs = parse(&contents).expect("Some Cirru content");
let emit_binary = matches.is_present("EMIT_BINARY");
let eval_binary = matches.is_present("EVALUATE_BINARY");

let mut fns: Vec<CalxFunc> = vec![];
for x in xs {
if let Cirru::List(ys) = x {
let f = parse_function(&ys)?;
fns.push(f);
} else {
panic!("expected top level expressions");

if eval_binary {
let code = fs::read(source).expect("read binar from source file");
fns = bincode::decode_from_slice(&code, bincode::config::standard())
.expect("decode functions from binary")
.0;
} else {
let contents = fs::read_to_string(source).expect("Cirru file for instructions");
let xs = parse(&contents).expect("Some Cirru content");

for x in xs {
if let Cirru::List(ys) = x {
let f = parse_function(&ys)?;
fns.push(f);
} else {
panic!("expected top level expressions");
}
}
}

if emit_binary {
let mut slice = [0u8; 10000];
let length = match bincode::encode_into_slice(&fns, &mut slice, bincode::config::standard()) {
Ok(l) => {
println!("encoded binary length: {}", l);
l
}
Err(e) => panic!("failed on default length of 10000: {}", e),
};
let slice = &slice[..length];
let target_file = matches.value_of("EMIT_BINARY").unwrap();
match fs::write(target_file, slice) {
Ok(_) => println!("wrote binary to {}", target_file),
Err(e) => panic!("failed to write binary to {}: {}", target_file, e),
};
return Ok(());
// println!("Bytes written: {:?}", slice);
}

let mut imports: CalxImportsDict = HashMap::new();
imports.insert(String::from("log"), (log_calx_value, 1));
imports.insert(String::from("log2"), (log_calx_value, 2));
Expand Down
8 changes: 4 additions & 4 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ pub fn parse_function(nodes: &[Cirru]) -> Result<CalxFunc, String> {
}

Ok(CalxFunc {
name,
name: name.to_string(),
params_types,
ret_types,
instrs: body,
Expand Down Expand Up @@ -210,7 +210,7 @@ pub fn parse_instr(ptr_base: usize, node: &Cirru) -> Result<Vec<CalxInstr>, Stri
Cirru::List(_) => return Err(format!("expected a name, got {:?}", xs[1])),
};

Ok(vec![CalxInstr::Call(name)])
Ok(vec![CalxInstr::Call((*name).to_owned())])
}
"call-import" => {
if xs.len() != 2 {
Expand All @@ -221,7 +221,7 @@ pub fn parse_instr(ptr_base: usize, node: &Cirru) -> Result<Vec<CalxInstr>, Stri
Cirru::List(_) => return Err(format!("expected a name, got {:?}", xs[1])),
};

Ok(vec![CalxInstr::CallImport(name)])
Ok(vec![CalxInstr::CallImport((*name).to_owned())])
}
"unreachable" => Ok(vec![CalxInstr::Unreachable]),
"nop" => Ok(vec![CalxInstr::Nop]),
Expand Down Expand Up @@ -252,7 +252,7 @@ pub fn parse_instr(ptr_base: usize, node: &Cirru) -> Result<Vec<CalxInstr>, Stri
Cirru::List(_) => return Err(format!("assert expected a message, got {:?}", xs[1])),
};

Ok(vec![CalxInstr::Assert(message)])
Ok(vec![CalxInstr::Assert((*message).to_owned())])
}
_ => Err(format!("unknown instruction: {}", name)),
},
Expand Down
22 changes: 11 additions & 11 deletions src/primes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@
* (I'm not equiped enough for building a bytecode VM yet...)
*/

use bincode::{Decode, Encode};
use std::fmt;

/// Simplied from Calcit, but trying to be basic and mutable
#[derive(Debug, Clone, PartialEq, PartialOrd)]
#[derive(Debug, Clone, PartialEq, PartialOrd, Decode, Encode)]
pub enum Calx {
Nil,
Bool(bool),
Expand All @@ -18,10 +19,10 @@ pub enum Calx {
Str(String),
List(Vec<Calx>),
// to simultate linked structures
Link(Box<Calx>, Box<Calx>, Box<Calx>),
// Link(Box<Calx>, Box<Calx>, Box<Calx>),
}

#[derive(Debug, Clone, PartialEq, PartialOrd)]
#[derive(Debug, Clone, PartialEq, PartialOrd, Decode, Encode)]
pub enum CalxType {
Nil,
Bool,
Expand Down Expand Up @@ -52,15 +53,14 @@ impl fmt::Display for Calx {
}
f.write_str(")")?;
Ok(())
}
Calx::Link(..) => f.write_str("TODO LINK"),
} // Calx::Link(..) => f.write_str("TODO LINK"),
}
}
}

#[derive(Debug, Clone, PartialEq, PartialOrd)]
#[derive(Debug, Clone, PartialEq, PartialOrd, Encode, Decode)]
pub struct CalxFunc {
pub name: Box<str>,
pub name: String,
pub params_types: Vec<CalxType>,
pub ret_types: Vec<CalxType>,
pub instrs: Vec<CalxInstr>,
Expand All @@ -86,7 +86,7 @@ impl fmt::Display for CalxFunc {
}

/// learning from WASM but for dynamic data
#[derive(Debug, Clone, PartialEq, PartialOrd)]
#[derive(Debug, Clone, PartialEq, PartialOrd, Decode, Encode)]
pub enum CalxInstr {
// Param, // load variable from parameter
LocalSet(usize),
Expand Down Expand Up @@ -150,14 +150,14 @@ pub enum CalxInstr {
/// pop and println current value
Echo,
/// TODO use function name at first, during running, only use index,
Call(Box<str>),
CallImport(Box<str>),
Call(String),
CallImport(String),
Unreachable,
Nop,
Quit(usize), // quit and return value
Return,
/// TODO might also be a foreign function instead
Assert(Box<str>),
Assert(String),
}

#[derive(Debug, Clone, PartialEq, PartialOrd)]
Expand Down

0 comments on commit 66b1f6c

Please sign in to comment.