cl-ast: Separate function *signature* from function bindings, for cl-typeck

Note: this breaks cl-typeck
This commit is contained in:
John 2024-04-16 20:31:23 -05:00
parent d0ed8309f4
commit 75adbd6473
5 changed files with 72 additions and 51 deletions

View File

@ -166,9 +166,30 @@ mod display {
} }
impl Display for Function { impl Display for Function {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 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} ")?; 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 { if let Some(rety) = rety {
write!(f, " -> {rety}")?; write!(f, " -> {rety}")?;
} }
@ -180,8 +201,8 @@ mod display {
} }
impl Display for Param { impl Display for Param {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { mutability, name, ty } = self; let Self { mutability, name } = self;
write!(f, "{mutability}{name}: {ty}") write!(f, "{mutability}{name}")
} }
} }
impl Display for Struct { impl Display for Struct {

View File

@ -135,9 +135,9 @@ pub enum ModuleKind {
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Function { pub struct Function {
pub name: Identifier, pub name: Identifier,
pub args: Vec<Param>, pub sign: TyFn,
pub bind: Vec<Param>,
pub body: Option<Block>, pub body: Option<Block>,
pub rety: Option<Box<Ty>>,
} }
/// A single parameter for a [Function] /// A single parameter for a [Function]
@ -145,7 +145,6 @@ pub struct Function {
pub struct Param { pub struct Param {
pub mutability: Mutability, pub mutability: Mutability,
pub name: Identifier, pub name: Identifier,
pub ty: Box<Ty>,
} }
/// A user-defined product type /// A user-defined product type

View File

@ -324,7 +324,7 @@ pub mod function {
name name
} }
fn call(&self, env: &mut Environment, args: &[ConValue]) -> IResult<ConValue> { fn call(&self, env: &mut Environment, args: &[ConValue]) -> IResult<ConValue> {
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 // Check arg mapping
if args.len() != declargs.len() { if args.len() != declargs.len() {
return Err(Error::ArgNumber { want: declargs.len(), got: args.len() }); return Err(Error::ArgNumber { want: declargs.len(), got: args.len() });
@ -334,7 +334,7 @@ pub mod function {
}; };
// TODO: completely refactor data storage // TODO: completely refactor data storage
let mut frame = env.frame("fn args"); 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) declargs.iter().zip(args)
{ {
frame.insert(name, Some(value.clone())); frame.insert(name, Some(value.clone()));

View File

@ -394,20 +394,19 @@ impl<'t> Parser<'t> {
const PARSING: Parsing = Parsing::Function; const PARSING: Parsing = Parsing::Function;
self.match_type(TokenKind::Fn, PARSING)?; 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 { Ok(Function {
name: self.identifier()?, name,
args: self.parse_params()?, sign,
rety: match self.peek_kind(PARSING)? { bind,
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,
))?,
},
body: match self.peek_kind(PARSING)? { body: match self.peek_kind(PARSING)? {
TokenKind::Punct(Punct::LCurly) => Some(self.block()?), TokenKind::Punct(Punct::LCurly) => Some(self.block()?),
TokenKind::Punct(Punct::Semi) => { TokenKind::Punct(Punct::Semi) => {
@ -420,25 +419,29 @@ impl<'t> Parser<'t> {
} }
/// Parses the [parameters](Param) associated with a Function /// Parses the [parameters](Param) associated with a Function
pub fn parse_params(&mut self) -> PResult<Vec<Param>> { pub fn parse_params(&mut self) -> PResult<(Vec<Param>, Vec<TyKind>)> {
const PARSING: Parsing = Parsing::Function; const PARSING: Parsing = Parsing::Function;
delim( let (mut params, mut types) = (vec![], vec![]);
sep(Self::parse_param, Punct::Comma, PARENS.1, PARSING), while Ok(TokenKind::Punct(Punct::RParen)) != self.peek_kind(PARSING) {
PARENS, let (param, ty) = self.parse_param()?;
PARSING, params.push(param);
)(self) types.push(ty);
if self.match_op(Punct::Comma, PARSING).is_err() {
break;
}
}
Ok((params, types))
} }
/// Parses a single function [parameter](Param) /// Parses a single function [parameter](Param)
pub fn parse_param(&mut self) -> PResult<Param> { pub fn parse_param(&mut self) -> PResult<(Param, TyKind)> {
Ok(Param { Ok((
mutability: self.mutability()?, Param { mutability: self.mutability()?, name: self.identifier()? },
name: self.identifier()?, {
ty: {
self.match_op(Punct::Colon, Parsing::Param)?; self.match_op(Punct::Colon, Parsing::Param)?;
self.ty()?.into() self.tykind()?
}, },
}) ))
} }
/// Parses a [`struct` definition](Struct) /// Parses a [`struct` definition](Struct)
@ -680,13 +683,14 @@ impl<'t> Parser<'t> {
t if t.is_empty() => TyKind::Empty, t if t.is_empty() => TyKind::Empty,
types => TyKind::Tuple(TyTuple { types }), types => TyKind::Tuple(TyTuple { types }),
}), }),
rety: match self.peek_kind(PARSING) { rety: self.parse_rety()?.map(Into::into),
Ok(TokenKind::Punct(Punct::Arrow)) => { })
self.consume_peeked();
Some(self.ty()?.into())
} }
_ => None,
}, pub fn parse_rety(&mut self) -> PResult<Option<Ty>> {
Ok(match self.match_op(Punct::Arrow, Parsing::TyFn) {
Ok(_) => Some(self.ty()?),
Err(_) => None,
}) })
} }

View File

@ -247,12 +247,12 @@ pub mod yamlify {
} }
impl Yamlify for Function { impl Yamlify for Function {
fn yaml(&self, y: &mut Yamler) { fn yaml(&self, y: &mut Yamler) {
let Self { name, args, body, rety } = self; let Self { name, sign, bind, body } = self;
y.key("Function") y.key("Function")
.pair("name", name) .pair("name", name)
.pair("args", args) .pair("sign", sign)
.pair("body", body) .pair("bind", bind)
.pair("rety", rety); .pair("body", body);
} }
} }
impl Yamlify for Struct { impl Yamlify for Struct {
@ -533,11 +533,8 @@ pub mod yamlify {
} }
impl Yamlify for Param { impl Yamlify for Param {
fn yaml(&self, y: &mut Yamler) { fn yaml(&self, y: &mut Yamler) {
let Self { mutability, name, ty } = self; let Self { mutability, name } = self;
y.key("Param") y.key("Param").yaml(mutability).pair("name", name);
.yaml(mutability)
.pair("name", name)
.pair("ty", ty);
} }
} }
impl Yamlify for Ty { impl Yamlify for Ty {