cl-ast: Separate function *signature* from function bindings, for cl-typeck
Note: this breaks cl-typeck
This commit is contained in:
parent
d0ed8309f4
commit
75adbd6473
@ -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 {
|
||||||
|
@ -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
|
||||||
|
@ -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()));
|
||||||
|
@ -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,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user