Skip to content

Commit 70c01ac

Browse files
committed
runtime and builder can now register global values
1 parent 476b639 commit 70c01ac

File tree

10 files changed

+84
-49
lines changed

10 files changed

+84
-49
lines changed

CHANGES.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
* 0.2.12
2+
* Clamping is now true by default on overflow
3+
* Globals can now be registered with the runtime
14
* 0.2.11
25
* FEATURE: ranges
36
* `padding` function

anathema-default-widgets/src/testing.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,15 +159,16 @@ impl TestRunner {
159159
let main = doc.add_component("main", src.to_template()).unwrap();
160160
component_registry.add_component(main, (), TestState::new());
161161

162-
let (blueprint, globals) = doc.compile().unwrap();
162+
let mut variables = Default::default();
163+
let blueprint = doc.compile(&mut variables).unwrap();
163164

164165
Self {
165166
factory,
166167
backend: TestBackend::new(size),
167168
states,
168169
component_registry,
169170
blueprint,
170-
variables: globals,
171+
variables,
171172
components: Components::new(),
172173
function_table: FunctionTable::new(),
173174
}

anathema-runtime/src/builder.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::sync::atomic::Ordering;
33
use anathema_backend::Backend;
44
use anathema_default_widgets::register_default_widgets;
55
use anathema_geometry::Size;
6-
use anathema_templates::{Document, ToSourceKind};
6+
use anathema_templates::{Document, Expression, ToSourceKind, Variables};
77
use anathema_value_resolver::{Function, FunctionTable};
88
use anathema_widgets::components::deferred::DeferredComponents;
99
use anathema_widgets::components::events::Event;
@@ -28,6 +28,7 @@ pub struct Builder<G> {
2828
global_event_handler: G,
2929
hot_reload: bool,
3030
function_table: FunctionTable,
31+
variables: Variables,
3132
}
3233

3334
impl<G: GlobalEventHandler> Builder<G> {
@@ -54,6 +55,7 @@ impl<G: GlobalEventHandler> Builder<G> {
5455
global_event_handler,
5556
hot_reload: true,
5657
function_table: FunctionTable::new(),
58+
variables: Variables::new(),
5759
}
5860
}
5961

@@ -164,9 +166,15 @@ impl<G: GlobalEventHandler> Builder<G> {
164166
global_event_handler,
165167
hot_reload: self.hot_reload,
166168
function_table: self.function_table,
169+
variables: Variables::new(),
167170
}
168171
}
169172

173+
pub fn register_global(&mut self, key: impl Into<String>, value: impl Into<Expression>) -> Result<()> {
174+
self.variables.define_global(key, value).map_err(|e| e.to_error(None))?;
175+
Ok(())
176+
}
177+
170178
pub fn finish<F, B>(mut self, backend: &mut B, mut f: F) -> Result<()>
171179
where
172180
F: FnMut(&mut Runtime<G>, &mut B) -> Result<()>,
@@ -180,8 +188,8 @@ impl<G: GlobalEventHandler> Builder<G> {
180188
server
181189
};
182190

