Implement subtraction and multiplication
This commit is contained in:
parent
57782d3ed6
commit
60bd8f5352
@ -53,6 +53,7 @@ pub enum Statement {
|
|||||||
value_arguments: Option<Vec<Node>>,
|
value_arguments: Option<Vec<Node>>,
|
||||||
},
|
},
|
||||||
PropertyAccess(Box<Node>, Box<Node>),
|
PropertyAccess(Box<Node>, Box<Node>),
|
||||||
|
Subtract(Box<Node>, Box<Node>),
|
||||||
List(Vec<Node>),
|
List(Vec<Node>),
|
||||||
Multiply(Box<Node>, Box<Node>),
|
Multiply(Box<Node>, Box<Node>),
|
||||||
|
|
||||||
@ -75,6 +76,7 @@ impl Statement {
|
|||||||
Statement::List(_) => None,
|
Statement::List(_) => None,
|
||||||
Statement::Multiply(left, _) => left.statement.expected_type(variables),
|
Statement::Multiply(left, _) => left.statement.expected_type(variables),
|
||||||
Statement::PropertyAccess(_, _) => None,
|
Statement::PropertyAccess(_, _) => None,
|
||||||
|
Statement::Subtract(left, _) => left.statement.expected_type(variables),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -154,7 +156,6 @@ impl Display for Statement {
|
|||||||
|
|
||||||
write!(f, ")")
|
write!(f, ")")
|
||||||
}
|
}
|
||||||
Statement::PropertyAccess(left, right) => write!(f, "{left}.{right}"),
|
|
||||||
Statement::List(nodes) => {
|
Statement::List(nodes) => {
|
||||||
write!(f, "[")?;
|
write!(f, "[")?;
|
||||||
for (i, node) in nodes.iter().enumerate() {
|
for (i, node) in nodes.iter().enumerate() {
|
||||||
@ -165,9 +166,11 @@ impl Display for Statement {
|
|||||||
}
|
}
|
||||||
write!(f, "]")
|
write!(f, "]")
|
||||||
}
|
}
|
||||||
|
Statement::PropertyAccess(left, right) => write!(f, "{left}.{right}"),
|
||||||
Statement::Multiply(left, right) => write!(f, "{left} * {right}"),
|
Statement::Multiply(left, right) => write!(f, "{left} * {right}"),
|
||||||
Statement::Constant(value) => write!(f, "{value}"),
|
Statement::Constant(value) => write!(f, "{value}"),
|
||||||
Statement::Identifier(identifier) => write!(f, "{identifier}"),
|
Statement::Identifier(identifier) => write!(f, "{identifier}"),
|
||||||
|
Statement::Subtract(left, right) => write!(f, "{left} - {right}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,6 +75,9 @@ impl<'a> Analyzer<'a> {
|
|||||||
fn analyze_node(&self, node: &Node) -> Result<(), AnalyzerError> {
|
fn analyze_node(&self, node: &Node) -> Result<(), AnalyzerError> {
|
||||||
match &node.statement {
|
match &node.statement {
|
||||||
Statement::Add(left, right) => {
|
Statement::Add(left, right) => {
|
||||||
|
self.analyze_node(left)?;
|
||||||
|
self.analyze_node(right)?;
|
||||||
|
|
||||||
let left_type = left.statement.expected_type(self.variables);
|
let left_type = left.statement.expected_type(self.variables);
|
||||||
let right_type = right.statement.expected_type(self.variables);
|
let right_type = right.statement.expected_type(self.variables);
|
||||||
|
|
||||||
@ -95,9 +98,6 @@ impl<'a> Analyzer<'a> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.analyze_node(left)?;
|
|
||||||
self.analyze_node(right)?;
|
|
||||||
}
|
}
|
||||||
Statement::Assign(left, right) => {
|
Statement::Assign(left, right) => {
|
||||||
if let Statement::Identifier(_) = &left.statement {
|
if let Statement::Identifier(_) = &left.statement {
|
||||||
@ -135,6 +135,9 @@ impl<'a> Analyzer<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Statement::Multiply(left, right) => {
|
Statement::Multiply(left, right) => {
|
||||||
|
self.analyze_node(left)?;
|
||||||
|
self.analyze_node(right)?;
|
||||||
|
|
||||||
if let Some(Type::Integer) | Some(Type::Float) =
|
if let Some(Type::Integer) | Some(Type::Float) =
|
||||||
left.statement.expected_type(self.variables)
|
left.statement.expected_type(self.variables)
|
||||||
{
|
{
|
||||||
@ -154,9 +157,6 @@ impl<'a> Analyzer<'a> {
|
|||||||
position: right.position,
|
position: right.position,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
self.analyze_node(left)?;
|
|
||||||
self.analyze_node(right)?;
|
|
||||||
}
|
}
|
||||||
Statement::PropertyAccess(left, right) => {
|
Statement::PropertyAccess(left, right) => {
|
||||||
if let Statement::Identifier(_) | Statement::Constant(_) | Statement::List(_) =
|
if let Statement::Identifier(_) | Statement::Constant(_) | Statement::List(_) =
|
||||||
@ -184,6 +184,30 @@ impl<'a> Analyzer<'a> {
|
|||||||
|
|
||||||
self.analyze_node(right)?;
|
self.analyze_node(right)?;
|
||||||
}
|
}
|
||||||
|
Statement::Subtract(left, right) => {
|
||||||
|
self.analyze_node(left)?;
|
||||||
|
self.analyze_node(right)?;
|
||||||
|
|
||||||
|
let left_type = left.statement.expected_type(self.variables);
|
||||||
|
let right_type = right.statement.expected_type(self.variables);
|
||||||
|
|
||||||
|
match (left_type, right_type) {
|
||||||
|
(Some(Type::Integer), Some(Type::Integer)) => {}
|
||||||
|
(Some(Type::Float), Some(Type::Float)) => {}
|
||||||
|
(Some(Type::Integer), _) | (Some(Type::Float), _) => {
|
||||||
|
return Err(AnalyzerError::ExpectedIntegerOrFloat {
|
||||||
|
actual: right.as_ref().clone(),
|
||||||
|
position: right.position,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return Err(AnalyzerError::ExpectedIntegerOrFloat {
|
||||||
|
actual: left.as_ref().clone(),
|
||||||
|
position: left.position,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -103,6 +103,14 @@ impl Lexer {
|
|||||||
let (token, span) = if let Some(c) = self.peek_char(source) {
|
let (token, span) = if let Some(c) = self.peek_char(source) {
|
||||||
match c {
|
match c {
|
||||||
'0'..='9' => self.lex_number(source)?,
|
'0'..='9' => self.lex_number(source)?,
|
||||||
|
'-' => {
|
||||||
|
if let Some('0'..='9') = self.peek_second_char(source) {
|
||||||
|
self.lex_number(source)?
|
||||||
|
} else {
|
||||||
|
self.position += 1;
|
||||||
|
(Token::Minus, (self.position - 1, self.position))
|
||||||
|
}
|
||||||
|
}
|
||||||
'a'..='z' | 'A'..='Z' => self.lex_alphabetical(source)?,
|
'a'..='z' | 'A'..='Z' => self.lex_alphabetical(source)?,
|
||||||
'"' => self.lex_string('"', source)?,
|
'"' => self.lex_string('"', source)?,
|
||||||
'\'' => self.lex_string('\'', source)?,
|
'\'' => self.lex_string('\'', source)?,
|
||||||
@ -185,6 +193,10 @@ impl Lexer {
|
|||||||
let start_pos = self.position;
|
let start_pos = self.position;
|
||||||
let mut is_float = false;
|
let mut is_float = false;
|
||||||
|
|
||||||
|
if let Some('-') = self.peek_char(source) {
|
||||||
|
self.next_char(source);
|
||||||
|
}
|
||||||
|
|
||||||
while let Some(c) = self.peek_char(source) {
|
while let Some(c) = self.peek_char(source) {
|
||||||
if c == '.' {
|
if c == '.' {
|
||||||
if let Some('0'..='9') = self.peek_second_char(source) {
|
if let Some('0'..='9') = self.peek_second_char(source) {
|
||||||
@ -324,8 +336,60 @@ impl From<ParseIntError> for LexError {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn max_integer() {
|
||||||
|
let input = "9223372036854775807";
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
lex(input),
|
||||||
|
Ok(vec![
|
||||||
|
(Token::Integer(i64::MAX), (0, 19)),
|
||||||
|
(Token::Eof, (19, 19)),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn min_integer() {
|
||||||
|
let input = "-9223372036854775808";
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
lex(input),
|
||||||
|
Ok(vec![
|
||||||
|
(Token::Integer(i64::MIN), (0, 20)),
|
||||||
|
(Token::Eof, (20, 20)),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn subtract_negative_integers() {
|
||||||
|
let input = "-42 - -42";
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
lex(input),
|
||||||
|
Ok(vec![
|
||||||
|
(Token::Integer(-42), (0, 3)),
|
||||||
|
(Token::Minus, (4, 5)),
|
||||||
|
(Token::Integer(-42), (6, 9)),
|
||||||
|
(Token::Eof, (9, 9)),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn negative_integer() {
|
||||||
|
let input = "-42";
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
lex(input),
|
||||||
|
Ok(vec![(Token::Integer(-42), (0, 3)), (Token::Eof, (3, 3))])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn read_line() {
|
fn read_line() {
|
||||||
let input = "read_line()";
|
let input = "read_line()";
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
//! The Dust programming language.
|
//! The Dust programming language.
|
||||||
//!
|
//!
|
||||||
//! Dust is a statically typed, interpreted programming language.
|
//! Dust is a statically typed, interpreted programming language.
|
||||||
//!
|
|
||||||
//! The [interpreter] module contains the `Interpreter` struct, which is used to lex, parse and/or
|
|
||||||
//! interpret Dust code. The `interpret` function is a convenience function that creates a new
|
|
||||||
//! `Interpreter` and runs the given source code.
|
|
||||||
pub mod abstract_tree;
|
pub mod abstract_tree;
|
||||||
pub mod analyzer;
|
pub mod analyzer;
|
||||||
pub mod built_in_function;
|
pub mod built_in_function;
|
||||||
|
@ -183,6 +183,17 @@ impl<'src> Parser<'src> {
|
|||||||
(left_start, right_end),
|
(left_start, right_end),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
(Token::Minus, _) => {
|
||||||
|
self.next_token()?;
|
||||||
|
|
||||||
|
let right_node = self.parse_node(self.current_precedence())?;
|
||||||
|
let right_end = right_node.position.1;
|
||||||
|
|
||||||
|
return Ok(Node::new(
|
||||||
|
Statement::Subtract(Box::new(left_node), Box::new(right_node)),
|
||||||
|
(left_start, right_end),
|
||||||
|
));
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -338,8 +349,9 @@ impl<'src> Parser<'src> {
|
|||||||
match self.current.0 {
|
match self.current.0 {
|
||||||
Token::Dot => 4,
|
Token::Dot => 4,
|
||||||
Token::Equal => 3,
|
Token::Equal => 3,
|
||||||
Token::Plus => 1,
|
|
||||||
Token::Star => 2,
|
Token::Star => 2,
|
||||||
|
Token::Plus => 1,
|
||||||
|
Token::Minus => 1,
|
||||||
_ => 0,
|
_ => 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -394,6 +406,25 @@ mod tests {
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn subtract_negative_integers() {
|
||||||
|
let input = "-1 - -2";
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
parse(input),
|
||||||
|
Ok(AbstractSyntaxTree {
|
||||||
|
nodes: [Node::new(
|
||||||
|
Statement::Subtract(
|
||||||
|
Box::new(Node::new(Statement::Constant(Value::integer(-1)), (0, 2))),
|
||||||
|
Box::new(Node::new(Statement::Constant(Value::integer(-2)), (5, 7)))
|
||||||
|
),
|
||||||
|
(0, 7)
|
||||||
|
)]
|
||||||
|
.into()
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn string_concatenation() {
|
fn string_concatenation() {
|
||||||
let input = "\"Hello, \" + \"World!\"";
|
let input = "\"Hello, \" + \"World!\"";
|
||||||
|
@ -29,6 +29,7 @@ pub enum Token<'src> {
|
|||||||
Equal,
|
Equal,
|
||||||
LeftParenthesis,
|
LeftParenthesis,
|
||||||
LeftSquareBrace,
|
LeftSquareBrace,
|
||||||
|
Minus,
|
||||||
Plus,
|
Plus,
|
||||||
RightParenthesis,
|
RightParenthesis,
|
||||||
RightSquareBrace,
|
RightSquareBrace,
|
||||||
@ -58,6 +59,7 @@ impl<'src> Token<'src> {
|
|||||||
Token::RightParenthesis => TokenOwned::RightParenthesis,
|
Token::RightParenthesis => TokenOwned::RightParenthesis,
|
||||||
Token::LeftSquareBrace => TokenOwned::LeftSquareBrace,
|
Token::LeftSquareBrace => TokenOwned::LeftSquareBrace,
|
||||||
Token::RightSquareBrace => TokenOwned::RightSquareBrace,
|
Token::RightSquareBrace => TokenOwned::RightSquareBrace,
|
||||||
|
Token::Minus => TokenOwned::Minus,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -85,6 +87,7 @@ impl<'src> Display for Token<'src> {
|
|||||||
Token::RightParenthesis => write!(f, ")"),
|
Token::RightParenthesis => write!(f, ")"),
|
||||||
Token::LeftSquareBrace => write!(f, "["),
|
Token::LeftSquareBrace => write!(f, "["),
|
||||||
Token::RightSquareBrace => write!(f, "]"),
|
Token::RightSquareBrace => write!(f, "]"),
|
||||||
|
Token::Minus => write!(f, "-"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -117,6 +120,7 @@ pub enum TokenOwned {
|
|||||||
Equal,
|
Equal,
|
||||||
LeftParenthesis,
|
LeftParenthesis,
|
||||||
LeftSquareBrace,
|
LeftSquareBrace,
|
||||||
|
Minus,
|
||||||
Plus,
|
Plus,
|
||||||
RightParenthesis,
|
RightParenthesis,
|
||||||
RightSquareBrace,
|
RightSquareBrace,
|
||||||
@ -146,6 +150,7 @@ impl Display for TokenOwned {
|
|||||||
TokenOwned::RightParenthesis => write!(f, ")"),
|
TokenOwned::RightParenthesis => write!(f, ")"),
|
||||||
TokenOwned::LeftSquareBrace => write!(f, "["),
|
TokenOwned::LeftSquareBrace => write!(f, "["),
|
||||||
TokenOwned::RightSquareBrace => write!(f, "]"),
|
TokenOwned::RightSquareBrace => write!(f, "]"),
|
||||||
|
TokenOwned::Minus => write!(f, "-"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,11 +129,31 @@ impl Value {
|
|||||||
match (self.inner().as_ref(), other.inner().as_ref()) {
|
match (self.inner().as_ref(), other.inner().as_ref()) {
|
||||||
(ValueInner::Float(left), ValueInner::Float(right)) => Ok(Value::float(left + right)),
|
(ValueInner::Float(left), ValueInner::Float(right)) => Ok(Value::float(left + right)),
|
||||||
(ValueInner::Integer(left), ValueInner::Integer(right)) => {
|
(ValueInner::Integer(left), ValueInner::Integer(right)) => {
|
||||||
Ok(Value::integer(left + right))
|
Ok(Value::integer(left.saturating_add(*right)))
|
||||||
}
|
}
|
||||||
_ => Err(ValueError::CannotAdd(self.clone(), other.clone())),
|
_ => Err(ValueError::CannotAdd(self.clone(), other.clone())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn subtract(&self, other: &Value) -> Result<Value, ValueError> {
|
||||||
|
match (self.inner().as_ref(), other.inner().as_ref()) {
|
||||||
|
(ValueInner::Float(left), ValueInner::Float(right)) => Ok(Value::float(left - right)),
|
||||||
|
(ValueInner::Integer(left), ValueInner::Integer(right)) => {
|
||||||
|
Ok(Value::integer(left.saturating_sub(*right)))
|
||||||
|
}
|
||||||
|
_ => Err(ValueError::CannotSubtract(self.clone(), other.clone())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn multiply(&self, other: &Value) -> Result<Value, ValueError> {
|
||||||
|
match (self.inner().as_ref(), other.inner().as_ref()) {
|
||||||
|
(ValueInner::Float(left), ValueInner::Float(right)) => Ok(Value::float(left * right)),
|
||||||
|
(ValueInner::Integer(left), ValueInner::Integer(right)) => {
|
||||||
|
Ok(Value::integer(left * right))
|
||||||
|
}
|
||||||
|
_ => Err(ValueError::CannotMultiply(self.clone(), other.clone())),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Value {
|
impl Display for Value {
|
||||||
@ -653,6 +673,8 @@ impl Display for Function {
|
|||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum ValueError {
|
pub enum ValueError {
|
||||||
CannotAdd(Value, Value),
|
CannotAdd(Value, Value),
|
||||||
|
CannotMultiply(Value, Value),
|
||||||
|
CannotSubtract(Value, Value),
|
||||||
PropertyNotFound { value: Value, property: Identifier },
|
PropertyNotFound { value: Value, property: Identifier },
|
||||||
IndexOutOfBounds { value: Value, index: i64 },
|
IndexOutOfBounds { value: Value, index: i64 },
|
||||||
ExpectedList(Value),
|
ExpectedList(Value),
|
||||||
@ -664,6 +686,12 @@ impl Display for ValueError {
|
|||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
ValueError::CannotAdd(left, right) => write!(f, "Cannot add {} and {}", left, right),
|
ValueError::CannotAdd(left, right) => write!(f, "Cannot add {} and {}", left, right),
|
||||||
|
ValueError::CannotMultiply(left, right) => {
|
||||||
|
write!(f, "Cannot multiply {} and {}", left, right)
|
||||||
|
}
|
||||||
|
ValueError::CannotSubtract(left, right) => {
|
||||||
|
write!(f, "Cannot subtract {} and {}", left, right)
|
||||||
|
}
|
||||||
ValueError::PropertyNotFound { value, property } => {
|
ValueError::PropertyNotFound { value, property } => {
|
||||||
write!(f, "{} does not have a property named {}", value, property)
|
write!(f, "{} does not have a property named {}", value, property)
|
||||||
}
|
}
|
||||||
|
@ -182,7 +182,27 @@ impl Vm {
|
|||||||
|
|
||||||
Ok(Some(Value::list(values)))
|
Ok(Some(Value::list(values)))
|
||||||
}
|
}
|
||||||
Statement::Multiply(_, _) => todo!(),
|
Statement::Multiply(left, right) => {
|
||||||
|
let left_span = left.position;
|
||||||
|
let left = if let Some(value) = self.run_node(*left, variables)? {
|
||||||
|
value
|
||||||
|
} else {
|
||||||
|
return Err(VmError::ExpectedValue {
|
||||||
|
position: left_span,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
let right_span = right.position;
|
||||||
|
let right = if let Some(value) = self.run_node(*right, variables)? {
|
||||||
|
value
|
||||||
|
} else {
|
||||||
|
return Err(VmError::ExpectedValue {
|
||||||
|
position: right_span,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
let product = left.multiply(&right)?;
|
||||||
|
|
||||||
|
Ok(Some(product))
|
||||||
|
}
|
||||||
Statement::PropertyAccess(left, right) => {
|
Statement::PropertyAccess(left, right) => {
|
||||||
let left_span = left.position;
|
let left_span = left.position;
|
||||||
let left_value = if let Some(value) = self.run_node(*left, variables)? {
|
let left_value = if let Some(value) = self.run_node(*left, variables)? {
|
||||||
@ -239,6 +259,27 @@ impl Vm {
|
|||||||
position: right_span,
|
position: right_span,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Statement::Subtract(left, right) => {
|
||||||
|
let left_span = left.position;
|
||||||
|
let left = if let Some(value) = self.run_node(*left, variables)? {
|
||||||
|
value
|
||||||
|
} else {
|
||||||
|
return Err(VmError::ExpectedValue {
|
||||||
|
position: left_span,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
let right_span = right.position;
|
||||||
|
let right = if let Some(value) = self.run_node(*right, variables)? {
|
||||||
|
value
|
||||||
|
} else {
|
||||||
|
return Err(VmError::ExpectedValue {
|
||||||
|
position: right_span,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
let difference = left.subtract(&right)?;
|
||||||
|
|
||||||
|
Ok(Some(difference))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -341,6 +382,33 @@ impl Display for VmError {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn integer_saturating_add() {
|
||||||
|
let input = "9223372036854775807 + 1";
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
run(input, &mut HashMap::new()),
|
||||||
|
Ok(Some(Value::integer(i64::MAX)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn integer_saturating_sub() {
|
||||||
|
let input = "-9223372036854775808 - 1";
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
run(input, &mut HashMap::new()),
|
||||||
|
Ok(Some(Value::integer(i64::MIN)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn multiply() {
|
||||||
|
let input = "2 * 3";
|
||||||
|
|
||||||
|
assert_eq!(run(input, &mut HashMap::new()), Ok(Some(Value::integer(6))));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn boolean() {
|
fn boolean() {
|
||||||
let input = "true";
|
let input = "true";
|
||||||
|
Loading…
Reference in New Issue
Block a user