Add function expr parsing
* Introduce new `fn` keyword * Function example is added to examples/expr.not Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
# pow = (n, p) {
|
||||
# p == 0
|
||||
# ?? 1
|
||||
# !! n * pow(n, p - 1)
|
||||
# pow = fn (n, p) {
|
||||
# if p == 0 {
|
||||
# 1
|
||||
# } else {
|
||||
# n * pow(n, p - 1)
|
||||
# }
|
||||
# }
|
||||
|
||||
kilo = pow(2, 10)
|
||||
|
||||
@@ -48,5 +48,8 @@ impl Visit for CollectLocals<'_> {
|
||||
fn visit_call_expr(&mut self, expr: &CallExpr) -> Self::Out { DefaultAccept::default_accept(expr, self); }
|
||||
fn visit_index_expr(&mut self, expr: &IndexExpr) -> Self::Out { DefaultAccept::default_accept(expr, self); }
|
||||
fn visit_access_expr(&mut self, expr: &AccessExpr) -> Self::Out { DefaultAccept::default_accept(expr, self); }
|
||||
fn visit_fun_expr(&mut self, _expr: &FunExpr) -> Self::Out {
|
||||
// Do not collect names for function expressions, since they have their own scope.
|
||||
}
|
||||
fn visit_atom(&mut self, atom: &Atom) -> Self::Out { DefaultAccept::default_accept(atom, self); }
|
||||
}
|
||||
|
||||
@@ -345,6 +345,11 @@ impl Visit for CompileBody<'_> {
|
||||
Ok(thunk)
|
||||
}
|
||||
|
||||
fn visit_fun_expr(&mut self, _expr: &FunExpr) -> Self::Out {
|
||||
// TODO : fun exprs should be compiled as constants and put into the constant pool
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn visit_atom(&mut self, atom: &Atom) -> Self::Out {
|
||||
let thunk = match atom {
|
||||
Atom::Ident(ident) => {
|
||||
|
||||
@@ -104,12 +104,13 @@ impl<V: Visit<Out=()>> DefaultAccept<V> for LhsExpr {
|
||||
//
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum Expr {
|
||||
Atom(Atom),
|
||||
Bin(Box<BinExpr>),
|
||||
Un(Box<UnExpr>),
|
||||
Access(Box<AccessExpr>),
|
||||
Call(Box<CallExpr>),
|
||||
Index(Box<IndexExpr>),
|
||||
Access(Box<AccessExpr>),
|
||||
Fun(Box<FunExpr>),
|
||||
Atom(Atom),
|
||||
}
|
||||
|
||||
//
|
||||
@@ -127,12 +128,13 @@ impl<V: Visit> Accept<V> for Expr {
|
||||
impl<V: Visit> DefaultAccept<V> for Expr {
|
||||
fn default_accept(&self, visitor: &mut V) -> V::Out {
|
||||
match self {
|
||||
Expr::Atom(a) => a.accept(visitor),
|
||||
Expr::Bin(b) => b.accept(visitor),
|
||||
Expr::Un(u) => u.accept(visitor),
|
||||
Expr::Access(a) => a.accept(visitor),
|
||||
Expr::Call(c) => c.accept(visitor),
|
||||
Expr::Index(i) => i.accept(visitor),
|
||||
Expr::Access(a) => a.accept(visitor),
|
||||
Expr::Fun(f) => f.accept(visitor),
|
||||
Expr::Atom(a) => a.accept(visitor),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -176,6 +178,12 @@ impl From<IndexExpr> for Expr {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FunExpr> for Expr {
|
||||
fn from(other: FunExpr) -> Self {
|
||||
Expr::Fun(other.into())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum BinOp {
|
||||
Plus,
|
||||
@@ -368,6 +376,45 @@ impl<V: Visit> DefaultAccept<V> for AccessExpr {
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// struct FunExpr
|
||||
//
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct FunExpr {
|
||||
pub params: Vec<String>,
|
||||
pub body: Body,
|
||||
}
|
||||
|
||||
//
|
||||
// impl FunExpr
|
||||
//
|
||||
impl FunExpr {
|
||||
pub fn new_expr(params: Vec<String>, body: Body) -> Expr {
|
||||
Self { params, body, }.into()
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// impl Accept for FunExpr
|
||||
//
|
||||
impl<V: Visit> Accept<V> for FunExpr {
|
||||
fn accept(&self, visitor: &mut V) -> V::Out {
|
||||
visitor.visit_fun_expr(self)
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// impl DefaultAccept for FunExpr
|
||||
//
|
||||
impl<V: Visit> DefaultAccept<V> for FunExpr {
|
||||
fn default_accept(&self, visitor: &mut V) -> V::Out {
|
||||
visitor.visit_body(&self.body)
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// enum Atom
|
||||
//
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum Atom {
|
||||
Ident(String),
|
||||
@@ -376,12 +423,20 @@ pub enum Atom {
|
||||
String(String),
|
||||
}
|
||||
|
||||
//
|
||||
// impl Accept for Atom
|
||||
//
|
||||
|
||||
impl<V: Visit> Accept<V> for Atom {
|
||||
fn accept(&self, visitor: &mut V) -> V::Out {
|
||||
visitor.visit_atom(self)
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// impl DefaultAccept for Atom
|
||||
//
|
||||
|
||||
impl<V: Visit<Out=()>> DefaultAccept<V> for Atom {
|
||||
fn default_accept(&self, _visitor: &mut V) -> V::Out { }
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
%%
|
||||
fn "fn"
|
||||
|
||||
[\r\n;]+ "EOL"
|
||||
[a-zA-Z_][a-zA-Z0-9_]* "IDENT"
|
||||
:[a-zA-Z_][a-zA-Z0-9_]* "SYM"
|
||||
@@ -22,6 +24,8 @@
|
||||
\) ")"
|
||||
\[ "["
|
||||
\] "]"
|
||||
\{ "{"
|
||||
\} "}"
|
||||
\. "."
|
||||
, ","
|
||||
|
||||
|
||||
@@ -92,10 +92,25 @@ IndexExpr -> Result<Expr>:
|
||||
;
|
||||
|
||||
AccessExpr -> Result<Expr>:
|
||||
AtomExpr { $1 }
|
||||
FunExpr { $1 }
|
||||
| CallIndexExpr '.' Ident { Ok(AccessExpr::new_expr($1?, $3?)) }
|
||||
;
|
||||
|
||||
FunExpr -> Result<Expr>:
|
||||
AtomExpr { $1 }
|
||||
| 'fn' '(' FunParams ')' '{' Body '}' { Ok(FunExpr::new_expr($3?, $6?)) }
|
||||
;
|
||||
|
||||
FunParams -> Result<Vec<String>>:
|
||||
FunParamsTail { $1 }
|
||||
| { Ok(Vec::new()) }
|
||||
;
|
||||
|
||||
FunParamsTail -> Result<Vec<String>>:
|
||||
FunParamsTail ',' Ident { flatten($1, $3) }
|
||||
| Ident { Ok(vec![$1?]) }
|
||||
;
|
||||
|
||||
AtomExpr -> Result<Expr>:
|
||||
Atom { $1.map(Expr::Atom) }
|
||||
| '(' Expr ')' { $2 }
|
||||
|
||||
@@ -21,6 +21,7 @@ pub trait Visit {
|
||||
fn visit_call_expr(&mut self, expr: &CallExpr) -> Self::Out;
|
||||
fn visit_index_expr(&mut self, expr: &IndexExpr) -> Self::Out;
|
||||
fn visit_access_expr(&mut self, expr: &AccessExpr) -> Self::Out;
|
||||
fn visit_fun_expr(&mut self, expr: &FunExpr) -> Self::Out;
|
||||
fn visit_atom(&mut self, atom: &Atom) -> Self::Out;
|
||||
}
|
||||
|
||||
@@ -37,6 +38,7 @@ copy/paste of default_accepts
|
||||
fn visit_call_expr(&mut self, expr: &CallExpr) -> Self::Out { DefaultAccept::default_accept(expr, self); }
|
||||
fn visit_index_expr(&mut self, expr: &IndexExpr) -> Self::Out { DefaultAccept::default_accept(expr, self); }
|
||||
fn visit_access_expr(&mut self, expr: &AccessExpr) -> Self::Out { DefaultAccept::default_accept(expr, self); }
|
||||
fn visit_fun_expr(&mut self, expr: &FunExpr) -> Self::Out { DefaultAccept::default_accept(expr, self); }
|
||||
fn visit_atom(&mut self, atom: &Atom) -> Self::Out { DefaultAccept(atom, self); }
|
||||
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user