typst_library/foundations/
mod.rs1pub mod calc;
4pub mod ops;
5pub mod repr;
6pub mod sys;
7
8mod args;
9mod array;
10mod auto;
11mod bool;
12mod bytes;
13mod cast;
14mod content;
15mod context;
16mod datetime;
17mod decimal;
18mod dict;
19mod duration;
20mod fields;
21mod float;
22mod func;
23mod int;
24mod label;
25mod module;
26mod none;
27mod path;
28#[path = "plugin.rs"]
29mod plugin_;
30mod scope;
31mod selector;
32mod str;
33mod styles;
34mod symbol;
35#[path = "target.rs"]
36mod target_;
37mod ty;
38mod value;
39mod version;
40
41pub use self::args::*;
42pub use self::array::*;
43pub use self::auto::*;
44pub use self::bytes::*;
45pub use self::cast::*;
46pub use self::content::*;
47pub use self::context::*;
48pub use self::datetime::*;
49pub use self::decimal::*;
50pub use self::dict::*;
51pub use self::duration::*;
52pub use self::fields::*;
53pub use self::float::*;
54pub use self::func::*;
55pub use self::int::*;
56pub use self::label::*;
57pub use self::module::*;
58pub use self::none::*;
59pub use self::path::*;
60pub use self::plugin_::*;
61pub use self::repr::Repr;
62pub use self::scope::*;
63pub use self::selector::*;
64pub use self::str::*;
65pub use self::styles::*;
66pub use self::symbol::*;
67pub use self::target_::*;
68pub use self::ty::*;
69pub use self::value::*;
70pub use self::version::*;
71pub use typst_macros::{scope, ty};
72
73#[rustfmt::skip]
74#[doc(hidden)]
75pub use {
76 ecow::{eco_format, eco_vec},
77 indexmap::IndexMap,
78 smallvec::SmallVec,
79};
80
81use comemo::{Track, TrackedMut};
82use ecow::EcoString;
83use typst_syntax::{RootedPath, Spanned, SyntaxMode};
84
85use crate::diag::{SourceResult, StrResult, bail};
86use crate::engine::Engine;
87use crate::introspection::EmptyIntrospector;
88use crate::routines::SpanMode;
89
90pub(super) fn define(global: &mut Scope, inputs: Dict) {
92 global.start_category(crate::Category::Foundations);
93 global.define_type::<bool>();
94 global.define_type::<i64>();
95 global.define_type::<f64>();
96 global.define_type::<Str>();
97 global.define_type::<Label>();
98 global.define_type::<Bytes>();
99 global.define_type::<Content>();
100 global.define_type::<Array>();
101 global.define_type::<Dict>();
102 global.define_type::<Func>();
103 global.define_type::<Args>();
104 global.define_type::<Type>();
105 global.define_type::<Module>();
106 global.define_type::<Regex>();
107 global.define_type::<Selector>();
108 global.define_type::<Datetime>();
109 global.define_type::<Decimal>();
110 global.define_type::<Symbol>();
111 global.define_type::<Duration>();
112 global.define_type::<Version>();
113 global.define_type::<RootedPath>();
114 global.define_func::<repr::repr>();
115 global.define_func::<panic>();
116 global.define_func::<assert>();
117 global.define_func::<eval>();
118 global.define_func::<plugin>();
119 global.define_func::<target>();
120 global.define("calc", calc::module());
121 global.define("sys", sys::module(inputs));
122 global.reset_category();
123}
124
125#[func(keywords = ["error"])]
136pub fn panic(
137 #[variadic]
139 values: Vec<Value>,
140) -> StrResult<Never> {
141 let mut msg = EcoString::from("panicked");
142 if !values.is_empty() {
143 msg.push_str(" with: ");
144 for (i, value) in values.iter().enumerate() {
145 if i > 0 {
146 msg.push_str(", ");
147 }
148 match value {
149 Value::Str(s) => msg.push_str(s),
150 _ => msg.push_str(&value.repr()),
151 }
152 }
153 }
154 Err(msg)
155}
156
157#[func(scope)]
170pub fn assert(
171 condition: bool,
173 #[named]
175 message: Option<EcoString>,
176) -> StrResult<NoneValue> {
177 if !condition {
178 if let Some(message) = message {
179 bail!("assertion failed: {message}");
180 } else {
181 bail!("assertion failed");
182 }
183 }
184 Ok(NoneValue)
185}
186
187#[scope]
188impl assert {
189 #[func(title = "Assert Equal")]
198 pub fn eq(
199 left: Value,
201 right: Value,
203 #[named]
206 message: Option<EcoString>,
207 ) -> StrResult<NoneValue> {
208 if left != right {
209 if let Some(message) = message {
210 bail!("equality assertion failed: {message}");
211 } else {
212 bail!(
213 "equality assertion failed: value {} was not equal to {}",
214 left.repr(),
215 right.repr(),
216 );
217 }
218 }
219 Ok(NoneValue)
220 }
221
222 #[func(title = "Assert Not Equal")]
231 pub fn ne(
232 left: Value,
234 right: Value,
236 #[named]
239 message: Option<EcoString>,
240 ) -> StrResult<NoneValue> {
241 if left == right {
242 if let Some(message) = message {
243 bail!("inequality assertion failed: {message}");
244 } else {
245 bail!(
246 "inequality assertion failed: value {} was equal to {}",
247 left.repr(),
248 right.repr(),
249 );
250 }
251 }
252 Ok(NoneValue)
253 }
254}
255
256#[func(title = "Evaluate")]
267pub fn eval(
268 engine: &mut Engine,
269 source: Spanned<String>,
271 #[named]
279 #[default(SyntaxMode::Code)]
280 mode: SyntaxMode,
281 #[named]
295 #[default]
296 scope: Dict,
297) -> SourceResult<Value> {
298 let Spanned { v: text, span } = source;
299 let dict = scope;
300 let mut scope = Scope::new();
301 for (key, value) in dict {
302 scope.bind(key.into(), Binding::new(value, span));
303 }
304
305 (engine.library.routines.eval_string)(
306 engine.world,
307 engine.library,
308 TrackedMut::reborrow_mut(&mut engine.sink),
309 EmptyIntrospector.track(),
316 Context::none().track(),
317 &text,
318 SpanMode::Uniform(span),
319 mode,
320 scope,
321 )
322}