Browse Source

Generalize block into own statement

github-actions
Garrit Franke 3 years ago
parent
commit
b23a9bd751
  1. 1
      TODO
  2. 33
      src/generator/js.rs
  3. 17
      src/generator/x86.rs
  4. 43
      src/parser/mod.rs
  5. 5
      src/parser/node_type.rs

1
TODO

@ -11,5 +11,4 @@
# Cleanups # Cleanups
- Generalize function/if/loop bodies into a "Block" node to remove redundancy
- Improve error reporting (See ./util/string_util::highlight_position_in_file) - Improve error reporting (See ./util/string_util::highlight_position_in_file)

33
src/generator/js.rs

@ -27,15 +27,26 @@ fn generate_function(func: Function) -> String {
.join(", "); .join(", ");
let mut raw = format!("function {N}({A})", N = func.name, A = arguments); 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
raw += &generate_statement(statement); }
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 { 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::Declare(name, val) => generate_declare(name.name, val),
Statement::Exp(val) => generate_expression(val), Statement::Exp(val) => generate_expression(val),
Statement::If(expr, if_state, else_state) => { 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!(), Statement::While(_, _) => todo!(),
} }
} }
@ -63,15 +75,20 @@ fn generate_expression(expr: Expression) -> String {
fn generate_conditional( fn generate_conditional(
expr: Expression, expr: Expression,
if_state: Vec<Statement>, if_state: Statement,
else_state: Option<Statement>, else_state: Option<Statement>,
) -> String { ) -> String {
let expr_str = generate_expression(expr); 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); let mut outcome = format!("if ({})", expr_str);
outcome += "{\n"; outcome += "{\n";
for statement in if_state { for statement in body {
outcome += &generate_statement(statement); outcome += &generate_statement(statement);
} }
outcome += "}"; outcome += "}";

17
src/generator/x86.rs

@ -67,13 +67,16 @@ impl X86Generator {
fn gen_function(&mut self, func: Function) -> Assembly { fn gen_function(&mut self, func: Function) -> Assembly {
let mut asm = Assembly::new(); let mut asm = Assembly::new();
let has_return: bool = func.statements.iter().any(|s| { let has_return: bool = match &func.body {
if let Statement::Return(_) = *s { Statement::Block(statements) => statements.iter().any(|s| {
true if let Statement::Return(_) = *s {
} else { true
false } else {
} false
}); }
}),
_ => panic!("Function body should be of type Block"),
};
asm.add(format!(".globl _{}", func.name)); asm.add(format!(".globl _{}", func.name));
asm.add(format!("_{}:", func.name)); asm.add(format!("_{}:", func.name));

43
src/parser/mod.rs

@ -148,6 +148,22 @@ impl Parser {
}) })
} }
fn parse_block(&mut self) -> Result<Statement, String> {
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<Function, String> { fn parse_function(&mut self) -> Result<Function, String> {
self.match_keyword(Keyword::Function)?; self.match_keyword(Keyword::Function)?;
let name = self.match_identifier()?; let name = self.match_identifier()?;
@ -162,22 +178,13 @@ impl Parser {
}; };
self.match_token(TokenKind::BraceClose)?; 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 { Ok(Function {
name: name, name: name,
arguments: arguments, arguments: arguments,
statements: statements, body: body,
}) })
} }
@ -305,27 +312,19 @@ impl Parser {
fn parse_conditional_statement(&mut self) -> Result<Statement, String> { fn parse_conditional_statement(&mut self) -> Result<Statement, String> {
self.match_keyword(Keyword::If)?; self.match_keyword(Keyword::If)?;
let condition = self.parse_expression()?; 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() { match self.peek() {
Some(tok) if tok.kind == TokenKind::Keyword(Keyword::Else) => { Some(tok) if tok.kind == TokenKind::Keyword(Keyword::Else) => {
self.next_token(); self.next_token();
Ok(Statement::If( Ok(Statement::If(
condition, condition,
statements, Box::new(body),
Some(Box::new(self.parse_conditional_statement()?)), Some(Box::new(self.parse_conditional_statement()?)),
)) ))
} }
_ => Ok(Statement::If(condition, statements, None)), _ => Ok(Statement::If(condition, Box::new(body), None)),
} }
} }

5
src/parser/node_type.rs

@ -11,7 +11,7 @@ pub struct Program {
pub struct Function { pub struct Function {
pub name: String, pub name: String,
pub arguments: Vec<Variable>, pub arguments: Vec<Variable>,
pub statements: Vec<Statement>, pub body: Statement,
} }
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq)]
@ -21,9 +21,10 @@ pub struct Variable {
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq)]
pub enum Statement { pub enum Statement {
Block(Vec<Statement>),
Declare(Variable, Option<Expression>), Declare(Variable, Option<Expression>),
Return(Option<Expression>), Return(Option<Expression>),
If(Expression, Vec<Statement>, Option<Box<Statement>>), If(Expression, Box<Statement>, Option<Box<Statement>>),
While(Expression, Box<Statement>), While(Expression, Box<Statement>),
Exp(Expression), Exp(Expression),
} }

Loading…
Cancel
Save