1
0

Add and pass test

This commit is contained in:
Jeff 2024-03-06 18:15:25 -05:00
parent 4db3ae7cb8
commit bff5ba81a3
5 changed files with 78 additions and 18 deletions

View File

@ -29,10 +29,14 @@ impl<'src> AbstractTree for Assignment<'src> {
}
fn validate(&self, context: &Context) -> Result<(), ValidationError> {
if let Some(expected) = &self.r#type {
let statement_type = self.statement.expected_type(context)?;
let statement_type = self.statement.expected_type(context)?;
if let Some(expected) = &self.r#type {
expected.check(&statement_type)?;
context.set_type(self.identifier.clone(), expected.clone())?;
} else {
context.set_type(self.identifier.clone(), statement_type)?;
}
Ok(())
@ -41,7 +45,7 @@ impl<'src> AbstractTree for Assignment<'src> {
fn run(self, context: &Context) -> Result<Value, RuntimeError> {
let value = self.statement.run(context)?;
context.set(self.identifier, value)?;
context.set_value(self.identifier, value)?;
Ok(Value::none())
}
@ -69,7 +73,7 @@ mod tests {
.unwrap();
assert_eq!(
context.get(&Identifier::new("foobar")),
context.get_value(&Identifier::new("foobar")),
Ok(Some(Value::integer(42)))
)
}

View File

@ -26,15 +26,15 @@ impl Identifier {
impl AbstractTree for Identifier {
fn expected_type(&self, context: &Context) -> Result<Type, ValidationError> {
if let Some(value) = context.get(self)? {
Ok(value.r#type())
if let Some(r#type) = context.get_type(self)? {
Ok(r#type)
} else {
Err(ValidationError::VariableNotFound(self.clone()))
}
}
fn validate(&self, context: &Context) -> Result<(), ValidationError> {
if let Some(_) = context.get(self)? {
if let Some(_) = context.get_data(self)? {
Ok(())
} else {
Err(ValidationError::VariableNotFound(self.clone()))
@ -42,7 +42,10 @@ impl AbstractTree for Identifier {
}
fn run(self, context: &Context) -> Result<Value, RuntimeError> {
let value = context.get(&self)?.unwrap_or_else(Value::none).clone();
let value = context
.get_value(&self)?
.unwrap_or_else(Value::none)
.clone();
Ok(value)
}

View File

@ -3,10 +3,20 @@ use std::{
sync::{Arc, RwLock},
};
use crate::{abstract_tree::Identifier, error::RwLockPoisonError, Value};
use crate::{
abstract_tree::{Identifier, Type},
error::RwLockPoisonError,
Value,
};
pub struct Context {
inner: Arc<RwLock<BTreeMap<Identifier, Value>>>,
inner: Arc<RwLock<BTreeMap<Identifier, ValueData>>>,
}
#[derive(Clone, Debug)]
pub enum ValueData {
Type(Type),
Value(Value),
}
impl Context {
@ -16,20 +26,47 @@ impl Context {
}
}
pub fn with_values(values: BTreeMap<Identifier, Value>) -> Self {
pub fn with_data(data: BTreeMap<Identifier, ValueData>) -> Self {
Self {
inner: Arc::new(RwLock::new(values)),
inner: Arc::new(RwLock::new(data)),
}
}
pub fn get(&self, identifier: &Identifier) -> Result<Option<Value>, RwLockPoisonError> {
let value = self.inner.read()?.get(identifier).cloned();
Ok(value)
pub fn get_data(
&self,
identifier: &Identifier,
) -> Result<Option<ValueData>, RwLockPoisonError> {
Ok(self.inner.read()?.get(identifier).cloned())
}
pub fn set(&self, identifier: Identifier, value: Value) -> Result<(), RwLockPoisonError> {
self.inner.write()?.insert(identifier, value);
pub fn get_type(&self, identifier: &Identifier) -> Result<Option<Type>, RwLockPoisonError> {
if let Some(ValueData::Type(r#type)) = self.inner.read()?.get(identifier) {
Ok(Some(r#type.clone()))
} else {
Ok(None)
}
}
pub fn get_value(&self, identifier: &Identifier) -> Result<Option<Value>, RwLockPoisonError> {
if let Some(ValueData::Value(value)) = self.inner.read()?.get(identifier) {
Ok(Some(value.clone()))
} else {
Ok(None)
}
}
pub fn set_type(&self, identifier: Identifier, r#type: Type) -> Result<(), RwLockPoisonError> {
self.inner
.write()?
.insert(identifier, ValueData::Type(r#type));
Ok(())
}
pub fn set_value(&self, identifier: Identifier, value: Value) -> Result<(), RwLockPoisonError> {
self.inner
.write()?
.insert(identifier, ValueData::Value(value));
Ok(())
}

View File

@ -12,6 +12,13 @@ use lexer::lex;
pub use parser::{parse, parser, DustParser};
pub use value::Value;
pub fn interpret(source: &str) -> Result<Value, Vec<Error>> {
let context = Context::new();
let mut interpreter = Interpreter::new(context);
interpreter.run(source)
}
pub struct Interpreter {
context: Context,
}

9
tests/variables.rs Normal file
View File

@ -0,0 +1,9 @@
use dust_lang::*;
#[test]
fn set_and_get_variable() {
assert_eq!(
interpret("foobar = true foobar"),
Ok(Value::boolean(true))
);
}