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) {
|
# pow = fn (n, p) {
|
||||||
# p == 0
|
# if p == 0 {
|
||||||
# ?? 1
|
# 1
|
||||||
# !! n * pow(n, p - 1)
|
# } else {
|
||||||
|
# n * pow(n, p - 1)
|
||||||
|
# }
|
||||||
# }
|
# }
|
||||||
|
|
||||||
kilo = pow(2, 10)
|
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_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_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_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); }
|
fn visit_atom(&mut self, atom: &Atom) -> Self::Out { DefaultAccept::default_accept(atom, self); }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -345,6 +345,11 @@ impl Visit for CompileBody<'_> {
|
|||||||
Ok(thunk)
|
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 {
|
fn visit_atom(&mut self, atom: &Atom) -> Self::Out {
|
||||||
let thunk = match atom {
|
let thunk = match atom {
|
||||||
Atom::Ident(ident) => {
|
Atom::Ident(ident) => {
|
||||||
|
|||||||
@@ -104,12 +104,13 @@ impl<V: Visit<Out=()>> DefaultAccept<V> for LhsExpr {
|
|||||||
//
|
//
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum Expr {
|
pub enum Expr {
|
||||||
Atom(Atom),
|
|
||||||
Bin(Box<BinExpr>),
|
Bin(Box<BinExpr>),
|
||||||
Un(Box<UnExpr>),
|
Un(Box<UnExpr>),
|
||||||
Access(Box<AccessExpr>),
|
|
||||||
Call(Box<CallExpr>),
|
Call(Box<CallExpr>),
|
||||||
Index(Box<IndexExpr>),
|
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 {
|
impl<V: Visit> DefaultAccept<V> for Expr {
|
||||||
fn default_accept(&self, visitor: &mut V) -> V::Out {
|
fn default_accept(&self, visitor: &mut V) -> V::Out {
|
||||||
match self {
|
match self {
|
||||||
Expr::Atom(a) => a.accept(visitor),
|
|
||||||
Expr::Bin(b) => b.accept(visitor),
|
Expr::Bin(b) => b.accept(visitor),
|
||||||
Expr::Un(u) => u.accept(visitor),
|
Expr::Un(u) => u.accept(visitor),
|
||||||
Expr::Access(a) => a.accept(visitor),
|
|
||||||
Expr::Call(c) => c.accept(visitor),
|
Expr::Call(c) => c.accept(visitor),
|
||||||
Expr::Index(i) => i.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)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum BinOp {
|
pub enum BinOp {
|
||||||
Plus,
|
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)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum Atom {
|
pub enum Atom {
|
||||||
Ident(String),
|
Ident(String),
|
||||||
@@ -376,12 +423,20 @@ pub enum Atom {
|
|||||||
String(String),
|
String(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// impl Accept for Atom
|
||||||
|
//
|
||||||
|
|
||||||
impl<V: Visit> Accept<V> for Atom {
|
impl<V: Visit> Accept<V> for Atom {
|
||||||
fn accept(&self, visitor: &mut V) -> V::Out {
|
fn accept(&self, visitor: &mut V) -> V::Out {
|
||||||
visitor.visit_atom(self)
|
visitor.visit_atom(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// impl DefaultAccept for Atom
|
||||||
|
//
|
||||||
|
|
||||||
impl<V: Visit<Out=()>> DefaultAccept<V> for Atom {
|
impl<V: Visit<Out=()>> DefaultAccept<V> for Atom {
|
||||||
fn default_accept(&self, _visitor: &mut V) -> V::Out { }
|
fn default_accept(&self, _visitor: &mut V) -> V::Out { }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
%%
|
%%
|
||||||
|
fn "fn"
|
||||||
|
|
||||||
[\r\n;]+ "EOL"
|
[\r\n;]+ "EOL"
|
||||||
[a-zA-Z_][a-zA-Z0-9_]* "IDENT"
|
[a-zA-Z_][a-zA-Z0-9_]* "IDENT"
|
||||||
:[a-zA-Z_][a-zA-Z0-9_]* "SYM"
|
:[a-zA-Z_][a-zA-Z0-9_]* "SYM"
|
||||||
@@ -22,6 +24,8 @@
|
|||||||
\) ")"
|
\) ")"
|
||||||
\[ "["
|
\[ "["
|
||||||
\] "]"
|
\] "]"
|
||||||
|
\{ "{"
|
||||||
|
\} "}"
|
||||||
\. "."
|
\. "."
|
||||||
, ","
|
, ","
|
||||||
|
|
||||||
|
|||||||
@@ -92,10 +92,25 @@ IndexExpr -> Result<Expr>:
|
|||||||
;
|
;
|
||||||
|
|
||||||
AccessExpr -> Result<Expr>:
|
AccessExpr -> Result<Expr>:
|
||||||
AtomExpr { $1 }
|
FunExpr { $1 }
|
||||||
| CallIndexExpr '.' Ident { Ok(AccessExpr::new_expr($1?, $3?)) }
|
| 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>:
|
AtomExpr -> Result<Expr>:
|
||||||
Atom { $1.map(Expr::Atom) }
|
Atom { $1.map(Expr::Atom) }
|
||||||
| '(' Expr ')' { $2 }
|
| '(' Expr ')' { $2 }
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ pub trait Visit {
|
|||||||
fn visit_call_expr(&mut self, expr: &CallExpr) -> Self::Out;
|
fn visit_call_expr(&mut self, expr: &CallExpr) -> Self::Out;
|
||||||
fn visit_index_expr(&mut self, expr: &IndexExpr) -> Self::Out;
|
fn visit_index_expr(&mut self, expr: &IndexExpr) -> Self::Out;
|
||||||
fn visit_access_expr(&mut self, expr: &AccessExpr) -> 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;
|
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_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_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_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); }
|
fn visit_atom(&mut self, atom: &Atom) -> Self::Out { DefaultAccept(atom, self); }
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user