mirror of
https://github.com/typst/typst
synced 2025-06-28 00:03:17 +08:00
Make values hashable
This commit is contained in:
parent
c7a9bac992
commit
91e45458e3
@ -20,7 +20,7 @@ macro_rules! array {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// An array of values with clone-on-write value semantics.
|
/// An array of values with clone-on-write value semantics.
|
||||||
#[derive(Default, Clone, PartialEq)]
|
#[derive(Default, Clone, PartialEq, Hash)]
|
||||||
pub struct Array(Arc<Vec<Value>>);
|
pub struct Array(Arc<Vec<Value>>);
|
||||||
|
|
||||||
impl Array {
|
impl Array {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use std::fmt::{self, Debug, Formatter, Write};
|
use std::fmt::{self, Debug, Formatter, Write};
|
||||||
|
use std::hash::{Hash, Hasher};
|
||||||
|
|
||||||
use super::{Args, EvalContext, Func, StyleMap, Template, Value};
|
use super::{Args, EvalContext, Func, StyleMap, Template, Value};
|
||||||
use crate::diag::TypResult;
|
use crate::diag::TypResult;
|
||||||
@ -103,6 +104,13 @@ impl PartialEq for Class {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Hash for Class {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
(self.construct as usize).hash(state);
|
||||||
|
(self.set as usize).hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Construct an instance of a class.
|
/// Construct an instance of a class.
|
||||||
pub trait Construct {
|
pub trait Construct {
|
||||||
/// Construct an instance of this class from the arguments.
|
/// Construct an instance of this class from the arguments.
|
||||||
|
@ -19,7 +19,7 @@ macro_rules! dict {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A dictionary from strings to values with clone-on-write value semantics.
|
/// A dictionary from strings to values with clone-on-write value semantics.
|
||||||
#[derive(Default, Clone, PartialEq)]
|
#[derive(Default, Clone, PartialEq, Hash)]
|
||||||
pub struct Dict(Arc<BTreeMap<EcoString, Value>>);
|
pub struct Dict(Arc<BTreeMap<EcoString, Value>>);
|
||||||
|
|
||||||
impl Dict {
|
impl Dict {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use std::fmt::{self, Debug, Formatter, Write};
|
use std::fmt::{self, Debug, Formatter, Write};
|
||||||
|
use std::hash::{Hash, Hasher};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use super::{Cast, Eval, EvalContext, Scope, Value};
|
use super::{Cast, Eval, EvalContext, Scope, Value};
|
||||||
@ -8,10 +9,11 @@ use crate::syntax::{Span, Spanned};
|
|||||||
use crate::util::EcoString;
|
use crate::util::EcoString;
|
||||||
|
|
||||||
/// An evaluatable function.
|
/// An evaluatable function.
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Hash)]
|
||||||
pub struct Func(Arc<Repr>);
|
pub struct Func(Arc<Repr>);
|
||||||
|
|
||||||
/// The different kinds of function representations.
|
/// The different kinds of function representations.
|
||||||
|
#[derive(Hash)]
|
||||||
enum Repr {
|
enum Repr {
|
||||||
/// A native rust function.
|
/// A native rust function.
|
||||||
Native(Native),
|
Native(Native),
|
||||||
@ -89,7 +91,14 @@ struct Native {
|
|||||||
pub func: fn(&mut EvalContext, &mut Args) -> TypResult<Value>,
|
pub func: fn(&mut EvalContext, &mut Args) -> TypResult<Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Hash for Native {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
(self.func as usize).hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A user-defined closure.
|
/// A user-defined closure.
|
||||||
|
#[derive(Hash)]
|
||||||
pub struct Closure {
|
pub struct Closure {
|
||||||
/// The name of the closure.
|
/// The name of the closure.
|
||||||
pub name: Option<EcoString>,
|
pub name: Option<EcoString>,
|
||||||
@ -138,7 +147,7 @@ impl Closure {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Evaluated arguments to a function.
|
/// Evaluated arguments to a function.
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq, Hash)]
|
||||||
pub struct Args {
|
pub struct Args {
|
||||||
/// The span of the whole argument list.
|
/// The span of the whole argument list.
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
@ -147,7 +156,7 @@ pub struct Args {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// An argument to a function call: `12` or `draw: false`.
|
/// An argument to a function call: `12` or `draw: false`.
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq, Hash)]
|
||||||
pub struct Arg {
|
pub struct Arg {
|
||||||
/// The span of the whole argument.
|
/// The span of the whole argument.
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
use std::collections::BTreeMap;
|
||||||
use std::fmt::{self, Debug, Formatter};
|
use std::fmt::{self, Debug, Formatter};
|
||||||
|
use std::hash::{Hash, Hasher};
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
@ -68,7 +69,7 @@ impl<'a> Scopes<'a> {
|
|||||||
#[derive(Default, Clone)]
|
#[derive(Default, Clone)]
|
||||||
pub struct Scope {
|
pub struct Scope {
|
||||||
/// The mapping from names to slots.
|
/// The mapping from names to slots.
|
||||||
values: HashMap<EcoString, Slot>,
|
values: BTreeMap<EcoString, Slot>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Scope {
|
impl Scope {
|
||||||
@ -126,6 +127,16 @@ impl Scope {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Hash for Scope {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
self.values.len().hash(state);
|
||||||
|
for (name, value) in self.values.iter() {
|
||||||
|
name.hash(state);
|
||||||
|
value.borrow().hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Debug for Scope {
|
impl Debug for Scope {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
f.write_str("Scope ")?;
|
f.write_str("Scope ")?;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::fmt::{self, Debug, Formatter};
|
use std::fmt::{self, Debug, Formatter};
|
||||||
use std::hash::Hash;
|
use std::hash::{Hash, Hasher};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use super::{ops, Args, Array, Class, Dict, Func, Template};
|
use super::{ops, Args, Array, Class, Dict, Func, Template};
|
||||||
@ -173,6 +173,33 @@ impl PartialOrd for Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Hash for Value {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
std::mem::discriminant(self).hash(state);
|
||||||
|
match self {
|
||||||
|
Self::None => {}
|
||||||
|
Self::Auto => {}
|
||||||
|
Self::Bool(v) => v.hash(state),
|
||||||
|
Self::Int(v) => v.hash(state),
|
||||||
|
Self::Float(v) => v.to_bits().hash(state),
|
||||||
|
Self::Length(v) => v.hash(state),
|
||||||
|
Self::Angle(v) => v.hash(state),
|
||||||
|
Self::Relative(v) => v.hash(state),
|
||||||
|
Self::Linear(v) => v.hash(state),
|
||||||
|
Self::Fractional(v) => v.hash(state),
|
||||||
|
Self::Color(v) => v.hash(state),
|
||||||
|
Self::Str(v) => v.hash(state),
|
||||||
|
Self::Array(v) => v.hash(state),
|
||||||
|
Self::Dict(v) => v.hash(state),
|
||||||
|
Self::Template(v) => v.hash(state),
|
||||||
|
Self::Func(v) => v.hash(state),
|
||||||
|
Self::Args(v) => v.hash(state),
|
||||||
|
Self::Class(v) => v.hash(state),
|
||||||
|
Self::Dyn(v) => v.hash(state),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<i32> for Value {
|
impl From<i32> for Value {
|
||||||
fn from(v: i32) -> Self {
|
fn from(v: i32) -> Self {
|
||||||
Self::Int(v as i64)
|
Self::Int(v as i64)
|
||||||
@ -210,14 +237,14 @@ impl From<Dynamic> for Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A dynamic value.
|
/// A dynamic value.
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Hash)]
|
||||||
pub struct Dynamic(Arc<dyn Bounds>);
|
pub struct Dynamic(Arc<dyn Bounds>);
|
||||||
|
|
||||||
impl Dynamic {
|
impl Dynamic {
|
||||||
/// Create a new instance from any value that satisifies the required bounds.
|
/// Create a new instance from any value that satisifies the required bounds.
|
||||||
pub fn new<T>(any: T) -> Self
|
pub fn new<T>(any: T) -> Self
|
||||||
where
|
where
|
||||||
T: Type + Debug + PartialEq + Sync + Send + 'static,
|
T: Type + Debug + PartialEq + Hash + Sync + Send + 'static,
|
||||||
{
|
{
|
||||||
Self(Arc::new(any))
|
Self(Arc::new(any))
|
||||||
}
|
}
|
||||||
@ -254,11 +281,12 @@ trait Bounds: Debug + Sync + Send + 'static {
|
|||||||
fn as_any(&self) -> &dyn Any;
|
fn as_any(&self) -> &dyn Any;
|
||||||
fn dyn_eq(&self, other: &Dynamic) -> bool;
|
fn dyn_eq(&self, other: &Dynamic) -> bool;
|
||||||
fn dyn_type_name(&self) -> &'static str;
|
fn dyn_type_name(&self) -> &'static str;
|
||||||
|
fn hash64(&self) -> u64;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Bounds for T
|
impl<T> Bounds for T
|
||||||
where
|
where
|
||||||
T: Type + Debug + PartialEq + Sync + Send + 'static,
|
T: Type + Debug + PartialEq + Hash + Sync + Send + 'static,
|
||||||
{
|
{
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
self
|
self
|
||||||
@ -275,6 +303,21 @@ where
|
|||||||
fn dyn_type_name(&self) -> &'static str {
|
fn dyn_type_name(&self) -> &'static str {
|
||||||
T::TYPE_NAME
|
T::TYPE_NAME
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn hash64(&self) -> u64 {
|
||||||
|
// Also hash the TypeId since nodes with different types but
|
||||||
|
// equal data should be different.
|
||||||
|
let mut state = fxhash::FxHasher64::default();
|
||||||
|
self.type_id().hash(&mut state);
|
||||||
|
self.hash(&mut state);
|
||||||
|
state.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hash for dyn Bounds {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
state.write_u64(self.hash64());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The type of a value.
|
/// The type of a value.
|
||||||
|
@ -123,7 +123,7 @@ impl Sum for Angle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Different units of angular measurement.
|
/// Different units of angular measurement.
|
||||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
pub enum AngularUnit {
|
pub enum AngularUnit {
|
||||||
/// Radians.
|
/// Radians.
|
||||||
Rad,
|
Rad,
|
||||||
|
@ -211,7 +211,7 @@ impl<'a> Sum<&'a Self> for Length {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Different units of length measurement.
|
/// Different units of length measurement.
|
||||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
pub enum LengthUnit {
|
pub enum LengthUnit {
|
||||||
/// Points.
|
/// Points.
|
||||||
Pt,
|
Pt,
|
||||||
|
@ -30,7 +30,7 @@ macro_rules! node {
|
|||||||
node!{$(#[$attr])* $name: NodeKind::$variant}
|
node!{$(#[$attr])* $name: NodeKind::$variant}
|
||||||
};
|
};
|
||||||
($(#[$attr:meta])* $name:ident: $variants:pat) => {
|
($(#[$attr:meta])* $name:ident: $variants:pat) => {
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq, Hash)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
$(#[$attr])*
|
$(#[$attr])*
|
||||||
pub struct $name(RedNode);
|
pub struct $name(RedNode);
|
||||||
@ -138,7 +138,7 @@ impl EmphNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A raw block with optional syntax highlighting: `` `...` ``.
|
/// A raw block with optional syntax highlighting: `` `...` ``.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq, Hash)]
|
||||||
pub struct RawNode {
|
pub struct RawNode {
|
||||||
/// An optional identifier specifying the language to syntax-highlight in.
|
/// An optional identifier specifying the language to syntax-highlight in.
|
||||||
pub lang: Option<EcoString>,
|
pub lang: Option<EcoString>,
|
||||||
@ -151,7 +151,7 @@ pub struct RawNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A math formula: `$a^2 + b^2 = c^2$`.
|
/// A math formula: `$a^2 + b^2 = c^2$`.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq, Hash)]
|
||||||
pub struct MathNode {
|
pub struct MathNode {
|
||||||
/// The formula between the dollars / brackets.
|
/// The formula between the dollars / brackets.
|
||||||
pub formula: EcoString,
|
pub formula: EcoString,
|
||||||
@ -213,7 +213,7 @@ impl EnumNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// An expression.
|
/// An expression.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq, Hash)]
|
||||||
pub enum Expr {
|
pub enum Expr {
|
||||||
/// A literal: `1`, `true`, ...
|
/// A literal: `1`, `true`, ...
|
||||||
Lit(Lit),
|
Lit(Lit),
|
||||||
@ -504,7 +504,7 @@ impl UnaryExpr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A unary operator.
|
/// A unary operator.
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
pub enum UnOp {
|
pub enum UnOp {
|
||||||
/// The plus operator: `+`.
|
/// The plus operator: `+`.
|
||||||
Pos,
|
Pos,
|
||||||
@ -573,7 +573,7 @@ impl BinaryExpr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A binary operator.
|
/// A binary operator.
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
pub enum BinOp {
|
pub enum BinOp {
|
||||||
/// The addition operator: `+`.
|
/// The addition operator: `+`.
|
||||||
Add,
|
Add,
|
||||||
@ -707,7 +707,7 @@ impl BinOp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The associativity of a binary operator.
|
/// The associativity of a binary operator.
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
pub enum Associativity {
|
pub enum Associativity {
|
||||||
/// Left-associative: `a + b + c` is equivalent to `(a + b) + c`.
|
/// Left-associative: `a + b + c` is equivalent to `(a + b) + c`.
|
||||||
Left,
|
Left,
|
||||||
@ -745,7 +745,7 @@ impl CallArgs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// An argument to a function call.
|
/// An argument to a function call.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq, Hash)]
|
||||||
pub enum CallArg {
|
pub enum CallArg {
|
||||||
/// A positional argument: `12`.
|
/// A positional argument: `12`.
|
||||||
Pos(Expr),
|
Pos(Expr),
|
||||||
@ -814,7 +814,7 @@ impl ClosureExpr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A parameter to a closure.
|
/// A parameter to a closure.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq, Hash)]
|
||||||
pub enum ClosureParam {
|
pub enum ClosureParam {
|
||||||
/// A positional parameter: `x`.
|
/// A positional parameter: `x`.
|
||||||
Pos(Ident),
|
Pos(Ident),
|
||||||
@ -1059,7 +1059,7 @@ impl ImportExpr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The items that ought to be imported from a file.
|
/// The items that ought to be imported from a file.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq, Hash)]
|
||||||
pub enum Imports {
|
pub enum Imports {
|
||||||
/// All items in the scope of the file should be imported.
|
/// All items in the scope of the file should be imported.
|
||||||
Wildcard,
|
Wildcard,
|
||||||
|
@ -6,6 +6,7 @@ mod pretty;
|
|||||||
mod span;
|
mod span;
|
||||||
|
|
||||||
use std::fmt::{self, Debug, Display, Formatter};
|
use std::fmt::{self, Debug, Display, Formatter};
|
||||||
|
use std::hash::{Hash, Hasher};
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
@ -21,7 +22,7 @@ use crate::source::SourceId;
|
|||||||
use crate::util::EcoString;
|
use crate::util::EcoString;
|
||||||
|
|
||||||
/// An inner or leaf node in the untyped green tree.
|
/// An inner or leaf node in the untyped green tree.
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq, Hash)]
|
||||||
pub enum Green {
|
pub enum Green {
|
||||||
/// A reference-counted inner node.
|
/// A reference-counted inner node.
|
||||||
Node(Arc<GreenNode>),
|
Node(Arc<GreenNode>),
|
||||||
@ -101,7 +102,7 @@ impl Debug for Green {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// An inner node in the untyped green tree.
|
/// An inner node in the untyped green tree.
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq, Hash)]
|
||||||
pub struct GreenNode {
|
pub struct GreenNode {
|
||||||
/// Node metadata.
|
/// Node metadata.
|
||||||
data: GreenData,
|
data: GreenData,
|
||||||
@ -209,7 +210,7 @@ impl Debug for GreenNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Data shared between inner and leaf nodes.
|
/// Data shared between inner and leaf nodes.
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq, Hash)]
|
||||||
pub struct GreenData {
|
pub struct GreenData {
|
||||||
/// What kind of node this is (each kind would have its own struct in a
|
/// What kind of node this is (each kind would have its own struct in a
|
||||||
/// strongly typed AST).
|
/// strongly typed AST).
|
||||||
@ -250,7 +251,7 @@ impl Debug for GreenData {
|
|||||||
/// A owned wrapper for a green node with span information.
|
/// A owned wrapper for a green node with span information.
|
||||||
///
|
///
|
||||||
/// Owned variant of [`RedRef`]. Can be [cast](Self::cast) to an AST node.
|
/// Owned variant of [`RedRef`]. Can be [cast](Self::cast) to an AST node.
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq, Hash)]
|
||||||
pub struct RedNode {
|
pub struct RedNode {
|
||||||
id: SourceId,
|
id: SourceId,
|
||||||
offset: usize,
|
offset: usize,
|
||||||
@ -325,7 +326,7 @@ impl Debug for RedNode {
|
|||||||
/// A borrowed wrapper for a [`GreenNode`] with span information.
|
/// A borrowed wrapper for a [`GreenNode`] with span information.
|
||||||
///
|
///
|
||||||
/// Borrowed variant of [`RedNode`]. Can be [cast](Self::cast) to an AST node.
|
/// Borrowed variant of [`RedNode`]. Can be [cast](Self::cast) to an AST node.
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq, Hash)]
|
||||||
pub struct RedRef<'a> {
|
pub struct RedRef<'a> {
|
||||||
id: SourceId,
|
id: SourceId,
|
||||||
offset: usize,
|
offset: usize,
|
||||||
@ -716,7 +717,7 @@ pub enum NodeKind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Where in a node an error should be annotated.
|
/// Where in a node an error should be annotated.
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum ErrorPos {
|
pub enum ErrorPos {
|
||||||
/// At the start of the node.
|
/// At the start of the node.
|
||||||
Start,
|
Start,
|
||||||
@ -932,3 +933,119 @@ impl Display for NodeKind {
|
|||||||
f.pad(self.as_str())
|
f.pad(self.as_str())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Hash for NodeKind {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
std::mem::discriminant(self).hash(state);
|
||||||
|
match self {
|
||||||
|
Self::LeftBracket => {}
|
||||||
|
Self::RightBracket => {}
|
||||||
|
Self::LeftBrace => {}
|
||||||
|
Self::RightBrace => {}
|
||||||
|
Self::LeftParen => {}
|
||||||
|
Self::RightParen => {}
|
||||||
|
Self::Star => {}
|
||||||
|
Self::Underscore => {}
|
||||||
|
Self::Comma => {}
|
||||||
|
Self::Semicolon => {}
|
||||||
|
Self::Colon => {}
|
||||||
|
Self::Plus => {}
|
||||||
|
Self::Minus => {}
|
||||||
|
Self::Slash => {}
|
||||||
|
Self::Eq => {}
|
||||||
|
Self::EqEq => {}
|
||||||
|
Self::ExclEq => {}
|
||||||
|
Self::Lt => {}
|
||||||
|
Self::LtEq => {}
|
||||||
|
Self::Gt => {}
|
||||||
|
Self::GtEq => {}
|
||||||
|
Self::PlusEq => {}
|
||||||
|
Self::HyphEq => {}
|
||||||
|
Self::StarEq => {}
|
||||||
|
Self::SlashEq => {}
|
||||||
|
Self::Not => {}
|
||||||
|
Self::And => {}
|
||||||
|
Self::Or => {}
|
||||||
|
Self::With => {}
|
||||||
|
Self::Dots => {}
|
||||||
|
Self::Arrow => {}
|
||||||
|
Self::None => {}
|
||||||
|
Self::Auto => {}
|
||||||
|
Self::Let => {}
|
||||||
|
Self::Set => {}
|
||||||
|
Self::Show => {}
|
||||||
|
Self::Wrap => {}
|
||||||
|
Self::If => {}
|
||||||
|
Self::Else => {}
|
||||||
|
Self::For => {}
|
||||||
|
Self::In => {}
|
||||||
|
Self::As => {}
|
||||||
|
Self::While => {}
|
||||||
|
Self::Break => {}
|
||||||
|
Self::Continue => {}
|
||||||
|
Self::Return => {}
|
||||||
|
Self::Import => {}
|
||||||
|
Self::Include => {}
|
||||||
|
Self::From => {}
|
||||||
|
Self::Markup(c) => c.hash(state),
|
||||||
|
Self::Space(n) => n.hash(state),
|
||||||
|
Self::Linebreak => {}
|
||||||
|
Self::Parbreak => {}
|
||||||
|
Self::Text(s) => s.hash(state),
|
||||||
|
Self::TextInLine(s) => s.hash(state),
|
||||||
|
Self::NonBreakingSpace => {}
|
||||||
|
Self::EnDash => {}
|
||||||
|
Self::EmDash => {}
|
||||||
|
Self::Escape(c) => c.hash(state),
|
||||||
|
Self::Strong => {}
|
||||||
|
Self::Emph => {}
|
||||||
|
Self::Raw(raw) => raw.hash(state),
|
||||||
|
Self::Math(math) => math.hash(state),
|
||||||
|
Self::List => {}
|
||||||
|
Self::Heading => {}
|
||||||
|
Self::Enum => {}
|
||||||
|
Self::EnumNumbering(num) => num.hash(state),
|
||||||
|
Self::Ident(v) => v.hash(state),
|
||||||
|
Self::Bool(v) => v.hash(state),
|
||||||
|
Self::Int(v) => v.hash(state),
|
||||||
|
Self::Float(v) => v.to_bits().hash(state),
|
||||||
|
Self::Length(v, u) => (v.to_bits(), u).hash(state),
|
||||||
|
Self::Angle(v, u) => (v.to_bits(), u).hash(state),
|
||||||
|
Self::Percentage(v) => v.to_bits().hash(state),
|
||||||
|
Self::Fraction(v) => v.to_bits().hash(state),
|
||||||
|
Self::Str(v) => v.hash(state),
|
||||||
|
Self::Array => {}
|
||||||
|
Self::Dict => {}
|
||||||
|
Self::Named => {}
|
||||||
|
Self::Template => {}
|
||||||
|
Self::Group => {}
|
||||||
|
Self::Block => {}
|
||||||
|
Self::Unary => {}
|
||||||
|
Self::Binary => {}
|
||||||
|
Self::Call => {}
|
||||||
|
Self::CallArgs => {}
|
||||||
|
Self::Spread => {}
|
||||||
|
Self::Closure => {}
|
||||||
|
Self::ClosureParams => {}
|
||||||
|
Self::WithExpr => {}
|
||||||
|
Self::LetExpr => {}
|
||||||
|
Self::SetExpr => {}
|
||||||
|
Self::ShowExpr => {}
|
||||||
|
Self::WrapExpr => {}
|
||||||
|
Self::IfExpr => {}
|
||||||
|
Self::WhileExpr => {}
|
||||||
|
Self::ForExpr => {}
|
||||||
|
Self::ForPattern => {}
|
||||||
|
Self::ImportExpr => {}
|
||||||
|
Self::ImportItems => {}
|
||||||
|
Self::IncludeExpr => {}
|
||||||
|
Self::BreakExpr => {}
|
||||||
|
Self::ContinueExpr => {}
|
||||||
|
Self::ReturnExpr => {}
|
||||||
|
Self::LineComment => {}
|
||||||
|
Self::BlockComment => {}
|
||||||
|
Self::Error(pos, msg) => (pos, msg).hash(state),
|
||||||
|
Self::Unknown(src) => src.hash(state),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -5,7 +5,7 @@ use std::ops::Range;
|
|||||||
use crate::source::SourceId;
|
use crate::source::SourceId;
|
||||||
|
|
||||||
/// A value with the span it corresponds to in the source code.
|
/// A value with the span it corresponds to in the source code.
|
||||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
pub struct Spanned<T> {
|
pub struct Spanned<T> {
|
||||||
/// The spanned value.
|
/// The spanned value.
|
||||||
pub v: T,
|
pub v: T,
|
||||||
@ -46,7 +46,7 @@ impl<T: Debug> Debug for Spanned<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Bounds of a slice of source code.
|
/// Bounds of a slice of source code.
|
||||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
pub struct Span {
|
pub struct Span {
|
||||||
/// The id of the source file.
|
/// The id of the source file.
|
||||||
pub source: SourceId,
|
pub source: SourceId,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user