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