aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-02-15 13:43:46 -0500
committerBruce Hill <bruce@bruce-hill.com>2024-02-15 13:43:46 -0500
commit317b8f53193e5ec14c92e229c89bc84ca32b7810 (patch)
tree481ea31ebfedf6915bb59a24fd6c9cb0506abd20
parent0577469f9c49473fe95eedfa27b0f282ac9ffdb6 (diff)
Progress towards environments
-rw-r--r--Makefile4
-rw-r--r--compile.c20
-rw-r--r--environment.c62
-rw-r--r--environment.h26
-rw-r--r--nextlang.c14
-rw-r--r--parse.c64
-rw-r--r--types.h4
-rw-r--r--util.h1
8 files changed, 150 insertions, 45 deletions
diff --git a/Makefile b/Makefile
index e26ad184..86cd749e 100644
--- a/Makefile
+++ b/Makefile
@@ -24,12 +24,12 @@ 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/char.o builtins/floats.o builtins/functions.o builtins/integers.o \
+BUILTIN_OBJS=builtins/array.o builtins/bool.o builtins/builtins.o builtins/floats.o builtins/functions.o builtins/integers.o \
builtins/memory.o builtins/string.o builtins/table.o builtins/types.o
all: nextlang libnext.so
-nextlang: nextlang.c parse.o files.o util.o ast.o compile.o types.o SipHash/halfsiphash.o $(BUILTIN_OBJS)
+nextlang: nextlang.c parse.o files.o util.o ast.o compile.o types.o environment.o SipHash/halfsiphash.o $(BUILTIN_OBJS)
libnext.so: metamethods/cord.o util.o SipHash/halfsiphash.o
$(CC) $^ $(CFLAGS) $(EXTRA) $(CWARN) $(G) $(O) $(OSFLAGS) $(LDLIBS) -Wl,-soname,libnext.so -shared -o $@
diff --git a/compile.c b/compile.c
index c15e2dd7..01aeba63 100644
--- a/compile.c
+++ b/compile.c
@@ -303,13 +303,13 @@ CORD compile(env_t *env, ast_t *ast)
CORD_appendf(&env->typedefs, "typedef struct %s_s %s_t;\n", def->name, def->name);
CORD_appendf(&env->typedefs, "#define %s(...) ((%s_t){__VA_ARGS__})\n", def->name, def->name);
- CORD_appendf(&env->types, "struct %s_s {\n", def->name);
+ CORD_appendf(&env->typecode, "struct %s_s {\n", def->name);
for (arg_ast_t *field = def->fields; field; field = field->next) {
CORD type = compile_type(env, field->type);
- CORD_appendf(&env->types, "%r %s%s;\n", type, field->name,
+ CORD_appendf(&env->typecode, "%r %s%s;\n", type, field->name,
CORD_cmp(type, "Bool_t") ? "" : ":1");
}
- CORD_appendf(&env->types, "};\n");
+ CORD_appendf(&env->typecode, "};\n");
CORD cord_func = CORD_asprintf("CORD %s$cord(%s_t *obj, bool use_color) {\n"
"\tif (!obj) return \"%s\";\n", def->name, def->name, def->name);
@@ -341,21 +341,21 @@ CORD compile(env_t *env, ast_t *ast)
case EnumDef: {
auto def = Match(ast, EnumDef);
CORD_appendf(&env->typedefs, "typedef struct %s_s %s_t;\n", def->name, def->name);
- CORD_appendf(&env->types, "struct %s_s {\nenum {", def->name);
+ CORD_appendf(&env->typecode, "struct %s_s {\nenum {", def->name);
for (tag_ast_t *tag = def->tags; tag; tag = tag->next) {
- CORD_appendf(&env->types, "%s$%s = %ld, ", def->name, tag->name, tag->value);
+ CORD_appendf(&env->typecode, "%s$%s = %ld, ", def->name, tag->name, tag->value);
}
- env->types = CORD_cat(env->types, "} tag;\nunion {\n");
+ env->typecode = CORD_cat(env->typecode, "} tag;\nunion {\n");
for (tag_ast_t *tag = def->tags; tag; tag = tag->next) {
- env->types = CORD_cat(env->types, "struct {\n");
+ env->typecode = CORD_cat(env->typecode, "struct {\n");
for (arg_ast_t *field = tag->fields; field; field = field->next) {
CORD type = compile_type(env, field->type);
- CORD_appendf(&env->types, "%r %s%s;\n", type, field->name,
+ CORD_appendf(&env->typecode, "%r %s%s;\n", type, field->name,
CORD_cmp(type, "Bool_t") ? "" : ":1");
}
- CORD_appendf(&env->types, "} %s;\n", tag->name);
+ CORD_appendf(&env->typecode, "} %s;\n", tag->name);
}
- env->types = CORD_cat(env->types, "} $data;\n};\n");
+ env->typecode = CORD_cat(env->typecode, "} $data;\n};\n");
return CORD_EMPTY;
}
case DocTest: {
diff --git a/environment.c b/environment.c
new file mode 100644
index 00000000..c3ecabc7
--- /dev/null
+++ b/environment.c
@@ -0,0 +1,62 @@
+
+#include <stdlib.h>
+
+#include "environment.h"
+#include "builtins/table.h"
+#include "util.h"
+
+typedef struct {
+ const char *name;
+ binding_t binding;
+} ns_entry_t;
+
+static type_t *namespace_type(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);
+ }
+ return Type(StructType, .fields=fields);
+}
+
+env_t *new_environment(void)
+{
+ env_t *env = new(env_t);
+
+ struct {
+ const char *name;
+ binding_t binding;
+ } global_vars[] = {
+ {"say", {.code="say", .type=Type(FunctionType, .args=new(arg_t, .name="text", .type=Type(StringType)), .ret=Type(VoidType))}},
+ {"fail", {.code="fail", .type=Type(FunctionType, .args=new(arg_t, .name="message", .type=Type(StringType)), .ret=Type(AbortType))}},
+ {"USE_COLOR", {.code="USE_COLOR", .type=Type(BoolType)}},
+ };
+
+ for (size_t i = 0; i < sizeof(global_vars)/sizeof(global_vars[0]); i++) {
+ Table_str_set(&env->globals, global_vars[i].name, &global_vars[i].binding);
+ }
+
+ struct {
+ const char *name;
+ type_t *type;
+ CORD typename;
+ CORD struct_val;
+ table_t namespace;
+ } global_types[] = {
+ {"Bool", Type(BoolType), "Bool_t", "Bool", {}},
+ {"Int", Type(IntType, .bits=64), "Int_t", "Int", Table_from_entries(*(array_t*)ARRAY(
+ new(ns_entry_t, "min", {"Int.min", Type(IntType, .bits=64)}),
+ new(ns_entry_t, "max", {"Int.max", Type(IntType, .bits=64)}),
+ ), NULL)},
+ };
+
+ for (size_t i = 0; i < sizeof(global_types)/sizeof(global_types[0]); i++) {
+ Table_str_set(&env->globals, global_types[i].name, namespace_type(&global_types[i].namespace));
+ Table_str_set(&env->types, global_types[i].name, global_types[i].type);
+ }
+
+ return env;
+}
+
+// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/environment.h b/environment.h
new file mode 100644
index 00000000..a03ccd42
--- /dev/null
+++ b/environment.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <gc/cord.h>
+
+#include "types.h"
+#include "builtins/table.h"
+
+typedef struct {
+ table_t globals, types;
+ table_t *locals;
+ CORD imports;
+ CORD typedefs;
+ CORD typecode;
+ CORD staticdefs;
+ CORD funcs;
+ CORD main;
+} env_t;
+
+typedef struct {
+ CORD code;
+ type_t *type;
+} binding_t;
+
+env_t *new_environment(void);
+
+// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0
diff --git a/nextlang.c b/nextlang.c
index 8fec05f4..152c7b65 100644
--- a/nextlang.c
+++ b/nextlang.c
@@ -42,16 +42,16 @@ int main(int argc, char *argv[])
fclose(out);
}
- env_t env = {.bindings = new(table_t)};
+ env_t *env = new_environment();
- CORD_appendf(&env.imports, "#include \"nextlang.h\"\n");
- CORD_appendf(&env.staticdefs, "static bool USE_COLOR = true;\n");
+ CORD_appendf(&env->imports, "#include \"nextlang.h\"\n");
+ CORD_appendf(&env->staticdefs, "static bool USE_COLOR = true;\n");
// Main body:
for (ast_list_t *stmt = Match(ast, Block)->statements; stmt; stmt = stmt->next) {
- CORD code = compile_statement(&env, stmt->ast);
+ CORD code = compile_statement(env, stmt->ast);
if (code)
- CORD_appendf(&env.main, "%r\n", code);
+ CORD_appendf(&env->main, "%r\n", code);
}
CORD program = CORD_asprintf(
@@ -76,8 +76,8 @@ int main(int argc, char *argv[])
"return 0;\n"
"}\n",
f->filename,
- env.imports, env.typedefs, env.types, env.staticdefs,
- env.funcs, env.main);
+ env->imports, env->typedefs, env->types, env->staticdefs,
+ env->funcs, env->main);
if (verbose) {
FILE *out = popen(heap_strf("%s | bat -P --file-name=program.c", autofmt), "w");
diff --git a/parse.c b/parse.c
index d87675ed..79c1e2a7 100644
--- a/parse.c
+++ b/parse.c
@@ -570,6 +570,23 @@ PARSER(parse_num) {
return NewAST(ctx->file, start, pos, Num, .n=d, .precision=precision);
}
+static inline bool match_separator(const char **pos) { // Either comma or newline
+ const char *p = *pos;
+ int separators = 0;
+ for (;;) {
+ if (some_of(&p, "\r\n,"))
+ ++separators;
+ else if (!comment(&p) && !some_of(&p, " \t"))
+ break;
+ }
+ if (separators > 0) {
+ *pos = p;
+ return true;
+ } else {
+ return false;
+ }
+}
+
PARSER(parse_array) {
const char *start = pos;
if (!match(&pos, "[")) return NULL;
@@ -581,15 +598,15 @@ PARSER(parse_array) {
if (match(&pos, ":")) {
whitespace(&pos);
item_type = expect(ctx, pos-1, &pos, parse_type, "I couldn't parse a type for this array");
+ whitespace(&pos);
}
for (;;) {
- whitespace(&pos);
ast_t *item = optional(ctx, &pos, parse_extended_expr);
if (!item) break;
items = new(ast_list_t, .ast=item, .next=items);
- whitespace(&pos);
- if (!match(&pos, ",")) break;
+ if (!match_separator(&pos))
+ break;
}
whitespace(&pos);
expect_closing(ctx, &pos, "]", "I wasn't able to parse the rest of this array");
@@ -616,10 +633,10 @@ PARSER(parse_table) {
if (!match(&pos, "=>"))
parser_err(ctx, pos, pos, "I expected an '=>' for this table type");
value_type = expect(ctx, pos-1, &pos, parse_type, "I couldn't parse a value type for this table");
+ whitespace(&pos);
}
for (;;) {
- whitespace(&pos);
const char *entry_start = pos;
ast_t *key = optional(ctx, &pos, parse_extended_expr);
if (!key) break;
@@ -640,8 +657,8 @@ PARSER(parse_table) {
pos = entry->end;
entries = new(ast_list_t, .ast=entry, .next=entries);
- whitespace(&pos);
- if (!match(&pos, ",")) break;
+ if (!match_separator(&pos))
+ break;
}
REVERSE_LIST(entries);
@@ -1124,10 +1141,8 @@ ast_t *parse_fncall_suffix(parse_ctx_t *ctx, ast_t *fn, bool is_extern) {
got_arg:;
- whitespace(&pos);
- if (!match(&pos, ","))
+ if (!match_separator(&pos))
break;
- whitespace(&pos);
}
whitespace(&pos);
@@ -1413,15 +1428,15 @@ PARSER(parse_struct_def) {
whitespace(&pos);
bool secret = false;
if (match(&pos, ";")) { // Extra flags
- for (bool done = false; !done; done = true) {
- whitespace(&pos);
- if (match_word(&pos, "secret")) {
+ whitespace(&pos);
+ for (;;) {
+ if (match_word(&pos, "secret"))
secret = true;
- done = false;
- }
- whitespace(&pos);
- match(&pos, ",");
- match(&pos, ";");
+ else
+ break;
+
+ if (!match_separator(&pos))
+ break;
}
}
@@ -1487,14 +1502,10 @@ ast_t *parse_enum_def(parse_ctx_t *ctx, const char *pos) {
}
tags = new(tag_ast_t, .name=tag_name, .value=next_value, .fields=fields, .next=tags);
+ ++next_value;
- const char *next_pos = pos;
- whitespace(&next_pos);
- if (!match(&next_pos, ","))
+ if (!match_separator(&pos))
break;
- whitespace(&next_pos);
- pos = next_pos;
- ++next_value;
}
whitespace(&pos);
@@ -1566,8 +1577,9 @@ arg_ast_t *parse_args(parse_ctx_t *ctx, const char **pos, bool allow_unnamed)
REVERSE_LIST(names);
for (; names; names = names->next)
args = new(arg_ast_t, .name=names->name, .type=type, .default_val=default_val, .next=args);
- whitespace(pos);
- match(pos, ",");
+
+ if (!match_separator(pos))
+ break;
}
REVERSE_LIST(args);
@@ -1589,7 +1601,7 @@ PARSER(parse_func_def) {
whitespace(&pos);
bool is_inline = false;
ast_t *cache_ast = NULL;
- for (; whitespace(&pos), (match(&pos, ";") || match(&pos, ",")); ) {
+ for (bool specials = match(&pos, ";"); specials; specials = match_separator(&pos)) {
const char *flag_start = pos;
if (match_word(&pos, "inline")) {
is_inline = true;
diff --git a/types.h b/types.h
index f71f8883..fa0c7bff 100644
--- a/types.h
+++ b/types.h
@@ -37,6 +37,7 @@ struct type_s {
BoolType,
IntType,
NumType,
+ StringType,
ArrayType,
TableType,
FunctionType,
@@ -57,6 +58,9 @@ struct type_s {
int64_t bits;
} NumType;
struct {
+ const char *dsl;
+ } StringType;
+ struct {
type_t *item_type;
} ArrayType;
struct {
diff --git a/util.h b/util.h
index 68ce2c9f..34acb8ff 100644
--- a/util.h
+++ b/util.h
@@ -9,6 +9,7 @@
#define streq(a, b) (((a) == NULL && (b) == NULL) || (((a) == NULL) == ((b) == NULL) && strcmp(a, b) == 0))
#define new(t, ...) ((t*)memcpy(GC_MALLOC(sizeof(t)), &(t){__VA_ARGS__}, sizeof(t)))
+#define copy(obj_ptr) ((__typeof(obj_ptr))memcpy(GC_MALLOC(sizeof(*(obj_ptr))), obj_ptr, sizeof(*(obj_ptr))))
#define grow(arr, new_size) ((typeof (arr))GC_REALLOC(arr, (sizeof(arr[0]))*(new_size)))
#define Match(x, _tag) ((x)->tag == _tag ? &(x)->__data._tag : (errx(1, __FILE__ ":%d This was supposed to be a " # _tag "\n", __LINE__), &(x)->__data._tag))
#define Tagged(t, _tag, ...) new(t, .tag=_tag, .__data._tag={__VA_ARGS__})