Skip to main content

kain/
ast.rs

1//! KAIN Abstract Syntax Tree
2//!
3//! The AST represents the structure of a KAIN program after parsing.
4//! It captures all language constructs as first-class citizens:
5//! - Functions with effect annotations
6//! - Components (React-like UI)
7//! - Shaders (GPU programs)
8//! - Actors (Erlang-style concurrency)
9//! - Comptime blocks (Zig-style compile-time execution)
10
11use crate::span::Span;
12use crate::effects::Effect;
13
14/// A complete KAIN program/module
15#[derive(Debug, Clone)]
16pub struct Program {
17    pub items: Vec<Item>,
18    pub span: Span,
19}
20
21/// Top-level items in a module
22#[derive(Debug, Clone)]
23pub enum Item {
24    /// `fn name(args) -> Type with Effects: body`
25    Function(Function),
26    
27    /// `component Name(props) -> UI with Reactive: jsx`
28    Component(Component),
29    
30    /// `shader Name(inputs) -> Fragment with GPU: body`
31    Shader(Shader),
32    
33    /// `actor Name: handlers`
34    Actor(Actor),
35    
36    /// `struct Name { fields }`
37    Struct(Struct),
38    
39    /// `enum Name { variants }`
40    Enum(Enum),
41    
42    /// `trait Name { methods }`
43    Trait(Trait),
44    
45    /// `impl Trait for Type { methods }`
46    Impl(Impl),
47    
48    /// `type Alias = Type`
49    TypeAlias(TypeAlias),
50    
51    /// `use path::to::item`
52    Use(Use),
53    
54    /// `mod name`
55    Mod(Mod),
56    
57    /// `const NAME: Type = value`
58    Const(Const),
59    
60    /// `comptime { code }`
61    Comptime(ComptimeBlock),
62    
63    /// `macro name!(params) { expansion }`
64    Macro(MacroDef),
65
66    /// `test "name": body`
67    Test(TestDef),
68}
69
70#[derive(Debug, Clone)]
71pub struct TestDef {
72    pub name: String,
73    pub body: Block,
74    pub span: Span,
75}
76
77// === FUNCTIONS ===
78
79/// Function attribute/decorator (e.g., @wasm, @js, @inline)
80#[derive(Debug, Clone)]
81pub struct Attribute {
82    pub name: String,
83    pub args: Vec<Expr>,
84    pub span: Span,
85}
86
87#[derive(Debug, Clone)]
88pub struct Function {
89    pub name: String,
90    pub generics: Vec<Generic>,
91    pub params: Vec<Param>,
92    pub return_type: Option<Type>,
93    pub effects: Vec<Effect>,
94    pub body: Block,
95    pub visibility: Visibility,
96    pub attributes: Vec<Attribute>,
97    pub span: Span,
98}
99
100#[derive(Debug, Clone)]
101pub struct Param {
102    pub name: String,
103    pub ty: Type,
104    pub mutable: bool,
105    pub default: Option<Expr>,
106    pub span: Span,
107}
108
109#[derive(Debug, Clone)]
110pub struct Generic {
111    pub name: String,
112    pub bounds: Vec<TypeBound>,
113    pub span: Span,
114}
115
116#[derive(Debug, Clone)]
117pub struct TypeBound {
118    pub trait_name: String,
119    pub span: Span,
120}
121
122// === COMPONENTS (React-like UI) ===
123
124#[derive(Debug, Clone)]
125pub struct Component {
126    pub name: String,
127    pub props: Vec<Param>,
128    pub state: Vec<StateDecl>,
129    pub methods: Vec<Function>,
130    pub effects: Vec<Effect>,
131    pub body: JSXNode,
132    pub visibility: Visibility,
133    pub attributes: Vec<Attribute>,
134    pub span: Span,
135}
136
137#[derive(Debug, Clone)]
138pub struct StateDecl {
139    pub name: String,
140    pub ty: Type,
141    pub initial: Expr,
142    pub weak: bool,
143    pub span: Span,
144}
145
146#[derive(Debug, Clone)]
147pub enum JSXNode {
148    /// `<tag attr="value">children</tag>`
149    Element {
150        tag: String,
151        attributes: Vec<JSXAttribute>,
152        children: Vec<JSXNode>,
153        span: Span,
154    },
155    /// `{expression}`
156    Expression(Box<Expr>),
157    /// Plain text
158    Text(String, Span),
159    /// `<Component prop={value} />`
160    ComponentCall {
161        name: String,
162        props: Vec<JSXAttribute>,
163        children: Vec<JSXNode>,
164        span: Span,
165    },
166    /// `for item in list: jsx`
167    For {
168        binding: String,
169        iter: Box<Expr>,
170        body: Box<JSXNode>,
171        span: Span,
172    },
173    /// `if cond: jsx [else: jsx]`
174    If {
175        condition: Box<Expr>,
176        then_branch: Box<JSXNode>,
177        else_branch: Option<Box<JSXNode>>,
178        span: Span,
179    },
180    /// Fragment wrapper
181    Fragment(Vec<JSXNode>, Span),
182}
183
184#[derive(Debug, Clone)]
185pub struct JSXAttribute {
186    pub name: String,
187    pub value: JSXAttrValue,
188    pub span: Span,
189}
190
191#[derive(Debug, Clone)]
192pub enum JSXAttrValue {
193    String(String),
194    Expr(Expr),
195    Bool(bool),
196}
197
198// === SHADERS (GPU Programs) ===
199
200#[derive(Debug, Clone)]
201pub struct Shader {
202    pub name: String,
203    pub stage: ShaderStage,
204    pub inputs: Vec<Param>,
205    pub outputs: Type,
206    pub uniforms: Vec<Uniform>,
207    pub body: Block,
208    pub span: Span,
209}
210
211#[derive(Debug, Clone, Copy, PartialEq, Eq)]
212pub enum ShaderStage {
213    Vertex,
214    Fragment,
215    Compute,
216}
217
218#[derive(Debug, Clone)]
219pub struct Uniform {
220    pub name: String,
221    pub ty: Type,
222    pub binding: u32,
223    pub span: Span,
224}
225
226// === ACTORS (Erlang-style Concurrency) ===
227
228#[derive(Debug, Clone)]
229pub struct Actor {
230    pub name: String,
231    pub state: Vec<StateDecl>,
232    pub handlers: Vec<MessageHandler>,
233    pub span: Span,
234}
235
236#[derive(Debug, Clone)]
237pub struct MessageHandler {
238    pub message_type: String,
239    pub params: Vec<Param>,
240    pub body: Block,
241    pub span: Span,
242}
243
244// === DATA STRUCTURES ===
245
246#[derive(Debug, Clone)]
247pub struct Struct {
248    pub name: String,
249    pub generics: Vec<Generic>,
250    pub fields: Vec<Field>,
251    pub visibility: Visibility,
252    pub span: Span,
253}
254
255#[derive(Debug, Clone)]
256pub struct Field {
257    pub name: String,
258    pub ty: Type,
259    pub visibility: Visibility,
260    pub default: Option<Expr>,
261    pub weak: bool,
262    pub span: Span,
263}
264
265#[derive(Debug, Clone)]
266pub struct Enum {
267    pub name: String,
268    pub generics: Vec<Generic>,
269    pub variants: Vec<Variant>,
270    pub visibility: Visibility,
271    pub span: Span,
272}
273
274#[derive(Debug, Clone)]
275pub struct Variant {
276    pub name: String,
277    pub fields: VariantFields,
278    pub span: Span,
279}
280
281#[derive(Debug, Clone)]
282pub enum VariantFields {
283    Unit,
284    Tuple(Vec<Type>),
285    Struct(Vec<Field>),
286}
287
288// === TRAITS AND IMPLS ===
289
290#[derive(Debug, Clone)]
291pub struct Trait {
292    pub name: String,
293    pub generics: Vec<Generic>,
294    pub methods: Vec<TraitMethod>,
295    pub visibility: Visibility,
296    pub span: Span,
297}
298
299#[derive(Debug, Clone)]
300pub struct TraitMethod {
301    pub name: String,
302    pub params: Vec<Param>,
303    pub return_type: Option<Type>,
304    pub effects: Vec<Effect>,
305    pub default_impl: Option<Block>,
306    pub span: Span,
307}
308
309#[derive(Debug, Clone)]
310pub struct Impl {
311    pub generics: Vec<Generic>,
312    pub trait_name: Option<String>,
313    pub target_type: Type,
314    pub methods: Vec<Function>,
315    pub span: Span,
316}
317
318// === TYPE SYSTEM ===
319
320#[derive(Debug, Clone, PartialEq)]
321pub enum Type {
322    /// Named type: `Int`, `String`, `Vec<T>`
323    Named {
324        name: String,
325        generics: Vec<Type>,
326        span: Span,
327    },
328    /// Tuple: `(A, B, C)`
329    Tuple(Vec<Type>, Span),
330    /// Array: `[T; N]`
331    Array(Box<Type>, usize, Span),
332    /// Slice: `[T]`
333    Slice(Box<Type>, Span),
334    /// Reference: `&T`, `&mut T`
335    Ref {
336        mutable: bool,
337        inner: Box<Type>,
338        lifetime: Option<String>,
339        span: Span,
340    },
341    /// Function type: `fn(A, B) -> C with Effects`
342    Function {
343        params: Vec<Type>,
344        return_type: Box<Type>,
345        effects: Vec<Effect>,
346        span: Span,
347    },
348    /// Option shorthand: `T?`
349    Option(Box<Type>, Span),
350    /// Result shorthand: `T!E`
351    Result(Box<Type>, Box<Type>, Span),
352    /// Inferred: `_`
353    Infer(Span),
354    /// Never type: `!`
355    Never(Span),
356    /// Unit type: `()`
357    Unit(Span),
358    /// impl Trait: `impl Future`, `impl Iterator<Item = T>`
359    Impl {
360        trait_name: String,
361        generics: Vec<Type>,
362        span: Span,
363    },
364}
365
366impl Type {
367    pub fn span(&self) -> Span {
368        match self {
369            Type::Named { span, .. }
370            | Type::Tuple(_, span)
371            | Type::Array(_, _, span)
372            | Type::Slice(_, span)
373            | Type::Ref { span, .. }
374            | Type::Function { span, .. }
375            | Type::Option(_, span)
376            | Type::Result(_, _, span)
377            | Type::Infer(span)
378            | Type::Never(span)
379            | Type::Unit(span)
380            | Type::Impl { span, .. } => *span,
381        }
382    }
383}
384
385// === OTHER TOP-LEVEL ITEMS ===
386
387#[derive(Debug, Clone)]
388pub struct TypeAlias {
389    pub name: String,
390    pub generics: Vec<Generic>,
391    pub target: Type,
392    pub visibility: Visibility,
393    pub span: Span,
394}
395
396#[derive(Debug, Clone)]
397pub struct Use {
398    pub path: Vec<String>,
399    pub alias: Option<String>,
400    pub glob: bool,
401    pub span: Span,
402}
403
404#[derive(Debug, Clone)]
405pub struct Mod {
406    pub name: String,
407    pub inline: Option<Vec<Item>>,
408    pub visibility: Visibility,
409    pub span: Span,
410}
411
412#[derive(Debug, Clone)]
413pub struct Const {
414    pub name: String,
415    pub ty: Type,
416    pub value: Expr,
417    pub visibility: Visibility,
418    pub span: Span,
419}
420
421#[derive(Debug, Clone)]
422pub struct ComptimeBlock {
423    pub body: Block,
424    pub span: Span,
425}
426
427#[derive(Debug, Clone)]
428pub struct MacroDef {
429    pub name: String,
430    pub params: Vec<MacroParam>,
431    pub body: MacroBody,
432    pub span: Span,
433}
434
435#[derive(Debug, Clone)]
436pub struct MacroParam {
437    pub name: String,
438    pub kind: MacroParamKind,
439    pub span: Span,
440}
441
442#[derive(Debug, Clone)]
443pub enum MacroParamKind {
444    Expr,
445    Type,
446    Ident,
447    Block,
448    Token,
449    Repetition(Box<MacroParamKind>),
450}
451
452#[derive(Debug, Clone)]
453pub enum MacroBody {
454    Tokens(Vec<MacroToken>),
455    Block(Block),
456}
457
458#[derive(Debug, Clone)]
459pub struct MacroToken {
460    pub content: String,
461    pub span: Span,
462}
463
464// === EXPRESSIONS ===
465
466#[derive(Debug, Clone)]
467pub struct Block {
468    pub stmts: Vec<Stmt>,
469    pub span: Span,
470}
471
472#[derive(Debug, Clone)]
473pub enum Stmt {
474    /// `let pattern [: Type] = value`
475    Let {
476        pattern: Pattern,
477        ty: Option<Type>,
478        value: Option<Expr>,
479        span: Span,
480    },
481    /// Expression statement
482    Expr(Expr),
483    /// `return [value]`
484    Return(Option<Expr>, Span),
485    /// `break [value]`
486    Break(Option<Expr>, Span),
487    /// `continue`
488    Continue(Span),
489    /// `for binding in iter: body`
490    For {
491        binding: Pattern,
492        iter: Expr,
493        body: Block,
494        span: Span,
495    },
496    /// `while cond: body`
497    While {
498        condition: Expr,
499        body: Block,
500        span: Span,
501    },
502    /// `loop: body`
503    Loop {
504        body: Block,
505        span: Span,
506    },
507    /// Item declaration (nested function, struct, etc.)
508    Item(Box<Item>),
509}
510
511#[derive(Debug, Clone)]
512pub enum Expr {
513    /// Literals
514    Int(i64, Span),
515    Float(f64, Span),
516    String(String, Span),
517    FString(Vec<Expr>, Span),
518    Bool(bool, Span),
519    None(Span),
520    
521    /// Identifier
522    Ident(String, Span),
523    
524    /// Macro call
525    MacroCall {
526        name: String,
527        args: Vec<Expr>,
528        span: Span,
529    },
530    
531    /// Binary operation
532    Binary {
533        left: Box<Expr>,
534        op: BinaryOp,
535        right: Box<Expr>,
536        span: Span,
537    },
538    
539    /// Unary operation
540    Unary {
541        op: UnaryOp,
542        operand: Box<Expr>,
543        span: Span,
544    },
545    
546    /// Function call: `func(args)`
547    Call {
548        callee: Box<Expr>,
549        args: Vec<CallArg>,
550        span: Span,
551    },
552    
553    /// Method call: `obj.method(args)`
554    MethodCall {
555        receiver: Box<Expr>,
556        method: String,
557        args: Vec<CallArg>,
558        span: Span,
559    },
560    
561    /// Field access: `obj.field`
562    Field {
563        object: Box<Expr>,
564        field: String,
565        span: Span,
566    },
567    
568    /// Index: `arr[i]`
569    Index {
570        object: Box<Expr>,
571        index: Box<Expr>,
572        span: Span,
573    },
574
575    /// Assignment: `target = value`
576    Assign {
577        target: Box<Expr>,
578        value: Box<Expr>,
579        span: Span,
580    },
581    
582    /// Struct literal: `Point { x: 1, y: 2 }`
583    Struct {
584        name: String,
585        fields: Vec<(String, Expr)>,
586        span: Span,
587    },
588
589    EnumVariant {
590        enum_name: String,
591        variant: String,
592        fields: EnumVariantFields,
593        span: Span,
594    },
595    
596    /// Array literal: `[1, 2, 3]`
597    Array(Vec<Expr>, Span),
598    
599    /// Tuple literal: `(a, b, c)`
600    Tuple(Vec<Expr>, Span),
601    
602    /// Range: `start..end`, `start..=end`
603    Range {
604        start: Option<Box<Expr>>,
605        end: Option<Box<Expr>>,
606        inclusive: bool,
607        span: Span,
608    },
609    
610    /// If expression
611    If {
612        condition: Box<Expr>,
613        then_branch: Block,
614        else_branch: Option<Box<ElseBranch>>,
615        span: Span,
616    },
617    
618    /// Match expression
619    Match {
620        scrutinee: Box<Expr>,
621        arms: Vec<MatchArm>,
622        span: Span,
623    },
624    
625    /// Lambda: `|args| body` or `|args| -> Type: body`
626    Lambda {
627        params: Vec<Param>,
628        return_type: Option<Type>,
629        body: Box<Expr>,
630        span: Span,
631    },
632    
633    /// Reference: `&value`, `&mut value`
634    Ref {
635        mutable: bool,
636        value: Box<Expr>,
637        span: Span,
638    },
639    
640    /// Dereference: `*ptr`
641    Deref(Box<Expr>, Span),
642    
643    /// Cast: `value as Type`
644    Cast {
645        value: Box<Expr>,
646        target: Type,
647        span: Span,
648    },
649    
650    /// Try: `expr?`
651    Try(Box<Expr>, Span),
652    
653    /// Await: `await expr`
654    Await(Box<Expr>, Span),
655    
656    /// Spawn actor: `spawn ActorName { state }`
657    Spawn {
658        actor: String,
659        init: Vec<(String, Expr)>,
660        span: Span,
661    },
662    
663    /// Send message: `send target <- Message { data }`
664    SendMsg {
665        target: Box<Expr>,
666        message: String,
667        data: Vec<(String, Expr)>,
668        span: Span,
669    },
670    
671    /// Comptime expression: `comptime { expr }`
672    Comptime(Box<Expr>, Span),
673    
674    /// Macro invocation: `name!(args)`
675    // Already defined above, remove duplicate
676    
677    /// Block expression
678    Block(Block, Span),
679
680    /// JSX embedded in expression
681    JSX(JSXNode, Span),
682    
683    /// Grouped expression: `(expr)`
684    Paren(Box<Expr>, Span),
685    
686    /// Return expression: `return [expr]`
687    Return(Option<Box<Expr>>, Span),
688    
689    /// Break expression: `break [expr]`
690    Break(Option<Box<Expr>>, Span),
691    
692    /// Continue expression: `continue`
693    Continue(Span),
694}
695
696impl Expr {
697    pub fn span(&self) -> Span {
698        match self {
699            Expr::Int(_, s)
700            | Expr::Float(_, s)
701            | Expr::String(_, s)
702            | Expr::FString(_, s)
703            | Expr::Bool(_, s)
704            | Expr::None(s)
705            | Expr::Ident(_, s)
706            | Expr::Binary { span: s, .. }
707            | Expr::Unary { span: s, .. }
708            | Expr::Call { span: s, .. }
709            | Expr::MethodCall { span: s, .. }
710            | Expr::Field { span: s, .. }
711            | Expr::Index { span: s, .. }
712            | Expr::Struct { span: s, .. }
713            | Expr::EnumVariant { span: s, .. }
714            | Expr::Array(_, s)
715            | Expr::Tuple(_, s)
716            | Expr::Range { span: s, .. }
717            | Expr::If { span: s, .. }
718            | Expr::Match { span: s, .. }
719            | Expr::Lambda { span: s, .. }
720            | Expr::Ref { span: s, .. }
721            | Expr::Deref(_, s)
722            | Expr::Cast { span: s, .. }
723            | Expr::Try(_, s)
724            | Expr::Await(_, s)
725            | Expr::Spawn { span: s, .. }
726            | Expr::SendMsg { span: s, .. }
727            | Expr::Comptime(_, s)
728            | Expr::MacroCall { span: s, .. }
729            | Expr::Block(_, s)
730            | Expr::JSX(_, s)
731            | Expr::Assign { span: s, .. }
732            | Expr::Paren(_, s)
733            | Expr::Return(_, s)
734            | Expr::Break(_, s)
735            | Expr::Continue(s) => *s,
736        }
737    }
738}
739
740#[derive(Debug, Clone)]
741pub enum EnumVariantFields {
742    Unit,
743    Tuple(Vec<Expr>),
744    Struct(Vec<(String, Expr)>),
745}
746
747#[derive(Debug, Clone)]
748pub struct CallArg {
749    pub name: Option<String>,
750    pub value: Expr,
751    pub span: Span,
752}
753
754#[derive(Debug, Clone)]
755pub enum ElseBranch {
756    Else(Block),
757    ElseIf(Box<Expr>, Block, Option<Box<ElseBranch>>),
758}
759
760#[derive(Debug, Clone)]
761pub struct MatchArm {
762    pub pattern: Pattern,
763    pub guard: Option<Expr>,
764    pub body: Expr,
765    pub span: Span,
766}
767
768#[derive(Debug, Clone)]
769pub enum Pattern {
770    /// Wildcard: `_`
771    Wildcard(Span),
772    /// Literal: `1`, `"hello"`, `true`
773    Literal(Expr),
774    /// Binding: `x`, `mut x`
775    Binding {
776        name: String,
777        mutable: bool,
778        span: Span,
779    },
780    /// Struct: `Point { x, y }`
781    Struct {
782        name: String,
783        fields: Vec<(String, Pattern)>,
784        rest: bool,
785        span: Span,
786    },
787    /// Tuple: `(a, b, c)`
788    Tuple(Vec<Pattern>, Span),
789    /// Enum variant: `Some(x)`, `None`
790    Variant {
791        enum_name: Option<String>,
792        variant: String,
793        fields: VariantPatternFields,
794        span: Span,
795    },
796    /// Array/Slice: `[first, rest @ ..]`
797    Slice {
798        patterns: Vec<Pattern>,
799        rest: Option<String>,
800        span: Span,
801    },
802    /// Or pattern: `A | B`
803    Or(Vec<Pattern>, Span),
804    /// Range: `1..10`
805    Range {
806        start: Option<Box<Expr>>,
807        end: Option<Box<Expr>>,
808        inclusive: bool,
809        span: Span,
810    },
811}
812
813#[derive(Debug, Clone)]
814pub enum VariantPatternFields {
815    Unit,
816    Tuple(Vec<Pattern>),
817    Struct(Vec<(String, Pattern)>),
818}
819
820// === OPERATORS ===
821
822#[derive(Debug, Clone, Copy, PartialEq, Eq)]
823pub enum BinaryOp {
824    // Arithmetic
825    Add,
826    Sub,
827    Mul,
828    Div,
829    Mod,
830    Pow,
831    
832    // Comparison
833    Eq,
834    Ne,
835    Lt,
836    Gt,
837    Le,
838    Ge,
839    
840    // Logical
841    And,
842    Or,
843    
844    // Bitwise
845    BitAnd,
846    BitOr,
847    BitXor,
848    Shl,
849    Shr,
850    
851    // Assignment
852    Assign,
853    AddAssign,
854    SubAssign,
855    MulAssign,
856    DivAssign,
857    
858    // Range
859    Range,
860    RangeInclusive,
861}
862
863#[derive(Debug, Clone, Copy, PartialEq, Eq)]
864pub enum UnaryOp {
865    Neg,
866    Not,
867    BitNot,
868    Ref,
869    RefMut,
870    Deref,
871}
872
873// === VISIBILITY ===
874
875#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
876pub enum Visibility {
877    #[default]
878    Private,
879    Public,
880    Crate,
881    Super,
882}
883