summaryrefslogtreecommitdiff
path: root/src/library/mod.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2020-08-16 22:14:27 +0200
committerLaurenz <laurmaedje@gmail.com>2020-08-16 22:39:21 +0200
commit30f16bbf6431ca0c174ca0a1abaa6a13ef50ab06 (patch)
treef5a5c0adad15840ebe24b39e77ff467862067c91 /src/library/mod.rs
parent9f6137d8a829fe8f34554623495fa620252a0184 (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.rs62
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))
}