From 8f91098792809d64d91822d3ec07a4291e3c8abd Mon Sep 17 00:00:00 2001 From: MCorange Date: Mon, 13 Mar 2023 17:38:05 +0200 Subject: [PATCH] Added Else less if --- src/compile/linux_x86_64.rs | 26 +++++++++++++++++++-- src/constants.rs | 15 ++++++++---- src/interpret/linux_x86_64.rs | 26 +++++++++++++++++---- src/lexer.rs | 2 ++ src/parser.rs | 43 +++++++++++++++++++++++++++++------ test.mcl | 6 ++--- 6 files changed, 97 insertions(+), 21 deletions(-) diff --git a/src/compile/linux_x86_64.rs b/src/compile/linux_x86_64.rs index 9440f56..b31bafb 100644 --- a/src/compile/linux_x86_64.rs +++ b/src/compile/linux_x86_64.rs @@ -55,17 +55,22 @@ pub fn compile(tokens: Vec, args: Args) -> Result<()>{ writeln!(writer, "_start:")?; - - for token in tokens { + let mut ti = 0; + while ti < tokens.len() { + let token = &tokens[ti]; + writeln!(writer, "addr_{}:", ti)?; match token.typ { OpType::Push => { writeln!(writer, " ; -- PUSH {}", token.value)?; writeln!(writer, " mov rax, {}", token.value)?; writeln!(writer, " push rax")?; + ti += 1; + }, OpType::Pop => { writeln!(writer, " ; -- POP")?; writeln!(writer, " pop")?; + ti += 1; }, OpType::Plus => { writeln!(writer, " ; -- PLUS")?; @@ -73,6 +78,7 @@ pub fn compile(tokens: Vec, args: Args) -> Result<()>{ writeln!(writer, " pop rbx")?; writeln!(writer, " add rax, rbx")?; writeln!(writer, " push rax")?; + ti += 1; }, OpType::Minus => { writeln!(writer, " ; -- MINUS")?; @@ -80,6 +86,7 @@ pub fn compile(tokens: Vec, args: Args) -> Result<()>{ writeln!(writer, " pop rbx")?; writeln!(writer, " sub rbx, rax")?; writeln!(writer, " push rbx")?; + ti += 1; }, OpType::Equals => { writeln!(writer, " ; -- EQUALS")?; @@ -90,12 +97,27 @@ pub fn compile(tokens: Vec, args: Args) -> Result<()>{ writeln!(writer, " cmp rax, rbx")?; writeln!(writer, " cmove rcx, rdx")?; writeln!(writer, " push rcx")?; + ti += 1; }, OpType::Print => { writeln!(writer, " ; -- PRINT")?; writeln!(writer, " pop rdi")?; writeln!(writer, " call print")?; + ti += 1; + }, + OpType::If => { + writeln!(writer, " ; -- IF")?; + writeln!(writer, " pop rax")?; + writeln!(writer, " test rax, rax")?; + writeln!(writer, " jz addr_{}", token.value)?; + ti += 1; + }, + OpType::Else => { + ti += 1; + }, + OpType::End => { + ti += 1; }, } } diff --git a/src/constants.rs b/src/constants.rs index ae4e086..0cd6624 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -1,12 +1,15 @@ -#[derive(Debug)] +#[derive(Debug, Clone, PartialEq)] pub enum OpType { Push, Pop, Minus, Plus, Equals, - Print + Print, + If, + Else, + End, } @@ -15,17 +18,19 @@ pub enum OpType { // } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Operator { pub typ: OpType, pub value: i32, + pub pos: (String, u32, u32) } impl Operator { - pub fn new(typ: OpType, value: i32) -> Self { + pub fn new(typ: OpType, value: i32, file: String, row: u32, col: u32) -> Self { Self { typ, - value + value, + pos: (file, row, col) } } } diff --git a/src/interpret/linux_x86_64.rs b/src/interpret/linux_x86_64.rs index 26ce712..e7f1485 100644 --- a/src/interpret/linux_x86_64.rs +++ b/src/interpret/linux_x86_64.rs @@ -11,37 +11,55 @@ fn stack_pop(stack: &mut Vec) -> Result { pub fn run(tokens: Vec) -> Result<(), &'static str>{ let mut stack: Vec = Vec::new(); - - for token in tokens { + let mut ti = 0; + while ti < tokens.len() { + let token = &tokens[ti]; match token.typ { OpType::Push => { stack.push(token.value); + ti += 1; }, OpType::Pop => { stack.pop(); + ti += 1; }, OpType::Plus => { let a = stack_pop(&mut stack)?; let b = stack_pop(&mut stack)?; stack.push(b + a); + ti += 1; }, OpType::Minus => { let a = stack_pop(&mut stack)?; let b = stack_pop(&mut stack)?; stack.push(b - a); + ti += 1; }, OpType::Equals => { let a = stack_pop(&mut stack)?; let b = stack_pop(&mut stack)?; stack.push((a == b) as i32); - + ti += 1; }, - + OpType::Print => { let a = stack_pop(&mut stack)?; println!("{a}"); // let _ = io::stdout().flush(); + ti += 1; }, + OpType::If => { + let a = stack_pop(&mut stack)?; + if a == 0 { + ti = token.value as usize; + } + ti += 1; + }, + OpType::Else => { + ti += 1; + + }, + OpType::End => ti += 1 } } Ok(()) diff --git a/src/lexer.rs b/src/lexer.rs index fa2e79f..3d52d0b 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -2,6 +2,8 @@ use crate::constants::Token; use color_eyre::Result; + + pub fn find_col(text: String, mut col: u32, predicate: F) -> Result where F: Fn(char) -> bool { while (col as usize) < text.len() && !predicate(text.chars().nth(col as usize).unwrap()) { col += 1; diff --git a/src/parser.rs b/src/parser.rs index b6f9fe2..e16542a 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,6 +1,32 @@ use crate::{constants::{Operator, OpType, Token}, util}; use color_eyre::Result; +pub fn cross_ref(mut tokens: Vec) -> Vec { + let mut stack: Vec = Vec::new(); + for ip in 0..tokens.len() { + let op = &tokens.clone()[ip]; + match op.typ { + OpType::If => { + stack.push(ip as u32) + } + + OpType::End => { + let if_ip = stack.pop().unwrap(); + let mut if_og = &mut tokens[if_ip as usize]; + if !vec![OpType::If].contains(&(*if_og).typ) { + util::logger::pos_error(op.clone().pos,"'end' can only close 'if' blocks"); + std::process::exit(1); // idc + } + + (*if_og).value = ip as i32; + + } + _ => () + } + + } + tokens.clone() +} pub struct Parser { tokens: Vec @@ -21,14 +47,17 @@ impl Parser { match token.text.as_str() { t if t.parse::().is_ok() => { let num = t.parse::().unwrap(); - tokens.push(Operator::new(OpType::Push, num)); + tokens.push(Operator::new(OpType::Push, num, token.file.clone(), token.line, token.col)); }, - "pop" => tokens.push(Operator::new(OpType::Pop, 0)), - "+" => tokens.push(Operator::new(OpType::Plus, 0)), - "-" => tokens.push(Operator::new(OpType::Minus, 0)), - "print" => tokens.push(Operator::new(OpType::Print, 0)), - "=" => tokens.push(Operator::new(OpType::Equals, 0)), + "pop" => tokens.push(Operator::new(OpType::Pop, 0, token.file.clone(), token.line, token.col)), + "+" => 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)), t => { @@ -38,6 +67,6 @@ impl Parser { } } - Ok(tokens) + Ok(cross_ref(tokens)) } } \ No newline at end of file diff --git a/test.mcl b/test.mcl index 663c870..06ed952 100644 --- a/test.mcl +++ b/test.mcl @@ -1,3 +1,3 @@ -35 34 + 69 = print - -500 80 - print \ No newline at end of file +35 34 + 692 = if + 21 print +end \ No newline at end of file