Skip to main content

kore/
ast.rs

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