More complicated FormalParam type

This commit is contained in:
greg 2019-06-16 14:56:52 -07:00
parent 30498d5c98
commit 33c2786ea1
5 changed files with 49 additions and 26 deletions

View File

@ -43,7 +43,13 @@ pub enum Statement {
pub type Block = Vec<Meta<Statement>>;
pub type ParamName = Rc<String>;
pub type FormalParam = (ParamName, Option<TypeIdentifier>);
#[derive(Debug, PartialEq, Clone)]
pub struct FormalParam {
pub name: ParamName,
pub default: Option<Expression>,
pub anno: Option<TypeIdentifier>
}
#[derive(Debug, PartialEq, Clone)]
pub enum Declaration {

View File

@ -461,14 +461,16 @@ impl Parser {
Ok(delimited!(self, LParen, formal_param, Comma, RParen))
}
//TODO needs to support default values
#[recursive_descent_method]
fn formal_param(&mut self) -> ParseResult<FormalParam> {
let name = self.identifier()?;
let ty = match self.token_handler.peek_kind() {
let anno = match self.token_handler.peek_kind() {
Colon => Some(self.type_anno()?),
_ => None
};
Ok((name, ty))
let default = None;
Ok(FormalParam { name, anno, default })
}
#[recursive_descent_method]
@ -1185,7 +1187,7 @@ mod parse_tests {
use super::tokenize;
use super::ParseResult;
use crate::builtin::{PrefixOp, BinOp};
use crate::ast::{AST, Meta, Expression, Statement, IfExpressionBody, Discriminator, Pattern, PatternLiteral, TypeBody, Enumerator, ForBody, InvocationArgument};
use crate::ast::{AST, Meta, Expression, Statement, IfExpressionBody, Discriminator, Pattern, PatternLiteral, TypeBody, Enumerator, ForBody, InvocationArgument, FormalParam};
use super::Statement::*;
use super::Declaration::*;
use super::Signature;
@ -1375,15 +1377,16 @@ mod parse_tests {
parse_test!("fn a(b, c: Int): Int", AST(vec![Meta::new(Declaration(
FuncSig(Signature { name: rc!(a), operator: false, params: vec![
(rc!(b), None), (rc!(c), Some(ty!("Int")))
FormalParam { name: rc!(b), anno: None, default: None },
FormalParam { name: rc!(c), anno: Some(ty!("Int")), default: None }
], type_anno: Some(ty!("Int")) })))]));
parse_test!("fn a(x) { x() }", AST(vec![Meta::new(Declaration(
FuncDecl(Signature { name: rc!(a), operator: false, params: vec![(rc!(x),None)], type_anno: None },
FuncDecl(Signature { name: rc!(a), operator: false, params: vec![FormalParam { name: rc!(x), anno: None, default: None }], type_anno: None },
vec![exst!(Call { f: bx!(ex!(m val!("x"))), arguments: vec![] })])))]));
parse_test!("fn a(x) {\n x() }", AST(vec![Meta::new(Declaration(
FuncDecl(Signature { name: rc!(a), operator: false, params: vec![(rc!(x),None)], type_anno: None },
FuncDecl(Signature { name: rc!(a), operator: false, params: vec![FormalParam { name: rc!(x), anno: None, default: None }], type_anno: None },
vec![exst!(Call { f: bx!(ex!(m val!("x"))), arguments: vec![] })])))]));
let multiline = r#"
@ -1392,7 +1395,7 @@ fn a(x) {
}
"#;
parse_test!(multiline, AST(vec![Meta::new(Declaration(
FuncDecl(Signature { name: rc!(a), operator: false, params: vec![(rc!(x),None)], type_anno: None },
FuncDecl(Signature { name: rc!(a), operator: false, params: vec![FormalParam { name: rc!(x), default: None, anno: None }], type_anno: None },
vec![exst!(Call { f: bx!(ex!(m val!("x"))), arguments: vec![] })])))]));
let multiline2 = r#"
fn a(x) {
@ -1402,7 +1405,7 @@ fn a(x) {
}
"#;
parse_test!(multiline2, AST(vec![Meta::new(Declaration(
FuncDecl(Signature { name: rc!(a), operator: false, params: vec![(rc!(x),None)], type_anno: None },
FuncDecl(Signature { name: rc!(a), operator: false, params: vec![FormalParam { name: rc!(x), default: None, anno: None }], type_anno: None },
vec![exst!(s "x()")])))]));
}
@ -1535,7 +1538,14 @@ fn a(x) {
Meta::new(Declaration(Interface {
name: rc!(Unglueable),
signatures: vec![
Signature { name: rc!(unglue), operator: false, params: vec![(rc!(a), Some(Singleton(TypeSingletonName { name: rc!(Glue), params: vec![] })))], type_anno: None },
Signature {
name: rc!(unglue),
operator: false,
params: vec![
FormalParam { name: rc!(a), anno: Some(Singleton(TypeSingletonName { name: rc!(Glue), params: vec![] })), default: None }
],
type_anno: None
},
Signature { name: rc!(mar), operator: false, params: vec![], type_anno: Some(Singleton(TypeSingletonName { name: rc!(Glue), params: vec![] })) },
]
}))
@ -1613,13 +1623,16 @@ fn a(x) {
#[test]
fn parsing_lambdas() {
parse_test_wrap_ast! { r#"\(x) { x + 1}"#, exst!(
Lambda { params: vec![(rc!(x), None)], type_anno: None, body: vec![exst!(s "x + 1")] }
)
Lambda { params: vec![FormalParam { name: rc!(x), anno: None, default: None } ], type_anno: None, body: vec![exst!(s "x + 1")] }
)
}
parse_test!(r#"\ (x: Int, y) { a;b;c;}"#, AST(vec![
exst!(Lambda {
params: vec![(rc!(x), Some(ty!("Int"))), (rc!(y), None)],
params: vec![
FormalParam { name: rc!(x), anno: Some(ty!("Int")), default: None },
FormalParam { name: rc!(y), anno: None, default: None }
],
type_anno: None,
body: vec![exst!(s "a"), exst!(s "b"), exst!(s "c")]
})
@ -1627,8 +1640,10 @@ fn a(x) {
parse_test!(r#"\(x){y}(1)"#, AST(vec![
exst!(Call { f: bx!(ex!(m
Lambda {
params: vec![(rc!(x), None)],
Lambda {
params: vec![
FormalParam { name: rc!(x), anno: None, default: None }
],
type_anno: None,
body: vec![exst!(s "y")] }
)),
@ -1637,7 +1652,9 @@ fn a(x) {
parse_test_wrap_ast! {
r#"\(x: Int): String { "q" }"#,
exst!(Lambda {
params: vec![(rc!(x), Some(ty!("Int")))],
params: vec![
FormalParam { name: rc!(x), anno: Some(ty!("Int")), default: None },
],
type_anno: Some(ty!("String")),
body: vec![exst!(s r#""q""#)]
})
@ -1647,18 +1664,18 @@ fn a(x) {
#[test]
fn single_param_lambda() {
parse_test_wrap_ast! {
r"\x { x + 10 }",
r"\x { x + 10 }",
exst!(Lambda {
params: vec![(rc!(x), None)],
params: vec![FormalParam { name: rc!(x), anno: None, default: None }],
type_anno: None,
body: vec![exst!(s r"x + 10")]
})
}
parse_test_wrap_ast! {
r"\x: Nat { x + 10 }",
r"\x: Nat { x + 10 }",
exst!(Lambda {
params: vec![(rc!(x), Some(ty!("Nat")))],
params: vec![FormalParam { name: rc!(x), anno: Some(ty!("Nat")), default: None }],
type_anno: None,
body: vec![exst!(s r"x + 10")]
})

View File

@ -165,7 +165,7 @@ impl Expression {
fn reduce_lambda(params: &Vec<FormalParam>, body: &Block, symbol_table: &SymbolTable) -> Expr {
Expr::Func(Func::UserDefined {
name: None,
params: params.iter().map(|param| param.0.clone()).collect(),
params: params.iter().map(|param| param.name.clone()).collect(),
body: reduce_block(body, symbol_table),
})
}
@ -377,7 +377,7 @@ impl Declaration {
name: name.clone(),
func: Func::UserDefined {
name: Some(name.clone()),
params: params.iter().map(|param| param.0.clone()).collect(),
params: params.iter().map(|param| param.name.clone()).collect(),
body: reduce_block(&statements, symbol_table),
}
},

View File

@ -169,9 +169,9 @@ impl SymbolTable {
fn add_function_signature(&mut self, signature: &Signature, scope_name_stack: &mut Vec<ScopeSegment>) -> Result<(), String> {
let mut local_type_context = LocalTypeContext::new();
let types = signature.params.iter().map(|param| match param {
(_, Some(type_identifier)) => Rc::new(format!("{:?}", type_identifier)),
(_, None) => local_type_context.new_universal_type()
let types = signature.params.iter().map(|param| match param.anno {
Some(ref type_identifier) => Rc::new(format!("{:?}", type_identifier)),
None => local_type_context.new_universal_type()
}).collect();
self.add_new_symbol(&signature.name, scope_name_stack, SymbolSpec::Func(types));
Ok(())

View File

@ -369,7 +369,7 @@ impl<'a> TypeContext<'a> {
fn lambda(&mut self, params: &Vec<FormalParam>, type_anno: &Option<TypeIdentifier>, _body: &Block) -> InferResult<Type> {
let argument_types: InferResult<Vec<Type>> = params.iter().map(|param: &FormalParam| {
if let (_, Some(type_identifier)) = param {
if let FormalParam { anno: Some(type_identifier), .. } = param {
self.get_type_from_name(type_identifier)
} else {
Ok(Type::Var(self.fresh_type_variable()))