Skip to content

Commit

Permalink
fix expression grouping
Browse files Browse the repository at this point in the history
  • Loading branch information
simvux committed Sep 6, 2024
1 parent 1f8878a commit a5c32ab
Show file tree
Hide file tree
Showing 29 changed files with 152 additions and 195 deletions.
5 changes: 5 additions & 0 deletions examples/operators/config.lm
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
val name = "operators"
val version = "1.0"
val authors = []

val dependencies = []
6 changes: 6 additions & 0 deletions examples/operators/src/main.lm
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
use std:io

fn main =
io:println (10 - 1 * 2 / (4 + 1) - 2 +++ 5)

fn +++ x y as int, int -> int = x + y + y
2 changes: 1 addition & 1 deletion lumina-compiler/src/ast/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ fn path<'a, 's>(
exp: &'static str,
) -> Result<(&'a parser::AnnotatedPath<'s>, &'a [Tr<parser::Expr<'s>>]), Error> {
match expr.value {
parser::Expr::Call(apath, params, _) => Ok((apath, params)),
parser::Expr::Call(apath, params) => Ok((apath, params)),
_ => Err(Error::Expected(expr.span, exp)),
}
}
Expand Down
114 changes: 68 additions & 46 deletions lumina-compiler/src/hir/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ impl<'t, 'a, 's> FuncLower<'t, 'a, 's> {
.collect::<Vec<_>>()
}

