use std::rc::Rc; use std::convert::From; use crate::derivative::Derivative; use crate::symbol_table::FullyQualifiedSymbolName; mod operators; pub use operators::*; /// An abstract identifier for an AST node #[derive(Debug, PartialEq, Eq, Hash, Clone)] 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 } } /// Always returns an ItemId with internal value zero #[cfg(test)] pub fn new_id() -> ItemId { ItemId { idx: 0 } } /// This limits the size of the AST to 2^32 tree elements pub fn fresh(&mut self) -> ItemId { let idx = self.last_idx; self.last_idx += 1; ItemId::new(idx) } } #[derive(Clone, Debug, PartialEq)] pub struct Meta { pub n: T, pub fqsn: Option } impl Meta { pub fn new(n: T) -> Meta { Meta { n, fqsn: None, } } pub fn node(&self) -> &T { &self.n } pub fn mut_node(&mut self) -> &mut T { &mut self.n } } //TODO this PartialEq is here to make tests work - find a way to make it not necessary #[derive(Clone, Debug, Default, PartialEq)] struct SourceMap { } impl From for Meta { fn from(expr: Expression) -> Meta { Meta::new(expr) } } #[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, pub kind: StatementKind, } #[derive(Debug, PartialEq, Clone)] pub enum StatementKind { Expression(Expression), Declaration(Declaration), //TODO Declaration should also be Meta-wrapped; only Expression and Declaration are Meta-wrapped maybe? } 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 }, TypeAlias(Rc, Rc), //should have TypeSingletonName in it, or maybe just String, not sure Binding { name: Rc, constant: bool, type_anno: Option, expr: Expression, }, Impl { type_name: TypeIdentifier, interface_name: Option, block: Vec, }, Interface { name: Rc, signatures: 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, PartialEq, Clone)] pub enum Variant { UnitStruct(Rc), TupleStruct(Rc, Vec), Record { name: Rc, members: 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 } } 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: Box, 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 Discriminator { Simple(Expression), BinOp(Expression, BinOp) } #[derive(Debug, PartialEq, Clone)] pub enum IfExpressionBody { SimpleConditional(Block, Option), SimplePatternMatch(Pattern, Block, Option), GuardList(Vec) } #[derive(Debug, PartialEq, Clone)] pub struct GuardArm { pub guard: Guard, pub body: Block, } #[derive(Debug, PartialEq, Clone)] pub enum Guard { Pat(Pattern), HalfExpr(HalfExpr) } #[derive(Debug, PartialEq, Clone)] pub struct HalfExpr { pub op: Option, pub expr: ExpressionKind, } #[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), }