Allow more complicated types of bindings in For and use $ for var bindings
This commit is contained in:
parent
1a1dc740e8
commit
062bd8abd7
@ -46,13 +46,19 @@ pub struct IfBlock {
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
|
||||
pub struct ForBlock {
|
||||
pub binding: IStr,
|
||||
pub binding: Binding,
|
||||
pub iterable: Expression,
|
||||
pub blocks: Vec<Block>,
|
||||
pub empty_blocks: Vec<Block>,
|
||||
pub loc: Locator,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
|
||||
pub enum Binding {
|
||||
Variable(IStr),
|
||||
Ignore,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
|
||||
pub struct DefineExpandSlot {
|
||||
pub name: IStr,
|
||||
|
@ -185,8 +185,10 @@ MapLiteral = { "{" ~ commaSeparatedKVPairs ~ "}" }
|
||||
// As in a let binding or for binding.
|
||||
// More options in the future, but for now you just get one identifier and that's it!
|
||||
Binding = {
|
||||
Identifier
|
||||
VarBinding | IgnoreBinding
|
||||
}
|
||||
VarBinding = { "$" ~ Identifier }
|
||||
IgnoreBinding = { "_" }
|
||||
|
||||
LocalisationIdentifier = @{ ASCII_ALPHA ~ (ASCII_ALPHANUMERIC | "_" | "-")+ }
|
||||
ParameterisedLocalisation = { "@" ~ LocalisationIdentifier ~ (!"{" | MapLiteral) }
|
||||
|
@ -1,8 +1,8 @@
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use crate::ast::{
|
||||
Block, ComponentElement, DefineExpandSlot, DefineFragment, Expression, ForBlock, HtmlElement,
|
||||
IfBlock, StringExpr, StringPiece, Template,
|
||||
Binding, Block, ComponentElement, DefineExpandSlot, DefineFragment, Expression, ForBlock,
|
||||
HtmlElement, IfBlock, StringExpr, StringPiece, Template,
|
||||
};
|
||||
use crate::{intern, IStr, Locator};
|
||||
use lazy_static::lazy_static;
|
||||
@ -374,8 +374,20 @@ impl HornbeamParser {
|
||||
}))
|
||||
}
|
||||
|
||||
fn Binding(input: Node) -> PCResult<IStr> {
|
||||
Ok(intern(input.as_str()))
|
||||
fn Binding(input: Node) -> PCResult<Binding> {
|
||||
Ok(match_nodes!(input.into_children();
|
||||
[VarBinding(b)] => b,
|
||||
[IgnoreBinding(b)] => b,
|
||||
))
|
||||
}
|
||||
|
||||
fn VarBinding(input: Node) -> PCResult<Binding> {
|
||||
let str = Self::Identifier(input.into_children().single()?)?;
|
||||
Ok(Binding::Variable(str))
|
||||
}
|
||||
|
||||
fn IgnoreBinding(input: Node) -> PCResult<Binding> {
|
||||
Ok(Binding::Ignore)
|
||||
}
|
||||
|
||||
fn EmptyForBlock(input: Node) -> PCResult<Vec<Block>> {
|
||||
@ -515,8 +527,8 @@ else // peculiar.
|
||||
fn for_blocks() {
|
||||
assert_yaml_snapshot!(parse_template(
|
||||
r#"
|
||||
for x in $xs
|
||||
for y in $ys
|
||||
for $x in $xs
|
||||
for $y in $ys
|
||||
"Woot"
|
||||
empty
|
||||
"no ys"
|
||||
|
@ -1,27 +1,29 @@
|
||||
---
|
||||
source: hornbeam_grammar/src/parser.rs
|
||||
expression: "parse_template(r#\"\nfor x in $xs\n for y in $ys\n \"Woot\"\n empty\n \"no ys\"\nempty\n \"no xs\"\n \"#,\n \"inp\").unwrap()"
|
||||
expression: "parse_template(r#\"\nfor $x in $xs\n for $y in $ys\n \"Woot\"\n empty\n \"no ys\"\nempty\n \"no xs\"\n \"#,\n \"inp\").unwrap()"
|
||||
---
|
||||
blocks:
|
||||
- ForBlock:
|
||||
binding: x
|
||||
iterator:
|
||||
binding:
|
||||
Variable: x
|
||||
iterable:
|
||||
Variable:
|
||||
name: xs
|
||||
loc:
|
||||
filename: inp
|
||||
line: 2
|
||||
column: 10
|
||||
column: 11
|
||||
blocks:
|
||||
- ForBlock:
|
||||
binding: y
|
||||
iterator:
|
||||
binding:
|
||||
Variable: y
|
||||
iterable:
|
||||
Variable:
|
||||
name: ys
|
||||
loc:
|
||||
filename: inp
|
||||
line: 3
|
||||
column: 14
|
||||
column: 15
|
||||
blocks:
|
||||
- Text:
|
||||
pieces:
|
||||
|
@ -3,6 +3,7 @@ use crate::InterpreterError;
|
||||
use async_recursion::async_recursion;
|
||||
use bevy_reflect::{FromReflect, Reflect, ReflectRef};
|
||||
use fluent_templates::lazy_static::lazy_static;
|
||||
use hornbeam_grammar::ast::Binding;
|
||||
use hornbeam_grammar::Locator;
|
||||
use hornbeam_ir::ir::{Expression, Step, StepDef, StringPiece};
|
||||
use itertools::Itertools;
|
||||
@ -195,12 +196,26 @@ impl<'a, O: OutputSystem + Send, LS: LocalisationSystem + Sync + Send> Interpret
|
||||
self.run_steps(scope_idx, empty_steps).await?;
|
||||
} else {
|
||||
for val in list {
|
||||
// TODO duplicated code
|
||||
match binding {
|
||||
Binding::Variable(var) => {
|
||||
self.scopes[scope_idx]
|
||||
.variables
|
||||
.insert(String::from(binding as &str), val);
|
||||
.insert(String::from(var as &str), val);
|
||||
}
|
||||
Binding::Ignore => {}
|
||||
}
|
||||
|
||||
self.run_steps(scope_idx, body_steps).await?;
|
||||
}
|
||||
self.scopes[scope_idx].variables.remove(binding as &str);
|
||||
|
||||
// TODO duplicated code
|
||||
match binding {
|
||||
Binding::Variable(var) => {
|
||||
self.scopes[scope_idx].variables.remove(var as &str);
|
||||
}
|
||||
Binding::Ignore => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
Value::Reflective(reflective) => match reflective.reflect_ref() {
|
||||
@ -212,13 +227,26 @@ impl<'a, O: OutputSystem + Send, LS: LocalisationSystem + Sync + Send> Interpret
|
||||
// TODO(performance) I'd like to remove this clone!
|
||||
// Can possibly do so with a Yoke or something...
|
||||
let val = list.get(idx).expect("checked iter").clone_value();
|
||||
// TODO duplicated code
|
||||
match binding {
|
||||
Binding::Variable(var) => {
|
||||
self.scopes[scope_idx].variables.insert(
|
||||
String::from(binding as &str),
|
||||
String::from(var as &str),
|
||||
Value::from_reflect(val),
|
||||
);
|
||||
}
|
||||
Binding::Ignore => {}
|
||||
}
|
||||
self.run_steps(scope_idx, body_steps).await?;
|
||||
}
|
||||
self.scopes[scope_idx].variables.remove(binding as &str);
|
||||
|
||||
// TODO duplicated code
|
||||
match binding {
|
||||
Binding::Variable(var) => {
|
||||
self.scopes[scope_idx].variables.remove(var as &str);
|
||||
}
|
||||
Binding::Ignore => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
other => {
|
||||
|
@ -1,3 +1,4 @@
|
||||
use hornbeam_grammar::ast::Binding;
|
||||
pub use hornbeam_grammar::ast::{Expression, StringPiece};
|
||||
use hornbeam_grammar::{IStr, Locator};
|
||||
use serde::Serialize;
|
||||
@ -34,8 +35,7 @@ pub enum StepDef {
|
||||
},
|
||||
For {
|
||||
iterable: Expression,
|
||||
// TODO!
|
||||
binding: IStr,
|
||||
binding: Binding,
|
||||
body_steps: Vec<Step>,
|
||||
empty_steps: Vec<Step>,
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user