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 Block = Vec<Meta<Statement>>;
pub type ParamName = Rc<String>; 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)] #[derive(Debug, PartialEq, Clone)]
pub enum Declaration { pub enum Declaration {

View File

@ -461,14 +461,16 @@ impl Parser {
Ok(delimited!(self, LParen, formal_param, Comma, RParen)) Ok(delimited!(self, LParen, formal_param, Comma, RParen))
} }
//TODO needs to support default values
#[recursive_descent_method] #[recursive_descent_method]
fn formal_param(&mut self) -> ParseResult<FormalParam> { fn formal_param(&mut self) -> ParseResult<FormalParam> {
let name = self.identifier()?; 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()?), Colon => Some(self.type_anno()?),
_ => None _ => None
}; };
Ok((name, ty)) let default = None;
Ok(FormalParam { name, anno, default })
} }
#[recursive_descent_method] #[recursive_descent_method]
@ -1185,7 +1187,7 @@ mod parse_tests {
use super::tokenize; use super::tokenize;
use super::ParseResult; use super::ParseResult;
use crate::builtin::{PrefixOp, BinOp}; 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::Statement::*;
use super::Declaration::*; use super::Declaration::*;
use super::Signature; use super::Signature;
@ -1375,15 +1377,16 @@ mod parse_tests {
parse_test!("fn a(b, c: Int): Int", AST(vec![Meta::new(Declaration( parse_test!("fn a(b, c: Int): Int", AST(vec![Meta::new(Declaration(
FuncSig(Signature { name: rc!(a), operator: false, params: vec![ 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")) })))])); ], type_anno: Some(ty!("Int")) })))]));
parse_test!("fn a(x) { x() }", AST(vec![Meta::new(Declaration( 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![] })])))])); vec![exst!(Call { f: bx!(ex!(m val!("x"))), arguments: vec![] })])))]));
parse_test!("fn a(x) {\n x() }", AST(vec![Meta::new(Declaration( 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![] })])))])); vec![exst!(Call { f: bx!(ex!(m val!("x"))), arguments: vec![] })])))]));
let multiline = r#" let multiline = r#"
@ -1392,7 +1395,7 @@ fn a(x) {
} }
"#; "#;
parse_test!(multiline, AST(vec![Meta::new(Declaration( 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![] })])))])); vec![exst!(Call { f: bx!(ex!(m val!("x"))), arguments: vec![] })])))]));
let multiline2 = r#" let multiline2 = r#"
fn a(x) { fn a(x) {
@ -1402,7 +1405,7 @@ fn a(x) {
} }
"#; "#;
parse_test!(multiline2, AST(vec![Meta::new(Declaration( 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()")])))])); vec![exst!(s "x()")])))]));
} }
@ -1535,7 +1538,14 @@ fn a(x) {
Meta::new(Declaration(Interface { Meta::new(Declaration(Interface {
name: rc!(Unglueable), name: rc!(Unglueable),
signatures: vec![ 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![] })) }, 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] #[test]
fn parsing_lambdas() { fn parsing_lambdas() {
parse_test_wrap_ast! { r#"\(x) { x + 1}"#, exst!( 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![ parse_test!(r#"\ (x: Int, y) { a;b;c;}"#, AST(vec![
exst!(Lambda { 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, type_anno: None,
body: vec![exst!(s "a"), exst!(s "b"), exst!(s "c")] body: vec![exst!(s "a"), exst!(s "b"), exst!(s "c")]
}) })
@ -1628,7 +1641,9 @@ fn a(x) {
parse_test!(r#"\(x){y}(1)"#, AST(vec![ parse_test!(r#"\(x){y}(1)"#, AST(vec![
exst!(Call { f: bx!(ex!(m exst!(Call { f: bx!(ex!(m
Lambda { Lambda {
params: vec![(rc!(x), None)], params: vec![
FormalParam { name: rc!(x), anno: None, default: None }
],
type_anno: None, type_anno: None,
body: vec![exst!(s "y")] } body: vec![exst!(s "y")] }
)), )),
@ -1637,7 +1652,9 @@ fn a(x) {
parse_test_wrap_ast! { parse_test_wrap_ast! {
r#"\(x: Int): String { "q" }"#, r#"\(x: Int): String { "q" }"#,
exst!(Lambda { 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")), type_anno: Some(ty!("String")),
body: vec![exst!(s r#""q""#)] body: vec![exst!(s r#""q""#)]
}) })
@ -1649,7 +1666,7 @@ fn a(x) {
parse_test_wrap_ast! { parse_test_wrap_ast! {
r"\x { x + 10 }", r"\x { x + 10 }",
exst!(Lambda { exst!(Lambda {
params: vec![(rc!(x), None)], params: vec![FormalParam { name: rc!(x), anno: None, default: None }],
type_anno: None, type_anno: None,
body: vec![exst!(s r"x + 10")] body: vec![exst!(s r"x + 10")]
}) })
@ -1658,7 +1675,7 @@ fn a(x) {
parse_test_wrap_ast! { parse_test_wrap_ast! {
r"\x: Nat { x + 10 }", r"\x: Nat { x + 10 }",
exst!(Lambda { exst!(Lambda {
params: vec![(rc!(x), Some(ty!("Nat")))], params: vec![FormalParam { name: rc!(x), anno: Some(ty!("Nat")), default: None }],
type_anno: None, type_anno: None,
body: vec![exst!(s r"x + 10")] 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 { fn reduce_lambda(params: &Vec<FormalParam>, body: &Block, symbol_table: &SymbolTable) -> Expr {
Expr::Func(Func::UserDefined { Expr::Func(Func::UserDefined {
name: None, 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), body: reduce_block(body, symbol_table),
}) })
} }
@ -377,7 +377,7 @@ impl Declaration {
name: name.clone(), name: name.clone(),
func: Func::UserDefined { func: Func::UserDefined {
name: Some(name.clone()), 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), 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> { fn add_function_signature(&mut self, signature: &Signature, scope_name_stack: &mut Vec<ScopeSegment>) -> Result<(), String> {
let mut local_type_context = LocalTypeContext::new(); let mut local_type_context = LocalTypeContext::new();
let types = signature.params.iter().map(|param| match param { let types = signature.params.iter().map(|param| match param.anno {
(_, Some(type_identifier)) => Rc::new(format!("{:?}", type_identifier)), Some(ref type_identifier) => Rc::new(format!("{:?}", type_identifier)),
(_, None) => local_type_context.new_universal_type() None => local_type_context.new_universal_type()
}).collect(); }).collect();
self.add_new_symbol(&signature.name, scope_name_stack, SymbolSpec::Func(types)); self.add_new_symbol(&signature.name, scope_name_stack, SymbolSpec::Func(types));
Ok(()) 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> { 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| { 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) self.get_type_from_name(type_identifier)
} else { } else {
Ok(Type::Var(self.fresh_type_variable())) Ok(Type::Var(self.fresh_type_variable()))