Cleanup of builtins

This commit is contained in:
Bruce Hill 2024-02-17 19:32:30 -05:00
parent 7355b2f7fe
commit d46925dbfa
19 changed files with 193 additions and 124 deletions

View File

@ -24,14 +24,14 @@ G=-ggdb
O=-Og
CFLAGS=$(CCONFIG) $(EXTRA) $(CWARN) $(G) $(O) $(OSFLAGS)
LDLIBS=-lgc -lgccjit -lcord -lm -lunistring
BUILTIN_OBJS=builtins/array.o builtins/bool.o builtins/builtins.o builtins/floats.o builtins/functions.o builtins/integers.o \
BUILTIN_OBJS=builtins/array.o builtins/bool.o builtins/floats.o builtins/functions.o builtins/integers.o \
builtins/pointer.o builtins/memory.o builtins/string.o builtins/table.o builtins/types.o
all: nextlang libnext.so
all: libnext.so nextlang
nextlang: nextlang.c SipHash/halfsiphash.o util.o files.o ast.o parse.o environment.o types.o typecheck.o compile.o $(BUILTIN_OBJS)
libnext.so: util.o SipHash/halfsiphash.o
libnext.so: util.o $(BUILTIN_OBJS) SipHash/halfsiphash.o
$(CC) $^ $(CFLAGS) $(EXTRA) $(CWARN) $(G) $(O) $(OSFLAGS) $(LDLIBS) -Wl,-soname,libnext.so -shared -o $@
SipHash/halfsiphash.c:

4
ast.c
View File

@ -85,8 +85,8 @@ CORD ast_to_cord(ast_t *ast)
T(Nil, "(%r)", type_ast_to_cord(data.type))
T(Bool, "(\x1b[35m%s\x1b[m)", data.b ? "yes" : "no")
T(Var, "(\x1b[36;1m%s\x1b[m)", data.name)
T(Int, "(\x1b[35m%ld\x1b[m, precision=\x1b[35m%ld\x1b[m)", data.i, data.precision)
T(Num, "(\x1b[35m%ld\x1b[m, precision=\x1b[35m%ld\x1b[m)", data.n, data.precision)
T(Int, "(\x1b[35m%ld\x1b[m, bits=\x1b[35m%ld\x1b[m)", data.i, data.bits)
T(Num, "(\x1b[35m%ld\x1b[m, bits=\x1b[35m%ld\x1b[m)", data.n, data.bits)
T(StringLiteral, "\x1b[35m\"%r\"\x1b[m", data.cord)
T(StringJoin, "(%r)", ast_list_to_cord(data.children))
T(Declare, "(var=%s, value=%r)", ast_to_cord(data.var), ast_to_cord(data.value))

4
ast.h
View File

