diff --git a/crates/codegen/src/fmt/mod.rs b/crates/codegen/src/fmt/mod.rs index 6da4bdd..b714300 100644 --- a/crates/codegen/src/fmt/mod.rs +++ b/crates/codegen/src/fmt/mod.rs @@ -176,7 +176,7 @@ impl GetMist for TypeExpr { } Self::UnsafePtr { mutable, ty } => { let mutable = if *mutable { "mut " } else { "const " }; - format!("*{mutable}{}", ty.get_mist()) + format!("{} {mutable} unsafe&", ty.get_mist()) } Self::Ref { lifetime, @@ -185,19 +185,12 @@ impl GetMist for TypeExpr { } => { let base = ty.get_mist(); if let Some(lifetime) = lifetime { - match lifetime { - Lifetime::Lifetime(v) => { - format!( - "{} {} '{}&", - base, - if *mutable { "mut" } else { "" }, - v.get_mist() - ) - } - Lifetime::Unsafe => { - format!("{} {} unsafe&", base, if *mutable { "mut" } else { "const" }) - } - } + format!( + "{} {} '{}&", + base, + if *mutable { "mut" } else { "" }, + lifetime.get_mist() + ) } else if *mutable { format!("{} mut&", base) } else { @@ -207,10 +200,40 @@ impl GetMist for TypeExpr { Self::Dyn(ty) => { format!("dyn {}", ty.get_mist()) } + Self::Void => "void".to_string(), + Self::Fn { + kind, + return_type, + params, + } => { + format!( + "{} {}({})", + return_type.get_mist(), + kind.get_mist(), + params + .iter() + .map(TypeExpr::get_mist) + .collect::>() + .join(", ") + ) + } } } } +impl GetMist for FnKind { + fn get_mist(&self) -> String { + match self { + Self::Fn => "fn", + Self::UnsafeFn => "unsafe fn", + Self::FnClosure => "Fn", + Self::FnMut => "FnMut", + Self::FnOnce => "FnOnce", + } + .to_string() + } +} + impl GetMist for ExprPath { fn get_mist(&self) -> String { self.0 diff --git a/crates/codegen/src/lib.rs b/crates/codegen/src/lib.rs index 6323b91..3e0610a 100644 --- a/crates/codegen/src/lib.rs +++ b/crates/codegen/src/lib.rs @@ -247,23 +247,12 @@ impl GetRust for TypeExpr { ty, } => { if let Some(lifetime) = lifetime { - match lifetime { - Lifetime::Lifetime(v) => { - format!( - "&'{} {}{}", - v.get_rust(), - if *mutable { "mut " } else { "" }, - ty.get_rust() - ) - } - Lifetime::Unsafe => { - format!( - "*{} {}", - if *mutable { "mut" } else { "const" }, - ty.get_rust() - ) - } - } + format!( + "&'{} {}{}", + lifetime.get_rust(), + if *mutable { "mut " } else { "" }, + ty.get_rust() + ) } else { format!("&{}{}", if *mutable { "mut " } else { "" }, ty.get_rust()) } @@ -272,10 +261,40 @@ impl GetRust for TypeExpr { Self::Dyn(ty) => { format!("dyn {}", ty.get_rust()) } + Self::Void => "()".to_string(), + Self::Fn { + kind, + return_type, + params, + } => { + format!( + "{}({}) -> {}", + kind.get_rust(), + params + .iter() + .map(TypeExpr::get_rust) + .collect::>() + .join(", "), + return_type.get_rust(), + ) + } } } } +impl GetRust for FnKind { + fn get_rust(&self) -> String { + match self { + Self::Fn => "fn", + Self::UnsafeFn => "unsafe fn", + Self::FnClosure => "Fn", + Self::FnMut => "FnMut", + Self::FnOnce => "FnOnce", + } + .to_string() + } +} + impl GenRust for Pattern { fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { match self { diff --git a/crates/parser/src/ast/mod.rs b/crates/parser/src/ast/mod.rs index 7de3984..44ab48d 100644 --- a/crates/parser/src/ast/mod.rs +++ b/crates/parser/src/ast/mod.rs @@ -18,15 +18,18 @@ pub struct Identifier(pub String); pub struct ParamList(pub Vec); #[derive(Debug, Clone, Serialize, PartialEq, Eq, Hash)] -pub enum Lifetime { - Lifetime(Identifier), - Unsafe, +pub enum FnKind { + Fn, + UnsafeFn, + FnClosure, + FnOnce, + FnMut, } #[derive(Debug, Clone, Serialize, PartialEq, Eq, Hash)] pub enum TypeExpr { Ref { - lifetime: Option, + lifetime: Option, mutable: bool, ty: Box, }, @@ -39,6 +42,12 @@ pub enum TypeExpr { StaticFn(Vec, Option>), Tuple(Vec), Lifetime(Identifier), + Void, + Fn { + kind: FnKind, + return_type: Box, + params: Vec, + }, } #[derive(Debug, Clone, Serialize)] diff --git a/crates/parser/src/grammar.pest b/crates/parser/src/grammar.pest index ae5c4bc..4cfbbe1 100644 --- a/crates/parser/src/grammar.pest +++ b/crates/parser/src/grammar.pest @@ -81,7 +81,6 @@ module_program = { visibility = { "pub" ~ ("(" ~ static_path ~ ")")? } mutable = { "mut" } -unsafe_kw = { "unsafe" } // ====================================================== // GENERICS @@ -104,18 +103,42 @@ path_type = { static_path ~ generics? } -ref_lifetime = { lifetime | unsafe_kw } +unsafe_ref_type = { + mutable? ~ "unsafe" ~ "*" +} ref_type = { - mutable? ~ ref_lifetime? ~ "&" + mutable? ~ lifetime? ~ "&" +} + +fn_kind_fn = { "fn" } +fn_kind_unsafe = { "unsafe" ~ "fn" } +fn_kind_closure = { "Fn" } +fn_kind_once = { "FnOnce" } +fn_kind_mut = { "FnMut" } + +fn_kind = _{ + fn_kind_fn + | fn_kind_unsafe + | fn_kind_closure + | fn_kind_once + | fn_kind_mut +} + +fn_type = { + fn_kind ~ "(" ~ (type_expr ~ ("," ~ type_expr)*)? ~ ")" } dyn_type = { "dyn" ~ type_expr } +void_type = { + "void" +} + type_expr = { - (path_type | tuple_type | dyn_type) ~ ref_type* + (void_type | path_type | tuple_type | dyn_type) ~ (unsafe_ref_type | ref_type | fn_type)* } lifetime = { @@ -467,7 +490,7 @@ match_stmt = { closure = { ("(" ~ param_list ~ ")" ~ "=>" ~ expr) - | (type_expr ~ "(" ~ param_list ~ ")" ~ "=>" ~ expr) + | (type_expr ~ "(" ~ param_list ~ ")" ~ "=>" ~ expr) } // ------------------------------------------------------ diff --git a/crates/parser/src/parser/common/types.rs b/crates/parser/src/parser/common/types.rs index adf253d..6726f41 100644 --- a/crates/parser/src/parser/common/types.rs +++ b/crates/parser/src/parser/common/types.rs @@ -21,23 +21,46 @@ impl<'a> TryFrom> for TypeExpr { let mut ty = TypeExpr::try_from(inner.next().unwrap())?; for ref_pair in inner { - let mut ref_inner = ref_pair.into_inner(); + let mut ref_inner = ref_pair.clone().into_inner(); - ty = TypeExpr::Ref { - lifetime: consume_rule(&mut ref_inner, Rule::ref_lifetime) - .map(|v| v.into_inner().next().map(Lifetime::try_from)) - .unwrap_or_default() - .transpose()?, - mutable: listen_rule(&mut ref_inner, Rule::mutable), - ty: Box::new(ty), - }; + match ref_pair.as_rule() { + Rule::ref_type => { + ty = TypeExpr::Ref { + mutable: listen_rule(&mut ref_inner, Rule::mutable), + lifetime: consume_rule(&mut ref_inner, Rule::lifetime) + .map(|v| v.into_inner().next().map(Identifier::try_from)) + .unwrap_or_default() + .transpose()?, + ty: Box::new(ty), + }; + } + + Rule::unsafe_ref_type => { + ty = TypeExpr::UnsafePtr { + mutable: listen_rule(&mut ref_inner, Rule::mutable), + ty: Box::new(ty), + }; + } + + Rule::fn_type => { + ty = TypeExpr::Fn { + return_type: Box::new(ty), + kind: ref_inner.next().unwrap().try_into()?, + params: collect_recovered(ref_inner)?, + }; + } + + _ => AstError::bug_unimplemented(ref_pair)?, + } } Ok(ty) } Rule::lifetime => Ok(TypeExpr::Lifetime(inner.next().unwrap().try_into()?)), + Rule::void_type => Ok(TypeExpr::Void), Rule::tuple_type => Ok(TypeExpr::Tuple(collect_recovered(inner)?)), + Rule::path_type => Ok(TypeExpr::Path( Path::try_from(inner.next().unwrap())?, inner.next().map(Generics::try_from).transpose()?, @@ -52,6 +75,22 @@ impl<'a> TryFrom> for TypeExpr { } } +impl<'a> TryFrom> for FnKind { + type Error = AstError<'a>; + + fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { + match pair.as_rule() { + Rule::fn_kind_fn => Ok(FnKind::Fn), + Rule::fn_kind_unsafe => Ok(FnKind::UnsafeFn), + Rule::fn_kind_closure => Ok(FnKind::FnClosure), + Rule::fn_kind_once => Ok(FnKind::FnOnce), + Rule::fn_kind_mut => Ok(FnKind::FnMut), + + _ => AstError::bug_unimplemented(pair), + } + } +} + impl<'a> TryFrom> for GenericsDecl { type Error = AstError<'a>; diff --git a/crates/parser/src/parser/items/function.rs b/crates/parser/src/parser/items/function.rs index dca1d06..7c7ac46 100644 --- a/crates/parser/src/parser/items/function.rs +++ b/crates/parser/src/parser/items/function.rs @@ -2,7 +2,7 @@ use crate::{ Rule, ast::*, ast_ensure, - error::{self, AstError, AstResult}, + error::{AstError, AstResult}, parser::{consume_rule, consume_rule_map, listen_rule}, }; @@ -66,18 +66,3 @@ impl<'a> TryFrom> for Override { }) } } - -impl<'a> TryFrom> for Lifetime { - type Error = AstError<'a>; - - fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { - let mut inner = pair.clone().into_inner(); - - match pair.as_rule() { - Rule::ref_lifetime => inner.next().unwrap().try_into(), - Rule::lifetime => Ok(Lifetime::Lifetime(inner.next().unwrap().try_into()?)), - Rule::unsafe_kw => Ok(Lifetime::Unsafe), - _ => error::AstError::bug_unimplemented(pair), - } - } -}