Insert Locators into the interesting AST nodes
This commit is contained in:
parent
67545f9e8e
commit
f54f2093de
@ -1,4 +1,4 @@
|
|||||||
use crate::IStr;
|
use crate::{IStr, Locator};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
@ -24,6 +24,7 @@ pub struct HtmlElement {
|
|||||||
pub classes: Vec<IStr>,
|
pub classes: Vec<IStr>,
|
||||||
pub dom_id: Option<IStr>,
|
pub dom_id: Option<IStr>,
|
||||||
pub attributes: BTreeMap<IStr, Expression>,
|
pub attributes: BTreeMap<IStr, Expression>,
|
||||||
|
pub loc: Locator,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
|
||||||
@ -31,6 +32,7 @@ pub struct ComponentElement {
|
|||||||
pub name: IStr,
|
pub name: IStr,
|
||||||
pub slots: BTreeMap<IStr, Vec<Block>>,
|
pub slots: BTreeMap<IStr, Vec<Block>>,
|
||||||
pub attributes: BTreeMap<IStr, Expression>,
|
pub attributes: BTreeMap<IStr, Expression>,
|
||||||
|
pub loc: Locator,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
|
||||||
@ -38,18 +40,21 @@ pub struct IfBlock {
|
|||||||
pub condition: Expression,
|
pub condition: Expression,
|
||||||
pub blocks: Vec<Block>,
|
pub blocks: Vec<Block>,
|
||||||
pub else_blocks: Vec<Block>,
|
pub else_blocks: Vec<Block>,
|
||||||
|
pub loc: Locator,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
|
||||||
pub struct DefineExpandSlot {
|
pub struct DefineExpandSlot {
|
||||||
pub name: IStr,
|
pub name: IStr,
|
||||||
pub optional: bool,
|
pub optional: bool,
|
||||||
|
pub loc: Locator,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
|
||||||
pub struct DefineFragment {
|
pub struct DefineFragment {
|
||||||
pub name: IStr,
|
pub name: IStr,
|
||||||
pub blocks: Vec<Block>,
|
pub blocks: Vec<Block>,
|
||||||
|
pub loc: Locator,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
|
||||||
@ -128,19 +133,23 @@ pub enum Expression {
|
|||||||
FieldLookup {
|
FieldLookup {
|
||||||
obj: Box<Expression>,
|
obj: Box<Expression>,
|
||||||
ident: IStr,
|
ident: IStr,
|
||||||
|
loc: Locator,
|
||||||
},
|
},
|
||||||
MethodCall {
|
MethodCall {
|
||||||
obj: Box<Expression>,
|
obj: Box<Expression>,
|
||||||
ident: IStr,
|
ident: IStr,
|
||||||
args: Vec<Expression>,
|
args: Vec<Expression>,
|
||||||
|
loc: Locator,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Other Primaries
|
// Other Primaries
|
||||||
Variable {
|
Variable {
|
||||||
name: IStr,
|
name: IStr,
|
||||||
|
loc: Locator,
|
||||||
},
|
},
|
||||||
FunctionCall {
|
FunctionCall {
|
||||||
name: IStr,
|
name: IStr,
|
||||||
args: Vec<Expression>,
|
args: Vec<Expression>,
|
||||||
|
loc: Locator,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
pub mod ast;
|
pub mod ast;
|
||||||
mod parser;
|
mod parser;
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
use arc_interner::ArcIntern;
|
use arc_interner::ArcIntern;
|
||||||
pub use parser::parse_template;
|
pub use parser::parse_template;
|
||||||
|
use pest::Span;
|
||||||
|
|
||||||
use parser::Rule;
|
use parser::Rule;
|
||||||
pub type ParseError = pest::error::Error<Rule>;
|
pub type ParseError = pest::error::Error<Rule>;
|
||||||
@ -12,3 +14,21 @@ pub type IStr = ArcIntern<String>;
|
|||||||
pub fn intern(s: impl Into<String>) -> ArcIntern<String> {
|
pub fn intern(s: impl Into<String>) -> ArcIntern<String> {
|
||||||
ArcIntern::new(s.into())
|
ArcIntern::new(s.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Serialize)]
|
||||||
|
pub struct Locator {
|
||||||
|
pub filename: IStr,
|
||||||
|
pub line: u16,
|
||||||
|
pub column: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Locator {
|
||||||
|
pub(crate) fn from_span(span: Span, file: IStr) -> Locator {
|
||||||
|
let (line, col) = span.start_pos().line_col();
|
||||||
|
Locator {
|
||||||
|
filename: file,
|
||||||
|
line: line.min(u16::MAX as usize) as u16,
|
||||||
|
column: col.min(u16::MAX as usize) as u16,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -4,7 +4,7 @@ use crate::ast::{
|
|||||||
Block, ComponentElement, DefineExpandSlot, DefineFragment, Expression, HtmlElement, IfBlock,
|
Block, ComponentElement, DefineExpandSlot, DefineFragment, Expression, HtmlElement, IfBlock,
|
||||||
StringExpr, StringPiece, Template,
|
StringExpr, StringPiece, Template,
|
||||||
};
|
};
|
||||||
use crate::{intern, IStr};
|
use crate::{intern, IStr, Locator};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use pest::error::ErrorVariant;
|
use pest::error::ErrorVariant;
|
||||||
use pest::pratt_parser::{Assoc, Op, PrattParser};
|
use pest::pratt_parser::{Assoc, Op, PrattParser};
|
||||||
@ -15,12 +15,21 @@ use std::fmt::Debug;
|
|||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
|
||||||
type PCResult<T> = Result<T, PCError<Rule>>;
|
type PCResult<T> = Result<T, PCError<Rule>>;
|
||||||
type Node<'i> = pest_consume::Node<'i, Rule, ()>;
|
type Node<'i> = pest_consume::Node<'i, Rule, ParserUserData>;
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
#[grammar = "hornbeam.pest"]
|
#[grammar = "hornbeam.pest"]
|
||||||
struct HornbeamParser;
|
struct HornbeamParser;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
struct ParserUserData {
|
||||||
|
pub(crate) file: IStr,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn nodeloc(node: &Node) -> Locator {
|
||||||
|
Locator::from_span(node.as_span(), node.user_data().file.clone())
|
||||||
|
}
|
||||||
|
|
||||||
fn error<R: Copy + Debug + Hash + Ord>(msg: &str, span: Span) -> PCError<R> {
|
fn error<R: Copy + Debug + Hash + Ord>(msg: &str, span: Span) -> PCError<R> {
|
||||||
PCError::new_from_span(
|
PCError::new_from_span(
|
||||||
ErrorVariant::CustomError {
|
ErrorVariant::CustomError {
|
||||||
@ -51,7 +60,8 @@ impl HornbeamParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn Element(input: Node) -> PCResult<Block> {
|
fn Element(input: Node) -> PCResult<Block> {
|
||||||
let loc = input.as_span();
|
let span = input.as_span();
|
||||||
|
let loc = nodeloc(&input);
|
||||||
let mut children = input.into_children();
|
let mut children = input.into_children();
|
||||||
|
|
||||||
let name = HornbeamParser::ElementName(children.next().unwrap())?;
|
let name = HornbeamParser::ElementName(children.next().unwrap())?;
|
||||||
@ -86,7 +96,7 @@ impl HornbeamParser {
|
|||||||
|
|
||||||
Ok(if name.chars().next().unwrap().is_ascii_lowercase() {
|
Ok(if name.chars().next().unwrap().is_ascii_lowercase() {
|
||||||
if !supply_slots.is_empty() {
|
if !supply_slots.is_empty() {
|
||||||
return Err(error("You can't supply slots to HTML elements.", loc));
|
return Err(error("You can't supply slots to HTML elements.", span));
|
||||||
}
|
}
|
||||||
|
|
||||||
Block::HtmlElement(HtmlElement {
|
Block::HtmlElement(HtmlElement {
|
||||||
@ -95,6 +105,7 @@ impl HornbeamParser {
|
|||||||
classes,
|
classes,
|
||||||
dom_id,
|
dom_id,
|
||||||
attributes,
|
attributes,
|
||||||
|
loc,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
if !supply_slots.is_empty() {
|
if !supply_slots.is_empty() {
|
||||||
@ -106,6 +117,7 @@ impl HornbeamParser {
|
|||||||
name,
|
name,
|
||||||
slots,
|
slots,
|
||||||
attributes,
|
attributes,
|
||||||
|
loc,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
let mut slots = BTreeMap::new();
|
let mut slots = BTreeMap::new();
|
||||||
@ -114,22 +126,25 @@ impl HornbeamParser {
|
|||||||
name,
|
name,
|
||||||
slots,
|
slots,
|
||||||
attributes,
|
attributes,
|
||||||
|
loc,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn DefineFragment(input: Node) -> PCResult<Block> {
|
fn DefineFragment(input: Node) -> PCResult<Block> {
|
||||||
|
let loc = nodeloc(&input);
|
||||||
Ok(match_nodes!(input.into_children();
|
Ok(match_nodes!(input.into_children();
|
||||||
[Identifier(name), blocks..] => {
|
[Identifier(name), blocks..] => {
|
||||||
Block::DefineFragment(DefineFragment {
|
Block::DefineFragment(DefineFragment {
|
||||||
name, blocks: HornbeamParser::helper_blocks(blocks)?
|
name, blocks: HornbeamParser::helper_blocks(blocks)?, loc
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn DefineExpandSlot(input: Node) -> PCResult<Block> {
|
fn DefineExpandSlot(input: Node) -> PCResult<Block> {
|
||||||
|
let loc = nodeloc(&input);
|
||||||
let (optional, name) = match_nodes!(input.into_children();
|
let (optional, name) = match_nodes!(input.into_children();
|
||||||
[SlotOptional(_), Identifier(name)] => {
|
[SlotOptional(_), Identifier(name)] => {
|
||||||
(true, name)
|
(true, name)
|
||||||
@ -138,7 +153,11 @@ impl HornbeamParser {
|
|||||||
(false, name)
|
(false, name)
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
Ok(Block::DefineExpandSlot(DefineExpandSlot { name, optional }))
|
Ok(Block::DefineExpandSlot(DefineExpandSlot {
|
||||||
|
name,
|
||||||
|
optional,
|
||||||
|
loc,
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn SlotOptional(_input: Node) -> PCResult<()> {
|
fn SlotOptional(_input: Node) -> PCResult<()> {
|
||||||
@ -231,19 +250,23 @@ impl HornbeamParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn Variable(input: Node) -> PCResult<Expression> {
|
fn Variable(input: Node) -> PCResult<Expression> {
|
||||||
|
let loc = nodeloc(&input);
|
||||||
let name = intern(input.into_children().single()?.as_str());
|
let name = intern(input.into_children().single()?.as_str());
|
||||||
Ok(Expression::Variable { name })
|
Ok(Expression::Variable { name, loc })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn Expr(input: Node) -> PCResult<Expression> {
|
fn Expr(input: Node) -> PCResult<Expression> {
|
||||||
PRATT_PARSER
|
let ud = input.user_data().clone();
|
||||||
.map_primary(|primary| Ok(match primary.as_rule() {
|
let result = PRATT_PARSER
|
||||||
Rule::IntLiteral => Expression::IntLiteral { val: primary.as_str().parse().map_err(|e| error(&format!("can't parse int: {e:?}"), primary.as_span()))? },
|
.map_primary(|primary| {
|
||||||
Rule::String => Expression::StringExpr(HornbeamParser::String(Node::new(primary))?),
|
let node = Node::new_with_user_data(primary, ud.clone());
|
||||||
Rule::Variable => HornbeamParser::Variable(Node::new(primary))?,
|
Ok(match node.as_rule() {
|
||||||
Rule::FunctionCall => HornbeamParser::FunctionCall(Node::new(primary))?,
|
Rule::IntLiteral => Expression::IntLiteral { val: node.as_str().parse().map_err(|e| error(&format!("can't parse int: {e:?}"), node.as_span()))? },
|
||||||
|
Rule::String => Expression::StringExpr(HornbeamParser::String(node)?),
|
||||||
|
Rule::Variable => HornbeamParser::Variable(node)?,
|
||||||
|
Rule::FunctionCall => HornbeamParser::FunctionCall(node)?,
|
||||||
other => unimplemented!("unimp primary {other:?}!"),
|
other => unimplemented!("unimp primary {other:?}!"),
|
||||||
}))
|
})})
|
||||||
.map_prefix(|op, rhs| Ok(match op.as_rule() {
|
.map_prefix(|op, rhs| Ok(match op.as_rule() {
|
||||||
Rule::negation => Expression::Negate { sub: Box::new(rhs?) },
|
Rule::negation => Expression::Negate { sub: Box::new(rhs?) },
|
||||||
other => unimplemented!("unimp prefix {other:?}!"),
|
other => unimplemented!("unimp prefix {other:?}!"),
|
||||||
@ -258,28 +281,33 @@ impl HornbeamParser {
|
|||||||
Rule::band => Expression::BAnd { left: Box::new(lhs?), right: Box::new(rhs?) },
|
Rule::band => Expression::BAnd { left: Box::new(lhs?), right: Box::new(rhs?) },
|
||||||
other => unimplemented!("unimp infix {other:?}!"),
|
other => unimplemented!("unimp infix {other:?}!"),
|
||||||
}))
|
}))
|
||||||
.map_postfix(|lhs, op| Ok(match op.as_rule() {
|
.map_postfix(|lhs, op| {
|
||||||
|
let node = Node::new_with_user_data(op, ud.clone());
|
||||||
|
let loc = nodeloc(&node);
|
||||||
|
Ok(match node.as_rule() {
|
||||||
Rule::unwrap => unimplemented!("unimp unwrap"),
|
Rule::unwrap => unimplemented!("unimp unwrap"),
|
||||||
Rule::FieldLookup => {
|
Rule::FieldLookup => {
|
||||||
let ident = intern(Node::new(op).into_children().single()?.as_str());
|
let ident = intern(node.into_children().single()?.as_str());
|
||||||
Expression::FieldLookup { obj: Box::new(lhs?), ident }
|
Expression::FieldLookup { obj: Box::new(lhs?), ident, loc }
|
||||||
},
|
},
|
||||||
Rule::MethodCall => {
|
Rule::MethodCall => {
|
||||||
match_nodes!(Node::new(op).into_children();
|
match_nodes!(node.into_children();
|
||||||
[Identifier(ident), Expr(args)..] => {
|
[Identifier(ident), Expr(args)..] => {
|
||||||
Expression::MethodCall { obj: Box::new(lhs?), ident, args: args.collect() }
|
Expression::MethodCall { obj: Box::new(lhs?), ident, args: args.collect(), loc }
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
other => unimplemented!("unimp postfix {other:?}!"),
|
other => unimplemented!("unimp postfix {other:?}!"),
|
||||||
}))
|
})})
|
||||||
.parse(input.into_children().into_pairs())
|
.parse(input.into_children().into_pairs());
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
fn FunctionCall(input: Node) -> PCResult<Expression> {
|
fn FunctionCall(input: Node) -> PCResult<Expression> {
|
||||||
|
let loc = nodeloc(&input);
|
||||||
Ok(match_nodes!(input.into_children();
|
Ok(match_nodes!(input.into_children();
|
||||||
[Identifier(name), Expr(args)..] => {
|
[Identifier(name), Expr(args)..] => {
|
||||||
Expression::FunctionCall { name, args: args.collect() }
|
Expression::FunctionCall { name, args: args.collect(), loc }
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -289,6 +317,8 @@ impl HornbeamParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn IfBlock(input: Node) -> PCResult<Block> {
|
fn IfBlock(input: Node) -> PCResult<Block> {
|
||||||
|
let loc = nodeloc(&input);
|
||||||
|
|
||||||
let (cond, blocks, else_blocks) = match_nodes!(input.into_children();
|
let (cond, blocks, else_blocks) = match_nodes!(input.into_children();
|
||||||
[IfCondition(cond), blocks.., ElseBlock(else_blocks)] => {
|
[IfCondition(cond), blocks.., ElseBlock(else_blocks)] => {
|
||||||
(cond, blocks, else_blocks)
|
(cond, blocks, else_blocks)
|
||||||
@ -302,6 +332,7 @@ impl HornbeamParser {
|
|||||||
condition: cond,
|
condition: cond,
|
||||||
blocks: HornbeamParser::helper_blocks(blocks)?,
|
blocks: HornbeamParser::helper_blocks(blocks)?,
|
||||||
else_blocks,
|
else_blocks,
|
||||||
|
loc,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,8 +370,14 @@ impl HornbeamParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_template(input: &str) -> PCResult<Template> {
|
pub fn parse_template(input: &str, filename: &str) -> PCResult<Template> {
|
||||||
let res = HornbeamParser::parse(Rule::Hornbeam, input)?;
|
let res = HornbeamParser::parse_with_userdata(
|
||||||
|
Rule::Hornbeam,
|
||||||
|
input,
|
||||||
|
ParserUserData {
|
||||||
|
file: intern(filename),
|
||||||
|
},
|
||||||
|
)?;
|
||||||
let hornbeam = res.single()?;
|
let hornbeam = res.single()?;
|
||||||
HornbeamParser::Hornbeam(hornbeam)
|
HornbeamParser::Hornbeam(hornbeam)
|
||||||
}
|
}
|
||||||
@ -356,7 +393,8 @@ mod tests {
|
|||||||
r#"
|
r#"
|
||||||
// This is a simple Hornbeam template that just shows a <div>
|
// This is a simple Hornbeam template that just shows a <div>
|
||||||
div
|
div
|
||||||
"#
|
"#,
|
||||||
|
"inp"
|
||||||
)
|
)
|
||||||
.unwrap());
|
.unwrap());
|
||||||
}
|
}
|
||||||
@ -368,7 +406,8 @@ div
|
|||||||
div
|
div
|
||||||
:someslot
|
:someslot
|
||||||
"Oops!"
|
"Oops!"
|
||||||
"#
|
"#,
|
||||||
|
"inp"
|
||||||
));
|
));
|
||||||
|
|
||||||
assert_yaml_snapshot!(parse_template(
|
assert_yaml_snapshot!(parse_template(
|
||||||
@ -376,7 +415,8 @@ div
|
|||||||
MyComponent
|
MyComponent
|
||||||
:someslot
|
:someslot
|
||||||
"That's better!"
|
"That's better!"
|
||||||
"#
|
"#,
|
||||||
|
"inp"
|
||||||
)
|
)
|
||||||
.unwrap());
|
.unwrap());
|
||||||
}
|
}
|
||||||
@ -391,7 +431,8 @@ MyComponent
|
|||||||
${"abc" + "def${ 1 + 1 }"}
|
${"abc" + "def${ 1 + 1 }"}
|
||||||
Not too bad now.
|
Not too bad now.
|
||||||
''
|
''
|
||||||
"#
|
"#,
|
||||||
|
"inp"
|
||||||
)
|
)
|
||||||
.unwrap());
|
.unwrap());
|
||||||
}
|
}
|
||||||
@ -402,7 +443,8 @@ MyComponent
|
|||||||
r#"
|
r#"
|
||||||
if 10 / 2 == 5 or $point.x == 42 // div for a div?
|
if 10 / 2 == 5 or $point.x == 42 // div for a div?
|
||||||
div
|
div
|
||||||
"#
|
"#,
|
||||||
|
"inp"
|
||||||
)
|
)
|
||||||
.unwrap());
|
.unwrap());
|
||||||
|
|
||||||
@ -416,7 +458,8 @@ else if 1 + 2 - 1 == 3 // not too far off, I suppose
|
|||||||
"Not quite, but fairly close. What kind of world is this?"
|
"Not quite, but fairly close. What kind of world is this?"
|
||||||
else // peculiar.
|
else // peculiar.
|
||||||
"Not even close, eh?"
|
"Not even close, eh?"
|
||||||
"#
|
"#,
|
||||||
|
"inp"
|
||||||
)
|
)
|
||||||
.unwrap());
|
.unwrap());
|
||||||
}
|
}
|
||||||
@ -433,7 +476,8 @@ div
|
|||||||
slot :main
|
slot :main
|
||||||
div
|
div
|
||||||
optional slot :footer
|
optional slot :footer
|
||||||
"#
|
"#,
|
||||||
|
"inp"
|
||||||
)
|
)
|
||||||
.unwrap());
|
.unwrap());
|
||||||
}
|
}
|
||||||
@ -452,7 +496,8 @@ div
|
|||||||
''
|
''
|
||||||
Footer
|
Footer
|
||||||
@footer-copyright{year = today().year}
|
@footer-copyright{year = today().year}
|
||||||
"#
|
"#,
|
||||||
|
"inp"
|
||||||
)
|
)
|
||||||
.unwrap());
|
.unwrap());
|
||||||
}
|
}
|
||||||
|
@ -415,7 +415,7 @@ impl<'a, L: Sync + Send, O: OutputSystem + Send, LS: LocalisationSystem + Sync +
|
|||||||
}
|
}
|
||||||
Ok(Value::Str(Arc::new(output)))
|
Ok(Value::Str(Arc::new(output)))
|
||||||
}
|
}
|
||||||
Expression::FieldLookup { obj, ident } => {
|
Expression::FieldLookup { obj, ident, loc } => {
|
||||||
let obj_val = self.evaluate_expression(scope_idx, obj)?;
|
let obj_val = self.evaluate_expression(scope_idx, obj)?;
|
||||||
match obj_val {
|
match obj_val {
|
||||||
Value::Reflective(reflective) => match reflective.reflect_ref() {
|
Value::Reflective(reflective) => match reflective.reflect_ref() {
|
||||||
@ -468,7 +468,7 @@ impl<'a, L: Sync + Send, O: OutputSystem + Send, LS: LocalisationSystem + Sync +
|
|||||||
Expression::MethodCall { .. } => {
|
Expression::MethodCall { .. } => {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
Expression::Variable { name } => {
|
Expression::Variable { name, loc } => {
|
||||||
let locals = &self.scopes[scope_idx].variables;
|
let locals = &self.scopes[scope_idx].variables;
|
||||||
match locals.get(name as &str) {
|
match locals.get(name as &str) {
|
||||||
Some(variable_value) => Ok(variable_value.clone()),
|
Some(variable_value) => Ok(variable_value.clone()),
|
||||||
|
@ -88,8 +88,9 @@ impl<'a, LS> LoadedTemplates<(), LS> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
template_name: &str,
|
template_name: &str,
|
||||||
template: &'a str,
|
template: &'a str,
|
||||||
|
filename: &str,
|
||||||
) -> Result<(), InterpreterError<Infallible, Infallible>> {
|
) -> Result<(), InterpreterError<Infallible, Infallible>> {
|
||||||
let template = parse_template(template)?;
|
let template = parse_template(template, filename)?;
|
||||||
let ir = ast_to_optimised_ir(template_name, template)?;
|
let ir = ast_to_optimised_ir(template_name, template)?;
|
||||||
for (k, v) in ir {
|
for (k, v) in ir {
|
||||||
self.template_functions.insert(k, Arc::new(v));
|
self.template_functions.insert(k, Arc::new(v));
|
||||||
|
@ -317,6 +317,7 @@ div
|
|||||||
fragment Footer
|
fragment Footer
|
||||||
"Or even adjacent ones"
|
"Or even adjacent ones"
|
||||||
"#,
|
"#,
|
||||||
|
"inp",
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_yaml_snapshot!(pull_out_entrypoints(template, "TemplateName").unwrap());
|
assert_yaml_snapshot!(pull_out_entrypoints(template, "TemplateName").unwrap());
|
||||||
@ -336,6 +337,7 @@ div
|
|||||||
fragment Footer
|
fragment Footer
|
||||||
"Or even adjacent ones"
|
"Or even adjacent ones"
|
||||||
"#,
|
"#,
|
||||||
|
"inp",
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_yaml_snapshot!(compile_functions(
|
assert_yaml_snapshot!(compile_functions(
|
||||||
@ -352,6 +354,7 @@ div.stylish#myid {size=42, stringy="yup", arb=$ritrary}
|
|||||||
"This is a div with a few extras"
|
"This is a div with a few extras"
|
||||||
OtherComponent {param1=1, param2="two", param3=$three}
|
OtherComponent {param1=1, param2="two", param3=$three}
|
||||||
"#,
|
"#,
|
||||||
|
"inp",
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_yaml_snapshot!(compile_functions(
|
assert_yaml_snapshot!(compile_functions(
|
||||||
|
@ -168,7 +168,7 @@ mod tests {
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
fn parse_ir_and_peephole(text: &str) -> BTreeMap<String, Vec<Step<()>>> {
|
fn parse_ir_and_peephole(text: &str) -> BTreeMap<String, Vec<Step<()>>> {
|
||||||
let template = parse_template(text).unwrap();
|
let template = parse_template(text, "inp").unwrap();
|
||||||
let entrypoints = pull_out_entrypoints(template, "TemplateName").unwrap();
|
let entrypoints = pull_out_entrypoints(template, "TemplateName").unwrap();
|
||||||
let mut compiled = compile_functions(&entrypoints).unwrap();
|
let mut compiled = compile_functions(&entrypoints).unwrap();
|
||||||
compiled.values_mut().for_each(apply_all_peephole_passes);
|
compiled.values_mut().for_each(apply_all_peephole_passes);
|
||||||
|
Loading…
Reference in New Issue
Block a user