summaryrefslogtreecommitdiff
path: root/src/syntax
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2020-08-14 20:43:03 +0200
committerLaurenz <laurmaedje@gmail.com>2020-08-14 20:43:03 +0200
commitc8f6b5bd5c55845562571c196a0b2c1a7ca20f71 (patch)
tree0e5066064f1bf81f847cb1cfe23578e2f42fe1e8 /src/syntax
parent650c712eabc6f665a0a0cc2a47fb5b90cf715d87 (diff)
Desugar body into last argument 🍩
Diffstat (limited to 'src/syntax')
-rw-r--r--src/syntax/parsing.rs53
-rw-r--r--src/syntax/test.rs24
-rw-r--r--src/syntax/value.rs2
3 files changed, 33 insertions, 46 deletions
diff --git a/src/syntax/parsing.rs b/src/syntax/parsing.rs
index 502f4de1..2980cce2 100644
--- a/src/syntax/parsing.rs
+++ b/src/syntax/parsing.rs
@@ -16,21 +16,10 @@ pub type CallParser = dyn Fn(FuncCall, &ParseState) -> Pass<SyntaxNode>;
/// An invocation of a function.
#[derive(Debug, Clone, PartialEq)]
pub struct FuncCall {
- pub header: FuncHeader,
- pub body: FuncBody,
-}
-
-/// The parsed header of a function (everything in the first set of brackets).
-#[derive(Debug, Clone, PartialEq)]
-pub struct FuncHeader {
pub name: Spanned<Ident>,
pub args: FuncArgs,
}
-/// The body of a function as a raw spanned string containing what's inside of
-/// the brackets.
-pub type FuncBody = Option<Spanned<SyntaxTree>>;
-
/// The positional and keyword arguments passed to a function.
#[derive(Debug, Default, Clone, PartialEq)]
pub struct FuncArgs {
@@ -166,8 +155,8 @@ impl<'s> FuncParser<'s> {
}
fn parse(mut self) -> Pass<SyntaxNode> {
- let (parser, header) = if let Some(header) = self.parse_func_header() {
- let name = header.name.v.as_str();
+ let (parser, mut call) = if let Some(call) = self.parse_func_call() {
+ let name = call.name.v.as_str();
let (parser, deco) = match self.state.scope.get_parser(name) {
// The function exists in the scope.
Some(parser) => (parser, Decoration::ResolvedFunc),
@@ -177,32 +166,34 @@ impl<'s> FuncParser<'s> {
// the content of the function is not totally dropped (on a best
// effort basis).
None => {
- error!(@self.feedback, header.name.span, "unknown function");
+ error!(@self.feedback, call.name.span, "unknown function");
let parser = self.state.scope.get_fallback_parser();
(parser, Decoration::UnresolvedFunc)
}
};
- self.feedback.decorations.push(Spanned::new(deco, header.name.span));
- (parser, header)
+ self.feedback.decorations.push(Spanned::new(deco, call.name.span));
+ (parser, call)
} else {
- // Parse the body with the fallback parser even when the header is
+ // Parse the call with the fallback parser even when the header is
// completely unparsable.
let parser = self.state.scope.get_fallback_parser();
- let header = FuncHeader {
+ let call = FuncCall {
name: Spanned::new(Ident(String::new()), Span::ZERO),
args: FuncArgs::new(),
};
- (parser, header)
+ (parser, call)
};
- let body = self.body.map(|body| body.map(|src| {
- let parsed = parse(src, body.span.start, &self.state);
- self.feedback.extend(parsed.feedback);
- parsed.output
- }));
+ if let Some(body) = self.body {
+ let tree = body.map(|src| {
+ let parsed = parse(src, body.span.start, &self.state);
+ self.feedback.extend(parsed.feedback);
+ Expr::Tree(parsed.output)
+ });
- let call = FuncCall { header, body };
+ call.args.pos.push(tree);
+ }
let parsed = parser(call, self.state);
self.feedback.extend(parsed.feedback);
@@ -210,7 +201,7 @@ impl<'s> FuncParser<'s> {
Pass::new(parsed.output, self.feedback)
}
- fn parse_func_header(&mut self) -> Option<FuncHeader> {
+ fn parse_func_call(&mut self) -> Option<FuncCall> {
let after_bracket = self.pos();
self.skip_white();
@@ -229,7 +220,7 @@ impl<'s> FuncParser<'s> {
None => FuncArgs::new(),
};
- Some(FuncHeader { name, args })
+ Some(FuncCall { name, args })
}
fn parse_func_args(&mut self) -> FuncArgs {
@@ -790,13 +781,13 @@ mod tests {
value: Z($value),
})));)*)?
)?
- SyntaxNode::boxed(DebugNode {
- header: FuncHeader {
+ SyntaxNode::boxed(DebugNode(
+ FuncCall {
name: span_item!($name).map(|s| Ident(s.to_string())),
args,
},
- body: func!(@body $($($body)*)?),
- })
+ func!(@body $($($body)*)?),
+ ))
}};
(@body [$($body:tt)*]) => { Some(span_vec![$($body)*].0) };
(@body) => { None };
diff --git a/src/syntax/test.rs b/src/syntax/test.rs
index 2ea5dde3..97fecebc 100644
--- a/src/syntax/test.rs
+++ b/src/syntax/test.rs
@@ -3,10 +3,10 @@ use std::fmt::Debug;
use crate::func::prelude::*;
use super::decoration::Decoration;
use super::expr::{Expr, Ident, NamedTuple, Object, Pair, Tuple};
-use super::parsing::{FuncArg, FuncArgs, FuncHeader};
+use super::parsing::{FuncArg, FuncArgs};
use super::span::Spanned;
use super::tokens::Token;
-use super::tree::{DynamicNode, SyntaxNode, SyntaxTree};
+use super::tree::{DynamicNode, SyntaxNode};
pub fn check<T>(src: &str, exp: T, found: T, cmp_spans: bool)
where
@@ -58,19 +58,13 @@ macro_rules! span_item {
};
}
-pub fn debug_func(call: FuncCall, _: &ParseState) -> Pass<SyntaxNode> {
- let node = DebugNode {
- header: call.header,
- body: call.body.map(|s| s.v),
- };
- Pass::node(node, Feedback::new())
+pub fn debug_func(mut call: FuncCall, _: &ParseState) -> Pass<SyntaxNode> {
+ let tree = call.args.pos.get::<SyntaxTree>();
+ Pass::node(DebugNode(call, tree), Feedback::new())
}
#[derive(Debug, Clone, PartialEq)]
-pub struct DebugNode {
- pub header: FuncHeader,
- pub body: Option<SyntaxTree>,
-}
+pub struct DebugNode(pub FuncCall, pub Option<SyntaxTree>);
#[async_trait(?Send)]
impl Layout for DebugNode {
@@ -102,12 +96,12 @@ impl SpanlessEq for SyntaxNode {
impl SpanlessEq for DebugNode {
fn spanless_eq(&self, other: &Self) -> bool {
- self.header.spanless_eq(&other.header)
- && self.body.spanless_eq(&other.body)
+ self.0.spanless_eq(&other.0)
+ && self.1.spanless_eq(&other.1)
}
}
-impl SpanlessEq for FuncHeader {
+impl SpanlessEq for FuncCall {
fn spanless_eq(&self, other: &Self) -> bool {
self.name.spanless_eq(&other.name)
&& self.args.spanless_eq(&other.args)
diff --git a/src/syntax/value.rs b/src/syntax/value.rs
index c523ff93..aa5049e0 100644
--- a/src/syntax/value.rs
+++ b/src/syntax/value.rs
@@ -8,6 +8,7 @@ use crate::paper::Paper;
use crate::Feedback;
use super::expr::*;
use super::span::Spanned;
+use super::tree::SyntaxTree;
/// Value types are used to extract values from functions, tuples and
/// objects. They represent the value part of an argument.
@@ -58,6 +59,7 @@ match_value!(String, "string", Expr::Str(s) => s);
match_value!(bool, "bool", Expr::Bool(b) => b);
match_value!(f64, "number", Expr::Number(n) => n);
match_value!(Length, "length", Expr::Length(l) => l);
+match_value!(SyntaxTree, "tree", Expr::Tree(t) => t);
match_value!(Tuple, "tuple", Expr::Tuple(t) => t);
match_value!(Object, "object", Expr::Object(o) => o);
match_value!(ScaleLength, "number or length",