From 5ec182ab58fc6c0e08c9d9e01ddce8590f93c2e7 Mon Sep 17 00:00:00 2001 From: MCorange Date: Tue, 14 Mar 2023 00:43:16 +0200 Subject: [PATCH] added while loops --- src/compile/linux_x86_64.rs | 15 +++++++- src/constants.rs | 4 +- src/interpret/linux_x86_64.rs | 18 ++++++++- src/parser.rs | 69 +++++++++++++++++++++++++---------- test.mcl | 9 +++-- 5 files changed, 89 insertions(+), 26 deletions(-) diff --git a/src/compile/linux_x86_64.rs b/src/compile/linux_x86_64.rs index 3f2f554..2753319 100644 --- a/src/compile/linux_x86_64.rs +++ b/src/compile/linux_x86_64.rs @@ -58,6 +58,7 @@ pub fn compile(tokens: Vec, args: Args) -> Result<()>{ let mut ti = 0; while ti < tokens.len() { let token = &tokens[ti]; + writeln!(writer, "addr_{}:", ti)?; match token.typ { OpType::Push => { @@ -152,13 +153,25 @@ pub fn compile(tokens: Vec, args: Args) -> Result<()>{ writeln!(writer, " jmp addr_{}", token.value)?; ti += 1; }, + OpType::While => { + writeln!(writer, " ; -- WHILE")?; + ti += 1; + } + OpType::Do => { + writeln!(writer, " ; -- DO")?; + writeln!(writer, " pop rax")?; + writeln!(writer, " test rax, rax")?; + writeln!(writer, " jz addr_{}", token.value)?; + ti += 1; + } OpType::End => { writeln!(writer, " ; -- END")?; + writeln!(writer, " jmp addr_{}", token.value)?; ti += 1; }, } } - + writeln!(writer, "addr_{}:", ti)?; writeln!(writer, " mov rax, 60")?; writeln!(writer, " mov rdi, 0")?; writeln!(writer, " syscall")?; diff --git a/src/constants.rs b/src/constants.rs index 2c61ecc..dafbcc6 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -12,7 +12,9 @@ pub enum OpType { End, Dup, Gt, - Lt + Lt, + While, + Do } diff --git a/src/interpret/linux_x86_64.rs b/src/interpret/linux_x86_64.rs index f25a6dc..44760d6 100644 --- a/src/interpret/linux_x86_64.rs +++ b/src/interpret/linux_x86_64.rs @@ -14,6 +14,7 @@ pub fn run(tokens: Vec) -> Result<(), &'static str>{ let mut ti = 0; while ti < tokens.len() { let token = &tokens[ti]; + match token.typ { OpType::Push => { stack.push(token.value); @@ -65,6 +66,7 @@ pub fn run(tokens: Vec) -> Result<(), &'static str>{ let a = stack_pop(&mut stack)?; stack.push(a); stack.push(a); + ti += 1; }, OpType::If => { let a = stack_pop(&mut stack)?; @@ -78,7 +80,21 @@ pub fn run(tokens: Vec) -> Result<(), &'static str>{ ti = token.value as usize; }, - OpType::End => ti += 1 + + OpType::While => { + ti += 1; + } + OpType::Do => { + let a = stack.pop().unwrap(); + if a == 0 { + ti = token.value as usize; + } else { + ti += 1; + } + } + OpType::End => { + ti = token.value as usize; + } } } Ok(()) diff --git a/src/parser.rs b/src/parser.rs index 23d657e..6a23a96 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -9,19 +9,6 @@ pub fn cross_ref(mut tokens: Vec) -> Vec { OpType::If => { stack.push(ip as u32) } - - OpType::End => { - let block_ip = stack.pop().unwrap(); - let mut block_og = &mut tokens[block_ip as usize]; - if vec![OpType::If, OpType::Else].contains(&(*block_og).typ) { - (*block_og).value = ip as i32; - tokens[block_ip as usize] = block_og.clone(); - } else { - util::logger::pos_error(op.clone().pos,"'end' can only close 'if' blocks"); - std::process::exit(1); // idc - } - - } OpType::Else => { let if_ip = stack.pop().unwrap(); let mut if_og = &mut tokens[if_ip as usize]; @@ -30,7 +17,42 @@ pub fn cross_ref(mut tokens: Vec) -> Vec { std::process::exit(1); // idc } - (*if_og).value = ip as i32; + (*if_og).value = (ip + 1) as i32; + stack.push(ip as u32); + }, + OpType::End => { + let block_ip = stack.pop().unwrap(); + let mut block_og = &mut tokens[block_ip as usize].clone(); + if vec![OpType::If, OpType::Else].contains(&(*block_og).typ) { + + (*block_og).value = ip as i32; + tokens[block_ip as usize] = block_og.clone(); + + let do_og = &mut tokens[ip as usize].clone(); + do_og.value = (ip + 1) as i32; + + tokens[ip as usize] = (*do_og).clone(); + + } else if (*block_og).typ == OpType::Do { + let do_og = &mut tokens[ip as usize]; + do_og.value = block_og.value; + + tokens[ip as usize] = (*do_og).clone(); + let mut block_og = block_og.clone(); + block_og.value = (ip + 1) as i32; + tokens[block_ip as usize] = block_og.clone(); + } else { + util::logger::pos_error(op.clone().pos,"'end' can only close 'if' blocks"); + std::process::exit(1); // idc + } + + } + OpType::While => { + stack.push(ip as u32); + } + OpType::Do => { + let while_ip = stack.pop().unwrap(); + (&mut tokens[ip as usize]).value = while_ip as i32; stack.push(ip as u32); } _ => () @@ -65,17 +87,26 @@ impl Parser { tokens.push(Operator::new(OpType::Push, num, token.file.clone(), token.line, token.col)); }, + "print" => tokens.push(Operator::new(OpType::Print, 0, token.file.clone(), token.line, token.col)), + + // stack + "dup" => tokens.push(Operator::new(OpType::Dup, 0, token.file.clone(), token.line, token.col)), "pop" => tokens.push(Operator::new(OpType::Pop, 0, token.file.clone(), token.line, token.col)), + + // comp and math "+" => tokens.push(Operator::new(OpType::Plus, 0, token.file.clone(), token.line, token.col)), "-" => tokens.push(Operator::new(OpType::Minus, 0, token.file.clone(), token.line, token.col)), - "print" => tokens.push(Operator::new(OpType::Print, 0, token.file.clone(), token.line, token.col)), "=" => tokens.push(Operator::new(OpType::Equals, 0, token.file.clone(), token.line, token.col)), - "if" => tokens.push(Operator::new(OpType::If, 0, token.file.clone(), token.line, token.col)), - "else" => tokens.push(Operator::new(OpType::Else, 0, token.file.clone(), token.line, token.col)), - "end" => tokens.push(Operator::new(OpType::End, 0, token.file.clone(), token.line, token.col)), - "dup" => tokens.push(Operator::new(OpType::Dup, 0, token.file.clone(), token.line, token.col)), ">" => tokens.push(Operator::new(OpType::Gt, 0, token.file.clone(), token.line, token.col)), "<" => tokens.push(Operator::new(OpType::Lt, 0, token.file.clone(), token.line, token.col)), + + // block + "if" => tokens.push(Operator::new(OpType::If, 0, token.file.clone(), token.line, token.col)), + "else" => tokens.push(Operator::new(OpType::Else, 0, token.file.clone(), token.line, token.col)), + "end" => tokens.push(Operator::new(OpType::End, 0, token.file.clone(), token.line, token.col)), + "while" => tokens.push(Operator::new(OpType::While, 0, token.file.clone(), token.line, token.col)), + "do" => tokens.push(Operator::new(OpType::Do, 0, token.file.clone(), token.line, token.col)), + t => { diff --git a/test.mcl b/test.mcl index ab3029f..c5b077f 100644 --- a/test.mcl +++ b/test.mcl @@ -1,5 +1,6 @@ -2 1 < if - 1 print -else - 0 print +10 while dup 0 > do + dup print + 1 - end + +696969 print \ No newline at end of file