#![allow(clippy::upper_case_acronyms)] #![allow(clippy::enum_variant_names)] use std::rc::Rc; use std::convert::{AsRef, From}; mod visitor; mod operators; pub use operators::{PrefixOp, BinOp}; pub use visitor::*; use crate::derivative::Derivative; use crate::tokenizing::Location; use crate::identifier::{Id, define_id_kind}; define_id_kind!(ASTItem); /* #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Default)] pub struct ASTItem; impl IdKind for ASTItem { fn tag() -> &'static str { "ASTItem" } } */ pub type ItemId = Id; #[derive(Derivative, Debug)] #[derivative(PartialEq)] pub struct AST { #[derivative(PartialEq="ignore")] pub id: ItemId, pub statements: Block, } #[derive(Derivative, Debug, Clone)] #[derivative(PartialEq)] pub struct Statement { #[derivative(PartialEq="ignore")] pub id: ItemId, #[derivative(PartialEq="ignore")] pub location: Location, pub kind: StatementKind, } #[derive(Debug, PartialEq, Clone)] pub enum StatementKind { Expression(Expression), Declaration(Declaration), Import(ImportSpecifier), Module(ModuleSpecifier), } #[derive(Debug, Clone, PartialEq, Default)] pub struct Block { pub statements: Vec } impl From> for Block { fn from(statements: Vec) -> Self { Self { statements } } } impl From for Block { fn from(statement: Statement) -> Self { Self { statements: vec![statement] } } } impl AsRef<[Statement]> for Block { fn as_ref(&self) -> &[Statement] { self.statements.as_ref() } } pub type ParamName = Rc; #[derive(Debug, Derivative, Clone)] #[derivative(PartialEq)] pub struct QualifiedName { #[derivative(PartialEq="ignore")] pub id: ItemId, pub components: Vec>, } #[derive(Debug, PartialEq, Clone)] pub struct FormalParam { pub name: ParamName, pub default: Option, pub anno: Option } #[derive(Debug, PartialEq, Clone)] pub enum Declaration { FuncSig(Signature), FuncDecl(Signature, Block), TypeDecl { name: TypeSingletonName, body: TypeBody, mutable: bool }, //TODO this needs to be more sophisticated TypeAlias { alias: Rc, original: Rc, }, Binding { name: Rc, constant: bool, type_anno: Option, expr: Expression, }, Impl { type_name: TypeIdentifier, interface_name: Option, block: Vec, }, Interface { name: Rc, signatures: Vec }, Annotation { name: Rc, arguments: Vec } } #[derive(Debug, PartialEq, Clone)] pub struct Signature { pub name: Rc, pub operator: bool, pub params: Vec, pub type_anno: Option, } #[derive(Debug, PartialEq, Clone)] pub struct TypeBody(pub Vec); #[derive(Debug, Derivative, Clone)] #[derivative(PartialEq)] pub struct Variant { #[derivative(PartialEq="ignore")] pub id: ItemId, pub name: Rc, pub kind: VariantKind, } #[derive(Debug, PartialEq, Clone)] pub enum VariantKind { UnitStruct, TupleStruct(Vec), Record(Vec<(Rc, TypeIdentifier)>), } #[derive(Debug, Derivative, Clone)] #[derivative(PartialEq)] pub struct Expression { #[derivative(PartialEq="ignore")] pub id: ItemId, pub kind: ExpressionKind, pub type_anno: Option } impl Expression { pub fn new(id: ItemId, kind: ExpressionKind) -> Expression { Expression { id, kind, type_anno: None } } #[cfg(test)] pub fn with_anno(id: ItemId, kind: ExpressionKind, type_anno: TypeIdentifier) -> Expression { Expression { id, kind, type_anno: Some(type_anno) } } } #[derive(Debug, PartialEq, Clone)] pub enum TypeIdentifier { Tuple(Vec), Singleton(TypeSingletonName) } #[derive(Debug, PartialEq, Clone)] pub struct TypeSingletonName { pub name: Rc, pub params: Vec, } #[derive(Debug, PartialEq, Clone)] pub enum ExpressionKind { NatLiteral(u64), FloatLiteral(f64), StringLiteral(Rc), BoolLiteral(bool), BinExp(BinOp, Box, Box), PrefixExp(PrefixOp, Box), TupleLiteral(Vec), Value(QualifiedName), NamedStruct { name: QualifiedName, fields: Vec<(Rc, Expression)>, }, Call { f: Box, arguments: Vec, }, Index { indexee: Box, indexers: Vec, }, IfExpression { discriminator: Option>, body: Box, }, WhileExpression { condition: Option>, body: Block, }, ForExpression { enumerators: Vec, body: Box, }, Lambda { params: Vec, type_anno: Option, body: Block, }, ListLiteral(Vec), } #[derive(Debug, PartialEq, Clone)] pub enum InvocationArgument { Positional(Expression), Keyword { name: Rc, expr: Expression, }, Ignored } #[derive(Debug, PartialEq, Clone)] pub enum IfExpressionBody { SimpleConditional { then_case: Block, else_case: Option }, SimplePatternMatch { pattern: Pattern, then_case: Block, else_case: Option }, CondList(Vec) } #[derive(Debug, PartialEq, Clone)] pub struct ConditionArm { pub condition: Condition, pub guard: Option, pub body: Block, } #[derive(Debug, PartialEq, Clone)] pub enum Condition { Pattern(Pattern), TruncatedOp(BinOp, Expression), Expression(Expression), Else, } #[derive(Debug, PartialEq, Clone)] pub enum Pattern { Ignored, TuplePattern(Vec), Literal(PatternLiteral), TupleStruct(QualifiedName, Vec), Record(QualifiedName, Vec<(Rc, Pattern)>), VarOrName(QualifiedName), } #[derive(Debug, PartialEq, Clone)] pub enum PatternLiteral { NumPattern { neg: bool, num: ExpressionKind, }, StringPattern(Rc), BoolPattern(bool), } #[derive(Debug, PartialEq, Clone)] pub struct Enumerator { pub id: Rc, pub generator: Expression, } #[derive(Debug, PartialEq, Clone)] pub enum ForBody { MonadicReturn(Expression), StatementBlock(Block), } #[derive(Debug, Derivative, Clone)] #[derivative(PartialEq)] pub struct ImportSpecifier { #[derivative(PartialEq="ignore")] pub id: ItemId, pub path_components: Vec>, pub imported_names: ImportedNames } #[derive(Debug, PartialEq, Clone)] pub enum ImportedNames { All, LastOfPath, List(Vec>) } #[derive(Debug, PartialEq, Clone)] pub struct ModuleSpecifier { pub name: Rc, pub contents: Block, }