schala/schala-lang/language/src/ast.rs
2019-09-03 21:14:12 -07:00

260 lines
5.6 KiB
Rust

use std::rc::Rc;
use std::convert::From;
use crate::typechecking::TypeData;
use crate::symbol_table::FullyQualifiedSymbolName;
mod operators;
pub use operators::*;
#[derive(Clone, Debug, PartialEq)]
pub struct Meta<T> {
n: T,
source_map: SourceMap,
type_data: TypeData,
pub fqsn: Option<FullyQualifiedSymbolName>
}
impl<T> Meta<T> {
pub fn new(n: T) -> Meta<T> {
Meta { n,
source_map: SourceMap::default(),
type_data: TypeData::new(),
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<Expression> for Meta<Expression> {
fn from(expr: Expression) -> Meta<Expression> {
Meta::new(expr)
}
}
#[derive(Debug, PartialEq)]
pub struct AST(pub Vec<Meta<Statement>>);
#[derive(Debug, PartialEq, Clone)]
pub enum Statement {
ExpressionStatement(Meta<Expression>),
Declaration(Declaration), //TODO Declaration should also be Meta-wrapped; only Expression and Declaration are Meta-wrapped maybe?
}
pub type Block = Vec<Meta<Statement>>;
pub type ParamName = Rc<String>;
#[derive(Debug, PartialEq, Clone)]
pub struct QualifiedName(pub Vec<Rc<String>>);
#[derive(Debug, PartialEq, Clone)]
pub struct FormalParam {
pub name: ParamName,
pub default: Option<Meta<Expression>>,
pub anno: Option<TypeIdentifier>
}
#[derive(Debug, PartialEq, Clone)]
pub enum Declaration {
FuncSig(Signature),
FuncDecl(Signature, Block),
TypeDecl {
name: TypeSingletonName,
body: TypeBody,
mutable: bool
},
TypeAlias(Rc<String>, Rc<String>), //should have TypeSingletonName in it, or maybe just String, not sure
Binding {
name: Rc<String>,
constant: bool,
type_anno: Option<TypeIdentifier>,
expr: Meta<Expression>,
},
Impl {
type_name: TypeIdentifier,
interface_name: Option<TypeSingletonName>,
block: Vec<Declaration>,
},
Interface {
name: Rc<String>,
signatures: Vec<Signature>
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct Signature {
pub name: Rc<String>,
pub operator: bool,
pub params: Vec<FormalParam>,
pub type_anno: Option<TypeIdentifier>,
}
#[derive(Debug, PartialEq, Clone)]
pub struct TypeBody(pub Vec<Variant>);
#[derive(Debug, PartialEq, Clone)]
pub enum Variant {
UnitStruct(Rc<String>),
TupleStruct(Rc<String>, Vec<TypeIdentifier>),
Record {
name: Rc<String>,
members: Vec<(Rc<String>, TypeIdentifier)>,
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct Expression {
pub kind: ExpressionKind,
pub type_anno: Option<TypeIdentifier>
}
impl Expression {
pub fn new(kind: ExpressionKind) -> Expression {
Expression { kind, type_anno: None }
}
pub fn with_anno(kind: ExpressionKind, type_anno: TypeIdentifier) -> Expression {
Expression { kind, type_anno: Some(type_anno) }
}
}
#[derive(Debug, PartialEq, Clone)]
pub enum TypeIdentifier {
Tuple(Vec<TypeIdentifier>),
Singleton(TypeSingletonName)
}
#[derive(Debug, PartialEq, Clone)]
pub struct TypeSingletonName {
pub name: Rc<String>,
pub params: Vec<TypeIdentifier>,
}
#[derive(Debug, PartialEq, Clone)]
pub enum ExpressionKind {
NatLiteral(u64),
FloatLiteral(f64),
StringLiteral(Rc<String>),
BoolLiteral(bool),
BinExp(BinOp, Box<Meta<Expression>>, Box<Meta<Expression>>),
PrefixExp(PrefixOp, Box<Meta<Expression>>),
TupleLiteral(Vec<Meta<Expression>>),
Value(QualifiedName),
NamedStruct {
name: QualifiedName,
fields: Vec<(Rc<String>, Meta<Expression>)>,
},
Call {
f: Box<Meta<Expression>>,
arguments: Vec<InvocationArgument>,
},
Index {
indexee: Box<Meta<Expression>>,
indexers: Vec<Meta<Expression>>,
},
IfExpression {
discriminator: Box<Discriminator>,
body: Box<IfExpressionBody>,
},
WhileExpression {
condition: Option<Box<Meta<Expression>>>,
body: Block,
},
ForExpression {
enumerators: Vec<Enumerator>,
body: Box<ForBody>,
},
Lambda {
params: Vec<FormalParam>,
type_anno: Option<TypeIdentifier>,
body: Block,
},
ListLiteral(Vec<Meta<Expression>>),
}
#[derive(Debug, PartialEq, Clone)]
pub enum InvocationArgument {
Positional(Meta<Expression>),
Keyword {
name: Rc<String>,
expr: Meta<Expression>,
},
Ignored
}
#[derive(Debug, PartialEq, Clone)]
pub enum Discriminator {
Simple(Meta<Expression>),
BinOp(Meta<Expression>, BinOp)
}
#[derive(Debug, PartialEq, Clone)]
pub enum IfExpressionBody {
SimpleConditional(Block, Option<Block>),
SimplePatternMatch(Pattern, Block, Option<Block>),
GuardList(Vec<GuardArm>)
}
#[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<BinOp>,
pub expr: ExpressionKind,
}
#[derive(Debug, PartialEq, Clone)]
pub enum Pattern {
Ignored,
TuplePattern(Vec<Pattern>),
Literal(PatternLiteral),
TupleStruct(Rc<String>, Vec<Pattern>),
Record(Rc<String>, Vec<(Rc<String>, Pattern)>),
}
#[derive(Debug, PartialEq, Clone)]
pub enum PatternLiteral {
NumPattern {
neg: bool,
num: ExpressionKind,
},
StringPattern(Rc<String>),
BoolPattern(bool),
//TODO I think VarPattern also needs to know about FQSNs
VarPattern(QualifiedName)
}
#[derive(Debug, PartialEq, Clone)]
pub struct Enumerator {
pub id: Rc<String>,
pub generator: Meta<Expression>,
}
#[derive(Debug, PartialEq, Clone)]
pub enum ForBody {
MonadicReturn(Meta<Expression>),
StatementBlock(Block),
}