183-
let (blueprint, globals) = loop {
184-
match self.document.compile() {
191+
let blueprint = loop {
192+
match self.document.compile(&mut self.variables) {
185193
Ok(val) => break val,
186194
// This can only show template errors.
187195
// Widget errors doesn't become available until after the first tick.
@@ -199,7 +207,7 @@ impl<G: GlobalEventHandler> Builder<G> {
199207

200208
let mut inst = Runtime::new(
201209
blueprint,
202-
globals,
210+
self.variables,
203211
self.component_registry,
204212
self.document,
205213
self.factory,

anathema-runtime/src/runtime/mod.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use anathema_geometry::Size;
77
use anathema_state::{Changes, StateId, States, clear_all_changes, clear_all_subs, drain_changes};
88
use anathema_store::tree::root_node;
99
use anathema_templates::blueprints::Blueprint;
10-
use anathema_templates::{Document, Variables};
10+
use anathema_templates::{Document, Expression, Variables};
1111
use anathema_value_resolver::{AttributeStorage, FunctionTable, Scope};
1212
use anathema_widgets::components::deferred::{CommandKind, DeferredComponents};
1313
use anathema_widgets::components::events::{Event, EventType};
@@ -65,6 +65,11 @@ impl Runtime<()> {
6565
Builder::new(doc, backend.size(), ())
6666
}
6767

68+
pub fn register_global(&mut self, key: impl Into<String>, value: impl Into<Expression>) -> Result<()> {
69+
self.variables.define_global(key, value).map_err(|e| e.to_error(None))?;
70+
Ok(())
71+
}
72+
6873
/// Create a runtime builder using an existing emitter
6974
pub fn with_receiver<B: Backend>(
7075
message_receiver: MessageReceiver,
@@ -267,9 +272,8 @@ impl<G: GlobalEventHandler> Runtime<G> {
267272
// Reload templates
268273
self.document.reload_templates()?;
269274

270-
let (blueprint, variables) = self.document.compile()?;
275+
let blueprint = self.document.compile(&mut self.variables)?;
271276
self.blueprint = blueprint;
272-
self.variables = variables;
273277

274278
Ok(())
275279
}

anathema-templates/src/document.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ use crate::{ComponentBlueprintId, Lexer, Variables};
2121
pub struct Document {
2222
template: TemplateSource,
2323
pub strings: Strings,
24-
globals: Variables,
2524
components: ComponentTemplates,
2625
pub hot_reload: bool,
2726
}
@@ -32,7 +31,6 @@ impl Document {
3231
Self {
3332
template,
3433
strings: Strings::new(),
35-
globals: Variables::default(),
3634
components: ComponentTemplates::new(),
3735
hot_reload: true,
3836
}
@@ -58,9 +56,7 @@ impl Document {
5856
Ok(id)
5957
}
6058

61-
pub fn compile(&mut self) -> Result<(Blueprint, Variables)> {
62-
self.globals = Variables::default();
63-
59+
pub fn compile(&mut self, globals: &mut Variables) -> Result<Blueprint> {
6460
let tokens = Lexer::new(&self.template, &mut self.strings).collect::<Result<Vec<_>>>()?;
6561
let tokens = Tokens::new(tokens, self.template.len());
6662
let parser = Parser::new(tokens, &mut self.strings, &self.template, &mut self.components);
@@ -69,7 +65,7 @@ impl Document {
6965

7066
let mut context = Context {
7167
template: &self.template,
72-
variables: &mut self.globals,
68+
variables: globals,
7369
strings: &mut self.strings,
7470
components: &mut self.components,
7571
slots: SmallMap::empty(),
@@ -79,7 +75,7 @@ impl Document {
7975
let mut blueprints = Scope::new(statements).eval(&mut context)?;
8076
match blueprints.is_empty() {
8177
true => Err(Error::no_template(ErrorKind::EmptyTemplate)),
82-
false => Ok((blueprints.remove(0), self.globals.take())),
78+
false => Ok(blueprints.remove(0)),
8379
}
8480
}
8581

anathema-templates/src/error/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ pub enum ErrorKind {
5858
}
5959

6060
impl ErrorKind {
61-
pub(crate) fn to_error(self, template: Option<PathBuf>) -> Error {
61+
pub fn to_error(self, template: Option<PathBuf>) -> Error {
6262
Error::new(template, self)
6363
}
6464
}

anathema-templates/src/expressions/mod.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,33 @@ impl<T: Into<Primitive>> From<T> for Expression {
9797
}
9898
}
9999

100+
impl<T: Into<Expression>> From<HashMap<String, T>> for Expression {
101+
fn from(map: HashMap<String, T>) -> Self {
102+
let map = map.into_iter().map(|(key, val)| (key, val.into())).collect();
103+
Self::Map(map)
104+
}
105+
}
106+
107+
impl<T: Into<Expression>> From<Vec<T>> for Expression {
108+
fn from(list: Vec<T>) -> Self {
109+
let inner = list.into_iter().map(|i| i.into()).collect();
110+
Self::List(inner)
111+
}
112+
}
113+
114+
impl<const N: usize, T: Into<Expression>> From<[T; N]> for Expression {
115+
fn from(list: [T; N]) -> Self {
116+
let inner = list.map(|i| i.into());
117+
Self::List(inner.to_vec())
118+
}
119+
}
120+
121+
impl From<String> for Expression {
122+
fn from(value: String) -> Self {
123+
Self::Str(value)
124+
}
125+
}
126+
100127
impl From<&str> for Expression {
101128
fn from(value: &str) -> Self {
102129
Self::Str(value.into())

anathema-templates/src/statements/eval.rs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -261,12 +261,12 @@ impl Scope {
261261
mod test {
262262
use super::*;
263263
use crate::document::Document;
264-
use crate::{ToSourceKind, single};
264+
use crate::{ToSourceKind, Variables, single};
265265

266266
#[test]
267267
fn eval_node() {
268268
let mut doc = Document::new("node");
269-
let (bp, _) = doc.compile().unwrap();
269+
let bp = doc.compile(&mut Variables::new()).unwrap();
270270
assert_eq!(bp, single!("node"));
271271
}
272272

@@ -277,7 +277,7 @@ mod test {
277277
b
278278
";
279279
let mut doc = Document::new(src);
280-
let (blueprint, _) = doc.compile().unwrap();
280+
let blueprint = doc.compile(&mut Variables::new()).unwrap();
281281
assert_eq!(blueprint, single!(children @ "a", vec![single!("b")]));
282282
}
283283

@@ -289,7 +289,7 @@ mod test {
289289
";
290290

291291
let mut doc = Document::new(src);
292-
let (blueprint, _) = doc.compile().unwrap();
292+
let blueprint = doc.compile(&mut Variables::new()).unwrap();
293293
assert!(matches!(blueprint, Blueprint::Single(Single { value: Some(_), .. })));
294294
}
295295

@@ -298,7 +298,7 @@ mod test {
298298
let src = "let state = 1";
299299

300300
let mut doc = Document::new(src);
301-
let response = doc.compile();
301+
let response = doc.compile(&mut Variables::new());
302302
assert_eq!(
303303
response.err().unwrap().to_string(),
304304
"invalid statement: state is a reserved identifier"
@@ -313,7 +313,7 @@ mod test {
313313
";
314314

315315
let mut doc = Document::new(src);
316-
let response = doc.compile();
316+
let response = doc.compile(&mut Variables::new());
317317
assert_eq!(
318318
response.err().unwrap().to_string(),
319319
"invalid statement: state is a reserved identifier"
@@ -327,7 +327,7 @@ mod test {
327327
node
328328
";
329329
let mut doc = Document::new(src);
330-
let (blueprint, _) = doc.compile().unwrap();
330+
let blueprint = doc.compile(&mut Variables::new()).unwrap();
331331
assert!(matches!(blueprint, Blueprint::For(For { .. })));
332332
}
333333

@@ -341,7 +341,7 @@ mod test {
341341
";
342342

343343
let mut doc = Document::new(src);
344-
let (blueprint, _) = doc.compile().unwrap();
344+
let blueprint = doc.compile(&mut Variables::new()).unwrap();
345345
let Blueprint::ControlFlow(controlflow) = blueprint else { panic!() };
346346
assert!(matches!(controlflow.elses[0], Else { .. }));
347347
assert!(!controlflow.elses.is_empty());
@@ -356,7 +356,7 @@ mod test {
356356
";
357357

358358
let mut doc = Document::new(src);
359-
let (blueprint, _) = doc.compile().unwrap();
359+
let blueprint = doc.compile(&mut Variables::new()).unwrap();
360360
let Blueprint::ControlFlow(controlflow) = blueprint else { panic!() };
361361
assert!(matches!(controlflow.elses[0], Else { .. }));
362362
assert!(!controlflow.elses.is_empty());
@@ -374,7 +374,7 @@ mod test {
374374
";
375375

376376
let mut doc = Document::new(src);
377-
let (blueprint, _) = doc.compile().unwrap();
377+
let blueprint = doc.compile(&mut Variables::new()).unwrap();
378378
let Blueprint::ControlFlow(controlflow) = blueprint else { panic!() };
379379
assert!(matches!(controlflow.elses[0], Else { .. }));
380380
assert!(!controlflow.elses.is_empty());
@@ -387,7 +387,7 @@ mod test {
387387

388388
let mut doc = Document::new(src);
389389
doc.add_component("comp", comp_src.to_template()).unwrap();
390-
let (blueprint, _) = doc.compile().unwrap();
390+
let blueprint = doc.compile(&mut Variables::new()).unwrap();
391391
assert!(matches!(blueprint, Blueprint::Component(Component { .. })));
392392
}
393393

@@ -412,7 +412,7 @@ mod test {
412412

413413
let mut doc = Document::new(src);
414414
doc.add_component("comp", comp_src.to_template()).unwrap();
415-
let (blueprint, _) = doc.compile().unwrap();
415+
let blueprint = doc.compile(&mut Variables::new()).unwrap();
416416
assert!(matches!(blueprint, Blueprint::Component(Component { .. })));
417417
}
418418

@@ -426,7 +426,7 @@ mod test {
426426

427427
let mut doc = Document::new(src);
428428
doc.add_component("comp", "node a".to_template()).unwrap();
429-
let _ = doc.compile().unwrap();
429+
let _ = doc.compile(&mut Variables::new()).unwrap();
430430
}
431431

432432
#[test]
@@ -437,7 +437,7 @@ mod test {
437437

438438
let mut doc = Document::new(src);
439439
doc.add_component("comp", "node a".to_template()).unwrap();
440-
let _ = doc.compile().unwrap();
440+
let _ = doc.compile(&mut Variables::new()).unwrap();
441441
}
442442

443443
#[test]
@@ -449,7 +449,7 @@ mod test {
449449

450450
let mut doc = Document::new(src);
451451
doc.add_component("comp", "node a".to_template()).unwrap();
452-
let (blueprint, _) = doc.compile().unwrap();
452+
let blueprint = doc.compile(&mut Variables::new()).unwrap();
453453
assert!(matches!(blueprint, Blueprint::With(With { .. })));
454454
}
455455
}

anathema-templates/src/variables.rs

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::error::ErrorKind;
77
use crate::expressions::Expression;
88

99
#[derive(Debug, Default, Clone)]
10-
pub(crate) struct Globals(HashMap<String, Expression>);
10+
pub struct Globals(HashMap<String, Expression>);
1111

1212
impl Globals {
1313
pub fn empty() -> Self {
@@ -22,7 +22,7 @@ impl Globals {
2222
self.0.get(ident)
2323
}
2424

25-
pub(crate) fn set(&mut self, ident: String, value: Expression) {
25+
pub fn set(&mut self, ident: String, value: Expression) {
2626
if self.0.contains_key(&ident) {
2727
return;
2828
}
@@ -229,6 +229,12 @@ pub struct Variables {
229229

230230
impl Default for Variables {
231231
fn default() -> Self {
232+
Self::new()
233+
}
234+
}
235+
236+
impl Variables {
237+
pub fn new() -> Self {
232238
let root = RootScope::default();
233239
Self {
234240
globals: Globals::empty(),
@@ -239,16 +245,6 @@ impl Default for Variables {
239245
declarations: Declarations::new(),
240246
}
241247
}
242-
}
243-
244-
impl Variables {
245-
pub fn new() -> Self {
246-
Self::default()
247-
}
248-
249-
pub fn take(&mut self) -> Self {
250-
std::mem::take(self)
251-
}
252248

253249
fn declare_at(&mut self, ident: impl Into<String>, var_id: VarId, id: ScopeId) -> VarId {
254250
let ident = ident.into();
@@ -262,8 +258,7 @@ impl Variables {
262258
return Err(ErrorKind::GlobalAlreadyAssigned(ident));
263259
}
264260

265-
let value = value.into();
266-
self.globals.set(ident, value);
261+
self.globals.set(ident, value.into());
267262
Ok(())
268263
}
269264

0 commit comments

Comments
 (0)