aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-02-29 13:28:39 -0500
committerBruce Hill <bruce@bruce-hill.com>2024-02-29 13:28:39 -0500
commit8171a38b7130849e3049a4ea15a4fd06c154d9b0 (patch)
tree7ec4b204e6600ac3dc553d9caadfc722d04d0c8c
parent764d9fe73b0c9da918d2ecf2c4031219a1fac5be (diff)
Add type namespaces
-rw-r--r--builtins/array.h6
-rw-r--r--compile.c7
-rw-r--r--environment.c53
-rw-r--r--environment.h1
-rw-r--r--typecheck.c6
-rw-r--r--typecheck.h1
6 files changed, 55 insertions, 19 deletions
diff --git a/builtins/array.h b/builtins/array.h
index 86e57169..76ab29fd 100644
--- a/builtins/array.h
+++ b/builtins/array.h
@@ -18,6 +18,12 @@
int64_t $off = $index + ($index < 0) * ($arr.length + 1) - 1; \
(type*)($arr.data + $arr.stride * $off);})
#define $is_atomic(x) _Generic(x, bool: true, int8_t: true, int16_t: true, int32_t: true, int64_t: true, float: true, double: true, default: false)
+#define $TypedArray(t, ...) ({ t $items[] = {__VA_ARGS__}; \
+ (array_t){.length=sizeof($items)/sizeof($items[0]), \
+ .stride=(int64_t)&$items[1] - (int64_t)&$items[0], \
+ .data=memcpy(GC_MALLOC(sizeof($items)), $items, sizeof($items)), \
+ .atomic=0, \
+ .data_refcount=1}; })
#define $Array(x, ...) ({ __typeof(x) $items[] = {x, __VA_ARGS__}; \
(array_t){.length=sizeof($items)/sizeof($items[0]), \
.stride=(int64_t)&$items[1] - (int64_t)&$items[0], \
diff --git a/compile.c b/compile.c
index cf3bed4d..c4120651 100644
--- a/compile.c
+++ b/compile.c
@@ -146,7 +146,12 @@ CORD compile(env_t *env, ast_t *ast)
switch (ast->tag) {
case Nil: return CORD_asprintf("$Null(%r)", compile_type_ast(Match(ast, Nil)->type));
case Bool: return Match(ast, Bool)->b ? "yes" : "no";
- case Var: return Match(ast, Var)->name;
+ case Var: {
+ binding_t *b = get_binding(env, Match(ast, Var)->name);
+ if (b)
+ return b->code ? b->code : Match(ast, Var)->name;
+ code_err(ast, "I don't know of any variable by this name");
+ }
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
diff --git a/environment.c b/environment.c
index 0f0e18d2..87fe8a1e 100644
--- a/environment.c
+++ b/environment.c
@@ -5,6 +5,7 @@
#include "environment.h"
#include "builtins/table.h"
#include "builtins/string.h"
+#include "typecheck.h"
#include "util.h"
typedef struct {
@@ -12,22 +13,23 @@ typedef struct {
binding_t binding;
} ns_entry_t;
-static type_t *namespace_type(const char *name, table_t *ns)
-{
- arg_t *fields = NULL;
- for (int64_t i = Table_length(ns); i >= 1; i--) {
- struct {const char *name; binding_t *binding; } *entry = Table_entry(ns, i);
- fields = new(arg_t, .next=fields, .name=entry->name, .type=entry->binding->type);
- }
- name = heap_strf("%s_namespace", name);
- return Type(StructType, .name=name, .fields=fields);
-}
+// static type_t *namespace_type(const char *name, table_t *ns)
+// {
+// arg_t *fields = NULL;
+// for (int64_t i = Table_length(ns); i >= 1; i--) {
+// struct {const char *name; binding_t *binding; } *entry = Table_entry(ns, i);
+// fields = new(arg_t, .next=fields, .name=entry->name, .type=entry->binding->type);
+// }
+// name = heap_strf("%s_namespace", name);
+// return Type(StructType, .name=name, .fields=fields);
+// }
env_t *new_compilation_unit(void)
{
env_t *env = new(env_t);
env->code = new(compilation_unit_t);
env->types = new(table_t);
+ env->type_namespaces = new(table_t);
env->globals = new(table_t);
env->locals = new(table_t, .fallback=env->globals);
@@ -46,31 +48,46 @@ env_t *new_compilation_unit(void)
Table_str_set(env->globals, global_vars[i].name, b);
}
+ typedef struct {
+ const char *name, *code, *type_str;
+ } ns_entry_t;
+
struct {
const char *name;
type_t *type;
CORD typename;
CORD struct_val;
- table_t namespace;
+ array_t namespace;
} global_types[] = {
{"Bool", Type(BoolType), "Bool_t", "Bool", {}},
{"Int", Type(IntType, .bits=64), "Int_t", "Int", {}},
- {"Int32", Type(IntType, .bits=32), "Int32_t", "Int", {}},
- {"Int16", Type(IntType, .bits=16), "Int16_t", "Int", {}},
- {"Int8", Type(IntType, .bits=8), "Int8_t", "Int", {}},
+ {"Int32", Type(IntType, .bits=32), "Int32_t", "Int32", {}},
+ {"Int16", Type(IntType, .bits=16), "Int16_t", "Int16", {}},
+ {"Int8", Type(IntType, .bits=8), "Int8_t", "Int8", {}},
{"Num", Type(NumType, .bits=64), "Num_t", "Num", {}},
{"Num32", Type(NumType, .bits=32), "Num32_t", "Num32", {}},
- {"Str", Type(StringType), "Str_t", "Str", {}},
+ {"Str", Type(StringType), "Str_t", "Str", $TypedArray(ns_entry_t,
+ {"quoted", "Str__quoted", "func(s:Str, color=no)->Str"}
+ )},
};
for (size_t i = 0; i < sizeof(global_types)/sizeof(global_types[0]); i++) {
- table_t *ns = new(table_t);
- *ns = global_types[i].namespace;
- binding_t *binding = new(binding_t, .type=namespace_type(global_types[i].name, ns));
+ binding_t *binding = new(binding_t, .type=Type(TypeInfoType));
Table_str_set(env->globals, global_types[i].name, binding);
Table_str_set(env->types, global_types[i].name, global_types[i].type);
}
+ for (size_t i = 0; i < sizeof(global_types)/sizeof(global_types[0]); i++) {
+ table_t *namespace = new(table_t);
+ $ARRAY_FOREACH(global_types[i].namespace, j, ns_entry_t, entry, {
+ type_t *type = parse_type_string(env, entry.type_str);
+ binding_t *b = new(binding_t, .code=entry.code, .type=type);
+ Table_str_set(namespace, entry.name, b);
+ // printf("Bound %s:%s -> %T\n", global_types[i].name, entry.name, b->type);
+ }, {})
+ Table_str_set(env->type_namespaces, global_types[i].name, namespace);
+ }
+
return env;
}
diff --git a/environment.h b/environment.h
index 2f5c84dd..5c2e9641 100644
--- a/environment.h
+++ b/environment.h
@@ -17,6 +17,7 @@ typedef struct {
typedef struct {
table_t *types, *globals, *locals;
+ table_t *type_namespaces; // Map of type name -> namespace table
compilation_unit_t *code;
} env_t;
diff --git a/typecheck.c b/typecheck.c
index 3d408857..1f79d308 100644
--- a/typecheck.c
+++ b/typecheck.c
@@ -749,4 +749,10 @@ bool can_be_mutated(env_t *env, ast_t *ast)
}
}
+type_t *parse_type_string(env_t *env, const char *str)
+{
+ type_ast_t *ast = parse_type_str(str);
+ return ast ? parse_type_ast(env, ast) : NULL;
+}
+
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/typecheck.h b/typecheck.h
index bb6ed397..4df9a8a0 100644
--- a/typecheck.h
+++ b/typecheck.h
@@ -18,5 +18,6 @@ type_t *get_function_def_type(env_t *env, ast_t *ast);
type_t *get_arg_type(env_t *env, arg_t *arg);
type_t *get_arg_ast_type(env_t *env, arg_ast_t *arg);
bool can_be_mutated(env_t *env, ast_t *ast);
+type_t *parse_type_string(env_t *env, const char *str);
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0