feat: function calls and captures

This commit is contained in:
rvcas 2022-10-02 18:53:29 -04:00 committed by Lucas
parent 1b61f4b25b
commit fb1ff759e1
3 changed files with 226 additions and 13 deletions

View File

@ -7,6 +7,8 @@ use crate::{
tipo::{self, PatternConstructor, Type, ValueConstructor}, tipo::{self, PatternConstructor, Type, ValueConstructor},
}; };
pub const CAPTURE_VARIABLE: &str = "_capture";
pub type TypedModule = Module<tipo::Module, TypedDefinition>; pub type TypedModule = Module<tipo::Module, TypedDefinition>;
pub type UntypedModule = Module<(), UntypedDefinition>; pub type UntypedModule = Module<(), UntypedDefinition>;
@ -465,7 +467,6 @@ pub enum TodoKind {
pub struct SrcId(Intern<Vec<String>>); pub struct SrcId(Intern<Vec<String>>);
impl SrcId { impl SrcId {
#[cfg(test)]
pub fn empty() -> Self { pub fn empty() -> Self {
SrcId(Intern::new(Vec::new())) SrcId(Intern::new(Vec::new()))
} }
@ -479,7 +480,6 @@ pub struct Span {
} }
impl Span { impl Span {
#[cfg(test)]
pub fn empty() -> Self { pub fn empty() -> Self {
use chumsky::Span; use chumsky::Span;

View File

@ -2,22 +2,12 @@ use chumsky::prelude::*;
use vec1::Vec1; use vec1::Vec1;
use crate::{ use crate::{
ast::{self, BinOp, Span, TodoKind}, ast::{self, BinOp, Span, TodoKind, CAPTURE_VARIABLE},
error::ParseError, error::ParseError,
expr, expr,
token::Token, token::Token,
}; };
// Parsing a function call into the appropriate structure
#[derive(Debug)]
pub enum ParserArg {
Arg(Box<ast::CallArg<expr::UntypedExpr>>),
Hole {
location: Span,
label: Option<String>,
},
}
pub fn module_parser( pub fn module_parser(
kind: ast::ModuleKind, kind: ast::ModuleKind,
) -> impl Parser<Token, ast::UntypedModule, Error = ParseError> { ) -> impl Parser<Token, ast::UntypedModule, Error = ParseError> {
@ -463,6 +453,16 @@ pub fn expr_parser(
assert_parser, assert_parser,
)); ));
// Parsing a function call into the appropriate structure
#[derive(Debug)]
enum ParserArg {
Arg(Box<ast::CallArg<expr::UntypedExpr>>),
Hole {
location: Span,
label: Option<String>,
},
}
enum Chain { enum Chain {
FieldAccess(String, Span), FieldAccess(String, Span),
RecordUpdate, RecordUpdate,
@ -511,6 +511,55 @@ pub fn expr_parser(
label, label,
container: Box::new(e), container: Box::new(e),
}, },
Chain::Call(args, span) => {
let mut holes = Vec::new();
let args = args
.into_iter()
.enumerate()
.map(|(index, a)| match a {
ParserArg::Arg(arg) => *arg,
ParserArg::Hole { location, label } => {
holes.push(ast::Arg {
location: Span::empty(),
annotation: None,
arg_name: ast::ArgName::Named {
name: format!("{}__{}", CAPTURE_VARIABLE, index),
location: Span::empty(),
},
tipo: (),
});
ast::CallArg {
label,
location,
value: expr::UntypedExpr::Var {
location,
name: format!("{}__{}", CAPTURE_VARIABLE, index),
},
}
}
})
.collect();
let call = expr::UntypedExpr::Call {
location: span,
fun: Box::new(e),
arguments: args,
};
if holes.is_empty() {
call
} else {
expr::UntypedExpr::Fn {
location: call.location(),
is_capture: true,
arguments: holes,
body: Box::new(call),
return_annotation: None,
}
}
}
_ => todo!(), _ => todo!(),
}); });

View File

@ -81,6 +81,14 @@ fn module() {
fn name(user: User) { fn name(user: User) {
user.name user.name
} }
fn calls() {
let x = add_one(3)
let map_add_x = list.map(_, fn (y) { x + y })
map_add_x([ 1, 2, 3 ])
}
"#; "#;
let len = code.chars().count(); let len = code.chars().count();
@ -759,6 +767,162 @@ fn module() {
return_annotation: None, return_annotation: None,
return_type: (), return_type: (),
}, },
ast::UntypedDefinition::Fn {
arguments: vec![],
body: expr::UntypedExpr::Sequence {
location: Span::new(SrcId::empty(), 1521..1642),
expressions: vec![
expr::UntypedExpr::Assignment {
location: Span::new(SrcId::empty(), 1521..1539),
value: Box::new(expr::UntypedExpr::Call {
location: Span::new(SrcId::empty(), 1536..1539),
fun: Box::new(expr::UntypedExpr::Var {
location: Span::new(SrcId::empty(), 1529..1536),
name: "add_one".to_string(),
}),
arguments: vec![ast::CallArg {
label: None,
location: Span::new(SrcId::empty(), 1537..1538),
value: expr::UntypedExpr::Int {
location: Span::new(SrcId::empty(), 1537..1538),
value: "3".to_string(),
},
},],
}),
pattern: ast::Pattern::Var {
location: Span::new(SrcId::empty(), 1525..1526),
name: "x".to_string(),
},
kind: ast::AssignmentKind::Let,
annotation: None,
},
expr::UntypedExpr::Assignment {
location: Span::new(SrcId::empty(), 1557..1602),
value: Box::new(expr::UntypedExpr::Fn {
location: Span::new(SrcId::empty(), 1581..1602),
is_capture: true,
arguments: vec![ast::Arg {
arg_name: ast::ArgName::Named {
name: "_capture__0".to_string(),
location: Span::new(SrcId::empty(), 0..0),
},
location: Span::new(SrcId::empty(), 0..0),
annotation: None,
tipo: (),
},],
body: Box::new(expr::UntypedExpr::Call {
location: Span::new(SrcId::empty(), 1581..1602),
fun: Box::new(expr::UntypedExpr::FieldAccess {
location: Span::new(SrcId::empty(), 1573..1581),
label: "map".to_string(),
container: Box::new(expr::UntypedExpr::Var {
location: Span::new(SrcId::empty(), 1573..1577),
name: "list".to_string(),
}),
}),
arguments: vec![
ast::CallArg {
label: None,
location: Span::new(SrcId::empty(), 1582..1583),
value: expr::UntypedExpr::Var {
location: Span::new(SrcId::empty(), 1582..1583),
name: "_capture__0".to_string(),
},
},
ast::CallArg {
label: None,
location: Span::new(SrcId::empty(), 1585..1601),
value: expr::UntypedExpr::Fn {
location: Span::new(SrcId::empty(), 1585..1601),
is_capture: false,
arguments: vec![ast::Arg {
arg_name: ast::ArgName::Named {
name: "y".to_string(),
location: Span::new(
SrcId::empty(),
1589..1590
),
},
location: Span::new(
SrcId::empty(),
1589..1590
),
annotation: None,
tipo: (),
},],
body: Box::new(expr::UntypedExpr::BinOp {
location: Span::new(
SrcId::empty(),
1594..1599
),
name: ast::BinOp::AddInt,
left: Box::new(expr::UntypedExpr::Var {
location: Span::new(
SrcId::empty(),
1594..1595
),
name: "x".to_string(),
}),
right: Box::new(expr::UntypedExpr::Var {
location: Span::new(
SrcId::empty(),
1598..1599
),
name: "y".to_string(),
}),
}),
return_annotation: None,
},
},
],
}),
return_annotation: None,
}),
pattern: ast::Pattern::Var {
location: Span::new(SrcId::empty(), 1561..1570),
name: "map_add_x".to_string(),
},
kind: ast::AssignmentKind::Let,
annotation: None,
},
expr::UntypedExpr::Call {
location: Span::new(SrcId::empty(), 1629..1642),
fun: Box::new(expr::UntypedExpr::Var {
location: Span::new(SrcId::empty(), 1620..1629),
name: "map_add_x".to_string(),
}),
arguments: vec![ast::CallArg {
label: None,
location: Span::new(SrcId::empty(), 1630..1641),
value: expr::UntypedExpr::List {
location: Span::new(SrcId::empty(), 1630..1641),
elements: vec![
expr::UntypedExpr::Int {
location: Span::new(SrcId::empty(), 1632..1633),
value: "1".to_string(),
},
expr::UntypedExpr::Int {
location: Span::new(SrcId::empty(), 1635..1636),
value: "2".to_string(),
},
expr::UntypedExpr::Int {
location: Span::new(SrcId::empty(), 1638..1639),
value: "3".to_string(),
},
],
tail: None,
},
},],
},
],
},
doc: None,
location: Span::new(SrcId::empty(), 1492..1656),
name: "calls".to_string(),
public: false,
return_annotation: None,
return_type: (),
},
] ]
}, },
); );