#![allow(clippy::upper_case_acronyms)] #![allow(clippy::enum_variant_names)] use std::rc::Rc; use crate::derivative::Derivative; mod walker; mod visitor; mod visitor_test; mod operators; pub use operators::{PrefixOp, BinOp}; pub use visitor::ASTVisitor; pub use walker::walk_ast; use crate::tokenizing::Location; /// An abstract identifier for an AST node. Note that /// the u32 index limits the size of an AST to 2^32 nodes. #[derive(Debug, PartialEq, Eq, Hash, Clone, Default)] pub struct ItemId { idx: u32, } impl ItemId { fn new(n: u32) -> ItemId { ItemId { idx: n } } } pub struct ItemIdStore { last_idx: u32 } impl ItemIdStore { pub fn new() -> ItemIdStore { ItemIdStore { last_idx: 0 } } pub fn fresh(&mut self) -> ItemId { let idx = self.last_idx; self.last_idx += 1; ItemId::new(idx) } } #[derive(Derivative, Debug)] #[derivative(PartialEq)] pub struct AST { #[derivative(PartialEq="ignore")] pub id: ItemId, pub statements: Vec } #[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), } pub type Block = Vec; 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 } } /* * @foo(arg1, arg2) * fn hello() { * * } * * Declaration::Annotation { * name: "foo", * arguments: vec!["arg1", "arg2"] * } * * * */ #[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: Vec, }