From f70656c837ed31becda534536689d77c78b87be2 Mon Sep 17 00:00:00 2001 From: Jeff Date: Sun, 25 Feb 2024 03:12:09 -0500 Subject: [PATCH] Add plumbing --- src/lib.rs | 466 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 310 insertions(+), 156 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 3a07342..20162fe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,24 +1,168 @@ -use std::{collections::BTreeMap, ops::Range}; +use std::{ + collections::BTreeMap, + ops::Range, + sync::{Arc, OnceLock, PoisonError, RwLock}, +}; use chumsky::{prelude::*, Parser}; +pub static NONE: OnceLock = OnceLock::new(); + +pub enum BuiltInValue { + None, +} + +impl BuiltInValue { + pub fn get(&self) -> Value { + match self { + BuiltInValue::None => NONE.get_or_init(|| { + Value::r#enum(EnumInstance { + type_name: Identifier("Option".to_string()), + variant: Identifier("None".to_string()), + }) + }), + } + .clone() + } +} + +pub enum Error<'src> { + Parse(Vec>), + Runtime(RuntimeError), +} + +impl<'src> From>> for Error<'src> { + fn from(errors: Vec>) -> Self { + Error::Parse(errors) + } +} + +impl<'src> From for Error<'src> { + fn from(error: RuntimeError) -> Self { + Error::Runtime(error) + } +} + +pub enum RuntimeError { + RwLockPoison(RwLockPoisonError), +} + +impl From for RuntimeError { + fn from(error: RwLockPoisonError) -> Self { + RuntimeError::RwLockPoison(error) + } +} + +pub struct RwLockPoisonError; + +impl From> for RwLockPoisonError { + fn from(_: PoisonError) -> Self { + RwLockPoisonError + } +} + +pub struct Context { + inner: Arc>>, +} + +impl Context { + pub fn get(&self, identifier: &Identifier) -> Result, RwLockPoisonError> { + let value = self.inner.read()?.get(&identifier).cloned(); + + Ok(value) + } + + pub fn set(&self, identifier: Identifier, value: Value) -> Result<(), RwLockPoisonError> { + self.inner.write()?.insert(identifier, value); + + Ok(()) + } +} + +pub trait AbstractTree { + fn run(self, context: &Context) -> Result; +} + +pub struct Interpreter

{ + parser: P, + context: Context, +} + +impl<'src, P> Interpreter

+where + P: Parser<'src, &'src str, Statement, extra::Err>>, +{ + pub fn run(&self, source: &'src str) -> Result> { + let final_value = self + .parser + .parse(source) + .into_result()? + .run(&self.context)?; + + Ok(final_value) + } +} + #[derive(Clone, Debug, PartialEq)] pub enum Statement { Assignment(Assignment), + Expression(Expression), +} + +impl AbstractTree for Statement { + fn run(self, context: &Context) -> Result { + match self { + Statement::Assignment(assignment) => assignment.run(context), + Statement::Expression(expression) => expression.run(context), + } + } +} + +#[derive(Clone, Debug, PartialEq)] +pub enum Expression { Identifier(Identifier), Logic(Logic), Value(Value), } -#[derive(Clone, Debug, PartialEq)] +impl AbstractTree for Expression { + fn run(self, context: &Context) -> Result { + match self { + Expression::Identifier(identifier) => identifier.run(context), + Expression::Logic(logic) => logic.run(context), + Expression::Value(value) => value.run(context), + } + } +} + +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct Identifier(String); +impl AbstractTree for Identifier { + fn run(self, context: &Context) -> Result { + let value = context + .get(&self)? + .unwrap_or_else(|| BuiltInValue::None.get()) + .clone(); + + Ok(value) + } +} + #[derive(Clone, Debug, PartialEq)] pub struct Assignment { identifier: Identifier, value: Value, } +impl AbstractTree for Assignment { + fn run(self, context: &Context) -> Result { + context.set(self.identifier, self.value)?; + + Ok(BuiltInValue::None.get().clone()) + } +} + #[derive(Clone, Debug, PartialEq)] pub struct Logic { left: LogicExpression, @@ -26,9 +170,22 @@ pub struct Logic { right: LogicExpression, } +impl AbstractTree for Logic { + fn run(self, _: &Context) -> Result { + todo!() + } +} + #[derive(Clone, Debug, PartialEq)] pub enum LogicOperator { Equal, + NotEqual, + Greater, + Less, + GreaterOrEqual, + LessOrEqual, + And, + Or, } #[derive(Clone, Debug, PartialEq)] @@ -39,14 +196,64 @@ pub enum LogicExpression { } #[derive(Clone, Debug, PartialEq)] -pub enum Value { +pub struct Value(Arc); + +impl Value { + pub fn boolean(boolean: bool) -> Self { + Value(Arc::new(ValueInner::Boolean(boolean))) + } + + pub fn float(float: f64) -> Self { + Value(Arc::new(ValueInner::Float(float))) + } + + pub fn integer(integer: i64) -> Self { + Value(Arc::new(ValueInner::Integer(integer))) + } + + pub fn list(list: Vec) -> Self { + Value(Arc::new(ValueInner::List(list))) + } + + pub fn map(map: BTreeMap) -> Self { + Value(Arc::new(ValueInner::Map(map))) + } + + pub fn range(range: Range) -> Self { + Value(Arc::new(ValueInner::Range(range))) + } + + pub fn string(string: String) -> Self { + Value(Arc::new(ValueInner::String(string))) + } + + pub fn r#enum(r#enum: EnumInstance) -> Self { + Value(Arc::new(ValueInner::Enum(r#enum))) + } +} + +#[derive(Clone, Debug, PartialEq)] +pub enum ValueInner { Boolean(bool), Float(f64), Integer(i64), List(Vec), - Map(BTreeMap), + Map(BTreeMap), Range(Range), String(String), + Enum(EnumInstance), +} + +#[derive(Clone, Debug, PartialEq)] +pub struct EnumInstance { + type_name: Identifier, + variant: Identifier, +} + +impl AbstractTree for Value { + fn run(self, _: &Context) -> Result { + Ok(self) + } } pub fn parser<'src>() -> impl Parser<'src, &'src str, Statement, extra::Err>> { @@ -55,17 +262,17 @@ pub fn parser<'src>() -> impl Parser<'src, &'src str, Statement, extra::Err() -> impl Parser<'src, &'src str, Statement, extra::Err().unwrap(); - Value::Integer(integer) + Value::integer(integer) }); let delimited_string = |delimiter| { @@ -84,7 +291,7 @@ pub fn parser<'src>() -> impl Parser<'src, &'src str, Statement, extra::Err() -> impl Parser<'src, &'src str, Statement, extra::Err() -> impl Parser<'src, &'src str, Statement, extra::Err").map(|_| LogicOperator::Greater), + operator("<").map(|_| LogicOperator::Less), + operator(">=").map(|_| LogicOperator::GreaterOrEqual), + operator("<=").map(|_| LogicOperator::LessOrEqual), + operator("&&").map(|_| LogicOperator::And), + operator("||").map(|_| LogicOperator::Or), + ))) .then(choice(( value.clone().map(|value| LogicExpression::Value(value)), identifier.map(|identifier| LogicExpression::Identifier(identifier)), @@ -133,12 +349,18 @@ pub fn parser<'src>() -> impl Parser<'src, &'src str, Statement, extra::Err