mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
package odin_parser
This commit is contained in:
@@ -0,0 +1,607 @@
|
|||||||
|
package odin_ast
|
||||||
|
|
||||||
|
import "core:odin/token"
|
||||||
|
|
||||||
|
Proc_Tag :: enum {
|
||||||
|
Bounds_Check,
|
||||||
|
No_Bounds_Check,
|
||||||
|
Require_Results,
|
||||||
|
No_Context,
|
||||||
|
}
|
||||||
|
Proc_Tags :: distinct bit_set[Proc_Tag; u32];
|
||||||
|
|
||||||
|
Proc_Inlining :: enum u32 {
|
||||||
|
None = 0,
|
||||||
|
Inline = 1,
|
||||||
|
No_Inline = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
Proc_Calling_Convention :: enum i32 {
|
||||||
|
Invalid = 0,
|
||||||
|
Odin,
|
||||||
|
Contextless,
|
||||||
|
C_Decl,
|
||||||
|
Std_Call,
|
||||||
|
Fast_Call,
|
||||||
|
|
||||||
|
Foreign_Block_Default = -1,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Comment_Group :: struct {
|
||||||
|
list: []token.Token,
|
||||||
|
}
|
||||||
|
|
||||||
|
Node :: struct {
|
||||||
|
pos: token.Pos,
|
||||||
|
end: token.Pos,
|
||||||
|
derived: any,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Expr :: struct {
|
||||||
|
using expr_base: Node,
|
||||||
|
}
|
||||||
|
Stmt :: struct {
|
||||||
|
using stmt_base: Node,
|
||||||
|
}
|
||||||
|
Decl :: struct {
|
||||||
|
using decl_base: Stmt,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expressions
|
||||||
|
|
||||||
|
Bad_Expr :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
}
|
||||||
|
|
||||||
|
Ident :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
name: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
Implicit :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
tok: token.Token,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Undef :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
tok: token.Kind,
|
||||||
|
}
|
||||||
|
|
||||||
|
Basic_Lit :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
tok: token.Token,
|
||||||
|
}
|
||||||
|
|
||||||
|
Basic_Directive :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
tok: token.Token,
|
||||||
|
name: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
Ellipsis :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
tok: token.Kind,
|
||||||
|
expr: ^Expr,
|
||||||
|
}
|
||||||
|
|
||||||
|
Proc_Lit :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
type: ^Proc_Type,
|
||||||
|
body: ^Stmt,
|
||||||
|
tags: Proc_Tags,
|
||||||
|
inlining: Proc_Inlining,
|
||||||
|
}
|
||||||
|
|
||||||
|
Comp_Lit :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
type: ^Expr,
|
||||||
|
open: token.Pos,
|
||||||
|
elems: []^Expr,
|
||||||
|
close: token.Pos,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Tag_Expr :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
op: token.Token,
|
||||||
|
name: string,
|
||||||
|
expr: ^Expr,
|
||||||
|
}
|
||||||
|
|
||||||
|
Unary_Expr :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
op: token.Token,
|
||||||
|
expr: ^Expr,
|
||||||
|
}
|
||||||
|
|
||||||
|
Binary_Expr :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
left: ^Expr,
|
||||||
|
op: token.Token,
|
||||||
|
right: ^Expr,
|
||||||
|
}
|
||||||
|
|
||||||
|
Paren_Expr :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
open: token.Pos,
|
||||||
|
expr: ^Expr,
|
||||||
|
close: token.Pos,
|
||||||
|
}
|
||||||
|
|
||||||
|
Selector_Expr :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
expr: ^Expr,
|
||||||
|
field: ^Ident,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Index_Expr :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
expr: ^Expr,
|
||||||
|
open: token.Pos,
|
||||||
|
index: ^Expr,
|
||||||
|
close: token.Pos,
|
||||||
|
}
|
||||||
|
|
||||||
|
Deref_Expr :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
expr: ^Expr,
|
||||||
|
op: token.Token,
|
||||||
|
}
|
||||||
|
|
||||||
|
Slice_Expr :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
expr: ^Expr,
|
||||||
|
open: token.Pos,
|
||||||
|
low: ^Expr,
|
||||||
|
interval: token.Token,
|
||||||
|
high: ^Expr,
|
||||||
|
close: token.Pos,
|
||||||
|
}
|
||||||
|
|
||||||
|
Call_Expr :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
inlining: Proc_Inlining,
|
||||||
|
expr: ^Expr,
|
||||||
|
open: token.Pos,
|
||||||
|
args: []^Expr,
|
||||||
|
ellipsis: token.Token,
|
||||||
|
close: token.Pos,
|
||||||
|
}
|
||||||
|
|
||||||
|
Field_Value :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
field: ^Expr,
|
||||||
|
sep: token.Pos,
|
||||||
|
value: ^Expr,
|
||||||
|
}
|
||||||
|
|
||||||
|
Ternary_Expr :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
cond: ^Expr,
|
||||||
|
op1: token.Token,
|
||||||
|
x: ^Expr,
|
||||||
|
op2: token.Token,
|
||||||
|
y: ^Expr,
|
||||||
|
}
|
||||||
|
|
||||||
|
Type_Assertion :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
expr: ^Expr,
|
||||||
|
dot: token.Pos,
|
||||||
|
open: token.Pos,
|
||||||
|
type: ^Expr,
|
||||||
|
close: token.Pos,
|
||||||
|
}
|
||||||
|
|
||||||
|
Type_Cast :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
tok: token.Token,
|
||||||
|
open: token.Pos,
|
||||||
|
type: ^Expr,
|
||||||
|
close: token.Pos,
|
||||||
|
expr: ^Expr,
|
||||||
|
}
|
||||||
|
|
||||||
|
Auto_Cast :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
op: token.Token,
|
||||||
|
expr: ^Expr,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Statements
|
||||||
|
|
||||||
|
Bad_Stmt :: struct {
|
||||||
|
using node: Stmt,
|
||||||
|
}
|
||||||
|
|
||||||
|
Empty_Stmt :: struct {
|
||||||
|
using node: Stmt,
|
||||||
|
semicolon: token.Pos, // Position of the following ';'
|
||||||
|
}
|
||||||
|
|
||||||
|
Expr_Stmt :: struct {
|
||||||
|
using node: Stmt,
|
||||||
|
expr: ^Expr,
|
||||||
|
}
|
||||||
|
|
||||||
|
Tag_Stmt :: struct {
|
||||||
|
using node: Stmt,
|
||||||
|
op: token.Token,
|
||||||
|
name: string,
|
||||||
|
stmt: ^Stmt,
|
||||||
|
}
|
||||||
|
|
||||||
|
Assign_Stmt :: struct {
|
||||||
|
using node: Stmt,
|
||||||
|
lhs: []^Expr,
|
||||||
|
op: token.Token,
|
||||||
|
rhs: []^Expr,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Block_Stmt :: struct {
|
||||||
|
using node: Stmt,
|
||||||
|
label: ^Expr,
|
||||||
|
open: token.Pos,
|
||||||
|
stmts: []^Stmt,
|
||||||
|
close: token.Pos,
|
||||||
|
}
|
||||||
|
|
||||||
|
If_Stmt :: struct {
|
||||||
|
using node: Stmt,
|
||||||
|
label: ^Expr,
|
||||||
|
if_pos: token.Pos,
|
||||||
|
init: ^Stmt,
|
||||||
|
cond: ^Expr,
|
||||||
|
body: ^Stmt,
|
||||||
|
else_stmt: ^Stmt,
|
||||||
|
}
|
||||||
|
|
||||||
|
When_Stmt :: struct {
|
||||||
|
using node: Stmt,
|
||||||
|
when_pos: token.Pos,
|
||||||
|
cond: ^Expr,
|
||||||
|
body: ^Stmt,
|
||||||
|
else_stmt: ^Stmt,
|
||||||
|
}
|
||||||
|
|
||||||
|
Return_Stmt :: struct {
|
||||||
|
using node: Stmt,
|
||||||
|
results: []^Expr,
|
||||||
|
}
|
||||||
|
|
||||||
|
Defer_Stmt :: struct {
|
||||||
|
using node: Stmt,
|
||||||
|
stmt: ^Stmt,
|
||||||
|
}
|
||||||
|
|
||||||
|
For_Stmt :: struct {
|
||||||
|
using node: Stmt,
|
||||||
|
label: ^Expr,
|
||||||
|
for_pos: token.Pos,
|
||||||
|
init: ^Stmt,
|
||||||
|
cond: ^Expr,
|
||||||
|
post: ^Stmt,
|
||||||
|
body: ^Stmt,
|
||||||
|
}
|
||||||
|
|
||||||
|
Range_Stmt :: struct {
|
||||||
|
using node: Stmt,
|
||||||
|
label: ^Expr,
|
||||||
|
for_pos: token.Pos,
|
||||||
|
val0: ^Expr,
|
||||||
|
val1: ^Expr,
|
||||||
|
in_pos: token.Pos,
|
||||||
|
expr: ^Expr,
|
||||||
|
body: ^Stmt,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Case_Clause :: struct {
|
||||||
|
using node: Stmt,
|
||||||
|
case_pos: token.Pos,
|
||||||
|
list: []^Expr,
|
||||||
|
terminator: token.Token,
|
||||||
|
body: []^Stmt,
|
||||||
|
}
|
||||||
|
|
||||||
|
Switch_Stmt :: struct {
|
||||||
|
using node: Stmt,
|
||||||
|
label: ^Expr,
|
||||||
|
switch_pos: token.Pos,
|
||||||
|
init: ^Stmt,
|
||||||
|
cond: ^Expr,
|
||||||
|
body: ^Stmt,
|
||||||
|
complete: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
Type_Switch_Stmt :: struct {
|
||||||
|
using node: Stmt,
|
||||||
|
label: ^Expr,
|
||||||
|
switch_pos: token.Pos,
|
||||||
|
tag: ^Stmt,
|
||||||
|
expr: ^Expr,
|
||||||
|
body: ^Stmt,
|
||||||
|
complete: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
Branch_Stmt :: struct {
|
||||||
|
using node: Stmt,
|
||||||
|
tok: token.Token,
|
||||||
|
label: ^Ident,
|
||||||
|
}
|
||||||
|
|
||||||
|
Using_Stmt :: struct {
|
||||||
|
using node: Stmt,
|
||||||
|
list: []^Expr,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Declarations
|
||||||
|
|
||||||
|
Bad_Decl :: struct {
|
||||||
|
using node: Decl,
|
||||||
|
}
|
||||||
|
|
||||||
|
Value_Decl :: struct {
|
||||||
|
using node: Decl,
|
||||||
|
docs: ^Comment_Group,
|
||||||
|
attributes: [dynamic]^Attribute, // dynamic as parsing will add to them lazily
|
||||||
|
names: []^Expr,
|
||||||
|
type: ^Expr,
|
||||||
|
values: []^Expr,
|
||||||
|
comment: ^Comment_Group,
|
||||||
|
is_static: bool,
|
||||||
|
is_using: bool,
|
||||||
|
is_mutable: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
Package_Decl :: struct {
|
||||||
|
using node: Decl,
|
||||||
|
docs: ^Comment_Group,
|
||||||
|
token: token.Token,
|
||||||
|
name: string,
|
||||||
|
comment: ^Comment_Group,
|
||||||
|
}
|
||||||
|
|
||||||
|
Import_Decl :: struct {
|
||||||
|
using node: Decl,
|
||||||
|
docs: ^Comment_Group,
|
||||||
|
is_using: bool,
|
||||||
|
import_tok: token.Token,
|
||||||
|
name: token.Token,
|
||||||
|
relpath: token.Token,
|
||||||
|
fullpath: string,
|
||||||
|
comment: ^Comment_Group,
|
||||||
|
}
|
||||||
|
|
||||||
|
Foreign_Block_Decl :: struct {
|
||||||
|
using node: Decl,
|
||||||
|
docs: ^Comment_Group,
|
||||||
|
attributes: [dynamic]^Attribute, // dynamic as parsing will add to them lazily
|
||||||
|
tok: token.Token,
|
||||||
|
foreign_library: ^Expr,
|
||||||
|
body: ^Stmt,
|
||||||
|
}
|
||||||
|
|
||||||
|
Foreign_Import_Decl :: struct {
|
||||||
|
using node: Decl,
|
||||||
|
docs: ^Comment_Group,
|
||||||
|
foreign_tok: token.Token,
|
||||||
|
import_tok: token.Token,
|
||||||
|
name: ^Ident,
|
||||||
|
collection_name: string,
|
||||||
|
fullpaths: []string,
|
||||||
|
comment: ^Comment_Group,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Other things
|
||||||
|
unparen_expr :: proc(expr: ^Expr) -> ^Expr {
|
||||||
|
if expr == nil {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
e, ok := expr.derived.(Paren_Expr);
|
||||||
|
if !ok do break;
|
||||||
|
expr = e.expr;
|
||||||
|
}
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Field_Flag :: enum {
|
||||||
|
Ellipsis,
|
||||||
|
Using,
|
||||||
|
No_Alias,
|
||||||
|
C_Vararg,
|
||||||
|
Auto_Cast,
|
||||||
|
In,
|
||||||
|
Results,
|
||||||
|
Default_Parameters,
|
||||||
|
Typeid_Token,
|
||||||
|
}
|
||||||
|
|
||||||
|
Field_Flags :: distinct bit_set[Field_Flag];
|
||||||
|
|
||||||
|
Field_Flags_Struct :: Field_Flags{
|
||||||
|
Field_Flag.Using,
|
||||||
|
};
|
||||||
|
Field_Flags_Record_Poly_Params :: Field_Flags{
|
||||||
|
Field_Flag.Typeid_Token,
|
||||||
|
};
|
||||||
|
Field_Flags_Signature :: Field_Flags{
|
||||||
|
Field_Flag.Ellipsis,
|
||||||
|
Field_Flag.Using,
|
||||||
|
Field_Flag.No_Alias,
|
||||||
|
Field_Flag.C_Vararg,
|
||||||
|
Field_Flag.Auto_Cast,
|
||||||
|
Field_Flag.Default_Parameters,
|
||||||
|
};
|
||||||
|
|
||||||
|
Field_Flags_Signature_Params :: Field_Flags_Signature | {Field_Flag.Typeid_Token};
|
||||||
|
Field_Flags_Signature_Results :: Field_Flags_Signature;
|
||||||
|
|
||||||
|
|
||||||
|
Proc_Group :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
tok: token.Token,
|
||||||
|
open: token.Pos,
|
||||||
|
args: []^Expr,
|
||||||
|
close: token.Pos,
|
||||||
|
}
|
||||||
|
|
||||||
|
Attribute :: struct {
|
||||||
|
using node: Node,
|
||||||
|
tok: token.Kind,
|
||||||
|
open: token.Pos,
|
||||||
|
elems: []^Expr,
|
||||||
|
close: token.Pos,
|
||||||
|
}
|
||||||
|
|
||||||
|
Field :: struct {
|
||||||
|
using node: Node,
|
||||||
|
docs: ^Comment_Group,
|
||||||
|
names: []^Expr, // Could be polymorphic
|
||||||
|
type: ^Expr,
|
||||||
|
default_value: ^Expr,
|
||||||
|
flags: Field_Flags,
|
||||||
|
comment: ^Comment_Group,
|
||||||
|
}
|
||||||
|
|
||||||
|
Field_List :: struct {
|
||||||
|
using node: Node,
|
||||||
|
open: token.Pos,
|
||||||
|
list: []^Field,
|
||||||
|
close: token.Pos,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Types
|
||||||
|
Typeid_Type :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
tok: token.Kind,
|
||||||
|
specialization: ^Expr,
|
||||||
|
}
|
||||||
|
|
||||||
|
Helper_Type :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
tok: token.Kind,
|
||||||
|
type: ^Expr,
|
||||||
|
}
|
||||||
|
|
||||||
|
Distinct_Type :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
tok: token.Kind,
|
||||||
|
type: ^Expr,
|
||||||
|
}
|
||||||
|
|
||||||
|
Opaque_Type :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
tok: token.Kind,
|
||||||
|
type: ^Expr,
|
||||||
|
}
|
||||||
|
|
||||||
|
Poly_Type :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
dollar: token.Pos,
|
||||||
|
type: ^Ident,
|
||||||
|
specialization: ^Expr,
|
||||||
|
}
|
||||||
|
|
||||||
|
Proc_Type :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
tok: token.Token,
|
||||||
|
calling_convention: Proc_Calling_Convention,
|
||||||
|
params: ^Field_List,
|
||||||
|
arrow: token.Pos,
|
||||||
|
results: ^Field_List,
|
||||||
|
tags: Proc_Tags,
|
||||||
|
generic: bool,
|
||||||
|
diverging: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
Pointer_Type :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
pointer: token.Pos,
|
||||||
|
elem: ^Expr,
|
||||||
|
}
|
||||||
|
|
||||||
|
Array_Type :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
open: token.Pos,
|
||||||
|
len: ^Expr, // Ellipsis node for [?]T arrray types, nil for slice types
|
||||||
|
close: token.Pos,
|
||||||
|
elem: ^Expr,
|
||||||
|
}
|
||||||
|
|
||||||
|
Dynamic_Array_Type :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
open: token.Pos,
|
||||||
|
dynamic_pos: token.Pos,
|
||||||
|
close: token.Pos,
|
||||||
|
elem: ^Expr,
|
||||||
|
}
|
||||||
|
|
||||||
|
Struct_Type :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
tok_pos: token.Pos,
|
||||||
|
poly_params: ^Field_List,
|
||||||
|
align: ^Expr,
|
||||||
|
is_packed: bool,
|
||||||
|
is_raw_union: bool,
|
||||||
|
fields: ^Field_List,
|
||||||
|
name_count: int,
|
||||||
|
}
|
||||||
|
|
||||||
|
Union_Type :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
tok_pos: token.Pos,
|
||||||
|
poly_params: ^Field_List,
|
||||||
|
align: ^Expr,
|
||||||
|
variants: []^Expr,
|
||||||
|
}
|
||||||
|
|
||||||
|
Enum_Type :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
tok_pos: token.Pos,
|
||||||
|
base_type: ^Expr,
|
||||||
|
open: token.Pos,
|
||||||
|
fields: []^Expr,
|
||||||
|
close: token.Pos,
|
||||||
|
|
||||||
|
is_using: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
Bit_Field_Type :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
tok_pos: token.Pos,
|
||||||
|
align: ^Expr,
|
||||||
|
open: token.Pos,
|
||||||
|
fields: []^Field_Value, // Field_Value with ':' rather than '='
|
||||||
|
close: token.Pos,
|
||||||
|
}
|
||||||
|
|
||||||
|
Bit_Set_Type :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
tok_pos: token.Pos,
|
||||||
|
open: token.Pos,
|
||||||
|
elem: ^Expr,
|
||||||
|
underlying: ^Expr,
|
||||||
|
close: token.Pos,
|
||||||
|
}
|
||||||
|
|
||||||
|
Map_Type :: struct {
|
||||||
|
using node: Expr,
|
||||||
|
tok_pos: token.Pos,
|
||||||
|
key: ^Expr,
|
||||||
|
value: ^Expr,
|
||||||
|
}
|
||||||
@@ -0,0 +1,313 @@
|
|||||||
|
package odin_ast
|
||||||
|
|
||||||
|
import "core:mem"
|
||||||
|
import "core:fmt"
|
||||||
|
import "core:odin/token"
|
||||||
|
|
||||||
|
new :: proc($T: typeid, pos, end: token.Pos) -> ^T {
|
||||||
|
n := mem.new(T);
|
||||||
|
n.pos = pos;
|
||||||
|
n.end = end;
|
||||||
|
n.derived = n^;
|
||||||
|
base: ^Node = n; // dummy check
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
clone :: proc{
|
||||||
|
clone_node,
|
||||||
|
clone_expr,
|
||||||
|
clone_stmt,
|
||||||
|
clone_decl,
|
||||||
|
clone_array,
|
||||||
|
clone_dynamic_array,
|
||||||
|
};
|
||||||
|
|
||||||
|
clone_array :: proc(array: $A/[]^$T) -> A {
|
||||||
|
if len(array) == 0 {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
res := make(A, len(array));
|
||||||
|
for elem, i in array {
|
||||||
|
res[i] = auto_cast clone(elem);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
clone_dynamic_array :: proc(array: $A/[dynamic]^$T) -> A {
|
||||||
|
if len(array) == 0 {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
res := make(A, len(array));
|
||||||
|
for elem, i in array {
|
||||||
|
res[i] = auto_cast clone(elem);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
clone_expr :: proc(node: ^Expr) -> ^Expr {
|
||||||
|
return cast(^Expr)clone_node(node);
|
||||||
|
}
|
||||||
|
clone_stmt :: proc(node: ^Stmt) -> ^Stmt {
|
||||||
|
return cast(^Stmt)clone_node(node);
|
||||||
|
}
|
||||||
|
clone_decl :: proc(node: ^Decl) -> ^Decl {
|
||||||
|
return cast(^Decl)clone_node(node);
|
||||||
|
}
|
||||||
|
clone_node :: proc(node: ^Node) -> ^Node {
|
||||||
|
if node == nil {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
size := size_of(Node);
|
||||||
|
align := align_of(Node);
|
||||||
|
ti := type_info_of(node.derived.id);
|
||||||
|
if ti != nil {
|
||||||
|
size = ti.size;
|
||||||
|
align = ti.align;
|
||||||
|
}
|
||||||
|
|
||||||
|
res := cast(^Node)mem.alloc(size, align);
|
||||||
|
src: rawptr = node;
|
||||||
|
if node.derived != nil {
|
||||||
|
src = node.derived.data;
|
||||||
|
}
|
||||||
|
mem.copy(res, src, size);
|
||||||
|
res.derived.data = rawptr(res);
|
||||||
|
|
||||||
|
switch n in node.derived {
|
||||||
|
case Bad_Expr:
|
||||||
|
case Ident:
|
||||||
|
case Implicit:
|
||||||
|
case Undef:
|
||||||
|
case Basic_Lit:
|
||||||
|
|
||||||
|
case Ellipsis:
|
||||||
|
r := cast(^Ellipsis)res;
|
||||||
|
r.expr = clone(r.expr);
|
||||||
|
case Proc_Lit:
|
||||||
|
r := cast(^Proc_Lit)res;
|
||||||
|
r.type = auto_cast clone(r.type);
|
||||||
|
r.body = clone(r.body);
|
||||||
|
case Comp_Lit:
|
||||||
|
r := cast(^Comp_Lit)res;
|
||||||
|
r.type = clone(r.type);
|
||||||
|
r.elems = clone(r.elems);
|
||||||
|
|
||||||
|
case Tag_Expr:
|
||||||
|
r := cast(^Tag_Expr)res;
|
||||||
|
r.expr = clone(r.expr);
|
||||||
|
case Unary_Expr:
|
||||||
|
r := cast(^Unary_Expr)res;
|
||||||
|
r.expr = clone(r.expr);
|
||||||
|
case Binary_Expr:
|
||||||
|
r := cast(^Binary_Expr)res;
|
||||||
|
r.left = clone(r.left);
|
||||||
|
r.right = clone(r.right);
|
||||||
|
case Paren_Expr:
|
||||||
|
r := cast(^Paren_Expr)res;
|
||||||
|
r.expr = clone(r.expr);
|
||||||
|
case Selector_Expr:
|
||||||
|
r := cast(^Selector_Expr)res;
|
||||||
|
r.expr = clone(r.expr);
|
||||||
|
r.field = auto_cast clone(r.field);
|
||||||
|
case Index_Expr:
|
||||||
|
r := cast(^Index_Expr)res;
|
||||||
|
r.expr = clone(r.expr);
|
||||||
|
r.index = clone(r.index);
|
||||||
|
case Deref_Expr:
|
||||||
|
r := cast(^Deref_Expr)res;
|
||||||
|
r.expr = clone(r.expr);
|
||||||
|
case Slice_Expr:
|
||||||
|
r := cast(^Slice_Expr)res;
|
||||||
|
r.expr = clone(r.expr);
|
||||||
|
r.low = clone(r.low);
|
||||||
|
r.high = clone(r.high);
|
||||||
|
case Call_Expr:
|
||||||
|
r := cast(^Call_Expr)res;
|
||||||
|
r.expr = clone(r.expr);
|
||||||
|
r.args = clone(r.args);
|
||||||
|
case Field_Value:
|
||||||
|
r := cast(^Field_Value)res;
|
||||||
|
r.field = clone(r.field);
|
||||||
|
r.value = clone(r.value);
|
||||||
|
case Ternary_Expr:
|
||||||
|
r := cast(^Ternary_Expr)res;
|
||||||
|
r.cond = clone(r.cond);
|
||||||
|
r.x = clone(r.x);
|
||||||
|
r.y = clone(r.y);
|
||||||
|
case Type_Assertion:
|
||||||
|
r := cast(^Type_Assertion)res;
|
||||||
|
r.expr = clone(r.expr);
|
||||||
|
r.type = clone(r.type);
|
||||||
|
case Type_Cast:
|
||||||
|
r := cast(^Type_Cast)res;
|
||||||
|
r.type = clone(r.type);
|
||||||
|
r.expr = clone(r.expr);
|
||||||
|
case Auto_Cast:
|
||||||
|
r := cast(^Auto_Cast)res;
|
||||||
|
r.expr = clone(r.expr);
|
||||||
|
|
||||||
|
case Bad_Stmt:
|
||||||
|
case Empty_Stmt:
|
||||||
|
case Expr_Stmt:
|
||||||
|
r := cast(^Expr_Stmt)res;
|
||||||
|
r.expr = clone(r.expr);
|
||||||
|
case Tag_Stmt:
|
||||||
|
r := cast(^Expr_Stmt)res;
|
||||||
|
r.expr = clone(r.expr);
|
||||||
|
|
||||||
|
case Assign_Stmt:
|
||||||
|
r := cast(^Assign_Stmt)res;
|
||||||
|
r.lhs = clone(r.lhs);
|
||||||
|
r.rhs = clone(r.rhs);
|
||||||
|
case Block_Stmt:
|
||||||
|
r := cast(^Block_Stmt)res;
|
||||||
|
r.label = auto_cast clone(r.label);
|
||||||
|
r.stmts = clone(r.stmts);
|
||||||
|
case If_Stmt:
|
||||||
|
r := cast(^If_Stmt)res;
|
||||||
|
r.label = auto_cast clone(r.label);
|
||||||
|
r.init = clone(r.init);
|
||||||
|
r.cond = clone(r.cond);
|
||||||
|
r.body = clone(r.body);
|
||||||
|
r.else_stmt = clone(r.else_stmt);
|
||||||
|
case When_Stmt:
|
||||||
|
r := cast(^When_Stmt)res;
|
||||||
|
r.cond = clone(r.cond);
|
||||||
|
r.body = clone(r.body);
|
||||||
|
r.else_stmt = clone(r.else_stmt);
|
||||||
|
case Return_Stmt:
|
||||||
|
r := cast(^Return_Stmt)res;
|
||||||
|
r.results = clone(r.results);
|
||||||
|
case Defer_Stmt:
|
||||||
|
r := cast(^Defer_Stmt)res;
|
||||||
|
r.stmt = clone(r.stmt);
|
||||||
|
case For_Stmt:
|
||||||
|
r := cast(^For_Stmt)res;
|
||||||
|
r.label = auto_cast clone(r.label);
|
||||||
|
r.init = clone(r.init);
|
||||||
|
r.cond = clone(r.cond);
|
||||||
|
r.post = clone(r.post);
|
||||||
|
r.body = clone(r.body);
|
||||||
|
case Range_Stmt:
|
||||||
|
r := cast(^Range_Stmt)res;
|
||||||
|
r.label = auto_cast clone(r.label);
|
||||||
|
r.val0 = clone(r.val0);
|
||||||
|
r.val1 = clone(r.val1);
|
||||||
|
r.expr = clone(r.expr);
|
||||||
|
r.body = clone(r.body);
|
||||||
|
case Case_Clause:
|
||||||
|
r := cast(^Case_Clause)res;
|
||||||
|
r.list = clone(r.list);
|
||||||
|
r.body = clone(r.body);
|
||||||
|
case Switch_Stmt:
|
||||||
|
r := cast(^Switch_Stmt)res;
|
||||||
|
r.label = auto_cast clone(r.label);
|
||||||
|
r.init = clone(r.init);
|
||||||
|
r.cond = clone(r.cond);
|
||||||
|
r.body = clone(r.body);
|
||||||
|
case Type_Switch_Stmt:
|
||||||
|
r := cast(^Type_Switch_Stmt)res;
|
||||||
|
r.label = auto_cast clone(r.label);
|
||||||
|
r.tag = clone(r.tag);
|
||||||
|
r.expr = clone(r.expr);
|
||||||
|
r.body = clone(r.body);
|
||||||
|
case Branch_Stmt:
|
||||||
|
r := cast(^Branch_Stmt)res;
|
||||||
|
r.label = auto_cast clone(r.label);
|
||||||
|
case Using_Stmt:
|
||||||
|
r := cast(^Using_Stmt)res;
|
||||||
|
r.list = clone(r.list);
|
||||||
|
case Bad_Decl:
|
||||||
|
case Value_Decl:
|
||||||
|
r := cast(^Value_Decl)res;
|
||||||
|
r.attributes = clone(r.attributes);
|
||||||
|
r.names = clone(r.names);
|
||||||
|
r.type = clone(r.type);
|
||||||
|
r.values = clone(r.values);
|
||||||
|
case Package_Decl:
|
||||||
|
case Import_Decl:
|
||||||
|
case Foreign_Block_Decl:
|
||||||
|
r := cast(^Foreign_Block_Decl)res;
|
||||||
|
r.attributes = clone(r.attributes);
|
||||||
|
r.foreign_library = clone(r.foreign_library);
|
||||||
|
r.body = clone(r.body);
|
||||||
|
case Foreign_Import_Decl:
|
||||||
|
r := cast(^Foreign_Import_Decl)res;
|
||||||
|
r.name = auto_cast clone(r.name);
|
||||||
|
case Proc_Group:
|
||||||
|
r := cast(^Proc_Group)res;
|
||||||
|
r.args = clone(r.args);
|
||||||
|
case Attribute:
|
||||||
|
r := cast(^Attribute)res;
|
||||||
|
r.elems = clone(r.elems);
|
||||||
|
case Field:
|
||||||
|
r := cast(^Field)res;
|
||||||
|
r.names = clone(r.names);
|
||||||
|
r.type = clone(r.type);
|
||||||
|
r.default_value = clone(r.default_value);
|
||||||
|
case Field_List:
|
||||||
|
r := cast(^Field_List)res;
|
||||||
|
r.list = clone(r.list);
|
||||||
|
case Typeid_Type:
|
||||||
|
r := cast(^Typeid_Type)res;
|
||||||
|
r.specialization = clone(r.specialization);
|
||||||
|
case Helper_Type:
|
||||||
|
r := cast(^Helper_Type)res;
|
||||||
|
r.type = clone(r.type);
|
||||||
|
case Distinct_Type:
|
||||||
|
r := cast(^Distinct_Type)res;
|
||||||
|
r.type = clone(r.type);
|
||||||
|
case Opaque_Type:
|
||||||
|
r := cast(^Opaque_Type)res;
|
||||||
|
r.type = clone(r.type);
|
||||||
|
case Poly_Type:
|
||||||
|
r := cast(^Poly_Type)res;
|
||||||
|
r.type = auto_cast clone(r.type);
|
||||||
|
r.specialization = clone(r.specialization);
|
||||||
|
case Proc_Type:
|
||||||
|
r := cast(^Proc_Type)res;
|
||||||
|
r.params = auto_cast clone(r.params);
|
||||||
|
r.results = auto_cast clone(r.results);
|
||||||
|
case Pointer_Type:
|
||||||
|
r := cast(^Pointer_Type)res;
|
||||||
|
r.elem = clone(r.elem);
|
||||||
|
case Array_Type:
|
||||||
|
r := cast(^Array_Type)res;
|
||||||
|
r.len = clone(r.len);
|
||||||
|
r.elem = clone(r.elem);
|
||||||
|
case Dynamic_Array_Type:
|
||||||
|
r := cast(^Dynamic_Array_Type)res;
|
||||||
|
r.elem = clone(r.elem);
|
||||||
|
case Struct_Type:
|
||||||
|
r := cast(^Struct_Type)res;
|
||||||
|
r.poly_params = auto_cast clone(r.poly_params);
|
||||||
|
r.align = clone(r.align);
|
||||||
|
r.fields = auto_cast clone(r.fields);
|
||||||
|
case Union_Type:
|
||||||
|
r := cast(^Union_Type)res;
|
||||||
|
r.poly_params = auto_cast clone(r.poly_params);
|
||||||
|
r.align = clone(r.align);
|
||||||
|
r.variants = clone(r.variants);
|
||||||
|
case Enum_Type:
|
||||||
|
r := cast(^Enum_Type)res;
|
||||||
|
r.base_type = clone(r.base_type);
|
||||||
|
r.fields = clone(r.fields);
|
||||||
|
case Bit_Field_Type:
|
||||||
|
r := cast(^Bit_Field_Type)res;
|
||||||
|
r.fields = clone(r.fields);
|
||||||
|
case Bit_Set_Type:
|
||||||
|
r := cast(^Bit_Set_Type)res;
|
||||||
|
r.elem = clone(r.elem);
|
||||||
|
r.underlying = clone(r.underlying);
|
||||||
|
case Map_Type:
|
||||||
|
r := cast(^Map_Type)res;
|
||||||
|
r.key = clone(r.key);
|
||||||
|
r.value = clone(r.value);
|
||||||
|
|
||||||
|
case:
|
||||||
|
fmt.panicf("Unhandled node kind: %T", n);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package odin_ast
|
||||||
|
|
||||||
|
import "core:odin/token"
|
||||||
|
|
||||||
|
Package_Kind :: enum {
|
||||||
|
Normal,
|
||||||
|
Runtime,
|
||||||
|
Init,
|
||||||
|
}
|
||||||
|
|
||||||
|
Package :: struct {
|
||||||
|
kind: Package_Kind,
|
||||||
|
id: int,
|
||||||
|
name: string,
|
||||||
|
fullpath: string,
|
||||||
|
files: []^File,
|
||||||
|
|
||||||
|
user_data: rawptr,
|
||||||
|
}
|
||||||
|
|
||||||
|
File :: struct {
|
||||||
|
id: int,
|
||||||
|
pkg: ^Package,
|
||||||
|
|
||||||
|
fullpath: string,
|
||||||
|
src: []byte,
|
||||||
|
|
||||||
|
pkg_decl: ^Package_Decl,
|
||||||
|
pkg_token: token.Token,
|
||||||
|
pkg_name: string,
|
||||||
|
|
||||||
|
decls: [dynamic]^Stmt,
|
||||||
|
imports: [dynamic]^Import_Decl,
|
||||||
|
directive_count: int,
|
||||||
|
|
||||||
|
comments: [dynamic]^Comment_Group,
|
||||||
|
|
||||||
|
syntax_warning_count: int,
|
||||||
|
syntax_error_count: int,
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user