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:
|
## <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.
|
||||||
|
|
|
@ -49,20 +49,8 @@ impl Compiler {
|
||||||
result.append(&mut self.compile(body.clone())?);
|
result.append(&mut self.compile(body.clone())?);
|
||||||
result.push(Instr::Return);
|
result.push(Instr::Return);
|
||||||
},
|
},
|
||||||
"print" => {
|
_ => {
|
||||||
result.append(&mut self.compile(cdr[0].clone())?);
|
result.append(&mut self.compile_intrinsic(call, &cdr)?);
|
||||||
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,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
_ => { dbg!(call); unimplemented!() },
|
_ => { dbg!(call); unimplemented!() },
|
||||||
} // End `match call`
|
} // End `match call`
|
||||||
|
@ -70,7 +58,7 @@ impl Compiler {
|
||||||
_ => { dbg!(car); unimplemented!() },
|
_ => { dbg!(car); unimplemented!() },
|
||||||
} // End `match car`
|
} // End `match car`
|
||||||
}, // End `Cons(car, cdr)`
|
}, // End `Cons(car, cdr)`
|
||||||
_ => { result.append(&mut self.compile_atom(src)?); },
|
_ => { result.append(&mut self.compile_atom(&src)?); },
|
||||||
} // End `match src`
|
} // End `match src`
|
||||||
|
|
||||||
break 'tco;
|
break 'tco;
|
||||||
|
@ -79,32 +67,95 @@ impl Compiler {
|
||||||
Ok(result)
|
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 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)
|
||||||
|
|
|
@ -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"),
|
||||||
|
|
|
@ -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); },
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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"
|
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 "--------------------------------------------------"
|
||||||
|
|
Loading…
Reference in a new issue