Fix everything except the parser
This commit is contained in:
parent
e9bfd9f1f8
commit
3224c04f72
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
18
src/value.rs
18
src/value.rs
@ -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)]
|
||||
|
Loading…
Reference in New Issue
Block a user