Add Span.
This commit is contained in:
parent
c64fc6f523
commit
3b9dbd5fce
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use super::{ASTNode, BinaryExpr, Expr, FnCallExpr, Ident, OptionFlags, AST_OPTION_FLAGS::*};
|
use super::{ASTNode, BinaryExpr, Expr, FnCallExpr, Ident, OptionFlags, AST_OPTION_FLAGS::*};
|
||||||
use crate::engine::KEYWORD_EVAL;
|
use crate::engine::KEYWORD_EVAL;
|
||||||
use crate::tokenizer::Token;
|
use crate::tokenizer::{Span, Token};
|
||||||
use crate::{calc_fn_hash, Position, StaticVec, INT};
|
use crate::{calc_fn_hash, Position, StaticVec, INT};
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
@ -134,7 +134,7 @@ pub struct TryCatchBlock {
|
|||||||
/// _(internals)_ A scoped block of statements.
|
/// _(internals)_ A scoped block of statements.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
#[derive(Clone, Hash, Default)]
|
#[derive(Clone, Hash, Default)]
|
||||||
pub struct StmtBlock(StaticVec<Stmt>, (Position, Position));
|
pub struct StmtBlock(StaticVec<Stmt>, Span);
|
||||||
|
|
||||||
impl StmtBlock {
|
impl StmtBlock {
|
||||||
/// A [`StmtBlock`] that does not exist.
|
/// A [`StmtBlock`] that does not exist.
|
||||||
@ -149,13 +149,13 @@ impl StmtBlock {
|
|||||||
) -> Self {
|
) -> Self {
|
||||||
let mut statements: StaticVec<_> = statements.into_iter().collect();
|
let mut statements: StaticVec<_> = statements.into_iter().collect();
|
||||||
statements.shrink_to_fit();
|
statements.shrink_to_fit();
|
||||||
Self(statements, (start_pos, end_pos))
|
Self(statements, Span::new(start_pos, end_pos))
|
||||||
}
|
}
|
||||||
/// Create an empty [`StmtBlock`].
|
/// Create an empty [`StmtBlock`].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn empty(pos: Position) -> Self {
|
pub const fn empty(pos: Position) -> Self {
|
||||||
Self(StaticVec::new_const(), (pos, pos))
|
Self(StaticVec::new_const(), Span::new(pos, pos))
|
||||||
}
|
}
|
||||||
/// Is this statements block empty?
|
/// Is this statements block empty?
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@ -191,38 +191,34 @@ impl StmtBlock {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn position(&self) -> Position {
|
pub const fn position(&self) -> Position {
|
||||||
(self.1).0
|
(self.1).start()
|
||||||
}
|
}
|
||||||
/// Get the end position (location of the ending `}`) of this statements block.
|
/// Get the end position (location of the ending `}`) of this statements block.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn end_position(&self) -> Position {
|
pub const fn end_position(&self) -> Position {
|
||||||
(self.1).1
|
(self.1).end()
|
||||||
}
|
}
|
||||||
/// Get the positions (locations of the beginning `{` and ending `}`) of this statements block.
|
/// Get the positions (locations of the beginning `{` and ending `}`) of this statements block.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn positions(&self) -> (Position, Position) {
|
pub const fn span(&self) -> Span {
|
||||||
self.1
|
self.1
|
||||||
}
|
}
|
||||||
/// Get the positions (locations of the beginning `{` and ending `}`) of this statements block
|
/// Get the positions (locations of the beginning `{` and ending `}`) of this statements block
|
||||||
/// or a default.
|
/// or a default.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn positions_or_else(
|
pub const fn span_or_else(&self, def_start_pos: Position, def_end_pos: Position) -> Span {
|
||||||
&self,
|
Span::new(
|
||||||
def_start_pos: Position,
|
(self.1).start().or_else(def_start_pos),
|
||||||
def_end_pos: Position,
|
(self.1).end().or_else(def_end_pos),
|
||||||
) -> (Position, Position) {
|
|
||||||
(
|
|
||||||
(self.1).0.or_else(def_start_pos),
|
|
||||||
(self.1).1.or_else(def_end_pos),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/// Set the positions of this statements block.
|
/// Set the positions of this statements block.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn set_position(&mut self, start_pos: Position, end_pos: Position) {
|
pub fn set_position(&mut self, start_pos: Position, end_pos: Position) {
|
||||||
self.1 = (start_pos, end_pos);
|
self.1 = Span::new(start_pos, end_pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,10 +256,8 @@ impl fmt::Debug for StmtBlock {
|
|||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
f.write_str("Block")?;
|
f.write_str("Block")?;
|
||||||
fmt::Debug::fmt(&self.0, f)?;
|
fmt::Debug::fmt(&self.0, f)?;
|
||||||
(self.1).0.debug_print(f)?;
|
if !self.1.is_none() {
|
||||||
#[cfg(not(feature = "no_position"))]
|
write!(f, " @ {:?}", self.1)?;
|
||||||
if !(self.1).1.is_none() {
|
|
||||||
write!(f, "-{:?}", (self.1).1)?;
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -273,11 +267,11 @@ impl From<Stmt> for StmtBlock {
|
|||||||
#[inline]
|
#[inline]
|
||||||
fn from(stmt: Stmt) -> Self {
|
fn from(stmt: Stmt) -> Self {
|
||||||
match stmt {
|
match stmt {
|
||||||
Stmt::Block(mut block, pos) => Self(block.iter_mut().map(mem::take).collect(), pos),
|
Stmt::Block(mut block, span) => Self(block.iter_mut().map(mem::take).collect(), span),
|
||||||
Stmt::Noop(pos) => Self(StaticVec::new_const(), (pos, pos)),
|
Stmt::Noop(pos) => Self(StaticVec::new_const(), Span::new(pos, pos)),
|
||||||
_ => {
|
_ => {
|
||||||
let pos = stmt.position();
|
let pos = stmt.position();
|
||||||
Self(vec![stmt].into(), (pos, Position::NONE))
|
Self(vec![stmt].into(), Span::new(pos, Position::NONE))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -344,7 +338,7 @@ pub enum Stmt {
|
|||||||
/// function call forming one statement.
|
/// function call forming one statement.
|
||||||
FnCall(Box<FnCallExpr>, Position),
|
FnCall(Box<FnCallExpr>, Position),
|
||||||
/// `{` stmt`;` ... `}`
|
/// `{` stmt`;` ... `}`
|
||||||
Block(Box<[Stmt]>, (Position, Position)),
|
Block(Box<[Stmt]>, Span),
|
||||||
/// `try` `{` stmt; ... `}` `catch` `(` var `)` `{` stmt; ... `}`
|
/// `try` `{` stmt; ... `}` `catch` `(` var `)` `{` stmt; ... `}`
|
||||||
TryCatch(Box<TryCatchBlock>, Position),
|
TryCatch(Box<TryCatchBlock>, Position),
|
||||||
/// [expression][Expr]
|
/// [expression][Expr]
|
||||||
@ -412,7 +406,6 @@ impl Stmt {
|
|||||||
match self {
|
match self {
|
||||||
Self::Noop(pos)
|
Self::Noop(pos)
|
||||||
| Self::BreakLoop(.., pos)
|
| Self::BreakLoop(.., pos)
|
||||||
| Self::Block(.., (pos, ..))
|
|
||||||
| Self::Assignment(.., pos)
|
| Self::Assignment(.., pos)
|
||||||
| Self::FnCall(.., pos)
|
| Self::FnCall(.., pos)
|
||||||
| Self::If(.., pos)
|
| Self::If(.., pos)
|
||||||
@ -424,6 +417,8 @@ impl Stmt {
|
|||||||
| Self::Var(.., pos)
|
| Self::Var(.., pos)
|
||||||
| Self::TryCatch(.., pos) => *pos,
|
| Self::TryCatch(.., pos) => *pos,
|
||||||
|
|
||||||
|
Self::Block(.., span) => span.start(),
|
||||||
|
|
||||||
Self::Expr(x) => x.start_position(),
|
Self::Expr(x) => x.start_position(),
|
||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
@ -440,7 +435,6 @@ impl Stmt {
|
|||||||
match self {
|
match self {
|
||||||
Self::Noop(pos)
|
Self::Noop(pos)
|
||||||
| Self::BreakLoop(.., pos)
|
| Self::BreakLoop(.., pos)
|
||||||
| Self::Block(.., (pos, ..))
|
|
||||||
| Self::Assignment(.., pos)
|
| Self::Assignment(.., pos)
|
||||||
| Self::FnCall(.., pos)
|
| Self::FnCall(.., pos)
|
||||||
| Self::If(.., pos)
|
| Self::If(.., pos)
|
||||||
@ -452,6 +446,8 @@ impl Stmt {
|
|||||||
| Self::Var(.., pos)
|
| Self::Var(.., pos)
|
||||||
| Self::TryCatch(.., pos) => *pos = new_pos,
|
| Self::TryCatch(.., pos) => *pos = new_pos,
|
||||||
|
|
||||||
|
Self::Block(.., span) => *span = Span::new(new_pos, span.end()),
|
||||||
|
|
||||||
Self::Expr(x) => {
|
Self::Expr(x) => {
|
||||||
x.set_position(new_pos);
|
x.set_position(new_pos);
|
||||||
}
|
}
|
||||||
|
@ -247,7 +247,7 @@ pub use tokenizer::{get_next_token, parse_string_literal};
|
|||||||
|
|
||||||
#[cfg(feature = "internals")]
|
#[cfg(feature = "internals")]
|
||||||
pub use tokenizer::{
|
pub use tokenizer::{
|
||||||
InputStream, MultiInputsStream, Token, TokenIterator, TokenizeState, TokenizerControl,
|
InputStream, MultiInputsStream, Span, Token, TokenIterator, TokenizeState, TokenizerControl,
|
||||||
TokenizerControlBlock,
|
TokenizerControlBlock,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ use crate::engine::{KEYWORD_DEBUG, KEYWORD_EVAL, KEYWORD_FN_PTR, KEYWORD_PRINT,
|
|||||||
use crate::eval::{EvalState, GlobalRuntimeState};
|
use crate::eval::{EvalState, GlobalRuntimeState};
|
||||||
use crate::func::builtin::get_builtin_binary_op_fn;
|
use crate::func::builtin::get_builtin_binary_op_fn;
|
||||||
use crate::func::hashing::get_hasher;
|
use crate::func::hashing::get_hasher;
|
||||||
use crate::tokenizer::Token;
|
use crate::tokenizer::{Span, Token};
|
||||||
use crate::types::dynamic::AccessMode;
|
use crate::types::dynamic::AccessMode;
|
||||||
use crate::{
|
use crate::{
|
||||||
calc_fn_hash, calc_fn_params_hash, combine_hashes, Dynamic, Engine, FnPtr, Position, Scope,
|
calc_fn_hash, calc_fn_params_hash, combine_hashes, Dynamic, Engine, FnPtr, Position, Scope,
|
||||||
@ -471,7 +471,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
|||||||
// -> { expr, Noop }
|
// -> { expr, Noop }
|
||||||
Stmt::Block(
|
Stmt::Block(
|
||||||
[Stmt::Expr(expr), Stmt::Noop(pos)].into(),
|
[Stmt::Expr(expr), Stmt::Noop(pos)].into(),
|
||||||
(pos, Position::NONE),
|
Span::new(pos, Position::NONE),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// -> expr
|
// -> expr
|
||||||
@ -490,7 +490,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
|||||||
match optimize_stmt_block(mem::take(&mut *x.1), state, preserve_result, true, false)
|
match optimize_stmt_block(mem::take(&mut *x.1), state, preserve_result, true, false)
|
||||||
{
|
{
|
||||||
statements if statements.is_empty() => Stmt::Noop(x.1.position()),
|
statements if statements.is_empty() => Stmt::Noop(x.1.position()),
|
||||||
statements => Stmt::Block(statements.into_boxed_slice(), x.1.positions()),
|
statements => Stmt::Block(statements.into_boxed_slice(), x.1.span()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if true { if_block } else { else_block } -> if_block
|
// if true { if_block } else { else_block } -> if_block
|
||||||
@ -500,7 +500,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
|||||||
match optimize_stmt_block(mem::take(&mut *x.0), state, preserve_result, true, false)
|
match optimize_stmt_block(mem::take(&mut *x.0), state, preserve_result, true, false)
|
||||||
{
|
{
|
||||||
statements if statements.is_empty() => Stmt::Noop(x.0.position()),
|
statements if statements.is_empty() => Stmt::Noop(x.0.position()),
|
||||||
statements => Stmt::Block(statements.into_boxed_slice(), x.0.positions()),
|
statements => Stmt::Block(statements.into_boxed_slice(), x.0.span()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if expr { if_block } else { else_block }
|
// if expr { if_block } else { else_block }
|
||||||
@ -534,7 +534,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
|||||||
mem::take(&mut block.statements),
|
mem::take(&mut block.statements),
|
||||||
Stmt::Block(
|
Stmt::Block(
|
||||||
def_stmt.into_boxed_slice(),
|
def_stmt.into_boxed_slice(),
|
||||||
x.def_case.positions_or_else(*pos, Position::NONE),
|
x.def_case.span_or_else(*pos, Position::NONE),
|
||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
)),
|
)),
|
||||||
@ -549,8 +549,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
|||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
*stmt =
|
*stmt = Stmt::Block(statements.into_boxed_slice(), block.statements.span());
|
||||||
Stmt::Block(statements.into_boxed_slice(), block.statements.positions());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
state.set_dirty();
|
state.set_dirty();
|
||||||
@ -590,7 +589,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
|||||||
mem::take(&mut block.statements),
|
mem::take(&mut block.statements),
|
||||||
Stmt::Block(
|
Stmt::Block(
|
||||||
def_stmt.into_boxed_slice(),
|
def_stmt.into_boxed_slice(),
|
||||||
x.def_case.positions_or_else(*pos, Position::NONE),
|
x.def_case.span_or_else(*pos, Position::NONE),
|
||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
)),
|
)),
|
||||||
@ -601,10 +600,8 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
|||||||
let statements = mem::take(&mut *block.statements);
|
let statements = mem::take(&mut *block.statements);
|
||||||
let statements =
|
let statements =
|
||||||
optimize_stmt_block(statements, state, true, true, false);
|
optimize_stmt_block(statements, state, true, true, false);
|
||||||
*stmt = Stmt::Block(
|
*stmt =
|
||||||
statements.into_boxed_slice(),
|
Stmt::Block(statements.into_boxed_slice(), block.statements.span());
|
||||||
block.statements.positions(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
state.set_dirty();
|
state.set_dirty();
|
||||||
@ -651,7 +648,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
|||||||
optimize_stmt_block(mem::take(&mut x.def_case), state, true, true, false);
|
optimize_stmt_block(mem::take(&mut x.def_case), state, true, true, false);
|
||||||
*stmt = Stmt::Block(
|
*stmt = Stmt::Block(
|
||||||
def_stmt.into_boxed_slice(),
|
def_stmt.into_boxed_slice(),
|
||||||
x.def_case.positions_or_else(*pos, Position::NONE),
|
x.def_case.span_or_else(*pos, Position::NONE),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// switch
|
// switch
|
||||||
@ -708,8 +705,10 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
|||||||
if preserve_result {
|
if preserve_result {
|
||||||
statements.push(Stmt::Noop(pos))
|
statements.push(Stmt::Noop(pos))
|
||||||
}
|
}
|
||||||
*stmt =
|
*stmt = Stmt::Block(
|
||||||
Stmt::Block(statements.into_boxed_slice(), (pos, Position::NONE));
|
statements.into_boxed_slice(),
|
||||||
|
Span::new(pos, Position::NONE),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
*stmt = Stmt::Noop(pos);
|
*stmt = Stmt::Noop(pos);
|
||||||
};
|
};
|
||||||
@ -726,7 +725,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
|||||||
*stmt = Stmt::Block(
|
*stmt = Stmt::Block(
|
||||||
optimize_stmt_block(mem::take(&mut **body), state, false, true, false)
|
optimize_stmt_block(mem::take(&mut **body), state, false, true, false)
|
||||||
.into_boxed_slice(),
|
.into_boxed_slice(),
|
||||||
body.positions(),
|
body.span(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// do { block } while|until expr
|
// do { block } while|until expr
|
||||||
@ -747,21 +746,21 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
|||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
Stmt::Import(expr, ..) => optimize_expr(expr, state, false),
|
Stmt::Import(expr, ..) => optimize_expr(expr, state, false),
|
||||||
// { block }
|
// { block }
|
||||||
Stmt::Block(statements, pos) => {
|
Stmt::Block(statements, span) => {
|
||||||
let statements = mem::take(statements).into_vec().into();
|
let statements = mem::take(statements).into_vec().into();
|
||||||
let mut block = optimize_stmt_block(statements, state, preserve_result, true, false);
|
let mut block = optimize_stmt_block(statements, state, preserve_result, true, false);
|
||||||
|
|
||||||
match block.as_mut_slice() {
|
match block.as_mut_slice() {
|
||||||
[] => {
|
[] => {
|
||||||
state.set_dirty();
|
state.set_dirty();
|
||||||
*stmt = Stmt::Noop(pos.0);
|
*stmt = Stmt::Noop(span.start());
|
||||||
}
|
}
|
||||||
// Only one statement which is not block-dependent - promote
|
// Only one statement which is not block-dependent - promote
|
||||||
[s] if !s.is_block_dependent() => {
|
[s] if !s.is_block_dependent() => {
|
||||||
state.set_dirty();
|
state.set_dirty();
|
||||||
*stmt = mem::take(s);
|
*stmt = mem::take(s);
|
||||||
}
|
}
|
||||||
_ => *stmt = Stmt::Block(block.into_boxed_slice(), *pos),
|
_ => *stmt = Stmt::Block(block.into_boxed_slice(), *span),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// try { pure try_block } catch ( var ) { catch_block } -> try_block
|
// try { pure try_block } catch ( var ) { catch_block } -> try_block
|
||||||
@ -771,7 +770,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
|||||||
*stmt = Stmt::Block(
|
*stmt = Stmt::Block(
|
||||||
optimize_stmt_block(mem::take(&mut *x.try_block), state, false, true, false)
|
optimize_stmt_block(mem::take(&mut *x.try_block), state, false, true, false)
|
||||||
.into_boxed_slice(),
|
.into_boxed_slice(),
|
||||||
x.try_block.positions(),
|
x.try_block.span(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// try { try_block } catch ( var ) { catch_block }
|
// try { try_block } catch ( var ) { catch_block }
|
||||||
|
@ -9,7 +9,7 @@ use crate::ast::{
|
|||||||
use crate::engine::{Precedence, KEYWORD_THIS, OP_CONTAINS};
|
use crate::engine::{Precedence, KEYWORD_THIS, OP_CONTAINS};
|
||||||
use crate::func::hashing::get_hasher;
|
use crate::func::hashing::get_hasher;
|
||||||
use crate::tokenizer::{
|
use crate::tokenizer::{
|
||||||
is_keyword_function, is_valid_function_name, is_valid_identifier, Token, TokenStream,
|
is_keyword_function, is_valid_function_name, is_valid_identifier, Span, Token, TokenStream,
|
||||||
TokenizerControl,
|
TokenizerControl,
|
||||||
};
|
};
|
||||||
use crate::types::dynamic::AccessMode;
|
use crate::types::dynamic::AccessMode;
|
||||||
@ -2818,7 +2818,7 @@ fn parse_block(
|
|||||||
|
|
||||||
Ok(Stmt::Block(
|
Ok(Stmt::Block(
|
||||||
statements.into_boxed_slice(),
|
statements.into_boxed_slice(),
|
||||||
(settings.pos, end_pos),
|
Span::new(settings.pos, end_pos),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,10 +59,10 @@ pub type TokenStream<'a> = Peekable<TokenIterator<'a>>;
|
|||||||
/// Advancing beyond the maximum line length or maximum number of lines is not an error but has no effect.
|
/// Advancing beyond the maximum line length or maximum number of lines is not an error but has no effect.
|
||||||
#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)]
|
#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)]
|
||||||
pub struct Position {
|
pub struct Position {
|
||||||
/// Line number - 0 = none
|
/// Line number: 0 = none
|
||||||
#[cfg(not(feature = "no_position"))]
|
#[cfg(not(feature = "no_position"))]
|
||||||
line: u16,
|
line: u16,
|
||||||
/// Character position - 0 = BOL
|
/// Character position: 0 = BOL
|
||||||
#[cfg(not(feature = "no_position"))]
|
#[cfg(not(feature = "no_position"))]
|
||||||
pos: u16,
|
pos: u16,
|
||||||
}
|
}
|
||||||
@ -300,6 +300,71 @@ impl AddAssign for Position {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// _(internals)_ A span consisting of a starting and an ending [positions][Position].
|
||||||
|
/// Exported under the `internals` feature only.
|
||||||
|
#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy, Default)]
|
||||||
|
pub struct Span {
|
||||||
|
/// Starting [position][Position].
|
||||||
|
start: Position,
|
||||||
|
/// Ending [position][Position].
|
||||||
|
end: Position,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Span {
|
||||||
|
pub const NONE: Self = Self::new(Position::NONE, Position::NONE);
|
||||||
|
|
||||||
|
/// Create a new [`Span`].
|
||||||
|
#[inline(always)]
|
||||||
|
#[must_use]
|
||||||
|
pub const fn new(start: Position, end: Position) -> Self {
|
||||||
|
Self { start, end }
|
||||||
|
}
|
||||||
|
/// Is this [`Span`] non-existent?
|
||||||
|
#[inline(always)]
|
||||||
|
#[must_use]
|
||||||
|
pub const fn is_none(&self) -> bool {
|
||||||
|
self.start.is_none() && self.end.is_none()
|
||||||
|
}
|
||||||
|
/// Get the [`Span`]'s starting [position][Position].
|
||||||
|
#[inline(always)]
|
||||||
|
#[must_use]
|
||||||
|
pub const fn start(&self) -> Position {
|
||||||
|
self.start
|
||||||
|
}
|
||||||
|
/// Get the [`Span`]'s ending [position][Position].
|
||||||
|
#[inline(always)]
|
||||||
|
#[must_use]
|
||||||
|
pub const fn end(&self) -> Position {
|
||||||
|
self.end
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Span {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match (self.start().is_none(), self.end().is_none()) {
|
||||||
|
(false, false) if self.start().line() != self.end().line() => {
|
||||||
|
write!(f, "{:?}-{:?}", self.start(), self.end())
|
||||||
|
}
|
||||||
|
(false, false) => write!(
|
||||||
|
f,
|
||||||
|
"{}:{}-{}",
|
||||||
|
self.start().line().unwrap(),
|
||||||
|
self.start().position().unwrap_or(0),
|
||||||
|
self.end().position().unwrap_or(0)
|
||||||
|
),
|
||||||
|
(true, false) => write!(f, "..{:?}", self.end()),
|
||||||
|
(false, true) => write!(f, "{:?}", self.start()),
|
||||||
|
(true, true) => write!(f, "{:?}", Position::NONE),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for Span {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
fmt::Display::fmt(self, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// _(internals)_ A Rhai language token.
|
/// _(internals)_ A Rhai language token.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
#[derive(Debug, PartialEq, Clone, Hash)]
|
#[derive(Debug, PartialEq, Clone, Hash)]
|
||||||
|
Loading…
Reference in New Issue
Block a user