so... jai :D
This commit is contained in:
326
src/ast.zig
Normal file
326
src/ast.zig
Normal file
@@ -0,0 +1,326 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub const Span = struct {
|
||||
start: u32,
|
||||
end: u32,
|
||||
};
|
||||
|
||||
pub const Node = struct {
|
||||
span: Span,
|
||||
data: Data,
|
||||
|
||||
pub const Data = union(enum) {
|
||||
root: Root,
|
||||
fn_decl: FnDecl,
|
||||
block: Block,
|
||||
int_literal: IntLiteral,
|
||||
float_literal: FloatLiteral,
|
||||
bool_literal: BoolLiteral,
|
||||
string_literal: StringLiteral,
|
||||
identifier: Identifier,
|
||||
enum_literal: EnumLiteral,
|
||||
binary_op: BinaryOp,
|
||||
chained_comparison: ChainedComparison,
|
||||
unary_op: UnaryOp,
|
||||
call: Call,
|
||||
field_access: FieldAccess,
|
||||
if_expr: IfExpr,
|
||||
match_expr: MatchExpr,
|
||||
match_arm: MatchArm,
|
||||
const_decl: ConstDecl,
|
||||
var_decl: VarDecl,
|
||||
assignment: Assignment,
|
||||
enum_decl: EnumDecl,
|
||||
struct_decl: StructDecl,
|
||||
struct_literal: StructLiteral,
|
||||
union_decl: UnionDecl,
|
||||
union_literal: UnionLiteral,
|
||||
lambda: Lambda,
|
||||
type_expr: TypeExpr,
|
||||
param: Param,
|
||||
defer_stmt: DeferStmt,
|
||||
comptime_expr: ComptimeExpr,
|
||||
insert_expr: InsertExpr,
|
||||
return_stmt: ReturnStmt,
|
||||
import_decl: ImportDecl,
|
||||
namespace_decl: NamespaceDecl,
|
||||
array_type_expr: ArrayTypeExpr,
|
||||
array_literal: ArrayLiteral,
|
||||
parameterized_type_expr: ParameterizedTypeExpr,
|
||||
index_expr: IndexExpr,
|
||||
while_expr: WhileExpr,
|
||||
for_expr: ForExpr,
|
||||
spread_expr: SpreadExpr,
|
||||
break_expr: void,
|
||||
continue_expr: void,
|
||||
undef_literal: void,
|
||||
builtin_expr: void,
|
||||
|
||||
pub fn declName(self: Data) ?[]const u8 {
|
||||
return switch (self) {
|
||||
.fn_decl => |d| d.name,
|
||||
.const_decl => |d| d.name,
|
||||
.var_decl => |d| d.name,
|
||||
.enum_decl => |d| d.name,
|
||||
.struct_decl => |d| d.name,
|
||||
.union_decl => |d| d.name,
|
||||
.namespace_decl => |d| d.name,
|
||||
else => null,
|
||||
};
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
pub const Root = struct {
|
||||
decls: []const *Node,
|
||||
};
|
||||
|
||||
pub const FnDecl = struct {
|
||||
name: []const u8,
|
||||
params: []const Param,
|
||||
return_type: ?*Node,
|
||||
body: *Node,
|
||||
type_params: []const StructTypeParam = &.{},
|
||||
};
|
||||
|
||||
pub const Param = struct {
|
||||
name: []const u8,
|
||||
name_span: Span,
|
||||
type_expr: *Node,
|
||||
is_variadic: bool = false,
|
||||
is_comptime: bool = false,
|
||||
};
|
||||
|
||||
pub const Block = struct {
|
||||
stmts: []const *Node,
|
||||
};
|
||||
|
||||
pub const IntLiteral = struct {
|
||||
value: i64,
|
||||
};
|
||||
|
||||
pub const FloatLiteral = struct {
|
||||
value: f64,
|
||||
};
|
||||
|
||||
pub const BoolLiteral = struct {
|
||||
value: bool,
|
||||
};
|
||||
|
||||
pub const StringLiteral = struct {
|
||||
raw: []const u8,
|
||||
};
|
||||
|
||||
pub const Identifier = struct {
|
||||
name: []const u8,
|
||||
};
|
||||
|
||||
pub const EnumLiteral = struct {
|
||||
name: []const u8, // without the leading dot
|
||||
};
|
||||
|
||||
pub const BinaryOp = struct {
|
||||
op: Op,
|
||||
lhs: *Node,
|
||||
rhs: *Node,
|
||||
|
||||
pub const Op = enum {
|
||||
add,
|
||||
sub,
|
||||
mul,
|
||||
div,
|
||||
mod,
|
||||
eq,
|
||||
neq,
|
||||
lt,
|
||||
lte,
|
||||
gt,
|
||||
gte,
|
||||
and_op,
|
||||
or_op,
|
||||
};
|
||||
};
|
||||
|
||||
pub const ChainedComparison = struct {
|
||||
operands: []const *Node,
|
||||
ops: []const BinaryOp.Op,
|
||||
};
|
||||
|
||||
pub const UnaryOp = struct {
|
||||
op: Op,
|
||||
operand: *Node,
|
||||
|
||||
pub const Op = enum {
|
||||
negate,
|
||||
not,
|
||||
xx,
|
||||
};
|
||||
};
|
||||
|
||||
pub const Call = struct {
|
||||
callee: *Node,
|
||||
args: []const *Node,
|
||||
};
|
||||
|
||||
pub const FieldAccess = struct {
|
||||
object: *Node,
|
||||
field: []const u8,
|
||||
};
|
||||
|
||||
pub const IfExpr = struct {
|
||||
condition: *Node,
|
||||
then_branch: *Node,
|
||||
else_branch: ?*Node,
|
||||
is_inline: bool, // true for `if cond then a else b`
|
||||
};
|
||||
|
||||
pub const MatchExpr = struct {
|
||||
subject: *Node,
|
||||
arms: []const MatchArm,
|
||||
};
|
||||
|
||||
pub const MatchArm = struct {
|
||||
pattern: ?*Node, // null = else (default) arm
|
||||
body: *Node,
|
||||
is_break: bool,
|
||||
};
|
||||
|
||||
pub const ConstDecl = struct {
|
||||
name: []const u8,
|
||||
type_annotation: ?*Node,
|
||||
value: *Node,
|
||||
};
|
||||
|
||||
pub const VarDecl = struct {
|
||||
name: []const u8,
|
||||
type_annotation: ?*Node,
|
||||
value: ?*Node,
|
||||
};
|
||||
|
||||
pub const Assignment = struct {
|
||||
target: *Node,
|
||||
op: Op,
|
||||
value: *Node,
|
||||
|
||||
pub const Op = enum {
|
||||
assign,
|
||||
add_assign,
|
||||
sub_assign,
|
||||
mul_assign,
|
||||
div_assign,
|
||||
mod_assign,
|
||||
};
|
||||
};
|
||||
|
||||
pub const EnumDecl = struct {
|
||||
name: []const u8,
|
||||
variants: []const []const u8,
|
||||
};
|
||||
|
||||
pub const StructTypeParam = struct {
|
||||
name: []const u8, // e.g. "N" or "T" (without $)
|
||||
constraint: *Node, // type_expr: "u32" for value param, "Type" for type param
|
||||
};
|
||||
|
||||
pub const StructDecl = struct {
|
||||
name: []const u8,
|
||||
field_names: []const []const u8,
|
||||
field_types: []const *Node, // type_expr nodes
|
||||
field_defaults: []const ?*Node, // default value per field, null if none
|
||||
type_params: []const StructTypeParam = &.{},
|
||||
};
|
||||
|
||||
pub const StructFieldInit = struct {
|
||||
name: ?[]const u8, // null for positional, non-null for named/shorthand
|
||||
value: *Node,
|
||||
};
|
||||
|
||||
pub const StructLiteral = struct {
|
||||
struct_name: ?[]const u8, // null for anonymous `.{ ... }`
|
||||
type_expr: ?*Node = null, // for GenericType(args).{ ... }
|
||||
field_inits: []const StructFieldInit,
|
||||
};
|
||||
|
||||
pub const Lambda = struct {
|
||||
params: []const Param,
|
||||
return_type: ?*Node,
|
||||
body: *Node,
|
||||
type_params: []const StructTypeParam = &.{},
|
||||
};
|
||||
|
||||
pub const TypeExpr = struct {
|
||||
name: []const u8,
|
||||
is_generic: bool = false,
|
||||
};
|
||||
|
||||
pub const DeferStmt = struct {
|
||||
expr: *Node,
|
||||
};
|
||||
|
||||
pub const ComptimeExpr = struct {
|
||||
expr: *Node,
|
||||
};
|
||||
|
||||
pub const InsertExpr = struct {
|
||||
expr: *Node,
|
||||
};
|
||||
|
||||
pub const ReturnStmt = struct {
|
||||
value: ?*Node,
|
||||
};
|
||||
|
||||
pub const ImportDecl = struct {
|
||||
path: []const u8,
|
||||
name: ?[]const u8,
|
||||
};
|
||||
|
||||
pub const ArrayTypeExpr = struct {
|
||||
length: *Node, // int_literal for the size
|
||||
element_type: *Node, // type_expr for the element type
|
||||
};
|
||||
|
||||
pub const ArrayLiteral = struct {
|
||||
elements: []const *Node,
|
||||
type_expr: ?*Node = null,
|
||||
};
|
||||
|
||||
pub const ParameterizedTypeExpr = struct {
|
||||
name: []const u8, // e.g. "Vector", or later generic struct names
|
||||
args: []const *Node, // e.g. [int_literal(3), type_expr("f32")]
|
||||
};
|
||||
|
||||
pub const IndexExpr = struct {
|
||||
object: *Node,
|
||||
index: *Node,
|
||||
};
|
||||
|
||||
pub const WhileExpr = struct {
|
||||
condition: *Node,
|
||||
body: *Node,
|
||||
};
|
||||
|
||||
pub const ForExpr = struct {
|
||||
iterable: *Node,
|
||||
body: *Node,
|
||||
};
|
||||
|
||||
pub const SpreadExpr = struct {
|
||||
operand: *Node,
|
||||
};
|
||||
|
||||
pub const UnionDecl = struct {
|
||||
name: []const u8,
|
||||
variant_names: []const []const u8,
|
||||
variant_types: []const ?*Node, // null for void variants
|
||||
};
|
||||
|
||||
pub const UnionLiteral = struct {
|
||||
union_name: ?[]const u8, // null for anonymous `.variant(expr)`
|
||||
variant_name: []const u8,
|
||||
payload: ?*Node, // null for void variants
|
||||
};
|
||||
|
||||
pub const NamespaceDecl = struct {
|
||||
name: []const u8,
|
||||
decls: []const *Node,
|
||||
};
|
||||
Reference in New Issue
Block a user