hare::ast
hare::ast provides an abstract syntax tree for Hare code.
Index
Types
type _null = void;
type _type = struct {
start: lex::location,
end: lex::location,
flags: type_flag,
repr: (alias_type | builtin_type | enum_type | func_type | list_type | pointer_type | struct_type | union_type | tagged_type | tuple_type),
};
type access_expr = (access_identifier | access_index | access_field | access_tuple);
type access_field = struct {
object: *expr,
field: str,
};
type access_identifier = ident;
type access_index = struct {
object: *expr,
index: *expr,
};
type access_tuple = struct {
object: *expr,
value: *expr,
};
type alias_type = struct {
unwrap: bool,
ident: ident,
};
type align_expr = *_type;
type alloc_expr = struct {
init: *expr,
form: alloc_form,
capacity: nullable *expr,
};
type alloc_form = enum {
OBJECT,
COPY,
};
type append_expr = struct {
object: *expr,
value: *expr,
length: nullable *expr,
variadic: bool,
is_static: bool,
};
type array_literal = struct {
expand: bool,
values: []*expr,
};
type assert_expr = struct {
cond: nullable *expr,
message: nullable *expr,
is_static: bool,
};
type assign_expr = struct {
op: (binarithm_op | void),
object: *expr,
value: *expr,
};
type binarithm_expr = struct {
op: binarithm_op,
lvalue: *expr,
rvalue: *expr,
};
type binarithm_op = enum {
BAND, BOR, DIV, GT, GTEQ, LAND, LEQUAL, LESS, LESSEQ, LOR, LSHIFT, LXOR, MINUS, MODULO, NEQUAL, PLUS, RSHIFT, TIMES, BXOR, };
type binding = struct {
name: (str | binding_unpack),
_type: nullable *_type,
init: *expr,
};
type binding_expr = struct {
is_static: bool,
kind: binding_kind,
bindings: []binding,
};
type binding_kind = enum {
CONST,
DEF,
LET,
};
type binding_unpack = [](str | void);
type break_expr = label;
type builtin_type = enum {
BOOL,
DONE,
F32,
F64,
FCONST,
I16,
I32,
I64,
I8,
ICONST,
INT,
NEVER,
NULL,
OPAQUE,
RCONST,
RUNE,
SIZE,
STR,
U16,
U32,
U64,
U8,
UINT,
UINTPTR,
VALIST,
VOID,
};
type call_expr = struct {
lvalue: *expr,
variadic: bool,
args: []*expr,
};
type cast_expr = struct {
kind: cast_kind,
value: *expr,
_type: *_type,
};
type cast_kind = enum {
CAST,
ASSERTION,
TEST,
};
type compound_expr = struct {
exprs: []*expr,
label: label,
};
type continue_expr = label;
type decl = struct {
exported: bool,
start: lex::location,
end: lex::location,
decl: ([]decl_const | []decl_global | []decl_type | decl_func | assert_expr),
docs: str,
};
type decl_const = struct {
ident: ident,
_type: nullable *_type,
init: *expr,
};
type decl_func = struct {
symbol: str,
ident: ident,
prototype: *_type,
body: nullable *expr,
attrs: fndecl_attr,
};
type decl_global = struct {
is_const: bool,
is_threadlocal: bool,
symbol: str,
ident: ident,
_type: nullable *_type,
init: nullable *expr,
};
type decl_type = struct {
ident: ident,
_type: *_type,
};
type defer_expr = *expr;
type delete_expr = struct {
object: *expr,
is_static: bool,
};
type enum_field = struct {
name: str,
value: nullable *expr,
loc: lex::location,
docs: str,
};
type enum_type = struct {
storage: builtin_type,
values: []enum_field,
};
type error_assert_expr = *expr;
type expr = struct {
start: lex::location,
end: lex::location,
expr: (access_expr | align_expr | alloc_expr | append_expr | assert_expr | assign_expr | binarithm_expr | binding_expr | break_expr | call_expr | cast_expr | literal_expr | continue_expr | defer_expr | delete_expr | for_expr | free_expr | error_assert_expr | if_expr | insert_expr | compound_expr | match_expr | len_expr | size_expr | offset_expr | propagate_expr | return_expr | slice_expr | switch_expr | unarithm_expr | variadic_expr | yield_expr),
};
type fndecl_attr = enum {
NONE,
FINI,
INIT,
TEST,
};
type for_expr = struct {
kind: for_kind,
bindings: nullable *expr,
cond: nullable *expr,
afterthought: nullable *expr,
body: *expr,
label: label,
};
type for_kind = enum {
ACCUMULATOR,
EACH_VALUE,
EACH_POINTER,
ITERATOR,
};
type free_expr = *expr;
type func_param = struct {
loc: lex::location,
name: str,
_type: *_type,
default_value: (void | expr),
};
type func_type = struct {
result: *_type,
variadism: variadism,
params: []func_param,
};
type ident = []str;
type if_expr = struct {
cond: *expr,
tbranch: *expr,
fbranch: nullable *expr,
};
type import = struct {
start: lex::location,
end: lex::location,
ident: ident,
bindings: (void | import_alias | import_members | import_wildcard),
};
type import_alias = str;
type import_members = []str;
type import_wildcard = void;
type insert_expr = append_expr;
type label = str;
type len_contextual = void;
type len_expr = *expr;
type len_slice = void;
type len_unbounded = void;
type list_type = struct {
length: (*expr | len_slice | len_unbounded | len_contextual),
members: *_type,
};
type literal_expr = (value | array_literal | number_literal | struct_literal | tuple_literal);
type match_case = struct {
name: str,
_type: nullable *_type,
exprs: []*expr,
};
type match_expr = struct {
value: *expr,
cases: []match_case,
label: label,
};
type number_literal = struct {
suff: lex::ltok,
value: (i64 | u64 | f64),
sign: bool,
};
type offset_expr = *expr;
type pointer_flag = enum uint {
NONE = 0,
NULLABLE = 1 << 0,
};
type pointer_type = struct {
referent: *_type,
flags: pointer_flag,
};
type propagate_expr = *expr;
type return_expr = nullable *expr;
type size_expr = *_type;
type slice_expr = struct {
object: *expr,
start: nullable *expr,
end: nullable *expr,
};
type struct_alias = ident;
type struct_embedded = *_type;
type struct_field = struct {
name: str,
_type: *_type,
};
type struct_literal = struct {
autofill: bool,
alias: ident,
fields: [](struct_value | *struct_literal),
};
type struct_member = struct {
_offset: nullable *expr,
member: (struct_field | struct_embedded | struct_alias),
docs: str,
};
type struct_type = struct {
packed: bool,
members: []struct_member,
};
type struct_value = struct {
name: str,
_type: nullable *_type,
init: *expr,
};
type subunit = struct {
imports: []import,
decls: []decl,
};
type switch_case = struct {
options: []*expr,
exprs: []*expr,
};
type switch_expr = struct {
value: *expr,
cases: []switch_case,
label: label,
};
type tagged_type = []*_type;
type tuple_literal = []*expr;
type tuple_type = []*_type;
type type_flag = enum uint {
NONE = 0,
CONST = 1 << 0,
ERROR = 1 << 1,
};
type unarithm_expr = struct {
op: unarithm_op,
operand: *expr,
};
type unarithm_op = enum {
ADDR, BNOT, DEREF, LNOT, MINUS, };
type union_type = []struct_member;
type vaarg_expr = struct {
ap: *expr,
_type: *_type,
};
type vaend_expr = *expr;
type value = (bool | done | _null | str | rune | void);
type variadic_expr = (vastart_expr | vaarg_expr | vaend_expr);
type variadism = enum {
NONE,
C,
HARE,
};
type vastart_expr = void;
type yield_expr = struct {
label: label,
value: nullable *expr,
};
type struct_union_type = (struct_type | union_type);
Constants
def IDENT_MAX: size = 255;
Functions
fn decl_finish(d: decl) void;
fn expr_finish(e: nullable *expr) void;
fn ident_dup(id: ident) ident;
fn ident_eq(a: ident, b: ident) bool;
fn ident_free(ident: ident) void;
fn import_finish(import: import) void;
fn imports_finish(imports: []import) void;
fn subunit_finish(u: subunit) void;
fn type_finish(t: nullable *_type) void;
Types
type _null
type _null = void;
The value "null".
type _type
type _type = struct {
start: lex::location,
end: lex::location,
flags: type_flag,
repr: (alias_type | builtin_type | enum_type | func_type | list_type | pointer_type | struct_type | union_type | tagged_type | tuple_type),
};
A Hare type.
type access_expr
type access_expr = (access_identifier | access_index | access_field | access_tuple);
An access expression.
type access_field
type access_field = struct {
object: *expr,
field: str,
};
A struct field access expression.
foo.bar
type access_identifier
type access_identifier = ident;
An identifier access expression.
foo
type access_index
type access_index = struct {
object: *expr,
index: *expr,
};
An index access expression.
foo[0]
type access_tuple
type access_tuple = struct {
object: *expr,
value: *expr,
};
A tuple field access expression.
foo.1
type alias_type
type alias_type = struct {
unwrap: bool,
ident: ident,
};
A type alias.
type align_expr
type align_expr = *_type;
An align expression.
align(int)
type alloc_expr
type alloc_expr = struct {
init: *expr,
form: alloc_form,
capacity: nullable *expr,
};
An allocation expression.
alloc(foo)
alloc(foo...)
alloc(foo, bar)
type alloc_form = enum {
OBJECT,
COPY,
};
The form of an allocation expression.
alloc(foo) // OBJECT
alloc(foo...) // COPY
type append_expr
type append_expr = struct {
object: *expr,
value: *expr,
length: nullable *expr,
variadic: bool,
is_static: bool,
};
An append expression.
append(foo, bar);
append(foo, bar...);
append(foo, [0...], bar);
type array_literal
type array_literal = struct {
expand: bool,
values: []*expr,
};
An array literal.
[foo, bar, ...]
type assert_expr
type assert_expr = struct {
cond: nullable *expr,
message: nullable *expr,
is_static: bool,
};
An assertion expression.
assert(foo)
assert(foo, "error")
abort()
abort("error")
type assign_expr
type assign_expr = struct {
op: (binarithm_op | void),
object: *expr,
value: *expr,
};
An assignment expression.
foo = bar
type binarithm_expr
type binarithm_expr = struct {
op: binarithm_op,
lvalue: *expr,
rvalue: *expr,
};
A binary arithmetic expression.
foo * bar
type binarithm_op
type binarithm_op = enum {
BAND, BOR, DIV, GT, GTEQ, LAND, LEQUAL, LESS, LESSEQ, LOR, LSHIFT, LXOR, MINUS, MODULO, NEQUAL, PLUS, RSHIFT, TIMES, BXOR, };
A binary arithmetic operator
type binding
type binding = struct {
name: (str | binding_unpack),
_type: nullable *_type,
init: *expr,
};
A single variable biding.
foo: int = bar
(foo, foo2): int = bar
type binding_expr
type binding_expr = struct {
is_static: bool,
kind: binding_kind,
bindings: []binding,
};
A variable binding expression.
let foo: int = bar, ...
type binding_kind
type binding_kind = enum {
CONST,
DEF,
LET,
};
The kind of binding expression being used.
type binding_unpack
type binding_unpack = [](str | void);
Tuple unpacking binding.
(foo, _, bar)
type break_expr
type break_expr = label;
A break expression. The label is set to empty string if absent.
break :label
type builtin_type
type builtin_type = enum {
BOOL,
DONE,
F32,
F64,
FCONST,
I16,
I32,
I64,
I8,
ICONST,
INT,
NEVER,
NULL,
OPAQUE,
RCONST,
RUNE,
SIZE,
STR,
U16,
U32,
U64,
U8,
UINT,
UINTPTR,
VALIST,
VOID,
};
A built-in primitive type (int, bool, str, etc).
type call_expr
type call_expr = struct {
lvalue: *expr,
variadic: bool,
args: []*expr,
};
A function call expression.
foo(bar)
type cast_expr
type cast_expr = struct {
kind: cast_kind,
value: *expr,
_type: *_type,
};
A cast expression.
foo: int
foo as int
foo is int
type cast_kind
type cast_kind = enum {
CAST,
ASSERTION,
TEST,
};
The kind of cast expression being used.
type compound_expr
type compound_expr = struct {
exprs: []*expr,
label: label,
};
A compound expression.
{
foo;
bar;
// ...
}
type continue_expr
type continue_expr = label;
A continue expression. The label is set to empty string if absent.
continue :label
type decl
type decl = struct {
exported: bool,
start: lex::location,
end: lex::location,
decl: ([]decl_const | []decl_global | []decl_type | decl_func | assert_expr),
docs: str,
};
A Hare declaration.
type decl_const
type decl_const = struct {
ident: ident,
_type: nullable *_type,
init: *expr,
};
A constant declaration.
def foo: int = 0;
type decl_func
type decl_func = struct {
symbol: str,
ident: ident,
prototype: *_type,
body: nullable *expr,
attrs: fndecl_attr,
};
A function declaration.
fn main() void = void;
type decl_global
type decl_global = struct {
is_const: bool,
is_threadlocal: bool,
symbol: str,
ident: ident,
_type: nullable *_type,
init: nullable *expr,
};
A global declaration.
let foo: int = 0;
const foo: int = 0;
type decl_type
type decl_type = struct {
ident: ident,
_type: *_type,
};
A type declaration.
type foo = int;
type defer_expr
type defer_expr = *expr;
A deferred expression.
defer foo
type delete_expr
type delete_expr = struct {
object: *expr,
is_static: bool,
};
A delete expression.
delete(foo[10])
delete(foo[4..42])
type enum_field
type enum_field = struct {
name: str,
value: nullable *expr,
loc: lex::location,
docs: str,
};
An enumeration field (and optional value).
type enum_type
type enum_type = struct {
storage: builtin_type,
values: []enum_field,
};
enum { FOO = 0, BAR, ... }
type error_assert_expr
type error_assert_expr = *expr;
An error assertion expression.
foo!
type expr
type expr = struct {
start: lex::location,
end: lex::location,
expr: (access_expr | align_expr | alloc_expr | append_expr | assert_expr | assign_expr | binarithm_expr | binding_expr | break_expr | call_expr | cast_expr | literal_expr | continue_expr | defer_expr | delete_expr | for_expr | free_expr | error_assert_expr | if_expr | insert_expr | compound_expr | match_expr | len_expr | size_expr | offset_expr | propagate_expr | return_expr | slice_expr | switch_expr | unarithm_expr | variadic_expr | yield_expr),
};
A Hare expression.
type fndecl_attr
type fndecl_attr = enum {
NONE,
FINI,
INIT,
TEST,
};
Attributes applicable to a function declaration.
type for_expr
type for_expr = struct {
kind: for_kind,
bindings: nullable *expr,
cond: nullable *expr,
afterthought: nullable *expr,
body: *expr,
label: label,
};
A for loop.
for (let foo = 0; foo < bar; baz) quux
for (let line => next_line()) quux
for (let number .. [1, 2, 3]) quux
for (let ptr &.. [1, 2, 3]) quux
type for_kind
type for_kind = enum {
ACCUMULATOR,
EACH_VALUE,
EACH_POINTER,
ITERATOR,
};
The kind of for expression being used.
type free_expr
type free_expr = *expr;
A free expression.
free(foo)
type func_param
type func_param = struct {
loc: lex::location,
name: str,
_type: *_type,
default_value: (void | expr),
};
A parameter to a function type.
type func_type
type func_type = struct {
result: *_type,
variadism: variadism,
params: []func_param,
};
fn(foo: int, baz: int...) int
type ident
type ident = []str;
Identifies a single object, e.g. foo::bar::baz.
type if_expr
type if_expr = struct {
cond: *expr,
tbranch: *expr,
fbranch: nullable *expr,
};
An if or if..else expression.
if (foo) bar else baz
type import
type import = struct {
start: lex::location,
end: lex::location,
ident: ident,
bindings: (void | import_alias | import_members | import_wildcard),
};
An imported module.
use foo;
use foo = bar;
use foo::{bar, baz};
use foo::*;
type import_alias
type import_alias = str;
An import alias.
use foo = bar;
type import_members
type import_members = []str;
An import members list.
use foo::{bar, baz};
type import_wildcard
type import_wildcard = void;
An import wildcard.
use foo::*;
type insert_expr
type insert_expr = append_expr;
An insert expression.
insert(foo[0], bar);
insert(foo[0], bar...);
insert(foo[0], [0...], bar);
type label
type label = str;
:label. The ":" character is not included.
type len_contextual
type len_contextual = void;
The length for a list type which is inferred from context (e.g. [_]int).
type len_expr
type len_expr = *expr;
A length expression.
len(foo)
type len_slice
type len_slice = void;
The length for a list type which is a slice (e.g. []int).
type len_unbounded
type len_unbounded = void;
The length for a list type which is unbounded (e.g. [*]int).
type list_type
type list_type = struct {
length: (*expr | len_slice | len_unbounded | len_contextual),
members: *_type,
};
[]int, [*]int, [_]int, [foo]int
type literal_expr
type literal_expr = (value | array_literal | number_literal | struct_literal | tuple_literal);
A literal expression.
type match_case
type match_case = struct {
name: str,
_type: nullable *_type,
exprs: []*expr,
};
A match case.
case type => exprs
case let name: type => exprs
type match_expr
type match_expr = struct {
value: *expr,
cases: []match_case,
label: label,
};
A match expression.
match (foo) { case int => bar; ... }
type number_literal
type number_literal = struct {
suff: lex::ltok,
value: (i64 | u64 | f64),
sign: bool,
};
An integer or float literal.
type offset_expr
type offset_expr = *expr;
An offset expression.
offset(foo.bar)
type pointer_flag
type pointer_flag = enum uint {
NONE = 0,
NULLABLE = 1 << 0,
};
Flags which apply to a pointer type.
type pointer_type
type pointer_type = struct {
referent: *_type,
flags: pointer_flag,
};
*int
type propagate_expr
type propagate_expr = *expr;
An error propagation expression.
foo?
type return_expr
type return_expr = nullable *expr;
A return statement.
return foo
type size_expr
type size_expr = *_type;
A size expression.
size(int)
type slice_expr
type slice_expr = struct {
object: *expr,
start: nullable *expr,
end: nullable *expr,
};
A slicing expression.
foo[bar..baz]
type struct_alias
type struct_alias = ident;
An embedded type alias.
type struct_embedded
type struct_embedded = *_type;
An embedded struct type.
type struct_field
type struct_field = struct {
name: str,
_type: *_type,
};
A single field of a struct type.
type struct_literal
type struct_literal = struct {
autofill: bool,
alias: ident,
fields: [](struct_value | *struct_literal),
};
A struct literal.
struct { foo: int = bar, struct { baz = quux }, ... }
type struct_member
type struct_member = struct {
_offset: nullable *expr,
member: (struct_field | struct_embedded | struct_alias),
docs: str,
};
struct { @offset(10) foo: int, struct { bar: int }, baz::quux }
type struct_type
type struct_type = struct {
packed: bool,
members: []struct_member,
};
struct { ... }
type struct_value
type struct_value = struct {
name: str,
_type: nullable *_type,
init: *expr,
};
A single struct field and value.
foo: int = 10
type subunit
type subunit = struct {
imports: []import,
decls: []decl,
};
A sub-unit, typically representing a single source file.
type switch_case
type switch_case = struct {
options: []*expr,
exprs: []*expr,
};
A switch case.
case value => exprs
type switch_expr
type switch_expr = struct {
value: *expr,
cases: []switch_case,
label: label,
};
A switch expression.
switch (foo) { case bar => baz; ... }
type tagged_type
type tagged_type = []*_type;
(int | bool)
type tuple_literal
type tuple_literal = []*expr;
A tuple literal.
(foo, bar, ...)
type tuple_type
type tuple_type = []*_type;
(int, bool, ...)
type type_flag
type type_flag = enum uint {
NONE = 0,
CONST = 1 << 0,
ERROR = 1 << 1,
};
Flags which apply to types.
type unarithm_expr
type unarithm_expr = struct {
op: unarithm_op,
operand: *expr,
};
A unary arithmetic expression.
!example
type unarithm_op
type unarithm_op = enum {
ADDR, BNOT, DEREF, LNOT, MINUS, };
A unary operator
type union_type
type union_type = []struct_member;
union { ... }
type vaarg_expr
type vaarg_expr = struct {
ap: *expr,
_type: *_type,
};
A vaarg expression.
vaarg(ap, int)
type vaend_expr
type vaend_expr = *expr;
A vaend expression.
vaend(ap)
type value
type value = (bool | done | _null | str | rune | void);
A scalar value.
type variadic_expr
type variadic_expr = (vastart_expr | vaarg_expr | vaend_expr);
A C-style variadic expression.
type variadism
type variadism = enum {
NONE,
C,
HARE,
};
The variadism strategy for a function type.
type vastart_expr
type vastart_expr = void;
A vastart expression.
vastart()
type yield_expr
type yield_expr = struct {
label: label,
value: nullable *expr,
};
A yield expression.
yield foo
type struct_union_type
Show undocumented member
type struct_union_type = (struct_type | union_type);
Constants
def IDENT_MAX
def IDENT_MAX: size = 255;
Maximum length of an identifier, as the sum of the lengths of its parts plus one for each namespace deliniation.
In other words, the length of "a::b::c" is 5.
Functions
fn decl_finish
fn decl_finish(d: decl) void;
Frees resources associated with a declaration.
fn expr_finish
fn expr_finish(e: nullable *expr) void;
Frees resources associated with a Hare expression.
fn ident_dup
fn ident_dup(id: ident) ident;
Duplicates an ident.
fn ident_eq
fn ident_eq(a: ident, b: ident) bool;
Returns true if two idents are identical.
fn ident_free
fn ident_free(ident: ident) void;
Frees resources associated with an identifier.
fn import_finish
fn import_finish(import: import) void;
Frees resources associated with an import.
fn imports_finish
fn imports_finish(imports: []import) void;
Frees resources associated with each import in a slice, and then frees the slice itself.
fn subunit_finish
fn subunit_finish(u: subunit) void;
Frees resources associated with a subunit.
fn type_finish
fn type_finish(t: nullable *_type) void;
Frees resources associated with a _type.