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)?;
|
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,
|
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()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
|
|
||||||
|
@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
18
src/value.rs
18
src/value.rs
@ -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)]
|
||||||
|
Loading…
Reference in New Issue
Block a user