Fix positions.
This commit is contained in:
parent
3050e38c5e
commit
d23d1159ab
@ -879,7 +879,7 @@ impl Eq for ASTNode<'_> {}
|
|||||||
|
|
||||||
impl ASTNode<'_> {
|
impl ASTNode<'_> {
|
||||||
/// Get the [`Position`] of this [`ASTNode`].
|
/// Get the [`Position`] of this [`ASTNode`].
|
||||||
pub const fn position(&self) -> Position {
|
pub fn position(&self) -> Position {
|
||||||
match self {
|
match self {
|
||||||
ASTNode::Stmt(stmt) => stmt.position(),
|
ASTNode::Stmt(stmt) => stmt.position(),
|
||||||
ASTNode::Expr(expr) => expr.position(),
|
ASTNode::Expr(expr) => expr.position(),
|
||||||
|
@ -440,7 +440,7 @@ impl Default for Expr {
|
|||||||
|
|
||||||
impl fmt::Debug for Expr {
|
impl fmt::Debug for Expr {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let mut display_pos = self.start_position();
|
let mut display_pos = format!(" @ {:?}", self.start_position());
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Self::DynamicConstant(value, ..) => write!(f, "{:?}", value),
|
Self::DynamicConstant(value, ..) => write!(f, "{:?}", value),
|
||||||
@ -470,24 +470,34 @@ impl fmt::Debug for Expr {
|
|||||||
f.write_str("Variable(")?;
|
f.write_str("Variable(")?;
|
||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
if let Some((.., ref namespace)) = x.1 {
|
if let Some((ref namespace, ..)) = x.1 {
|
||||||
write!(f, "{}{}", namespace, Token::DoubleColon.literal_syntax())?
|
write!(f, "{}{}", namespace, Token::DoubleColon.literal_syntax())?;
|
||||||
|
let pos = namespace.position();
|
||||||
|
if !pos.is_none() {
|
||||||
|
display_pos = format!(" @ {:?}", pos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
f.write_str(&x.2)?;
|
f.write_str(&x.2)?;
|
||||||
if let Some(n) = i.map_or_else(|| x.0, |n| NonZeroUsize::new(n.get() as usize)) {
|
if let Some(n) = i.map_or_else(|| x.0, |n| NonZeroUsize::new(n.get() as usize)) {
|
||||||
write!(f, " #{}", n)?
|
write!(f, " #{}", n)?;
|
||||||
}
|
}
|
||||||
f.write_str(")")
|
f.write_str(")")
|
||||||
}
|
}
|
||||||
Self::Property(x, ..) => write!(f, "Property({})", x.2),
|
Self::Property(x, ..) => write!(f, "Property({})", x.2),
|
||||||
Self::Stack(x, ..) => write!(f, "ConstantArg[{}]", x),
|
Self::Stack(x, ..) => write!(f, "ConstantArg[{}]", x),
|
||||||
Self::Stmt(x) => {
|
Self::Stmt(x) => {
|
||||||
|
let pos = x.span();
|
||||||
|
if !pos.is_none() {
|
||||||
|
display_pos = format!(" @ {:?}", pos);
|
||||||
|
}
|
||||||
f.write_str("ExprStmtBlock")?;
|
f.write_str("ExprStmtBlock")?;
|
||||||
f.debug_list().entries(x.iter()).finish()
|
f.debug_list().entries(x.iter()).finish()
|
||||||
}
|
}
|
||||||
Self::FnCall(x, ..) => fmt::Debug::fmt(x, f),
|
Self::FnCall(x, ..) => fmt::Debug::fmt(x, f),
|
||||||
Self::Index(x, term, pos) => {
|
Self::Index(x, term, pos) => {
|
||||||
display_pos = *pos;
|
if !pos.is_none() {
|
||||||
|
display_pos = format!(" @ {:?}", pos);
|
||||||
|
}
|
||||||
|
|
||||||
f.debug_struct("Index")
|
f.debug_struct("Index")
|
||||||
.field("lhs", &x.lhs)
|
.field("lhs", &x.lhs)
|
||||||
@ -506,7 +516,9 @@ impl fmt::Debug for Expr {
|
|||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
display_pos = *pos;
|
if !pos.is_none() {
|
||||||
|
display_pos = format!(" @ {:?}", pos);
|
||||||
|
}
|
||||||
|
|
||||||
f.debug_struct(op_name)
|
f.debug_struct(op_name)
|
||||||
.field("lhs", &x.lhs)
|
.field("lhs", &x.lhs)
|
||||||
@ -516,7 +528,7 @@ impl fmt::Debug for Expr {
|
|||||||
Self::Custom(x, ..) => f.debug_tuple("Custom").field(x).finish(),
|
Self::Custom(x, ..) => f.debug_tuple("Custom").field(x).finish(),
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
display_pos.debug_print(f)
|
f.write_str(&display_pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -708,8 +720,16 @@ impl Expr {
|
|||||||
/// For a binary expression, this will be the left-most LHS instead of the operator.
|
/// For a binary expression, this will be the left-most LHS instead of the operator.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn start_position(&self) -> Position {
|
pub fn start_position(&self) -> Position {
|
||||||
match self {
|
match self {
|
||||||
|
#[cfg(not(feature = "no_module"))]
|
||||||
|
Self::Variable(.., x) => {
|
||||||
|
if let Some((ref namespace, ..)) = x.1 {
|
||||||
|
namespace.position()
|
||||||
|
} else {
|
||||||
|
self.position()
|
||||||
|
}
|
||||||
|
}
|
||||||
Self::And(x, ..) | Self::Or(x, ..) | Self::Index(x, ..) | Self::Dot(x, ..) => {
|
Self::And(x, ..) | Self::Or(x, ..) | Self::Index(x, ..) | Self::Dot(x, ..) => {
|
||||||
x.lhs.start_position()
|
x.lhs.start_position()
|
||||||
}
|
}
|
||||||
|
@ -402,7 +402,7 @@ impl Stmt {
|
|||||||
}
|
}
|
||||||
/// Get the [position][Position] of this statement.
|
/// Get the [position][Position] of this statement.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn position(&self) -> Position {
|
pub fn position(&self) -> Position {
|
||||||
match self {
|
match self {
|
||||||
Self::Noop(pos)
|
Self::Noop(pos)
|
||||||
| Self::BreakLoop(.., pos)
|
| Self::BreakLoop(.., pos)
|
||||||
|
@ -325,7 +325,13 @@ fn main() {
|
|||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
["node", ..] => {
|
["node", ..] => {
|
||||||
println!("{:?} {}@{:?}", node, source.unwrap_or_default(), pos);
|
if pos.is_none() {
|
||||||
|
println!("{:?}", node);
|
||||||
|
} else if let Some(source) = source {
|
||||||
|
println!("{:?} {} @ {:?}", node, source, pos);
|
||||||
|
} else {
|
||||||
|
println!("{:?} @ {:?}", node, pos);
|
||||||
|
}
|
||||||
println!();
|
println!();
|
||||||
}
|
}
|
||||||
["list" | "l", ..] => print_current_source(context, source, pos, &lines),
|
["list" | "l", ..] => print_current_source(context, source, pos, &lines),
|
||||||
|
@ -147,7 +147,6 @@ impl Engine {
|
|||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
ChainType::Indexing => {
|
ChainType::Indexing => {
|
||||||
let pos = rhs.start_position();
|
let pos = rhs.start_position();
|
||||||
let root_pos = idx_val.position();
|
|
||||||
let idx_val = idx_val.into_index_value().expect("`ChainType::Index`");
|
let idx_val = idx_val.into_index_value().expect("`ChainType::Index`");
|
||||||
|
|
||||||
match rhs {
|
match rhs {
|
||||||
@ -190,7 +189,7 @@ impl Engine {
|
|||||||
)
|
)
|
||||||
.or_else(|idx_err| match *idx_err {
|
.or_else(|idx_err| match *idx_err {
|
||||||
ERR::ErrorIndexingType(..) => Ok((Dynamic::UNIT, false)),
|
ERR::ErrorIndexingType(..) => Ok((Dynamic::UNIT, false)),
|
||||||
_ => Err(idx_err.fill_position(root_pos)),
|
_ => Err(idx_err),
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,8 +230,7 @@ impl Engine {
|
|||||||
let new_val = &mut new_val;
|
let new_val = &mut new_val;
|
||||||
self.call_indexer_set(
|
self.call_indexer_set(
|
||||||
global, state, lib, target, idx, new_val, is_ref_mut, level,
|
global, state, lib, target, idx, new_val, is_ref_mut, level,
|
||||||
)
|
)?;
|
||||||
.map_err(|err| err.fill_position(root_pos))?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((Dynamic::UNIT, true))
|
Ok((Dynamic::UNIT, true))
|
||||||
@ -506,7 +504,7 @@ impl Engine {
|
|||||||
.map_err(
|
.map_err(
|
||||||
|idx_err| match *idx_err {
|
|idx_err| match *idx_err {
|
||||||
ERR::ErrorIndexingType(..) => err,
|
ERR::ErrorIndexingType(..) => err,
|
||||||
_ => idx_err.fill_position(pos),
|
_ => idx_err,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -553,12 +551,12 @@ impl Engine {
|
|||||||
is_ref_mut, level,
|
is_ref_mut, level,
|
||||||
)
|
)
|
||||||
.or_else(|idx_err| match *idx_err {
|
.or_else(|idx_err| match *idx_err {
|
||||||
|
// If there is no setter, no need to feed it
|
||||||
|
// back because the property is read-only
|
||||||
ERR::ErrorIndexingType(..) => {
|
ERR::ErrorIndexingType(..) => {
|
||||||
// If there is no setter, no need to feed it back because
|
|
||||||
// the property is read-only
|
|
||||||
Ok((Dynamic::UNIT, false))
|
Ok((Dynamic::UNIT, false))
|
||||||
}
|
}
|
||||||
_ => Err(idx_err.fill_position(pos)),
|
_ => Err(idx_err),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
_ => Err(err),
|
_ => Err(err),
|
||||||
@ -872,7 +870,7 @@ impl Engine {
|
|||||||
lib: &[&Module],
|
lib: &[&Module],
|
||||||
target: &'t mut Dynamic,
|
target: &'t mut Dynamic,
|
||||||
idx: Dynamic,
|
idx: Dynamic,
|
||||||
pos: Position,
|
idx_pos: Position,
|
||||||
add_if_not_found: bool,
|
add_if_not_found: bool,
|
||||||
use_indexers: bool,
|
use_indexers: bool,
|
||||||
level: usize,
|
level: usize,
|
||||||
@ -889,10 +887,10 @@ impl Engine {
|
|||||||
// val_array[idx]
|
// val_array[idx]
|
||||||
let index = idx
|
let index = idx
|
||||||
.as_int()
|
.as_int()
|
||||||
.map_err(|typ| self.make_type_mismatch_err::<crate::INT>(typ, pos))?;
|
.map_err(|typ| self.make_type_mismatch_err::<crate::INT>(typ, idx_pos))?;
|
||||||
let len = arr.len();
|
let len = arr.len();
|
||||||
let arr_idx = super::calc_index(len, index, true, || {
|
let arr_idx = super::calc_index(len, index, true, || {
|
||||||
ERR::ErrorArrayBounds(len, index, pos).into()
|
ERR::ErrorArrayBounds(len, index, idx_pos).into()
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(arr.get_mut(arr_idx).map(Target::from).unwrap())
|
Ok(arr.get_mut(arr_idx).map(Target::from).unwrap())
|
||||||
@ -903,10 +901,10 @@ impl Engine {
|
|||||||
// val_blob[idx]
|
// val_blob[idx]
|
||||||
let index = idx
|
let index = idx
|
||||||
.as_int()
|
.as_int()
|
||||||
.map_err(|typ| self.make_type_mismatch_err::<crate::INT>(typ, pos))?;
|
.map_err(|typ| self.make_type_mismatch_err::<crate::INT>(typ, idx_pos))?;
|
||||||
let len = arr.len();
|
let len = arr.len();
|
||||||
let arr_idx = super::calc_index(len, index, true, || {
|
let arr_idx = super::calc_index(len, index, true, || {
|
||||||
ERR::ErrorArrayBounds(len, index, pos).into()
|
ERR::ErrorArrayBounds(len, index, idx_pos).into()
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let value = arr.get(arr_idx).map(|&v| (v as crate::INT).into()).unwrap();
|
let value = arr.get(arr_idx).map(|&v| (v as crate::INT).into()).unwrap();
|
||||||
@ -922,7 +920,7 @@ impl Engine {
|
|||||||
Dynamic(Union::Map(map, ..)) => {
|
Dynamic(Union::Map(map, ..)) => {
|
||||||
// val_map[idx]
|
// val_map[idx]
|
||||||
let index = idx.read_lock::<crate::ImmutableString>().ok_or_else(|| {
|
let index = idx.read_lock::<crate::ImmutableString>().ok_or_else(|| {
|
||||||
self.make_type_mismatch_err::<crate::ImmutableString>(idx.type_name(), pos)
|
self.make_type_mismatch_err::<crate::ImmutableString>(idx.type_name(), idx_pos)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
if _add_if_not_found && !map.contains_key(index.as_str()) {
|
if _add_if_not_found && !map.contains_key(index.as_str()) {
|
||||||
@ -932,7 +930,7 @@ impl Engine {
|
|||||||
if let Some(value) = map.get_mut(index.as_str()) {
|
if let Some(value) = map.get_mut(index.as_str()) {
|
||||||
Ok(Target::from(value))
|
Ok(Target::from(value))
|
||||||
} else if self.fail_on_invalid_map_property() {
|
} else if self.fail_on_invalid_map_property() {
|
||||||
Err(ERR::ErrorPropertyNotFound(index.to_string(), pos).into())
|
Err(ERR::ErrorPropertyNotFound(index.to_string(), idx_pos).into())
|
||||||
} else {
|
} else {
|
||||||
Ok(Target::from(Dynamic::UNIT))
|
Ok(Target::from(Dynamic::UNIT))
|
||||||
}
|
}
|
||||||
@ -950,10 +948,10 @@ impl Engine {
|
|||||||
let end = range.end;
|
let end = range.end;
|
||||||
|
|
||||||
let start = super::calc_index(BITS, start, false, || {
|
let start = super::calc_index(BITS, start, false, || {
|
||||||
ERR::ErrorBitFieldBounds(BITS, start, pos).into()
|
ERR::ErrorBitFieldBounds(BITS, start, idx_pos).into()
|
||||||
})?;
|
})?;
|
||||||
let end = super::calc_index(BITS, end, false, || {
|
let end = super::calc_index(BITS, end, false, || {
|
||||||
ERR::ErrorBitFieldBounds(BITS, end, pos).into()
|
ERR::ErrorBitFieldBounds(BITS, end, idx_pos).into()
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
if end <= start {
|
if end <= start {
|
||||||
@ -975,10 +973,10 @@ impl Engine {
|
|||||||
let end = *range.end();
|
let end = *range.end();
|
||||||
|
|
||||||
let start = super::calc_index(BITS, start, false, || {
|
let start = super::calc_index(BITS, start, false, || {
|
||||||
ERR::ErrorBitFieldBounds(BITS, start, pos).into()
|
ERR::ErrorBitFieldBounds(BITS, start, idx_pos).into()
|
||||||
})?;
|
})?;
|
||||||
let end = super::calc_index(BITS, end, false, || {
|
let end = super::calc_index(BITS, end, false, || {
|
||||||
ERR::ErrorBitFieldBounds(BITS, end, pos).into()
|
ERR::ErrorBitFieldBounds(BITS, end, idx_pos).into()
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
if end < start {
|
if end < start {
|
||||||
@ -1014,12 +1012,12 @@ impl Engine {
|
|||||||
// val_int[idx]
|
// val_int[idx]
|
||||||
let index = idx
|
let index = idx
|
||||||
.as_int()
|
.as_int()
|
||||||
.map_err(|typ| self.make_type_mismatch_err::<crate::INT>(typ, pos))?;
|
.map_err(|typ| self.make_type_mismatch_err::<crate::INT>(typ, idx_pos))?;
|
||||||
|
|
||||||
const BITS: usize = std::mem::size_of::<crate::INT>() * 8;
|
const BITS: usize = std::mem::size_of::<crate::INT>() * 8;
|
||||||
|
|
||||||
let bit = super::calc_index(BITS, index, true, || {
|
let bit = super::calc_index(BITS, index, true, || {
|
||||||
ERR::ErrorBitFieldBounds(BITS, index, pos).into()
|
ERR::ErrorBitFieldBounds(BITS, index, idx_pos).into()
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let bit_value = (*value & (1 << bit)) != 0;
|
let bit_value = (*value & (1 << bit)) != 0;
|
||||||
@ -1036,14 +1034,14 @@ impl Engine {
|
|||||||
// val_string[idx]
|
// val_string[idx]
|
||||||
let index = idx
|
let index = idx
|
||||||
.as_int()
|
.as_int()
|
||||||
.map_err(|typ| self.make_type_mismatch_err::<crate::INT>(typ, pos))?;
|
.map_err(|typ| self.make_type_mismatch_err::<crate::INT>(typ, idx_pos))?;
|
||||||
|
|
||||||
let (ch, offset) = if index >= 0 {
|
let (ch, offset) = if index >= 0 {
|
||||||
let offset = index as usize;
|
let offset = index as usize;
|
||||||
(
|
(
|
||||||
s.chars().nth(offset).ok_or_else(|| {
|
s.chars().nth(offset).ok_or_else(|| {
|
||||||
let chars_len = s.chars().count();
|
let chars_len = s.chars().count();
|
||||||
ERR::ErrorStringBounds(chars_len, index, pos)
|
ERR::ErrorStringBounds(chars_len, index, idx_pos)
|
||||||
})?,
|
})?,
|
||||||
offset,
|
offset,
|
||||||
)
|
)
|
||||||
@ -1053,13 +1051,13 @@ impl Engine {
|
|||||||
// Count from end if negative
|
// Count from end if negative
|
||||||
s.chars().rev().nth(offset - 1).ok_or_else(|| {
|
s.chars().rev().nth(offset - 1).ok_or_else(|| {
|
||||||
let chars_len = s.chars().count();
|
let chars_len = s.chars().count();
|
||||||
ERR::ErrorStringBounds(chars_len, index, pos)
|
ERR::ErrorStringBounds(chars_len, index, idx_pos)
|
||||||
})?,
|
})?,
|
||||||
offset,
|
offset,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
let chars_len = s.chars().count();
|
let chars_len = s.chars().count();
|
||||||
return Err(ERR::ErrorStringBounds(chars_len, index, pos).into());
|
return Err(ERR::ErrorStringBounds(chars_len, index, idx_pos).into());
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Target::StringChar {
|
Ok(Target::StringChar {
|
||||||
|
@ -327,8 +327,7 @@ impl Engine {
|
|||||||
Expr::Unit(..) => Ok(Dynamic::UNIT),
|
Expr::Unit(..) => Ok(Dynamic::UNIT),
|
||||||
|
|
||||||
// `... ${...} ...`
|
// `... ${...} ...`
|
||||||
Expr::InterpolatedString(x, pos) => {
|
Expr::InterpolatedString(x, _) => {
|
||||||
let mut pos = *pos;
|
|
||||||
let mut concat: Dynamic = self.const_empty_string().into();
|
let mut concat: Dynamic = self.const_empty_string().into();
|
||||||
let mut result = Ok(Dynamic::UNIT);
|
let mut result = Ok(Dynamic::UNIT);
|
||||||
|
|
||||||
@ -347,7 +346,7 @@ impl Engine {
|
|||||||
state,
|
state,
|
||||||
lib,
|
lib,
|
||||||
Some(OpAssignment::new(OP_CONCAT)),
|
Some(OpAssignment::new(OP_CONCAT)),
|
||||||
pos,
|
expr.start_position(),
|
||||||
&mut (&mut concat).into(),
|
&mut (&mut concat).into(),
|
||||||
("", Position::NONE),
|
("", Position::NONE),
|
||||||
item,
|
item,
|
||||||
@ -356,8 +355,6 @@ impl Engine {
|
|||||||
result = Err(err.fill_position(expr.start_position()));
|
result = Err(err.fill_position(expr.start_position()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = expr.start_position();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result.map(|_| concat)
|
result.map(|_| concat)
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
use crate::ast::Ident;
|
use crate::ast::Ident;
|
||||||
use crate::tokenizer::Token;
|
use crate::tokenizer::Token;
|
||||||
use crate::StaticVec;
|
use crate::{Position, StaticVec};
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
use std::{
|
use std::{
|
||||||
@ -114,4 +114,12 @@ impl Namespace {
|
|||||||
pub(crate) fn set_index(&mut self, index: Option<NonZeroUsize>) {
|
pub(crate) fn set_index(&mut self, index: Option<NonZeroUsize>) {
|
||||||
self.index = index
|
self.index = index
|
||||||
}
|
}
|
||||||
|
/// Get the [position][Position] of this [`NameSpace`].
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if the path is empty.
|
||||||
|
pub fn position(&self) -> Position {
|
||||||
|
self.path[0].pos
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -940,7 +940,7 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, chaining: bool) {
|
|||||||
while n < x.len() - 1 {
|
while n < x.len() - 1 {
|
||||||
match (mem::take(&mut x[n]), mem::take(&mut x[n+1])) {
|
match (mem::take(&mut x[n]), mem::take(&mut x[n+1])) {
|
||||||
(Expr::StringConstant(mut s1, pos), Expr::StringConstant(s2, ..)) => { s1 += s2; x[n] = Expr::StringConstant(s1, pos); x.remove(n+1); state.set_dirty(); }
|
(Expr::StringConstant(mut s1, pos), Expr::StringConstant(s2, ..)) => { s1 += s2; x[n] = Expr::StringConstant(s1, pos); x.remove(n+1); state.set_dirty(); }
|
||||||
(expr1, Expr::Unit(..)) => { x[n] = expr1; x.remove(n+1); state.set_dirty(); }
|
(expr1, Expr::Unit(..)) => { x[n] = expr1; x.remove(n+1); state.set_dirty(); }
|
||||||
(Expr::Unit(..), expr2) => { x[n+1] = expr2; x.remove(n); state.set_dirty(); }
|
(Expr::Unit(..), expr2) => { x[n+1] = expr2; x.remove(n); state.set_dirty(); }
|
||||||
(expr1, Expr::StringConstant(s, ..)) if s.is_empty() => { x[n] = expr1; x.remove(n+1); state.set_dirty(); }
|
(expr1, Expr::StringConstant(s, ..)) if s.is_empty() => { x[n] = expr1; x.remove(n+1); state.set_dirty(); }
|
||||||
(Expr::StringConstant(s, ..), expr2) if s.is_empty()=> { x[n+1] = expr2; x.remove(n); state.set_dirty(); }
|
(Expr::StringConstant(s, ..), expr2) if s.is_empty()=> { x[n+1] = expr2; x.remove(n); state.set_dirty(); }
|
||||||
|
@ -1291,8 +1291,9 @@ fn parse_primary(
|
|||||||
let mut segments = StaticVec::<Expr>::new();
|
let mut segments = StaticVec::<Expr>::new();
|
||||||
|
|
||||||
match input.next().expect(NEVER_ENDS) {
|
match input.next().expect(NEVER_ENDS) {
|
||||||
|
(Token::InterpolatedString(s), ..) if s.is_empty() => (),
|
||||||
(Token::InterpolatedString(s), pos) => {
|
(Token::InterpolatedString(s), pos) => {
|
||||||
segments.push(Expr::StringConstant(s.into(), pos));
|
segments.push(Expr::StringConstant(s.into(), pos))
|
||||||
}
|
}
|
||||||
token => unreachable!("Token::InterpolatedString expected but gets {:?}", token),
|
token => unreachable!("Token::InterpolatedString expected but gets {:?}", token),
|
||||||
}
|
}
|
||||||
@ -1302,7 +1303,10 @@ fn parse_primary(
|
|||||||
block @ Stmt::Block(..) => Expr::Stmt(Box::new(block.into())),
|
block @ Stmt::Block(..) => Expr::Stmt(Box::new(block.into())),
|
||||||
stmt => unreachable!("Stmt::Block expected but gets {:?}", stmt),
|
stmt => unreachable!("Stmt::Block expected but gets {:?}", stmt),
|
||||||
};
|
};
|
||||||
segments.push(expr);
|
match expr {
|
||||||
|
Expr::StringConstant(s, ..) if s.is_empty() => (),
|
||||||
|
_ => segments.push(expr),
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure to parse the following as text
|
// Make sure to parse the following as text
|
||||||
let mut control = state.tokenizer_control.get();
|
let mut control = state.tokenizer_control.get();
|
||||||
@ -1332,6 +1336,12 @@ fn parse_primary(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if segments.is_empty() {
|
||||||
|
segments.push(Expr::StringConstant(
|
||||||
|
state.get_interned_string("", ""),
|
||||||
|
settings.pos,
|
||||||
|
));
|
||||||
|
}
|
||||||
segments.shrink_to_fit();
|
segments.shrink_to_fit();
|
||||||
Expr::InterpolatedString(segments.into(), settings.pos)
|
Expr::InterpolatedString(segments.into(), settings.pos)
|
||||||
}
|
}
|
||||||
|
@ -257,16 +257,19 @@ impl fmt::Display for Position {
|
|||||||
|
|
||||||
impl fmt::Debug for Position {
|
impl fmt::Debug for Position {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
#[cfg(not(feature = "no_position"))]
|
if self.is_none() {
|
||||||
if self.is_beginning_of_line() {
|
f.write_str("none")
|
||||||
write!(f, "{}", self.line)?;
|
|
||||||
} else {
|
} else {
|
||||||
write!(f, "{}:{}", self.line, self.pos)?;
|
#[cfg(not(feature = "no_position"))]
|
||||||
}
|
if self.is_beginning_of_line() {
|
||||||
#[cfg(feature = "no_position")]
|
write!(f, "{}", self.line)
|
||||||
f.write_str("none")?;
|
} else {
|
||||||
|
write!(f, "{}:{}", self.line, self.pos)
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
#[cfg(feature = "no_position")]
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user