pub fn expr(&mut self, expr: Tr<&parser::Expr<'s>>) -> Tr<Expr<'s>> {
pub fn expr(&mut self, mut expr: Tr<&parser::Expr<'s>>) -> Tr<Expr<'s>> {
trace!("lowering expression {expr}");

match expr.value {
Expand All @@ -91,19 +91,19 @@ impl<'t, 'a, 's> FuncLower<'t, 'a, 's> {
}
parser::Expr::Lit(parser::Literal::Float(n)) => Expr::Lit(Literal::Float(*n)),
parser::Expr::Lit(parser::Literal::String(str)) => Expr::Lit(Literal::String(*str)),
parser::Expr::Call(apath, params, _) => {
self.callable(apath.as_ref(), params, Expr::Call)
}
parser::Expr::Lambda(patterns, params, body, _seal) => {
parser::Expr::Call(apath, params) => self.callable(apath.as_ref(), params, Expr::Call),
parser::Expr::Lambda(patterns, params, body) => {
let lambda = self.lambda(patterns, None, (**body).as_ref());
let params = self.exprs(params);
Expr::Call(lambda.into(), TypeAnnotation::new(), params)
}

parser::Expr::Group(inner) => self.expr((&**inner).tr(expr.span)).value,

// (f 0) 1
// -------
// let _ = #(f 0) in _ 1
parser::Expr::CallExpr(inner, params, _) => {
parser::Expr::CallExpr(inner, params) => {
let value = Expr::PassExpr(Box::new(self.expr((**inner).as_ref()))).tr(inner.span);
let params = self.exprs(params);

Expand All @@ -123,7 +123,8 @@ impl<'t, 'a, 's> FuncLower<'t, 'a, 's> {
}
parser::Expr::DotPipe(elems) => {
let [left, right] = &**elems;
self.dotpipe(expr.span, left.as_ref(), right.as_ref())
expr.span = right.span;
self.dotpipe(left.as_ref(), right.as_ref())
}
parser::Expr::Match(on, branches) => {
let on = self.expr(on.as_ref().as_ref());
Expand Down Expand Up @@ -193,43 +194,52 @@ impl<'t, 'a, 's> FuncLower<'t, 'a, 's> {
.tr(expr.span)
}

fn pass(&mut self, inner: Tr<&parser::Expr<'s>>) -> Expr<'s> {
match &inner.value {
parser::Expr::Call(apath, params, seal) if *seal < 2 => {
self.callable(apath.as_ref(), params, Expr::Pass)
}
parser::Expr::Call(apath, params, _) => {
// #((f a))
// lowers to
// let _ = f a in #_
let expr = self.callable(apath.as_ref(), params, Expr::Call);
let bind = self.bindings.declare_nameless();
let pat = Pattern::Bind(bind, Box::new(Pattern::Any)).tr(apath.span);
let and_then =
Expr::Pass(bind.into(), TypeAnnotation::new(), vec![]).tr(apath.span);
Expr::let_bind(expr.tr(apath.span), pat, and_then)
}
parser::Expr::Lambda(patterns, params, body, seal) if *seal == 1 => {
assert!(params.is_empty(), "does the parser allow parameters here?");
warn!(
fn pass(&mut self, to_pass: Tr<&parser::Expr<'s>>) -> Expr<'s> {
match &to_pass.value {
// #(...)
parser::Expr::Group(inner) => match &**inner {
// #(\ ...)
parser::Expr::Lambda(patterns, params, body) => {
assert!(params.is_empty());
warn!(
"TODO: add type annotation to the parser and give the typing here for lambdas"
);
let lambda = self.lambda(patterns, None, (**body).as_ref());
let params = self.exprs(params);
Expr::Pass(lambda.into(), TypeAnnotation::new(), params)
}
parser::Expr::Lambda(_, _, _, seal) => {
assert_ne!(*seal, 0);
todo!("evaluate and then pass the returned value from evaluation");
let lambda = self.lambda(patterns, None, (**body).as_ref());
let params = self.exprs(params);
Expr::Pass(lambda.into(), TypeAnnotation::new(), params)
}
// #(f ...)
parser::Expr::Call(apath, params) => {
self.callable(apath.as_ref(), params, Expr::Pass)
}
// #((f ...))
parser::Expr::Group(inner) => {
let inner = self.expr((&**inner).tr(to_pass.span));
Expr::PassExpr(Box::new(inner))
}
parser::Expr::CallExpr(inner, _) => {
let inner = self.expr((**inner).as_ref());
todo!("error that it's not a valid pass?");
}
// #(0)
_ => {
let lkey = self.lambda(&[], None, (&**inner).tr(to_pass.span));
Expr::Pass(lkey.into(), TypeAnnotation::new(), vec![])
}
},
// #f
parser::Expr::Call(apath, params) => {
assert!(params.is_empty());
self.callable(apath.as_ref(), params, Expr::Pass)
}
// ##...
parser::Expr::Pass(inner) => {
let inner = self.expr((**inner).as_ref());
Expr::PassExpr(Box::new(inner))
let inner = self.pass((**inner).as_ref());
Expr::PassExpr(Box::new(inner.tr(to_pass.span)))
}
parser::Expr::CallExpr(_, _, _) => todo!(""),

// #0
_ => {
let lkey = self.lambda(&[], None, inner);
let lkey = self.lambda(&[], None, (&**to_pass).tr(to_pass.span));
Expr::Pass(lkey.into(), TypeAnnotation::new(), vec![])
}
}
Expand Down Expand Up @@ -265,14 +275,9 @@ impl<'t, 'a, 's> FuncLower<'t, 'a, 's> {
}
}

fn dotpipe(
&mut self,
span: Span,
left: Tr<&parser::Expr<'s>>,
right: Tr<&parser::Expr<'s>>,
) -> Expr<'s> {
fn dotpipe(&mut self, left: Tr<&parser::Expr<'s>>, right: Tr<&parser::Expr<'s>>) -> Expr<'s> {
match right.value {
parser::Expr::Call(apath, params, _) => {
parser::Expr::Call(apath, params) => {
let left = self.expr(left);

let path = apath.path.as_slice();
Expand Down Expand Up @@ -315,12 +320,29 @@ impl<'t, 'a, 's> FuncLower<'t, 'a, 's> {
})
}
}
// 1 . (returns_function 0)
// lowers to
// let _ = #(returns_function 0) in _ 1
parser::Expr::Group(inner) => {
let yielded_function = self.expr((&**inner).tr(right.span));
let intermediate = self.bindings.declare_nameless();
let param = self.expr(left);
Expr::let_bind(
yielded_function,
Pattern::Bind(intermediate, Box::new(Pattern::Any)).tr(left.span),
Expr::Call(intermediate.into(), TypeAnnotation::new(), vec![param])
.tr(right.span),
)
}
_ => {
self.ast
.sources
.error("invalid pipe operator")
.m(self.module)
.eline(span, "dot pipes may only be used to applicate functions")
.eline(
right.span,
"dot pipes may only be used to applicate functions",
)
.emit();

Expr::Poison
Expand Down
Loading

0 comments on commit a5c32ab

Please sign in to comment.