Fix everything except the parser

This commit is contained in:
Jeff 2024-03-17 01:26:05 -04:00
parent e9bfd9f1f8
commit 3224c04f72
6 changed files with 131 additions and 104 deletions

View File

@ -50,6 +50,6 @@ impl AbstractTree for FunctionCall {
let function_context = Context::inherit_data_from(context)?; let function_context = Context::inherit_data_from(context)?;
function.call(arguments, function_context) function.clone().call(arguments, function_context)
} }
} }

View File

@ -4,19 +4,19 @@ use crate::{
Value, Value,
}; };
use super::{AbstractTree, Action, Expression, Type}; use super::{AbstractTree, Action, Expression, Positioned, Type};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub enum Logic { pub enum Logic {
Equal(Expression, Expression), Equal(Positioned<Expression>, Positioned<Expression>),
NotEqual(Expression, Expression), NotEqual(Positioned<Expression>, Positioned<Expression>),
Greater(Expression, Expression), Greater(Positioned<Expression>, Positioned<Expression>),
Less(Expression, Expression), Less(Positioned<Expression>, Positioned<Expression>),
GreaterOrEqual(Expression, Expression), GreaterOrEqual(Positioned<Expression>, Positioned<Expression>),
LessOrEqual(Expression, Expression), LessOrEqual(Positioned<Expression>, Positioned<Expression>),
And(Expression, Expression), And(Positioned<Expression>, Positioned<Expression>),
Or(Expression, Expression), Or(Positioned<Expression>, Positioned<Expression>),
Not(Expression), Not(Positioned<Expression>),
} }
impl AbstractTree for Logic { impl AbstractTree for Logic {
@ -32,16 +32,22 @@ impl AbstractTree for Logic {
| Logic::Less(left, right) | Logic::Less(left, right)
| Logic::GreaterOrEqual(left, right) | Logic::GreaterOrEqual(left, right)
| Logic::LessOrEqual(left, right) => { | Logic::LessOrEqual(left, right) => {
let left = left.expected_type(context)?; let left_type = left.node.expected_type(context)?;
let right = right.expected_type(context)?; let right_type = right.node.expected_type(context)?;
left.check(&right)?; left_type
.check(&right_type)
.map_err(|conflict| ValidationError::TypeCheck {
conflict,
actual_position: left.position,
expected_position: right.position,
})?;
Ok(()) Ok(())
} }
Logic::And(left, right) | Logic::Or(left, right) => { Logic::And(left, right) | Logic::Or(left, right) => {
let left = left.expected_type(context)?; let left = left.node.expected_type(context)?;
let right = right.expected_type(context)?; let right = right.node.expected_type(context)?;
if let (Type::Boolean, Type::Boolean) = (left, right) { if let (Type::Boolean, Type::Boolean) = (left, right) {
Ok(()) Ok(())
@ -50,7 +56,7 @@ impl AbstractTree for Logic {
} }
} }
Logic::Not(expression) => { Logic::Not(expression) => {
if let Type::Boolean = expression.expected_type(context)? { if let Type::Boolean = expression.node.expected_type(context)? {
Ok(()) Ok(())
} else { } else {
Err(ValidationError::ExpectedBoolean) Err(ValidationError::ExpectedBoolean)
@ -62,55 +68,59 @@ impl AbstractTree for Logic {
fn run(self, _context: &Context) -> Result<Action, RuntimeError> { fn run(self, _context: &Context) -> Result<Action, RuntimeError> {
let boolean = match self { let boolean = match self {
Logic::Equal(left, right) => { Logic::Equal(left, right) => {
let left = left.run(_context)?.as_return_value()?; let left = left.node.run(_context)?.as_return_value()?;
let right = right.run(_context)?.as_return_value()?; let right = right.node.run(_context)?.as_return_value()?;
left == right left == right
} }
Logic::NotEqual(left, right) => { Logic::NotEqual(left, right) => {
let left = left.run(_context)?.as_return_value()?; let left = left.node.run(_context)?.as_return_value()?;
let right = right.run(_context)?.as_return_value()?; let right = right.node.run(_context)?.as_return_value()?;
left != right left != right
} }
Logic::Greater(left, right) => { Logic::Greater(left, right) => {
let left = left.run(_context)?.as_return_value()?; let left = left.node.run(_context)?.as_return_value()?;
let right = right.run(_context)?.as_return_value()?; let right = right.node.run(_context)?.as_return_value()?;
left > right left > right
} }
Logic::Less(left, right) => { Logic::Less(left, right) => {
let left = left.run(_context)?.as_return_value()?; let left = left.node.run(_context)?.as_return_value()?;
let right = right.run(_context)?.as_return_value()?; let right = right.node.run(_context)?.as_return_value()?;
left < right left < right
} }
Logic::GreaterOrEqual(left, right) => { Logic::GreaterOrEqual(left, right) => {
let left = left.run(_context)?.as_return_value()?; let left = left.node.run(_context)?.as_return_value()?;
let right = right.run(_context)?.as_return_value()?; let right = right.node.run(_context)?.as_return_value()?;
left >= right left >= right
} }
Logic::LessOrEqual(left, right) => { Logic::LessOrEqual(left, right) => {
let left = left.run(_context)?.as_return_value()?; let left = left.node.run(_context)?.as_return_value()?;
let right = right.run(_context)?.as_return_value()?; let right = right.node.run(_context)?.as_return_value()?;
left <= right left <= right
} }
Logic::And(left, right) => { Logic::And(left, right) => {
let left = left.run(_context)?.as_return_value()?.as_boolean()?; let left = left.node.run(_context)?.as_return_value()?.as_boolean()?;
let right = right.run(_context)?.as_return_value()?.as_boolean()?; let right = right.node.run(_context)?.as_return_value()?.as_boolean()?;
left && right left && right
} }
Logic::Or(left, right) => { Logic::Or(left, right) => {
let left = left.run(_context)?.as_return_value()?.as_boolean()?; let left = left.node.run(_context)?.as_return_value()?.as_boolean()?;
let right = right.run(_context)?.as_return_value()?.as_boolean()?; let right = right.node.run(_context)?.as_return_value()?.as_boolean()?;
left || right left || right
} }
Logic::Not(statement) => { Logic::Not(statement) => {
let boolean = statement.run(_context)?.as_return_value()?.as_boolean()?; let boolean = statement
.node
.run(_context)?
.as_return_value()?
.as_boolean()?;
!boolean !boolean
} }
@ -129,8 +139,8 @@ mod tests {
#[test] #[test]
fn equal() { fn equal() {
assert!(Logic::Equal( assert!(Logic::Equal(
Expression::Value(ValueNode::Integer(42)), Expression::Value(ValueNode::Integer(42)).positioned((0, 0)),
Expression::Value(ValueNode::Integer(42)), Expression::Value(ValueNode::Integer(42)).positioned((0, 0)),
) )
.run(&Context::new()) .run(&Context::new())
.unwrap() .unwrap()
@ -143,8 +153,8 @@ mod tests {
#[test] #[test]
fn not_equal() { fn not_equal() {
assert!(Logic::NotEqual( assert!(Logic::NotEqual(
Expression::Value(ValueNode::Integer(42)), Expression::Value(ValueNode::Integer(42)).positioned((0, 0)),
Expression::Value(ValueNode::Integer(43)), Expression::Value(ValueNode::Integer(43)).positioned((0, 0)),
) )
.run(&Context::new()) .run(&Context::new())
.unwrap() .unwrap()
@ -157,8 +167,8 @@ mod tests {
#[test] #[test]
fn greater() { fn greater() {
assert!(Logic::Greater( assert!(Logic::Greater(
Expression::Value(ValueNode::Integer(43)), Expression::Value(ValueNode::Integer(43)).positioned((0, 0)),
Expression::Value(ValueNode::Integer(42)), Expression::Value(ValueNode::Integer(42)).positioned((0, 0)),
) )
.run(&Context::new()) .run(&Context::new())
.unwrap() .unwrap()
@ -171,8 +181,8 @@ mod tests {
#[test] #[test]
fn less() { fn less() {
assert!(Logic::Less( assert!(Logic::Less(
Expression::Value(ValueNode::Integer(42)), Expression::Value(ValueNode::Integer(42)).positioned((0, 0)),
Expression::Value(ValueNode::Integer(43)), Expression::Value(ValueNode::Integer(43)).positioned((0, 0)),
) )
.run(&Context::new()) .run(&Context::new())
.unwrap() .unwrap()
@ -185,8 +195,8 @@ mod tests {
#[test] #[test]
fn greater_or_equal() { fn greater_or_equal() {
assert!(Logic::GreaterOrEqual( assert!(Logic::GreaterOrEqual(
Expression::Value(ValueNode::Integer(42)), Expression::Value(ValueNode::Integer(42)).positioned((0, 0)),
Expression::Value(ValueNode::Integer(41)), Expression::Value(ValueNode::Integer(41)).positioned((0, 0)),
) )
.run(&Context::new()) .run(&Context::new())
.unwrap() .unwrap()
@ -196,8 +206,8 @@ mod tests {
.unwrap()); .unwrap());
assert!(Logic::GreaterOrEqual( assert!(Logic::GreaterOrEqual(
Expression::Value(ValueNode::Integer(42)), Expression::Value(ValueNode::Integer(42)).positioned((0, 0)),
Expression::Value(ValueNode::Integer(42)), Expression::Value(ValueNode::Integer(42)).positioned((0, 0)),
) )
.run(&Context::new()) .run(&Context::new())
.unwrap() .unwrap()
@ -210,8 +220,8 @@ mod tests {
#[test] #[test]
fn less_or_equal() { fn less_or_equal() {
assert!(Logic::LessOrEqual( assert!(Logic::LessOrEqual(
Expression::Value(ValueNode::Integer(42)), Expression::Value(ValueNode::Integer(42)).positioned((0, 0)),
Expression::Value(ValueNode::Integer(43)), Expression::Value(ValueNode::Integer(43)).positioned((0, 0)),
) )
.run(&Context::new()) .run(&Context::new())
.unwrap() .unwrap()
@ -221,8 +231,8 @@ mod tests {
.unwrap()); .unwrap());
assert!(Logic::LessOrEqual( assert!(Logic::LessOrEqual(
Expression::Value(ValueNode::Integer(42)), Expression::Value(ValueNode::Integer(42)).positioned((0, 0)),
Expression::Value(ValueNode::Integer(42)), Expression::Value(ValueNode::Integer(42)).positioned((0, 0)),
) )
.run(&Context::new()) .run(&Context::new())
.unwrap() .unwrap()
@ -235,8 +245,8 @@ mod tests {
#[test] #[test]
fn and() { fn and() {
assert!(Logic::And( assert!(Logic::And(
Expression::Value(ValueNode::Boolean(true)), Expression::Value(ValueNode::Boolean(true)).positioned((0, 0)),
Expression::Value(ValueNode::Boolean(true)), Expression::Value(ValueNode::Boolean(true)).positioned((0, 0)),
) )
.run(&Context::new()) .run(&Context::new())
.unwrap() .unwrap()
@ -249,8 +259,8 @@ mod tests {
#[test] #[test]
fn or() { fn or() {
assert!(Logic::Or( assert!(Logic::Or(
Expression::Value(ValueNode::Boolean(true)), Expression::Value(ValueNode::Boolean(true)).positioned((0, 0)),
Expression::Value(ValueNode::Boolean(false)), Expression::Value(ValueNode::Boolean(false)).positioned((0, 0)),
) )
.run(&Context::new()) .run(&Context::new())
.unwrap() .unwrap()
@ -262,12 +272,14 @@ mod tests {
#[test] #[test]
fn not() { fn not() {
assert!(Logic::Not(Expression::Value(ValueNode::Boolean(false))) assert!(
.run(&Context::new()) Logic::Not(Expression::Value(ValueNode::Boolean(false)).positioned((0, 0)))
.unwrap() .run(&Context::new())
.as_return_value() .unwrap()
.unwrap() .as_return_value()
.as_boolean() .unwrap()
.unwrap()) .as_boolean()
.unwrap()
)
} }
} }

View File

@ -58,7 +58,7 @@ mod tests {
#[test] #[test]
fn basic_loop() { fn basic_loop() {
let result = Loop { let result = Loop {
statements: vec![Statement::r#break((0..1).into())], statements: vec![Statement::Break],
} }
.run(&Context::new()); .run(&Context::new());

View File

@ -1,5 +1,3 @@
use chumsky::span::{SimpleSpan, Span};
use crate::{ use crate::{
context::Context, context::Context,
error::{RuntimeError, ValidationError}, error::{RuntimeError, ValidationError},
@ -21,37 +19,37 @@ pub enum Statement {
impl AbstractTree for Statement { impl AbstractTree for Statement {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> { fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
match self { match self {
StatementInner::Assignment(assignment) => assignment.expected_type(_context), Statement::Assignment(assignment) => assignment.expected_type(_context),
StatementInner::Block(block) => block.expected_type(_context), Statement::Block(block) => block.expected_type(_context),
StatementInner::Break => Ok(Type::None), Statement::Break => Ok(Type::None),
StatementInner::Expression(expression) => expression.expected_type(_context), Statement::Expression(expression) => expression.expected_type(_context),
StatementInner::IfElse(if_else) => if_else.expected_type(_context), Statement::IfElse(if_else) => if_else.expected_type(_context),
StatementInner::Loop(r#loop) => r#loop.expected_type(_context), Statement::Loop(r#loop) => r#loop.expected_type(_context),
StatementInner::While(r#while) => r#while.expected_type(_context), Statement::While(r#while) => r#while.expected_type(_context),
} }
} }
fn validate(&self, _context: &Context) -> Result<(), ValidationError> { fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
match self { match self {
StatementInner::Assignment(assignment) => assignment.validate(_context), Statement::Assignment(assignment) => assignment.validate(_context),
StatementInner::Block(block) => block.validate(_context), Statement::Block(block) => block.validate(_context),
StatementInner::Break => Ok(()), Statement::Break => Ok(()),
StatementInner::Expression(expression) => expression.validate(_context), Statement::Expression(expression) => expression.validate(_context),
StatementInner::IfElse(if_else) => if_else.validate(_context), Statement::IfElse(if_else) => if_else.validate(_context),
StatementInner::Loop(r#loop) => r#loop.validate(_context), Statement::Loop(r#loop) => r#loop.validate(_context),
StatementInner::While(r#while) => r#while.validate(_context), Statement::While(r#while) => r#while.validate(_context),
} }
} }
fn run(self, _context: &Context) -> Result<Action, RuntimeError> { fn run(self, _context: &Context) -> Result<Action, RuntimeError> {
match self { match self {
StatementInner::Assignment(assignment) => assignment.run(_context), Statement::Assignment(assignment) => assignment.run(_context),
StatementInner::Block(block) => block.run(_context), Statement::Block(block) => block.run(_context),
StatementInner::Break => Ok(Action::Break), Statement::Break => Ok(Action::Break),
StatementInner::Expression(expression) => expression.run(_context), Statement::Expression(expression) => expression.run(_context),
StatementInner::IfElse(if_else) => if_else.run(_context), Statement::IfElse(if_else) => if_else.run(_context),
StatementInner::Loop(r#loop) => r#loop.run(_context), Statement::Loop(r#loop) => r#loop.run(_context),
StatementInner::While(r#while) => r#while.run(_context), Statement::While(r#while) => r#while.run(_context),
} }
} }
} }

View File

@ -2,11 +2,11 @@ use std::{cmp::Ordering, collections::BTreeMap, ops::Range};
use crate::{ use crate::{
context::Context, context::Context,
error::{RuntimeError, ValidationError}, error::{RuntimeError, TypeConflict, ValidationError},
Value, Value,
}; };
use super::{AbstractTree, Action, Block, Expression, Identifier, Type}; use super::{AbstractTree, Action, Block, Expression, Identifier, Positioned, Type};
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub enum ValueNode { pub enum ValueNode {
@ -14,13 +14,13 @@ pub enum ValueNode {
Float(f64), Float(f64),
Integer(i64), Integer(i64),
List(Vec<Expression>), List(Vec<Expression>),
Map(Vec<(Identifier, Option<Type>, Expression)>), Map(Vec<(Identifier, Option<Positioned<Type>>, Positioned<Expression>)>),
Range(Range<i64>), Range(Range<i64>),
String(String), String(String),
Function { Function {
parameters: Vec<(Identifier, Type)>, parameters: Vec<(Identifier, Type)>,
return_type: Type, return_type: Positioned<Type>,
body: Block, body: Positioned<Block>,
}, },
} }
@ -52,7 +52,7 @@ impl AbstractTree for ValueNode {
.map(|(_, r#type)| r#type) .map(|(_, r#type)| r#type)
.cloned() .cloned()
.collect(), .collect(),
return_type: Box::new(return_type.clone()), return_type: Box::new(return_type.node.clone()),
}, },
}; };
@ -63,9 +63,15 @@ impl AbstractTree for ValueNode {
if let ValueNode::Map(map_assignments) = self { if let ValueNode::Map(map_assignments) = self {
for (_identifier, r#type, expression) in map_assignments { for (_identifier, r#type, expression) in map_assignments {
if let Some(expected_type) = r#type { if let Some(expected_type) = r#type {
let actual_type = expression.expected_type(context)?; let actual_type = expression.node.expected_type(context)?;
expected_type.check(&actual_type)?; expected_type.node.check(&actual_type).map_err(|conflict| {
ValidationError::TypeCheck {
conflict,
actual_position: expression.position,
expected_position: expected_type.position,
}
});
} }
} }
} }
@ -82,11 +88,18 @@ impl AbstractTree for ValueNode {
function_context.set_type(identifier.clone(), r#type.clone())?; function_context.set_type(identifier.clone(), r#type.clone())?;
} }
body.validate(&function_context)?; body.node.validate(&function_context)?;
let actual_return_type = body.expected_type(&function_context)?; let actual_return_type = body.node.expected_type(&function_context)?;
return_type.check(&actual_return_type)?; return_type
.node
.check(&actual_return_type)
.map_err(|conflict| ValidationError::TypeCheck {
conflict,
actual_position: body.position,
expected_position: return_type.position,
})?;
} }
Ok(()) Ok(())
@ -112,7 +125,7 @@ impl AbstractTree for ValueNode {
let mut property_map = BTreeMap::new(); let mut property_map = BTreeMap::new();
for (identifier, _type, expression) in property_list { for (identifier, _type, expression) in property_list {
let value = expression.run(_context)?.as_return_value()?; let value = expression.node.run(_context)?.as_return_value()?;
property_map.insert(identifier, value); property_map.insert(identifier, value);
} }

View File

@ -13,7 +13,7 @@ use stanza::{
}; };
use crate::{ use crate::{
abstract_tree::{AbstractTree, Action, Block, Identifier, Type}, abstract_tree::{AbstractTree, Action, Block, Identifier, Positioned, Type},
context::Context, context::Context,
error::{RuntimeError, ValidationError}, error::{RuntimeError, ValidationError},
}; };
@ -54,7 +54,11 @@ impl Value {
Value(Arc::new(ValueInner::String(string))) Value(Arc::new(ValueInner::String(string)))
} }
pub fn function(parameters: Vec<(Identifier, Type)>, return_type: Type, body: Block) -> Self { pub fn function(
parameters: Vec<(Identifier, Type)>,
return_type: Positioned<Type>,
body: Positioned<Block>,
) -> Self {
Value(Arc::new(ValueInner::Function(Function::Parsed( Value(Arc::new(ValueInner::Function(Function::Parsed(
ParsedFunction { ParsedFunction {
parameters, parameters,
@ -223,7 +227,7 @@ impl Display for Value {
write!(f, "{identifier}: {}", r#type)?; write!(f, "{identifier}: {}", r#type)?;
} }
write!(f, "): {return_type} {body:?}") write!(f, "): {} {:?}", return_type.node, body.node)
} }
ValueInner::Function(Function::BuiltIn(built_in_function)) => { ValueInner::Function(Function::BuiltIn(built_in_function)) => {
write!(f, "{built_in_function}") write!(f, "{built_in_function}")
@ -306,7 +310,7 @@ pub enum Function {
} }
impl Function { impl Function {
pub fn call(&self, arguments: Vec<Value>, context: Context) -> Result<Action, RuntimeError> { pub fn call(self, arguments: Vec<Value>, context: Context) -> Result<Action, RuntimeError> {
let action = match self { let action = match self {
Function::Parsed(ParsedFunction { Function::Parsed(ParsedFunction {
parameters, body, .. parameters, body, ..
@ -315,7 +319,7 @@ impl Function {
context.set_value(identifier.clone(), value)?; context.set_value(identifier.clone(), value)?;
} }
body.clone().run(&context)? body.node.run(&context)?
} }
Function::BuiltIn(built_in_function) => built_in_function.call(arguments, &context)?, Function::BuiltIn(built_in_function) => built_in_function.call(arguments, &context)?,
}; };
@ -327,8 +331,8 @@ impl Function {
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct ParsedFunction { pub struct ParsedFunction {
parameters: Vec<(Identifier, Type)>, parameters: Vec<(Identifier, Type)>,
return_type: Type, return_type: Positioned<Type>,
body: Block, body: Positioned<Block>,
} }
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]