@@ 57,6 57,18 @@ impl Codegen {
self.vm.chunk.push(OpCode::SUB.into());
self.vm.lines.last_mut().unwrap().1 += 1;
}
+ Mul => {
+ self.visit(right);
+ self.visit(left);
+ self.vm.chunk.push(OpCode::MUL.into());
+ self.vm.lines.last_mut().unwrap().1 += 1;
+ }
+ Div => {
+ self.visit(right);
+ self.visit(left);
+ self.vm.chunk.push(OpCode::DIV.into());
+ self.vm.lines.last_mut().unwrap().1 += 1;
+ }
_ => { panic!("not implemented") }
}
}
@@ 112,7 112,7 @@ pub fn compile(program: String) -> String {
#[cfg(feature = "timer")]
let vm_instant = Instant::now();
let mut vm = codegen.vm;
- match vm.run() {
+ match vm.run(&mut output) {
Ok(()) => {}
Err(e) => output += &e.to_string(),
}
@@ 20,7 20,7 @@ impl VM {
text: text.lines().map(|s| s.to_string()).collect(),
}
}
- pub fn run(&mut self) -> Result<(), KabelRuntimeError> {
+ pub fn run(&mut self, output: &mut String) -> Result<(), KabelRuntimeError> {
use Value::*;
while self.ip < self.chunk.len() {
match self.read() {
@@ 56,14 56,50 @@ impl VM {
}
}
}
+ 0x03 => { // MUL
+ match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) {
+ (Num(v1), Num(v2)) => self.stack.push(Num(v1 * v2)),
+ (Str(v1), Num(v2)) => {
+ if v2.fract() == 0.0 {
+ self.stack.push(Str(v1.repeat(v2 as usize)));
+ } else {
+ return Err(wrong_type!(self, "Number must be an integer"))
+ }
+ }
+ (Str(_v1), Str(_v2)) => {
+ return Err(wrong_type!(self, "Cannot multiply strings"))
+ },
+ (Bool(_v1), Bool(_v2)) => {
+ return Err(wrong_type!(self, "Cannot multiply booleans"))
+ }
+ (v1, v2) => {
+ return Err(mismatched_types!(self, "Mismatched types: {} and {}", v1.type_str(), v2.type_str()))
+ }
+ }
+ }
+ 0x04 => { // DIV
+ match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) {
+ (Num(v1), Num(v2)) => self.stack.push(Num(v1 / v2)),
+ (Str(_v1), Str(_v2)) => {
+ return Err(wrong_type!(self, "Cannot divide strings"))
+ },
+ (Bool(_v1), Bool(_v2)) => {
+ return Err(wrong_type!(self, "Cannot divide booleans"))
+ }
+ (v1, v2) => {
+ return Err(mismatched_types!(self, "Mismatched types: {} and {}", v1.type_str(), v2.type_str()))
+ }
+ }
+ }
0xFE => { // PRINT
let value = self.stack.pop().unwrap();
match value {
- Num(v) => println!("{}", v),
- Str(v) => println!("{}", v.to_string()),
- Bool(v) => println!("{}", v),
+ Num(v) => *output += &v.to_string(),
+ Str(v) => *output += &v,
+ Bool(v) => *output += &v.to_string(),
}
+ *output += "\n";
}
_ => {}
}
@@ 9,7 9,7 @@ fn main() {
let program =
fs::read_to_string(args[1].clone()).unwrap();*/
- let program = "print \"hello, \" + \"world\";".to_string();
+ let program = "print 4 / 5;".to_string();
let mut output = "".to_string();
@@ 47,7 47,7 @@ fn main() {
let codegen = run_codegen(program, ast);
let mut vm = codegen.vm;
- match vm.run() {
+ match vm.run(&mut output) {
Ok(()) => {}
Err(e) => output += &e.to_string(),
}