Browse Source

feat: scoped variables

github-actions
Garrit Franke 3 years ago
parent
commit
c156773c5f
  1. 22
      src/generator/c.rs
  2. 6
      src/generator/js.rs
  3. 2
      src/generator/x86.rs
  4. 2
      src/parser/infer.rs
  5. 3
      src/parser/node_type.rs
  6. 12
      src/parser/rules.rs

22
src/generator/c.rs

@ -71,7 +71,9 @@ pub(super) fn generate_type(t: Either<Variable, Option<Type>>) -> String {
fn generate_function(func: Function) -> String {
let mut buf = String::new();
buf += &format!("{} ", &generate_function_signature(func.clone()));
buf += &generate_block(func.body);
if let Statement::Block(statements, scope) = func.body {
buf += &generate_block(statements, scope);
}
buf
}
@ -87,15 +89,10 @@ fn generate_function_signature(func: Function) -> String {
format!("{T} {N}({A})", T = t, N = func.name, A = arguments)
}
fn generate_block(block: Statement) -> String {
fn generate_block(block: Vec<Statement>, scope: Vec<Variable>) -> 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 {
for statement in block {
generated += &generate_statement(statement);
}
@ -113,7 +110,7 @@ fn generate_statement(statement: Statement) -> String {
generate_conditional(expr, *if_state, else_state.map(|x| *x))
}
Statement::Assign(name, state) => generate_assign(*name, *state),
Statement::Block(_) => generate_block(statement),
Statement::Block(statements, scope) => generate_block(statements, scope),
Statement::While(expr, body) => generate_while_loop(expr, *body),
Statement::For(ident, expr, body) => todo!(),
Statement::Continue => todo!(),
@ -142,7 +139,10 @@ fn generate_while_loop(expr: Expression, body: Statement) -> String {
out_str += &generate_expression(expr);
out_str += ") ";
out_str += &generate_block(body);
if let Statement::Block(statements, scope) = body {
out_str += &generate_block(statements, scope);
}
out_str
}
@ -175,7 +175,7 @@ fn generate_conditional(
let expr_str = generate_expression(expr);
let body = match if_state {
Statement::Block(blk) => blk,
Statement::Block(blk, _) => blk,
_ => panic!("Conditional body should be of type block"),
};

6
src/generator/js.rs

@ -65,7 +65,7 @@ fn generate_block(block: Statement, prepend: Option<String>) -> String {
// TODO: Prepend statements
let statements = match block {
Statement::Block(blk) => blk,
Statement::Block(blk, _) => blk,
_ => panic!("Block body should be of type Statement::Block"),
};
@ -87,7 +87,7 @@ fn generate_statement(statement: Statement) -> String {
generate_conditional(expr, *if_state, else_state.map(|x| *x))
}
Statement::Assign(name, state) => generate_assign(*name, *state),
Statement::Block(_) => generate_block(statement, None),
Statement::Block(_, _) => generate_block(statement, None),
Statement::While(expr, body) => generate_while_loop(expr, *body),
Statement::For(ident, expr, body) => generate_for_loop(ident, expr, *body),
Statement::Continue => generate_continue(),
@ -175,7 +175,7 @@ fn generate_conditional(
let expr_str = generate_expression(expr);
let body = match if_state {
Statement::Block(blk) => blk,
Statement::Block(blk, _) => blk,
_ => panic!("Conditional body should be of type block"),
};

2
src/generator/x86.rs

@ -77,7 +77,7 @@ impl X86Generator {
let mut asm = Assembly::new();
let has_return: bool = match &func.body {
Statement::Block(statements) => statements.iter().any(|s| {
Statement::Block(statements, _) => statements.iter().any(|s| {
if let Statement::Return(_) = *s {
true
} else {

2
src/parser/infer.rs

@ -8,7 +8,7 @@ pub(super) fn infer(program: &mut Program) -> Result<(), String> {
let table = &program.get_symbol_table();
// TODO: Fix aweful nesting
for func in &mut program.func {
if let Statement::Block(statements) = &mut func.body {
if let Statement::Block(statements, _) = &mut func.body {
for statement in statements {
match statement {
Statement::Declare(var, expr) => {

3
src/parser/node_type.rs

@ -81,7 +81,8 @@ impl TryFrom<String> for Type {
#[derive(Debug, Eq, PartialEq, Clone)]
pub enum Statement {
Block(Vec<Statement>),
/// (Statements, Scoped variables)
Block(Vec<Statement>, Vec<Variable>),
Declare(Variable, Option<Expression>),
Assign(Box<Expression>, Box<Expression>),
Return(Option<Expression>),

12
src/parser/rules.rs

@ -39,15 +39,25 @@ impl Parser {
self.match_token(TokenKind::CurlyBracesOpen)?;
let mut statements = vec![];
let mut scope = vec![];
// Parse statements until a curly brace is encountered
while let Err(_) = self.peek_token(TokenKind::CurlyBracesClose) {
let statement = self.parse_statement()?;
// If the current statement is a variable declaration,
// let the scope know
if let Statement::Declare(var, _) = &statement {
// TODO: Not sure if we should clone here
scope.push(var.to_owned());
}
statements.push(statement);
}
self.match_token(TokenKind::CurlyBracesClose)?;
Ok(Statement::Block(statements))
Ok(Statement::Block(statements, scope))
}
fn parse_function(&mut self) -> Result<Function, String> {

Loading…
Cancel
Save