Skip to content

Commit 8190f1a

Browse files
Add support for lambda expressions
1 parent c06fe60 commit 8190f1a

9 files changed

Lines changed: 107 additions & 60 deletions

File tree

src/environment/environment.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ impl<A: Clone + Debug> Environment<A> {
8383
return self.current_func.clone();
8484
}
8585

86+
pub fn get_current_scope(&self) -> &Scope<A> {
87+
self.stack.front().unwrap_or(&self.globals)
88+
}
89+
8690
pub fn set_current_func(&mut self, func_signature: &FuncSignature) {
8791
self.current_func = func_signature.clone();
8892
}

src/interpreter/expression_eval.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,9 @@ pub fn eval_function_call(
407407
}
408408
None => return Err(format!("Identifier '{}' was never declared", name)),
409409
},
410+
Expression::Lambda(func) => {
411+
actual_arg_values.push(Expression::Lambda(func.clone()));
412+
}
410413
_ => match eval(arg.clone(), env)? {
411414
ExpressionResult::Value(expr) => {
412415
actual_arg_values.push(expr);

src/interpreter/statement_execute.rs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,23 @@ pub fn execute(stmt: Statement, env: &Environment<Expression>) -> Result<Computa
5959
}
6060

6161
Statement::Assignment(name, exp) => {
62-
let value = match eval(*exp, &new_env)? {
63-
ExpressionResult::Value(expr) => expr,
64-
ExpressionResult::Propagate(expr) => {
65-
return Ok(Computation::PropagateError(expr, new_env))
62+
match *exp {
63+
Expression::Lambda(mut func) => {
64+
func.name = name;
65+
new_env.map_function(func);
66+
return Ok(Computation::Continue(new_env));
6667
}
67-
};
68-
new_env.map_variable(name, true, value);
69-
Ok(Computation::Continue(new_env))
68+
_ => {
69+
let value = match eval(*exp, &mut new_env)? {
70+
ExpressionResult::Value(expr) => expr,
71+
ExpressionResult::Propagate(expr) => {
72+
return Ok(Computation::PropagateError(expr, new_env));
73+
}
74+
};
75+
new_env.map_variable(name, true,value);
76+
return Ok(Computation::Continue(new_env));
77+
}
78+
}
7079
}
7180

7281
Statement::IfThenElse(cond, stmt_then, stmt_else) => {

src/parser/keywords.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ pub const KEYWORDS: &[&str] = &[
88
"val",
99
"var",
1010
"return",
11+
"lambda",
1112
"Ok",
1213
"Err",
1314
"Just",

src/parser/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ use nom::{
1414
use crate::ir::ast::Statement;
1515
use crate::parser::parser_common::SEMICOLON_CHAR;
1616

17-
pub use parser_expr::parse_expression;
18-
pub use parser_stmt::parse_statement;
17+
pub use parser_common::keyword;
18+
pub use parser_expr::{parse_expression, parse_lambda};
19+
pub use parser_stmt::{parse_formal_argument, parse_return_statement, parse_statement};
1920
pub use parser_type::parse_type;
2021

2122
pub fn parse(input: &str) -> IResult<&str, Vec<Statement>> {

src/parser/parser_common.rs

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use nom::{
22
branch::alt,
33
bytes::complete::tag,
4-
character::complete::{alpha1, multispace0},
5-
combinator::{not, peek, recognize},
4+
character::complete::{alpha1, multispace0, multispace1},
5+
combinator::{map, not, peek, recognize},
66
multi::many0,
7-
sequence::{delimited, terminated},
7+
sequence::{delimited, preceded, terminated, tuple},
88
IResult,
99
};
1010

@@ -71,10 +71,20 @@ pub fn separator<'a>(sep: &'static str) -> impl FnMut(&'a str) -> IResult<&'a st
7171
/// Parses a reserved keyword (e.g., "if") surrounded by optional spaces
7272
/// Fails if followed by an identifier character
7373
pub fn keyword<'a>(kw: &'static str) -> impl FnMut(&'a str) -> IResult<&'a str, &'a str> {
74-
terminated(
75-
delimited(multispace0, tag(kw), multispace0),
76-
not(peek(identifier_start_or_continue)),
77-
)
74+
move |input: &'a str| {
75+
let result = map(
76+
tuple((
77+
terminated(
78+
preceded(multispace0, tag(kw)),
79+
not(peek(identifier_start_or_continue)),
80+
),
81+
multispace0,
82+
)),
83+
|(kw, _)| kw,
84+
)(input);
85+
86+
result
87+
}
7888
}
7989

8090
/// Parsers for identifiers.

src/parser/parser_expr.rs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use nom::{
55
combinator::{map, map_res, opt, value, verify},
66
error::Error,
77
multi::{fold_many0, separated_list0},
8-
sequence::{delimited, pair, preceded, tuple},
8+
sequence::{delimited, pair, preceded, terminated, tuple},
99
IResult,
1010
};
1111

@@ -133,11 +133,9 @@ fn parse_factor(input: &str) -> IResult<&str, Expression> {
133133
))(input)
134134
}
135135

136-
fn parse_lambda(input: &str) -> IResult<&str, Expression> {
137-
map(
136+
pub fn parse_lambda(input: &str) -> IResult<&str, Expression> { map(
138137
tuple((
139-
keyword(LAMBDA_KEYWORD),
140-
preceded(multispace1, identifier),
138+
preceded(keyword(LAMBDA_KEYWORD), multispace0),
141139
delimited(
142140
char::<&str, Error<&str>>(LEFT_PAREN),
143141
separated_list0(
@@ -146,18 +144,21 @@ fn parse_lambda(input: &str) -> IResult<&str, Expression> {
146144
char::<&str, Error<&str>>(COMMA_CHAR),
147145
multispace0,
148146
)),
149-
parse_formal_argument,
147+
terminated(parse_formal_argument, multispace0),
150148
),
151149
char::<&str, Error<&str>>(RIGHT_PAREN),
152150
),
153151
preceded(multispace0, tag(FUNCTION_ARROW)),
154-
delimited(multispace0, parse_type, char::<&str, Error<&str>>(COLON_CHAR)),
155-
parse_return_statement,
156-
keyword(END_KEYWORD)
152+
delimited(
153+
multispace0,
154+
parse_type,
155+
char::<&str, Error<&str>>(COLON_CHAR),
156+
),
157+
delimited(multispace0, parse_return_statement, keyword(END_KEYWORD)),
157158
)),
158-
|(_, name, args, _, t, return_stmt, _)| {
159+
|(_, args, _, t, return_stmt)| {
159160
Expression::Lambda(Function {
160-
name: name.to_string(),
161+
name: "".to_string(),
161162
kind: t,
162163
params: args,
163164
body: Some(Box::new(Statement::Block(vec![return_stmt]))),

src/parser/parser_type.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ fn parse_result_type(input: &str) -> IResult<&str, Type> {
101101
)(input)
102102
}
103103

104-
fn parse_function_type(input: &str) -> IResult<&str, Type> {
104+
pub fn parse_function_type(input: &str) -> IResult<&str, Type> {
105105
map(
106106
tuple((
107107
preceded(multispace0, char(LEFT_PAREN)),

src/type_checker/statement_type_checker.rs

Lines changed: 50 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::collections::HashSet;
22

33
use crate::environment::environment::Environment;
44
use crate::ir::ast::{
5-
Expression, FormalArgument, FuncSignature, Function, Name, Statement, Type, ValueConstructor
5+
Expression, FormalArgument, FuncSignature, Function, Name, Statement, Type, ValueConstructor,
66
};
77
use crate::type_checker::expression_type_checker::check_expr;
88

@@ -58,25 +58,35 @@ fn check_assignment_stmt(
5858
env: &Environment<Type>,
5959
) -> Result<Environment<Type>, ErrorMessage> {
6060
let mut new_env = env.clone();
61-
let exp_type = check_expr(*exp, &new_env)?;
61+
let exp_type = check_expr(*exp.clone(), &new_env)?;
6262

63-
match new_env.lookup(&name) {
64-
Some((mutable, var_type)) => {
65-
if !mutable {
66-
Err(format!("[Type Error] cannot reassign '{:?}' variable, since it was declared as a constant value.", name))
67-
} else if var_type == Type::TAny {
68-
new_env.map_variable(name.clone(), true, exp_type);
69-
Ok(new_env)
70-
} else if var_type == exp_type {
71-
Ok(new_env)
72-
} else {
73-
Err(format!(
74-
"[Type Error] expected '{:?}', found '{:?}'.",
75-
var_type, exp_type
76-
))
77-
}
63+
match *exp {
64+
Expression::Lambda(mut func) => {
65+
func.name = name;
66+
new_env = check_func_def_stmt(func, env)?;
67+
Ok(new_env)
7868
}
79-
None => Err(format!("[Type Error] variable '{:?}' not declared.", name)),
69+
_ => match new_env.lookup(&name) {
70+
Some((mutable, var_type)) => {
71+
if !mutable {
72+
Err(format!(
73+
"[Type Error] cannot reassign '{:?}' variable, since it was declared as a constant value.",
74+
name
75+
))
76+
} else if var_type == Type::TAny {
77+
new_env.map_variable(name.clone(), true, exp_type);
78+
Ok(new_env)
79+
} else if var_type == exp_type {
80+
Ok(new_env)
81+
} else {
82+
Err(format!(
83+
"[Type Error] expected '{:?}', found '{:?}'.",
84+
var_type, exp_type
85+
))
86+
}
87+
}
88+
None => Err(format!("[Type Error] variable '{:?}' not declared.", name)),
89+
},
8090
}
8191
}
8292

@@ -205,9 +215,9 @@ fn check_func_def_stmt(
205215
// Previous environment functions and the formal parameters are regarded as global
206216
new_env.set_global_functions(env.get_all_functions());
207217

208-
// Ensure that each function is defined only once
209-
if new_env
210-
.globals
218+
// Ensure that each function is defined only once in current scope
219+
let current_scope = env.get_current_scope();
220+
if current_scope
211221
.functions
212222
.contains_key(&FuncSignature::from_func(&function))
213223
{
@@ -230,21 +240,29 @@ fn check_func_def_stmt(
230240

231241
for formal_arg in function.params.iter() {
232242
match formal_arg.argument_type.clone() {
233-
Type::TFunction(arg_func_ret_type,arg_func_params_type ) => {
243+
Type::TFunction(arg_func_ret_type, arg_func_params_type) => {
234244
let mut params: Vec<FormalArgument> = Vec::new();
235-
let mut count:u64 = 0;
236-
for arg_type in &arg_func_params_type
237-
{
238-
params.push(FormalArgument { argument_name: count.to_string(), argument_type: arg_type.clone() });
245+
let mut count: u64 = 0;
246+
for arg_type in &arg_func_params_type {
247+
params.push(FormalArgument {
248+
argument_name: count.to_string(),
249+
argument_type: arg_type.clone(),
250+
});
239251
count += 1;
240252
}
241-
new_env.map_function(Function { name: formal_arg.argument_name.clone(), kind: *arg_func_ret_type, params: params, body: None});
253+
new_env.map_function(Function {
254+
name: formal_arg.argument_name.clone(),
255+
kind: *arg_func_ret_type,
256+
params: params,
257+
body: None,
258+
});
242259
}
243-
_ =>
244-
{
245-
new_env.map_variable(formal_arg.argument_name.clone(),
246-
false,
247-
formal_arg.argument_type.clone());
260+
_ => {
261+
new_env.map_variable(
262+
formal_arg.argument_name.clone(),
263+
false,
264+
formal_arg.argument_type.clone(),
265+
);
248266
}
249267
}
250268
}

0 commit comments

Comments
 (0)