more bitwise ops (shl, shr)
This commit is contained in:
parent
515b3c1037
commit
9d279067ad
7 changed files with 175 additions and 33 deletions
27
src/chunk.rs
27
src/chunk.rs
|
|
@ -2,7 +2,7 @@ use tracing::debug;
|
||||||
use crate::value::Value;
|
use crate::value::Value;
|
||||||
use crate::{
|
use crate::{
|
||||||
OP_ADD, OP_BITAND, OP_BITOR, OP_BITXOR, OP_CONSTANT, OP_DIVIDE, OP_FALSE, OP_MULTIPLY,
|
OP_ADD, OP_BITAND, OP_BITOR, OP_BITXOR, OP_CONSTANT, OP_DIVIDE, OP_FALSE, OP_MULTIPLY,
|
||||||
OP_NEGATE, OP_RETURN, OP_SUBTRACT, OP_TRUE,
|
OP_NEGATE, OP_RETURN, OP_SUBTRACT, OP_TRUE, OP_NOT, OP_SHL, OP_SHR
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct Chunk {
|
pub struct Chunk {
|
||||||
|
|
@ -50,16 +50,21 @@ impl Chunk {
|
||||||
}
|
}
|
||||||
let instruction = self.code[offset];
|
let instruction = self.code[offset];
|
||||||
match instruction {
|
match instruction {
|
||||||
OP_CONSTANT => self.constant_inst("OP_CONSTANT", offset),
|
OP_CONSTANT => self.constant_inst("LDC", offset),
|
||||||
OP_ADD => self.simple_inst("OP_ADD", offset),
|
OP_ADD => self.simple_inst("ADD", offset),
|
||||||
OP_FALSE => self.simple_inst("OP_FALSE", offset),
|
OP_FALSE => self.simple_inst("LDC_false", offset),
|
||||||
OP_TRUE => self.simple_inst("OP_TRUE", offset),
|
OP_TRUE => self.simple_inst("LDC_true", offset),
|
||||||
OP_SUBTRACT => self.simple_inst("OP_SUBTRACT", offset),
|
OP_SUBTRACT => self.simple_inst("SUB", offset),
|
||||||
OP_MULTIPLY => self.simple_inst("OP_MULTIPLY", offset),
|
OP_MULTIPLY => self.simple_inst("MUL", offset),
|
||||||
OP_DIVIDE => self.simple_inst("OP_DIVIDE", offset),
|
OP_DIVIDE => self.simple_inst("DIV", offset),
|
||||||
OP_BITAND => self.simple_inst("OP_BITAND", offset),
|
OP_BITAND => self.simple_inst("BITAND", offset),
|
||||||
OP_NEGATE => self.simple_inst("OP_NEGATE", offset),
|
OP_BITOR => self.simple_inst("BITOR", offset),
|
||||||
OP_RETURN => self.simple_inst("OP_RETURN", offset),
|
OP_BITXOR => self.simple_inst("BITXOR", offset),
|
||||||
|
OP_NEGATE => self.simple_inst("NEG", offset),
|
||||||
|
OP_NOT => self.simple_inst("NOT", offset),
|
||||||
|
OP_RETURN => self.simple_inst("RET", offset),
|
||||||
|
OP_SHL => self.simple_inst("SHL", offset),
|
||||||
|
OP_SHR => self.simple_inst("SHR", offset),
|
||||||
_ => {
|
_ => {
|
||||||
println!("Unknown instruction");
|
println!("Unknown instruction");
|
||||||
offset + 1
|
offset + 1
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use crate::chunk::Chunk;
|
||||||
use crate::scanner::scan;
|
use crate::scanner::scan;
|
||||||
use crate::tokens::{Token, TokenType};
|
use crate::tokens::{Token, TokenType};
|
||||||
use crate::value::Value;
|
use crate::value::Value;
|
||||||
use crate::{OP_ADD, OP_BITAND, OP_BITOR, OP_BITXOR, OP_CONSTANT, OP_DIVIDE, OP_FALSE, OP_MULTIPLY, OP_NEGATE, OP_RETURN, OP_SUBTRACT, OP_TRUE};
|
use crate::{OP_ADD, OP_BITAND, OP_BITOR, OP_BITXOR, OP_CONSTANT, OP_DIVIDE, OP_FALSE, OP_MULTIPLY, OP_NEGATE, OP_NOT, OP_RETURN, OP_SHR, OP_SHL, OP_SUBTRACT, OP_TRUE};
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::LazyLock;
|
use std::sync::LazyLock;
|
||||||
|
|
@ -160,7 +160,10 @@ fn unary(s: &mut Compiler) -> anyhow::Result<()> {
|
||||||
TokenType::Minus => {
|
TokenType::Minus => {
|
||||||
s.emit_byte(OP_NEGATE);
|
s.emit_byte(OP_NEGATE);
|
||||||
}
|
}
|
||||||
_ => unimplemented!("unary other than minus"),
|
TokenType::Bang => {
|
||||||
|
s.emit_byte(OP_NOT);
|
||||||
|
}
|
||||||
|
_ => unimplemented!("unary other than ! and -"),
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -178,6 +181,8 @@ fn binary(s: &mut Compiler) -> anyhow::Result<()> {
|
||||||
TokenType::BitAnd => s.emit_byte(OP_BITAND),
|
TokenType::BitAnd => s.emit_byte(OP_BITAND),
|
||||||
TokenType::BitOr => s.emit_byte(OP_BITOR),
|
TokenType::BitOr => s.emit_byte(OP_BITOR),
|
||||||
TokenType::BitXor => s.emit_byte(OP_BITXOR),
|
TokenType::BitXor => s.emit_byte(OP_BITXOR),
|
||||||
|
TokenType::GreaterGreater => s.emit_byte(OP_SHR),
|
||||||
|
TokenType::LessLess => s.emit_byte(OP_SHL),
|
||||||
_ => unimplemented!("binary other than plus, minus, star, slash"),
|
_ => unimplemented!("binary other than plus, minus, star, slash"),
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -209,14 +214,16 @@ static RULES: LazyLock<HashMap<TokenType, Rule>> = LazyLock::new(|| {
|
||||||
rules.insert(TokenType::Colon, Rule::new(None, None, PREC_NONE));
|
rules.insert(TokenType::Colon, Rule::new(None, None, PREC_NONE));
|
||||||
rules.insert(TokenType::Slash, Rule::new(None, Some(binary), PREC_FACTOR));
|
rules.insert(TokenType::Slash, Rule::new(None, Some(binary), PREC_FACTOR));
|
||||||
rules.insert(TokenType::Star, Rule::new(None, Some(binary), PREC_FACTOR));
|
rules.insert(TokenType::Star, Rule::new(None, Some(binary), PREC_FACTOR));
|
||||||
rules.insert(TokenType::Bang, Rule::new(None, None, PREC_NONE));
|
rules.insert(TokenType::Bang, Rule::new(Some(unary), None, PREC_UNARY));
|
||||||
rules.insert(TokenType::BangEqual, Rule::new(None, None, PREC_NONE));
|
rules.insert(TokenType::BangEqual, Rule::new(None, None, PREC_NONE));
|
||||||
rules.insert(TokenType::Equal, Rule::new(None, None, PREC_NONE));
|
rules.insert(TokenType::Equal, Rule::new(None, None, PREC_NONE));
|
||||||
rules.insert(TokenType::EqualEqual, Rule::new(None, None, PREC_NONE));
|
rules.insert(TokenType::EqualEqual, Rule::new(None, None, PREC_NONE));
|
||||||
rules.insert(TokenType::Greater, Rule::new(None, None, PREC_NONE));
|
rules.insert(TokenType::Greater, Rule::new(None, None, PREC_NONE));
|
||||||
rules.insert(TokenType::GreaterEqual, Rule::new(None, None, PREC_NONE));
|
rules.insert(TokenType::GreaterEqual, Rule::new(None, None, PREC_NONE));
|
||||||
|
rules.insert(TokenType::GreaterGreater, Rule::new(None, Some(binary), PREC_BITSHIFT));
|
||||||
rules.insert(TokenType::Less, Rule::new(None, None, PREC_NONE));
|
rules.insert(TokenType::Less, Rule::new(None, None, PREC_NONE));
|
||||||
rules.insert(TokenType::LessEqual, Rule::new(None, None, PREC_NONE));
|
rules.insert(TokenType::LessEqual, Rule::new(None, None, PREC_NONE));
|
||||||
|
rules.insert(TokenType::LessLess, Rule::new(None, Some(binary), PREC_BITSHIFT));
|
||||||
rules.insert(TokenType::Identifier, Rule::new(None, None, PREC_NONE));
|
rules.insert(TokenType::Identifier, Rule::new(None, None, PREC_NONE));
|
||||||
rules.insert(TokenType::String, Rule::new(None, None, PREC_NONE));
|
rules.insert(TokenType::String, Rule::new(None, None, PREC_NONE));
|
||||||
rules.insert(TokenType::Number, Rule::new(Some(number), None, PREC_NONE));
|
rules.insert(TokenType::Number, Rule::new(Some(number), None, PREC_NONE));
|
||||||
|
|
|
||||||
21
src/lib.rs
21
src/lib.rs
|
|
@ -1,7 +1,7 @@
|
||||||
use anyhow::anyhow;
|
|
||||||
use tracing::debug;
|
|
||||||
use crate::chunk::Chunk;
|
use crate::chunk::Chunk;
|
||||||
use crate::value::Value;
|
use crate::value::Value;
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use tracing::debug;
|
||||||
|
|
||||||
pub mod chunk;
|
pub mod chunk;
|
||||||
pub mod compiler;
|
pub mod compiler;
|
||||||
|
|
@ -62,8 +62,8 @@ impl Vm {
|
||||||
Err(anyhow!("Cannot compare"))
|
Err(anyhow!("Cannot compare"))
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
OP_NOT => {}
|
OP_NOT => unary_op(self, |a| !a),
|
||||||
OP_BITAND => binary_op(self, bitand),
|
OP_BITAND => binary_op(self, |a, b| a & b),
|
||||||
OP_BITOR => binary_op(self, |a, b| a | b),
|
OP_BITOR => binary_op(self, |a, b| a | b),
|
||||||
OP_BITXOR => binary_op(self, |a, b| a ^ b),
|
OP_BITXOR => binary_op(self, |a, b| a ^ b),
|
||||||
OP_NEGATE => unary_op(self, |a| -a),
|
OP_NEGATE => unary_op(self, |a| -a),
|
||||||
|
|
@ -71,6 +71,8 @@ impl Vm {
|
||||||
// println!("{:?}", self.pop());
|
// println!("{:?}", self.pop());
|
||||||
return Result::Ok(self.pop());
|
return Result::Ok(self.pop());
|
||||||
}
|
}
|
||||||
|
OP_SHL => binary_op(self, |a, b| a << b),
|
||||||
|
OP_SHR => binary_op(self, |a, b| a >> b),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -85,7 +87,9 @@ impl Vm {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pop(&mut self) -> Value {
|
fn pop(&mut self) -> Value {
|
||||||
self.stack.pop().unwrap_or_else(|| Value::Error("Error occurred".to_string()))
|
self.stack
|
||||||
|
.pop()
|
||||||
|
.unwrap_or_else(|| Value::Error("Error occurred".to_string()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -109,11 +113,6 @@ fn unary_op(stack: &mut Vm, op: impl Fn(&Value) -> anyhow::Result<Value> + Copy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn bitand(a: &Value, b: &Value) -> anyhow::Result<Value> {
|
|
||||||
a& b
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Result {
|
pub enum Result {
|
||||||
Ok(Value),
|
Ok(Value),
|
||||||
|
|
@ -143,3 +142,5 @@ pub const OP_LESS_EQUAL: u16 = 19;
|
||||||
pub const OP_BITAND: u16 = 20;
|
pub const OP_BITAND: u16 = 20;
|
||||||
pub const OP_BITOR: u16 = 21;
|
pub const OP_BITOR: u16 = 21;
|
||||||
pub const OP_BITXOR: u16 = 22;
|
pub const OP_BITXOR: u16 = 22;
|
||||||
|
pub const OP_SHR: u16 = 23;
|
||||||
|
pub const OP_SHL: u16 = 24;
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ use crudlang::interpret;
|
||||||
// use crudlang::scanner::scan;
|
// use crudlang::scanner::scan;
|
||||||
|
|
||||||
fn main() -> anyhow::Result<()> {
|
fn main() -> anyhow::Result<()> {
|
||||||
|
tracing_subscriber::fmt::init();
|
||||||
// let mut chunk = Chunk::new("main");
|
// let mut chunk = Chunk::new("main");
|
||||||
// let constant = chunk.add_constant(1.2);
|
// let constant = chunk.add_constant(1.2);
|
||||||
// chunk.add(crudlang::opcode::OP_CONSTANT, 123);
|
// chunk.add(crudlang::opcode::OP_CONSTANT, 123);
|
||||||
|
|
@ -16,10 +17,11 @@ fn main() -> anyhow::Result<()> {
|
||||||
// chunk.add(crudlang::opcode::OP_ADD, 123);
|
// chunk.add(crudlang::opcode::OP_ADD, 123);
|
||||||
//
|
//
|
||||||
// chunk.add(crudlang::opcode::OP_RETURN, 123);
|
// chunk.add(crudlang::opcode::OP_RETURN, 123);
|
||||||
let chunk = compile("1&3")?;
|
let chunk = compile("3<<2")?;
|
||||||
chunk.disassemble();
|
chunk.disassemble();
|
||||||
|
|
||||||
let result = interpret(chunk);
|
let result = interpret(chunk);
|
||||||
|
println!("{:?}", result);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::tokens::TokenType::BitXor;
|
||||||
use crate::{
|
use crate::{
|
||||||
keywords,
|
keywords,
|
||||||
tokens::{
|
tokens::{
|
||||||
|
|
@ -5,7 +6,6 @@ use crate::{
|
||||||
TokenType::{self},
|
TokenType::{self},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use crate::tokens::TokenType::BitXor;
|
|
||||||
|
|
||||||
pub fn scan(source: &str) -> Vec<Token> {
|
pub fn scan(source: &str) -> Vec<Token> {
|
||||||
let scanner = Scanner {
|
let scanner = Scanner {
|
||||||
|
|
@ -70,6 +70,8 @@ impl Scanner {
|
||||||
'<' => {
|
'<' => {
|
||||||
let t = if self.match_next('=') {
|
let t = if self.match_next('=') {
|
||||||
TokenType::LessEqual
|
TokenType::LessEqual
|
||||||
|
} else if self.match_next('<') {
|
||||||
|
TokenType::LessLess
|
||||||
} else {
|
} else {
|
||||||
TokenType::Less
|
TokenType::Less
|
||||||
};
|
};
|
||||||
|
|
@ -78,6 +80,8 @@ impl Scanner {
|
||||||
'>' => {
|
'>' => {
|
||||||
let t = if self.match_next('=') {
|
let t = if self.match_next('=') {
|
||||||
TokenType::GreaterEqual
|
TokenType::GreaterEqual
|
||||||
|
} else if self.match_next('>') {
|
||||||
|
TokenType::GreaterGreater
|
||||||
} else {
|
} else {
|
||||||
TokenType::Greater
|
TokenType::Greater
|
||||||
};
|
};
|
||||||
|
|
@ -176,7 +180,7 @@ impl Scanner {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn peek(&self) -> char {
|
fn peek(&self) -> char {
|
||||||
if self.current>=self.chars.len(){
|
if self.current >= self.chars.len() {
|
||||||
'\0'
|
'\0'
|
||||||
} else {
|
} else {
|
||||||
self.chars[self.current]
|
self.chars[self.current]
|
||||||
|
|
@ -243,7 +247,7 @@ mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test() {
|
fn test() {
|
||||||
let tokens = scan(
|
let tokens = scan(
|
||||||
r#"struct Customer:
|
r#"struct Customer:
|
||||||
id: u32,
|
id: u32,
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ pub(crate) enum TokenType {
|
||||||
Slash,
|
Slash,
|
||||||
Plus,
|
Plus,
|
||||||
Minus,
|
Minus,
|
||||||
|
Not,
|
||||||
Hash,
|
Hash,
|
||||||
Bang,
|
Bang,
|
||||||
BangEqual,
|
BangEqual,
|
||||||
|
|
@ -44,6 +45,8 @@ pub(crate) enum TokenType {
|
||||||
Greater,
|
Greater,
|
||||||
Less,
|
Less,
|
||||||
GreaterEqual,
|
GreaterEqual,
|
||||||
|
GreaterGreater,
|
||||||
|
LessLess,
|
||||||
LessEqual,
|
LessEqual,
|
||||||
Indent,
|
Indent,
|
||||||
Identifier,
|
Identifier,
|
||||||
|
|
|
||||||
128
src/value.rs
128
src/value.rs
|
|
@ -1,7 +1,9 @@
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use chrono::Utc;
|
use chrono::{DateTime, Utc};
|
||||||
|
use std::cmp::Ordering;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Sub};
|
use std::hash::{Hash, Hasher};
|
||||||
|
use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Not, Shl, Shr, Sub};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
|
|
@ -14,7 +16,7 @@ pub enum Value {
|
||||||
String(String),
|
String(String),
|
||||||
Char(char),
|
Char(char),
|
||||||
Bool(bool),
|
Bool(bool),
|
||||||
Date(Utc),
|
Date(DateTime<Utc>),
|
||||||
Enum,
|
Enum,
|
||||||
Struct,
|
Struct,
|
||||||
List(Vec<Value>),
|
List(Vec<Value>),
|
||||||
|
|
@ -75,7 +77,7 @@ impl Into<Value> for bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Into<Value> for Utc {
|
impl Into<Value> for DateTime<Utc> {
|
||||||
fn into(self) -> Value {
|
fn into(self) -> Value {
|
||||||
Value::Date(self)
|
Value::Date(self)
|
||||||
}
|
}
|
||||||
|
|
@ -223,3 +225,121 @@ impl BitXor<&Value> for &Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Not for &Value {
|
||||||
|
type Output = anyhow::Result<Value>;
|
||||||
|
|
||||||
|
fn not(self) -> Self::Output {
|
||||||
|
match (self) {
|
||||||
|
Value::Bool(b) => Ok(Value::Bool(!b)),
|
||||||
|
Value::I32(i32) => Ok(Value::I32(!i32)),
|
||||||
|
Value::I64(i64) => Ok(Value::I64(!i64)),
|
||||||
|
Value::U32(u32) => Ok(Value::U32(!u32)),
|
||||||
|
Value::U64(u64) => Ok(Value::U64(!u64)),
|
||||||
|
_ => Err(anyhow!("Cannot calculate not")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Shl<&Value> for &Value {
|
||||||
|
type Output = anyhow::Result<Value>;
|
||||||
|
fn shl(self, rhs: &Value) -> Self::Output {
|
||||||
|
match (self, rhs) {
|
||||||
|
(Value::I32(a), Value::I32(b)) => Ok(Value::I32(a << b)),
|
||||||
|
(Value::I64(a), Value::I64(b)) => Ok(Value::I64(a << b)),
|
||||||
|
(Value::U32(a), Value::U32(b)) => Ok(Value::U32(a << b)),
|
||||||
|
(Value::U64(a), Value::U64(b)) => Ok(Value::U64(a << b)),
|
||||||
|
_ => Err(anyhow!("Cannot shift left on")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Shr<&Value> for &Value {
|
||||||
|
type Output = anyhow::Result<Value>;
|
||||||
|
fn shr(self, rhs: &Value) -> Self::Output {
|
||||||
|
match (self, rhs) {
|
||||||
|
(Value::I32(a), Value::I32(b)) => Ok(Value::I32(a >> b)),
|
||||||
|
(Value::I64(a), Value::I64(b)) => Ok(Value::I64(a >> b)),
|
||||||
|
(Value::U32(a), Value::U32(b)) => Ok(Value::U32(a >> b)),
|
||||||
|
(Value::U64(a), Value::U64(b)) => Ok(Value::U64(a >> b)),
|
||||||
|
_ => Err(anyhow!("Cannot shift right on")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for Value {
|
||||||
|
fn eq(&self, rhs: &Self) -> bool {
|
||||||
|
match (self, rhs) {
|
||||||
|
(Value::I32(a), Value::I32(b)) => a == b,
|
||||||
|
(Value::I64(a), Value::I64(b)) => a == b,
|
||||||
|
(Value::U32(a), Value::U32(b)) => a == b,
|
||||||
|
(Value::U64(a), Value::U64(b)) => a == b,
|
||||||
|
(Value::F32(a), Value::F32(b)) => a == b,
|
||||||
|
(Value::F64(a), Value::F64(b)) => a == b,
|
||||||
|
(Value::Bool(a), Value::Bool(b)) => a == b,
|
||||||
|
(Value::String(a), Value::String(b)) => a == b,
|
||||||
|
(Value::Char(a), Value::Char(b)) => a == b,
|
||||||
|
(Value::Date(a), Value::Date(b)) => a == b,
|
||||||
|
(Value::List(a), Value::List(b)) => a == b,
|
||||||
|
(Value::Map(a), Value::Map(b)) => {
|
||||||
|
let mut equal = true;
|
||||||
|
for (k, v) in a.iter() {
|
||||||
|
if !b.contains_key(k) || b.get(k).unwrap() != v { //safe unwrap
|
||||||
|
equal = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
equal
|
||||||
|
}
|
||||||
|
// struct?
|
||||||
|
_ => false, //?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for Value {}
|
||||||
|
|
||||||
|
impl PartialOrd for Value {
|
||||||
|
fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
|
||||||
|
match (self, rhs) {
|
||||||
|
(Value::I32(a), Value::I32(b)) => Some(a.partial_cmp(b)?),
|
||||||
|
(Value::I64(a), Value::I64(b)) => Some(a.partial_cmp(b)?),
|
||||||
|
(Value::U32(a), Value::U32(b)) => Some(a.partial_cmp(b)?),
|
||||||
|
(Value::U64(a), Value::U64(b)) =>Some(a.partial_cmp(b)?),
|
||||||
|
(Value::F32(a), Value::F32(b)) =>Some(a.partial_cmp(b)?),
|
||||||
|
(Value::F64(a), Value::F64(b)) => Some(a.partial_cmp(b)?),
|
||||||
|
(Value::String(a), Value::String(b)) => Some(a.partial_cmp(b)?),
|
||||||
|
(Value::Char(a), Value::Char(b)) => Some(a.partial_cmp(b)?),
|
||||||
|
(Value::Date(a), Value::Date(b)) => Some(a.partial_cmp(b)?),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hash for Value{
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
std::mem::discriminant(self).hash(state);
|
||||||
|
|
||||||
|
// Then hash the fields
|
||||||
|
match self {
|
||||||
|
Value::I32(i32) => i32.hash(state),
|
||||||
|
Value::I64(i64) => i64.hash(state),
|
||||||
|
Value::U32(u32) => u32.hash(state),
|
||||||
|
Value::U64(u64) => u64.hash(state),
|
||||||
|
Value::F32(f32) => f32.to_bits().hash(state),
|
||||||
|
Value::F64(f64) => f64.to_bits().hash(state),
|
||||||
|
Value::String(s) => s.hash(state),
|
||||||
|
Value::Char(c) => c.hash(state),
|
||||||
|
Value::Bool(b) => b.hash(state),
|
||||||
|
Value::Date(d) => d.hash(state),
|
||||||
|
Value::List(l) => l.hash(state),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// impl Ord for Value {
|
||||||
|
// fn cmp(&self, rhs: &Self) -> Ordering {
|
||||||
|
// self.partial_cmp(rhs).unwrap()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue