Use template for object map literal.
This commit is contained in:
parent
f70225ca1d
commit
f9429c06f9
23
src/ast.rs
23
src/ast.rs
@ -26,9 +26,6 @@ use crate::{stdlib::str::FromStr, FLOAT};
|
|||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
use crate::Array;
|
use crate::Array;
|
||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
|
||||||
use crate::Map;
|
|
||||||
|
|
||||||
/// A type representing the access mode of a function.
|
/// A type representing the access mode of a function.
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||||
pub enum FnAccess {
|
pub enum FnAccess {
|
||||||
@ -1535,7 +1532,10 @@ pub enum Expr {
|
|||||||
/// [ expr, ... ]
|
/// [ expr, ... ]
|
||||||
Array(Box<StaticVec<Expr>>, Position),
|
Array(Box<StaticVec<Expr>>, Position),
|
||||||
/// #{ name:expr, ... }
|
/// #{ name:expr, ... }
|
||||||
Map(Box<StaticVec<(Ident, Expr)>>, Position),
|
Map(
|
||||||
|
Box<(StaticVec<(Ident, Expr)>, BTreeMap<ImmutableString, Dynamic>)>,
|
||||||
|
Position,
|
||||||
|
),
|
||||||
/// ()
|
/// ()
|
||||||
Unit(Position),
|
Unit(Position),
|
||||||
/// Variable access - (optional index, optional (hash, modules), variable name)
|
/// Variable access - (optional index, optional (hash, modules), variable name)
|
||||||
@ -1594,11 +1594,10 @@ impl Expr {
|
|||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Self::Map(x, _) if self.is_constant() => {
|
Self::Map(x, _) if self.is_constant() => {
|
||||||
let mut map = Map::new();
|
let mut map = x.1.clone();
|
||||||
map.extend(
|
x.0.iter().for_each(|(k, v)| {
|
||||||
x.iter()
|
*map.get_mut(&k.name).unwrap() = v.get_constant_value().unwrap()
|
||||||
.map(|(k, v)| (k.name.clone(), v.get_constant_value().unwrap())),
|
});
|
||||||
);
|
|
||||||
Dynamic(Union::Map(Box::new(map), AccessMode::ReadOnly))
|
Dynamic(Union::Map(Box::new(map), AccessMode::ReadOnly))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1677,7 +1676,7 @@ impl Expr {
|
|||||||
match self {
|
match self {
|
||||||
Self::Array(x, _) => x.iter().all(Self::is_pure),
|
Self::Array(x, _) => x.iter().all(Self::is_pure),
|
||||||
|
|
||||||
Self::Map(x, _) => x.iter().map(|(_, v)| v).all(Self::is_pure),
|
Self::Map(x, _) => x.0.iter().map(|(_, v)| v).all(Self::is_pure),
|
||||||
|
|
||||||
Self::Index(x, _) | Self::And(x, _) | Self::Or(x, _) => {
|
Self::Index(x, _) | Self::And(x, _) | Self::Or(x, _) => {
|
||||||
x.lhs.is_pure() && x.rhs.is_pure()
|
x.lhs.is_pure() && x.rhs.is_pure()
|
||||||
@ -1717,7 +1716,7 @@ impl Expr {
|
|||||||
Self::Array(x, _) => x.iter().all(Self::is_constant),
|
Self::Array(x, _) => x.iter().all(Self::is_constant),
|
||||||
|
|
||||||
// An map literal is constant if all items are constant
|
// An map literal is constant if all items are constant
|
||||||
Self::Map(x, _) => x.iter().map(|(_, expr)| expr).all(Self::is_constant),
|
Self::Map(x, _) => x.0.iter().map(|(_, expr)| expr).all(Self::is_constant),
|
||||||
|
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
@ -1804,7 +1803,7 @@ impl Expr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Self::Map(x, _) => {
|
Self::Map(x, _) => {
|
||||||
for (_, e) in x.as_ref() {
|
for (_, e) in &x.0 {
|
||||||
if !e.walk(path, on_node) {
|
if !e.walk(path, on_node) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1686,13 +1686,11 @@ impl Engine {
|
|||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Expr::Map(x, _) => {
|
Expr::Map(x, _) => {
|
||||||
let mut map = Map::new();
|
let mut map = x.1.clone();
|
||||||
for (Ident { name: key, .. }, expr) in x.as_ref() {
|
for (Ident { name: key, .. }, expr) in &x.0 {
|
||||||
map.insert(
|
*map.get_mut(key).unwrap() = self
|
||||||
key.clone(),
|
.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?
|
||||||
self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?
|
.flatten();
|
||||||
.flatten(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
Ok(Dynamic(Union::Map(Box::new(map), AccessMode::ReadWrite)))
|
Ok(Dynamic(Union::Map(Box::new(map), AccessMode::ReadWrite)))
|
||||||
}
|
}
|
||||||
|
@ -615,12 +615,12 @@ fn optimize_expr(expr: &mut Expr, state: &mut State) {
|
|||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Expr::Dot(x, _) => match (&mut x.lhs, &mut x.rhs) {
|
Expr::Dot(x, _) => match (&mut x.lhs, &mut x.rhs) {
|
||||||
// map.string
|
// map.string
|
||||||
(Expr::Map(m, pos), Expr::Property(p)) if m.iter().all(|(_, x)| x.is_pure()) => {
|
(Expr::Map(m, pos), Expr::Property(p)) if m.0.iter().all(|(_, x)| x.is_pure()) => {
|
||||||
let prop = &p.2.name;
|
let prop = &p.2.name;
|
||||||
// Map literal where everything is pure - promote the indexed item.
|
// Map literal where everything is pure - promote the indexed item.
|
||||||
// All other items can be thrown away.
|
// All other items can be thrown away.
|
||||||
state.set_dirty();
|
state.set_dirty();
|
||||||
*expr = mem::take(m).into_iter().find(|(x, _)| &x.name == prop)
|
*expr = mem::take(&mut m.0).into_iter().find(|(x, _)| &x.name == prop)
|
||||||
.map(|(_, mut expr)| { expr.set_position(*pos); expr })
|
.map(|(_, mut expr)| { expr.set_position(*pos); expr })
|
||||||
.unwrap_or_else(|| Expr::Unit(*pos));
|
.unwrap_or_else(|| Expr::Unit(*pos));
|
||||||
}
|
}
|
||||||
@ -645,11 +645,11 @@ fn optimize_expr(expr: &mut Expr, state: &mut State) {
|
|||||||
*expr = result;
|
*expr = result;
|
||||||
}
|
}
|
||||||
// map[string]
|
// map[string]
|
||||||
(Expr::Map(m, pos), Expr::StringConstant(s, _)) if m.iter().all(|(_, x)| x.is_pure()) => {
|
(Expr::Map(m, pos), Expr::StringConstant(s, _)) if m.0.iter().all(|(_, x)| x.is_pure()) => {
|
||||||
// Map literal where everything is pure - promote the indexed item.
|
// Map literal where everything is pure - promote the indexed item.
|
||||||
// All other items can be thrown away.
|
// All other items can be thrown away.
|
||||||
state.set_dirty();
|
state.set_dirty();
|
||||||
*expr = mem::take(m).into_iter().find(|(x, _)| x.name == *s)
|
*expr = mem::take(&mut m.0).into_iter().find(|(x, _)| x.name == *s)
|
||||||
.map(|(_, mut expr)| { expr.set_position(*pos); expr })
|
.map(|(_, mut expr)| { expr.set_position(*pos); expr })
|
||||||
.unwrap_or_else(|| Expr::Unit(*pos));
|
.unwrap_or_else(|| Expr::Unit(*pos));
|
||||||
}
|
}
|
||||||
@ -681,7 +681,7 @@ fn optimize_expr(expr: &mut Expr, state: &mut State) {
|
|||||||
}
|
}
|
||||||
// #{ key:value, .. }
|
// #{ key:value, .. }
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Expr::Map(x, _) => x.iter_mut().for_each(|(_, expr)| optimize_expr(expr, state)),
|
Expr::Map(x, _) => x.0.iter_mut().for_each(|(_, expr)| optimize_expr(expr, state)),
|
||||||
// lhs && rhs
|
// lhs && rhs
|
||||||
Expr::And(x, _) => match (&mut x.lhs, &mut x.rhs) {
|
Expr::And(x, _) => match (&mut x.lhs, &mut x.rhs) {
|
||||||
// true && rhs -> rhs
|
// true && rhs -> rhs
|
||||||
|
@ -690,6 +690,7 @@ fn parse_map_literal(
|
|||||||
settings.pos = eat_token(input, Token::MapStart);
|
settings.pos = eat_token(input, Token::MapStart);
|
||||||
|
|
||||||
let mut map: StaticVec<(Ident, Expr)> = Default::default();
|
let mut map: StaticVec<(Ident, Expr)> = Default::default();
|
||||||
|
let mut template: BTreeMap<ImmutableString, Dynamic> = Default::default();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
const MISSING_RBRACE: &str = "to end this object map literal";
|
const MISSING_RBRACE: &str = "to end this object map literal";
|
||||||
@ -760,6 +761,7 @@ fn parse_map_literal(
|
|||||||
|
|
||||||
let expr = parse_expr(input, state, lib, settings.level_up())?;
|
let expr = parse_expr(input, state, lib, settings.level_up())?;
|
||||||
let name = state.get_interned_string(name);
|
let name = state.get_interned_string(name);
|
||||||
|
template.insert(name.clone(), Default::default());
|
||||||
map.push((Ident { name, pos }, expr));
|
map.push((Ident { name, pos }, expr));
|
||||||
|
|
||||||
match input.peek().unwrap() {
|
match input.peek().unwrap() {
|
||||||
@ -784,7 +786,7 @@ fn parse_map_literal(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Expr::Map(Box::new(map), settings.pos))
|
Ok(Expr::Map(Box::new((map, template)), settings.pos))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a switch expression.
|
/// Parse a switch expression.
|
||||||
|
Loading…
Reference in New Issue
Block a user