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

293 lines
8.8 KiB
Rust
Raw Normal View History

2024-08-09 01:59:09 +00:00
//! In-memory representation of a Dust program.
use std::{
2024-08-09 10:09:59 +00:00
collections::{BTreeMap, HashMap, VecDeque},
fmt::{self, Display, Formatter},
};
2024-08-05 03:11:04 +00:00
use serde::{Deserialize, Serialize};
use crate::{BuiltInFunction, 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
// Variable assignment
2024-08-09 08:23:02 +00:00
Assignment {
2024-08-09 09:18:39 +00:00
identifier: Node<Identifier>,
2024-08-09 08:23:02 +00:00
value_node: Box<Node<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
PropertyAccess(Box<Node<Statement>>, 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 10:09:59 +00:00
Map(Vec<(Node<Identifier>, 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 {
pub fn expected_type(&self, variables: &HashMap<Identifier, Value>) -> Option<Type> {
match self {
2024-08-09 08:23:02 +00:00
Statement::Assignment { .. } => None,
2024-08-09 15:41:23 +00:00
Statement::Block(nodes) => nodes.last().unwrap().inner.expected_type(variables),
2024-08-09 08:23:02 +00:00
Statement::BinaryOperation { left, .. } => left.inner.expected_type(variables),
Statement::BuiltInFunctionCall { function, .. } => function.expected_return_type(),
Statement::Constant(value) => Some(value.r#type(variables)),
Statement::FunctionCall { function, .. } => function.inner.expected_type(variables),
Statement::Identifier(identifier) => variables
.get(identifier)
.map(|value| value.r#type(variables)),
2024-08-09 10:09:59 +00:00
Statement::List(nodes) => {
let item_type = nodes.first().unwrap().inner.expected_type(variables)?;
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 {
types.insert(
identifier.inner.clone(),
item.inner.expected_type(variables)?,
);
}
Some(Type::Map(types))
}
Statement::PropertyAccess(_, _) => None,
2024-08-09 15:41:23 +00:00
Statement::Nil(_) => None,
}
}
}
impl Display for Statement {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
2024-08-09 08:23:02 +00:00
Statement::Assignment {
identifier,
value_node: value,
} => {
write!(f, "{identifier} = {value}")
}
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}"),
}
}
}
#[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 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 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, "-"),
}
}
}