summaryrefslogtreecommitdiffhomepage
path: root/ast.c
diff options
context:
space:
mode:
Diffstat (limited to 'ast.c')
-rw-r--r--ast.c694
1 files changed, 0 insertions, 694 deletions
diff --git a/ast.c b/ast.c
deleted file mode 100644
index 5715afb..0000000
--- a/ast.c
+++ /dev/null
@@ -1,694 +0,0 @@
-/*
- * Copyright (C) 2020 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 "ast.h"
-#include "lib.h"
-#include "lexer.h"
-#include "parser.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <math.h>
-#include <regex.h>
-
-static size_t uc_ext_types_count = 0;
-static struct uc_extended_type *uc_ext_types = NULL;
-
-uint32_t
-uc_new_op(struct uc_state *s, int type, struct json_object *val, ...)
-{
- struct uc_op *newop;
- uint32_t child;
- int n_op = 0;
- va_list ap;
-
- if ((s->poolsize + 1) == UINT32_MAX) {
- fprintf(stderr, "Program too large\n");
- exit(127);
- }
-
- s->pool = xrealloc(s->pool, (s->poolsize + 1) * sizeof(*newop));
-
- newop = &s->pool[s->poolsize];
- memset(newop, 0, sizeof(*newop));
-
- newop->is_first = !s->poolsize;
- newop->is_op = true;
- newop->type = type;
- newop->val = val;
-
- va_start(ap, val);
-
- while (n_op < OPn_NUM && (child = va_arg(ap, uint32_t)) != UINT32_MAX)
- newop->tree.operand[n_op++] = child;
-
- va_end(ap);
-
- return s->poolsize++;
-}
-
-uint32_t
-uc_wrap_op(struct uc_state *state, uint32_t parent, ...)
-{
- uint32_t child;
- int n_op = 0;
- va_list ap;
-
- va_start(ap, parent);
-
- while (n_op < OPn_NUM && (child = va_arg(ap, uint32_t)) != UINT32_MAX)
- OPn(parent, n_op++) = child;
-
- va_end(ap);
-
- return parent;
-}
-
-uint32_t
-uc_append_op(struct uc_state *state, uint32_t a, uint32_t b)
-{
- uint32_t tail_off, next_off;
-
- for (tail_off = a, next_off = OP_NEXT(tail_off);
- next_off != 0;
- tail_off = next_off, next_off = OP_NEXT(next_off))
- ;
-
- OP_NEXT(tail_off) = b;
-
- return a;
-}
-
-static int
-double_rounded_to_string(struct json_object *v, struct printbuf *pb, int level, int flags)
-{
- bool strict = (level > 0) || (flags & JSON_C_TO_STRING_STRICT);
- double d = json_object_get_double(v);
-
- if (isnan(d))
- return sprintbuf(pb, strict ? "\"NaN\"" : "NaN");
-
- if (d == INFINITY)
- return sprintbuf(pb, strict ? "1e309" : "Infinity");
-
- if (d == -INFINITY)
- return sprintbuf(pb, strict ? "-1e309" : "-Infinity");
-
- return sprintbuf(pb, "%g", d);
-}
-
-struct json_object *
-uc_new_double(double v)
-{
- struct json_object *d = json_object_new_double(v);
-
- if (!d) {
- fprintf(stderr, "Out of memory\n");
- abort();
- }
-
- json_object_set_serializer(d, double_rounded_to_string, NULL, NULL);
-
- return d;
-}
-
-static int
-null_obj_to_string(struct json_object *v, struct printbuf *pb, int level, int flags)
-{
- return sprintbuf(pb, "null");
-}
-
-struct json_object *
-uc_new_null(void)
-{
- struct json_object *d = json_object_new_boolean(false);
-
- if (!d) {
- fprintf(stderr, "Out of memory\n");
- abort();
- }
-
- json_object_set_serializer(d, null_obj_to_string, NULL, NULL);
-
- return d;
-}
-
-static void
-obj_free(struct json_object *v, void *ud)
-{
- struct uc_op *op = json_object_get_userdata(v);
-
- json_object_put(op->tag.proto);
- free(ud);
-}
-
-struct json_object *
-uc_new_object(struct json_object *proto) {
- struct json_object *val = xjs_new_object();
- struct uc_op *op = xalloc(sizeof(*op));
-
- op->val = val;
- op->type = T_LBRACE;
- op->tag.proto = json_object_get(proto);
-
- json_object_set_serializer(val, NULL, op, obj_free);
-
- return op->val;
-}
-
-static void
-re_free(struct json_object *v, void *ud)
-{
- struct uc_op *op = ud;
-
- regfree((regex_t *)op->tag.data);
- free(op);
-}
-
-static int
-re_to_string(struct json_object *v, struct printbuf *pb, int level, int flags)
-{
- bool strict = (level > 0) || (flags & JSON_C_TO_STRING_STRICT);
- struct uc_op *op = json_object_get_userdata(v);
- struct json_object *s;
- const char *p;
- size_t len;
-
- sprintbuf(pb, "%s/", strict ? "\"" : "");
-
- s = xjs_new_string((char *)op + sizeof(*op) + sizeof(regex_t));
-
- if (strict)
- for (p = json_object_to_json_string(s) + 1, len = strlen(p) - 1; len > 0; len--, p++)
- sprintbuf(pb, "%c", *p);
- else
- sprintbuf(pb, "%s", json_object_get_string(s));
-
- json_object_put(s);
-
- return sprintbuf(pb, "/%s%s%s%s",
- op->is_reg_global ? "g" : "",
- op->is_reg_icase ? "i" : "",
- op->is_reg_newline ? "s" : "",
- strict ? "\"" : "");
-}
-
-struct json_object *
-uc_new_regexp(const char *source, bool icase, bool newline, bool global, char **err) {
- int cflags = REG_EXTENDED, res;
- struct uc_op *op;
- regex_t *re;
- size_t len;
-
- op = xalloc(sizeof(*op) + sizeof(*re) + strlen(source) + 1);
- re = (regex_t *)((char *)op + sizeof(*op));
- strcpy((char *)op + sizeof(*op) + sizeof(*re), source);
-
- if (icase)
- cflags |= REG_ICASE;
-
- if (newline)
- cflags |= REG_NEWLINE;
-
- op->type = T_REGEXP;
- op->tag.data = re;
- op->is_reg_icase = icase;
- op->is_reg_global = global;
- op->is_reg_newline = newline;
-
- res = regcomp(re, source, cflags);
-
- if (res != 0) {
- len = regerror(res, re, NULL, 0);
- *err = xalloc(len);
-
- regerror(res, re, *err, len);
- free(op);
-
- return NULL;
- }
-
- op->val = xjs_new_object();
-
- if (!op->val) {
- free(op);
-
- return NULL;
- }
-
- json_object_set_serializer(op->val, re_to_string, op, re_free);
-
- return op->val;
-}
-
-static void
-func_free(struct json_object *v, void *ud)
-{
- struct uc_op *op = ud;
- struct uc_function *fn = op->tag.data;
-
- json_object_put(fn->args);
- uc_release_scope(fn->parent_scope);
-
- free(op);
-}
-
-static int
-func_to_string(struct json_object *v, struct printbuf *pb, int level, int flags)
-{
- bool strict = (level > 0) || (flags & JSON_C_TO_STRING_STRICT), rest;
- struct uc_op *op = json_object_get_userdata(v);
- struct uc_function *fn = op->tag.data;
- size_t i, len;
-
- if (op->is_arrow)
- sprintbuf(pb, "%s(", strict ? "\"" : "");
- else
- sprintbuf(pb, "%sfunction%s%s(",
- strict ? "\"" : "",
- fn->name ? " " : "",
- fn->name ? fn->name : "");
-
- if (fn->args) {
- len = json_object_array_length(fn->args);
- rest = (len > 1) && json_object_is_type(json_object_array_get_idx(fn->args, len - 1), json_type_null);
-
- for (i = 0; i < len - rest; i++) {
- sprintbuf(pb, "%s%s%s",
- i ? ", " : "",
- rest && i == len - 2 ? "..." : "",
- json_object_get_string(json_object_array_get_idx(fn->args, i)));
- }
- }
-
- return sprintbuf(pb, ") %s{ ... }%s",
- op->is_arrow ? "=> " : "",
- strict ? "\"" : "");
-}
-
-struct json_object *
-uc_new_func(struct uc_state *state, uint32_t decl, struct uc_scope *scope)
-{
- struct json_object *val = xjs_new_object();
- uint32_t name_off, args_off, arg_off;
- struct uc_function *fn;
- struct uc_op *op;
- size_t sz;
-
- sz = ALIGN(sizeof(*op)) + ALIGN(sizeof(*fn));
-
- name_off = OPn(decl, 0);
- args_off = OPn(decl, 1);
-
- if (name_off)
- sz += ALIGN(json_object_get_string_len(OP_VAL(name_off)) + 1);
-
- op = xalloc(sz);
-
- fn = (void *)op + ALIGN(sizeof(*op));
- fn->entry = OPn(decl, 2);
-
- if (name_off)
- fn->name = strcpy((char *)fn + ALIGN(sizeof(*fn)), json_object_get_string(OP_VAL(name_off)));
-
- if (args_off) {
- fn->args = xjs_new_array();
-
- for (arg_off = args_off; arg_off != 0; arg_off = OP_NEXT(arg_off)) {
- json_object_array_add(fn->args, json_object_get(OP_VAL(arg_off)));
-
- /* if the last argument is a rest one (...arg), add extra null entry */
- if (OP_IS_ELLIP(arg_off)) {
- json_object_array_add(fn->args, NULL);
- break;
- }
- }
- }
-
- fn->source = state->function ? state->function->source : NULL;
- fn->parent_scope = uc_acquire_scope(scope);
-
- op->val = val;
- op->type = T_FUNC;
- op->is_arrow = (OP_TYPE(decl) == T_ARROW);
- op->tag.data = fn;
-
- json_object_set_serializer(val, func_to_string, op, func_free);
-
- return op->val;
-}
-
-static void
-exception_free(struct json_object *v, void *ud)
-{
- free(ud);
-}
-
-static int
-exception_to_string(struct json_object *v, struct printbuf *pb, int level, int flags)
-{
- return sprintbuf(pb, "%s", json_object_get_string(json_object_object_get(v, "message")));
-}
-
-static void
-add_stacktrace(struct json_object *a, struct uc_function *function, size_t off) {
- struct json_object *o = xjs_new_object();
- size_t line = 1, rlen = 0, len;
- bool truncated = false;
- char buf[256];
-
- if (function->source->filename)
- json_object_object_add(o, "filename", xjs_new_string(function->source->filename));
-
- if (function->name)
- json_object_object_add(o, "function", xjs_new_string(function->name));
-
- if (function->source->fp) {
- fseek(function->source->fp, 0, SEEK_SET);
-
- while (fgets(buf, sizeof(buf), function->source->fp)) {
- len = strlen(buf);
- rlen += len;
-
- if (rlen > off) {
- json_object_object_add(o, "line", xjs_new_int64(line));
- json_object_object_add(o, "byte", xjs_new_int64(len - (rlen - off) + (truncated ? sizeof(buf) : 0) + 1));
- break;
- }
-
- truncated = (len > 0 && buf[len-1] != '\n');
- line += !truncated;
- }
- }
-
- json_object_array_add(a, o);
-}
-
-__attribute__((format(printf, 3, 4))) struct json_object *
-uc_new_exception(struct uc_state *s, uint32_t off, const char *fmt, ...)
-{
- struct uc_callstack *callstack, *prevcall, here = {};
- struct json_object *a;
- struct uc_op *op;
- va_list ap;
- char *p;
- int len;
-
- op = xalloc(sizeof(*op));
- op->type = T_EXCEPTION;
- op->val = xjs_new_object();
- op->off = off;
- op->tag.data = s->function ? s->function->source : s->source;
-
- a = xjs_new_array();
-
- here.next = s->callstack;
- here.function = s->function;
- here.off = off;
-
- for (callstack = &here, prevcall = NULL; callstack != NULL;
- prevcall = callstack, callstack = callstack->next)
- if (callstack->off && callstack->function && callstack->function->source &&
- (!prevcall || callstack->function != prevcall->function || callstack->off != prevcall->off))
- add_stacktrace(a, callstack->function, callstack->off);
-
- json_object_object_add(op->val, "stacktrace", a);
-
- va_start(ap, fmt);
- len = xvasprintf(&p, fmt, ap);
- va_end(ap);
-
- json_object_object_add(op->val, "message", xjs_new_string_len(p, len));
- free(p);
-
- if (s->exception)
- json_object_put(s->exception);
-
- s->exception = op->val;
-
- json_object_set_serializer(op->val, exception_to_string, op, exception_free);
-
- return json_object_get(op->val);
-}
-
-static void
-scope_free(struct json_object *v, void *ud)
-{
- struct uc_scope *sc = ud;
-
- if (sc->parent) {
- uc_release_scope(json_object_get_userdata(sc->parent));
- sc->parent = NULL;
- }
-
- sc->scope = NULL;
-}
-
-void
-uc_release_scope(struct uc_scope *sc)
-{
- if (sc->refs == 0)
- abort();
-
- sc->refs--;
-
- if (sc->refs == 0)
- json_object_put(sc->scope);
-}
-
-struct uc_scope *
-uc_acquire_scope(struct uc_scope *sc)
-{
- sc->refs++;
-
- return sc;
-}
-
-struct uc_scope *
-uc_new_scope(struct uc_state *s, struct uc_scope *parent)
-{
- struct uc_scope *sc;
-
- sc = xalloc(sizeof(*sc));
- sc->scope = xjs_new_object();
-
- if (parent)
- sc->parent = uc_acquire_scope(parent)->scope;
-
- json_object_set_userdata(sc->scope, sc, scope_free);
-
- sc->next = s->scopelist;
- s->scopelist = sc;
-
- return uc_acquire_scope(sc);
-}
-
-struct uc_scope *
-uc_parent_scope(struct uc_scope *scope)
-{
- return json_object_get_userdata(scope->parent);
-}
-
-static void
-uc_reset(struct uc_state *s)
-{
- json_object_put(s->exception);
- s->exception = NULL;
-
- free(s->lex.lookbehind);
- free(s->lex.buf);
- memset(&s->lex, 0, sizeof(s->lex));
-}
-
-void
-uc_free(struct uc_state *s)
-{
- struct uc_source *src, *src_next;
- struct uc_scope *sc, *sc_next;
- struct json_object *scj;
- size_t n;
-
- if (s) {
- json_object_put(s->ctx);
-
- for (n = 0; n < s->poolsize; n++)
- json_object_put(s->pool[n].val);
-
- free(s->pool);
-
- s->pool = NULL;
- s->poolsize = 0;
-
- uc_reset(s);
-
- json_object_put(s->rval);
-
- for (sc = s->scopelist; sc; sc = sc->next) {
- scj = sc->scope;
- sc->scope = NULL;
- json_object_put(scj);
- }
-
- for (sc = s->scopelist; sc; sc = sc_next) {
- sc_next = sc->next;
- free(sc);
- }
-
- for (src = s->sources; src; src = src_next) {
- src_next = src->next;
-
- if (src->fp)
- fclose(src->fp);
-
- free(src->filename);
- free(src);
- }
- }
-
- while (uc_ext_types_count > 0)
- json_object_put(uc_ext_types[--uc_ext_types_count].proto);
-
- free(uc_ext_types);
- free(s);
-}
-
-struct json_object *
-uc_parse(struct uc_state *state, FILE *fp)
-{
- void *pParser;
- uint32_t off;
-
- uc_reset(state);
-
- pParser = ParseAlloc(xalloc);
-
- while (state->lex.state != UT_LEX_EOF) {
- off = uc_get_token(state, fp);
-
- if (state->exception)
- goto out;
-
- if (off)
- Parse(pParser, OP_TYPE(off), off, state);
-
- if (state->exception)
- goto out;
- }
-
- Parse(pParser, 0, 0, state);
-
-out:
- ParseFree(pParser, free);
-
- return state->exception;
-}
-
-bool
-uc_register_extended_type(const char *name, struct json_object *proto, void (*freefn)(void *))
-{
- uc_ext_types = xrealloc(uc_ext_types, (uc_ext_types_count + 1) * sizeof(*uc_ext_types));
- uc_ext_types[uc_ext_types_count].name = name;
- uc_ext_types[uc_ext_types_count].free = freefn;
- uc_ext_types[uc_ext_types_count].proto = proto;
- uc_ext_types_count++;
-
- return true;
-}
-
-static int
-uc_extended_type_to_string(struct json_object *v, struct printbuf *pb, int level, int flags)
-{
- bool strict = (level > 0) || (flags & JSON_C_TO_STRING_STRICT);
- struct uc_op *op = json_object_get_userdata(v);
- struct uc_extended_type *et;
-
- if (!op)
- return 0;
-
- et = &uc_ext_types[op->tag.type - 1];
-
- return sprintbuf(pb, "%s<%s %p>%s",
- strict ? "\"" : "",
- et->name, op->tag.data,
- strict ? "\"" : "");
-}
-
-static void
-uc_extended_type_free(struct json_object *v, void *ud)
-{
- struct uc_op *op = json_object_get_userdata(v);
- struct uc_extended_type *et;
-
- if (!op)
- return;
-
- et = &uc_ext_types[op->tag.type - 1];
-
- if (et->free && op->tag.data)
- et->free(op->tag.data);
-
- json_object_put(op->tag.proto);
- free(ud);
-}
-
-struct json_object *
-uc_set_extended_type(struct json_object *v, const char *name, void *data)
-{
- struct uc_extended_type *et = NULL;
- struct uc_op *op;
- size_t n;
-
- for (n = 0; n < uc_ext_types_count; n++) {
- if (!strcmp(name, uc_ext_types[n].name)) {
- et = &uc_ext_types[n];
- break;
- }
- }
-
- if (!et)
- return NULL;
-
- op = xalloc(sizeof(*op));
- op->val = v;
- op->type = T_RESSOURCE;
- op->tag.proto = json_object_get(et->proto);
- op->tag.type = n + 1;
- op->tag.data = data;
-
- json_object_set_serializer(op->val, uc_extended_type_to_string, op, uc_extended_type_free);
-
- return op->val;
-}
-
-void **
-uc_get_extended_type(struct json_object *v, const char *name)
-{
- struct uc_op *op = json_object_get_userdata(v);
- size_t n = op ? op->tag.type : 0;
- struct uc_extended_type *et;
-
- if (!op || op->type != T_RESSOURCE || n == 0 || n > uc_ext_types_count)
- return NULL;
-
- et = &uc_ext_types[n - 1];
-
- if (name && strcmp(et->name, name))
- return NULL;
-
- return &op->tag.data;
-}