2024-08-07 14:03:33 +00:00
|
|
|
use std::{
|
2024-08-07 15:38:08 +00:00
|
|
|
collections::{HashMap, VecDeque},
|
2024-08-07 14:03:33 +00:00
|
|
|
fmt::{self, Display, Formatter},
|
|
|
|
};
|
2024-08-05 03:11:04 +00:00
|
|
|
|
2024-08-07 14:03:33 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
2024-08-07 23:03:50 +00:00
|
|
|
use crate::{Identifier, Span, Type, Value};
|
2024-08-07 14:03:33 +00:00
|
|
|
|
2024-08-07 15:38:08 +00:00
|
|
|
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
2024-08-07 23:03:50 +00:00
|
|
|
pub struct AbstractSyntaxTree {
|
|
|
|
pub nodes: VecDeque<Node>,
|
2024-08-07 15:38:08 +00:00
|
|
|
}
|
|
|
|
|
2024-08-07 14:03:33 +00:00
|
|
|
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
2024-08-07 23:03:50 +00:00
|
|
|
pub struct Node {
|
|
|
|
pub statement: Statement,
|
|
|
|
pub position: Span,
|
2024-08-05 03:11:04 +00:00
|
|
|
}
|
|
|
|
|
2024-08-07 23:03:50 +00:00
|
|
|
impl Node {
|
|
|
|
pub fn new(operation: Statement, position: Span) -> Self {
|
2024-08-05 04:40:51 +00:00
|
|
|
Self {
|
|
|
|
statement: operation,
|
2024-08-07 19:47:37 +00:00
|
|
|
position,
|
2024-08-05 04:40:51 +00:00
|
|
|
}
|
2024-08-05 03:11:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-07 23:03:50 +00:00
|
|
|
impl Display for Node {
|
2024-08-07 14:03:33 +00:00
|
|
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
|
|
|
write!(f, "{}", self.statement)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
2024-08-07 23:03:50 +00:00
|
|
|
pub enum Statement {
|
2024-08-05 03:11:04 +00:00
|
|
|
// Top-level statements
|
2024-08-07 23:03:50 +00:00
|
|
|
Assign(Box<Node>, Box<Node>),
|
2024-08-05 03:11:04 +00:00
|
|
|
|
|
|
|
// Expressions
|
2024-08-07 23:03:50 +00:00
|
|
|
Add(Box<Node>, Box<Node>),
|
2024-08-07 22:24:25 +00:00
|
|
|
BuiltInFunctionCall {
|
|
|
|
function: BuiltInFunction,
|
2024-08-07 23:03:50 +00:00
|
|
|
type_arguments: Option<Vec<Node>>,
|
|
|
|
value_arguments: Option<Vec<Node>>,
|
2024-08-07 22:24:25 +00:00
|
|
|
},
|
|
|
|
FunctionCall {
|
2024-08-07 23:03:50 +00:00
|
|
|
function: Box<Node>,
|
|
|
|
type_arguments: Option<Vec<Node>>,
|
|
|
|
value_arguments: Option<Vec<Node>>,
|
2024-08-07 22:24:25 +00:00
|
|
|
},
|
2024-08-07 23:03:50 +00:00
|
|
|
PropertyAccess(Box<Node>, Box<Node>),
|
|
|
|
List(Vec<Node>),
|
|
|
|
Multiply(Box<Node>, Box<Node>),
|
2024-08-05 03:11:04 +00:00
|
|
|
|
|
|
|
// Hard-coded values
|
|
|
|
Constant(Value),
|
|
|
|
Identifier(Identifier),
|
|
|
|
}
|
2024-08-07 14:03:33 +00:00
|
|
|
|
2024-08-07 23:03:50 +00:00
|
|
|
impl Statement {
|
2024-08-07 14:03:33 +00:00
|
|
|
pub fn expected_type(&self, variables: &HashMap<Identifier, Value>) -> Option<Type> {
|
|
|
|
match self {
|
|
|
|
Statement::Add(left, _) => left.statement.expected_type(variables),
|
|
|
|
Statement::Assign(_, _) => None,
|
2024-08-07 22:24:25 +00:00
|
|
|
Statement::BuiltInFunctionCall { function, .. } => function.expected_type(),
|
2024-08-07 14:03:33 +00:00
|
|
|
Statement::Constant(value) => Some(value.r#type(variables)),
|
2024-08-07 22:24:25 +00:00
|
|
|
Statement::FunctionCall { function, .. } => function.statement.expected_type(variables),
|
2024-08-07 14:03:33 +00:00
|
|
|
Statement::Identifier(identifier) => variables
|
|
|
|
.get(identifier)
|
|
|
|
.map(|value| value.r#type(variables)),
|
|
|
|
Statement::List(_) => None,
|
|
|
|
Statement::Multiply(left, _) => left.statement.expected_type(variables),
|
|
|
|
Statement::PropertyAccess(_, _) => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-07 23:03:50 +00:00
|
|
|
impl Display for Statement {
|
2024-08-07 14:03:33 +00:00
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
match self {
|
2024-08-07 14:41:27 +00:00
|
|
|
Statement::Assign(left, right) => write!(f, "{left} = {right}"),
|
|
|
|
Statement::Add(left, right) => write!(f, "{left} + {right}"),
|
2024-08-07 22:24:25 +00:00
|
|
|
Statement::BuiltInFunctionCall {
|
|
|
|
function,
|
|
|
|
type_arguments: type_parameters,
|
|
|
|
value_arguments: value_parameters,
|
|
|
|
} => {
|
|
|
|
write!(f, "{function}")?;
|
|
|
|
|
|
|
|
if let Some(type_parameters) = type_parameters {
|
|
|
|
write!(f, "<")?;
|
|
|
|
|
|
|
|
for (i, type_parameter) in type_parameters.iter().enumerate() {
|
|
|
|
if i > 0 {
|
|
|
|
write!(f, ", ")?;
|
|
|
|
}
|
|
|
|
|
|
|
|
write!(f, "{type_parameter}")?;
|
|
|
|
}
|
|
|
|
|
|
|
|
write!(f, ">")?;
|
|
|
|
}
|
|
|
|
|
|
|
|
write!(f, "(")?;
|
|
|
|
|
|
|
|
if let Some(value_parameters) = value_parameters {
|
|
|
|
for (i, value_parameter) in value_parameters.iter().enumerate() {
|
|
|
|
if i > 0 {
|
|
|
|
write!(f, ", ")?;
|
|
|
|
}
|
|
|
|
|
|
|
|
write!(f, "{value_parameter}")?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
write!(f, ")")
|
|
|
|
}
|
|
|
|
Statement::FunctionCall {
|
|
|
|
function,
|
|
|
|
type_arguments: type_parameters,
|
|
|
|
value_arguments: value_parameters,
|
|
|
|
} => {
|
|
|
|
write!(f, "{function}")?;
|
|
|
|
|
|
|
|
if let Some(type_parameters) = type_parameters {
|
|
|
|
write!(f, "<")?;
|
|
|
|
|
|
|
|
for (i, type_parameter) in type_parameters.iter().enumerate() {
|
|
|
|
if i > 0 {
|
|
|
|
write!(f, ", ")?;
|
|
|
|
}
|
|
|
|
|
|
|
|
write!(f, "{type_parameter}")?;
|
|
|
|
}
|
|
|
|
|
|
|
|
write!(f, ">")?;
|
|
|
|
}
|
|
|
|
|
|
|
|
write!(f, "(")?;
|
|
|
|
|
|
|
|
if let Some(value_parameters) = value_parameters {
|
|
|
|
for (i, value_parameter) in value_parameters.iter().enumerate() {
|
|
|
|
if i > 0 {
|
|
|
|
write!(f, ", ")?;
|
|
|
|
}
|
|
|
|
|
|
|
|
write!(f, "{value_parameter}")?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
write!(f, ")")
|
|
|
|
}
|
2024-08-07 14:41:27 +00:00
|
|
|
Statement::PropertyAccess(left, right) => write!(f, "{left}.{right}"),
|
2024-08-07 14:03:33 +00:00
|
|
|
Statement::List(nodes) => {
|
|
|
|
write!(f, "[")?;
|
|
|
|
for (i, node) in nodes.iter().enumerate() {
|
|
|
|
if i > 0 {
|
|
|
|
write!(f, ", ")?;
|
|
|
|
}
|
2024-08-07 14:41:27 +00:00
|
|
|
write!(f, "{node}")?;
|
2024-08-07 14:03:33 +00:00
|
|
|
}
|
|
|
|
write!(f, "]")
|
|
|
|
}
|
2024-08-07 14:41:27 +00:00
|
|
|
Statement::Multiply(left, right) => write!(f, "{left} * {right}"),
|
|
|
|
Statement::Constant(value) => write!(f, "{value}"),
|
|
|
|
Statement::Identifier(identifier) => write!(f, "{identifier}"),
|
2024-08-07 14:03:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-08-07 22:24:25 +00:00
|
|
|
|
|
|
|
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
|
|
|
pub enum BuiltInFunction {
|
|
|
|
IsEven,
|
|
|
|
IsOdd,
|
|
|
|
Length,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl BuiltInFunction {
|
|
|
|
pub fn name(&self) -> &'static str {
|
|
|
|
match self {
|
|
|
|
BuiltInFunction::IsEven => "is_even",
|
|
|
|
BuiltInFunction::IsOdd => "is_odd",
|
|
|
|
BuiltInFunction::Length => "length",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn call(
|
|
|
|
&self,
|
|
|
|
_type_arguments: Option<Vec<Type>>,
|
|
|
|
value_arguments: Option<Vec<Value>>,
|
|
|
|
) -> Result<Value, BuiltInFunctionError> {
|
|
|
|
match self {
|
|
|
|
BuiltInFunction::IsEven => {
|
|
|
|
if let Some(value_arguments) = value_arguments {
|
|
|
|
if value_arguments.len() == 1 {
|
|
|
|
if let Some(integer) = value_arguments[0].as_integer() {
|
|
|
|
Ok(Value::boolean(integer % 2 == 0))
|
|
|
|
} else {
|
|
|
|
Err(BuiltInFunctionError::ExpectedInteger)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Err(BuiltInFunctionError::WrongNumberOfValueArguments)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Err(BuiltInFunctionError::WrongNumberOfValueArguments)
|
|
|
|
}
|
|
|
|
}
|
2024-08-07 22:43:24 +00:00
|
|
|
BuiltInFunction::IsOdd => {
|
|
|
|
if let Some(value_arguments) = value_arguments {
|
|
|
|
if value_arguments.len() == 1 {
|
|
|
|
if let Some(integer) = value_arguments[0].as_integer() {
|
|
|
|
Ok(Value::boolean(integer % 2 != 0))
|
|
|
|
} else {
|
|
|
|
Err(BuiltInFunctionError::ExpectedInteger)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Err(BuiltInFunctionError::WrongNumberOfValueArguments)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Err(BuiltInFunctionError::WrongNumberOfValueArguments)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BuiltInFunction::Length => {
|
|
|
|
if let Some(value_arguments) = value_arguments {
|
|
|
|
if value_arguments.len() == 1 {
|
|
|
|
if let Some(list) = value_arguments[0].as_list() {
|
|
|
|
Ok(Value::integer(list.len() as i64))
|
|
|
|
} else {
|
|
|
|
Err(BuiltInFunctionError::ExpectedInteger)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Err(BuiltInFunctionError::WrongNumberOfValueArguments)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Err(BuiltInFunctionError::WrongNumberOfValueArguments)
|
|
|
|
}
|
|
|
|
}
|
2024-08-07 22:24:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn expected_type(&self) -> Option<Type> {
|
|
|
|
match self {
|
|
|
|
BuiltInFunction::IsEven => Some(Type::Boolean),
|
|
|
|
BuiltInFunction::IsOdd => Some(Type::Boolean),
|
|
|
|
BuiltInFunction::Length => Some(Type::Integer),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Display for BuiltInFunction {
|
|
|
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
|
|
|
write!(f, "{}", self.name())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
|
|
pub enum BuiltInFunctionError {
|
|
|
|
ExpectedInteger,
|
|
|
|
WrongNumberOfValueArguments,
|
|
|
|
}
|