From b23a9bd751031303ddf87d27c425be9947e1f73c Mon Sep 17 00:00:00 2001 From: Garrit Franke Date: Wed, 9 Dec 2020 08:49:26 +0100 Subject: [PATCH] Generalize block into own statement --- TODO | 1 - src/generator/js.rs | 33 +++++++++++++++++++++++-------- src/generator/x86.rs | 17 +++++++++------- src/parser/mod.rs | 43 ++++++++++++++++++++--------------------- src/parser/node_type.rs | 5 +++-- 5 files changed, 59 insertions(+), 40 deletions(-) diff --git a/TODO b/TODO index 1c468c0..1d8de1d 100644 --- a/TODO +++ b/TODO @@ -11,5 +11,4 @@ # Cleanups -- Generalize function/if/loop bodies into a "Block" node to remove redundancy - Improve error reporting (See ./util/string_util::highlight_position_in_file) diff --git a/src/generator/js.rs b/src/generator/js.rs index 1a9a57e..5a2009e 100644 --- a/src/generator/js.rs +++ b/src/generator/js.rs @@ -27,15 +27,26 @@ fn generate_function(func: Function) -> String { .join(", "); let mut raw = format!("function {N}({A})", N = func.name, A = arguments); - raw += " {\n"; + raw += &generate_block(func.body); - for statement in func.statements { - raw += &generate_statement(statement); + raw +} + +fn generate_block(block: Statement) -> String { + let mut generated = String::from("{\n"); + + let statements = match block { + Statement::Block(blk) => blk, + _ => panic!("Block body should be of type Statement::Block"), + }; + + for statement in statements { + generated += &generate_statement(statement); } - raw += "}\n"; + generated += "}\n"; - raw + generated } fn generate_statement(statement: Statement) -> String { @@ -44,8 +55,9 @@ fn generate_statement(statement: Statement) -> String { Statement::Declare(name, val) => generate_declare(name.name, val), Statement::Exp(val) => generate_expression(val), Statement::If(expr, if_state, else_state) => { - generate_conditional(expr, if_state, else_state.map(|x| *x)) + generate_conditional(expr, *if_state, else_state.map(|x| *x)) } + Statement::Block(_) => generate_block(statement), Statement::While(_, _) => todo!(), } } @@ -63,15 +75,20 @@ fn generate_expression(expr: Expression) -> String { fn generate_conditional( expr: Expression, - if_state: Vec, + if_state: Statement, else_state: Option, ) -> String { let expr_str = generate_expression(expr); + let body = match if_state { + Statement::Block(blk) => blk, + _ => panic!("Conditional body should be of type block"), + }; + let mut outcome = format!("if ({})", expr_str); outcome += "{\n"; - for statement in if_state { + for statement in body { outcome += &generate_statement(statement); } outcome += "}"; diff --git a/src/generator/x86.rs b/src/generator/x86.rs index 65056f9..6e60d98 100644 --- a/src/generator/x86.rs +++ b/src/generator/x86.rs @@ -67,13 +67,16 @@ impl X86Generator { fn gen_function(&mut self, func: Function) -> Assembly { let mut asm = Assembly::new(); - let has_return: bool = func.statements.iter().any(|s| { - if let Statement::Return(_) = *s { - true - } else { - false - } - }); + let has_return: bool = match &func.body { + Statement::Block(statements) => statements.iter().any(|s| { + if let Statement::Return(_) = *s { + true + } else { + false + } + }), + _ => panic!("Function body should be of type Block"), + }; asm.add(format!(".globl _{}", func.name)); asm.add(format!("_{}:", func.name)); diff --git a/src/parser/mod.rs b/src/parser/mod.rs index ca10991..8eef3a3 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -148,6 +148,22 @@ impl Parser { }) } + fn parse_block(&mut self) -> Result { + self.match_token(TokenKind::CurlyBracesOpen)?; + + let mut statements = vec![]; + + while let Err(_) = self.peek_token(TokenKind::CurlyBracesClose) { + let statement = self.parse_statement()?; + dbg!("{:?}", &statement); + statements.push(statement); + } + + self.match_token(TokenKind::CurlyBracesClose)?; + + Ok(Statement::Block(statements)) + } + fn parse_function(&mut self) -> Result { self.match_keyword(Keyword::Function)?; let name = self.match_identifier()?; @@ -162,22 +178,13 @@ impl Parser { }; self.match_token(TokenKind::BraceClose)?; - self.match_token(TokenKind::CurlyBracesOpen)?; - - let mut statements = vec![]; - - while let Err(_) = self.peek_token(TokenKind::CurlyBracesClose) { - let statement = self.parse_statement()?; - dbg!("{:?}", &statement); - statements.push(statement); - } - self.match_token(TokenKind::CurlyBracesClose)?; + let body = self.parse_block()?; Ok(Function { name: name, arguments: arguments, - statements: statements, + body: body, }) } @@ -305,27 +312,19 @@ impl Parser { fn parse_conditional_statement(&mut self) -> Result { self.match_keyword(Keyword::If)?; let condition = self.parse_expression()?; - self.match_token(TokenKind::CurlyBracesOpen)?; - - let mut statements = Vec::new(); - while let Err(_) = self.peek_token(TokenKind::CurlyBracesClose) { - let statement = self.parse_statement()?; - dbg!("{:?}", &statement); - statements.push(statement); - } - self.match_token(TokenKind::CurlyBracesClose)?; + let body = self.parse_block()?; match self.peek() { Some(tok) if tok.kind == TokenKind::Keyword(Keyword::Else) => { self.next_token(); Ok(Statement::If( condition, - statements, + Box::new(body), Some(Box::new(self.parse_conditional_statement()?)), )) } - _ => Ok(Statement::If(condition, statements, None)), + _ => Ok(Statement::If(condition, Box::new(body), None)), } } diff --git a/src/parser/node_type.rs b/src/parser/node_type.rs index 365810e..5b29ab2 100644 --- a/src/parser/node_type.rs +++ b/src/parser/node_type.rs @@ -11,7 +11,7 @@ pub struct Program { pub struct Function { pub name: String, pub arguments: Vec, - pub statements: Vec, + pub body: Statement, } #[derive(Debug, Eq, PartialEq)] @@ -21,9 +21,10 @@ pub struct Variable { #[derive(Debug, Eq, PartialEq)] pub enum Statement { + Block(Vec), Declare(Variable, Option), Return(Option), - If(Expression, Vec, Option>), + If(Expression, Box, Option>), While(Expression, Box), Exp(Expression), }