diff --git a/src/compiler.rs b/src/compiler.rs index cfdc986..f60c267 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -202,6 +202,10 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec, va ops.push(Operation { opcode: 24, arg1: Some(condition_reg), arg2: Some(condition_reg as i64), arg3: None }); //Update the lastif variable + if !var_ids.contains_key("__LASTIF") { + var_ids.insert(String::from("__LASTIF"), *next_var_id); + *next_var_id += 1; + } ops.push(Operation { opcode: 7, arg1: Some(condition_reg), arg2: Some(var_ids["__LASTIF"] as i64), arg3: None }); set_register(registers, RegisterState { id: condition_reg, used: true, variable: var_ids["__LASTIF"], last_used: *op_count }); @@ -280,6 +284,10 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec, va ops.push(Operation { opcode: 24, arg1: Some(condition_reg), arg2: Some(condition_reg as i64), arg3: None }); //Update the lastif variable + if !var_ids.contains_key("__LASTIF") { + var_ids.insert(String::from("__LASTIF"), *next_var_id); + *next_var_id += 1; + } ops.push(Operation { opcode: 7, arg1: Some(condition_reg), arg2: Some(var_ids["__LASTIF"] as i64), arg3: None }); set_register(registers, RegisterState { id: condition_reg, used: true, variable: var_ids["__LASTIF"], last_used: *op_count }); @@ -301,6 +309,61 @@ fn do_ast_op(ast_op: ASTPart, op_count: &mut usize, ops: &mut Vec, va } garbage_collect_registers(registers); }, + ASTPart::While(while_part) => { + let start = ops.len(); + let condition_reg = do_ast_op(*while_part.condition, op_count, ops, var_ids, next_var_id, strings, next_string_id, functions, next_function_id, registers); + ops.push(Operation { opcode: 30, arg1: Some(condition_reg), arg2: Some(2), arg3: None }); + ops.push(Operation { opcode: 24, arg1: Some(condition_reg), arg2: Some(condition_reg as i64), arg3: None }); + + let op_placeholder = ops.len(); + let mut breaks: Vec = vec![]; + let mut continues: Vec = vec![]; + ops.push(Operation { opcode: 0, arg1: None, arg2: None, arg3: None }); + for while_op in while_part.body { + match while_op { + ASTPart::Break(_) => { + breaks.push(ops.len()); + ops.push(Operation { opcode: 0, arg1: None, arg2: None, arg3: None }); + }, + ASTPart::Continue(_) => { + continues.push(ops.len()); + ops.push(Operation { opcode: 0, arg1: None, arg2: None, arg3: None }); + }, + _ => { + do_ast_op(while_op, op_count, ops, var_ids, next_var_id, strings, next_string_id, functions, next_function_id, registers); + } + } + } + ops.push(Operation { opcode: 25, arg1: Some(condition_reg), arg2: Some(start as i64), arg3: None }); + ops[op_placeholder] = Operation { + opcode: 26, + arg1: Some(condition_reg), + arg2: Some(ops.len() as i64), + arg3: None, + }; + for brk in breaks { + ops[brk] = Operation { + opcode: 25, + arg1: None, + arg2: Some(ops.len() as i64), + arg3: None, + }; + } + for cont in continues { + ops[cont] = Operation { + opcode: 25, + arg1: None, + arg2: Some(start as i64), + arg3: None, + }; + } + }, + ASTPart::Break(_) => { + panic!("Unexpected break outside of loop at {}", op_count); + }, + ASTPart::Continue(_) => { + panic!("Unexpected continue outside of loop at {}", op_count); + }, ASTPart::Operation(op) => { let left_reg = do_ast_op(*op.left, op_count, ops, var_ids, next_var_id, strings, next_string_id, functions, next_function_id, registers); let right_reg = do_ast_op(*op.right, op_count, ops, var_ids, next_var_id, strings, next_string_id, functions, next_function_id, registers); @@ -374,9 +437,6 @@ fn compile_function(ast: Vec, args: Option>, registers: &mu let mut functions: HashMap = HashMap::new(); let mut next_function_id: u32 = 1; - var_ids.insert(String::from("__LASTIF"), next_var_id); - next_var_id += 1; - match args { Some(arg_list) => { for arg in arg_list {