diff options
author | Kimplul <kimi.h.kuparinen@gmail.com> | 2025-03-30 22:36:53 +0300 |
---|---|---|
committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2025-03-30 22:41:21 +0300 |
commit | 957da9056c36a5eea15c6058701f7465b31f64a8 (patch) | |
tree | 7006d7c4ce258e88533e3b0347078a0264fe1bf3 /src/compiler.c | |
parent | c87f5a8871edf6880b894a00b180c554ffd46d0a (diff) | |
download | fwd-957da9056c36a5eea15c6058701f7465b31f64a8.tar.gz fwd-957da9056c36a5eea15c6058701f7465b31f64a8.zip |
+ C allows for a bit more control, and we can manually handle closure
contexts. For example `examples/fib.fwd` now works for effectively any
`n`, pretty cool.
+ Fairly slow Fibonacci, I must admit. Initial profiling indicates it's
mainly due to branch mispredictions, but I'll have to look into this a
bit deeper.
+ The code is a bit hacked together, for now I'm more interested in
getting things working, I'll worry about making things pretty later.
+ For testing, there's also initial support for modules, just so I can
print stuff to the terminal
+ This commit is way too big, lol
Diffstat (limited to 'src/compiler.c')
-rw-r--r-- | src/compiler.c | 120 |
1 files changed, 94 insertions, 26 deletions
diff --git a/src/compiler.c b/src/compiler.c index 9f564d8..5de992d 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -19,8 +19,9 @@ #include <fwd/analyze.h> #include <fwd/parser.h> #include <fwd/debug.h> -#include <fwd/scope.h> #include <fwd/lower.h> +#include <fwd/scope.h> +#include <fwd/path.h> #include <fwd/move.h> /** @@ -65,11 +66,11 @@ static char *read_file(const char *file, FILE *f) * @param file File name to process. * @return \c 0 if processing was succesful, non-zero value otherwise. */ -static int process(struct scope **parent, const char *file) +static int process(struct scope *scope, const char *file) { FILE *f = fopen(file, "rb"); if (!f) { - error("failed opening %s: %s\n", file, strerror(errno)); + error("failed opening %s: %s", file, strerror(errno)); return -1; } @@ -86,30 +87,20 @@ static int process(struct scope **parent, const char *file) } parse(p, file, buf); + struct ast *tree = p->tree; bool failed = p->failed; destroy_parser(p); if (failed) { - free((void*)buf); + free((void *)buf); return -1; } ast_dump_list(0, tree); - struct scope *scope = create_scope(); - if (!scope) { - free((void *)buf); - return -1; - } - scope->fctx.fbuf = buf; scope->fctx.fname = strdup(file); - if (*parent) - scope_add_scope(*parent, scope); - else - *parent = scope; - if (analyze_root(scope, tree)) return -1; @@ -119,24 +110,101 @@ static int process(struct scope **parent, const char *file) return 0; } +#define MAP_KEY const char * +#define MAP_TYPE struct scope * +#define MAP_CMP(a, b) strcmp((a), (b)) +#define MAP_HASH(a) CONTS_MAP_STR_HASH(a) +#define MAP_NAME scopes +#include <conts/map.h> + +/* ugly global for now */ +static struct scopes scopes; + +static void destroy_scopes() +{ + foreach(scopes, n, &scopes) { + destroy_scope(n->data); + free((void *)n->key); + } + + scopes_destroy(&scopes); +} + +struct scope *compile_file(const char *file) +{ + struct scope *scope = NULL; + const char *base = NULL, *dir = NULL, *cwd = NULL, *real = NULL; + if (!(base = fwd_basename(file))) { + error("couldn't get basename of %s", file); + goto out; + } + + if (!(dir = fwd_dirname(file))) { + error("couldn't get dirname of %s", file); + goto out; + } + + if (!(cwd = fwd_cwdname())) { + error("couldn't get current working dir"); + goto out; + } + + if (*dir != 0 && chdir(dir)) { + error("couldn't change to directory %s: %s", dir, + strerror(errno)); + goto out; + } + + if (!(real = realpath(base, NULL))) { + error("no such file: %s", file); + goto out; + } + + struct scope **exists = scopes_find(&scopes, real); + if (exists) { + scope = *exists; + goto out; + } + + scope = create_scope(); + scopes_insert(&scopes, strdup(real), scope); + + if (process(scope, base)) { + scope = NULL; + goto out; + } + + if (chdir(cwd)) { + error("couldn't change back to directory %s: %s", cwd, + strerror(errno)); + goto out; + } + +out: + free((void *)base); + free((void *)dir); + free((void *)cwd); + free((void *)real); + return scope; +} + int compile(const char *input) { + scopes = scopes_create(1); + int ret = -1; - struct scope *root = NULL; - if (process(&root, input)) { - destroy_scope(root); - destroy_allocs(); + struct scope *root = compile_file(input); + if (!root) { error("processing of %s stopped due to errors", input); - return ret; + goto out; } if ((ret = lower(root))) { - destroy_scope(root); - destroy_allocs(); - error("lowering of %s stopped due to errors", input); - return ret; + error("lowering of %s failed due to errors", input); + goto out; } - destroy_scope(root); +out: + destroy_scopes(); destroy_allocs(); - return 0; + return ret; } |