use crate::common::Span;
use smallvec::SmallVec;
use std::fmt::{self, Display};
#[derive(Debug)]
pub struct AST {
pub nodes: Vec<ASTNode>,
pub span: Span,
}
impl AST {
pub fn new(nodes: Vec<ASTNode>, span: Span) -> Self {
AST { nodes, span }
}
}
#[derive(Debug, PartialEq)]
pub enum ASTNode {
Stmt(Stmt),
Expr(Expr),
}
impl From<Stmt> for ASTNode {
fn from(stmt: Stmt) -> ASTNode {
ASTNode::Stmt(stmt)
}
}
impl From<&Stmt> for ASTNode {
fn from(stmt: &Stmt) -> ASTNode {
ASTNode::Stmt(stmt.clone())
}
}
impl From<Expr> for ASTNode {
fn from(expr: Expr) -> ASTNode {
ASTNode::Expr(expr)
}
}
impl From<&Expr> for ASTNode {
fn from(expr: &Expr) -> ASTNode {
ASTNode::Expr(expr.clone())
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Signature {
pub name: Ident,
pub params: (Vec<Ident>, Vec<Option<Expr>>),
pub return_typ: Option<Expr>,
pub span: Span,
}
pub struct StmtBlock(SmallVec<[Stmt; 4]>, Span);
#[derive(Debug, Clone, PartialEq)]
pub struct Trait {
pub methods: Vec<TraitMethod>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub struct TraitMethod {
pub sig: Signature,
pub default: Option<Stmt>,
pub span: Span,
}
#[derive(Clone, Debug, PartialEq)]
pub enum Stmt {
IfStatement(Expr, Box<(Stmt, Option<Stmt>)>, Span),
WhileStatement(Expr, Box<Stmt>, Span),
LoopStatement(Box<Stmt>, Span),
ImportStatement(Expr, Span),
Block(Box<Vec<Stmt>>, Span),
VarDeclaration(Ident, Option<Expr>, Option<Expr>, Span),
ConDeclaration(Ident, Expr, Option<Expr>, Span),
AssignStatement(Expr, Expr, Span),
Function(Box<ScriptFun>, Span),
Class(Class, Span),
Trait(Trait),
Constructor(Box<Constructor>, Span),
Return(Option<Expr>, Span),
Break(Span),
Continue(Span),
Expr(Expr),
}
impl Stmt {
pub fn span(&self) -> Span {
match self.clone() {
Self::IfStatement(_, _, span) => span,
Self::WhileStatement(_, _, span) => span,
Self::LoopStatement(_, span) => span,
Self::ImportStatement(_, span) => span,
Self::Block(_, span) => span,
Self::VarDeclaration(_, _, _, span) => span,
Self::ConDeclaration(_, _, _, span) => span,
Self::AssignStatement(_, _, span) => span,
Self::Function(_, span) => span,
Self::Class(_, span) => span,
Self::Trait(trait_) => trait_.span,
Self::Constructor(_, span) => span,
Self::Return(_, span) => span,
Self::Break(span) => span,
Self::Continue(span) => span,
Self::Expr(expr) => expr.span(),
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct ScriptFun {
pub name: Ident,
pub params: Vec<Ident>,
pub body: Stmt,
pub params_typ: Vec<Option<Expr>>,
pub return_typ: Option<Expr>,
pub access: FunAccess,
}
impl ScriptFun {
pub fn new(
name: Ident,
params: Vec<Ident>,
body: Stmt,
params_typ: Vec<Option<Expr>>,
return_typ: Option<Expr>,
access: FunAccess,
) -> Self {
ScriptFun {
name,
params,
body,
params_typ,
return_typ,
access,
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum FunAccess {
Public,
Private,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Class {
pub name: Ident,
pub parent: Option<Ident>,
pub fields: Vec<Stmt>,
pub methods: Vec<Stmt>,
pub constructors: Vec<Stmt>,
}
impl Class {
pub fn new(
name: Ident,
parent: Option<Ident>,
fields: Vec<Stmt>,
methods: Vec<Stmt>,
constructors: Vec<Stmt>,
) -> Self {
Self {
name,
parent,
fields,
methods,
constructors,
}
}
pub fn name(&self) -> String {
self.name.name.clone()
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Constructor {
pub name: Ident,
pub params: Vec<Ident>,
pub body: Stmt,
pub class: String,
}
impl Constructor {
pub fn new(name: Ident, params: Vec<Ident>, body: Stmt, class: String) -> Self {
Self {
name,
params,
body,
class,
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct BinExpr {
pub op: Op,
pub lhs: Expr,
pub rhs: Expr,
}
impl BinExpr {
pub fn new(op: Op, lhs: Expr, rhs: Expr) -> Self {
BinExpr { op, lhs, rhs }
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum Op {
Add,
Subtract,
Multiply,
Divide,
Remainder,
GreaterThan,
GreaterThanEquals,
LessThan,
LessThanEquals,
EqualTo,
NotEqual,
BitwiseAnd,
BitwiseOr,
BitwiseXor,
Bang,
}
impl From<&str> for Op {
fn from(op: &str) -> Self {
match op {
"+" => Op::Add,
"-" => Op::Subtract,
"*" => Op::Multiply,
"/" => Op::Divide,
"%" => Op::Remainder,
">" => Op::GreaterThan,
">=" => Op::GreaterThanEquals,
"<" => Op::LessThan,
"<=" => Op::LessThanEquals,
"==" => Op::EqualTo,
"!=" => Op::NotEqual,
"&" => Op::BitwiseAnd,
"|" => Op::BitwiseOr,
"^" => Op::BitwiseXor,
"!" => Op::Bang,
_ => unreachable!(),
}
}
}
impl Display for Op {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Op::Add => f.write_str("+"),
Op::Subtract => f.write_str("-"),
Op::Multiply => f.write_str("*"),
Op::Divide => f.write_str("/"),
Op::Remainder => f.write_str("%"),
Op::GreaterThan => f.write_str(">"),
Op::GreaterThanEquals => f.write_str(">="),
Op::LessThan => f.write_str("<"),
Op::LessThanEquals => f.write_str("<="),
Op::EqualTo => f.write_str("=="),
Op::NotEqual => f.write_str("!="),
Op::BitwiseAnd => f.write_str("&"),
Op::BitwiseOr => f.write_str("|"),
Op::BitwiseXor => f.write_str("^"),
Op::Bang => f.write_str("!"),
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Ident {
pub name: String,
pub span: Span,
}
impl Ident {
pub fn span(&self) -> Span {
self.span.clone()
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum Expr {
Number(f64, Span),
String(String, Span),
Boolean(bool, Span),
Unit(Span),
Nil(Span),
SelfExpr(Span),
Identifier(Ident),
BinExpr(Box<BinExpr>, Span),
UnaryExpr(Op, Box<Expr>, Span),
Index(Box<Expr>, Box<Expr>, Span),
ParenExpr(Box<Expr>, Span),
List(Box<Vec<Expr>>, Span),
Tuple(Box<Vec<Expr>>, Span),
Map(Box<Vec<(Expr, Expr)>>, Span),
Or(Box<Expr>, Box<Expr>, Span),
And(Box<Expr>, Box<Expr>, Span),
FunCall(Box<Expr>, Box<Vec<Expr>>, Span),
MemberExpr(Box<Expr>, Box<Expr>, Span),
AssocExpr(Box<Expr>, Box<Expr>, Span),
Type(TypePath, Span),
}
impl Expr {
pub fn span(&self) -> Span {
match self.clone() {
Self::Number(_, span)
| Self::String(_, span)
| Self::Boolean(_, span)
| Self::Unit(span)
| Self::Nil(span)
| Self::SelfExpr(span)
| Self::BinExpr(_, span)
| Self::UnaryExpr(_, _, span)
| Self::ParenExpr(_, span)
| Self::Index(_, _, span)
| Self::List(_, span)
| Self::Tuple(_, span)
| Self::Map(_, span)
| Self::Or(_, _, span)
| Self::And(_, _, span)
| Self::FunCall(_, _, span)
| Self::MemberExpr(_, _, span)
| Self::AssocExpr(_, _, span)
| Self::Type(_, span) => span,
Self::Identifier(x) => x.span(),
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct TypePath {
pub ident: Ident,
pub arguments: Option<Box<TypePath>>,
}