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.
This commit is contained in:
11
ref/harec/include/arch.h
Normal file
11
ref/harec/include/arch.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef HAREC_ARCH_H
|
||||
#define HAREC_ARCH_H
|
||||
|
||||
enum arch {
|
||||
AARCH64,
|
||||
PPC64LE,
|
||||
RISCV64,
|
||||
X86_64,
|
||||
};
|
||||
|
||||
#endif
|
||||
444
ref/harec/include/ast.h
Normal file
444
ref/harec/include/ast.h
Normal file
@@ -0,0 +1,444 @@
|
||||
#ifndef HARE_AST_H
|
||||
#define HARE_AST_H
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "expr.h"
|
||||
#include "identifier.h"
|
||||
#include "lex.h"
|
||||
#include "types.h"
|
||||
|
||||
struct ast_type;
|
||||
|
||||
enum ast_import_mode {
|
||||
IMPORT_NORMAL, // use foo::bar;
|
||||
IMPORT_ALIAS, // use foo = bar::baz;
|
||||
IMPORT_MEMBERS, // use foo::{bar, baz};
|
||||
IMPORT_WILDCARD, // use foo::bar::*;
|
||||
};
|
||||
|
||||
struct ast_import_members {
|
||||
struct location loc;
|
||||
struct ident *name;
|
||||
struct ast_import_members *next;
|
||||
};
|
||||
|
||||
struct ast_imports {
|
||||
enum ast_import_mode mode;
|
||||
struct ident *ident;
|
||||
union {
|
||||
const char *alias;
|
||||
struct ast_import_members *members;
|
||||
};
|
||||
struct ast_imports *next;
|
||||
};
|
||||
|
||||
struct ast_array_type {
|
||||
struct ast_expression *length; // NULL for unbounded arrays
|
||||
struct ast_type *members;
|
||||
bool contextual;
|
||||
};
|
||||
|
||||
struct ast_slice_type {
|
||||
struct ast_type *members;
|
||||
};
|
||||
|
||||
struct ast_enum_field {
|
||||
struct location loc;
|
||||
struct ident *name;
|
||||
struct ast_expression *value;
|
||||
struct ast_enum_field *next;
|
||||
};
|
||||
|
||||
struct ast_enum_type {
|
||||
enum type_storage storage;
|
||||
struct ast_enum_field *values;
|
||||
};
|
||||
|
||||
struct ast_function_parameters {
|
||||
struct location loc;
|
||||
struct ident *name;
|
||||
struct ast_type *type;
|
||||
struct ast_expression *default_value;
|
||||
struct ast_function_parameters *next;
|
||||
};
|
||||
|
||||
struct ast_function_type {
|
||||
struct ast_type *result;
|
||||
struct ast_function_parameters *params;
|
||||
enum variadism variadism;
|
||||
};
|
||||
|
||||
struct ast_pointer_type {
|
||||
struct ast_type *referent;
|
||||
bool nullable;
|
||||
};
|
||||
|
||||
struct ast_tagged_union_type {
|
||||
struct ast_type *type;
|
||||
bool unwrap;
|
||||
struct ast_tagged_union_type *next;
|
||||
};
|
||||
|
||||
struct ast_tuple_type {
|
||||
struct ast_type *type;
|
||||
struct ast_tuple_type *next;
|
||||
};
|
||||
|
||||
struct ast_struct_union_field {
|
||||
struct ast_struct_union_field *next;
|
||||
const char *name; // null if embed, may be "_"
|
||||
struct ast_type *type;
|
||||
};
|
||||
|
||||
struct ast_struct_union_type {
|
||||
struct ast_struct_union_field fields;
|
||||
bool packed;
|
||||
};
|
||||
|
||||
struct ast_type {
|
||||
struct location loc;
|
||||
enum type_storage storage;
|
||||
union {
|
||||
struct ast_array_type array;
|
||||
struct ast_type *error;
|
||||
struct ast_function_type func;
|
||||
struct ast_pointer_type pointer;
|
||||
struct ast_slice_type slice;
|
||||
struct ast_struct_union_type struct_union;
|
||||
struct ast_tagged_union_type tagged;
|
||||
struct ast_tuple_type tuple;
|
||||
struct {
|
||||
struct ident *alias;
|
||||
// Only valid for enums
|
||||
struct ast_enum_type _enum;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
struct ast_types {
|
||||
const struct ast_type *type;
|
||||
struct ast_types *next;
|
||||
};
|
||||
|
||||
struct ast_expression_list {
|
||||
struct ast_expression *expr;
|
||||
struct ast_expression_list *next;
|
||||
};
|
||||
|
||||
struct ast_expression_access {
|
||||
enum access_type type;
|
||||
union {
|
||||
struct ident *ident;
|
||||
struct {
|
||||
struct ast_expression *array;
|
||||
struct ast_expression *index;
|
||||
};
|
||||
struct {
|
||||
struct ast_expression *_struct;
|
||||
const char *field;
|
||||
};
|
||||
struct {
|
||||
struct ast_expression *tuple;
|
||||
struct ast_expression *value;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
struct ast_expression_alloc {
|
||||
enum alloc_kind kind;
|
||||
struct ast_expression *init;
|
||||
struct ast_expression *cap;
|
||||
};
|
||||
|
||||
struct ast_expression_append {
|
||||
struct ast_expression *object;
|
||||
struct ast_expression *value;
|
||||
struct ast_expression *length;
|
||||
bool is_static, is_multi;
|
||||
};
|
||||
|
||||
struct ast_expression_assert {
|
||||
struct ast_expression *cond;
|
||||
struct ast_expression *message;
|
||||
bool is_static;
|
||||
};
|
||||
|
||||
struct ast_expression_assign {
|
||||
enum binarithm_operator op;
|
||||
// object == NULL for discarding assignment (`_ = foo`)
|
||||
struct ast_expression *object, *value;
|
||||
};
|
||||
|
||||
struct ast_expression_binarithm {
|
||||
enum binarithm_operator op;
|
||||
struct ast_expression *lvalue, *rvalue;
|
||||
};
|
||||
|
||||
struct ast_binding_names {
|
||||
struct ident *name; // NULL for _
|
||||
struct ast_binding_names *next;
|
||||
};
|
||||
|
||||
struct ast_expression_binding {
|
||||
// more than one name means tuple unpacking,
|
||||
// otherwise it's a regular binding
|
||||
struct ast_binding_names names;
|
||||
struct ast_type *type;
|
||||
bool is_static;
|
||||
struct ast_expression *initializer;
|
||||
struct ast_expression_binding *next;
|
||||
};
|
||||
|
||||
struct ast_expression_call {
|
||||
struct ast_expression *lvalue;
|
||||
struct ast_expression_list *args;
|
||||
bool variadic; // last argument is a variadic argument list
|
||||
};
|
||||
|
||||
struct ast_expression_cast {
|
||||
enum cast_kind kind;
|
||||
struct ast_expression *value;
|
||||
struct ast_type *type;
|
||||
};
|
||||
|
||||
struct ast_expression_literal {
|
||||
enum type_storage storage;
|
||||
union {
|
||||
int64_t ival;
|
||||
uint64_t uval;
|
||||
double fval;
|
||||
uint32_t rune;
|
||||
bool bval;
|
||||
struct {
|
||||
size_t len;
|
||||
char *value;
|
||||
} string;
|
||||
struct {
|
||||
struct ast_expression_list *exprs;
|
||||
bool expand;
|
||||
} array;
|
||||
};
|
||||
};
|
||||
|
||||
struct ast_expression_control {
|
||||
const char *label; // Never set for return.
|
||||
struct ast_expression *value; // Never set for continue
|
||||
};
|
||||
|
||||
struct ast_expression_defer {
|
||||
struct ast_expression *deferred;
|
||||
};
|
||||
|
||||
struct ast_expression_delete {
|
||||
struct ast_expression *expr;
|
||||
bool is_static;
|
||||
};
|
||||
|
||||
struct ast_expression_for {
|
||||
enum for_kind kind;
|
||||
const char *label;
|
||||
struct ast_expression *bindings;
|
||||
struct ast_expression *cond;
|
||||
struct ast_expression *afterthought;
|
||||
struct ast_expression *body;
|
||||
struct ast_expression *else_branch;
|
||||
};
|
||||
|
||||
struct ast_expression_free {
|
||||
struct ast_expression *expr;
|
||||
};
|
||||
|
||||
struct ast_expression_if {
|
||||
struct ast_expression *cond;
|
||||
struct ast_expression *true_branch, *false_branch;
|
||||
};
|
||||
|
||||
struct ast_expression_compound {
|
||||
const char *label;
|
||||
struct location label_loc;
|
||||
struct ast_expression_list list;
|
||||
};
|
||||
|
||||
struct ast_match_case {
|
||||
struct ident *name; // May be null
|
||||
struct ast_type *type;
|
||||
struct ast_expression_list exprs;
|
||||
struct ast_match_case *next;
|
||||
};
|
||||
|
||||
struct ast_expression_match {
|
||||
const char *label;
|
||||
struct ast_expression *value;
|
||||
struct ast_match_case *cases;
|
||||
};
|
||||
|
||||
enum measure_operator {
|
||||
M_ALIGN,
|
||||
M_LEN,
|
||||
M_SIZE,
|
||||
M_OFFSET,
|
||||
};
|
||||
|
||||
struct ast_expression_measure {
|
||||
enum measure_operator op;
|
||||
union {
|
||||
struct ast_expression *value;
|
||||
struct ast_type *type;
|
||||
// TODO: Field selection
|
||||
};
|
||||
};
|
||||
|
||||
struct ast_expression_propagate {
|
||||
struct ast_expression *value;
|
||||
bool abort;
|
||||
};
|
||||
|
||||
struct ast_expression_slice {
|
||||
struct ast_expression *object;
|
||||
struct ast_expression *start, *end;
|
||||
};
|
||||
|
||||
struct ast_case_option {
|
||||
struct ast_expression *value;
|
||||
struct ast_case_option *next;
|
||||
};
|
||||
|
||||
struct ast_switch_case {
|
||||
struct ast_case_option *options; // NULL for *
|
||||
struct ast_expression_list exprs;
|
||||
struct ast_switch_case *next;
|
||||
};
|
||||
|
||||
struct ast_expression_switch {
|
||||
const char *label;
|
||||
struct ast_expression *value;
|
||||
struct ast_switch_case *cases;
|
||||
};
|
||||
|
||||
struct ast_field_value {
|
||||
const char *name;
|
||||
struct ast_type *type;
|
||||
struct ast_expression *initializer;
|
||||
struct ast_field_value *next;
|
||||
};
|
||||
|
||||
struct ast_expression_struct {
|
||||
bool autofill;
|
||||
bool undefined;
|
||||
struct ident *type;
|
||||
struct ast_field_value *fields;
|
||||
};
|
||||
|
||||
struct ast_expression_tuple {
|
||||
struct ast_expression *expr;
|
||||
struct ast_expression_tuple *next;
|
||||
};
|
||||
|
||||
struct ast_expression_unarithm {
|
||||
enum unarithm_operator op;
|
||||
struct ast_expression *operand;
|
||||
};
|
||||
|
||||
struct ast_expression_vaarg {
|
||||
struct ast_expression *ap;
|
||||
struct ast_type *type;
|
||||
};
|
||||
|
||||
struct ast_expression {
|
||||
struct location loc;
|
||||
enum expr_type type;
|
||||
union {
|
||||
struct ast_expression_access access;
|
||||
struct ast_expression_alloc alloc;
|
||||
struct ast_expression_append append; // also insert
|
||||
struct ast_expression_assert assert;
|
||||
struct ast_expression_assign assign;
|
||||
struct ast_expression_binarithm binarithm;
|
||||
struct ast_expression_binding binding;
|
||||
struct ast_expression_call call;
|
||||
struct ast_expression_cast cast;
|
||||
struct ast_expression_compound compound;
|
||||
struct ast_expression_control control;
|
||||
struct ast_expression_defer defer;
|
||||
struct ast_expression_delete delete;
|
||||
struct ast_expression_for _for;
|
||||
struct ast_expression_free free;
|
||||
struct ast_expression_if _if;
|
||||
struct ast_expression_literal literal;
|
||||
struct ast_expression_match match;
|
||||
struct ast_expression_measure measure;
|
||||
struct ast_expression_propagate propagate;
|
||||
struct ast_expression_slice slice;
|
||||
struct ast_expression_struct _struct;
|
||||
struct ast_expression_switch _switch;
|
||||
struct ast_expression_tuple tuple;
|
||||
struct ast_expression_unarithm unarithm;
|
||||
struct ast_expression_vaarg vaarg;
|
||||
};
|
||||
};
|
||||
|
||||
struct ast_global_decl {
|
||||
const char *symbol;
|
||||
bool threadlocal;
|
||||
struct ident *ident;
|
||||
struct ast_type *type;
|
||||
struct ast_expression *init;
|
||||
};
|
||||
|
||||
struct ast_type_decl {
|
||||
struct ident *ident;
|
||||
struct ast_type *type;
|
||||
};
|
||||
|
||||
enum func_decl_flags {
|
||||
FN_FINI = 1 << 0,
|
||||
FN_INIT = 1 << 1,
|
||||
FN_TEST = 1 << 2,
|
||||
};
|
||||
|
||||
struct ast_function_decl {
|
||||
const char *symbol;
|
||||
struct ident *ident;
|
||||
struct ast_function_type prototype;
|
||||
struct ast_expression *body;
|
||||
enum func_decl_flags flags;
|
||||
};
|
||||
|
||||
enum ast_decl_type {
|
||||
ADECL_FUNC,
|
||||
ADECL_TYPE,
|
||||
ADECL_GLOBAL,
|
||||
ADECL_CONST,
|
||||
ADECL_ASSERT,
|
||||
};
|
||||
|
||||
struct ast_decl {
|
||||
struct location loc;
|
||||
enum ast_decl_type decl_type;
|
||||
bool exported;
|
||||
union {
|
||||
struct ast_global_decl global;
|
||||
struct ast_global_decl constant;
|
||||
struct ast_type_decl type;
|
||||
struct ast_function_decl function;
|
||||
struct ast_expression_assert assert;
|
||||
};
|
||||
};
|
||||
|
||||
struct ast_decls {
|
||||
struct ast_decl decl;
|
||||
struct ast_decls *next;
|
||||
};
|
||||
|
||||
struct ast_subunit {
|
||||
struct ast_imports *imports;
|
||||
struct ast_decls *decls;
|
||||
struct ast_subunit *next;
|
||||
};
|
||||
|
||||
struct ast_unit {
|
||||
struct ident *ns;
|
||||
struct ast_subunit subunits;
|
||||
};
|
||||
|
||||
#endif
|
||||
169
ref/harec/include/check.h
Normal file
169
ref/harec/include/check.h
Normal file
@@ -0,0 +1,169 @@
|
||||
#ifndef HARE_CHECK_H
|
||||
#define HARE_CHECK_H
|
||||
#include <stdbool.h>
|
||||
#include <stdnoreturn.h>
|
||||
#include "ast.h"
|
||||
#include "identifier.h"
|
||||
#include "scope.h"
|
||||
#include "types.h"
|
||||
#include "type_store.h"
|
||||
#include "util.h"
|
||||
|
||||
struct expression;
|
||||
|
||||
#define MODCACHE_BUCKETS 256
|
||||
|
||||
struct modcache {
|
||||
struct ident *ident;
|
||||
struct scope *scope;
|
||||
struct modcache *next;
|
||||
};
|
||||
|
||||
struct errors {
|
||||
struct location loc;
|
||||
char *msg;
|
||||
struct errors *next;
|
||||
};
|
||||
|
||||
struct context {
|
||||
type_store *store;
|
||||
struct modcache **modcache;
|
||||
const struct type *fntype;
|
||||
struct ident *ns;
|
||||
struct scope *unit;
|
||||
struct scope *scope;
|
||||
struct scope *defines;
|
||||
const char *mainsym;
|
||||
struct ident *mainident;
|
||||
bool is_test;
|
||||
int id;
|
||||
struct errors *errors;
|
||||
struct errors **next;
|
||||
struct declarations *decls;
|
||||
struct ast_types *unresolved;
|
||||
struct intern_table *itbl;
|
||||
};
|
||||
|
||||
struct constant_decl {
|
||||
const struct type *type;
|
||||
const struct expression *value;
|
||||
};
|
||||
|
||||
struct function_decl {
|
||||
const struct type *type;
|
||||
struct expression *body;
|
||||
struct scope *scope;
|
||||
unsigned int flags; // enum func_decl_flags
|
||||
};
|
||||
|
||||
struct global_decl {
|
||||
const struct type *type;
|
||||
struct expression *value; // EXPR_LITERAL
|
||||
bool threadlocal;
|
||||
};
|
||||
|
||||
enum decl_type {
|
||||
DECL_FUNC,
|
||||
DECL_TYPE,
|
||||
DECL_GLOBAL,
|
||||
DECL_CONST,
|
||||
};
|
||||
|
||||
struct declaration {
|
||||
enum decl_type decl_type;
|
||||
int file;
|
||||
struct ident *ident;
|
||||
const char *symbol;
|
||||
bool exported; // XXX: this bool takes up 8 bytes and i am in pain
|
||||
union {
|
||||
struct constant_decl constant;
|
||||
struct function_decl func;
|
||||
struct global_decl global;
|
||||
const struct type *type;
|
||||
};
|
||||
};
|
||||
|
||||
struct declarations {
|
||||
struct declaration decl;
|
||||
struct declarations *next;
|
||||
};
|
||||
|
||||
struct unit {
|
||||
struct ident *ns;
|
||||
struct declarations *declarations;
|
||||
struct identifiers *imports;
|
||||
};
|
||||
|
||||
enum idecl_type {
|
||||
IDECL_DECL,
|
||||
IDECL_ENUM_FLD,
|
||||
};
|
||||
|
||||
// Keeps track of enum specific context required for enum field resolution
|
||||
struct incomplete_enum_field {
|
||||
struct ast_enum_field *field;
|
||||
struct scope *enum_scope;
|
||||
};
|
||||
|
||||
// Keeps track of context required to resolve a declaration or an enum field
|
||||
// Extends the scope_object struct so it can be inserted into a scope
|
||||
struct incomplete_decl {
|
||||
struct scope *imports; // the scope of this declaration's subunit
|
||||
enum idecl_type type;
|
||||
bool in_progress;
|
||||
bool dealias_in_progress;
|
||||
union {
|
||||
struct ast_decl decl;
|
||||
struct incomplete_enum_field *field;
|
||||
};
|
||||
};
|
||||
|
||||
struct ident *mkident(struct context *ctx, struct ident *ident,
|
||||
const char *symbol);
|
||||
|
||||
void append_decl(struct context *ctx, struct declaration *decl);
|
||||
|
||||
void mkstrliteral(struct expression *expr, const char *fmt, ...) FORMAT(2, 3);
|
||||
|
||||
char *gen_typename(const struct type *type);
|
||||
|
||||
struct expression *lower_implicit_cast(struct context *ctx,
|
||||
const struct type *to, struct expression *expr);
|
||||
|
||||
typedef void (*resolvefn)(struct context *, struct scope_object *obj);
|
||||
|
||||
void resolve_dimensions(struct context *ctx, struct scope_object *obj);
|
||||
|
||||
void resolve_type(struct context *ctx, struct scope_object *obj);
|
||||
|
||||
void wrap_resolver(struct context *ctx,
|
||||
struct scope_object *obj, resolvefn resolver);
|
||||
|
||||
struct scope *check(type_store *ts,
|
||||
bool is_test,
|
||||
const char *mainsym,
|
||||
struct ident *mainident,
|
||||
const struct ast_decls *defines,
|
||||
const struct ast_unit *aunit,
|
||||
struct unit *unit,
|
||||
struct intern_table *itbl);
|
||||
|
||||
struct scope *check_internal(type_store *ts,
|
||||
struct modcache **cache,
|
||||
bool is_test,
|
||||
const char *mainsym,
|
||||
struct ident *mainident,
|
||||
const struct ast_decls *defines,
|
||||
const struct ast_unit *aunit,
|
||||
struct unit *unit,
|
||||
struct intern_table *itbl,
|
||||
bool scan_only);
|
||||
|
||||
void check_expression(struct context *ctx,
|
||||
const struct ast_expression *aexpr,
|
||||
struct expression *expr,
|
||||
const struct type *hint);
|
||||
|
||||
void error(struct context *ctx, struct location loc,
|
||||
struct expression *expr, const char *fmt, ...) FORMAT(4, 5);
|
||||
#endif
|
||||
12
ref/harec/include/eval.h
Normal file
12
ref/harec/include/eval.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef HAREC_EVAL_H
|
||||
#define HAREC_EVAL_H
|
||||
#include <stdbool.h>
|
||||
|
||||
struct expression;
|
||||
struct context;
|
||||
|
||||
// Evaluates an expression at compile time.
|
||||
bool eval_expr(struct context *ctx, const struct expression *restrict in,
|
||||
struct expression *restrict out);
|
||||
|
||||
#endif
|
||||
402
ref/harec/include/expr.h
Normal file
402
ref/harec/include/expr.h
Normal file
@@ -0,0 +1,402 @@
|
||||
#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
|
||||
53
ref/harec/include/identifier.h
Normal file
53
ref/harec/include/identifier.h
Normal file
@@ -0,0 +1,53 @@
|
||||
#ifndef HARE_IDENTIFIER_H
|
||||
#define HARE_IDENTIFIER_H
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// Maximum length of an identifier, as the sum of the lengths (excluding NUL
|
||||
// terminators) of its parts plus one for each namespace deliniation.
|
||||
//
|
||||
// In other words, the length of "a::b::c" is 5.
|
||||
#define IDENT_MAX 255
|
||||
|
||||
// Minimum buffer size needed to store an unparsed identifier, including the
|
||||
// terminating NUL byte.
|
||||
#define IDENT_BUFSIZ (IDENT_MAX / 2 + IDENT_MAX + 1)
|
||||
|
||||
struct ident {
|
||||
const char *name;
|
||||
struct ident *ns;
|
||||
};
|
||||
|
||||
struct identifiers {
|
||||
struct ident *ident;
|
||||
struct identifiers *next;
|
||||
};
|
||||
|
||||
struct bucket {
|
||||
void **ids;
|
||||
size_t sz;
|
||||
size_t cap;
|
||||
};
|
||||
|
||||
struct intern_table {
|
||||
struct bucket *sbuckets;
|
||||
struct bucket *ibuckets;
|
||||
};
|
||||
|
||||
bool ident_equal(const struct ident *a, const struct ident *b);
|
||||
uint32_t ident_hash(uint32_t init, const struct ident *ident);
|
||||
char *ident_unparse(const struct ident *ident);
|
||||
int ident_unparse_static(const struct ident *ident, char *buf);
|
||||
const char *ident_to_sym(struct intern_table *itbl, const struct ident *ident);
|
||||
|
||||
void intern_init(struct intern_table *itbl);
|
||||
|
||||
const char *intern_copy(struct intern_table *itbl, const char *s);
|
||||
const char *intern_owned(struct intern_table *itbl, char *s);
|
||||
|
||||
struct ident *intern_ident(struct intern_table *itbl,
|
||||
const char *name, struct ident *ns);
|
||||
struct ident *intern_name(struct intern_table *itbl, const char *name);
|
||||
|
||||
#endif
|
||||
190
ref/harec/include/lex.h
Normal file
190
ref/harec/include/lex.h
Normal file
@@ -0,0 +1,190 @@
|
||||
#ifndef HAREC_LEX_H
|
||||
#define HAREC_LEX_H
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "types.h"
|
||||
#include "utf8.h"
|
||||
|
||||
#define C_EOF UTF8_INVALID
|
||||
|
||||
// Keep sorted
|
||||
enum lexical_token {
|
||||
T_ATTR_FINI,
|
||||
T_ATTR_INIT,
|
||||
T_ATTR_PACKED,
|
||||
T_ATTR_SYMBOL,
|
||||
T_ATTR_TEST,
|
||||
T_ATTR_THREADLOCAL,
|
||||
T_ATTR_UNDEFINED,
|
||||
T_UNDERSCORE,
|
||||
T_ABORT,
|
||||
T_ALIGN,
|
||||
T_ALLOC,
|
||||
T_APPEND,
|
||||
T_AS,
|
||||
T_ASSERT,
|
||||
T_BOOL,
|
||||
T_BREAK,
|
||||
T_CASE,
|
||||
T_CONST,
|
||||
T_CONTINUE,
|
||||
T_DEF,
|
||||
T_DEFER,
|
||||
T_DELETE,
|
||||
T_DONE,
|
||||
T_ELSE,
|
||||
T_ENUM,
|
||||
T_EXPORT,
|
||||
T_F32,
|
||||
T_F64,
|
||||
T_FALSE,
|
||||
T_FN,
|
||||
T_FOR,
|
||||
T_FREE,
|
||||
T_I16,
|
||||
T_I32,
|
||||
T_I64,
|
||||
T_I8,
|
||||
T_IF,
|
||||
T_INSERT,
|
||||
T_INT,
|
||||
T_IS,
|
||||
T_LEN,
|
||||
T_LET,
|
||||
T_MATCH,
|
||||
T_NEVER,
|
||||
T_NOMEM,
|
||||
T_NULL,
|
||||
T_NULLABLE,
|
||||
T_OFFSET,
|
||||
T_OPAQUE,
|
||||
T_RETURN,
|
||||
T_RUNE,
|
||||
T_SIZE,
|
||||
T_STATIC,
|
||||
T_STR,
|
||||
T_STRUCT,
|
||||
T_SWITCH,
|
||||
T_TRUE,
|
||||
T_TYPE,
|
||||
T_U16,
|
||||
T_U32,
|
||||
T_U64,
|
||||
T_U8,
|
||||
T_UINT,
|
||||
T_UINTPTR,
|
||||
T_UNION,
|
||||
T_USE,
|
||||
T_VAARG,
|
||||
T_VAEND,
|
||||
T_VALIST,
|
||||
T_VASTART,
|
||||
T_VOID,
|
||||
T_YIELD,
|
||||
T_LAST_KEYWORD = T_YIELD,
|
||||
|
||||
// Operators
|
||||
T_ARROW,
|
||||
T_BANDEQ,
|
||||
T_BAND,
|
||||
T_BNOT,
|
||||
T_BOR,
|
||||
T_COLON,
|
||||
T_COMMA,
|
||||
T_DIV,
|
||||
T_DIVEQ,
|
||||
T_DOT,
|
||||
T_DOUBLE_COLON,
|
||||
T_DOUBLE_DOT,
|
||||
T_ELLIPSIS,
|
||||
T_EQUAL,
|
||||
T_GREATER,
|
||||
T_GREATEREQ,
|
||||
T_LAND,
|
||||
T_LANDEQ,
|
||||
T_LBRACE,
|
||||
T_LBRACKET,
|
||||
T_LEQUAL,
|
||||
T_LESS,
|
||||
T_LESSEQ,
|
||||
T_LNOT,
|
||||
T_LOR,
|
||||
T_LOREQ,
|
||||
T_LPAREN,
|
||||
T_LSHIFT,
|
||||
T_LSHIFTEQ,
|
||||
T_LXOR,
|
||||
T_LXOREQ,
|
||||
T_MINUS,
|
||||
T_MINUSEQ,
|
||||
T_MODEQ,
|
||||
T_MODULO,
|
||||
T_NEQUAL,
|
||||
T_BOREQ,
|
||||
T_PLUS,
|
||||
T_PLUSEQ,
|
||||
T_QUESTION,
|
||||
T_RBRACE,
|
||||
T_RBRACKET,
|
||||
T_RPAREN,
|
||||
T_RSHIFT,
|
||||
T_RSHIFTEQ,
|
||||
T_SEMICOLON,
|
||||
T_TIMES,
|
||||
T_TIMESEQ,
|
||||
T_BXOR,
|
||||
T_BXOREQ,
|
||||
T_LAST_OPERATOR = T_BXOREQ,
|
||||
|
||||
// Tokens with additional information
|
||||
T_NAME,
|
||||
T_LITERAL,
|
||||
|
||||
// Magic tokens
|
||||
T_EOF,
|
||||
T_NONE,
|
||||
};
|
||||
|
||||
struct location {
|
||||
int file;
|
||||
int lineno, colno;
|
||||
};
|
||||
|
||||
struct token {
|
||||
struct location loc;
|
||||
enum lexical_token token;
|
||||
enum type_storage storage;
|
||||
union {
|
||||
const char *name;
|
||||
uint32_t rune;
|
||||
int64_t ival;
|
||||
uint64_t uval;
|
||||
double fval;
|
||||
struct {
|
||||
size_t len;
|
||||
const char *value;
|
||||
} string;
|
||||
};
|
||||
};
|
||||
|
||||
struct lexer {
|
||||
FILE *in;
|
||||
char *buf;
|
||||
size_t bufsz, buflen;
|
||||
uint32_t c[2];
|
||||
struct token un;
|
||||
struct location loc;
|
||||
bool require_int;
|
||||
bool in_annotation;
|
||||
struct intern_table *itbl;
|
||||
};
|
||||
|
||||
void lex_init(struct lexer *lexer, FILE *f, int fileid, struct intern_table *itbl);
|
||||
void lex_finish(struct lexer *lexer);
|
||||
enum lexical_token lex(struct lexer *lexer, struct token *out);
|
||||
void unlex(struct lexer *lexer, const struct token *in);
|
||||
|
||||
const char *token_str(const struct token *tok);
|
||||
const char *lexical_token_str(enum lexical_token tok);
|
||||
|
||||
#endif
|
||||
11
ref/harec/include/mod.h
Normal file
11
ref/harec/include/mod.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef HARE_MOD_H
|
||||
#define HARE_MOD_H
|
||||
|
||||
struct ast_decls;
|
||||
struct context;
|
||||
struct ident;
|
||||
|
||||
struct scope *module_resolve(struct context *ctx,
|
||||
const struct ast_decls *defines, struct ident *ident);
|
||||
|
||||
#endif
|
||||
96
ref/harec/include/scope.h
Normal file
96
ref/harec/include/scope.h
Normal file
@@ -0,0 +1,96 @@
|
||||
#ifndef HAREC_SCOPE_H
|
||||
#define HAREC_SCOPE_H
|
||||
#include "expr.h"
|
||||
#include "identifier.h"
|
||||
|
||||
#define SCOPE_BUCKETS 4096
|
||||
|
||||
enum object_type {
|
||||
O_BIND,
|
||||
O_CONST,
|
||||
O_DECL,
|
||||
O_SCAN,
|
||||
O_TYPE,
|
||||
};
|
||||
|
||||
enum scope_object_flags {
|
||||
SO_THREADLOCAL = 1 << 0,
|
||||
SO_FOR_EACH_SUBJECT = 1 << 1,
|
||||
};
|
||||
|
||||
struct scope_object {
|
||||
enum object_type otype;
|
||||
// name is the name of the object within this scope (for lookups)
|
||||
// ident is the global identifier (these may be different in some cases)
|
||||
struct ident *name;
|
||||
struct ident *ident;
|
||||
enum scope_object_flags flags;
|
||||
|
||||
union {
|
||||
const struct type *type;
|
||||
struct expression *value; // For O_CONST
|
||||
};
|
||||
// Cannot be in union because type and idecl are needed at the same time
|
||||
struct incomplete_decl *idecl;
|
||||
|
||||
struct scope_object *lnext; // Linked list
|
||||
struct scope_object *mnext; // Hash map
|
||||
};
|
||||
|
||||
enum scope_class {
|
||||
SCOPE_COMPOUND,
|
||||
SCOPE_DEFER,
|
||||
SCOPE_ENUM,
|
||||
SCOPE_FUNC,
|
||||
SCOPE_LOOP,
|
||||
SCOPE_MATCH,
|
||||
SCOPE_SUBUNIT,
|
||||
SCOPE_UNIT,
|
||||
SCOPE_DEFINES,
|
||||
};
|
||||
|
||||
struct yield { // and break
|
||||
struct expression **expression;
|
||||
struct yield *next;
|
||||
};
|
||||
|
||||
struct scope {
|
||||
enum scope_class class;
|
||||
const char *label;
|
||||
struct scope *parent;
|
||||
|
||||
const struct type *hint;
|
||||
struct type_tagged_union results;
|
||||
struct yield *yields;
|
||||
|
||||
// Linked list in insertion order
|
||||
// Used for function parameters and enum values, where order matters
|
||||
struct scope_object *objects;
|
||||
struct scope_object **next;
|
||||
|
||||
// Hash map in reverse insertion order
|
||||
// Used for lookups, and accounts for shadowing
|
||||
struct scope_object *buckets[SCOPE_BUCKETS];
|
||||
};
|
||||
|
||||
struct scopes {
|
||||
struct scope *scope;
|
||||
struct scopes *next;
|
||||
};
|
||||
|
||||
struct scope *scope_push(struct scope **stack, enum scope_class class);
|
||||
struct scope *scope_pop(struct scope **stack);
|
||||
|
||||
struct scope *scope_lookup_class(struct scope *scope, enum scope_class class);
|
||||
struct scope *scope_lookup_label(struct scope *scope, const char *label);
|
||||
|
||||
void scope_free(struct scope *scope);
|
||||
void scope_free_all(struct scopes *scopes);
|
||||
|
||||
struct scope_object *scope_insert(struct scope *scope,
|
||||
enum object_type otype, struct ident *ident, struct ident *name,
|
||||
const struct type *type, struct expression *value);
|
||||
|
||||
struct scope_object *scope_lookup(struct scope *scope, struct ident *ident);
|
||||
|
||||
#endif
|
||||
60
ref/harec/include/type_store.h
Normal file
60
ref/harec/include/type_store.h
Normal file
@@ -0,0 +1,60 @@
|
||||
#ifndef HARE_TYPESTORE_H
|
||||
#define HARE_TYPESTORE_H
|
||||
#include "ast.h"
|
||||
#include "lex.h"
|
||||
#include "types.h"
|
||||
|
||||
#define TYPE_STORE_BUCKETS 65536
|
||||
|
||||
struct type_bucket {
|
||||
struct type type;
|
||||
struct type_bucket *next;
|
||||
};
|
||||
|
||||
struct context;
|
||||
|
||||
struct dimensions {
|
||||
size_t size;
|
||||
size_t align;
|
||||
};
|
||||
|
||||
typedef struct type_bucket *type_store[TYPE_STORE_BUCKETS];
|
||||
|
||||
// Applies the type reduction algorithm to the given tagged union.
|
||||
const struct type *type_store_reduce_result(struct context *ctx,
|
||||
struct location loc, struct type_tagged_union *in);
|
||||
|
||||
struct ast_type;
|
||||
|
||||
const struct type *type_store_lookup_atype(
|
||||
struct context *ctx, const struct ast_type *atype);
|
||||
|
||||
struct dimensions type_store_lookup_dimensions(
|
||||
struct context *ctx, const struct ast_type *atype);
|
||||
|
||||
const struct type *builtin_type_for_storage(enum type_storage storage);
|
||||
|
||||
const struct type *type_store_lookup_pointer(struct context *ctx,
|
||||
struct location loc, const struct type *referent, bool nullable);
|
||||
|
||||
const struct type *type_store_lookup_array(struct context *ctx,
|
||||
struct location loc, const struct type *members, size_t len,
|
||||
bool expandable);
|
||||
|
||||
const struct type *type_store_lookup_slice(struct context *ctx,
|
||||
struct location loc, const struct type *members);
|
||||
|
||||
const struct type *type_store_lookup_alias(struct context *ctx,
|
||||
struct ident *ident, struct ident *name,
|
||||
const struct type *secondary, bool exported);
|
||||
|
||||
const struct type *type_store_lookup_tagged(struct context *ctx,
|
||||
struct location loc, struct type_tagged_union *tags);
|
||||
|
||||
const struct type *type_store_lookup_tuple(struct context *ctx,
|
||||
struct location loc, struct type_tuple *values);
|
||||
|
||||
const struct type *type_store_lookup_enum(struct context *ctx,
|
||||
const struct ast_type *atype, bool exported);
|
||||
|
||||
#endif
|
||||
11
ref/harec/include/typedef.h
Normal file
11
ref/harec/include/typedef.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef HARE_TYPEDEF_H
|
||||
#define HARE_TYPEDEF_H
|
||||
#include <stdio.h>
|
||||
|
||||
struct type;
|
||||
struct unit;
|
||||
|
||||
void emit_type(const struct type *type, FILE *out);
|
||||
void emit_typedefs(const struct unit *unit, FILE *out);
|
||||
|
||||
#endif
|
||||
230
ref/harec/include/types.h
Normal file
230
ref/harec/include/types.h
Normal file
@@ -0,0 +1,230 @@
|
||||
#ifndef HARE_TYPES_H
|
||||
#define HARE_TYPES_H
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "arch.h"
|
||||
#include "identifier.h"
|
||||
|
||||
enum type_storage {
|
||||
// Built-in types
|
||||
// The order of these is important
|
||||
STORAGE_BOOL,
|
||||
STORAGE_DONE,
|
||||
STORAGE_F32,
|
||||
STORAGE_F64,
|
||||
STORAGE_I16,
|
||||
STORAGE_I32,
|
||||
STORAGE_I64,
|
||||
STORAGE_I8,
|
||||
STORAGE_INT,
|
||||
STORAGE_NEVER,
|
||||
STORAGE_NOMEM,
|
||||
STORAGE_NULL,
|
||||
STORAGE_OPAQUE,
|
||||
STORAGE_RUNE,
|
||||
STORAGE_SIZE,
|
||||
STORAGE_STRING,
|
||||
STORAGE_U16,
|
||||
STORAGE_U32,
|
||||
STORAGE_U64,
|
||||
STORAGE_U8,
|
||||
STORAGE_UINT,
|
||||
STORAGE_UINTPTR,
|
||||
STORAGE_UNDEFINED,
|
||||
STORAGE_VOID,
|
||||
// Other types
|
||||
STORAGE_ALIAS,
|
||||
STORAGE_ARRAY,
|
||||
STORAGE_ENUM,
|
||||
STORAGE_FUNCTION,
|
||||
STORAGE_POINTER,
|
||||
STORAGE_SLICE,
|
||||
STORAGE_STRUCT,
|
||||
STORAGE_TAGGED,
|
||||
STORAGE_TUPLE,
|
||||
STORAGE_UNION,
|
||||
STORAGE_VALIST,
|
||||
STORAGE_FCONST,
|
||||
STORAGE_ICONST,
|
||||
STORAGE_RCONST,
|
||||
STORAGE_ERROR,
|
||||
// For internal use only
|
||||
STORAGE_INVALID,
|
||||
};
|
||||
|
||||
struct context;
|
||||
struct type;
|
||||
|
||||
#define SIZE_UNDEFINED ((size_t)-1)
|
||||
#define ALIGN_UNDEFINED ((size_t)-1)
|
||||
|
||||
struct type_alias {
|
||||
struct ident *ident;
|
||||
struct ident *name;
|
||||
const struct type *type;
|
||||
bool exported; // Used to make sure unexported aliases aren't emitted
|
||||
};
|
||||
|
||||
struct type_array {
|
||||
size_t length; // SIZE_UNDEFINED for [*] and slices
|
||||
const struct type *members;
|
||||
bool expandable;
|
||||
};
|
||||
|
||||
struct type_enum {
|
||||
struct scope *values;
|
||||
};
|
||||
|
||||
enum variadism {
|
||||
VARIADISM_NONE,
|
||||
VARIADISM_C,
|
||||
VARIADISM_HARE,
|
||||
};
|
||||
|
||||
struct type_func_param {
|
||||
const struct type *type;
|
||||
struct expression *default_value;
|
||||
struct type_func_param *next;
|
||||
};
|
||||
|
||||
struct type_func {
|
||||
const struct type *result;
|
||||
enum variadism variadism;
|
||||
struct type_func_param *params;
|
||||
};
|
||||
|
||||
struct type_flexible {
|
||||
int64_t min, max;
|
||||
uint32_t id;
|
||||
const struct type ***refs;
|
||||
size_t nrefs;
|
||||
size_t zrefs;
|
||||
};
|
||||
|
||||
struct type_pointer {
|
||||
const struct type *referent;
|
||||
bool nullable;
|
||||
};
|
||||
|
||||
struct struct_field {
|
||||
const char *name;
|
||||
const struct type *type;
|
||||
size_t offset;
|
||||
size_t size;
|
||||
struct struct_field *next;
|
||||
};
|
||||
|
||||
struct type_struct_union {
|
||||
struct struct_field *fields;
|
||||
bool packed;
|
||||
};
|
||||
|
||||
struct type_tuple {
|
||||
const struct type *type;
|
||||
size_t offset;
|
||||
struct type_tuple *next;
|
||||
};
|
||||
|
||||
struct type_tagged_union {
|
||||
const struct type **types;
|
||||
size_t len;
|
||||
size_t cap;
|
||||
};
|
||||
|
||||
struct type {
|
||||
enum type_storage storage;
|
||||
uint32_t id;
|
||||
size_t size, align;
|
||||
union {
|
||||
struct {
|
||||
struct type_alias alias;
|
||||
struct type_enum _enum;
|
||||
};
|
||||
struct type_array array;
|
||||
const struct type *error;
|
||||
struct type_flexible flexible;
|
||||
struct type_func func;
|
||||
struct type_pointer pointer;
|
||||
struct type_struct_union struct_union;
|
||||
struct type_tagged_union tagged;
|
||||
struct type_tuple tuple;
|
||||
};
|
||||
};
|
||||
|
||||
const struct type *type_dereference(struct context *ctx, const struct type *type,
|
||||
bool allow_nullable);
|
||||
const struct type *type_dealias(struct context *ctx, const struct type *type);
|
||||
bool type_is_done(struct context *ctx, const struct type *type);
|
||||
const struct struct_field *type_get_field(struct context *ctx,
|
||||
const struct type *type, const char *name);
|
||||
const struct type_tuple *type_get_value(
|
||||
const struct type *type, uint64_t index);
|
||||
|
||||
void tagged_append(struct type_tagged_union *tagged, const struct type *memb);
|
||||
struct type_tagged_union tagged_dup_tags(const struct type_tagged_union *tags);
|
||||
const struct type *tagged_select_subtype(struct context *ctx,
|
||||
const struct type *tagged, const struct type *subtype, bool strip);
|
||||
bool tagged_subset_compat(struct context *ctx,
|
||||
const struct type *to, const struct type *from);
|
||||
|
||||
const char *type_storage_unparse(enum type_storage storage);
|
||||
bool type_is_signed(struct context *ctx, const struct type *type);
|
||||
bool type_is_integer(struct context *ctx, const struct type *type);
|
||||
bool type_is_numeric(struct context *ctx, const struct type *type);
|
||||
bool type_is_float(struct context *ctx, const struct type *type);
|
||||
bool type_is_flexible(const struct type *type);
|
||||
bool type_is_error(struct context *ctx, const struct type *type);
|
||||
bool type_has_error(struct context *ctx, const struct type *type);
|
||||
|
||||
uint32_t type_hash(const struct type *type);
|
||||
bool type_equal(const struct type *a, const struct type *b);
|
||||
|
||||
const struct type *promote_flexible(struct context *ctx,
|
||||
const struct type *a, const struct type *b);
|
||||
bool type_is_assignable(struct context *ctx,
|
||||
const struct type *to, const struct type *from);
|
||||
const struct type *type_is_castable(struct context *ctx,
|
||||
const struct type *to, const struct type *from);
|
||||
|
||||
const struct type *type_create_flexible(enum type_storage storage,
|
||||
int64_t min, int64_t max);
|
||||
const struct type *lower_flexible(struct context *ctx,
|
||||
const struct type *old, const struct type *new);
|
||||
void flexible_refer(const struct type *type, const struct type **ref);
|
||||
void flexible_reset_refs(const struct type *type);
|
||||
|
||||
void builtin_types_init(enum arch target);
|
||||
|
||||
// Built-in type singletons
|
||||
extern struct type
|
||||
// Primitive
|
||||
builtin_type_bool,
|
||||
builtin_type_done,
|
||||
builtin_type_invalid,
|
||||
builtin_type_f32,
|
||||
builtin_type_f64,
|
||||
builtin_type_i16,
|
||||
builtin_type_i32,
|
||||
builtin_type_i64,
|
||||
builtin_type_i8,
|
||||
builtin_type_int,
|
||||
builtin_type_never,
|
||||
builtin_type_nomem,
|
||||
builtin_type_null,
|
||||
builtin_type_opaque,
|
||||
builtin_type_rune,
|
||||
builtin_type_size,
|
||||
builtin_type_u16,
|
||||
builtin_type_u32,
|
||||
builtin_type_u64,
|
||||
builtin_type_u8,
|
||||
builtin_type_uint,
|
||||
builtin_type_uintptr,
|
||||
builtin_type_void,
|
||||
|
||||
// etc
|
||||
builtin_type_str,
|
||||
builtin_type_valist,
|
||||
builtin_type_undefined;
|
||||
|
||||
#endif
|
||||
26
ref/harec/include/utf8.h
Normal file
26
ref/harec/include/utf8.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef HAREC_UTF8_H
|
||||
#define HAREC_UTF8_H
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define UTF8_MAX_SIZE 4
|
||||
|
||||
#define UTF8_INVALID UINT32_MAX
|
||||
|
||||
/**
|
||||
* Grabs the next UTF-8 codepoint and advances the string pointer
|
||||
*/
|
||||
uint32_t utf8_decode(const char **str);
|
||||
|
||||
/**
|
||||
* Encodes a codepoint as UTF-8 and returns the length of that codepoint.
|
||||
*/
|
||||
size_t utf8_encode(char *str, uint32_t ch);
|
||||
|
||||
/**
|
||||
* Reads and returns the next codepoint from the file.
|
||||
*/
|
||||
uint32_t utf8_get(FILE *f);
|
||||
|
||||
#endif
|
||||
57
ref/harec/include/util.h
Normal file
57
ref/harec/include/util.h
Normal file
@@ -0,0 +1,57 @@
|
||||
#ifndef HARE_UTIL_H
|
||||
#define HARE_UTIL_H
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "lex.h"
|
||||
|
||||
enum exit_status {
|
||||
/* EXIT_SUCCESS = 0 (defined in stdlib.h) */
|
||||
EXIT_USER = 1,
|
||||
EXIT_LEX = 2,
|
||||
EXIT_PARSE = 3,
|
||||
EXIT_CHECK = 4,
|
||||
EXIT_ABNORMAL = 255,
|
||||
};
|
||||
|
||||
extern const char **sources;
|
||||
// Sources unaffected by the -M option
|
||||
extern const char **full_sources;
|
||||
extern size_t nsources;
|
||||
|
||||
#define FNV1A_INIT 2166136261u
|
||||
|
||||
uint32_t fnv1a(uint32_t hash, unsigned char c);
|
||||
uint32_t fnv1a_u32(uint32_t hash, uint32_t u32);
|
||||
uint32_t fnv1a_u64(uint32_t hash, uint64_t u64);
|
||||
uint32_t fnv1a_size(uint32_t hash, size_t sz);
|
||||
uint32_t fnv1a_s(uint32_t hash, const char *str);
|
||||
void *xcalloc(size_t n, size_t s);
|
||||
void *xrealloc(void *p, size_t s);
|
||||
char *xstrdup(const char *s);
|
||||
|
||||
#define FORMAT(FMT_PARAM, VA_PARAM)
|
||||
#ifdef __has_attribute
|
||||
#if __has_attribute(format)
|
||||
#undef FORMAT
|
||||
#define FORMAT(FMT_PARAM, VA_PARAM) __attribute__((format(printf, FMT_PARAM, VA_PARAM)))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int xfprintf(FILE *restrict f, const char *restrict fmt, ...) FORMAT(2, 3);
|
||||
int xvfprintf(FILE *restrict f, const char *restrict fmt, va_list ap) FORMAT(2, 0);
|
||||
|
||||
#define malloc(a) (void *)sizeof(struct { static_assert(0, "Use xcalloc instead"); int _; })
|
||||
#define calloc(a, b) (void *)sizeof(struct { static_assert(0, "Use xcalloc instead"); int _; })
|
||||
#define realloc(a, b) (void *)sizeof(struct { static_assert(0, "Use xrealloc instead"); int _; })
|
||||
#define strdup(s) (char *)(sizeof(struct { static_assert(0, "Use xstrdup instead"); int _; })
|
||||
|
||||
char *gen_name(int *id, const char *fmt);
|
||||
void append_buffer(char **buf, size_t *restrict ln, size_t *restrict cap,
|
||||
const char *b, size_t sz);
|
||||
|
||||
void errline(struct location loc);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user