1
0

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)?;
function.call(arguments, function_context)
function.clone().call(arguments, function_context)
}
}

View File

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

View File

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

View File

@ -1,5 +1,3 @@
use chumsky::span::{SimpleSpan, Span};
use crate::{
context::Context,
error::{RuntimeError, ValidationError},
@ -21,37 +19,37 @@ pub enum Statement {
impl AbstractTree for Statement {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
match self {
StatementInner::Assignment(assignment) => assignment.expected_type(_context),
StatementInner::Block(block) => block.expected_type(_context),
StatementInner::Break => Ok(Type::None),
StatementInner::Expression(expression) => expression.expected_type(_context),
StatementInner::IfElse(if_else) => if_else.expected_type(_context),
StatementInner::Loop(r#loop) => r#loop.expected_type(_context),
StatementInner::While(r#while) => r#while.expected_type(_context),
Statement::Assignment(assignment) => assignment.expected_type(_context),
Statement::Block(block) => block.expected_type(_context),
Statement::Break => Ok(Type::None),
Statement::Expression(expression) => expression.expected_type(_context),
Statement::IfElse(if_else) => if_else.expected_type(_context),
Statement::Loop(r#loop) => r#loop.expected_type(_context),
Statement::While(r#while) => r#while.expected_type(_context),
}
}
fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
match self {
StatementInner::Assignment(assignment) => assignment.validate(_context),
StatementInner::Block(block) => block.validate(_context),
StatementInner::Break => Ok(()),
StatementInner::Expression(expression) => expression.validate(_context),
StatementInner::IfElse(if_else) => if_else.validate(_context),
StatementInner::Loop(r#loop) => r#loop.validate(_context),
StatementInner::While(r#while) => r#while.validate(_context),
Statement::Assignment(assignment) => assignment.validate(_context),
Statement::Block(block) => block.validate(_context),
Statement::Break => Ok(()),
Statement::Expression(expression) => expression.validate(_context),
Statement::IfElse(if_else) => if_else.validate(_context),
Statement::Loop(r#loop) => r#loop.validate(_context),
Statement::While(r#while) => r#while.validate(_context),
}
}
fn run(self, _context: &Context) -> Result<Action, RuntimeError> {
match self {
StatementInner::Assignment(assignment) => assignment.run(_context),
StatementInner::Block(block) => block.run(_context),
StatementInner::Break => Ok(Action::Break),
StatementInner::Expression(expression) => expression.run(_context),
StatementInner::IfElse(if_else) => if_else.run(_context),
StatementInner::Loop(r#loop) => r#loop.run(_context),
StatementInner::While(r#while) => r#while.run(_context),
Statement::Assignment(assignment) => assignment.run(_context),
Statement::Block(block) => block.run(_context),
Statement::Break => Ok(Action::Break),
Statement::Expression(expression) => expression.run(_context),
Statement::IfElse(if_else) => if_else.run(_context),
Statement::Loop(r#loop) => r#loop.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::{
context::Context,
error::{RuntimeError, ValidationError},
error::{RuntimeError, TypeConflict, ValidationError},
Value,
};
use super::{AbstractTree, Action, Block, Expression, Identifier, Type};
use super::{AbstractTree, Action, Block, Expression, Identifier, Positioned, Type};
#[derive(Clone, Debug, PartialEq)]
pub enum ValueNode {
@ -14,13 +14,13 @@ pub enum ValueNode {
Float(f64),
Integer(i64),
List(Vec<Expression>),
Map(Vec<(Identifier, Option<Type>, Expression)>),
Map(Vec<(Identifier, Option<Positioned<Type>>, Positioned<Expression>)>),
Range(Range<i64>),
String(String),
Function {
parameters: Vec<(Identifier, Type)>,
return_type: Type,
body: Block,
return_type: Positioned<Type>,
body: Positioned<Block>,
},
}
@ -52,7 +52,7 @@ impl AbstractTree for ValueNode {
.map(|(_, r#type)| r#type)
.cloned()
.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 {
for (_identifier, r#type, expression) in map_assignments {
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())?;
}
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(())
@ -112,7 +125,7 @@ impl AbstractTree for ValueNode {
let mut property_map = BTreeMap::new();
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);
}

View File

@ -13,7 +13,7 @@ use stanza::{
};
use crate::{
abstract_tree::{AbstractTree, Action, Block, Identifier, Type},
abstract_tree::{AbstractTree, Action, Block, Identifier, Positioned, Type},
context::Context,
error::{RuntimeError, ValidationError},
};
@ -54,7 +54,11 @@ impl Value {
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(
ParsedFunction {
parameters,
@ -223,7 +227,7 @@ impl Display for Value {
write!(f, "{identifier}: {}", r#type)?;
}
write!(f, "): {return_type} {body:?}")
write!(f, "): {} {:?}", return_type.node, body.node)
}
ValueInner::Function(Function::BuiltIn(built_in_function)) => {
write!(f, "{built_in_function}")
@ -306,7 +310,7 @@ pub enum 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 {
Function::Parsed(ParsedFunction {
parameters, body, ..
@ -315,7 +319,7 @@ impl Function {
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)?,
};
@ -327,8 +331,8 @@ impl Function {
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct ParsedFunction {
parameters: Vec<(Identifier, Type)>,
return_type: Type,
body: Block,
return_type: Positioned<Type>,
body: Positioned<Block>,
}
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]