pub mod prelude;
use std::fmt;
use std::fmt::{Debug, Formatter};
use std::hash::Hash;
#[derive(PartialEq, Eq, Hash, Default, Clone)]
pub struct SpanWithoutFileId {
pub offset: u32,
pub length: u16,
}
impl Debug for SpanWithoutFileId {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "<{}:{}>", self.offset, self.length)
}
}
#[derive(PartialEq, Eq, Hash, Default, Clone)]
pub struct Node {
pub span: SpanWithoutFileId,
}
impl Debug for Node {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self.span)
}
}
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub struct QualifiedTypeIdentifier {
pub name: LocalTypeIdentifier,
pub module_path: Option<ModulePath>,
pub generic_params: Vec<Type>,
}
impl QualifiedTypeIdentifier {
#[must_use]
pub fn new(name: LocalTypeIdentifier, module_path: Vec<Node>) -> Self {
let module_path = if module_path.is_empty() {
None
} else {
Some(ModulePath(module_path))
};
Self {
name,
module_path,
generic_params: Vec::new(),
}
}
#[must_use]
pub fn new_with_generics(
name: LocalTypeIdentifier,
module_path: Vec<Node>,
generic_params: Vec<Type>,
) -> Self {
let module_path = if module_path.is_empty() {
None
} else {
Some(ModulePath(module_path))
};
Self {
name,
module_path,
generic_params,
}
}
}
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub struct QualifiedIdentifier {
pub name: Node,
pub module_path: Option<ModulePath>,
pub generic_params: Vec<Type>,
}
impl QualifiedIdentifier {
#[must_use]
pub fn new(name: Node, module_path: Vec<Node>) -> Self {
let module_path = if module_path.is_empty() {
None
} else {
Some(ModulePath(module_path))
};
Self {
name,
module_path,
generic_params: vec![],
}
}
#[must_use]
pub fn new_with_generics(
name: Node,
module_path: Vec<Node>,
generic_params: Vec<Type>,
) -> Self {
let module_path = if module_path.is_empty() {
None
} else {
Some(ModulePath(module_path))
};
Self {
name,
module_path,
generic_params,
}
}
}
#[derive(Debug, PartialEq, Eq, Hash, Default, Clone)]
pub struct LocalTypeIdentifier(pub Node);
impl LocalTypeIdentifier {
#[must_use]
pub const fn new(node: Node) -> Self {
Self(node)
}
}
#[derive(Debug, PartialEq, Eq, Hash, Default, Clone)]
pub struct TypeVariable(pub Node);
#[derive(Debug, PartialEq, Eq, Hash, Default, Clone)]
pub struct LocalTypeIdentifierWithOptionalTypeVariables {
pub name: Node,
pub type_variables: Vec<TypeVariable>,
}
#[derive(PartialEq, Eq, Hash, Debug, Clone)]
pub struct LocalIdentifier(pub Node);
impl LocalIdentifier {
#[must_use]
pub const fn new(node: Node) -> Self {
Self(node)
}
}
#[derive(Debug, PartialEq, Eq, Hash, Default, Clone)]
pub struct LocalConstantIdentifier(pub Node);
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub struct QualifiedConstantIdentifier {
pub name: Node,
pub module_path: Option<ModulePath>,
}
impl QualifiedConstantIdentifier {
#[must_use]
pub const fn new(name: Node, module_path: Option<ModulePath>) -> Self {
Self { name, module_path }
}
}
#[derive(Debug, Eq, Hash, Clone, PartialEq)]
pub struct FieldName(pub Node);
#[derive(Debug, Eq, Hash, PartialEq, Clone)]
pub struct ModulePath(pub Vec<Node>);
impl Default for ModulePath {
fn default() -> Self {
Self::new()
}
}
impl ModulePath {
#[must_use]
pub const fn new() -> Self {
Self(vec![])
}
}
#[derive(Debug, Clone)]
pub enum ImportItem {
Identifier(LocalIdentifier),
Type(LocalTypeIdentifier),
}
#[derive(Debug, Clone)]
pub enum ImportItems {
Nothing,
Items(Vec<ImportItem>),
All,
}
#[derive(Debug, Clone)]
pub struct Mod {
pub module_path: ModulePath,
pub items: ImportItems,
}
#[derive(Debug, Clone)]
pub struct Use {
pub module_path: ModulePath,
pub items: ImportItems,
}
#[derive(Debug, Eq, Clone, PartialEq)]
pub struct AliasType {
pub identifier: LocalTypeIdentifier,
pub referenced_type: Type,
}
#[derive(Debug, Eq, PartialEq, Hash, Clone, Default)]
pub struct AnonymousStructType {
pub fields: Vec<StructTypeField>,
}
impl AnonymousStructType {
#[must_use]
pub const fn new(fields: Vec<StructTypeField>) -> Self {
Self { fields }
}
}
#[derive(Debug, Clone)]
pub struct ConstantInfo {
pub constant_identifier: LocalConstantIdentifier,
pub expression: Box<Expression>,
}
#[derive(Debug, Clone)]
pub struct NamedStructDef {
pub identifier: LocalTypeIdentifierWithOptionalTypeVariables,
pub struct_type: AnonymousStructType,
}
#[derive(Debug, Clone)]
pub enum Definition {
AliasDef(AliasType),
NamedStructDef(NamedStructDef),
EnumDef(
LocalTypeIdentifierWithOptionalTypeVariables,
Vec<EnumVariantType>,
),
FunctionDef(Function),
ImplDef(LocalTypeIdentifierWithOptionalTypeVariables, Vec<Function>),
Mod(Mod),
Use(Use),
Constant(ConstantInfo),
}
#[derive(Debug, Clone)]
pub struct ForVar {
pub identifier: Node,
pub is_mut: Option<Node>,
}
#[derive(Debug, Clone)]
pub enum ForPattern {
Single(ForVar),
Pair(ForVar, ForVar),
}
impl ForPattern {
#[must_use]
pub fn any_mut(&self) -> Option<Node> {
match self {
Self::Single(a) => a.is_mut.clone(),
Self::Pair(a, b) => a.is_mut.clone().or_else(|| b.is_mut.clone()),
}
}
}
#[derive(Debug, Clone)]
pub struct IterableExpression {
pub expression: Box<MutableOrImmutableExpression>,
}
#[derive(Clone, Eq, PartialEq)]
pub struct Variable {
pub name: Node,
pub is_mutable: Option<Node>,
}
#[derive(Debug, Clone)]
pub struct VariableBinding {
pub variable: Variable,
pub expression: MutableOrImmutableExpression,
}
#[derive(Debug, Clone)]
pub struct WhenBinding {
pub variable: Variable,
pub expression: Option<MutableOrImmutableExpression>,
}
impl Variable {
#[must_use]
pub const fn new(name: Node, is_mutable: Option<Node>) -> Self {
Self { name, is_mutable }
}
}
impl Debug for Variable {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
if let Some(found) = &self.is_mutable {
write!(f, "mut {found:?} {:?}", self.name)
} else {
write!(f, "{:?}", self.name)
}
}
}
#[derive(Debug, Eq, Clone, PartialEq)]
pub struct Parameter {
pub variable: Variable,
pub param_type: Type,
}
#[derive(Debug, Clone)]
pub struct FunctionDeclaration {
pub name: Node,
pub params: Vec<Parameter>,
pub self_parameter: Option<SelfParameter>,
pub return_type: Option<Type>,
pub generic_variables: Vec<TypeVariable>,
}
#[derive(Debug, Clone)]
pub struct FunctionWithBody {
pub declaration: FunctionDeclaration,
pub body: Expression,
}
#[derive(Debug, Clone)]
pub enum Function {
Internal(FunctionWithBody),
External(FunctionDeclaration),
}
#[derive(Debug, Clone)]
pub struct SelfParameter {
pub is_mutable: Option<Node>,
pub self_node: Node,
}
#[derive(Debug, PartialEq, Eq)]
pub enum AssignmentOperatorKind {
Compound(CompoundOperatorKind),
Assign, }
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum CompoundOperatorKind {
Add, Sub, Mul, Div, Modulo, }
#[derive(Debug, Clone)]
pub struct CompoundOperator {
pub node: Node,
pub kind: CompoundOperatorKind,
}
#[derive(Debug, Clone)]
pub enum RangeMode {
Inclusive,
Exclusive,
}
#[derive(Debug, Clone)]
pub struct MutableOrImmutableExpression {
pub is_mutable: Option<Node>,
pub expression: Expression,
}
#[derive(Clone)]
pub struct Expression {
pub kind: ExpressionKind,
pub node: Node,
}
impl Debug for Expression {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
write!(f, "{:?}{:?}", self.node.span, self.kind)
}
}
#[derive(Debug, Clone)]
pub enum Postfix {
FieldAccess(Node),
Subscript(Expression),
MemberCall(Node, Vec<MutableOrImmutableExpression>),
FunctionCall(Node, Vec<MutableOrImmutableExpression>),
OptionalChainingOperator(Node), NoneCoalescingOperator(Expression), }
#[derive(Debug, Clone)]
pub struct PostfixChain {
pub base: Box<Expression>,
pub postfixes: Vec<Postfix>,
}
#[derive(Debug, Clone)]
pub enum ExpressionKind {
PostfixChain(PostfixChain),
VariableReference(Variable),
ConstantReference(QualifiedConstantIdentifier),
StaticMemberFunctionReference(QualifiedTypeIdentifier, Node),
IdentifierReference(QualifiedIdentifier),
VariableDefinition(Variable, Option<Type>, Box<MutableOrImmutableExpression>),
VariableAssignment(Variable, Box<MutableOrImmutableExpression>),
Assignment(Box<Expression>, Box<Expression>),
CompoundAssignment(Box<Expression>, CompoundOperator, Box<Expression>),
DestructuringAssignment(Vec<Variable>, Box<Expression>),
BinaryOp(Box<Expression>, BinaryOperator, Box<Expression>),
UnaryOp(UnaryOperator, Box<Expression>),
Block(Vec<Expression>),
With(Vec<VariableBinding>, Box<Expression>),
When(Vec<WhenBinding>, Box<Expression>, Option<Box<Expression>>),
ForLoop(
ForPattern,
IterableExpression,
Option<Box<Expression>>,
Box<Expression>,
),
WhileLoop(Box<Expression>, Box<Expression>),
If(Box<Expression>, Box<Expression>, Option<Box<Expression>>),
Match(Box<MutableOrImmutableExpression>, Vec<MatchArm>),
Guard(Vec<GuardExpr>),
InterpolatedString(Vec<StringPart>),
AnonymousStructLiteral(Vec<FieldExpression>, bool),
NamedStructLiteral(QualifiedTypeIdentifier, Vec<FieldExpression>, bool),
Range(Box<Expression>, Box<Expression>, RangeMode),
Literal(LiteralKind),
Lambda(Vec<Variable>, Box<Expression>),
}
#[derive(Debug, Clone)]
pub struct MatchArm {
pub pattern: Pattern,
pub expression: Expression,
}
#[derive(Debug, Clone)]
pub enum LiteralKind {
Int,
Float,
String(String),
Bool,
EnumVariant(EnumVariantLiteral),
Tuple(Vec<Expression>),
Slice(Vec<Expression>),
SlicePair(Vec<(Expression, Expression)>),
None,
}
#[derive(Debug, Clone)]
pub struct FieldExpression {
pub field_name: FieldName,
pub expression: Expression,
}
#[derive(Debug, Eq, Hash, Clone, PartialEq)]
pub struct StructTypeField {
pub field_name: FieldName,
pub field_type: Type,
}
#[derive(Debug, Clone)]
pub enum EnumVariantLiteral {
Simple(QualifiedTypeIdentifier, LocalTypeIdentifier),
Tuple(
QualifiedTypeIdentifier,
LocalTypeIdentifier,
Vec<Expression>,
),
Struct(
QualifiedTypeIdentifier,
LocalTypeIdentifier,
Vec<FieldExpression>,
bool,
),
}
impl EnumVariantLiteral {
#[must_use]
pub const fn node(&self) -> &Node {
match self {
EnumVariantLiteral::Simple(ident, _) => &ident.name.0,
EnumVariantLiteral::Tuple(ident, _, _) => &ident.name.0,
EnumVariantLiteral::Struct(ident, _, _, _) => &ident.name.0,
}
}
}
#[derive(Debug, Clone)]
pub enum EnumVariantType {
Simple(Node),
Tuple(Node, Vec<Type>),
Struct(Node, AnonymousStructType),
}
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub struct TypeForParameter {
pub ast_type: Type,
pub is_mutable: bool,
}
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub enum Type {
Slice(Box<Type>), SlicePair(Box<Type>, Box<Type>), AnonymousStruct(AnonymousStructType),
Unit,
Tuple(Vec<Type>),
Function(Vec<TypeForParameter>, Box<Type>),
Named(QualifiedTypeIdentifier),
Optional(Box<Type>, Node),
}
#[derive(Debug, Clone)]
pub struct BinaryOperator {
pub kind: BinaryOperatorKind,
pub node: Node,
}
#[derive(Debug, Clone)]
pub enum BinaryOperatorKind {
Add,
Subtract,
Multiply,
Divide,
Modulo,
LogicalOr,
LogicalAnd,
Equal,
NotEqual,
LessThan,
LessEqual,
GreaterThan,
GreaterEqual,
RangeExclusive,
}
#[derive(Debug, Clone)]
pub enum UnaryOperator {
Not(Node),
Negate(Node),
}
#[derive(Debug, Clone)]
pub struct GuardExpr {
pub clause: GuardClause,
pub result: Expression,
}
#[derive(Debug, Clone)]
pub enum GuardClause {
Wildcard(Node),
Expression(Expression),
}
#[derive(Debug, Clone)]
pub enum Pattern {
Wildcard(Node),
NormalPattern(Node, NormalPattern, Option<GuardClause>),
}
#[derive(Debug, Clone)]
pub enum NormalPattern {
PatternList(Vec<PatternElement>),
EnumPattern(Node, Option<Vec<PatternElement>>),
Literal(LiteralKind),
}
#[derive(Debug, Clone)]
pub enum PatternElement {
Variable(Variable),
Expression(Expression),
Wildcard(Node),
}
#[derive(Debug, Clone)]
pub enum StringPart {
Literal(Node, String),
Interpolation(Box<Expression>, Option<FormatSpecifier>),
}
#[derive(Debug, Clone)]
pub enum FormatSpecifier {
LowerHex(Node), UpperHex(Node), Binary(Node), Float(Node), Precision(u32, Node, PrecisionType), }
#[derive(Debug, Clone)]
pub enum PrecisionType {
Float(Node),
String(Node),
}
#[derive()]
pub struct Module {
pub expression: Option<Expression>,
pub definitions: Vec<Definition>,
}
impl Debug for Module {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
for definition in &self.definitions {
writeln!(f, "{definition:?}")?;
}
if !self.definitions.is_empty() && self.expression.is_some() {
writeln!(f, "---")?;
}
if let Some(found_expression) = &self.expression {
match &found_expression.kind {
ExpressionKind::Block(expressions) => {
for expression in expressions {
writeln!(f, "{expression:?}")?;
}
}
_ => writeln!(f, "{found_expression:?}")?,
}
}
Ok(())
}
}
impl Module {
#[must_use]
pub const fn new(definitions: Vec<Definition>, expression: Option<Expression>) -> Self {
Self {
expression,
definitions,
}
}
#[must_use]
pub const fn expression(&self) -> &Option<Expression> {
&self.expression
}
#[must_use]
pub const fn definitions(&self) -> &Vec<Definition> {
&self.definitions
}
#[must_use]
pub fn imports(&self) -> Vec<&Use> {
let mut use_items = Vec::new();
for def in &self.definitions {
if let Definition::Use(use_info) = def {
use_items.push(use_info);
}
}
use_items
}
}