deimos-lang/src/ast/mod.rs

692 lines
14 KiB
Rust

use crate::name_analysis::symbol::Symbol;
use pest::Parser;
use std::range::Range;
pub mod build;
pub mod named;
pub mod pretty_print;
pub mod unparse;
// Operators
#[derive(Debug)]
pub enum Operator {
Binary(BinaryOperator),
PrefixUnary(PrefixUnaryOperator),
SuffixUnary(SuffixUnaryOperator),
}
#[derive(Debug)]
pub enum BinaryOperator {
Or,
And,
EqualTo,
NotEqualTo,
Greater,
Less,
GreaterEqual,
LessEqual,
Add,
Subtract,
Multiply,
Divide,
Modulo,
LeftShift,
RightShift,
}
#[derive(Debug)]
pub enum PrefixUnaryOperator {
Spread,
BorrowMut,
Borrow,
Mut,
Not,
Negative,
}
#[derive(Debug)]
pub enum SuffixUnaryOperator {
PlusPlus,
MinusMinus,
}
/* Names */
#[derive(Debug, Clone)]
pub struct Identifier {
pub name: String,
pub file_id: usize,
pub range: Range<usize>,
scope_id: Option<usize>,
symbol: Option<Symbol>,
}
impl Identifier {
pub fn new(name: &str, file_id: usize, range: Range<usize>) -> Self {
Identifier {
name: name.to_string(),
file_id,
range,
scope_id: None,
symbol: None,
}
}
pub fn set_scope_id(&mut self, id: usize) {
self.scope_id = Some(id);
}
pub fn scope_id(&self) -> Option<usize> {
self.scope_id
}
pub fn set_symbol(&mut self, symbol: Symbol) {
self.symbol = Some(symbol);
}
pub fn symbol(&self) -> &Option<Symbol> {
&self.symbol
}
}
#[derive(Debug)]
pub struct FullyQualifiedName {
pub identifiers: Vec<Identifier>,
pub file_id: usize,
pub range: Range<usize>,
scope_id: Option<usize>,
symbol: Option<Symbol>,
}
impl FullyQualifiedName {
pub fn new(identifiers: Vec<Identifier>, file_id: usize, range: Range<usize>) -> Self {
FullyQualifiedName {
identifiers,
range,
file_id,
scope_id: None,
symbol: None,
}
}
pub fn set_scope_id(&mut self, scope_id: usize) {
self.scope_id = Some(scope_id);
}
pub fn scope_id(&self) -> Option<usize> {
self.scope_id
}
pub fn set_symbol(&mut self, symbol: Symbol) {
self.symbol = Some(symbol);
}
pub fn symbol(&self) -> &Option<Symbol> {
&self.symbol
}
}
/* Type Use */
#[derive(Debug)]
pub enum TypeUse {
Void,
InterfaceOrClass(InterfaceOrClassTypeUse),
Tuple(TupleTypeUse),
Function(FunctionTypeUse),
}
#[derive(Debug)]
pub struct InterfaceOrClassTypeUse {
pub borrow_count: usize,
pub is_mutable: bool,
pub fqn: FullyQualifiedName,
pub generics: GenericArguments,
}
#[derive(Debug)]
pub struct TupleTypeUse {
pub borrow_count: usize,
pub is_mutable: bool,
pub arguments: TupleArguments,
}
#[derive(Debug)]
pub struct FunctionTypeUse {
pub borrow_count: usize,
pub function_modifier: Option<FunctionTypeModifier>,
pub generics: GenericParameters,
pub parameters: Parameters,
pub return_type: ReturnType,
}
// Generic arguments
#[derive(Debug)]
pub struct GenericArguments(pub Vec<TypeUse>);
impl GenericArguments {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
impl Default for GenericArguments {
fn default() -> Self {
GenericArguments(Vec::new())
}
}
/* Generic parameters */
#[derive(Debug)]
pub struct GenericParameters(pub Vec<Identifier>);
impl GenericParameters {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
impl Default for GenericParameters {
fn default() -> Self {
GenericParameters(Vec::new())
}
}
/* Tuple Arguments */
#[derive(Debug)]
pub struct TupleArguments(pub Vec<TypeUse>);
/* Implements List */
#[derive(Debug)]
pub struct ImplementsList(pub Vec<TypeUse>);
impl ImplementsList {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
impl Default for ImplementsList {
fn default() -> Self {
ImplementsList(Vec::new())
}
}
/* Function Type Modifier */
#[derive(Debug)]
pub enum FunctionTypeModifier {
Cons,
MutRef,
Mut,
Ref,
}
/* Function Parameters */
#[derive(Debug)]
pub struct Parameters(pub Vec<Parameter>);
impl Parameters {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
impl Default for Parameters {
fn default() -> Self {
Parameters(Vec::new())
}
}
#[derive(Debug)]
pub struct Parameter {
pub identifier: Identifier,
pub type_use: TypeUse,
}
/* Return Type */
#[derive(Debug)]
pub struct ReturnType {
pub declared_type: Box<TypeUse>,
pub references: References,
}
impl ReturnType {
pub fn void() -> Self {
ReturnType {
declared_type: Box::new(TypeUse::Void),
references: References::default(),
}
}
}
/* References */
#[derive(Debug)]
pub struct References(pub Vec<Identifier>);
impl References {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
impl Default for References {
fn default() -> Self {
References(Vec::new())
}
}
/* Top-level construct */
#[derive(Debug)]
pub struct CompilationUnit {
pub namespace: Option<FullyQualifiedName>,
pub declarations: Vec<ModuleLevelDeclaration>,
}
// Declarations allowed in each level
#[derive(Debug)]
pub enum ModuleLevelDeclaration {
Module(ModuleDeclaration),
Interface(InterfaceDeclaration),
Class(ClassDeclaration),
Function(FunctionDefinition),
PlatformFunction(PlatformFunctionDeclaration),
}
#[derive(Debug)]
pub enum InterfaceLevelDeclaration {
Module(ModuleDeclaration),
Interface(InterfaceDeclaration),
Class(ClassDeclaration),
Function(InterfaceFunctionDeclaration),
OperatorFunction(InterfaceOperatorFunctionDeclaration),
}
#[derive(Debug)]
pub enum ClassLevelDeclaration {
Module(ModuleDeclaration),
Interface(InterfaceDeclaration),
Class(ClassDeclaration),
Function(FunctionDefinition),
OperatorFunction(OperatorFunctionDefinition),
PlatformFunction(PlatformFunctionDeclaration),
Property(PropertyDeclaration),
Field(FieldDeclaration),
}
// Declarations
#[derive(Debug)]
pub struct ModuleDeclaration {
pub is_public: bool,
pub identifier: Identifier,
pub declarations: Vec<ModuleLevelDeclaration>,
}
#[derive(Debug)]
pub struct InterfaceDeclaration {
pub is_public: bool,
pub identifier: Identifier,
pub generics: GenericParameters,
pub implements: ImplementsList,
pub declarations: Vec<InterfaceLevelDeclaration>,
}
#[derive(Debug)]
pub struct ClassDeclaration {
pub is_public: bool,
pub identifier: Identifier,
pub generics: GenericParameters,
pub class_constructor: Option<ClassConstructor>,
pub implements: ImplementsList,
pub declarations: Vec<ClassLevelDeclaration>,
}
// Function declarations and components
#[derive(Debug)]
pub struct FunctionDefinition {
pub is_public: bool,
pub modifier: Option<FunctionModifier>,
pub generics: GenericParameters,
pub identifier: Identifier,
pub parameters: Parameters,
pub return_type: ReturnType,
pub body: FunctionBody,
}
#[derive(Debug)]
pub struct OperatorFunctionDefinition {
pub is_public: bool,
pub modifier: Option<FunctionModifier>,
pub generics: GenericParameters,
pub operator: Operator,
pub parameters: Parameters,
pub return_type: ReturnType,
pub body: FunctionBody,
}
#[derive(Debug)]
pub struct PlatformFunctionDeclaration {
pub is_public: bool,
pub modifier: Option<FunctionModifier>,
pub generics: GenericParameters,
pub identifier: Identifier,
pub parameters: Parameters,
pub return_type: ReturnType,
}
#[derive(Debug)]
pub struct InterfaceFunctionDeclaration {
pub modifier: Option<FunctionModifier>,
pub generics: GenericParameters,
pub identifier: Identifier,
pub parameters: Parameters,
pub return_type: ReturnType,
pub body: Option<FunctionBody>,
}
#[derive(Debug)]
pub struct InterfaceOperatorFunctionDeclaration {
pub modifier: Option<FunctionModifier>,
pub generics: GenericParameters,
pub operator: Operator,
pub parameters: Parameters,
pub return_type: ReturnType,
pub body: Option<FunctionBody>,
}
#[derive(Debug)]
pub enum FunctionModifier {
Static,
Cons,
Mut,
Ref,
MutRef,
}
#[derive(Debug)]
pub enum FunctionBody {
Equals(Expression),
Block(BlockStatement),
Alias(Identifier),
}
// Class components
#[derive(Debug)]
pub struct ClassConstructor(pub Vec<ClassConstructorParameter>);
#[derive(Debug)]
pub enum ClassConstructorParameter {
Property(PropertyDeclaration),
Field(FieldDeclaration),
}
#[derive(Debug)]
pub struct PropertyDeclaration {
pub is_mutable: bool,
pub identifier: Identifier,
pub declared_type: TypeUse,
}
#[derive(Debug)]
pub struct FieldDeclaration {
pub is_mutable: bool,
pub identifier: Identifier,
pub declared_type: TypeUse,
}
// Statements
#[derive(Debug)]
pub struct BlockStatement {
pub statements: Vec<Statement>,
pub expression: Option<Expression>,
}
#[derive(Debug)]
pub enum Statement {
BlockStatement(BlockStatement),
VariableDeclarationStatement(VariableDeclarationStatement),
AssignStatement(AssignStatement),
CallStatement(CallStatement),
ReturnStatement(ReturnStatement),
IfStatement(IfStatement),
IfElseStatement(IfElseStatement),
WhileStatement(WhileStatement),
ForStatement(ForStatement),
}
#[derive(Debug)]
pub struct VariableDeclarationStatement {
pub is_mutable: bool,
pub identifier: Identifier,
pub declared_type: Option<TypeUse>,
pub initializer: Option<Expression>,
}
#[derive(Debug)]
pub struct AssignStatement {
pub lhs: Expression,
pub rhs: Expression,
}
#[derive(Debug)]
pub struct CallStatement(pub Expression);
#[derive(Debug)]
pub struct ReturnStatement(pub Option<Expression>);
#[derive(Debug)]
pub struct IfStatement {
pub condition: Expression,
pub then_block: BlockStatement,
}
#[derive(Debug)]
pub struct IfElseStatement {
pub if_statement: IfStatement,
pub else_ifs: ElseIfs,
pub else_block: Option<ElseBlock>,
}
#[derive(Debug, Default)]
pub struct ElseIfs(pub Vec<IfStatement>);
#[derive(Debug)]
pub struct ElseBlock(pub BlockStatement);
#[derive(Debug)]
pub struct WhileStatement {
pub condition: Expression,
pub body: BlockStatement,
}
#[derive(Debug)]
pub struct ForStatement {
pub variable: Identifier,
pub iterator: Expression,
pub body: BlockStatement,
}
// Expressions
#[derive(Debug)]
pub enum Expression {
Ternary(TernaryExpression),
Binary(BinaryExpression),
UnaryPrefix(PrefixExpression),
UnarySuffix(SuffixExpression),
Call(CallExpression),
ObjectAccess(ObjectAccess),
Literal(Literal),
FullyQualifiedName(FullyQualifiedName),
Closure(Closure),
}
#[derive(Debug)]
pub struct TernaryExpression {
pub condition: Box<Expression>,
pub true_expression: Box<Expression>,
pub false_expression: Box<Expression>,
}
#[derive(Debug)]
pub struct BinaryExpression {
pub left: Box<Expression>,
pub operator: BinaryOperator,
pub right: Box<Expression>,
}
#[derive(Debug)]
pub struct PrefixExpression {
pub operator: PrefixUnaryOperator,
pub expression: Box<Expression>,
}
#[derive(Debug)]
pub struct SuffixExpression {
expression: Box<Expression>,
operator: SuffixUnaryOperator,
}
#[derive(Debug)]
pub struct CallExpression {
pub callee: Box<Expression>,
pub turbo_fish: Option<TurboFish>,
pub arguments: CallArguments,
}
#[derive(Debug)]
pub struct TurboFish(pub GenericArguments);
#[derive(Debug)]
pub struct CallArguments(pub Vec<CallArgument>);
#[derive(Debug)]
pub struct CallArgument(pub Box<Expression>);
#[derive(Debug)]
pub struct Closure {
pub modifier: Option<ClosureModifier>,
pub is_move: bool,
pub captures: ClosureCaptures,
pub parameters: ClosureParameters,
pub statements: Vec<Statement>,
pub expression: Option<Box<Expression>>,
}
#[derive(Debug)]
pub enum ClosureModifier {
Cons,
Mut,
}
#[derive(Debug, Default)]
pub struct ClosureCaptures(pub Vec<ClosureCapture>);
impl ClosureCaptures {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
#[derive(Debug)]
pub struct ClosureCapture {
pub borrow_count: usize,
pub is_mutable: bool,
pub identifier: Box<Identifier>,
}
#[derive(Debug, Default)]
pub struct ClosureParameters(pub Vec<ClosureParameter>);
impl ClosureParameters {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
#[derive(Debug)]
pub struct ClosureParameter {
pub identifier: Identifier,
pub type_use: Option<TypeUse>,
}
#[derive(Debug)]
pub struct ObjectAccess {
pub receiver: Box<Expression>,
pub navigations: ObjectNavigations,
}
#[derive(Debug)]
pub struct ObjectNavigations(pub Vec<ObjectNavigation>);
#[derive(Debug)]
pub enum ObjectNavigation {
Index(Box<Expression>),
Identifier(Box<Identifier>),
}
#[derive(Debug)]
pub enum Literal {
Integer(i32),
Long(i64),
Double(f64),
USize(usize),
String(String),
DString(DString),
BacktickString(DString),
Boolean(bool),
}
#[derive(Debug)]
pub struct DString(pub Vec<DStringPart>);
#[derive(Debug)]
pub enum DStringPart {
String(String),
Expression(Box<Expression>),
}
impl DStringPart {
pub fn from_string(s: &str) -> DStringPart {
DStringPart::String(String::from(s))
}
pub fn from_expression(e: Expression) -> DStringPart {
DStringPart::Expression(Box::new(e))
}
pub fn is_string(&self) -> bool {
match self {
DStringPart::String(_) => true,
_ => false,
}
}
pub fn unwrap_string(self) -> String {
match self {
DStringPart::String(s) => s,
_ => panic!(),
}
}
pub fn is_expression(&self) -> bool {
match self {
DStringPart::Expression(_) => true,
_ => false,
}
}
}