summaryrefslogtreecommitdiffhomepage
path: root/source.c
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2020-12-23 20:54:05 +0100
committerJo-Philipp Wich <jo@mein.io>2021-02-17 14:10:51 +0100
commit3756806674da909ec6dc10ad25862b592792604e (patch)
treef2af7e47f8444caaff0a5a33599f381889db24e3 /source.c
parent77580a893283f2bde7ab46496bd3a3d7b2fc6784 (diff)
treewide: rewrite ucode interpreter
Replace the former AST walking interpreter implementation with a single pass bytecode compiler and a corresponding virtual machine. The rewrite lays the groundwork for a couple of improvements with will be subsequently implemented: - Ability to precompile ucode sources into binary byte code - Strippable debug information - Reduced runtime memory usage Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'source.c')
-rw-r--r--source.c118
1 files changed, 118 insertions, 0 deletions
diff --git a/source.c b/source.c
new file mode 100644
index 0000000..21b9124
--- /dev/null
+++ b/source.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2021 Jo-Philipp Wich <jo@mein.io>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <string.h>
+
+#include "source.h"
+
+
+uc_source *
+uc_source_new_file(const char *path)
+{
+ FILE *fp = fopen(path, "rb");
+ uc_source *src;
+
+ if (!fp)
+ return NULL;
+
+ src = xalloc(ALIGN(sizeof(*src)) + strlen(path) + 1);
+ src->fp = fp;
+ src->buffer = NULL;
+ src->filename = strcpy((char *)src + ALIGN(sizeof(*src)), path);
+
+ src->usecount = 1;
+
+ src->lineinfo.count = 0;
+ src->lineinfo.entries = NULL;
+
+ return src;
+}
+
+uc_source *
+uc_source_new_buffer(const char *name, char *buf, size_t len)
+{
+ FILE *fp = fmemopen(buf, len, "rb");
+ uc_source *src;
+
+ if (!fp)
+ return NULL;
+
+ src = xalloc(ALIGN(sizeof(*src)) + strlen(name) + 1);
+ src->fp = fp;
+ src->buffer = buf;
+ src->filename = strcpy((char *)src + ALIGN(sizeof(*src)), name);
+
+ src->usecount = 1;
+
+ src->lineinfo.count = 0;
+ src->lineinfo.entries = NULL;
+
+ return src;
+}
+
+size_t
+uc_source_get_line(uc_source *source, size_t *offset)
+{
+ uc_lineinfo *lines = &source->lineinfo;
+ size_t i, pos = 0, line = 0, lastoff = 0;
+
+ for (i = 0; i < lines->count; i++) {
+ if (lines->entries[i] & 0x80) {
+ lastoff = pos;
+ line++;
+ pos++;
+ }
+
+ pos += (lines->entries[i] & 0x7f);
+
+ if (pos >= *offset) {
+ *offset -= lastoff - 1;
+
+ return line;
+ }
+ }
+
+ return 0;
+}
+
+uc_source *
+uc_source_get(uc_source *source)
+{
+ if (!source)
+ return NULL;
+
+ source->usecount++;
+
+ return source;
+}
+
+void
+uc_source_put(uc_source *source)
+{
+ if (!source)
+ return;
+
+ if (source->usecount > 1) {
+ source->usecount--;
+
+ return;
+ }
+
+ uc_vector_clear(&source->lineinfo);
+ fclose(source->fp);
+ free(source->buffer);
+ free(source);
+}