1
0
dust/dust-lang/src/abstract_tree.rs

314 lines
9.5 KiB
Rust
Raw Normal View History

2024-08-09 01:59:09 +00:00
//! In-memory representation of a Dust program.
use std::{
collections::{BTreeMap, VecDeque},
fmt::{self, Display, Formatter},
};
2024-08-05 03:11:04 +00:00
use serde::{Deserialize, Serialize};
2024-08-10 00:52:13 +00:00
use crate::{BuiltInFunction, Context, Identifier, Span, Type, Value};
2024-08-09 01:59:09 +00:00
/// In-memory representation of a Dust program.
2024-08-07 15:38:08 +00:00
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct AbstractSyntaxTree {
pub nodes: VecDeque<Node<Statement>>,
2024-08-07 15:38:08 +00:00
}
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Node<T> {
pub inner: T,
pub position: Span,
2024-08-05 03:11:04 +00:00
}
impl<T> Node<T> {
pub fn new(inner: T, position: Span) -> Self {
Self { inner, position }
2024-08-05 03:11:04 +00:00
}
}
impl<T: Display> Display for Node<T> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}", self.inner)
}
}
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum Statement {
2024-08-09 15:41:23 +00:00
// A sequence of statements
Block(Vec<Node<Statement>>),
2024-08-09 08:23:02 +00:00
// Logic, math and comparison expressions
BinaryOperation {
left: Box<Node<Statement>>,
operator: Node<BinaryOperator>,
right: Box<Node<Statement>>,
},
2024-08-05 03:11:04 +00:00
// Function calls
BuiltInFunctionCall {
function: BuiltInFunction,
type_arguments: Option<Vec<Node<Statement>>>,
value_arguments: Option<Vec<Node<Statement>>>,
},
FunctionCall {
function: Box<Node<Statement>>,
type_arguments: Option<Vec<Node<Statement>>>,
value_arguments: Option<Vec<Node<Statement>>>,
},
2024-08-09 08:23:02 +00:00
// Property access expression
2024-08-10 09:23:43 +00:00
// TODO: This should be a binary operation
PropertyAccess(Box<Node<Statement>>, Box<Node<Statement>>),
2024-08-10 09:23:43 +00:00
// Loops
While {
condition: Box<Node<Statement>>,
body: Box<Node<Statement>>,
},
2024-08-09 08:23:02 +00:00
// Identifier expression
Identifier(Identifier),
// Value collection expressions
List(Vec<Node<Statement>>),
2024-08-09 22:14:46 +00:00
Map(Vec<(Node<Statement>, Node<Statement>)>),
2024-08-05 03:11:04 +00:00
2024-08-09 15:41:23 +00:00
// Hard-coded value
2024-08-05 03:11:04 +00:00
Constant(Value),
2024-08-09 15:41:23 +00:00
// A statement that always returns None. Created with a semicolon, it causes the preceding
// statement to return None. This is analagous to the semicolon or unit type in Rust.
Nil(Box<Node<Statement>>),
2024-08-05 03:11:04 +00:00
}
impl Statement {
2024-08-10 00:52:13 +00:00
pub fn expected_type(&self, context: &Context) -> Option<Type> {
match self {
2024-08-10 00:52:13 +00:00
Statement::Block(nodes) => nodes.last().unwrap().inner.expected_type(context),
2024-08-10 09:23:43 +00:00
Statement::BinaryOperation {
left,
operator,
right,
} => match operator.inner {
BinaryOperator::Add
| BinaryOperator::Divide
| BinaryOperator::Modulo
| BinaryOperator::Multiply
| BinaryOperator::Subtract => Some(left.inner.expected_type(context)?),
BinaryOperator::Equal
| BinaryOperator::Greater
| BinaryOperator::GreaterOrEqual
| BinaryOperator::Less
| BinaryOperator::LessOrEqual
| BinaryOperator::And
| BinaryOperator::Or => Some(Type::Boolean),
BinaryOperator::Assign | BinaryOperator::AddAssign => None,
},
2024-08-09 08:23:02 +00:00
Statement::BuiltInFunctionCall { function, .. } => function.expected_return_type(),
2024-08-10 00:52:13 +00:00
Statement::Constant(value) => Some(value.r#type(context)),
Statement::FunctionCall { function, .. } => function.inner.expected_type(context),
Statement::Identifier(identifier) => context.get_type(identifier).cloned(),
2024-08-09 10:09:59 +00:00
Statement::List(nodes) => {
2024-08-10 00:52:13 +00:00
let item_type = nodes.first().unwrap().inner.expected_type(context)?;
2024-08-09 10:09:59 +00:00
Some(Type::List {
length: nodes.len(),
item_type: Box::new(item_type),
})
}
Statement::Map(nodes) => {
let mut types = BTreeMap::new();
for (identifier, item) in nodes {
2024-08-09 22:14:46 +00:00
if let Statement::Identifier(identifier) = &identifier.inner {
2024-08-10 00:52:13 +00:00
types.insert(identifier.clone(), item.inner.expected_type(context)?);
2024-08-09 22:14:46 +00:00
}
2024-08-09 10:09:59 +00:00
}
Some(Type::Map(types))
}
2024-08-09 15:41:23 +00:00
Statement::Nil(_) => None,
2024-08-10 09:23:43 +00:00
Statement::PropertyAccess(_, _) => None,
Statement::While { .. } => None,
}
}
}
impl Display for Statement {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
2024-08-09 15:41:23 +00:00
Statement::Block(statements) => {
write!(f, "{{ ")?;
for (i, statement) in statements.iter().enumerate() {
if i > 0 {
write!(f, " ")?;
}
write!(f, "{statement}")?;
}
write!(f, " }}")
}
2024-08-09 08:23:02 +00:00
Statement::BinaryOperation {
left,
operator,
right,
} => {
write!(f, "{left} {operator} {right}")
}
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::Constant(value) => write!(f, "{value}"),
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, ")")
}
Statement::Identifier(identifier) => write!(f, "{identifier}"),
Statement::List(nodes) => {
write!(f, "[")?;
2024-08-09 10:09:59 +00:00
for (i, node) in nodes.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
2024-08-09 10:09:59 +00:00
2024-08-07 14:41:27 +00:00
write!(f, "{node}")?;
}
2024-08-09 10:09:59 +00:00
write!(f, "]")
}
2024-08-09 10:09:59 +00:00
Statement::Map(nodes) => {
write!(f, "{{")?;
for (i, (identifier, node)) in nodes.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{identifier} = {node}")?;
}
write!(f, "}}")
}
2024-08-09 15:41:23 +00:00
Statement::Nil(node) => write!(f, "{node};"),
Statement::PropertyAccess(left, right) => write!(f, "{left}.{right}"),
2024-08-10 09:23:43 +00:00
Statement::While { condition, body } => {
write!(f, "while {condition} {body}")
}
}
}
}
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
2024-08-09 08:23:02 +00:00
pub enum BinaryOperator {
2024-08-09 08:56:24 +00:00
// Math
2024-08-09 08:23:02 +00:00
Add,
Divide,
2024-08-09 11:02:55 +00:00
Modulo,
2024-08-09 08:56:24 +00:00
Multiply,
Subtract,
// Comparison
2024-08-09 11:15:09 +00:00
Equal,
2024-08-09 08:23:02 +00:00
Greater,
GreaterOrEqual,
Less,
LessOrEqual,
2024-08-09 08:56:24 +00:00
// Logic
And,
Or,
2024-08-09 22:14:46 +00:00
// Assignment
Assign,
AddAssign,
}
2024-08-09 08:23:02 +00:00
impl Display for BinaryOperator {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
2024-08-09 08:23:02 +00:00
BinaryOperator::Add => write!(f, "+"),
2024-08-09 22:14:46 +00:00
BinaryOperator::AddAssign => write!(f, "+="),
BinaryOperator::Assign => write!(f, "="),
2024-08-09 08:56:24 +00:00
BinaryOperator::And => write!(f, "&&"),
2024-08-09 08:23:02 +00:00
BinaryOperator::Divide => write!(f, "/"),
2024-08-09 11:15:09 +00:00
BinaryOperator::Equal => write!(f, "=="),
2024-08-09 08:23:02 +00:00
BinaryOperator::Greater => write!(f, ">"),
BinaryOperator::GreaterOrEqual => write!(f, ">="),
BinaryOperator::Less => write!(f, "<"),
BinaryOperator::LessOrEqual => write!(f, "<="),
2024-08-09 11:02:55 +00:00
BinaryOperator::Modulo => write!(f, "%"),
2024-08-09 08:23:02 +00:00
BinaryOperator::Multiply => write!(f, "*"),
2024-08-09 08:56:24 +00:00
BinaryOperator::Or => write!(f, "||"),
2024-08-09 08:23:02 +00:00
BinaryOperator::Subtract => write!(f, "-"),
}
}
}