Rework parser and abstract tree

This commit is contained in:
Jeff 2024-02-26 16:27:01 -05:00
parent fb7675a782
commit 4179f6ebe5
13 changed files with 323 additions and 239 deletions

View File

@ -1,15 +1,15 @@
use crate::{error::RuntimeError, Context}; use crate::{error::RuntimeError, value::Value, Context};
use super::{AbstractTree, Identifier, Statement, Value}; use super::{AbstractTree, Identifier, Statement};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct Assignment { pub struct Assignment<'src> {
identifier: Identifier, identifier: Identifier<'src>,
statement: Box<Statement>, statement: Box<Statement<'src>>,
} }
impl Assignment { impl<'src> Assignment<'src> {
pub fn new(identifier: Identifier, statement: Statement) -> Self { pub fn new(identifier: Identifier<'src>, statement: Statement<'src>) -> Self {
Self { Self {
identifier, identifier,
statement: Box::new(statement), statement: Box::new(statement),
@ -17,34 +17,36 @@ impl Assignment {
} }
} }
impl AbstractTree for Assignment { impl<'src> AbstractTree for Assignment<'src> {
fn run(self, context: &Context) -> Result<Value, RuntimeError> { fn run(self, _context: &Context) -> Result<Value, RuntimeError> {
let value = self.statement.run(context)?; todo!()
// let value = self.statement.run(context)?;
context.set(self.identifier, value)?; // context.set(self.identifier, value)?;
Ok(Value::none()) // Ok(Value::none())
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; // use super::*;
#[test] #[test]
fn assign_value() { fn assign_value() {
let context = Context::new(); todo!()
// let context = Context::new();
Assignment::new( // Assignment::new(
Identifier::new("foobar"), // Identifier::new("foobar"),
Statement::Value(Value::integer(42)), // Statement::Value(Value::integer(42)),
) // )
.run(&context) // .run(&context)
.unwrap(); // .unwrap();
assert_eq!( // assert_eq!(
context.get(&Identifier::new("foobar")).unwrap(), // context.get(&Identifier::new("foobar")).unwrap(),
Some(Value::integer(42)) // Some(Value::integer(42))
) // )
} }
} }

View File

@ -1,19 +1,19 @@
use crate::{context::Context, error::RuntimeError}; use crate::{context::Context, error::RuntimeError, Value};
use super::{AbstractTree, Statement, Value}; use super::{AbstractTree, Statement};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct Block { pub struct Block<'src> {
statements: Vec<Statement>, statements: Vec<Statement<'src>>,
} }
impl Block { impl<'src> Block<'src> {
pub fn new(statements: Vec<Statement>) -> Self { pub fn new(statements: Vec<Statement<'src>>) -> Self {
Self { statements } Self { statements }
} }
} }
impl AbstractTree for Block { impl<'src> AbstractTree for Block<'src> {
fn run(self, _: &Context) -> Result<Value, RuntimeError> { fn run(self, _: &Context) -> Result<Value, RuntimeError> {
todo!() todo!()
} }

View File

@ -1,20 +1,20 @@
use crate::{context::Context, error::RuntimeError}; use crate::{context::Context, error::RuntimeError, Value};
use super::{AbstractTree, Identifier, Logic, Value}; use super::{AbstractTree, Identifier, Logic, ValueNode};
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub enum Expression { pub enum Expression<'src> {
Identifier(Identifier), Identifier(Identifier<'src>),
Logic(Box<Logic>), Logic(Box<Logic<'src>>),
Value(Value), Value(ValueNode<'src>),
} }
impl AbstractTree for Expression { impl<'src> AbstractTree for Expression<'src> {
fn run(self, context: &Context) -> Result<Value, RuntimeError> { fn run(self, context: &Context) -> Result<Value, RuntimeError> {
match self { match self {
Expression::Identifier(identifier) => identifier.run(context), Expression::Identifier(identifier) => identifier.run(context),
Expression::Logic(logic) => logic.run(context), Expression::Logic(logic) => logic.run(context),
Expression::Value(value) => value.run(context), Expression::Value(value_node) => value_node.run(context),
} }
} }
} }

View File

@ -1,20 +1,21 @@
use crate::{context::Context, error::RuntimeError}; use crate::{context::Context, error::RuntimeError, Value};
use super::{AbstractTree, Value}; use super::AbstractTree;
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct Identifier(String); pub struct Identifier<'src>(&'src str);
impl Identifier { impl<'src> Identifier<'src> {
pub fn new<T: ToString>(string: T) -> Identifier { pub fn new(string: &'src str) -> Self {
Identifier(string.to_string()) Identifier(string)
} }
} }
impl AbstractTree for Identifier { impl<'src> AbstractTree for Identifier<'src> {
fn run(self, context: &Context) -> Result<Value, RuntimeError> { fn run(self, _context: &Context) -> Result<Value, RuntimeError> {
let value = context.get(&self)?.unwrap_or_else(Value::none).clone(); todo!()
// let value = context.get(&self)?.unwrap_or_else(Value::none).clone();
Ok(value) // Ok(value)
} }
} }

View File

@ -1,21 +1,21 @@
use crate::{context::Context, error::RuntimeError}; use crate::{context::Context, error::RuntimeError, Value};
use super::{AbstractTree, Statement, Value}; use super::{AbstractTree, Expression};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub enum Logic { pub enum Logic<'src> {
Equal(Statement, Statement), Equal(Expression<'src>, Expression<'src>),
NotEqual(Statement, Statement), NotEqual(Expression<'src>, Expression<'src>),
Greater(Statement, Statement), Greater(Expression<'src>, Expression<'src>),
Less(Statement, Statement), Less(Expression<'src>, Expression<'src>),
GreaterOrEqual(Statement, Statement), GreaterOrEqual(Expression<'src>, Expression<'src>),
LessOrEqual(Statement, Statement), LessOrEqual(Expression<'src>, Expression<'src>),
And(Statement, Statement), And(Expression<'src>, Expression<'src>),
Or(Statement, Statement), Or(Expression<'src>, Expression<'src>),
Not(Statement), Not(Expression<'src>),
} }
impl AbstractTree for Logic { impl<'src> AbstractTree for Logic<'src> {
fn run(self, _context: &Context) -> Result<Value, RuntimeError> { fn run(self, _context: &Context) -> Result<Value, RuntimeError> {
let boolean = match self { let boolean = match self {
Logic::Equal(left, right) => left.run(_context)? == right.run(_context)?, Logic::Equal(left, right) => left.run(_context)? == right.run(_context)?,
@ -39,13 +39,15 @@ impl AbstractTree for Logic {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::abstract_tree::{Expression, ValueNode};
use super::*; use super::*;
#[test] #[test]
fn equal() { fn equal() {
assert!(Logic::Equal( assert!(Logic::Equal(
Statement::Value(Value::integer(42)), Expression::Value(ValueNode::Integer(42)),
Statement::Value(Value::integer(42)), Expression::Value(ValueNode::Integer(42)),
) )
.run(&Context::new()) .run(&Context::new())
.unwrap() .unwrap()

View File

@ -1,13 +1,13 @@
use crate::{context::Context, error::RuntimeError}; use crate::{context::Context, error::RuntimeError, Value};
use super::{AbstractTree, Block, Value}; use super::{AbstractTree, Block};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct Loop { pub struct Loop<'src> {
block: Block, block: Block<'src>,
} }
impl AbstractTree for Loop { impl<'src> AbstractTree for Loop<'src> {
fn run(self, _: &Context) -> Result<Value, RuntimeError> { fn run(self, _: &Context) -> Result<Value, RuntimeError> {
todo!() todo!()
} }

View File

@ -1,17 +1,18 @@
pub mod assignment; pub mod assignment;
pub mod block; pub mod block;
pub mod expression;
pub mod identifier; pub mod identifier;
pub mod logic; pub mod logic;
pub mod r#loop; pub mod r#loop;
pub mod statement; pub mod statement;
pub mod value; pub mod value_node;
pub use self::{ pub use self::{
assignment::Assignment, block::Block, identifier::Identifier, logic::Logic, r#loop::Loop, assignment::Assignment, block::Block, expression::Expression, identifier::Identifier,
statement::Statement, value::Value, logic::Logic, r#loop::Loop, statement::Statement, value_node::ValueNode,
}; };
use crate::{context::Context, error::RuntimeError}; use crate::{context::Context, error::RuntimeError, Value};
pub trait AbstractTree { pub trait AbstractTree {
fn run(self, context: &Context) -> Result<Value, RuntimeError>; fn run(self, context: &Context) -> Result<Value, RuntimeError>;

View File

@ -1,26 +1,22 @@
use crate::{context::Context, error::RuntimeError}; use crate::{context::Context, error::RuntimeError};
use super::{AbstractTree, Assignment, Block, Identifier, Logic, Loop, Value}; use super::{AbstractTree, Assignment, Block, Expression, Loop, Value};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub enum Statement { pub enum Statement<'src> {
Assignment(Assignment), Assignment(Assignment<'src>),
Block(Block), Block(Block<'src>),
Identifier(Identifier), Expression(Expression<'src>),
Loop(Loop), Loop(Loop<'src>),
Value(Value),
Logic(Box<Logic>),
} }
impl AbstractTree for Statement { impl<'src> AbstractTree for Statement<'src> {
fn run(self, _context: &Context) -> Result<Value, RuntimeError> { fn run(self, _context: &Context) -> Result<Value, RuntimeError> {
match self { match self {
Statement::Assignment(assignment) => assignment.run(_context), Statement::Assignment(assignment) => assignment.run(_context),
Statement::Block(_) => todo!(), Statement::Block(_) => todo!(),
Statement::Identifier(identifier) => identifier.run(_context), Statement::Expression(_) => todo!(),
Statement::Loop(_) => todo!(), Statement::Loop(_) => todo!(),
Statement::Value(value) => value.run(_context),
Statement::Logic(_) => todo!(),
} }
} }
} }

View File

@ -0,0 +1,72 @@
use std::{cmp::Ordering, collections::BTreeMap, ops::Range};
use crate::{context::Context, error::RuntimeError, Value};
use super::{AbstractTree, Expression, Identifier};
#[derive(Clone, Debug, PartialEq)]
pub enum ValueNode<'src> {
Boolean(bool),
Float(f64),
Integer(i64),
List(Vec<Expression<'src>>),
Map(BTreeMap<Identifier<'src>, Expression<'src>>),
Range(Range<i64>),
String(&'src str),
Enum(&'src str, &'src str),
}
impl<'src> Eq for ValueNode<'src> {}
impl<'src> PartialOrd for ValueNode<'src> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<'src> Ord for ValueNode<'src> {
fn cmp(&self, other: &Self) -> Ordering {
use ValueNode::*;
match (self, other) {
(Boolean(left), Boolean(right)) => left.cmp(right),
(Boolean(_), _) => Ordering::Greater,
(Float(left), Float(right)) => left.total_cmp(right),
(Float(_), _) => Ordering::Greater,
(Integer(left), Integer(right)) => left.cmp(right),
(Integer(_), _) => Ordering::Greater,
(List(left), List(right)) => left.cmp(right),
(List(_), _) => Ordering::Greater,
(Map(left), Map(right)) => left.cmp(right),
(Map(_), _) => Ordering::Greater,
(Range(left), Range(right)) => {
let start_cmp = left.start.cmp(&right.start);
if start_cmp.is_eq() {
left.end.cmp(&right.end)
} else {
start_cmp
}
}
(Range(_), _) => Ordering::Greater,
(String(left), String(right)) => left.cmp(right),
(String(_), _) => Ordering::Greater,
(Enum(left_name, left_variant), Enum(right_name, right_variant)) => {
let name_cmp = left_name.cmp(right_name);
if name_cmp.is_eq() {
left_variant.cmp(right_variant)
} else {
name_cmp
}
}
(Enum(_, _), _) => Ordering::Greater,
}
}
}
impl<'src> AbstractTree for ValueNode<'src> {
fn run(self, _context: &Context) -> Result<Value, RuntimeError> {
todo!()
}
}

View File

@ -3,13 +3,10 @@ use std::{
sync::{Arc, RwLock}, sync::{Arc, RwLock},
}; };
use crate::{ use crate::{error::RwLockPoisonError, Value};
abstract_tree::{Identifier, Value},
error::RwLockPoisonError,
};
pub struct Context { pub struct Context {
inner: Arc<RwLock<BTreeMap<Identifier, Value>>>, inner: Arc<RwLock<BTreeMap<String, Value>>>,
} }
impl Context { impl Context {
@ -19,20 +16,20 @@ impl Context {
} }
} }
pub fn with_values(values: BTreeMap<Identifier, Value>) -> Self { pub fn with_values(values: BTreeMap<String, Value>) -> Self {
Self { Self {
inner: Arc::new(RwLock::new(values)), inner: Arc::new(RwLock::new(values)),
} }
} }
pub fn get(&self, identifier: &Identifier) -> Result<Option<Value>, RwLockPoisonError> { pub fn get(&self, key: &str) -> Result<Option<Value>, RwLockPoisonError> {
let value = self.inner.read()?.get(&identifier).cloned(); let value = self.inner.read()?.get(key).cloned();
Ok(value) Ok(value)
} }
pub fn set(&self, identifier: Identifier, value: Value) -> Result<(), RwLockPoisonError> { pub fn set(&self, key: String, value: Value) -> Result<(), RwLockPoisonError> {
self.inner.write()?.insert(identifier, value); self.inner.write()?.insert(key, value);
Ok(()) Ok(())
} }

View File

@ -3,11 +3,13 @@ pub mod context;
pub mod error; pub mod error;
pub mod lexer; pub mod lexer;
pub mod parser; pub mod parser;
pub mod value;
use abstract_tree::{Statement, Value}; use abstract_tree::Statement;
use chumsky::{prelude::*, Parser}; use chumsky::{prelude::*, Parser};
use context::Context; use context::Context;
use error::Error; use error::Error;
pub use value::Value;
pub struct Interpreter<P> { pub struct Interpreter<P> {
_parser: P, _parser: P,
@ -16,7 +18,7 @@ pub struct Interpreter<P> {
impl<'src, P> Interpreter<P> impl<'src, P> Interpreter<P>
where where
P: Parser<'src, &'src str, Statement, extra::Err<Rich<'src, char>>>, P: Parser<'src, &'src str, Statement<'src>, extra::Err<Rich<'src, char>>>,
{ {
pub fn run(&self, _source: &'src str) -> Result<Value, Error<'src>> { pub fn run(&self, _source: &'src str) -> Result<Value, Error<'src>> {
todo!(); todo!();

View File

@ -8,93 +8,108 @@ type ParserInput<'tokens, 'src> =
fn parser<'tokens, 'src: 'tokens>() -> impl Parser< fn parser<'tokens, 'src: 'tokens>() -> impl Parser<
'tokens, 'tokens,
ParserInput<'tokens, 'src>, ParserInput<'tokens, 'src>,
Vec<(Statement, SimpleSpan)>, Vec<(Statement<'src>, SimpleSpan)>,
extra::Err<Rich<'tokens, Token<'src>, SimpleSpan>>, extra::Err<Rich<'tokens, Token<'src>, SimpleSpan>>,
> { > {
recursive(|statement| { let identifier = select! {
let identifier = select! { Token::Identifier(text) => Identifier::new(text),
Token::Identifier(text) => Identifier::new(text), };
};
let identifier_statement = identifier.map(|identifier| Statement::Identifier(identifier));
let expression = recursive(|expression| {
let basic_value = select! { let basic_value = select! {
Token::None => Value::none(), Token::None => ValueNode::Enum("Option", "None"),
Token::Boolean(boolean) => Value::boolean(boolean), Token::Boolean(boolean) => ValueNode::Boolean(boolean),
Token::Integer(integer) => Value::integer(integer), Token::Integer(integer) => ValueNode::Integer(integer),
Token::Float(float) => Value::float(float), Token::Float(float) => ValueNode::Float(float),
Token::String(string) => Value::string(string.to_string()), Token::String(string) => ValueNode::String(string),
}; };
let list = statement let identifier_expression = identifier
.map(|identifier| Expression::Identifier(identifier))
.boxed();
let list = expression
.clone() .clone()
.separated_by(just(Token::Control(','))) .separated_by(just(Token::Control(',')))
.allow_trailing() .allow_trailing()
.collect() .collect()
.delimited_by(just(Token::Control('[')), just(Token::Control(']'))) .delimited_by(just(Token::Control('[')), just(Token::Control(']')))
.map(Value::list); .map(ValueNode::List);
let value = choice(( let value = choice((
basic_value.map(|value| Statement::Value(value)), basic_value.map(|value| Expression::Value(value)),
list.map(|list| Statement::Value(list)), list.map(|list| Expression::Value(list)),
))
.boxed();
let atom = choice((
identifier_expression.clone(),
value.clone(),
expression
.clone()
.delimited_by(just(Token::Control('(')), just(Token::Control(')'))),
)); ));
let logic = atom
.pratt((
prefix(2, just(Token::Operator("!")), |expression| {
Expression::Logic(Box::new(Logic::Not(expression)))
}),
infix(left(1), just(Token::Operator("==")), |left, right| {
Expression::Logic(Box::new(Logic::Equal(left, right)))
}),
infix(left(1), just(Token::Operator("!=")), |left, right| {
Expression::Logic(Box::new(Logic::NotEqual(left, right)))
}),
infix(left(1), just(Token::Operator(">")), |left, right| {
Expression::Logic(Box::new(Logic::Greater(left, right)))
}),
infix(left(1), just(Token::Operator("<")), |left, right| {
Expression::Logic(Box::new(Logic::Less(left, right)))
}),
infix(left(1), just(Token::Operator(">=")), |left, right| {
Expression::Logic(Box::new(Logic::GreaterOrEqual(left, right)))
}),
infix(left(1), just(Token::Operator("<=")), |left, right| {
Expression::Logic(Box::new(Logic::LessOrEqual(left, right)))
}),
infix(left(1), just(Token::Operator("&&")), |left, right| {
Expression::Logic(Box::new(Logic::And(left, right)))
}),
infix(left(1), just(Token::Operator("||")), |left, right| {
Expression::Logic(Box::new(Logic::Or(left, right)))
}),
))
.boxed();
choice([logic, identifier_expression, value])
});
let statement = recursive(|statement| {
let expression_statement = expression
.map(|expression| Statement::Expression(expression))
.boxed();
let assignment = identifier let assignment = identifier
.then_ignore(just(Token::Operator("="))) .then_ignore(just(Token::Operator("=")))
.then(statement.clone()) .then(statement.clone())
.map(|(identifier, statement)| { .map(|(identifier, statement)| {
Statement::Assignment(Assignment::new(identifier, statement)) Statement::Assignment(Assignment::new(identifier, statement))
}); })
.boxed();
let atom = choice(( choice([assignment, expression_statement])
identifier_statement, });
value.clone(),
assignment.clone(),
statement
.clone()
.delimited_by(just(Token::Control('(')), just(Token::Control(')'))),
));
let logic = atom.pratt(( statement
prefix(2, just(Token::Operator("!")), |statement| { .map_with(|item, state| (item, state.span()))
Statement::Logic(Box::new(Logic::Not(statement))) .repeated()
}), .collect()
infix(left(1), just(Token::Operator("==")), |left, right| {
Statement::Logic(Box::new(Logic::Equal(left, right)))
}),
infix(left(1), just(Token::Operator("!=")), |left, right| {
Statement::Logic(Box::new(Logic::NotEqual(left, right)))
}),
infix(left(1), just(Token::Operator(">")), |left, right| {
Statement::Logic(Box::new(Logic::Greater(left, right)))
}),
infix(left(1), just(Token::Operator("<")), |left, right| {
Statement::Logic(Box::new(Logic::Less(left, right)))
}),
infix(left(1), just(Token::Operator(">=")), |left, right| {
Statement::Logic(Box::new(Logic::GreaterOrEqual(left, right)))
}),
infix(left(1), just(Token::Operator("<=")), |left, right| {
Statement::Logic(Box::new(Logic::LessOrEqual(left, right)))
}),
infix(left(1), just(Token::Operator("&&")), |left, right| {
Statement::Logic(Box::new(Logic::And(left, right)))
}),
infix(left(1), just(Token::Operator("||")), |left, right| {
Statement::Logic(Box::new(Logic::Or(left, right)))
}),
));
choice((assignment, logic, value, identifier_statement))
})
.map_with(|statement, state| (statement, state.span()))
.repeated()
.collect()
} }
pub fn parse<'tokens>( pub fn parse<'tokens, 'src: 'tokens>(
tokens: &'tokens [(Token, SimpleSpan)], tokens: &'tokens [(Token<'src>, SimpleSpan)],
) -> Result<Vec<(Statement, SimpleSpan)>, Error<'tokens>> { ) -> Result<Vec<(Statement<'src>, SimpleSpan)>, Error<'tokens>> {
parser() parser()
.parse(tokens.spanned((0..0).into())) .parse(tokens.spanned((0..0).into()))
.into_result() .into_result()
@ -103,10 +118,7 @@ pub fn parse<'tokens>(
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{ use crate::{abstract_tree::Logic, lexer::lex};
abstract_tree::{value::ValueInner, Logic},
lexer::lex,
};
use super::*; use super::*;
@ -114,15 +126,15 @@ mod tests {
fn identifier() { fn identifier() {
assert_eq!( assert_eq!(
parse(&lex("x").unwrap()).unwrap()[0].0, parse(&lex("x").unwrap()).unwrap()[0].0,
Statement::Identifier(Identifier::new("x")), Statement::Expression(Expression::Identifier(Identifier::new("x")))
); );
assert_eq!( assert_eq!(
parse(&lex("foobar").unwrap()).unwrap()[0].0, parse(&lex("foobar").unwrap()).unwrap()[0].0,
Statement::Identifier(Identifier::new("foobar")), Statement::Expression(Expression::Identifier(Identifier::new("foobar")))
); );
assert_eq!( assert_eq!(
parse(&lex("HELLO").unwrap()).unwrap()[0].0, parse(&lex("HELLO").unwrap()).unwrap()[0].0,
Statement::Identifier(Identifier::new("HELLO")), Statement::Expression(Expression::Identifier(Identifier::new("HELLO")))
); );
} }
@ -132,7 +144,7 @@ mod tests {
parse(&lex("foobar = 1").unwrap()).unwrap()[0].0, parse(&lex("foobar = 1").unwrap()).unwrap()[0].0,
Statement::Assignment(Assignment::new( Statement::Assignment(Assignment::new(
Identifier::new("foobar"), Identifier::new("foobar"),
Statement::Value(Value::integer(1)) Statement::Expression(Expression::Value(ValueNode::Integer(1)))
)), )),
); );
} }
@ -141,10 +153,10 @@ mod tests {
fn logic() { fn logic() {
assert_eq!( assert_eq!(
parse(&lex("x == 1").unwrap()).unwrap()[0].0, parse(&lex("x == 1").unwrap()).unwrap()[0].0,
Statement::Logic(Box::new(Logic::Equal( Statement::Expression(Expression::Logic(Box::new(Logic::Equal(
Statement::Identifier(Identifier::new("x")), Expression::Identifier(Identifier::new("x")),
Statement::Value(Value::integer(1)) Expression::Value(ValueNode::Integer(1))
))), ))))
); );
} }
@ -152,24 +164,26 @@ mod tests {
fn list() { fn list() {
assert_eq!( assert_eq!(
parse(&lex("[]").unwrap()).unwrap()[0].0, parse(&lex("[]").unwrap()).unwrap()[0].0,
Statement::Value(Value::list(vec![])), Statement::Expression(Expression::Value(ValueNode::List(Vec::with_capacity(0))))
); );
assert_eq!( assert_eq!(
parse(&lex("[42]").unwrap()).unwrap()[0].0, parse(&lex("[42]").unwrap()).unwrap()[0].0,
Statement::Value(Value::list(vec![Statement::Value(Value::integer(42))])), Statement::Expression(Expression::Value(ValueNode::List(vec![Expression::Value(
ValueNode::Integer(42)
)])))
); );
assert_eq!( assert_eq!(
parse(&lex("[42, 'foo', 'bar', [1, 2, 3,]]").unwrap()).unwrap()[0].0, parse(&lex("[42, 'foo', 'bar', [1, 2, 3,]]").unwrap()).unwrap()[0].0,
Statement::Value(Value::list(vec![ Statement::Expression(Expression::Value(ValueNode::List(vec![
Statement::Value(Value::integer(42)), Expression::Value(ValueNode::Integer(42)),
Statement::Value(Value::string("foo")), Expression::Value(ValueNode::String("foo")),
Statement::Value(Value::string("bar")), Expression::Value(ValueNode::String("bar")),
Statement::Value(Value::list(vec![ Expression::Value(ValueNode::List(vec![
Statement::Value(Value::integer(1)), Expression::Value(ValueNode::Integer(1)),
Statement::Value(Value::integer(2)), Expression::Value(ValueNode::Integer(2)),
Statement::Value(Value::integer(3)), Expression::Value(ValueNode::Integer(3)),
])) ]))
])), ])),)
); );
} }
@ -177,7 +191,7 @@ mod tests {
fn r#true() { fn r#true() {
assert_eq!( assert_eq!(
parse(&lex("true").unwrap()).unwrap()[0].0, parse(&lex("true").unwrap()).unwrap()[0].0,
Statement::Value(Value::boolean(true)) Statement::Expression(Expression::Value(ValueNode::Boolean(true)))
); );
} }
@ -185,7 +199,7 @@ mod tests {
fn r#false() { fn r#false() {
assert_eq!( assert_eq!(
parse(&lex("false").unwrap()).unwrap()[0].0, parse(&lex("false").unwrap()).unwrap()[0].0,
Statement::Value(Value::boolean(false)) Statement::Expression(Expression::Value(ValueNode::Boolean(false)))
); );
} }
@ -193,25 +207,25 @@ mod tests {
fn positive_float() { fn positive_float() {
assert_eq!( assert_eq!(
parse(&lex("0.0").unwrap()).unwrap()[0].0, parse(&lex("0.0").unwrap()).unwrap()[0].0,
Statement::Value(Value::float(0.0)) Statement::Expression(Expression::Value(ValueNode::Float(0.0)))
); );
assert_eq!( assert_eq!(
parse(&lex("42.0").unwrap()).unwrap()[0].0, parse(&lex("42.0").unwrap()).unwrap()[0].0,
Statement::Value(Value::float(42.0)) Statement::Expression(Expression::Value(ValueNode::Float(42.0)))
); );
let max_float = f64::MAX.to_string() + ".0"; let max_float = f64::MAX.to_string() + ".0";
assert_eq!( assert_eq!(
parse(&lex(&max_float).unwrap()).unwrap()[0].0, parse(&lex(&max_float).unwrap()).unwrap()[0].0,
Statement::Value(Value::float(f64::MAX)) Statement::Expression(Expression::Value(ValueNode::Float(f64::MAX)))
); );
let min_positive_float = f64::MIN_POSITIVE.to_string(); let min_positive_float = f64::MIN_POSITIVE.to_string();
assert_eq!( assert_eq!(
parse(&lex(&min_positive_float).unwrap()).unwrap()[0].0, parse(&lex(&min_positive_float).unwrap()).unwrap()[0].0,
Statement::Value(Value::float(f64::MIN_POSITIVE)) Statement::Expression(Expression::Value(ValueNode::Float(f64::MIN_POSITIVE)))
); );
} }
@ -219,25 +233,25 @@ mod tests {
fn negative_float() { fn negative_float() {
assert_eq!( assert_eq!(
parse(&lex("-0.0").unwrap()).unwrap()[0].0, parse(&lex("-0.0").unwrap()).unwrap()[0].0,
Statement::Value(Value::float(-0.0)) Statement::Expression(Expression::Value(ValueNode::Float(-0.0)))
); );
assert_eq!( assert_eq!(
parse(&lex("-42.0").unwrap()).unwrap()[0].0, parse(&lex("-42.0").unwrap()).unwrap()[0].0,
Statement::Value(Value::float(-42.0)) Statement::Expression(Expression::Value(ValueNode::Float(-42.0)))
); );
let min_float = f64::MIN.to_string() + ".0"; let min_float = f64::MIN.to_string() + ".0";
assert_eq!( assert_eq!(
parse(&lex(&min_float).unwrap()).unwrap()[0].0, parse(&lex(&min_float).unwrap()).unwrap()[0].0,
Statement::Value(Value::float(f64::MIN)) Statement::Expression(Expression::Value(ValueNode::Float(f64::MIN)))
); );
let max_negative_float = format!("-{}", f64::MIN_POSITIVE); let max_negative_float = format!("-{}", f64::MIN_POSITIVE);
assert_eq!( assert_eq!(
parse(&lex(&max_negative_float).unwrap()).unwrap()[0].0, parse(&lex(&max_negative_float).unwrap()).unwrap()[0].0,
Statement::Value(Value::float(-f64::MIN_POSITIVE)) Statement::Expression(Expression::Value(ValueNode::Float(-f64::MIN_POSITIVE)))
); );
} }
@ -245,20 +259,20 @@ mod tests {
fn other_float() { fn other_float() {
assert_eq!( assert_eq!(
parse(&lex("Infinity").unwrap()).unwrap()[0].0, parse(&lex("Infinity").unwrap()).unwrap()[0].0,
Statement::Value(Value::float(f64::INFINITY)) Statement::Expression(Expression::Value(ValueNode::Float(f64::INFINITY)))
); );
assert_eq!( assert_eq!(
parse(&lex("-Infinity").unwrap()).unwrap()[0].0, parse(&lex("-Infinity").unwrap()).unwrap()[0].0,
Statement::Value(Value::float(f64::NEG_INFINITY)) Statement::Expression(Expression::Value(ValueNode::Float(f64::NEG_INFINITY)))
); );
if let Statement::Value(value) = &parse(&lex("NaN").unwrap()).unwrap()[0].0 { if let Statement::Expression(Expression::Value(ValueNode::Float(float))) =
if let ValueInner::Float(float) = value.inner().as_ref() { &parse(&lex("NaN").unwrap()).unwrap()[0].0
return assert!(float.is_nan()); {
} assert!(float.is_nan());
} else {
panic!("Expected a float.");
} }
panic!("Expected a float.")
} }
#[test] #[test]
@ -267,19 +281,22 @@ mod tests {
let source = i.to_string(); let source = i.to_string();
let statements = parse(&lex(&source).unwrap()).unwrap(); let statements = parse(&lex(&source).unwrap()).unwrap();
assert_eq!(statements[0].0, Statement::Value(Value::integer(i))) assert_eq!(
statements[0].0,
Statement::Expression(Expression::Value(ValueNode::Integer(i)))
)
} }
assert_eq!( assert_eq!(
parse(&lex("42").unwrap()).unwrap()[0].0, parse(&lex("42").unwrap()).unwrap()[0].0,
Statement::Value(Value::integer(42)) Statement::Expression(Expression::Value(ValueNode::Integer(42)))
); );
let maximum_integer = i64::MAX.to_string(); let maximum_integer = i64::MAX.to_string();
assert_eq!( assert_eq!(
parse(&lex(&maximum_integer).unwrap()).unwrap()[0].0, parse(&lex(&maximum_integer).unwrap()).unwrap()[0].0,
Statement::Value(Value::integer(i64::MAX)) Statement::Expression(Expression::Value(ValueNode::Integer(i64::MAX)))
); );
} }
@ -289,19 +306,22 @@ mod tests {
let source = i.to_string(); let source = i.to_string();
let statements = parse(&lex(&source).unwrap()).unwrap(); let statements = parse(&lex(&source).unwrap()).unwrap();
assert_eq!(statements[0].0, Statement::Value(Value::integer(i))) assert_eq!(
statements[0].0,
Statement::Expression(Expression::Value(ValueNode::Integer(i)))
)
} }
assert_eq!( assert_eq!(
parse(&lex("-42").unwrap()).unwrap()[0].0, parse(&lex("-42").unwrap()).unwrap()[0].0,
Statement::Value(Value::integer(-42)) Statement::Expression(Expression::Value(ValueNode::Integer(-42)))
); );
let minimum_integer = i64::MIN.to_string(); let minimum_integer = i64::MIN.to_string();
assert_eq!( assert_eq!(
parse(&lex(&minimum_integer).unwrap()).unwrap()[0].0, parse(&lex(&minimum_integer).unwrap()).unwrap()[0].0,
Statement::Value(Value::integer(i64::MIN)) Statement::Expression(Expression::Value(ValueNode::Integer(i64::MIN)))
); );
} }
@ -309,15 +329,15 @@ mod tests {
fn double_quoted_string() { fn double_quoted_string() {
assert_eq!( assert_eq!(
parse(&lex("\"\"").unwrap()).unwrap()[0].0, parse(&lex("\"\"").unwrap()).unwrap()[0].0,
Statement::Value(Value::string("".to_string())) Statement::Expression(Expression::Value(ValueNode::String("")))
); );
assert_eq!( assert_eq!(
parse(&lex("\"42\"").unwrap()).unwrap()[0].0, parse(&lex("\"42\"").unwrap()).unwrap()[0].0,
Statement::Value(Value::string("42".to_string())) Statement::Expression(Expression::Value(ValueNode::String("42")))
); );
assert_eq!( assert_eq!(
parse(&lex("\"foobar\"").unwrap()).unwrap()[0].0, parse(&lex("\"foobar\"").unwrap()).unwrap()[0].0,
Statement::Value(Value::string("foobar".to_string())) Statement::Expression(Expression::Value(ValueNode::String("foobar")))
); );
} }
@ -325,15 +345,15 @@ mod tests {
fn single_quoted_string() { fn single_quoted_string() {
assert_eq!( assert_eq!(
parse(&lex("''").unwrap()).unwrap()[0].0, parse(&lex("''").unwrap()).unwrap()[0].0,
Statement::Value(Value::string("".to_string())) Statement::Expression(Expression::Value(ValueNode::String("")))
); );
assert_eq!( assert_eq!(
parse(&lex("'42'").unwrap()).unwrap()[0].0, parse(&lex("'42'").unwrap()).unwrap()[0].0,
Statement::Value(Value::string("42".to_string())) Statement::Expression(Expression::Value(ValueNode::String("42")))
); );
assert_eq!( assert_eq!(
parse(&lex("'foobar'").unwrap()).unwrap()[0].0, parse(&lex("'foobar'").unwrap()).unwrap()[0].0,
Statement::Value(Value::string("foobar".to_string())) Statement::Expression(Expression::Value(ValueNode::String("foobar")))
); );
} }
@ -341,15 +361,15 @@ mod tests {
fn grave_quoted_string() { fn grave_quoted_string() {
assert_eq!( assert_eq!(
parse(&lex("``").unwrap()).unwrap()[0].0, parse(&lex("``").unwrap()).unwrap()[0].0,
Statement::Value(Value::string("".to_string())) Statement::Expression(Expression::Value(ValueNode::String("")))
); );
assert_eq!( assert_eq!(
parse(&lex("`42`").unwrap()).unwrap()[0].0, parse(&lex("`42`").unwrap()).unwrap()[0].0,
Statement::Value(Value::string("42".to_string())) Statement::Expression(Expression::Value(ValueNode::String("42")))
); );
assert_eq!( assert_eq!(
parse(&lex("`foobar`").unwrap()).unwrap()[0].0, parse(&lex("`foobar`").unwrap()).unwrap()[0].0,
Statement::Value(Value::string("foobar".to_string())) Statement::Expression(Expression::Value(ValueNode::String("foobar")))
); );
} }
} }

View File

@ -1,13 +1,10 @@
use std::{ use std::{
cmp::Ordering, cmp::Ordering,
collections::BTreeMap,
ops::Range, ops::Range,
sync::{Arc, OnceLock}, sync::{Arc, OnceLock},
}; };
use crate::{context::Context, error::RuntimeError}; use crate::error::RuntimeError;
use super::{AbstractTree, Identifier, Statement};
pub static NONE: OnceLock<Value> = OnceLock::new(); pub static NONE: OnceLock<Value> = OnceLock::new();
@ -22,8 +19,8 @@ impl Value {
pub fn none() -> Self { pub fn none() -> Self {
NONE.get_or_init(|| { NONE.get_or_init(|| {
Value::r#enum(EnumInstance { Value::r#enum(EnumInstance {
type_name: Identifier::new("Option"), type_name: "Option".to_string(),
variant: Identifier::new("None"), variant: "None".to_string(),
}) })
}) })
.clone() .clone()
@ -41,13 +38,13 @@ impl Value {
Value(Arc::new(ValueInner::Integer(integer))) Value(Arc::new(ValueInner::Integer(integer)))
} }
pub fn list(list: Vec<Statement>) -> Self { pub fn list(list: Vec<Value>) -> Self {
Value(Arc::new(ValueInner::List(list))) Value(Arc::new(ValueInner::List(list)))
} }
pub fn map(map: BTreeMap<Identifier, Value>) -> Self { // pub fn map(map: BTreeMap<Identifier, Value>) -> Self {
Value(Arc::new(ValueInner::Map(map))) // Value(Arc::new(ValueInner::Map(map)))
} // }
pub fn range(range: Range<i64>) -> Self { pub fn range(range: Range<i64>) -> Self {
Value(Arc::new(ValueInner::Range(range))) Value(Arc::new(ValueInner::Range(range)))
@ -89,8 +86,8 @@ pub enum ValueInner {
Boolean(bool), Boolean(bool),
Float(f64), Float(f64),
Integer(i64), Integer(i64),
List(Vec<Statement>), List(Vec<Value>),
Map(BTreeMap<Identifier, Value>), // Map(BTreeMap<Identifier, Value>),
Range(Range<i64>), Range(Range<i64>),
String(String), String(String),
Enum(EnumInstance), Enum(EnumInstance),
@ -117,8 +114,8 @@ impl Ord for ValueInner {
(Integer(_), _) => Ordering::Greater, (Integer(_), _) => Ordering::Greater,
(List(left), List(right)) => left.cmp(right), (List(left), List(right)) => left.cmp(right),
(List(_), _) => Ordering::Greater, (List(_), _) => Ordering::Greater,
(Map(left), Map(right)) => left.cmp(right), // (Map(left), Map(right)) => left.cmp(right),
(Map(_), _) => Ordering::Greater, // (Map(_), _) => Ordering::Greater,
(Range(left), Range(right)) => { (Range(left), Range(right)) => {
let start_cmp = left.start.cmp(&right.start); let start_cmp = left.start.cmp(&right.start);
@ -139,12 +136,6 @@ impl Ord for ValueInner {
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct EnumInstance { pub struct EnumInstance {
type_name: Identifier, type_name: String,
variant: Identifier, variant: String,
}
impl AbstractTree for Value {
fn run(self, _: &Context) -> Result<Value, RuntimeError> {
Ok(self)
}
} }