Files
ww/ref/harec/include/expr.h
Hojun-Cho 8e3752f5ea ref: vendor harec checker sources (#20)
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.
2026-05-21 23:03:11 +09:00

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