Begin implementing type arguments
This commit is contained in:
parent
a0a9bc2fdf
commit
6b0bb0016f
@ -161,7 +161,7 @@ impl AbstractNode for Assignment {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
use crate::{
|
||||||
abstract_tree::{Expression, ValueNode},
|
abstract_tree::{Expression, ValueNode, WithPos},
|
||||||
error::TypeConflict,
|
error::TypeConflict,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ impl AbstractNode for Block {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
use crate::{
|
||||||
abstract_tree::{Expression, ValueNode},
|
abstract_tree::{Expression, ValueNode, WithPos},
|
||||||
Value,
|
Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
context::Context,
|
context::Context,
|
||||||
error::{RuntimeError, ValidationError},
|
error::{RuntimeError, ValidationError},
|
||||||
value::ValueInner,
|
value::{Function, ParsedFunction, ValueInner},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{AbstractNode, Action, Expression, Type, WithPosition};
|
use super::{AbstractNode, Action, Expression, Type, WithPosition};
|
||||||
@ -32,7 +32,7 @@ impl AbstractNode for FunctionCall {
|
|||||||
let function_node_type = self.function.node.expected_type(_context)?;
|
let function_node_type = self.function.node.expected_type(_context)?;
|
||||||
|
|
||||||
if let Type::Function { return_type, .. } = function_node_type {
|
if let Type::Function { return_type, .. } = function_node_type {
|
||||||
Ok(*return_type)
|
Ok(return_type.node)
|
||||||
} else {
|
} else {
|
||||||
Err(ValidationError::ExpectedFunction {
|
Err(ValidationError::ExpectedFunction {
|
||||||
actual: function_node_type,
|
actual: function_node_type,
|
||||||
@ -41,14 +41,31 @@ impl AbstractNode for FunctionCall {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
|
fn validate(&self, context: &Context) -> Result<(), ValidationError> {
|
||||||
for expression in &self.arguments {
|
for expression in &self.arguments {
|
||||||
expression.node.validate(_context)?;
|
expression.node.validate(context)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let function_node_type = self.function.node.expected_type(_context)?;
|
let function_node_type = self.function.node.expected_type(context)?;
|
||||||
|
|
||||||
|
if let Type::Function {
|
||||||
|
parameter_types,
|
||||||
|
return_type: _,
|
||||||
|
} = function_node_type
|
||||||
|
{
|
||||||
|
for (type_parameter, type_argument) in
|
||||||
|
parameter_types.iter().zip(self.type_arguments.iter())
|
||||||
|
{
|
||||||
|
type_parameter
|
||||||
|
.node
|
||||||
|
.check(&type_argument.node)
|
||||||
|
.map_err(|conflict| ValidationError::TypeCheck {
|
||||||
|
conflict,
|
||||||
|
actual_position: type_argument.position,
|
||||||
|
expected_position: type_parameter.position,
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
|
||||||
if let Type::Function { .. } = function_node_type {
|
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(ValidationError::ExpectedFunction {
|
Err(ValidationError::ExpectedFunction {
|
||||||
@ -94,6 +111,21 @@ impl AbstractNode for FunctionCall {
|
|||||||
|
|
||||||
let function_context = Context::new();
|
let function_context = Context::new();
|
||||||
|
|
||||||
|
if let Function::Parsed(ParsedFunction {
|
||||||
|
type_parameters, ..
|
||||||
|
}) = function
|
||||||
|
{
|
||||||
|
for (type_parameter, type_argument) in type_parameters
|
||||||
|
.iter()
|
||||||
|
.map(|r#type| r#type.node.clone())
|
||||||
|
.zip(self.type_arguments.into_iter().map(|r#type| r#type.node))
|
||||||
|
{
|
||||||
|
if let Type::Argument(identifier) = type_parameter {
|
||||||
|
function_context.set_type(identifier, type_argument)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
function_context.inherit_data_from(&context)?;
|
function_context.inherit_data_from(&context)?;
|
||||||
function.clone().call(arguments, function_context)
|
function.clone().call(arguments, function_context)
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ impl AbstractNode for IfElse {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
use crate::{
|
||||||
abstract_tree::{Statement, ValueNode},
|
abstract_tree::{Statement, ValueNode, WithPos},
|
||||||
Value,
|
Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ impl AbstractNode for ListIndex {
|
|||||||
let found_item = list.get(index as usize);
|
let found_item = list.get(index as usize);
|
||||||
|
|
||||||
if let Some(item) = found_item {
|
if let Some(item) = found_item {
|
||||||
Ok(Action::Return(item.clone()))
|
Ok(Action::Return(item.node.clone()))
|
||||||
} else {
|
} else {
|
||||||
Ok(Action::None)
|
Ok(Action::None)
|
||||||
}
|
}
|
||||||
|
@ -187,7 +187,7 @@ impl AbstractNode for Logic {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::abstract_tree::ValueNode;
|
use crate::abstract_tree::{ValueNode, WithPos};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -70,7 +70,8 @@ impl Ord for Loop {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
use crate::{
|
||||||
abstract_tree::{
|
abstract_tree::{
|
||||||
Assignment, AssignmentOperator, Block, Expression, Identifier, IfElse, Logic, ValueNode,
|
Assignment, AssignmentOperator, Block, Expression, Identifier, IfElse, Logic,
|
||||||
|
ValueNode, WithPos,
|
||||||
},
|
},
|
||||||
Value,
|
Value,
|
||||||
};
|
};
|
||||||
@ -99,19 +100,19 @@ mod tests {
|
|||||||
.with_position((0, 0)),
|
.with_position((0, 0)),
|
||||||
Statement::Loop(Loop::new(vec![Statement::IfElse(IfElse::new(
|
Statement::Loop(Loop::new(vec![Statement::IfElse(IfElse::new(
|
||||||
Expression::Logic(Box::new(Logic::Greater(
|
Expression::Logic(Box::new(Logic::Greater(
|
||||||
Expression::Identifier(Identifier::new("i")).with_position((10, 11)),
|
Expression::Identifier(Identifier::new("i")).with_position((0, 0)),
|
||||||
Expression::Value(ValueNode::Integer(2)).with_position((14, 15)),
|
Expression::Value(ValueNode::Integer(2)).with_position((0, 0)),
|
||||||
)))
|
)))
|
||||||
.with_position((10, 15)),
|
.with_position((0, 0)),
|
||||||
Block::new(vec![Statement::Break.with_position((18, 24))]),
|
Block::new(vec![Statement::Break.with_position((0, 0))]),
|
||||||
Some(Block::new(vec![Statement::Assignment(Assignment::new(
|
Some(Block::new(vec![Statement::Assignment(Assignment::new(
|
||||||
Identifier::new("i").with_position((0, 0)),
|
Identifier::new("i").with_position((0, 0)),
|
||||||
None,
|
None,
|
||||||
AssignmentOperator::AddAssign,
|
AssignmentOperator::AddAssign,
|
||||||
Statement::Expression(Expression::Value(ValueNode::Integer(1)))
|
Statement::Expression(Expression::Value(ValueNode::Integer(1)))
|
||||||
.with_position((38, 39)),
|
.with_position((0, 0)),
|
||||||
))
|
))
|
||||||
.with_position((33, 39))])),
|
.with_position((0, 0))])),
|
||||||
))
|
))
|
||||||
.with_position((0, 0))]))
|
.with_position((0, 0))]))
|
||||||
.with_position((0, 0)),
|
.with_position((0, 0)),
|
||||||
|
@ -52,6 +52,17 @@ pub struct WithPosition<T> {
|
|||||||
pub position: SourcePosition,
|
pub position: SourcePosition,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait WithPos: Sized {
|
||||||
|
fn with_position<T: Into<SourcePosition>>(self, span: T) -> WithPosition<Self> {
|
||||||
|
WithPosition {
|
||||||
|
node: self,
|
||||||
|
position: span.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> WithPos for T {}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub struct SourcePosition(pub usize, pub usize);
|
pub struct SourcePosition(pub usize, pub usize);
|
||||||
|
|
||||||
@ -164,11 +175,4 @@ pub trait AbstractNode: Sized {
|
|||||||
fn expected_type(&self, context: &Context) -> Result<Type, ValidationError>;
|
fn expected_type(&self, context: &Context) -> Result<Type, ValidationError>;
|
||||||
fn validate(&self, context: &Context) -> Result<(), ValidationError>;
|
fn validate(&self, context: &Context) -> Result<(), ValidationError>;
|
||||||
fn run(self, context: &Context) -> Result<Action, RuntimeError>;
|
fn run(self, context: &Context) -> Result<Action, RuntimeError>;
|
||||||
|
|
||||||
fn with_position<T: Into<SourcePosition>>(self, span: T) -> WithPosition<Self> {
|
|
||||||
WithPosition {
|
|
||||||
node: self,
|
|
||||||
position: span.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -17,13 +17,13 @@ pub enum Type {
|
|||||||
Boolean,
|
Boolean,
|
||||||
Float,
|
Float,
|
||||||
Function {
|
Function {
|
||||||
parameter_types: Vec<Type>,
|
parameter_types: Vec<WithPosition<Type>>,
|
||||||
return_type: Box<Type>,
|
return_type: Box<WithPosition<Type>>,
|
||||||
},
|
},
|
||||||
Integer,
|
Integer,
|
||||||
List,
|
List,
|
||||||
ListOf(Box<Type>),
|
ListOf(Box<WithPosition<Type>>),
|
||||||
ListExact(Vec<Type>),
|
ListExact(Vec<WithPosition<Type>>),
|
||||||
Map,
|
Map,
|
||||||
None,
|
None,
|
||||||
Range,
|
Range,
|
||||||
@ -52,27 +52,27 @@ impl Type {
|
|||||||
| (Type::Range, Type::Range)
|
| (Type::Range, Type::Range)
|
||||||
| (Type::String, Type::String) => return Ok(()),
|
| (Type::String, Type::String) => return Ok(()),
|
||||||
(Type::ListOf(left), Type::ListOf(right)) => {
|
(Type::ListOf(left), Type::ListOf(right)) => {
|
||||||
if let Ok(()) = left.check(right) {
|
if let Ok(()) = left.node.check(&right.node) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(Type::ListOf(list_of), Type::ListExact(list_exact)) => {
|
(Type::ListOf(list_of), Type::ListExact(list_exact)) => {
|
||||||
for r#type in list_exact {
|
for r#type in list_exact {
|
||||||
list_of.check(r#type)?;
|
list_of.node.check(&r#type.node)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
(Type::ListExact(list_exact), Type::ListOf(list_of)) => {
|
(Type::ListExact(list_exact), Type::ListOf(list_of)) => {
|
||||||
for r#type in list_exact {
|
for r#type in list_exact {
|
||||||
r#type.check(&list_of)?;
|
r#type.node.check(&list_of.node)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
(Type::ListExact(left), Type::ListExact(right)) => {
|
(Type::ListExact(left), Type::ListExact(right)) => {
|
||||||
for (left, right) in left.iter().zip(right.iter()) {
|
for (left, right) in left.iter().zip(right.iter()) {
|
||||||
left.check(right)?;
|
left.node.check(&right.node)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@ -149,15 +149,15 @@ impl Display for Type {
|
|||||||
Type::Float => write!(f, "float"),
|
Type::Float => write!(f, "float"),
|
||||||
Type::Integer => write!(f, "int"),
|
Type::Integer => write!(f, "int"),
|
||||||
Type::List => write!(f, "list"),
|
Type::List => write!(f, "list"),
|
||||||
Type::ListOf(item_type) => write!(f, "list({item_type})"),
|
Type::ListOf(item_type) => write!(f, "list({})", item_type.node),
|
||||||
Type::ListExact(item_types) => {
|
Type::ListExact(item_types) => {
|
||||||
write!(f, "[")?;
|
write!(f, "[")?;
|
||||||
|
|
||||||
for (index, item_type) in item_types.into_iter().enumerate() {
|
for (index, item_type) in item_types.into_iter().enumerate() {
|
||||||
if index == item_types.len() - 1 {
|
if index == item_types.len() - 1 {
|
||||||
write!(f, "{item_type}")?;
|
write!(f, "{}", item_type.node)?;
|
||||||
} else {
|
} else {
|
||||||
write!(f, "{item_type}, ")?;
|
write!(f, "{}, ", item_type.node)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,10 +174,10 @@ impl Display for Type {
|
|||||||
write!(f, "(")?;
|
write!(f, "(")?;
|
||||||
|
|
||||||
for r#type in parameter_types {
|
for r#type in parameter_types {
|
||||||
write!(f, "{} ", r#type)?;
|
write!(f, "{} ", r#type.node)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(f, ") : {return_type}")
|
write!(f, ") : {}", return_type.node)
|
||||||
}
|
}
|
||||||
Type::Structure { name, .. } => write!(f, "{name}"),
|
Type::Structure { name, .. } => write!(f, "{name}"),
|
||||||
Type::Argument(_) => todo!(),
|
Type::Argument(_) => todo!(),
|
||||||
@ -187,6 +187,8 @@ impl Display for Type {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use crate::abstract_tree::WithPos;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -197,12 +199,14 @@ mod tests {
|
|||||||
assert_eq!(Type::Integer.check(&Type::Integer), Ok(()));
|
assert_eq!(Type::Integer.check(&Type::Integer), Ok(()));
|
||||||
assert_eq!(Type::List.check(&Type::List), Ok(()));
|
assert_eq!(Type::List.check(&Type::List), Ok(()));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Type::ListOf(Box::new(Type::Integer)).check(&Type::ListOf(Box::new(Type::Integer))),
|
Type::ListOf(Box::new(Type::Integer.with_position((0, 0))))
|
||||||
|
.check(&Type::ListOf(Box::new(Type::Integer.with_position((0, 0))))),
|
||||||
Ok(())
|
Ok(())
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Type::ListExact(vec![Type::Float]).check(&Type::ListExact(vec![Type::Float])),
|
Type::ListExact(vec![Type::Float.with_position((0, 0))])
|
||||||
|
.check(&Type::ListExact(vec![Type::Float.with_position((0, 0))])),
|
||||||
Ok(())
|
Ok(())
|
||||||
);
|
);
|
||||||
assert_eq!(Type::Map.check(&Type::Map), Ok(()));
|
assert_eq!(Type::Map.check(&Type::Map), Ok(()));
|
||||||
@ -237,8 +241,8 @@ mod tests {
|
|||||||
Type::Float,
|
Type::Float,
|
||||||
Type::Integer,
|
Type::Integer,
|
||||||
Type::List,
|
Type::List,
|
||||||
Type::ListOf(Box::new(Type::Boolean)),
|
Type::ListOf(Box::new(Type::Boolean.with_position((0, 0)))),
|
||||||
Type::ListExact(vec![Type::Integer]),
|
Type::ListExact(vec![Type::Integer.with_position((0, 0))]),
|
||||||
Type::Map,
|
Type::Map,
|
||||||
Type::None,
|
Type::None,
|
||||||
Type::Range,
|
Type::Range,
|
||||||
@ -263,8 +267,11 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn check_list_types() {
|
fn check_list_types() {
|
||||||
let list = Type::List;
|
let list = Type::List;
|
||||||
let list_exact = Type::ListExact(vec![Type::Integer, Type::Integer]);
|
let list_exact = Type::ListExact(vec![
|
||||||
let list_of = Type::ListOf(Box::new(Type::Integer));
|
Type::Integer.with_position((0, 0)),
|
||||||
|
Type::Integer.with_position((0, 0)),
|
||||||
|
]);
|
||||||
|
let list_of = Type::ListOf(Box::new(Type::Integer.with_position((0, 0))));
|
||||||
|
|
||||||
assert_eq!(list.check(&list_exact), Ok(()));
|
assert_eq!(list.check(&list_exact), Ok(()));
|
||||||
assert_eq!(list.check(&list_of), Ok(()));
|
assert_eq!(list.check(&list_of), Ok(()));
|
||||||
|
@ -7,7 +7,7 @@ use crate::{
|
|||||||
Value,
|
Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{AbstractNode, Action, Block, Expression, Identifier, Type, WithPosition};
|
use super::{AbstractNode, Action, Block, Expression, Identifier, Type, WithPos, WithPosition};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum ValueNode {
|
pub enum ValueNode {
|
||||||
@ -47,7 +47,12 @@ impl AbstractNode for ValueNode {
|
|||||||
let mut item_types = Vec::with_capacity(items.len());
|
let mut item_types = Vec::with_capacity(items.len());
|
||||||
|
|
||||||
for expression in items {
|
for expression in items {
|
||||||
item_types.push(expression.node.expected_type(context)?);
|
item_types.push(
|
||||||
|
expression
|
||||||
|
.node
|
||||||
|
.expected_type(context)?
|
||||||
|
.with_position(expression.position),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Type::ListExact(item_types)
|
Type::ListExact(item_types)
|
||||||
@ -61,10 +66,10 @@ impl AbstractNode for ValueNode {
|
|||||||
..
|
..
|
||||||
} => Type::Function {
|
} => Type::Function {
|
||||||
parameter_types: parameters
|
parameter_types: parameters
|
||||||
.into_iter()
|
.iter()
|
||||||
.map(|(_, r#type)| r#type.node.clone())
|
.map(|(_, r#type)| r#type.clone())
|
||||||
.collect(),
|
.collect(),
|
||||||
return_type: Box::new(return_type.node.clone()),
|
return_type: Box::new(return_type.clone()),
|
||||||
},
|
},
|
||||||
ValueNode::Structure {
|
ValueNode::Structure {
|
||||||
name,
|
name,
|
||||||
@ -185,7 +190,10 @@ impl AbstractNode for ValueNode {
|
|||||||
for expression in expression_list {
|
for expression in expression_list {
|
||||||
let action = expression.node.run(_context)?;
|
let action = expression.node.run(_context)?;
|
||||||
let value = if let Action::Return(value) = action {
|
let value = if let Action::Return(value) = action {
|
||||||
value
|
WithPosition {
|
||||||
|
node: value,
|
||||||
|
position: expression.position,
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(RuntimeError::ValidationFailure(
|
return Err(RuntimeError::ValidationFailure(
|
||||||
ValidationError::InterpreterExpectedReturn(expression.position),
|
ValidationError::InterpreterExpectedReturn(expression.position),
|
||||||
|
@ -74,7 +74,7 @@ impl AbstractNode for While {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::abstract_tree::{
|
use crate::abstract_tree::{
|
||||||
Assignment, AssignmentOperator, Block, Identifier, Logic, ValueNode,
|
Assignment, AssignmentOperator, Block, Identifier, Logic, ValueNode, WithPos,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -6,7 +6,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
abstract_tree::{Action, Type},
|
abstract_tree::{Action, Type, WithPos},
|
||||||
context::Context,
|
context::Context,
|
||||||
error::RuntimeError,
|
error::RuntimeError,
|
||||||
value::ValueInner,
|
value::ValueInner,
|
||||||
@ -36,8 +36,8 @@ impl BuiltInFunction {
|
|||||||
pub fn r#type(&self) -> Type {
|
pub fn r#type(&self) -> Type {
|
||||||
match self {
|
match self {
|
||||||
BuiltInFunction::WriteLine => Type::Function {
|
BuiltInFunction::WriteLine => Type::Function {
|
||||||
parameter_types: vec![Type::String],
|
parameter_types: vec![Type::String.with_position((0, 0))],
|
||||||
return_type: Box::new(Type::None),
|
return_type: Box::new(Type::None.with_position((0, 0))),
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
todo!()
|
todo!()
|
||||||
|
@ -121,8 +121,8 @@ pub fn parser<'src>() -> impl Parser<
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
))
|
))
|
||||||
})
|
.map_with(|r#type, state| r#type.with_position(state.span()))
|
||||||
.map_with(|r#type, state| r#type.with_position(state.span()));
|
});
|
||||||
|
|
||||||
let type_argument = identifier
|
let type_argument = identifier
|
||||||
.clone()
|
.clone()
|
||||||
@ -759,7 +759,10 @@ mod tests {
|
|||||||
parse(&lex("foobar : list(bool) = [true]").unwrap()).unwrap()[0].node,
|
parse(&lex("foobar : list(bool) = [true]").unwrap()).unwrap()[0].node,
|
||||||
Statement::Assignment(Assignment::new(
|
Statement::Assignment(Assignment::new(
|
||||||
Identifier::new("foobar").with_position((0, 6)),
|
Identifier::new("foobar").with_position((0, 6)),
|
||||||
Some(Type::ListOf(Box::new(Type::Boolean)).with_position((9, 19))),
|
Some(
|
||||||
|
Type::ListOf(Box::new(Type::Boolean.with_position((14, 18))))
|
||||||
|
.with_position((9, 19))
|
||||||
|
),
|
||||||
AssignmentOperator::Assign,
|
AssignmentOperator::Assign,
|
||||||
Statement::Expression(Expression::Value(ValueNode::List(vec![Expression::Value(
|
Statement::Expression(Expression::Value(ValueNode::List(vec![Expression::Value(
|
||||||
ValueNode::Boolean(true)
|
ValueNode::Boolean(true)
|
||||||
@ -776,7 +779,13 @@ mod tests {
|
|||||||
parse(&lex("foobar : [bool, str] = [true, '42']").unwrap()).unwrap()[0],
|
parse(&lex("foobar : [bool, str] = [true, '42']").unwrap()).unwrap()[0],
|
||||||
Statement::Assignment(Assignment::new(
|
Statement::Assignment(Assignment::new(
|
||||||
Identifier::new("foobar").with_position((0, 6)),
|
Identifier::new("foobar").with_position((0, 6)),
|
||||||
Some(Type::ListExact(vec![Type::Boolean, Type::String]).with_position((9, 20))),
|
Some(
|
||||||
|
Type::ListExact(vec![
|
||||||
|
Type::Boolean.with_position((10, 14)),
|
||||||
|
Type::String.with_position((16, 19))
|
||||||
|
])
|
||||||
|
.with_position((9, 20))
|
||||||
|
),
|
||||||
AssignmentOperator::Assign,
|
AssignmentOperator::Assign,
|
||||||
Statement::Expression(Expression::Value(ValueNode::List(vec![
|
Statement::Expression(Expression::Value(ValueNode::List(vec![
|
||||||
Expression::Value(ValueNode::Boolean(true)).with_position((24, 28)),
|
Expression::Value(ValueNode::Boolean(true)).with_position((24, 28)),
|
||||||
@ -797,7 +806,7 @@ mod tests {
|
|||||||
Some(
|
Some(
|
||||||
Type::Function {
|
Type::Function {
|
||||||
parameter_types: vec![],
|
parameter_types: vec![],
|
||||||
return_type: Box::new(Type::Any)
|
return_type: Box::new(Type::Any.with_position((17, 20)))
|
||||||
}
|
}
|
||||||
.with_position((9, 20))
|
.with_position((9, 20))
|
||||||
),
|
),
|
||||||
|
@ -13,7 +13,7 @@ use stanza::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
abstract_tree::{AbstractNode, Action, Block, Identifier, Type, WithPosition},
|
abstract_tree::{AbstractNode, Action, Block, Identifier, Type, WithPos, WithPosition},
|
||||||
built_in_functions::BuiltInFunction,
|
built_in_functions::BuiltInFunction,
|
||||||
context::Context,
|
context::Context,
|
||||||
error::{RuntimeError, ValidationError},
|
error::{RuntimeError, ValidationError},
|
||||||
@ -39,7 +39,7 @@ impl Value {
|
|||||||
Value(Arc::new(ValueInner::Integer(integer)))
|
Value(Arc::new(ValueInner::Integer(integer)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list(list: Vec<Value>) -> Self {
|
pub fn list(list: Vec<WithPosition<Value>>) -> Self {
|
||||||
Value(Arc::new(ValueInner::List(list)))
|
Value(Arc::new(ValueInner::List(list)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ impl Value {
|
|||||||
) -> Self {
|
) -> Self {
|
||||||
Value(Arc::new(ValueInner::Function(Function::Parsed(
|
Value(Arc::new(ValueInner::Function(Function::Parsed(
|
||||||
ParsedFunction {
|
ParsedFunction {
|
||||||
type_arguments,
|
type_parameters: type_arguments,
|
||||||
parameters,
|
parameters,
|
||||||
return_type,
|
return_type,
|
||||||
body,
|
body,
|
||||||
@ -91,7 +91,7 @@ impl Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_list(&self) -> Option<&Vec<Value>> {
|
pub fn as_list(&self) -> Option<&Vec<WithPosition<Value>>> {
|
||||||
if let ValueInner::List(list) = self.inner().as_ref() {
|
if let ValueInner::List(list) = self.inner().as_ref() {
|
||||||
Some(list)
|
Some(list)
|
||||||
} else {
|
} else {
|
||||||
@ -122,7 +122,7 @@ impl Display for Value {
|
|||||||
let mut table = create_table();
|
let mut table = create_table();
|
||||||
|
|
||||||
for value in list {
|
for value in list {
|
||||||
table = table.with_row([value.to_string()]);
|
table = table.with_row([value.node.to_string()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(f, "{}", Console::default().render(&table))
|
write!(f, "{}", Console::default().render(&table))
|
||||||
@ -139,7 +139,7 @@ impl Display for Value {
|
|||||||
ValueInner::Range(_) => todo!(),
|
ValueInner::Range(_) => todo!(),
|
||||||
ValueInner::String(string) => write!(f, "{string}"),
|
ValueInner::String(string) => write!(f, "{string}"),
|
||||||
ValueInner::Function(Function::Parsed(ParsedFunction {
|
ValueInner::Function(Function::Parsed(ParsedFunction {
|
||||||
type_arguments,
|
type_parameters: type_arguments,
|
||||||
parameters,
|
parameters,
|
||||||
return_type,
|
return_type,
|
||||||
body,
|
body,
|
||||||
@ -202,7 +202,7 @@ pub enum ValueInner {
|
|||||||
Float(f64),
|
Float(f64),
|
||||||
Function(Function),
|
Function(Function),
|
||||||
Integer(i64),
|
Integer(i64),
|
||||||
List(Vec<Value>),
|
List(Vec<WithPosition<Value>>),
|
||||||
Map(BTreeMap<Identifier, Value>),
|
Map(BTreeMap<Identifier, Value>),
|
||||||
Range(Range<i64>),
|
Range(Range<i64>),
|
||||||
String(String),
|
String(String),
|
||||||
@ -222,7 +222,7 @@ impl ValueInner {
|
|||||||
let mut types = Vec::with_capacity(values.len());
|
let mut types = Vec::with_capacity(values.len());
|
||||||
|
|
||||||
for value in values {
|
for value in values {
|
||||||
types.push(value.r#type(context)?);
|
types.push(value.node.r#type(context)?.with_position(value.position));
|
||||||
}
|
}
|
||||||
|
|
||||||
Type::ListExact(types)
|
Type::ListExact(types)
|
||||||
@ -235,9 +235,9 @@ impl ValueInner {
|
|||||||
parameter_types: parsed_function
|
parameter_types: parsed_function
|
||||||
.parameters
|
.parameters
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(_, r#type)| r#type.node.clone())
|
.map(|(_, r#type)| r#type.clone())
|
||||||
.collect(),
|
.collect(),
|
||||||
return_type: Box::new(parsed_function.return_type.node.clone()),
|
return_type: Box::new(parsed_function.return_type.clone()),
|
||||||
},
|
},
|
||||||
Function::BuiltIn(built_in_function) => {
|
Function::BuiltIn(built_in_function) => {
|
||||||
built_in_function.clone().as_value().r#type(context)?
|
built_in_function.clone().as_value().r#type(context)?
|
||||||
@ -343,8 +343,8 @@ impl Function {
|
|||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub struct ParsedFunction {
|
pub struct ParsedFunction {
|
||||||
type_arguments: Vec<WithPosition<Type>>,
|
pub type_parameters: Vec<WithPosition<Type>>,
|
||||||
parameters: Vec<(Identifier, WithPosition<Type>)>,
|
pub parameters: Vec<(Identifier, WithPosition<Type>)>,
|
||||||
return_type: WithPosition<Type>,
|
pub return_type: WithPosition<Type>,
|
||||||
body: WithPosition<Block>,
|
pub body: WithPosition<Block>,
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::{collections::BTreeMap, rc::Rc};
|
use std::{collections::BTreeMap, rc::Rc};
|
||||||
|
|
||||||
use dust_lang::{
|
use dust_lang::{
|
||||||
abstract_tree::{Identifier, Type},
|
abstract_tree::{Identifier, Type, WithPos},
|
||||||
error::{Error, TypeConflict, ValidationError},
|
error::{Error, TypeConflict, ValidationError},
|
||||||
*,
|
*,
|
||||||
};
|
};
|
||||||
@ -100,9 +100,9 @@ fn list() {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
interpret(Rc::new("test".to_string()), "[1, 2, 'foobar']"),
|
interpret(Rc::new("test".to_string()), "[1, 2, 'foobar']"),
|
||||||
Ok(Some(Value::list(vec![
|
Ok(Some(Value::list(vec![
|
||||||
Value::integer(1),
|
Value::integer(1).with_position((1, 2)),
|
||||||
Value::integer(2),
|
Value::integer(2).with_position((4, 5)),
|
||||||
Value::string("foobar".to_string()),
|
Value::string("foobar".to_string()).with_position((7, 15)),
|
||||||
])))
|
])))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use dust_lang::{
|
use dust_lang::{
|
||||||
abstract_tree::{AbstractNode, Block, Expression, Identifier, Statement, Type},
|
abstract_tree::{Block, Expression, Identifier, Statement, Type, WithPos},
|
||||||
error::{Error, TypeConflict, ValidationError},
|
error::{Error, TypeConflict, ValidationError},
|
||||||
*,
|
*,
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user