1
1
Fork 0
mirror of https://github.com/azur1s/bobbylisp.git synced 2024-10-16 02:37:40 -05: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:
DONE:
- Parsing, Compiling, Running(VM)
- Intrinsic: `fun`, `do`, `print`
- Intrinsic:
- `fun`, `do`, `print`
- Math:
TODO:
- Do the intrinsic left
- Quote, Quasiquote, etc.

View file

@ -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;
@ -79,32 +67,95 @@ impl Compiler {
Ok(result)
}
fn compile_atom(&mut self, atom: Sexpr) -> Result<Vec<Instr>, String> {
fn compile_intrinsic(&mut self, intrinsic: &String, args: &[Sexpr]) -> Result<Vec<Instr>, 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<Vec<Instr>, 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)

View file

@ -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"),

View file

@ -26,6 +26,7 @@ pub fn parse_instr(src: &str) -> Vec<Instr> {
}); },
"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); },

View file

@ -45,17 +45,19 @@ impl VM {
}
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() {
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();

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"
cat $noext.blsp
echo -e "\n----------------------------------------- COMPILED"
cat $noext.bsm
cat $name.bsm
echo -e "------------------------------------------- OUTPUT"
blspc run $name.bsm
echo -e "--------------------------------------------------"