@ -124,11 +124,11 @@ struct ast_s {
} Var;
struct {
int64_t i;
enum { INT_64BIT, INT_32BIT, INT_16BIT, INT_8BIT } precision;
int64_t bits;
} Int;
struct {
double n;
enum { NUM_64BIT, NUM_32BIT } precision;
int64_t bits;
} Num;
struct {
CORD cord;

View File

@ -9,13 +9,14 @@
#include <sys/param.h>
#include <err.h>
#include "types.h"
#include "../util.h"
#include "../SipHash/halfsiphash.h"
#include "../util.h"
#include "bool.h"
#include "types.h"
extern const void *SSS_HASH_VECTOR;
static CORD Bool__as_str(const bool *b, bool colorize, const TypeInfo *type)
public CORD Bool__as_str(const bool *b, bool colorize, const TypeInfo *type)
{
(void)type;
if (!b) return "Bool";
@ -25,9 +26,7 @@ static CORD Bool__as_str(const bool *b, bool colorize, const TypeInfo *type)
return *b ? "yes" : "no";
}
public struct {
TypeInfo type;
} Bool_type = {
Bool_namespace_t Bool_type = {
.type={
.size=sizeof(bool),
.align=alignof(bool),

16
builtins/bool.h Normal file
View File

@ -0,0 +1,16 @@
#pragma once
#include <gc/cord.h>
#include <stdbool.h>
#include <stdint.h>
#include "types.h"
CORD Bool__as_str(const bool *b, bool colorize, const TypeInfo *type);
typedef struct {
TypeInfo type;
} Bool_namespace_t;
extern Bool_namespace_t Bool_type;
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0

View File

@ -1,10 +0,0 @@
#include <gc.h>
#include <string.h>
#include <stdio.h>
#include "array.h"
#include "types.h"
#include "functions.h"
#include "table.h"
public const char *SSS_HASH_VECTOR = "sss hash vector ----------------------------------------------";

View File

@ -11,6 +11,7 @@
#include "../SipHash/halfsiphash.h"
#include "array.h"
#include "floats.h"
#include "string.h"
#include "types.h"
@ -23,12 +24,12 @@ public CORD Num__as_str(const double *f, bool colorize, const TypeInfo *type) {
return c;
}
static int32_t Num__compare(const double *x, const double *y, const TypeInfo *type) {
public int32_t Num__compare(const double *x, const double *y, const TypeInfo *type) {
(void)type;
return (*x > *y) - (*x < *y);
}
static bool Num__equal(const double *x, const double *y, const TypeInfo *type) {
public bool Num__equal(const double *x, const double *y, const TypeInfo *type) {
(void)type;
return *x == *y;
}
@ -50,30 +51,7 @@ public bool Num__isinf(double n) { return isinf(n); }
public bool Num__finite(double n) { return finite(n); }
public bool Num__isnan(double n) { return isnan(n); }
typedef bool (*double_pred_t)(double);
typedef double (*double_unary_fn_t)(double);
typedef double (*double_binary_fn_t)(double, double);
public struct {
TypeInfo type;
// Constants:
double NaN, _2_sqrt_pi, e, half_pi, inf, inverse_half_pi, inverse_pi, ln10, ln2,
log2e, pi, quarter_pi, sqrt2, sqrt_half, tau;
// Nullary functions:
double (*random)(void);
// Predicates:
double_pred_t finite, isinf, isnan;
// Unary functions:
double_unary_fn_t abs, acos, acosh, asin, asinh, atan, atanh, cbrt, ceil, cos, cosh, erf, erfc,
exp, exp10, exp2, expm1, floor, j0, j1, log, log10, log1p, log2, logb,
nextdown, nextup, rint, round, roundeven, significand, sin, sinh, sqrt,
tan, tanh, tgamma, trunc, y0, y1;
// Binary functions:
double_binary_fn_t atan2, copysign, dist, hypot, maxmag, minmag, mod, nextafter, pow, remainder;
// Odds and ends:
CORD (*format)(double f, int64_t precision);
CORD (*scientific)(double f, int64_t precision);
} Num_type = {
public Num_namespace_t Num_type = {
.type=(TypeInfo){
.size=sizeof(double),
.align=alignof(double),
@ -112,12 +90,12 @@ public CORD Num32__as_str(float *f, bool colorize, const TypeInfo *type) {
return c;
}
static int32_t Num32__compare(const float *x, const float *y, const TypeInfo *type) {
public int32_t Num32__compare(const float *x, const float *y, const TypeInfo *type) {
(void)type;
return (*x > *y) - (*x < *y);
}
static bool Num32__equal(const float *x, const float *y, const TypeInfo *type) {
public bool Num32__equal(const float *x, const float *y, const TypeInfo *type) {
(void)type;
return *x == *y;
}
@ -143,30 +121,7 @@ public bool Num32__isinf(float n) { return isinf(n); }
public bool Num32__finite(float n) { return finite(n); }
public bool Num32__isnan(float n) { return isnan(n); }
typedef bool (*float_pred_t)(float);
typedef float (*float_unary_fn_t)(float);
typedef float (*float_binary_fn_t)(float, float);
public struct {
TypeInfo type;
// Alphabetized:
float NaN, _2_sqrt_pi, e, half_pi, inf, inverse_half_pi, inverse_pi, ln10, ln2,
log2e, pi, quarter_pi, sqrt2, sqrt_half, tau;
// Nullary functions:
float (*random)(void);
// Predicates:
float_pred_t finite, isinf, isnan;
// Unary functions:
float_unary_fn_t abs, acos, acosh, asin, asinh, atan, atanh, cbrt, ceil, cos, cosh, erf, erfc,
exp, exp10, exp2, expm1, floor, j0, j1, log, log10, log1p, log2, logb,
nextdown, nextup, rint, round, roundeven, significand, sin, sinh, sqrt,
tan, tanh, tgamma, trunc, y0, y1;
// Binary functions:
float_binary_fn_t atan2, copysign, dist, hypot, maxmag, minmag, mod, nextafter, pow, remainder;
// Odds and ends:
CORD (*format)(float f, int64_t precision);
CORD (*scientific)(float f, int64_t precision);
} Num32_type = {
public Num32_namespace_t Num32_type = {
.type=(TypeInfo){
.size=sizeof(float),
.align=alignof(float),

83
builtins/floats.h Normal file
View File

@ -0,0 +1,83 @@
#pragma once
#include <gc/cord.h>
#include <stdbool.h>
#include <stdint.h>
#include "types.h"
typedef struct {
TypeInfo type;
} Bool_namespace_t;
CORD Num__as_str(const double *f, bool colorize, const TypeInfo *type);
int32_t Num__compare(const double *x, const double *y, const TypeInfo *type);
bool Num__equal(const double *x, const double *y, const TypeInfo *type);
CORD Num__format(double f, int64_t precision);
CORD Num__scientific(double f, int64_t precision);
double Num__mod(double num, double modulus);
bool Num__isinf(double n);
bool Num__finite(double n);
bool Num__isnan(double n);
typedef bool (*double_pred_t)(double);
typedef double (*double_unary_fn_t)(double);
typedef double (*double_binary_fn_t)(double, double);
typedef struct {
TypeInfo type;
// Constants:
double NaN, _2_sqrt_pi, e, half_pi, inf, inverse_half_pi, inverse_pi, ln10, ln2,
log2e, pi, quarter_pi, sqrt2, sqrt_half, tau;
// Nullary functions:
double (*random)(void);
// Predicates:
double_pred_t finite, isinf, isnan;
// Unary functions:
double_unary_fn_t abs, acos, acosh, asin, asinh, atan, atanh, cbrt, ceil, cos, cosh, erf, erfc,
exp, exp10, exp2, expm1, floor, j0, j1, log, log10, log1p, log2, logb,
nextdown, nextup, rint, round, roundeven, significand, sin, sinh, sqrt,
tan, tanh, tgamma, trunc, y0, y1;
// Binary functions:
double_binary_fn_t atan2, copysign, dist, hypot, maxmag, minmag, mod, nextafter, pow, remainder;
// Odds and ends:
CORD (*format)(double f, int64_t precision);
CORD (*scientific)(double f, int64_t precision);
} Num_namespace_t;
CORD Num32__as_str(float *f, bool colorize, const TypeInfo *type);
int32_t Num32__compare(const float *x, const float *y, const TypeInfo *type);
bool Num32__equal(const float *x, const float *y, const TypeInfo *type);
CORD Num32__format(float f, int64_t precision);
CORD Num32__scientific(float f, int64_t precision);
float Num32__mod(float num, float modulus);
float Num32__random(void);
bool Num32__isinf(float n);
bool Num32__finite(float n);
bool Num32__isnan(float n);
typedef bool (*float_pred_t)(float);
typedef float (*float_unary_fn_t)(float);
typedef float (*float_binary_fn_t)(float, float);
typedef struct {
TypeInfo type;
// Alphabetized:
float NaN, _2_sqrt_pi, e, half_pi, inf, inverse_half_pi, inverse_pi, ln10, ln2,
log2e, pi, quarter_pi, sqrt2, sqrt_half, tau;
// Nullary functions:
float (*random)(void);
// Predicates:
float_pred_t finite, isinf, isnan;
// Unary functions:
float_unary_fn_t abs, acos, acosh, asin, asinh, atan, atanh, cbrt, ceil, cos, cosh, erf, erfc,
exp, exp10, exp2, expm1, floor, j0, j1, log, log10, log1p, log2, logb,
nextdown, nextup, rint, round, roundeven, significand, sin, sinh, sqrt,
tan, tanh, tgamma, trunc, y0, y1;
// Binary functions:
float_binary_fn_t atan2, copysign, dist, hypot, maxmag, minmag, mod, nextafter, pow, remainder;
// Odds and ends:
CORD (*format)(float f, int64_t precision);
CORD (*scientific)(float f, int64_t precision);
} Num32_namespace_t;
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0

View File

@ -17,7 +17,8 @@
#include "types.h"
extern bool USE_COLOR;
extern const void *SSS_HASH_VECTOR;
public const char *SSS_HASH_VECTOR = "sss hash vector ----------------------------------------------";;
public void fail(const char *fmt, ...)
{

View File

@ -6,10 +6,12 @@
#include "types.h"
extern const char *SSS_HASH_VECTOR;
void builtin_say(CORD str, CORD end);
void builtin_fail(CORD fmt, ...);
CORD builtin_last_err();
void builtin_doctest(const char *label, CORD expr, const char *type, bool use_color, const char *expected, const char *filename, int start, int end);
void __doctest(CORD label, void *expr, TypeInfo *type, CORD expected, const char *filename, int start, int end);
uint32_t generic_hash(const void *obj, const TypeInfo *type);
int32_t generic_compare(const void *x, const void *y, const TypeInfo *type);

View File

@ -7,11 +7,10 @@
#include "../SipHash/halfsiphash.h"
#include "array.h"
#include "integers.h"
#include "types.h"
#include "string.h"
extern const void *SSS_HASH_VECTOR;
#define xstr(a) str(a)
#define str(a) #a
@ -48,15 +47,7 @@ extern const void *SSS_HASH_VECTOR;
uint32_t r = arc4random_uniform((uint32_t)range); \
return min + (c_type)r; \
} \
public struct { \
TypeInfo type; \
c_type min, max; \
c_type (*abs)(c_type i); \
CORD (*format)(c_type i, int64_t digits); \
CORD (*hex)(c_type i, int64_t digits, bool uppercase, bool prefix); \
CORD (*octal)(c_type i, int64_t digits, bool prefix); \
c_type (*random)(int64_t min, int64_t max); \
} KindOfInt##_type = { \
public KindOfInt##_namespace_t KindOfInt##_type = { \
.type={ \
.size=sizeof(c_type), \
.align=alignof(c_type), \
@ -72,9 +63,10 @@ extern const void *SSS_HASH_VECTOR;
.random=KindOfInt##__random, \
};
DEFINE_INT_TYPE(int64_t, Int, "ld", labs, INT64_MIN, INT64_MAX);
DEFINE_INT_TYPE(int64_t, Int64, "ld", labs, INT64_MIN, INT64_MAX);
DEFINE_INT_TYPE(int32_t, Int32, "d_i32", abs, INT32_MIN, INT32_MAX);
DEFINE_INT_TYPE(int16_t, Int16, "d_i16", abs, INT16_MIN, INT16_MAX);
DEFINE_INT_TYPE(int8_t, Int8, "d_i8", abs, INT8_MIN, INT8_MAX);
#undef DEFINE_INT_TYPE
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0

30
builtins/integers.h Normal file
View File

@ -0,0 +1,30 @@
#pragma once
#include <gc/cord.h>
#include <stdbool.h>
#include <stdint.h>
#include "types.h"
#define DEFINE_INT_TYPE(c_type, KindOfInt)\
CORD KindOfInt ## __as_str(const c_type *i, bool colorize, const TypeInfo *type); \
int32_t KindOfInt ## __compare(const c_type *x, const c_type *y, const TypeInfo *type); \
CORD KindOfInt ## __format(c_type i, int64_t digits); \
CORD KindOfInt ## __hex(c_type i, int64_t digits, bool uppercase, bool prefix); \
CORD KindOfInt ## __octal(c_type i, int64_t digits, bool prefix); \
c_type KindOfInt ## __random(int64_t min, int64_t max); \
typedef struct { \
TypeInfo type; \
c_type min, max; \
c_type (*abs)(c_type i); \
CORD (*format)(c_type i, int64_t digits); \
CORD (*hex)(c_type i, int64_t digits, bool uppercase, bool prefix); \
CORD (*octal)(c_type i, int64_t digits, bool prefix); \
c_type (*random)(int64_t min, int64_t max); \
} KindOfInt##_namespace_t;
DEFINE_INT_TYPE(int64_t, Int64);
DEFINE_INT_TYPE(int32_t, Int32);
DEFINE_INT_TYPE(int16_t, Int16);
DEFINE_INT_TYPE(int8_t, Int8);
#undef DEFINE_INT_TYPE
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0

View File

@ -40,7 +40,7 @@
#define END_OF_CHAIN UINT32_MAX
#define GET_ENTRY(t, i) ((t)->entries.data + (t)->entries.stride*(i))
#define ENTRY_TYPE(type) (&(TypeInfo){.size=entry_size(type), .align=entry_align(type), .tag=OpaqueInfo})
#define ENTRIES_TYPE(type) (&(TypeInfo){.size=sizeof(array_t), .align=alignof(array_t), .tag=ArrayInfo, .ArrayInfo.item=(&(TypeInfo){.size=entry_size(type), .align=entry_align(type), .tag=OpaqueInfo})})
extern const void *SSS_HASH_VECTOR;
@ -102,7 +102,7 @@ static inline void hshow(const table_t *t)
static void maybe_copy_on_write(table_t *t, const TypeInfo *type)
{
if (t->entries.copy_on_write) {
Array__compact(&t->entries, ENTRY_TYPE(type));
Array__compact(&t->entries, ENTRIES_TYPE(type));
}
if (t->bucket_info && t->bucket_info->copy_on_write) {
@ -279,7 +279,7 @@ public void *Table_reserve(table_t *t, const void *key, const void *value, const
memcpy(buf + value_offset(type), value, value_size);
else
memset(buf + value_offset(type), 0, value_size);
Array__insert(&t->entries, buf, 0, ENTRY_TYPE(type));
Array__insert(&t->entries, buf, 0, ENTRIES_TYPE(type));
int64_t entry_index = t->entries.length-1;
void *entry = GET_ENTRY(t, entry_index);
@ -365,7 +365,7 @@ public void Table_remove(table_t *t, const void *key, const TypeInfo *type)
// Last entry is being removed, so clear it out to be safe:
memset(GET_ENTRY(t, last_entry), 0, entry_size(type));
Array__remove(&t->entries, t->entries.length, 1, ENTRY_TYPE(type));
Array__remove(&t->entries, t->entries.length, 1, ENTRIES_TYPE(type));
int64_t bucket_to_clear;
if (prev) { // Middle (or end) of a chain

View File

@ -41,11 +41,11 @@ CORD compile(env_t *env, ast_t *ast)
case Nil: return CORD_asprintf("(%r)NULL", compile_type(env, Match(ast, Nil)->type));
case Bool: return Match(ast, Bool)->b ? "yes" : "no";
case Var: return Match(ast, Var)->name;
case Int: return CORD_asprintf("I%ld(%ld)", Match(ast, Int)->precision, Match(ast, Int)->i);
case Int: return CORD_asprintf("I%ld(%ld)", Match(ast, Int)->bits, Match(ast, Int)->i);
case Num: {
// HACK: since the cord library doesn't support the '%a' specifier, this workaround
// is necessary:
char *buf = asprintfa(Match(ast, Num)->precision == 64 ? "%a" : "%af", Match(ast, Num)->n);
char *buf = asprintfa(Match(ast, Num)->bits == 64 ? "%a" : "%af", Match(ast, Num)->n);
return CORD_from_char_star(buf);
}
case Not: return CORD_asprintf("not(%r)", compile(env, Match(ast, Not)->value));
@ -363,11 +363,15 @@ CORD compile(env_t *env, ast_t *ast)
if (test->expr->tag == Declare) {
auto decl = Match(test->expr, Declare);
return CORD_asprintf(
"$var(%r, %r);\n$test(%r, %r, %r);",
"$var(%r, %r);\n"
"__doctest(\"=\", &%r, %r, %r, %r, %ld, %ld);",
compile(env, decl->var), compile(env, decl->value),
compile(env, WrapAST(test->expr, StringLiteral, .cord=src)),
compile(env, decl->var),
compile(env, WrapAST(test->expr, StringLiteral, .cord=test->output)));
compile_type_info(env, get_type(env, decl->value)),
compile(env, WrapAST(test->expr, StringLiteral, .cord=test->output)),
compile(env, WrapAST(test->expr, StringLiteral, .cord=test->expr->file->filename)),
(int64_t)(test->expr->start - test->expr->file->text),
(int64_t)(test->expr->end - test->expr->file->text));
} else if (test->expr->tag == Assign) {
auto assign = Match(test->expr, Assign);
CORD code = "{ // Assignment\n";

View File

@ -10,5 +10,6 @@
CORD compile_type(env_t *env, type_ast_t *t);
CORD compile(env_t *env, ast_t *ast);
CORD compile_statement(env_t *env, ast_t *ast);
CORD compile_type_info(env_t *env, type_t *t);
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0

View File

@ -94,8 +94,8 @@ int main(int argc, char *argv[])
const char *ldflags = "-Wl,-rpath '-Wl,$ORIGIN'";
const char *run = heap_strf("tcc -run %s %s %s -", cflags, ldflags, ldlibs);
// const char *run = heap_strf("gcc -x c %s %s %s - -o program && ./program", cflags, ldflags, ldlibs);
// const char *run = heap_strf("tcc -run %s %s %s -", cflags, ldflags, ldlibs);
const char *run = heap_strf("gcc -x c %s %s %s - -o program && ./program", cflags, ldflags, ldlibs);
FILE *cc = popen(run, "w");
CORD_put(program, cc);
fclose(cc);

View File

@ -11,7 +11,13 @@
#include <string.h>
#include <unistd.h>
#include "builtins/array.h"
#include "builtins/datatypes.h"
#include "builtins/functions.h"
#include "builtins/pointer.h"
#include "builtins/string.h"
#include "builtins/table.h"
#include "builtins/types.h"
#define Int64_t int64_t
#define Int32_t int32_t

24
parse.c
View File

@ -420,19 +420,19 @@ PARSER(parse_int) {
if (match(&pos, "%")) {
double d = (double)i / 100.;
return NewAST(ctx->file, start, pos, Num, .n=d, .precision=64);
return NewAST(ctx->file, start, pos, Num, .n=d, .bits=64);
}
match(&pos, "_");
int64_t precision = 64;
if (match(&pos, "i64")) precision = 64;
else if (match(&pos, "i32")) precision = 32;
else if (match(&pos, "i16")) precision = 16;
else if (match(&pos, "i8")) precision = 8;
int64_t bits = 64;
if (match(&pos, "i64")) bits = 64;
else if (match(&pos, "i32")) bits = 32;
else if (match(&pos, "i16")) bits = 16;
else if (match(&pos, "i8")) bits = 8;
// else if (match(&pos, ".") || match(&pos, "e")) return NULL; // looks like a float
return NewAST(ctx->file, start, pos, Int, .i=i, .precision=precision);
return NewAST(ctx->file, start, pos, Int, .i=i, .bits=bits);
}
type_ast_t *parse_table_type(parse_ctx_t *ctx, const char *pos) {
@ -558,16 +558,16 @@ PARSER(parse_num) {
if (negative) d *= -1;
int64_t precision = 64;
int64_t bits = 64;
match(&pos, "_");
if (match(&pos, "f64")) precision = 64;
else if (match(&pos, "f32")) precision = 32;
if (match(&pos, "f64")) bits = 64;
else if (match(&pos, "f32")) bits = 32;
if (match(&pos, "%")) {
d /= 100.;
}
return NewAST(ctx->file, start, pos, Num, .n=d, .precision=precision);
return NewAST(ctx->file, start, pos, Num, .n=d, .bits=bits);
}
static inline bool match_separator(const char **pos) { // Either comma or newline
@ -1606,7 +1606,7 @@ PARSER(parse_func_def) {
if (match_word(&pos, "inline")) {
is_inline = true;
} else if (match_word(&pos, "cached")) {
if (!cache_ast) cache_ast = NewAST(ctx->file, pos, pos, Int, .i=INT64_MAX, .precision=64);
if (!cache_ast) cache_ast = NewAST(ctx->file, pos, pos, Int, .i=INT64_MAX, .bits=64);
} else if (match_word(&pos, "cache_size")) {
if (whitespace(&pos), !match(&pos, "="))
parser_err(ctx, flag_start, pos, "I expected a value for 'cache_size'");

View File

@ -133,21 +133,11 @@ type_t *get_type(env_t *env, ast_t *ast)
}
case Int: {
auto i = Match(ast, Int);
switch (i->precision) {
case INT_64BIT: return Type(IntType, .bits=64);
case INT_32BIT: return Type(IntType, .bits=32);
case INT_16BIT: return Type(IntType, .bits=16);
case INT_8BIT: return Type(IntType, .bits=8);
default: code_err(ast, "Unsupported precision");
}
return Type(IntType, .bits=i->bits);
}
case Num: {
auto n = Match(ast, Num);
switch (n->precision) {
case NUM_64BIT: return Type(NumType, .bits=64);
case NUM_32BIT: return Type(NumType, .bits=32);
default: code_err(ast, "Unsupported precision");
}
return Type(NumType, .bits=n->bits);
}
case HeapAllocate: {
type_t *pointed = get_type(env, Match(ast, HeapAllocate)->value);