use oxc_allocator::{Box, Vec};
use crate::{span::Span, token::Kind};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AstKind {
Program,
BooleanLiteral,
NumericLiteral,
StringLiteral,
IdentifierReference,
VariableExpression,
VariableMember,
ParenthesizedExpression,
BlockExpression,
BinaryExpression,
UnaryExpression,
TernaryExpression,
ConditionalExpression,
AssignmentExpression,
ResourceExpression,
ArrayAccessExpression,
ArrowAccessExpression,
CallExpression,
LoopExpression,
ForEachExpression,
Break,
Continue,
This,
Return,
}
#[derive(Debug)]
pub struct Program<'a> {
pub span: Span,
pub source: &'a str,
pub is_complex: bool,
pub body: Vec<'a, Expression<'a>>,
}
#[derive(Debug)]
pub enum Expression<'a> {
BooleanLiteral(Box<'a, BooleanLiteral>),
NumericLiteral(Box<'a, NumericLiteral<'a>>),
StringLiteral(Box<'a, StringLiteral<'a>>),
Variable(Box<'a, VariableExpression<'a>>),
Parenthesized(Box<'a, ParenthesizedExpression<'a>>),
Block(Box<'a, BlockExpression<'a>>),
Binary(Box<'a, BinaryExpression<'a>>),
Unary(Box<'a, UnaryExpression<'a>>),
Ternary(Box<'a, TernaryExpression<'a>>),
Conditional(Box<'a, ConditionalExpression<'a>>),
Assignment(Box<'a, AssignmentExpression<'a>>),
Resource(Box<'a, ResourceExpression<'a>>),
ArrayAccess(Box<'a, ArrayAccessExpression<'a>>),
ArrowAccess(Box<'a, ArrowAccessExpression<'a>>),
Call(Box<'a, CallExpression<'a>>),
Loop(Box<'a, LoopExpression<'a>>),
ForEach(Box<'a, ForEachExpression<'a>>),
Break(Box<'a, Break>),
Continue(Box<'a, Continue>),
This(Box<'a, This>),
Return(Box<'a, Return<'a>>),
}
#[derive(Debug)]
pub struct BooleanLiteral {
pub span: Span,
pub value: bool,
}
impl BooleanLiteral {
pub fn as_str(&self) -> &'static str {
if self.value {
"true"
} else {
"false"
}
}
}
#[derive(Debug)]
pub struct NumericLiteral<'a> {
pub span: Span,
pub value: f32,
pub raw: &'a str,
}
#[derive(Debug)]
pub struct StringLiteral<'a> {
pub span: Span,
pub value: &'a str,
}
#[derive(Debug)]
pub struct IdentifierReference<'a> {
pub span: Span,
pub name: &'a str,
}
#[derive(Debug)]
pub struct VariableExpression<'a> {
pub span: Span,
pub lifetime: VariableLifetime,
pub member: VariableMember<'a>,
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum VariableLifetime {
Temporary,
Variable,
Context,
}
impl VariableLifetime {
pub fn as_str(&self) -> &'static str {
match self {
Self::Temporary => "temp",
Self::Variable => "variable",
Self::Context => "context",
}
}
}
impl From<Kind> for VariableLifetime {
fn from(kind: Kind) -> Self {
match kind {
Kind::Temporary => Self::Temporary,
Kind::Variable => Self::Variable,
Kind::Context => Self::Context,
_ => unreachable!("Variable Lifetime: {kind:?}"),
}
}
}
#[derive(Debug)]
pub enum VariableMember<'a> {
Object {
span: Span,
object: Box<'a, VariableMember<'a>>,
property: IdentifierReference<'a>,
},
Property {
span: Span,
property: IdentifierReference<'a>,
},
}
#[derive(Debug)]
pub enum ParenthesizedExpression<'a> {
Single {
span: Span,
expression: Expression<'a>,
},
Complex {
span: Span,
expressions: Vec<'a, Expression<'a>>,
},
}
#[derive(Debug)]
pub struct BlockExpression<'a> {
pub span: Span,
pub expressions: Vec<'a, Expression<'a>>,
}
#[derive(Debug)]
pub struct BinaryExpression<'a> {
pub span: Span,
pub left: Expression<'a>,
pub operator: BinaryOperator,
pub right: Expression<'a>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BinaryOperator {
Equality,
Inequality,
LessThan,
LessEqualThan,
GreaterThan,
GreaterEqualThan,
Addition,
Subtraction,
Multiplication,
Division,
Or,
And,
Coalesce,
}
impl BinaryOperator {
pub fn as_str(&self) -> &'static str {
match self {
Self::Equality => "==",
Self::Inequality => "!=",
Self::LessThan => "<",
Self::LessEqualThan => "<=",
Self::GreaterThan => ">",
Self::GreaterEqualThan => ">=",
Self::Addition => "+",
Self::Subtraction => "-",
Self::Multiplication => "*",
Self::Division => "/",
Self::Or => "||",
Self::And => "&&",
Self::Coalesce => "??",
}
}
}
impl From<Kind> for BinaryOperator {
fn from(token: Kind) -> Self {
match token {
Kind::Eq => Self::Equality,
Kind::NotEq => Self::Inequality,
Kind::Lt => Self::LessThan,
Kind::Gt => Self::GreaterThan,
Kind::LtEq => Self::LessEqualThan,
Kind::GtEq => Self::GreaterEqualThan,
Kind::Or => Self::Or,
Kind::And => Self::And,
Kind::NullCoal => Self::Coalesce,
Kind::Minus => Self::Subtraction,
Kind::Plus => Self::Addition,
Kind::Star => Self::Multiplication,
Kind::Slash => Self::Division,
_ => unreachable!("Binary Operator: {token:?}"),
}
}
}
#[derive(Debug)]
pub struct UnaryExpression<'a> {
pub span: Span,
pub operator: UnaryOperator,
pub argument: Expression<'a>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum UnaryOperator {
Negate,
Not,
}
impl UnaryOperator {
pub fn as_str(&self) -> &'static str {
match self {
Self::Negate => "-",
Self::Not => "!",
}
}
}
impl From<Kind> for UnaryOperator {
fn from(token: Kind) -> Self {
match token {
Kind::Minus => Self::Negate,
Kind::Not => Self::Not,
_ => unreachable!("Unary Operator: {token:?}"),
}
}
}
#[derive(Debug)]
pub struct TernaryExpression<'a> {
pub span: Span,
pub test: Expression<'a>,
pub consequent: Expression<'a>,
pub alternate: Expression<'a>,
}
#[derive(Debug)]
pub struct ConditionalExpression<'a> {
pub span: Span,
pub test: Expression<'a>,
pub consequent: Expression<'a>,
}
#[derive(Debug)]
pub struct AssignmentExpression<'a> {
pub span: Span,
pub left: VariableExpression<'a>,
pub right: Expression<'a>,
}
#[derive(Debug)]
pub struct ResourceExpression<'a> {
pub span: Span,
pub section: ResourceSection,
pub name: IdentifierReference<'a>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ResourceSection {
Geometry,
Material,
Texture,
}
impl ResourceSection {
pub fn as_str(&self) -> &'static str {
match self {
Self::Geometry => "geometry",
Self::Material => "material",
Self::Texture => "texture",
}
}
}
impl From<Kind> for ResourceSection {
fn from(kind: Kind) -> Self {
match kind {
Kind::Geometry => Self::Geometry,
Kind::Material => Self::Material,
Kind::Texture => Self::Texture,
_ => unreachable!("Resource Section: {kind:?}"),
}
}
}
#[derive(Debug)]
pub struct ArrayAccessExpression<'a> {
pub span: Span,
pub name: IdentifierReference<'a>,
pub index: Expression<'a>,
}
#[derive(Debug)]
pub struct ArrowAccessExpression<'a> {
pub span: Span,
pub left: Expression<'a>,
pub right: Expression<'a>,
}
#[derive(Debug)]
pub struct CallExpression<'a> {
pub span: Span,
pub kind: CallKind,
pub callee: IdentifierReference<'a>,
pub arguments: Option<Vec<'a, Expression<'a>>>,
}
impl CallKind {
pub fn as_str(&self) -> &'static str {
match self {
Self::Math => "math",
Self::Query => "query",
}
}
}
impl From<Kind> for CallKind {
fn from(kind: Kind) -> Self {
match kind {
Kind::Math => Self::Math,
Kind::Query => Self::Query,
_ => unreachable!("Call Kind: {kind:?}"),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CallKind {
Math,
Query,
}
#[derive(Debug)]
pub struct LoopExpression<'a> {
pub span: Span,
pub count: Expression<'a>,
pub expression: BlockExpression<'a>,
}
#[derive(Debug)]
pub struct ForEachExpression<'a> {
pub span: Span,
pub variable: VariableExpression<'a>,
pub array: Expression<'a>,
pub expression: BlockExpression<'a>,
}
#[derive(Debug)]
pub struct Break {
pub span: Span,
}
#[derive(Debug)]
pub struct Continue {
pub span: Span,
}
#[derive(Debug)]
pub struct This {
pub span: Span,
}
#[derive(Debug)]
pub struct Return<'a> {
pub span: Span,
pub argument: Expression<'a>,
}