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 "--------------------------------------------------"