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:
parent
56f1e24947
commit
dc3d400d50
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"),
|
||||
|
|
|
@ -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); },
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
(print (/ (+ 345 345) 10))
|
||||
(fun main
|
||||
(print (/ (+ 345 345) 10)))
|
2
test.sh
2
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 "--------------------------------------------------"
|
||||
|
|
Loading…
Reference in a new issue