ref/hare/ ships only ast/lex/parse/module/unparse — no checker. Every bail-fix landing in A.6.2.1 (helper bail audit, N_IDENT bail audit, enum fold) needs a `ref/harec/...` cite anchor so divergence rationale isn't claimed against memory. PLAN.md L16, L35. Snapshot of upstream commit ee640c6b2c17f57e8014d277a3028b262ffb7952 (`rt/+openbsd/start.ha: remove outdated comment about crt0`). 20 files: 5 src (check.c, eval.c, scope.c, types.c, type_store.c), 14 transitive include/ headers (no parser/codegen surface), and COPYING. License GPLv3 (COPYING included). Vendored as read-only reference per CLAUDE.md rule 6 — no redistribution as binary, no edits.
403 lines
7.4 KiB
C
403 lines
7.4 KiB
C
#ifndef HAREC_EXPR_H
|
|
#define HAREC_EXPR_H
|
|
#include <stdint.h>
|
|
#include "lex.h"
|
|
#include "types.h"
|
|
|
|
struct scope;
|
|
struct scope_object;
|
|
|
|
enum expr_type {
|
|
EXPR_ACCESS,
|
|
EXPR_ALLOC,
|
|
EXPR_APPEND,
|
|
EXPR_ASSERT,
|
|
EXPR_ASSIGN,
|
|
EXPR_BINARITHM,
|
|
EXPR_BINDING,
|
|
EXPR_BREAK,
|
|
EXPR_CALL,
|
|
EXPR_CAST,
|
|
EXPR_COMPOUND,
|
|
EXPR_CONTINUE,
|
|
EXPR_DEFER,
|
|
EXPR_DEFINE,
|
|
EXPR_DELETE,
|
|
EXPR_FOR,
|
|
EXPR_FREE,
|
|
EXPR_IF,
|
|
EXPR_INSERT,
|
|
EXPR_LEN,
|
|
EXPR_MEASURE = EXPR_LEN, // for use in AST
|
|
EXPR_LITERAL,
|
|
EXPR_MATCH,
|
|
EXPR_PROPAGATE,
|
|
EXPR_RETURN,
|
|
EXPR_SLICE,
|
|
EXPR_STRUCT,
|
|
EXPR_SWITCH,
|
|
EXPR_TUPLE,
|
|
EXPR_UNARITHM,
|
|
EXPR_UNDEFINED,
|
|
EXPR_VAARG,
|
|
EXPR_VAEND,
|
|
EXPR_VASTART,
|
|
EXPR_YIELD,
|
|
};
|
|
|
|
struct expressions {
|
|
struct expression *expr;
|
|
struct expressions *next;
|
|
};
|
|
|
|
enum access_type {
|
|
ACCESS_IDENTIFIER,
|
|
ACCESS_INDEX,
|
|
ACCESS_FIELD,
|
|
ACCESS_TUPLE,
|
|
};
|
|
|
|
struct expression_access {
|
|
enum access_type type;
|
|
union {
|
|
struct scope_object *object;
|
|
struct {
|
|
struct expression *array;
|
|
struct expression *index;
|
|
bool bounds_checked;
|
|
};
|
|
struct {
|
|
struct expression *_struct;
|
|
const struct struct_field *field;
|
|
};
|
|
struct {
|
|
struct expression *tuple;
|
|
const struct type_tuple *tvalue;
|
|
size_t tindex;
|
|
};
|
|
};
|
|
};
|
|
|
|
enum alloc_kind {
|
|
ALLOC_OBJECT, // alloc(42)
|
|
ALLOC_CAP, // alloc([], 42)
|
|
ALLOC_LEN, // alloc([0...], 42)
|
|
ALLOC_COPY, // alloc(x...);
|
|
};
|
|
|
|
struct expression_alloc {
|
|
enum alloc_kind kind;
|
|
const struct type *allocation_result;
|
|
struct expression *init;
|
|
struct expression *cap;
|
|
};
|
|
|
|
struct expression_append {
|
|
struct expression *object;
|
|
struct expression *value;
|
|
struct expression *length;
|
|
bool is_static, is_multi;
|
|
};
|
|
|
|
enum fixed_aborts {
|
|
ABORT_OOB = 0,
|
|
ABORT_TYPE_ASSERTION = 1,
|
|
ABORT_UNREACHABLE = 2,
|
|
ABORT_CAP_TOO_SMALL = 3,
|
|
ABORT_ANON_ASSERTION_FAILED = 4,
|
|
ABORT_PROPAGATE_ERROR_OCCURRED = 5,
|
|
};
|
|
|
|
struct expression_assert {
|
|
struct expression *cond;
|
|
struct expression *message;
|
|
enum fixed_aborts fixed_reason;
|
|
};
|
|
|
|
enum binarithm_operator {
|
|
BIN_BAND, // &
|
|
BIN_BOR, // |
|
|
BIN_DIV, // /
|
|
BIN_GREATER, // >
|
|
BIN_GREATEREQ, // >=
|
|
BIN_LAND, // &&
|
|
BIN_LEQUAL, // ==
|
|
BIN_LESS, // <
|
|
BIN_LESSEQ, // <=
|
|
BIN_LOR, // ||
|
|
BIN_LSHIFT, // <<
|
|
BIN_LXOR, // ^^
|
|
BIN_MINUS, // -
|
|
BIN_MODULO, // %
|
|
BIN_NEQUAL, // !=
|
|
BIN_PLUS, // +
|
|
BIN_RSHIFT, // >>
|
|
BIN_TIMES, // *
|
|
BIN_BXOR, // ^
|
|
BIN_LAST = BIN_BXOR,
|
|
};
|
|
|
|
struct expression_assign {
|
|
enum binarithm_operator op;
|
|
struct expression *object, *value;
|
|
};
|
|
|
|
struct expression_binarithm {
|
|
enum binarithm_operator op;
|
|
struct expression *lvalue, *rvalue;
|
|
};
|
|
|
|
struct binding_unpack {
|
|
const struct scope_object *object;
|
|
size_t offset;
|
|
struct binding_unpack *next;
|
|
};
|
|
|
|
struct expression_binding {
|
|
const struct scope_object *object;
|
|
struct binding_unpack *unpack;
|
|
struct expression *initializer;
|
|
struct expression_binding *next;
|
|
};
|
|
|
|
enum cast_kind {
|
|
C_CAST,
|
|
C_ASSERTION,
|
|
C_TEST,
|
|
};
|
|
|
|
struct expression_cast {
|
|
enum cast_kind kind;
|
|
const struct type *secondary;
|
|
struct expression *value;
|
|
bool lowered;
|
|
};
|
|
|
|
struct call_argument {
|
|
struct expression *value;
|
|
struct call_argument *next;
|
|
};
|
|
|
|
struct expression_call {
|
|
struct expression *lvalue;
|
|
struct call_argument *args;
|
|
};
|
|
|
|
struct expression_compound {
|
|
const char *label;
|
|
struct scope *scope;
|
|
struct expressions exprs;
|
|
};
|
|
|
|
struct array_literal {
|
|
struct expression *value;
|
|
struct array_literal *next;
|
|
};
|
|
|
|
// Invariant: these are sorted by field offset
|
|
struct struct_literal {
|
|
const struct struct_field *field;
|
|
struct expression *value;
|
|
struct struct_literal *next;
|
|
};
|
|
|
|
struct tuple_literal {
|
|
const struct type_tuple *field;
|
|
struct expression *value;
|
|
struct tuple_literal *next;
|
|
};
|
|
|
|
struct tagged_literal {
|
|
const struct type *tag;
|
|
struct expression *value;
|
|
};
|
|
|
|
struct expression_literal {
|
|
// If non-null, ival is an offset from this object's address
|
|
const struct scope_object *object;
|
|
union {
|
|
bool bval;
|
|
double fval;
|
|
int64_t ival;
|
|
uint64_t uval;
|
|
uint32_t rune;
|
|
struct {
|
|
size_t len;
|
|
char *value;
|
|
} string;
|
|
struct {
|
|
union {
|
|
// if object is null
|
|
struct array_literal *array;
|
|
// if object is non-null
|
|
size_t offset;
|
|
};
|
|
size_t start;
|
|
size_t len;
|
|
size_t cap;
|
|
} slice;
|
|
struct array_literal *array;
|
|
struct struct_literal *_struct;
|
|
struct tuple_literal *tuple;
|
|
struct tagged_literal tagged;
|
|
};
|
|
};
|
|
|
|
struct expression_control {
|
|
const char *label;
|
|
const struct scope *scope;
|
|
struct expression *value; // Only set for yield and break
|
|
};
|
|
|
|
struct expression_defer {
|
|
struct scope *scope;
|
|
struct expression *deferred;
|
|
};
|
|
|
|
struct expression_delete {
|
|
struct expression *expr;
|
|
bool is_static;
|
|
};
|
|
|
|
enum for_kind {
|
|
FOR_ACCUMULATOR,
|
|
FOR_EACH_VALUE,
|
|
FOR_EACH_POINTER,
|
|
FOR_EACH_ITERATOR,
|
|
};
|
|
|
|
struct expression_for {
|
|
enum for_kind kind;
|
|
const char *label;
|
|
struct scope *scope;
|
|
struct expression *bindings;
|
|
struct expression *cond;
|
|
struct expression *afterthought;
|
|
struct expression *body;
|
|
struct expression *else_branch;
|
|
};
|
|
|
|
struct expression_free {
|
|
struct expression *expr;
|
|
};
|
|
|
|
struct expression_if {
|
|
struct expression *cond;
|
|
struct expression *true_branch, *false_branch;
|
|
};
|
|
|
|
struct match_case {
|
|
const struct scope_object *object; // NULL if not bound
|
|
const struct type *type; // NULL if default
|
|
struct expression *value;
|
|
struct match_case *next;
|
|
};
|
|
|
|
struct expression_len {
|
|
struct expression *value;
|
|
};
|
|
|
|
struct expression_match {
|
|
struct expression *value;
|
|
struct match_case *cases;
|
|
};
|
|
|
|
struct expression_return {
|
|
struct expression *value;
|
|
};
|
|
|
|
struct expression_slice {
|
|
struct expression *object;
|
|
struct expression *start, *end;
|
|
bool bounds_checked;
|
|
};
|
|
|
|
struct case_option {
|
|
struct expression *value;
|
|
struct case_option *next;
|
|
};
|
|
|
|
struct switch_case {
|
|
struct case_option *options; // NULL for default case
|
|
struct expression *value;
|
|
struct switch_case *next;
|
|
};
|
|
|
|
struct expression_switch {
|
|
struct expression *value;
|
|
struct switch_case *cases;
|
|
};
|
|
|
|
struct expr_struct_field {
|
|
const struct struct_field *field;
|
|
struct expression *value;
|
|
struct expr_struct_field *next;
|
|
};
|
|
|
|
struct expression_struct {
|
|
struct expr_struct_field *fields;
|
|
bool autofill, undefined;
|
|
};
|
|
|
|
struct expression_tuple {
|
|
struct expression *value;
|
|
struct expression_tuple *next;
|
|
};
|
|
|
|
enum unarithm_operator {
|
|
UN_ADDRESS, // &
|
|
UN_BNOT, // ~
|
|
UN_DEREF, // *
|
|
UN_LNOT, // !
|
|
UN_MINUS, // -
|
|
};
|
|
|
|
struct expression_unarithm {
|
|
enum unarithm_operator op;
|
|
struct expression *operand;
|
|
};
|
|
|
|
struct expression_vaarg {
|
|
struct expression *ap;
|
|
};
|
|
|
|
struct expression {
|
|
const struct type *result;
|
|
enum expr_type type;
|
|
struct location loc; // For fixed aborts
|
|
union {
|
|
struct expression_access access;
|
|
struct expression_alloc alloc;
|
|
struct expression_append append; // and insert
|
|
struct expression_assert assert;
|
|
struct expression_assign assign;
|
|
struct expression_binarithm binarithm;
|
|
struct expression_binding binding;
|
|
struct expression_call call;
|
|
struct expression_cast cast;
|
|
struct expression_compound compound;
|
|
struct expression_defer defer;
|
|
struct expression_delete delete;
|
|
struct expression_control control;
|
|
struct expression_for _for;
|
|
struct expression_free free;
|
|
struct expression_if _if;
|
|
struct expression_len len;
|
|
struct expression_literal literal;
|
|
struct expression_match match;
|
|
struct expression_return _return;
|
|
struct expression_switch _switch;
|
|
struct expression_struct _struct;
|
|
struct expression_slice slice;
|
|
struct expression_tuple tuple;
|
|
struct expression_unarithm unarithm;
|
|
struct expression_vaarg vaarg;
|
|
void *user;
|
|
};
|
|
};
|
|
|
|
uint32_t expr_hash(const struct expression *expr);
|
|
bool expr_equal(const struct expression *a, const struct expression *b);
|
|
|
|
#endif
|