feat(tazjin/rlox): Implement function definitions
... with this, functions now work. Note that this bubbled up another weird code structure nit: The parser::Function type should probably not carry its name directly. However this doesn't matter much and I don't care right now. Change-Id: If8e3b23f07033260433b9acd45f37c0e61fd2ff8 Reviewed-on: https://cl.tvl.fyi/c/depot/+/2393 Reviewed-by: tazjin <mail@tazj.in> Tested-by: BuildkiteCI
This commit is contained in:
		
							parent
							
								
									56d8fa97ed
								
							
						
					
					
						commit
						1d8e3f4f8b
					
				
					 3 changed files with 28 additions and 5 deletions
				
			
		| 
						 | 
					@ -41,7 +41,7 @@ impl<'a> Callable<'a> {
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                lox.interpret_block(Rc::new(RwLock::new(fn_env)), &func.body)
 | 
					                lox.interpret_block(Rc::new(RwLock::new(fn_env)), &func.body)
 | 
				
			||||||
            },
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -220,7 +220,7 @@ impl<'a> Interpreter<'a> {
 | 
				
			||||||
            Statement::Block(block) => return self.interpret_block(Default::default(), block),
 | 
					            Statement::Block(block) => return self.interpret_block(Default::default(), block),
 | 
				
			||||||
            Statement::If(if_stmt) => return self.interpret_if(if_stmt),
 | 
					            Statement::If(if_stmt) => return self.interpret_if(if_stmt),
 | 
				
			||||||
            Statement::While(while_stmt) => return self.interpret_while(while_stmt),
 | 
					            Statement::While(while_stmt) => return self.interpret_while(while_stmt),
 | 
				
			||||||
            Statement::Function(_) => unimplemented!(),
 | 
					            Statement::Function(func) => return self.interpret_function(func.clone()),
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Ok(value)
 | 
					        Ok(value)
 | 
				
			||||||
| 
						 | 
					@ -278,6 +278,13 @@ impl<'a> Interpreter<'a> {
 | 
				
			||||||
        Ok(value)
 | 
					        Ok(value)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn interpret_function(&mut self, stmt: Rc<parser::Function<'a>>) -> Result<Value<'a>, Error> {
 | 
				
			||||||
 | 
					        let name = stmt.name.clone();
 | 
				
			||||||
 | 
					        let value = Value::Callable(Callable::Function(stmt));
 | 
				
			||||||
 | 
					        self.define_var(&name, value.clone())?;
 | 
				
			||||||
 | 
					        Ok(value)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn eval(&mut self, expr: &Expr<'a>) -> Result<Value<'a>, Error> {
 | 
					    fn eval(&mut self, expr: &Expr<'a>) -> Result<Value<'a>, Error> {
 | 
				
			||||||
        match expr {
 | 
					        match expr {
 | 
				
			||||||
            Expr::Assign(assign) => self.eval_assign(assign),
 | 
					            Expr::Assign(assign) => self.eval_assign(assign),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -70,3 +70,18 @@ fn test_binary_operators() {
 | 
				
			||||||
        parse_eval(&code("\"foo\" + \"bar\";"))
 | 
					        parse_eval(&code("\"foo\" + \"bar\";"))
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[test]
 | 
				
			||||||
 | 
					fn test_functions() {
 | 
				
			||||||
 | 
					    let code = code(
 | 
				
			||||||
 | 
					        r#"
 | 
				
			||||||
 | 
					fun add(a, b, c) {
 | 
				
			||||||
 | 
					  a + b + c;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add(1, 2, 3);
 | 
				
			||||||
 | 
					"#,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert_eq!(Value::Literal(Literal::Number(6.0)), parse_eval(&code));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,6 +7,7 @@
 | 
				
			||||||
// have real types.
 | 
					// have real types.
 | 
				
			||||||
use crate::errors::{Error, ErrorKind};
 | 
					use crate::errors::{Error, ErrorKind};
 | 
				
			||||||
use crate::scanner::{Token, TokenKind};
 | 
					use crate::scanner::{Token, TokenKind};
 | 
				
			||||||
 | 
					use std::rc::Rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// AST
 | 
					// AST
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -108,7 +109,7 @@ pub enum Statement<'a> {
 | 
				
			||||||
    Block(Block<'a>),
 | 
					    Block(Block<'a>),
 | 
				
			||||||
    If(If<'a>),
 | 
					    If(If<'a>),
 | 
				
			||||||
    While(While<'a>),
 | 
					    While(While<'a>),
 | 
				
			||||||
    Function(Function<'a>),
 | 
					    Function(Rc<Function<'a>>),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Parser
 | 
					// Parser
 | 
				
			||||||
| 
						 | 
					@ -221,11 +222,11 @@ impl<'a> Parser<'a> {
 | 
				
			||||||
            ErrorKind::ExpectedToken("Expect '{' before function body."),
 | 
					            ErrorKind::ExpectedToken("Expect '{' before function body."),
 | 
				
			||||||
        )?;
 | 
					        )?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Ok(Statement::Function(Function {
 | 
					        Ok(Statement::Function(Rc::new(Function {
 | 
				
			||||||
            name,
 | 
					            name,
 | 
				
			||||||
            params,
 | 
					            params,
 | 
				
			||||||
            body: self.block_statement()?,
 | 
					            body: self.block_statement()?,
 | 
				
			||||||
        }))
 | 
					        })))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn var_declaration(&mut self) -> StmtResult<'a> {
 | 
					    fn var_declaration(&mut self) -> StmtResult<'a> {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue