diff options
| author | Laurenz <laurmaedje@gmail.com> | 2020-08-16 22:14:27 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2020-08-16 22:39:21 +0200 |
| commit | 30f16bbf6431ca0c174ca0a1abaa6a13ef50ab06 (patch) | |
| tree | f5a5c0adad15840ebe24b39e77ff467862067c91 /src/library/mod.rs | |
| parent | 9f6137d8a829fe8f34554623495fa620252a0184 (diff) | |
Add Value type and replace dyn-nodes with call-exprs 🏗
- In addition to syntax trees there are now `Value`s, which syntax trees can be evaluated into (e.g. the tree is `5+5` and the value is `10`)
- Parsing is completely pure, function calls are not parsed into nodes, but into simple call expressions, which are resolved later
- Functions aren't dynamic nodes anymore, but simply functions which receive their arguments as a table and the layouting context
- Functions may return any `Value`
- Layouting is powered by functions which return the new `Commands` value, which informs the layouting engine what to do
- When a function returns a non-`Commands` value, the layouter simply dumps the value into the document in monospace
Diffstat (limited to 'src/library/mod.rs')
| -rw-r--r-- | src/library/mod.rs | 62 |
1 files changed, 46 insertions, 16 deletions
diff --git a/src/library/mod.rs b/src/library/mod.rs index ef24d74f..1999ba31 100644 --- a/src/library/mod.rs +++ b/src/library/mod.rs @@ -5,30 +5,60 @@ mod boxed; mod font; mod page; mod spacing; -mod val; pub use align::*; pub use boxed::*; pub use font::*; pub use page::*; pub use spacing::*; -pub use val::*; -use crate::func::prelude::*; -use crate::syntax::scope::Scope; +use std::rc::Rc; -/// Create a scope with all standard library functions. -pub fn _std() -> Scope { - let mut std = Scope::new(Box::new(val)); +use crate::compute::scope::Scope; +use crate::prelude::*; - std.insert("val", Box::new(val)); - std.insert("font", Box::new(font)); - std.insert("page", Box::new(page)); - std.insert("align", Box::new(align)); - std.insert("box", Box::new(boxed)); - std.insert("pagebreak", Box::new(pagebreak)); - std.insert("h", Box::new(h)); - std.insert("v", Box::new(v)); +macro_rules! std { + (fallback: $fallback:expr $(, $name:literal => $func:expr)* $(,)?) => { + /// Create a scope with all standard library functions. + pub fn _std() -> Scope { + let mut std = Scope::new(wrap!(val)); + $(std.insert($name, wrap!($func));)* + std + } + }; +} + +macro_rules! wrap { + ($func:expr) => { + Rc::new(|args, ctx| Box::pin($func(args, ctx))) + }; +} + +std! { + fallback: val, + "align" => align, + "box" => boxed, + "dump" => dump, + "font" => font, + "h" => h, + "page" => page, + "pagebreak" => pagebreak, + "v" => v, + "val" => val, +} + +/// `val`: Layouts its body flatly, ignoring other arguments. +/// +/// This is also the fallback function, which is used when a function name +/// cannot be resolved. +pub async fn val(mut args: TableValue, _: LayoutContext<'_>) -> Pass<Value> { + Pass::commands(match args.take::<SyntaxTree>() { + Some(tree) => vec![LayoutSyntaxTree(tree)], + None => vec![], + }, Feedback::new()) +} - std +/// `dump`: Dumps its arguments. +pub async fn dump(args: TableValue, _: LayoutContext<'_>) -> Pass<Value> { + Pass::okay(Value::Table(args)) } |
