From 75adbd6473dc2f2b9e698aa499773af48c165631 Mon Sep 17 00:00:00 2001 From: John Date: Tue, 16 Apr 2024 20:31:23 -0500 Subject: [PATCH] cl-ast: Separate function *signature* from function bindings, for cl-typeck Note: this breaks cl-typeck --- cl-ast/src/ast_impl.rs | 29 ++++++++++++++--- cl-ast/src/lib.rs | 5 ++- cl-interpret/src/lib.rs | 4 +-- cl-parser/src/parser.rs | 70 +++++++++++++++++++++------------------- cl-repl/examples/yaml.rs | 15 ++++----- 5 files changed, 72 insertions(+), 51 deletions(-) diff --git a/cl-ast/src/ast_impl.rs b/cl-ast/src/ast_impl.rs index ca07eb8..2712f8e 100644 --- a/cl-ast/src/ast_impl.rs +++ b/cl-ast/src/ast_impl.rs @@ -166,9 +166,30 @@ mod display { } impl Display for Function { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let Self { name, args, body, rety } = self; + let Self { name, sign: sign @ TyFn { args, rety }, bind, body } = self; + let types = match **args { + TyKind::Tuple(TyTuple { ref types }) => types.as_slice(), + TyKind::Empty => Default::default(), + _ => { + write!(f, "Invalid function signature: {sign}")?; + Default::default() + } + }; + + debug_assert_eq!(bind.len(), types.len()); write!(f, "fn {name} ")?; - delimit(separate(args, ", "), INLINE_PARENS)(f)?; + delimit( + |f| { + for (idx, (arg, ty)) in bind.iter().zip(types.iter()).enumerate() { + if idx != 0 { + f.write_str(", ")?; + } + write!(f, "{arg}: {ty}")?; + } + Ok(()) + }, + INLINE_PARENS, + )(f)?; if let Some(rety) = rety { write!(f, " -> {rety}")?; } @@ -180,8 +201,8 @@ mod display { } impl Display for Param { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let Self { mutability, name, ty } = self; - write!(f, "{mutability}{name}: {ty}") + let Self { mutability, name } = self; + write!(f, "{mutability}{name}") } } impl Display for Struct { diff --git a/cl-ast/src/lib.rs b/cl-ast/src/lib.rs index 3e3c671..22e24e9 100644 --- a/cl-ast/src/lib.rs +++ b/cl-ast/src/lib.rs @@ -135,9 +135,9 @@ pub enum ModuleKind { #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct Function { pub name: Identifier, - pub args: Vec, + pub sign: TyFn, + pub bind: Vec, pub body: Option, - pub rety: Option>, } /// A single parameter for a [Function] @@ -145,7 +145,6 @@ pub struct Function { pub struct Param { pub mutability: Mutability, pub name: Identifier, - pub ty: Box, } /// A user-defined product type diff --git a/cl-interpret/src/lib.rs b/cl-interpret/src/lib.rs index 70d6901..a8f0f85 100644 --- a/cl-interpret/src/lib.rs +++ b/cl-interpret/src/lib.rs @@ -324,7 +324,7 @@ pub mod function { name } fn call(&self, env: &mut Environment, args: &[ConValue]) -> IResult { - let FnDecl { name: Identifier(name), args: declargs, body, rety: _ } = &*self.decl; + let FnDecl { name: Identifier(name), bind: declargs, body, sign: _ } = &*self.decl; // Check arg mapping if args.len() != declargs.len() { return Err(Error::ArgNumber { want: declargs.len(), got: args.len() }); @@ -334,7 +334,7 @@ pub mod function { }; // TODO: completely refactor data storage let mut frame = env.frame("fn args"); - for (Param { mutability: _, name: Identifier(name), ty: _ }, value) in + for (Param { mutability: _, name: Identifier(name) }, value) in declargs.iter().zip(args) { frame.insert(name, Some(value.clone())); diff --git a/cl-parser/src/parser.rs b/cl-parser/src/parser.rs index c69a0d9..add07d8 100644 --- a/cl-parser/src/parser.rs +++ b/cl-parser/src/parser.rs @@ -394,20 +394,19 @@ impl<'t> Parser<'t> { const PARSING: Parsing = Parsing::Function; self.match_type(TokenKind::Fn, PARSING)?; + let name = self.identifier()?; + let (bind, types) = delim(Self::parse_params, PARENS, PARSING)(self)?; + let sign = TyFn { + args: Box::new(match types.len() { + 0 => TyKind::Empty, + _ => TyKind::Tuple(TyTuple { types }), + }), + rety: self.parse_rety()?.map(Box::new), + }; Ok(Function { - name: self.identifier()?, - args: self.parse_params()?, - rety: match self.peek_kind(PARSING)? { - TokenKind::Punct(Punct::LCurly) | TokenKind::Punct(Punct::Semi) => None, - TokenKind::Punct(Punct::Arrow) => { - self.consume_peeked(); - Some(self.ty()?.into()) - } - got => Err(self.error( - ExpectedToken { want: TokenKind::Punct(Punct::Arrow), got }, - PARSING, - ))?, - }, + name, + sign, + bind, body: match self.peek_kind(PARSING)? { TokenKind::Punct(Punct::LCurly) => Some(self.block()?), TokenKind::Punct(Punct::Semi) => { @@ -420,25 +419,29 @@ impl<'t> Parser<'t> { } /// Parses the [parameters](Param) associated with a Function - pub fn parse_params(&mut self) -> PResult> { + pub fn parse_params(&mut self) -> PResult<(Vec, Vec)> { const PARSING: Parsing = Parsing::Function; - delim( - sep(Self::parse_param, Punct::Comma, PARENS.1, PARSING), - PARENS, - PARSING, - )(self) + let (mut params, mut types) = (vec![], vec![]); + while Ok(TokenKind::Punct(Punct::RParen)) != self.peek_kind(PARSING) { + let (param, ty) = self.parse_param()?; + params.push(param); + types.push(ty); + if self.match_op(Punct::Comma, PARSING).is_err() { + break; + } + } + Ok((params, types)) } /// Parses a single function [parameter](Param) - pub fn parse_param(&mut self) -> PResult { - Ok(Param { - mutability: self.mutability()?, - name: self.identifier()?, - ty: { + pub fn parse_param(&mut self) -> PResult<(Param, TyKind)> { + Ok(( + Param { mutability: self.mutability()?, name: self.identifier()? }, + { self.match_op(Punct::Colon, Parsing::Param)?; - self.ty()?.into() + self.tykind()? }, - }) + )) } /// Parses a [`struct` definition](Struct) @@ -680,13 +683,14 @@ impl<'t> Parser<'t> { t if t.is_empty() => TyKind::Empty, types => TyKind::Tuple(TyTuple { types }), }), - rety: match self.peek_kind(PARSING) { - Ok(TokenKind::Punct(Punct::Arrow)) => { - self.consume_peeked(); - Some(self.ty()?.into()) - } - _ => None, - }, + rety: self.parse_rety()?.map(Into::into), + }) + } + + pub fn parse_rety(&mut self) -> PResult> { + Ok(match self.match_op(Punct::Arrow, Parsing::TyFn) { + Ok(_) => Some(self.ty()?), + Err(_) => None, }) } diff --git a/cl-repl/examples/yaml.rs b/cl-repl/examples/yaml.rs index 4d25979..ae82e30 100644 --- a/cl-repl/examples/yaml.rs +++ b/cl-repl/examples/yaml.rs @@ -247,12 +247,12 @@ pub mod yamlify { } impl Yamlify for Function { fn yaml(&self, y: &mut Yamler) { - let Self { name, args, body, rety } = self; + let Self { name, sign, bind, body } = self; y.key("Function") .pair("name", name) - .pair("args", args) - .pair("body", body) - .pair("rety", rety); + .pair("sign", sign) + .pair("bind", bind) + .pair("body", body); } } impl Yamlify for Struct { @@ -533,11 +533,8 @@ pub mod yamlify { } impl Yamlify for Param { fn yaml(&self, y: &mut Yamler) { - let Self { mutability, name, ty } = self; - y.key("Param") - .yaml(mutability) - .pair("name", name) - .pair("ty", ty); + let Self { mutability, name } = self; + y.key("Param").yaml(mutability).pair("name", name); } } impl Yamlify for Ty {