1
1
Fork 0
mirror of https://github.com/azur1s/bobbylisp.git synced 2024-09-28 07:27:35 +00:00

feat: +-*/ and swap

This commit is contained in:
Natapat Samutpong 2022-01-28 07:07:38 +07:00
parent 56f1e24947
commit dc3d400d50
7 changed files with 95 additions and 28 deletions

View file

@ -23,7 +23,10 @@ Hello, World!
## <img src="https://raw.githubusercontent.com/azur1s/bobbylisp/master/assets/icon.png" width="25"> Progress: ## <img src="https://raw.githubusercontent.com/azur1s/bobbylisp/master/assets/icon.png" width="25"> Progress:
DONE: DONE:
- Parsing, Compiling, Running(VM) - Parsing, Compiling, Running(VM)
- Intrinsic: `fun`, `do`, `print` - Intrinsic:
- `fun`, `do`, `print`
- Math:
TODO: TODO:
- Do the intrinsic left - Do the intrinsic left
- Quote, Quasiquote, etc. - Quote, Quasiquote, etc.

View file

@ -49,8 +49,30 @@ impl Compiler {
result.append(&mut self.compile(body.clone())?); result.append(&mut self.compile(body.clone())?);
result.push(Instr::Return); result.push(Instr::Return);
}, },
_ => {
result.append(&mut self.compile_intrinsic(call, &cdr)?);
}
_ => { dbg!(call); unimplemented!() },
} // End `match call`
}, // End `Symbol(call)`
_ => { dbg!(car); unimplemented!() },
} // End `match car`
}, // End `Cons(car, cdr)`
_ => { result.append(&mut self.compile_atom(&src)?); },
} // End `match src`
break 'tco;
} // End `loop`
Ok(result)
}
fn compile_intrinsic(&mut self, intrinsic: &String, args: &[Sexpr]) -> Result<Vec<Instr>, String> {
let mut result = Vec::new();
match intrinsic.as_str() {
"print" => { "print" => {
result.append(&mut self.compile(cdr[0].clone())?); result.append(&mut self.compile(args[0].clone())?);
let to = self.next_register(); let to = self.next_register();
let call_register = self.next_register(); let call_register = self.next_register();
@ -63,48 +85,77 @@ impl Compiler {
address: call_register, address: call_register,
args: to, args: to,
}); });
} },
_ => { dbg!(call); unimplemented!() }, "add" | "+" => {
} // End `match call` let mut lhs = self.compile_atom(&args[0])?;
}, // End `Symbol(call)` result.append(&mut lhs);
_ => { dbg!(car); unimplemented!() },
} // End `match car`
}, // End `Cons(car, cdr)`
_ => { result.append(&mut self.compile_atom(src)?); },
} // End `match src`
break 'tco; let mut rhs = self.compile_atom(&args[1])?;
} // End `loop` 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) Ok(result)
} }
fn compile_atom(&mut self, atom: Sexpr) -> Result<Vec<Instr>, String> { fn compile_atom(&mut self, atom: &Sexpr) -> Result<Vec<Instr>, String> {
let mut result = Vec::new(); let mut result = Vec::new();
let comp = atom.clone(); // Used for commenting let comp = atom.clone(); // Used for commenting
match atom { match atom {
Int(i) => { Int(i) => {
result.push(Instr::Comment { text: format!("----- {}", comp) }); 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) => { Float(f) => {
result.push(Instr::Comment { text: format!("----- {}", comp) }); 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) => { Str(s) => {
result.push(Instr::Comment { text: format!("----- {}", comp) }); 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) => { Boolean(b) => {
result.push(Instr::Comment { text: format!("----- {}", comp) }); 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) => { Symbol(s) => {
result.push(Instr::Comment { text: format!("----- {} variable", comp) }); result.push(Instr::Comment { text: format!("----- {} variable", comp) });
result.push(Instr::Jump { to: format!("function_{}", s), }); result.push(Instr::Jump { to: format!("function_{}", s), });
}, },
_ => { dbg!(atom); unimplemented!() }, _ => { result.append(&mut self.compile(atom.clone())?); }
} }
Ok(result) Ok(result)

View file

@ -5,7 +5,7 @@ use crate::vm::vm::Error::{self, InvalidAriphmeticOperation};
/// Literal types for the assembler. /// Literal types for the assembler.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum Type { pub enum Type {
Null, StackGuard, Null,
Int(i64), Int(i64),
Float(f64), Float(f64),
Boolean(bool), Boolean(bool),
@ -183,7 +183,7 @@ pub enum Instr {
// Call intrinsic function. // Call intrinsic function.
Call { address: Register, args: Register }, Call { address: Register, args: Register },
// Stack operations. // Stack operations.
Push { value: Type }, Pop { address: Register }, Push { value: Type }, Pop { address: Register }, Swap,
// Stack arithmetic. // Stack arithmetic.
Add, Sub, Add, Sub,
Mul, Div, Mul, Div,
@ -205,6 +205,7 @@ impl Display for Instr {
Instr::Call { address, args } => write!(f, " CALL {} {}", address, args), Instr::Call { address, args } => write!(f, " CALL {} {}", address, args),
Instr::Push { value } => write!(f, " PUSH {}", value), Instr::Push { value } => write!(f, " PUSH {}", value),
Instr::Pop { address } => write!(f, " POP {}", address), Instr::Pop { address } => write!(f, " POP {}", address),
Instr::Swap => write!(f, " SWAP"),
Instr::Add => write!(f, " ADD"), Instr::Add => write!(f, " ADD"),
Instr::Sub => write!(f, " SUB"), Instr::Sub => write!(f, " SUB"),
Instr::Mul => write!(f, " MUL"), Instr::Mul => write!(f, " MUL"),

View file

@ -26,6 +26,7 @@ pub fn parse_instr(src: &str) -> Vec<Instr> {
}); }, }); },
"PUSH" => { result.push(Instr::Push { value: value!(tokens[1]) }); }, "PUSH" => { result.push(Instr::Push { value: value!(tokens[1]) }); },
"POP" => { result.push(Instr::Pop { address: register!(tokens[1]) }); }, "POP" => { result.push(Instr::Pop { address: register!(tokens[1]) }); },
"SWAP" => { result.push(Instr::Swap); },
"ADD" => { result.push(Instr::Add); }, "ADD" => { result.push(Instr::Add); },
"SUB" => { result.push(Instr::Sub); }, "SUB" => { result.push(Instr::Sub); },
"MUL" => { result.push(Instr::Mul); }, "MUL" => { result.push(Instr::Mul); },

View file

@ -45,17 +45,19 @@ impl VM {
} }
pub fn run(&mut self, instrs: Vec<Instr>, debug: bool) -> VMReturn { pub fn run(&mut self, instrs: Vec<Instr>, debug: bool) -> VMReturn {
let mut result: VMReturn; let result: VMReturn;
let mut found = false;
for (idx, instr) in instrs.iter().enumerate() { for (idx, instr) in instrs.iter().enumerate() {
match instr { match instr {
Label { name } => { 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)); self.function_pointer.push((name.clone(), idx as isize));
}, },
_ => {} _ => {}
} }
} }
if !found { return Err(Error::NoMainFunction); }
'tco: loop { 'tco: loop {
self.instr_pointer += 1; self.instr_pointer += 1;
@ -65,6 +67,7 @@ impl VM {
} }
let instr = &instrs[(self.instr_pointer - 1) as usize]; let instr = &instrs[(self.instr_pointer - 1) as usize];
if debug { print_debug(self, &instr); }
match instr { match instr {
Store { address, value, .. } => { Store { address, value, .. } => {
self.store(&address, &value)?; self.store(&address, &value)?;
@ -85,6 +88,13 @@ impl VM {
self.store(&address, &value.unwrap())?; self.store(&address, &value.unwrap())?;
continue 'tco; 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 => { Add => {
let lhs = self.stack.pop().unwrap(); let lhs = self.stack.pop().unwrap();
let rhs = self.stack.pop().unwrap(); let rhs = self.stack.pop().unwrap();

View file

@ -1 +1,2 @@
(print (/ (+ 345 345) 10)) (fun main
(print (/ (+ 345 345) 10)))

View file

@ -7,7 +7,7 @@ blspc compile $noext.blsp
echo -e "------------------------------------------- SOURCE" echo -e "------------------------------------------- SOURCE"
cat $noext.blsp cat $noext.blsp
echo -e "\n----------------------------------------- COMPILED" echo -e "\n----------------------------------------- COMPILED"
cat $noext.bsm cat $name.bsm
echo -e "------------------------------------------- OUTPUT" echo -e "------------------------------------------- OUTPUT"
blspc run $name.bsm blspc run $name.bsm
echo -e "--------------------------------------------------" echo -e "--------------------------------------------------"