diff --git a/.gitignore b/.gitignore index ea8c4bf..3de0729 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +dm42 \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 6400e0d..0ecb82a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + [[package]] name = "anstream" version = "0.6.4" @@ -108,6 +117,7 @@ version = "0.1.0" dependencies = [ "anyhow", "clap", + "regex", ] [[package]] @@ -116,6 +126,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "memchr" +version = "2.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" + [[package]] name = "proc-macro2" version = "1.0.69" @@ -134,6 +150,35 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "regex" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + [[package]] name = "strsim" version = "0.10.0" diff --git a/Cargo.toml b/Cargo.toml index 6115cba..2eeeccd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,3 +6,4 @@ edition = "2021" [dependencies] anyhow = "1.0.75" clap = { version = "4.4.7", features = ["derive"] } +regex = "1.10.2" diff --git a/bin/const.dm42 b/bin/const.dm42 new file mode 100644 index 0000000..2e64219 --- /dev/null +++ b/bin/const.dm42 @@ -0,0 +1,27 @@ +// Allows using various constants +// Flag 3 - Exit to custom menu + +export def const { + CLMENU + "c", KEY 1 GTO light_speed + "h", KEY 2 GTO planck_constant + "e", KEY 3 GTO elementary_charge + "N↓A", KEY 4 GTO avogadro_constant + // KEY 8 GTO page_2 + if { FS? 03 } { + KEY 9 GTO custom_menu + } + MENU + STOP +} + +def custom_menu { + SF 27 +} + +// == CONSTANTS == + +def light_speed { 299792458 } +def planck_constant { 6.62607015e-34 } +def elementary_charge { 1.602176634e-19 } +def avogadro_constant { 6.02214076e23 } \ No newline at end of file diff --git a/test.dm42 b/bin/sort.dm42 similarity index 100% rename from test.dm42 rename to bin/sort.dm42 diff --git a/out.free42 b/out.free42 index c5edce4..cec02fe 100644 --- a/out.free42 +++ b/out.free42 @@ -1,34 +1,35 @@ -LBL "sort" -MAT? -GTO 00 -GTO 01 +LBL "const" +CLMENU +"c" +KEY 1 GTO 01 +"h" +KEY 2 GTO 02 +"e" +KEY 3 GTO 03 +"N↓A" +KEY 4 GTO 04 +FS? 03 +GTO 06 +LBL 05 +MENU +STOP +RTN LBL 00 -STO "A" -INDEX "A" -1 -1 -STOIJ -DROPN 2 -GTO 03 +SF 27 +RTN +LBL 01 +299792458 +RTN LBL 02 -DROPN 2 -[MIN] -DROP -RCLIJ -DROP -R<>R -DROPN 2 -I+ +6.62607015e-34 +RTN LBL 03 -FC? 76 -GTO 02 -DROPN 2 -RCL "A" +1.602176634e-19 RTN -LBL 01 -DROPN 2 -"X is not a matrix" -AVIEW -STOP -GTO 00 +LBL 04 +6.02214076e23 +RTN +LBL 06 +KEY 9 GTO 00 +GTO 05 RTN diff --git a/src/codegen.rs b/src/codegen.rs index c2af68d..b6e09c1 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -1,5 +1,7 @@ use std::borrow::Cow; +use regex::Regex; + use crate::{ ident::FreeIdent, misc::OrderedMap, @@ -40,7 +42,9 @@ impl CodeGen { } fn get_function(&mut self, name: &str) -> &mut Function { - self.functions.get_mut(name).expect("Function not found") + self.functions + .get_mut(name) + .expect(format!("Function `{}` not found", name).as_str()) } fn new_ident(&mut self) -> String { @@ -102,6 +106,7 @@ fn _generate(codegen: &mut CodeGen, tokens: Vec, function: String) { if body.is_empty() && else_body.is_empty() { continue; } + let is_raw = condition.is_raw(); gen_condition(codegen, condition, function.clone()); let end_label = codegen.new_ident(); @@ -111,7 +116,9 @@ fn _generate(codegen: &mut CodeGen, tokens: Vec, function: String) { push_ins(codegen, format!("GTO {true_label}")); let mut fun = Function::new_private(true_label.clone()); - fun.ins("DROPN 2".to_owned()); + if !is_raw { + fun.ins("DROPN 2".to_owned()); + } codegen.functions.insert(true_label.clone(), fun); _generate(codegen, body, true_label.clone()); codegen @@ -128,14 +135,16 @@ fn _generate(codegen: &mut CodeGen, tokens: Vec, function: String) { push_ins(codegen, format!("GTO {false_label}")); let mut fun = Function::new_private(false_label.clone()); - fun.ins("DROPN 2".to_owned()); + if !is_raw { + fun.ins("DROPN 2".to_owned()); + } codegen.functions.insert(false_label.clone(), fun); _generate(codegen, else_body, false_label.clone()); codegen .get_function(&false_label) .body .push(format!("GTO {end_label}")); - } else { + } else if !is_raw { push_ins(codegen, "DROPN 2".to_owned()); } @@ -164,11 +173,25 @@ fn _generate(codegen: &mut CodeGen, tokens: Vec, function: String) { push_ins(codegen, format!("GTO {loop_start}")); push_ins(codegen, "DROPN 2".to_owned()); } - Token::Instruction(ins) => codegen.get_function(&function).body.push(ins), + Token::Instruction(ins) => { + let ins = transform_instruction(codegen, ins); + push_ins(codegen, ins); + } } } } +fn transform_instruction(codegen: &mut CodeGen, mut ins: String) -> String { + // Todo, clean this up + for (name, func) in codegen.functions.iter() { + let regex = Regex::new(&format!("\\b{name}\\b")).unwrap(); + ins = regex + .replace(&ins, format!("{}", func.ident())) + .into_owned(); + } + ins +} + fn gen_condition(codegen: &mut CodeGen, condition: Condition, function: String) { match condition { Condition::Comparison { a, b, comparison } => { diff --git a/src/token.rs b/src/token.rs index 8f05ab9..98983c4 100644 --- a/src/token.rs +++ b/src/token.rs @@ -47,6 +47,12 @@ pub enum Comparison { Lte, } +impl Condition { + pub fn is_raw(&self) -> bool { + matches!(self, Condition::Raw { .. }) + } +} + impl Comparison { pub fn instruction(&self) -> &str { match self { diff --git a/src/tokenize.rs b/src/tokenize.rs index f7e32ae..d906fda 100644 --- a/src/tokenize.rs +++ b/src/tokenize.rs @@ -4,8 +4,6 @@ use anyhow::{bail, Context, Result}; use crate::token::{Comparison, Condition, Token}; -const COMMENT_CHARS: &[char] = &['#', ';', '@']; - pub struct Tokenizer { chars: Vec, idx: usize,