Skip to content

Commit f6f4666

Browse files
Merge pull request #1 from Rafael-Sapienza/feat/lambda-parser
Feat/lambda parser
2 parents 3135447 + 59e3f29 commit f6f4666

9 files changed

Lines changed: 247 additions & 29 deletions

File tree

src/environment/environment.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,18 +52,32 @@ impl<A: Clone> Scope<A> {
5252

5353
#[derive(Clone)]
5454
pub struct Environment<A> {
55+
pub current_func: String,
5556
pub globals: Scope<A>,
5657
pub stack: LinkedList<Scope<A>>,
5758
}
5859

5960
impl<A: Clone> Environment<A> {
6061
pub fn new() -> Environment<A> {
6162
Environment {
63+
current_func: String::new(),
6264
globals: Scope::new(),
6365
stack: LinkedList::new(),
6466
}
6567
}
6668

69+
pub fn get_current_func(&self) -> String {
70+
return self.current_func.clone();
71+
}
72+
73+
pub fn set_current_func(&mut self, func_name: &str) {
74+
self.current_func = func_name.to_string();
75+
}
76+
77+
pub fn set_global_functions(&mut self, global_functions: HashMap<Name, Function>) {
78+
self.globals.functions = global_functions;
79+
}
80+
6781
pub fn map_variable(&mut self, var: Name, mutable: bool, value: A) -> () {
6882
match self.stack.front_mut() {
6983
None => self.globals.map_variable(var, mutable, value),
@@ -142,9 +156,22 @@ impl<A: Clone> Environment<A> {
142156
vars.push((name.clone(), value.clone()));
143157
}
144158
}
145-
146159
vars
147160
}
161+
162+
// The type checker ensures that each function is defined only once
163+
pub fn get_all_functions(&self) -> HashMap<Name, Function> {
164+
let mut all_functions = HashMap::new();
165+
for (name, func) in &self.globals.functions {
166+
all_functions.insert(name.clone(), func.clone());
167+
}
168+
for scope in self.stack.iter() {
169+
for (name, func) in &scope.functions {
170+
all_functions.insert(name.clone(), func.clone());
171+
}
172+
}
173+
all_functions
174+
}
148175
}
149176

150177
#[cfg(test)]

src/interpreter/expression_eval.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::statement_execute::Computation;
2-
use crate::environment::environment::Environment;
2+
use crate::environment::environment::{Environment, Scope};
33
use crate::ir::ast::{Expression, Name};
44

55
#[derive(Debug, PartialEq, Clone)]
@@ -398,7 +398,13 @@ pub fn eval_function_call(
398398
));
399399
}
400400

401-
new_env.push();
401+
// new_env.push(); <- Removed the push; parameters are now mapped directly to the global scope
402+
//In this new environment, external functions and actual parameters are regarded as globally accessible
403+
//This is justified, since their visibility extends across the entire function body
404+
new_env.set_current_func(&name);
405+
// Functions from the outer environment must be propagated to new_env to ensure access to external functions within the function body.
406+
// This also allows the function to reference itself, which enables recursion
407+
new_env.set_global_functions(env.get_all_functions());
402408

