From dc3d400d50b15e62379b4194489ec43a8e1b1584 Mon Sep 17 00:00:00 2001 From: Natapat Samutpong Date: Fri, 28 Jan 2022 07:07:38 +0700 Subject: [PATCH] feat: +-*/ and swap --- README.md | 5 +- blspc/src/compiler/compile.rs | 93 +++++++++++++++++++++++++++-------- blspc/src/vm/instr.rs | 5 +- blspc/src/vm/parser.rs | 1 + blspc/src/vm/vm.rs | 14 +++++- example/math.blsp | 3 +- test.sh | 2 +- 7 files changed, 95 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 8a75231..9c10642 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,10 @@ Hello, World! ## Progress: DONE: - Parsing, Compiling, Running(VM) -- Intrinsic: `fun`, `do`, `print` +- Intrinsic: + - `fun`, `do`, `print` + - Math: + TODO: - Do the intrinsic left - Quote, Quasiquote, etc. diff --git a/blspc/src/compiler/compile.rs b/blspc/src/compiler/compile.rs index 4af76d0..4647a18 100644 --- a/blspc/src/compiler/compile.rs +++ b/blspc/src/compiler/compile.rs @@ -49,20 +49,8 @@ impl Compiler { result.append(&mut self.compile(body.clone())?); result.push(Instr::Return); }, - "print" => { - result.append(&mut self.compile(cdr[0].clone())?); - let to = self.next_register(); - let call_register = self.next_register(); - - result.push(Instr::Pop { address: to }); - result.push(Instr::Store { - address: call_register, - value: Type::Int(1), - }); - result.push(Instr::Call { - address: call_register, - args: to, - }); + _ => { + result.append(&mut self.compile_intrinsic(call, &cdr)?); } _ => { dbg!(call); unimplemented!() }, } // End `match call` @@ -70,7 +58,7 @@ impl Compiler { _ => { dbg!(car); unimplemented!() }, } // End `match car` }, // End `Cons(car, cdr)` - _ => { result.append(&mut self.compile_atom(src)?); }, + _ => { result.append(&mut self.compile_atom(&src)?); }, } // End `match src` break 'tco; @@ -78,33 +66,96 @@ impl Compiler { Ok(result) } + + fn compile_intrinsic(&mut self, intrinsic: &String, args: &[Sexpr]) -> Result, String> { + let mut result = Vec::new(); + + match intrinsic.as_str() { + "print" => { + result.append(&mut self.compile(args[0].clone())?); + let to = self.next_register(); + let call_register = self.next_register(); + + result.push(Instr::Pop { address: to }); + result.push(Instr::Store { + address: call_register, + value: Type::Int(1), + }); + result.push(Instr::Call { + address: call_register, + args: to, + }); + }, + "add" | "+" => { + let mut lhs = self.compile_atom(&args[0])?; + result.append(&mut lhs); + + let mut rhs = self.compile_atom(&args[1])?; + result.append(&mut rhs); + + result.push(Instr::Add); + }, + "sub" | "-" => { + let mut lhs = self.compile_atom(&args[0])?; + result.append(&mut lhs); + + let mut rhs = self.compile_atom(&args[1])?; + result.append(&mut rhs); + + result.push(Instr::Swap); + result.push(Instr::Sub); + }, + "mul" | "*" => { + let mut lhs = self.compile_atom(&args[0])?; + result.append(&mut lhs); + + let mut rhs = self.compile_atom(&args[1])?; + result.append(&mut rhs); + + result.push(Instr::Mul); + }, + "div" | "/" => { + let mut lhs = self.compile_atom(&args[0])?; + result.append(&mut lhs); + + let mut rhs = self.compile_atom(&args[1])?; + result.append(&mut rhs); + + result.push(Instr::Swap); + result.push(Instr::Div); + }, + _ => return Err(format!("Unknown intrinsic: {}", intrinsic)), + } + + Ok(result) + } - fn compile_atom(&mut self, atom: Sexpr) -> Result, String> { + fn compile_atom(&mut self, atom: &Sexpr) -> Result, String> { let mut result = Vec::new(); let comp = atom.clone(); // Used for commenting match atom { Int(i) => { result.push(Instr::Comment { text: format!("----- {}", comp) }); - result.push(Instr::Push { value: Type::Int(i) }); + result.push(Instr::Push { value: Type::Int(*i) }); }, Float(f) => { result.push(Instr::Comment { text: format!("----- {}", comp) }); - result.push(Instr::Push { value: Type::Float(f) }); + result.push(Instr::Push { value: Type::Float(*f) }); }, Str(s) => { result.push(Instr::Comment { text: format!("----- {}", comp) }); - result.push(Instr::Push { value: Type::String(s) }); + result.push(Instr::Push { value: Type::String(s.to_string()) }); }, Boolean(b) => { result.push(Instr::Comment { text: format!("----- {}", comp) }); - result.push(Instr::Push { value: Type::Boolean(b) }); + result.push(Instr::Push { value: Type::Boolean(*b) }); }, Symbol(s) => { result.push(Instr::Comment { text: format!("----- {} variable", comp) }); result.push(Instr::Jump { to: format!("function_{}", s), }); }, - _ => { dbg!(atom); unimplemented!() }, + _ => { result.append(&mut self.compile(atom.clone())?); } } Ok(result) diff --git a/blspc/src/vm/instr.rs b/blspc/src/vm/instr.rs index a910d94..d291277 100644 --- a/blspc/src/vm/instr.rs +++ b/blspc/src/vm/instr.rs @@ -5,7 +5,7 @@ use crate::vm::vm::Error::{self, InvalidAriphmeticOperation}; /// Literal types for the assembler. #[derive(Clone, Debug)] pub enum Type { - Null, StackGuard, + Null, Int(i64), Float(f64), Boolean(bool), @@ -183,7 +183,7 @@ pub enum Instr { // Call intrinsic function. Call { address: Register, args: Register }, // Stack operations. - Push { value: Type }, Pop { address: Register }, + Push { value: Type }, Pop { address: Register }, Swap, // Stack arithmetic. Add, Sub, Mul, Div, @@ -205,6 +205,7 @@ impl Display for Instr { Instr::Call { address, args } => write!(f, " CALL {} {}", address, args), Instr::Push { value } => write!(f, " PUSH {}", value), Instr::Pop { address } => write!(f, " POP {}", address), + Instr::Swap => write!(f, " SWAP"), Instr::Add => write!(f, " ADD"), Instr::Sub => write!(f, " SUB"), Instr::Mul => write!(f, " MUL"), diff --git a/blspc/src/vm/parser.rs b/blspc/src/vm/parser.rs index a9673a2..ed1e6c7 100644 --- a/blspc/src/vm/parser.rs +++ b/blspc/src/vm/parser.rs @@ -26,6 +26,7 @@ pub fn parse_instr(src: &str) -> Vec { }); }, "PUSH" => { result.push(Instr::Push { value: value!(tokens[1]) }); }, "POP" => { result.push(Instr::Pop { address: register!(tokens[1]) }); }, + "SWAP" => { result.push(Instr::Swap); }, "ADD" => { result.push(Instr::Add); }, "SUB" => { result.push(Instr::Sub); }, "MUL" => { result.push(Instr::Mul); }, diff --git a/blspc/src/vm/vm.rs b/blspc/src/vm/vm.rs index 9024a9c..dd420c1 100644 --- a/blspc/src/vm/vm.rs +++ b/blspc/src/vm/vm.rs @@ -45,17 +45,19 @@ impl VM { } pub fn run(&mut self, instrs: Vec, debug: bool) -> VMReturn { - let mut result: VMReturn; + let result: VMReturn; + let mut found = false; for (idx, instr) in instrs.iter().enumerate() { match instr { Label { name } => { - if name == "function_main" { self.instr_pointer = idx as isize; } + if name == "function_main" { self.instr_pointer = idx as isize; found = true; } self.function_pointer.push((name.clone(), idx as isize)); }, _ => {} } } + if !found { return Err(Error::NoMainFunction); } 'tco: loop { self.instr_pointer += 1; @@ -65,6 +67,7 @@ impl VM { } let instr = &instrs[(self.instr_pointer - 1) as usize]; + if debug { print_debug(self, &instr); } match instr { Store { address, value, .. } => { self.store(&address, &value)?; @@ -85,6 +88,13 @@ impl VM { self.store(&address, &value.unwrap())?; continue 'tco; }, + Swap => { + let top = self.stack.pop().unwrap(); + let bottom = self.stack.pop().unwrap(); + self.stack.push(top); + self.stack.push(bottom); + continue 'tco; + }, Add => { let lhs = self.stack.pop().unwrap(); let rhs = self.stack.pop().unwrap(); diff --git a/example/math.blsp b/example/math.blsp index 1cd1035..1f2ec3e 100644 --- a/example/math.blsp +++ b/example/math.blsp @@ -1 +1,2 @@ -(print (/ (+ 345 345) 10)) \ No newline at end of file +(fun main + (print (/ (+ 345 345) 10))) \ No newline at end of file diff --git a/test.sh b/test.sh index 7008903..51e622e 100755 --- a/test.sh +++ b/test.sh @@ -7,7 +7,7 @@ blspc compile $noext.blsp echo -e "------------------------------------------- SOURCE" cat $noext.blsp echo -e "\n----------------------------------------- COMPILED" -cat $noext.bsm +cat $name.bsm echo -e "------------------------------------------- OUTPUT" blspc run $name.bsm echo -e "--------------------------------------------------"