403409
for (formal, actual) in function_definition.params.iter().zip(args.iter()) {
404410
let value = match eval(actual.clone(), env)? {
@@ -412,7 +418,7 @@ pub fn eval_function_call(
412418

413419
// Execute the body of the function.
414420
match super::statement_execute::execute(
415-
*function_definition.body.as_ref().unwrap().clone(),
421+
*function_definition.body.as_ref().unwrap().clone(), //Push occurs here, because function body is a Statement::Block
416422
&new_env,
417423
) {
418424
Ok(Computation::Continue(_)) => Err("Function did not return a value".to_string()),

src/interpreter/statement_execute.rs

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,12 @@ pub fn execute(stmt: Statement, env: &Environment<Expression>) -> Result<Computa
7979

8080
match value {
8181
Expression::CTrue => match *stmt_then {
82-
Statement::Block(stmts) => execute_block(stmts, &new_env),
82+
Statement::Block(stmts) => execute_if_block(stmts, &new_env),
8383
_ => execute(*stmt_then, &new_env),
8484
},
8585
Expression::CFalse => match stmt_else {
8686
Some(else_stmt) => match *else_stmt {
87-
Statement::Block(stmts) => execute_block(stmts, &new_env),
87+
Statement::Block(stmts) => execute_if_block(stmts, &new_env),
8888
_ => execute(*else_stmt, &new_env),
8989
},
9090
None => Ok(Computation::Continue(new_env)),
@@ -94,9 +94,14 @@ pub fn execute(stmt: Statement, env: &Environment<Expression>) -> Result<Computa
9494
}
9595

9696
Statement::Block(stmts) => {
97-
new_env.push();
97+
// new_env.push(); <- removing push()
9898
let result = execute_block(stmts, &new_env);
99-
new_env.pop();
99+
// new_env.pop(); <- removing pop()
100+
// `result` already encapsulates the updated environment,
101+
// So popping would have no effect on the final outcome
102+
// Therefore, push and pop operations will be handled in function 'execute_block'
103+
// A new function `execute_if_block` will be created specifically for executing blocks
104+
// without performing push/pop operations
100105
result
101106
}
102107

@@ -201,13 +206,38 @@ pub fn execute_block(
201206
env: &Environment<Expression>,
202207
) -> Result<Computation, String> {
203208
let mut current_env = env.clone();
209+
current_env.push();
204210

205211
for stmt in stmts {
206212
match execute(stmt, &current_env)? {
207213
Computation::Continue(new_env) => current_env = new_env,
208-
Computation::Return(expr, env) => return Ok(Computation::Return(expr, env)),
209-
Computation::PropagateError(expr, env) => {
210-
return Ok(Computation::PropagateError(expr, env))
214+
Computation::Return(expr, mut new_env) => {
215+
new_env.pop(); //expr has already been evaluated, so it is safe to pop here
216+
return Ok(Computation::Return(expr, new_env));
217+
}
218+
Computation::PropagateError(expr, new_env) => {
219+
return Ok(Computation::PropagateError(expr, new_env))
220+
}
221+
}
222+
}
223+
current_env.pop();
224+
Ok(Computation::Continue(current_env))
225+
}
226+
227+
pub fn execute_if_block(
228+
stmts: Vec<Statement>,
229+
env: &Environment<Expression>,
230+
) -> Result<Computation, String> {
231+
let mut current_env = env.clone();
232+
233+
for stmt in stmts {
234+
match execute(stmt, &current_env)? {
235+
Computation::Continue(new_env) => current_env = new_env,
236+
Computation::Return(expr, new_env) => {
237+
return Ok(Computation::Return(expr, new_env));
238+
}
239+
Computation::PropagateError(expr, new_env) => {
240+
return Ok(Computation::PropagateError(expr, new_env))
211241
}
212242
}
213243
}

src/ir/ast.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,9 @@ pub enum Expression {
116116
IsNothing(Box<Expression>),
117117
Propagate(Box<Expression>),
118118

119+
//Lambda expression
120+
Lambda(Function),
121+
119122
// List value
120123
ListValue(Vec<Expression>),
121124

src/parser/parser_common.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ pub const ASSERT_KEYWORD: &str = "assert";
3636
pub const VAR_KEYWORD: &str = "var";
3737
pub const VAL_KEYWORD: &str = "val";
3838
pub const DEF_KEYWORD: &str = "def";
39+
pub const LAMBDA_KEYWORD: &str = "lambda";
40+
pub const RET_KEYWORD: &str = "return";
3941

4042
// Operator and symbol constants
4143
pub const FUNCTION_ARROW: &str = "->";

src/parser/parser_expr.rs

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use nom::{
22
branch::alt,
33
bytes::complete::{tag, take_while},
4-
character::complete::{char, digit1, multispace0},
4+
character::complete::{char, digit1, multispace0, multispace1},
55
combinator::{map, map_res, opt, value, verify},
66
error::Error,
77
multi::{fold_many0, separated_list0},
@@ -11,19 +11,26 @@ use nom::{
1111

1212
use std::str::FromStr;
1313

14-
use crate::ir::ast::Expression;
14+
use crate::{ir::ast::Expression, parser::{parser_common::END_KEYWORD}};
1515
use crate::parser::parser_common::{
1616
identifier,
1717
is_string_char,
1818
keyword,
1919
// Other character constants
2020
COMMA_CHAR,
21+
COLON_CHAR,
2122
// Bracket and parentheses constants
2223
LEFT_BRACKET,
2324
LEFT_PAREN,
2425
RIGHT_BRACKET,
2526
RIGHT_PAREN,
27+
FUNCTION_ARROW,
28+
LAMBDA_KEYWORD,
2629
};
30+
use crate::parser::parser_stmt::{parse_formal_argument, parse_return_statement};
31+
use crate::parser::parser_type::parse_type;
32+
use crate::ir::ast::Function;
33+
use crate::ir::ast::Statement;
2734

2835
pub fn parse_expression(input: &str) -> IResult<&str, Expression> {
2936
parse_or(input)
@@ -117,6 +124,7 @@ fn parse_factor(input: &str) -> IResult<&str, Expression> {
117124
parse_list,
118125
parse_function_call,
119126
parse_var,
127+
parse_lambda,
120128
delimited(
121129
char::<&str, Error<&str>>(LEFT_PAREN),
122130
parse_expression,
@@ -125,6 +133,39 @@ fn parse_factor(input: &str) -> IResult<&str, Expression> {
125133
))(input)
126134
}
127135

136+
fn parse_lambda(input: &str) -> IResult<&str, Expression> {
137+
map(
138+
tuple((
139+
keyword(LAMBDA_KEYWORD),
140+
preceded(multispace1, identifier),
141+
delimited(
142+
char::<&str, Error<&str>>(LEFT_PAREN),
143+
separated_list0(
144+
tuple((
145+
multispace0,
146+
char::<&str, Error<&str>>(COMMA_CHAR),
147+
multispace0,
148+
)),
149+
parse_formal_argument,
150+
),
151+
char::<&str, Error<&str>>(RIGHT_PAREN),
152+
),
153+
preceded(multispace0, tag(FUNCTION_ARROW)),
154+
delimited(multispace0, parse_type, char::<&str, Error<&str>>(COLON_CHAR)),
155+
parse_return_statement,
156+
keyword(END_KEYWORD)
157+
)),
158+
|(_, name, args, _, t, return_stmt, _)| {
159+
Expression::Lambda(Function {
160+
name: name.to_string(),
161+
kind: t,
162+
params: args,
163+
body: Some(Box::new(Statement::Block(vec![return_stmt]))),
164+
})
165+
},
166+
)(input)
167+
}
168+
128169
fn parse_bool(input: &str) -> IResult<&str, Expression> {
129170
alt((
130171
value(Expression::CTrue, keyword("True")),

src/parser/parser_stmt.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use crate::ir::ast::{FormalArgument, Function, Statement};
1313
use crate::parser::parser_common::{
1414
identifier, keyword, ASSERT_KEYWORD, COLON_CHAR, COMMA_CHAR, DEF_KEYWORD, ELSE_KEYWORD,
1515
END_KEYWORD, EQUALS_CHAR, FOR_KEYWORD, FUNCTION_ARROW, IF_KEYWORD, IN_KEYWORD, LEFT_PAREN,
16-
RIGHT_PAREN, SEMICOLON_CHAR, VAL_KEYWORD, VAR_KEYWORD, WHILE_KEYWORD,
16+
RIGHT_PAREN, SEMICOLON_CHAR, VAL_KEYWORD, VAR_KEYWORD, WHILE_KEYWORD, RET_KEYWORD
1717
};
1818
use crate::parser::parser_expr::parse_expression;
1919
use crate::parser::parser_type::parse_type;
@@ -28,9 +28,21 @@ pub fn parse_statement(input: &str) -> IResult<&str, Statement> {
2828
parse_for_statement,
2929
parse_assert_statement,
3030
parse_function_definition_statement,
31+
parse_return_statement,
3132
))(input)
3233
}
3334

35+
pub fn parse_return_statement(input: &str) -> IResult<&str, Statement> {
36+
map(
37+
tuple((
38+
keyword(RET_KEYWORD),
39+
multispace0,
40+
parse_expression,
41+
)),
42+
|(_, _, expr)| Statement::Return(Box::new(expr)),
43+
)(input)
44+
}
45+
3446
fn parse_var_declaration_statement(input: &str) -> IResult<&str, Statement> {
3547
map(
3648
tuple((
@@ -181,7 +193,7 @@ fn parse_function_definition_statement(input: &str) -> IResult<&str, Statement>
181193
)(input)
182194
}
183195

184-
fn parse_block(input: &str) -> IResult<&str, Statement> {
196+
pub fn parse_block(input: &str) -> IResult<&str, Statement> {
185197
map(
186198
tuple((
187199
char::<&str, Error<&str>>(COLON_CHAR),
@@ -204,7 +216,7 @@ fn parse_block(input: &str) -> IResult<&str, Statement> {
204216
)(input)
205217
}
206218

207-
fn parse_formal_argument(input: &str) -> IResult<&str, FormalArgument> {
219+
pub fn parse_formal_argument(input: &str) -> IResult<&str, FormalArgument> {
208220
map(
209221
tuple((
210222
preceded(multispace0, identifier),

src/type_checker/expression_type_checker.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub fn check_expr(exp: Expression, env: &Environment<Type>) -> Result<Type, Erro
1919
Expression::Or(l, r) => check_bin_boolean_expression(*l, *r, env),
2020
Expression::Not(e) => check_not_expression(*e, env),
2121
Expression::EQ(l, r) => check_bin_relational_expression(*l, *r, env),
22+
Expression::NEQ(l, r) => check_bin_relational_expression(*l, *r, env),
2223
Expression::GT(l, r) => check_bin_relational_expression(*l, *r, env),
2324
Expression::LT(l, r) => check_bin_relational_expression(*l, *r, env),
2425
Expression::GTE(l, r) => check_bin_relational_expression(*l, *r, env),
@@ -34,11 +35,55 @@ pub fn check_expr(exp: Expression, env: &Environment<Type>) -> Result<Type, Erro
3435
Expression::Propagate(e) => check_propagate_type(*e, env),
3536
Expression::ListValue(elements) => check_list_value(&elements, env),
3637
Expression::Constructor(name, args) => check_adt_constructor(name, args, env),
38+
Expression::FuncCall(func_name, exp_vec) => {
39+
check_func_call(func_name.clone(), exp_vec.clone(), env)
40+
}
3741

3842
_ => Err("not implemented yet.".to_string()),
3943
}
4044
}
4145

46+
fn check_func_call(
47+
func_name: Name,
48+
exp_vector: Vec<Expression>,
49+
env: &Environment<Type>,
50+
) -> Result<Type, ErrorMessage> {
51+
let func = env.lookup_function(&func_name);
52+
if func.is_none() {
53+
return Err(format!(
54+
"Function {} was called but never declared",
55+
func_name
56+
));
57+
}
58+
let func = func.unwrap();
59+
if func.params.len() != exp_vector.len() {
60+
return Err(format!(
61+
"Function {} receives {} arguments, but {} were given",
62+
func_name,
63+
func.params.len(),
64+
exp_vector.len()
65+
));
66+
}
67+
let mut formal_arg_types = Vec::new();
68+
let mut actual_arg_types = Vec::new();
69+
for (param, arg) in func.params.iter().zip(exp_vector.iter()) {
70+
formal_arg_types.push(param.argument_type.clone());
71+
let arg_type = check_expr(arg.clone(), env)?;
72+
actual_arg_types.push(arg_type);
73+
}
74+
for (formal_type, actual_type) in formal_arg_types.iter().zip(actual_arg_types.iter()) {
75+
if formal_type != actual_type {
76+
return Err(format!(
77+
"Mismatched types in function {} call \n
78+
Expected:{:?}\n
79+
Received: {:?}",
80+
func_name, formal_arg_types, actual_arg_types
81+
));
82+
}
83+
}
84+
return Ok(func.kind.clone());
85+
}
86+
4287
fn check_var_name(name: Name, env: &Environment<Type>) -> Result<Type, ErrorMessage> {
4388
match env.lookup(&name) {
4489
Some((_, t)) => Ok(t.clone()),

0 commit comments

Comments
 (0)