diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md new file mode 100644 index 00000000..3230256c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -0,0 +1,27 @@ +--- +name: Bug report +about: Create a report to help us improve + +--- + +The following program `sample.go` triggers a panic: + +```go +package main + +func main() { +// add a sample +} +``` + +Expected result: +```console +$ go run ./sample.go +// ouput +``` + +Got: +```console +$ dyngo ./sample.go +// ouput +``` diff --git a/Makefile b/Makefile index b5f77497..20904e76 100644 --- a/Makefile +++ b/Makefile @@ -13,4 +13,9 @@ gen_all_syscall: cmd/goexports/goexports cmd/goexports/goexports: cmd/goexports/goexports.go go generate cmd/goexports/goexports.go -.PHONY: check gen_all_syscall +gen_tests: + make -C _test + +generate: gen_all_syscall cmd/goexports/goexports gen_tests + +.PHONY: check gen_all_syscall gen_tests diff --git a/_gi_c/Makefile b/_gi_c/Makefile deleted file mode 100644 index 4dd0315b..00000000 --- a/_gi_c/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -sys = $(shell uname -s) - -CPPFLAGS ?= -Wall -Ideps/include -CFLAGS ?= -g - -# Linux linker requires rpath set if lib is not in default path -Linux_LDFLAGS = -Wl,-rpath=$(CURDIR)/deps/lib - -LDFLAGS ?= $($(sys)_LDFLAGS) -Ldeps/lib -llightning - -all: deps gi l2 loop2 - -gi: gi.o graph.o hash.o init_go.o node.o parse_go.o run_cfg.o run_jit.o scan.o - -l2: l2.go - go build -o l2 l2.go - -loop2: loop2.go - go build -o loop2 loop2.go - -test: gi - ./gi -acx loop2.go - -deps: - $(MAKE) -C deps - -clean: - rm -f *.o gi loop2 l2 - -.PHONY: deps clean diff --git a/_gi_c/README.md b/_gi_c/README.md deleted file mode 100644 index 1f85081d..00000000 --- a/_gi_c/README.md +++ /dev/null @@ -1,23 +0,0 @@ -# gi_c - -Proof of concept for a go interpreter, using previous private works - -# Install - -dependencies: graphviz for AST / CFG visualization - -``` -make -make test -``` - -# Notes - -Language scope is very limited, just enough to run the demo script `loop2.go`. Interesting enough to get an idea of performances compared with binaries, with or without JIT compilation. - -the machine code generator is using GNU-lightning (installed with `make deps`). - -Do not expect many improvements here, the real work will take place in Go, and will try to reuse as much as possible existing Go assets. - --- -Marc diff --git a/_gi_c/deps/Makefile b/_gi_c/deps/Makefile deleted file mode 100644 index ab3a6783..00000000 --- a/_gi_c/deps/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# Build and install dependencies - -build: - for dep in *.makefile; do make -f $$dep build; done - -clean: - for dep in *.makefile; do make -f $$dep clean; done diff --git a/_gi_c/deps/deps.mk b/_gi_c/deps/deps.mk deleted file mode 100644 index 7e097413..00000000 --- a/_gi_c/deps/deps.mk +++ /dev/null @@ -1,24 +0,0 @@ -# fetch, build and install a dependency -# Just include this file and provide URL variable with the source location - -TGZ ?= $(notdir $(URL)) -DIR ?= $(shell a=$(TGZ); echo $${a%.t*z}) -DEST = $(CURDIR) - -all: build - -build: $(DIR)/.build_ok - -clean: - rm -rf $(DIR) - -$(DIR)/.build_ok: $(DIR) - cd $(DIR) && ./configure --prefix=$(DEST) && make && make install - touch $(DIR)/.build_ok - -$(DIR): $(TGZ) - tar xvfz $(TGZ) || { rm -rf $(DIR); false; } - -$(TGZ): - curl -L -o $@.tmp $(URL) - mv $@.tmp $@ diff --git a/_gi_c/deps/lightning.makefile b/_gi_c/deps/lightning.makefile deleted file mode 100644 index 340684ac..00000000 --- a/_gi_c/deps/lightning.makefile +++ /dev/null @@ -1,3 +0,0 @@ -URL = http://ftp.gnu.org/gnu/lightning/lightning-2.1.2.tar.gz - -include deps.mk diff --git a/_gi_c/gi.c b/_gi_c/gi.c deleted file mode 100644 index 79d0e57c..00000000 --- a/_gi_c/gi.c +++ /dev/null @@ -1,135 +0,0 @@ -/* a go interpreter */ - -#define VERSION "gi-c-0.1" - -static const char man_txt[] = -"NAME\n" -" gi - go interpreter\n" -"SYNOPSIS\n" -" gi [-acnsVx] [-A ast_file] [-C cfg_file] [--] [script_file [args ...]]\n" -"DESCRIPTION\n" -" gi is an interpreter that executes commands read from a file or the\n" -" standard input.\n" -"OPTIONS\n" -" -A ast_file \n" -" Write the abstract syntax tree in dot(1) format to ast_file or\n" -" standard output if ast_file is -\n" -" -a Display AST graph using dotty(1)\n" -" -C cfg_file \n" -" Write the control flow graph in dot(1) format to cfg_file or\n" -" standard output if cfg_file is -\n" -" -c Display CFG graph using dotty(1)\n" -" -n Compile only, do not run\n" -" -x Generate and execute machine code using a JIT compiler\n" -" -v Trace each instruction during execution\n" -" -V Print interpreter version and exit\n" -"BIP LANGUAGE\n" -" Commands are read in terms of lines of words separated by whitespaces\n" -" (blanks or tabs) and certain sequences of characters called ``operators''.\n" -" commands may also be separated by ';' or grouped between braces into a\n" -" list\n" -" OPERATORS\n" -" Bip uses the usual infix notation for operators (example: c = a + b).\n" -" Precedence rules identical to C are applied. Parenthesis are used to\n" -" group expression and make precedence explicit.\n" -" + - * / % \n" -" Arithmetic: addition, substraction, multiplication, division\n" -" and modulo.\n" -" < <= > >= == != \n" -" Comparison: lower, lower or equal, greater, greater or equal,\n" -" equal, not equal.\n" -" ! && || \n" -" Logical: not, and, or.\n" -" = Assignement.\n" -" << >> & | \n" -" Binary: left shift, right shift, boolean and, boolean or.\n" -" FLOW CONTROL\n" -" if cond list1 [else list0] \n" -" the cond is executed and if it returns a non zero value, list1\n" -" is executed. Otherwise, if defined, list0 is executed.\n" -" while cond list \n" -" cond and list are repeatedly executed while cond returns non zero.\n" -"AUTHORS\n" -" MV\n" -; - -#include -#include -#include -#include - -#include "init_go.h" -#include "trace.h" - -#define MSIZE 4096 - -int source_stream(bip_t *ip, FILE *fd) -{ - int len = 0, max = 0; - char *src = NULL; - - while (len == max) { /* Grow src buffer until everything is read */ - max += MSIZE; - src = (char *)realloc(src, max); - len += fread(src + len, 1, MSIZE, fd); - } - src[len] = 0; - eval_str(ip, NULL, src, len); - printf("%s", ip->out); - ip->out[0] = 0; - free(src); - return len; -} - -int main(int argc, char *argv[], char *env[]) -{ - int opt; - bip_t *ip = bip_init(0); - FILE *fd; - - while ((opt = getopt(argc, argv, "A:aC:chnpVvx")) != -1) { - switch (opt) { - case 'A': - ip->fd_ast = strcmp(optarg, "-") ? - fopen(optarg, "w") : stdout; - break; - case 'a': - ip->opt.a = 1; - break; - case 'C': - ip->fd_cfg = strcmp(optarg, "-") ? - fopen(optarg, "w") : stdout; - break; - case 'c': - ip->opt.c = 1; - break; - case 'h': - printf("%s", man_txt); - exit(0); - case 'n': - ip->opt.n = 1; - break; - case 'p': - ip->opt.p = 1; - break; - case 'v': - ip->opt.v = 1; - break; - case 'V': - printf("%s\n", VERSION); - exit(0); - case 'x': - ip->opt.x = 1; - break; - default: - fprintf(stderr, "Usage: b1 [-acnVvx] [-A astname] " - "[-C fgname] [file]\n"); - exit(1); - } - } - fd = ((argc - optind) > 0) ? fopen(argv[optind], "r") : stdin; - if (fd == NULL) - return 1; - while (source_stream(ip, fd)); - return 0; -} diff --git a/_gi_c/graph.c b/_gi_c/graph.c deleted file mode 100644 index 45432f0d..00000000 --- a/_gi_c/graph.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Generate a serial control flow graph from an abstract syntax tree - */ -#include - -#include "node.h" -#include "trace.h" - -static node_t *add_cond_branch(bip_t *ip, node_t *n) -{ - node_t *node = (node_t *)calloc(1, sizeof(node_t)); - node->type = COND_BRANCH; - node->num = ++ip->nc; - node->pv = n->pv; - node->sym = getsym(ip, "CB", 2); - node->f = node->sym->f; - return node; -} - -static void cfg_out(bip_t *ip, node_t *node, void *data) -{ - int i; - node_t *n; - - switch ((int)node->type) { - case FUN: case OP: case OPS: case SL: - for (i = 0; i < node->nchild; i++) { - if (!is_leaf(node->child[i])) { - node->start = node->child[i]->start; - break; - } - } - if (!node->start) - node->start = node; - for (i = 1; i < node->nchild; i++) { - node->child[i-1]->snext = node->child[i]->start; - } - for (i = node->nchild - 1; i >= 0; i--) { - if (!is_leaf(node->child[i])) { - node->child[i]->snext = node; - break; - } - } - break; - case IF: - node->start = node->child[0]->start; - node->child[1]->snext = node; - if (node->nchild == 3) { - node->child[2]->snext = node; - } - n = add_cond_branch(ip, node->child[0]); - node->child[0]->snext = n; - n->next[TRUE] = node->child[1]->start; - if (node->nchild == 3) { - n->next[FALSE] = node->child[2]->start; - } else { - n->next[FALSE] = node; - } - break; - case WHILE: - node->start = node->child[0]->start; - node->child[1]->snext = node->start; - n = add_cond_branch(ip, node->child[0]); - node->child[0]->snext = n; - n->next[TRUE] = node->child[1]->start; - n->next[FALSE] = node; - break; - case FOR: - node->start = node->child[0]->start; - node->child[0]->snext = node->child[1]->start; - n = add_cond_branch(ip, node->child[1]); - node->child[1]->snext = n; - n->next[TRUE] = node->child[3]->start; - n->next[FALSE] = node; - node->child[3]->snext = node->child[2]->start; - node->child[2]->snext = node->child[1]->start; - break; - default: - ; //t_s(nodetype[node->type]); - } -} - -void ast2cfg(bip_t *ip, node_t *node) -{ - tree_walk(ip, node, NULL, cfg_out, NULL); - addentry(ip, node->start); -} diff --git a/_gi_c/graph.h b/_gi_c/graph.h deleted file mode 100644 index 28044a68..00000000 --- a/_gi_c/graph.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef GRAPH_H -#define GRAPH_H - -#include "node.h" - -void ast2cfg(bip_t *ip, node_t *node); - -#endif /* GRAPH_H */ diff --git a/_gi_c/hash.c b/_gi_c/hash.c deleted file mode 100644 index 6a6a33bc..00000000 --- a/_gi_c/hash.c +++ /dev/null @@ -1,102 +0,0 @@ -#include - -#include "hash.h" - -hash_t *hinit(unsigned int n, cmpfun_t cmpf) -{ - hash_t *h = (hash_t *)malloc(sizeof(hash_t)); - h->htab = (hitem_t **)calloc(n, sizeof(hitem_t *)); - h->cmpf = cmpf; - h->len = n; - h->nhash = 0; - return h; -} - -static void hresize(hash_t *h, unsigned int n) -{ - unsigned int i, j; - hitem_t *p, *pp, **tab = (hitem_t **)calloc(n, sizeof(hitem_t *)); - - for (i = 0; i < h->len; i++) { - p = h->htab[i]; - while (p) { - pp = p->next; - j = p->key % n; - p->next = tab[j]; - tab[j] = p; - p = pp; - } - } - free(h->htab); - h->htab = tab; - h->len = n; -} - -unsigned int hkey(char *s) -{ - unsigned int h = 0; - while (*s) - h = h * 31 + *s++; - return h; -} - -unsigned int hnkey(const char *s, int n, unsigned int h) -{ - while (n--) - h = h * 31 + *s++; - return h; -} - -void *hadd(hash_t *h, unsigned int key, void *index, void *data) -{ - hitem_t *p; - unsigned int i; - - if (h->nhash >= h->len && h->len < HNITEM_MAX) - hresize(h, h->len * 2); - p = (hitem_t *)malloc(sizeof(hitem_t)); - i = key < h->len ? key : key % h->len; - p->key = key; - p->data = data; - p->index = index; - p->next = h->htab[i]; - h->htab[i] = p; - h->nhash++; - return data; -} - -void *hdel(hash_t *h, hitem_t *item) -{ - unsigned int i = item->key % h->len; - hitem_t *p = h->htab[i]; - void *data = item->data; - - if (p == item) { - h->htab[i] = p->next; - goto del; - } - for (; p; p = p->next) - if (p->next == item) { - p->next = p->next->next; - goto del; - } - return (void *)-1; -del: h->nhash--; - free(item); - return data; -} - -void *hlookup(hash_t *h, unsigned int key, void *data, int len) -{ - hitem_t *p; - unsigned int i = key < h->len ? key : key % h->len; - for (p = h->htab[i]; p; p = p->next) { - if (p->key == key) { - if (data && h->cmpf && (*h->cmpf)(data, p->data, len)) - continue; /* key collision */ - else - return p->data; - } - } - return NULL; -} diff --git a/_gi_c/hash.h b/_gi_c/hash.h deleted file mode 100644 index b979a8dd..00000000 --- a/_gi_c/hash.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef HASH_H -#define HASH_H - -/* hash item */ -typedef struct hitem_t { - struct hitem_t *next; /* next item in same slot */ - void *index; /* pointer to index data */ - void *data; /* pointer to value data */ - unsigned int key; /* hash key, obtained from index */ -} hitem_t; - -/* key hash comparison function type */ -typedef int (*cmpfun_t)(void *, void *, int); - -/* dynamically resizable array / hash table */ -typedef struct hash_t { - hitem_t **htab; /* hash slots */ - cmpfun_t cmpf; /* user provided key comparison function */ - unsigned int len; /* tab size */ - unsigned int nhash; /* number of hashed items */ -} hash_t; - -/* hash table iterator */ -#define hforeach(h, i, c) \ - for (c = 0; (unsigned int)c < (h)->len; c++) \ - for (i = (h)->htab[c]; i; i = i->next) - -#define HNITEM_MAX ((unsigned)(1 << (8 * sizeof(int) -1))) /* 2^31 on 32 bit */ - -hash_t *hinit(unsigned int n, cmpfun_t cmpf); -unsigned int hkey(char *s); -unsigned int hnkey(const char *s, int n, unsigned int h); -void *hadd(hash_t *h, unsigned int key, void *index, void *data); -void *hdel(hash_t *h, hitem_t *item); -void *hlookup(hash_t *h, unsigned int key, void *data, int len); - -#endif /* HASH_H */ diff --git a/_gi_c/init_go.c b/_gi_c/init_go.c deleted file mode 100644 index fef42d80..00000000 --- a/_gi_c/init_go.c +++ /dev/null @@ -1,133 +0,0 @@ -#include -#include - -#include "graph.h" -#include "node.h" -#include "parse_go.h" -#include "run_cfg.h" -#include "run_jit.h" -#include "scan.h" - -#define X4_scan_bad scan_bad, scan_bad, scan_bad, scan_bad -#define X16_scan_bad X4_scan_bad, X4_scan_bad, X4_scan_bad, X4_scan_bad -#define X64_scan_bad X16_scan_bad, X16_scan_bad, X16_scan_bad, X16_scan_bad - -/* BIP language lexical table */ - -static const scan_fun_t scanfun[256] = { - scan_bad, scan_bad, scan_bad, scan_bad, scan_bad, // NUL SOH STX ETX EOT - scan_bad, scan_bad, scan_bad, scan_bad, scan_wsep, // ENQ ACQ BELL BS HT - scan_csep, scan_bad, scan_bad, scan_csep, scan_bad, // LF VT FF CR SO - scan_bad, scan_bad, scan_bad, scan_bad, scan_bad, // SI DLE DC1 DC2 DC3 - scan_bad, scan_bad, scan_bad, scan_bad, scan_bad, // DC4 NAK SYN ETB CAN - scan_bad, scan_bad, scan_bad, scan_bad, scan_bad, // EM SUB ESC FS GS - scan_bad, scan_bad, scan_wsep, scan_go_op, scan_str, // RS US ' ' ! " - scan_cmt, scan_go_op, scan_go_op, scan_go_op, scan_go_op, // # $ % & ' - scan_paren, scan_bad, scan_go_op, scan_go_op, scan_lsep, // ( ) * + , - scan_go_op, scan_go_op, scan_go_op, scan_num, scan_num, // - . / 0 1 - scan_num, scan_num, scan_num, scan_num, scan_num, // 2 3 4 5 6 - scan_num, scan_num, scan_num, scan_go_op, scan_csep, // 7 8 9 : ; - scan_go_op, scan_go_op, scan_go_op, scan_go_op, scan_go_op, // < = > ? @ - scan_id, scan_id, scan_id, scan_id, scan_id, // A B C D E - scan_id, scan_id, scan_id, scan_id, scan_id, // F G H I J - scan_id, scan_id, scan_id, scan_id, scan_id, // K L M N O - scan_id, scan_id, scan_id, scan_id, scan_id, // P Q R S T - scan_id, scan_id, scan_id, scan_id, scan_id, // U V W X Y - scan_id, scan_bracket, scan_bad, scan_bad, scan_go_op, // Z [ \ ] ^ - scan_id, scan_go_op, scan_id, scan_id, scan_id, // _ ` a b c - scan_id, scan_id, scan_id, scan_id, scan_id, // d e f g h - scan_id, scan_id, scan_id, scan_id, scan_id, // i j k l m - scan_id, scan_id, scan_id, scan_id, scan_id, // n o p q r - scan_id, scan_id, scan_id, scan_id, scan_id, // s t u v w - scan_id, scan_id, scan_id, scan_brace, scan_go_op, // x y z { | - scan_bad, scan_go_op, scan_bad, // } ~ DEL - X64_scan_bad, X64_scan_bad // Non ASCII -}; - -static int cmpsym(void *data, void *sym, int n) -{ - return strncmp((char *)data, ((sym_t *)sym)->name, n); -} - -bip_t *bip_init(int trace_opt) -{ - bip_t *ip = (bip_t *)calloc(1, sizeof(*ip)); - - ip->scanfun = (scan_fun_t *)scanfun; - ip->gsym = hinit(64, cmpsym); - ip->lsym = hinit(16, cmpsym); - newsym(ip->gsym, "if", IF, 0, nop, j_nop); - newsym(ip->gsym, "break", BREAK, 0, NULL, j_nop); - newsym(ip->gsym, "continue", CONTINUE, 0, NULL, j_nop); - newsym(ip->gsym, "for", FOR, 0, nop, j_nop); - newsym(ip->gsym, "func", DEF, 0, NULL, j_nop); - newsym(ip->gsym, "return", RETURN, 0, NULL, j_nop); - newsym(ip->gsym, "local", LOCAL, 0, NULL, j_nop); - newsym(ip->gsym, "eval", FUN, 0, NULL, j_nop); - newsym(ip->gsym, "print", FUN, 0, NULL, j_nop); - newsym(ip->gsym, "println", FUN, 0, echo, j_echo); - newsym(ip->gsym, "source", FUN, 0, NULL, j_nop); - newsym(ip->gsym, "dsym", FUN, 0, NULL, j_nop); - newsym(ip->gsym, "map", FUN, 0, NULL, j_nop); - newsym(ip->gsym, "nop", OP, 0, nop, j_nop); - newsym(ip->gsym, "SL", SL, 0, nop, j_nop); - newsym(ip->gsym, "CB", COND_BRANCH, 0, cond_branch, j_nop); - newsym(ip->gsym, "package", NAMESPACE, 0, nop, j_nop); - newsym(ip->gsym, "++", OPS, 0, inc, j_inc); - newsym(ip->gsym, "--", OPS, 0, NULL, j_nop); - newsym(ip->gsym, "!", OP, 10, NULL, j_not); - newsym(ip->gsym, "+", OP, 8, add, j_add); - newsym(ip->gsym, "-", OP, 8, sub, j_sub); - newsym(ip->gsym, "~", OP, 10, NULL, j_nop); - newsym(ip->gsym, "^", OP, 10, NULL, j_xor); - newsym(ip->gsym, "*", OP, 9, mul, j_mul); - newsym(ip->gsym, "/", OP, 9, fdiv, j_div); - newsym(ip->gsym, "%", OP, 9, mod, j_rem); - newsym(ip->gsym, "<", OP, 6, lt, j_lt); - newsym(ip->gsym, "<=", OP, 6, le, j_le); - newsym(ip->gsym, ">=", OP, 6, ge, j_ge); - newsym(ip->gsym, ">", OP, 6, gt, j_gt); - newsym(ip->gsym, "==", OP, 5, eq, j_eq); - newsym(ip->gsym, "!=", OP, 5, neq, j_ne); - newsym(ip->gsym, ":=", OP, 0, assign, j_assign); - newsym(ip->gsym, "=", OP, 0, assign, j_assign); - newsym(ip->gsym, "&&", OP, 2, NULL, j_land); - newsym(ip->gsym, "||", OP, 1, NULL, j_lor); - newsym(ip->gsym, "&", OP, 4, band, j_and); - newsym(ip->gsym, "|", OP, 3, bor, j_or); - newsym(ip->gsym, "<<", OP, 7, lshift, j_lsh); - newsym(ip->gsym, ">>", OP, 7, rshift, j_rsh); - ip->out = (char *)calloc(1, 1024); - ip->opt.x = trace_opt; - return ip; -} - -node_t *eval_str(bip_t *ip, node_t *node, char *s, int len) -{ - node_t *n = parse_sl(ip, &s, &len); - - if (n->nchild == 0) - return node; - if (ip->fd_ast) - print_tree(ip, ip->fd_ast, n); - if (ip->opt.a) - dotty(ip, n, print_tree); - n = n->child[1]->child[2]; - ast2cfg(ip, n); - if (ip->fd_cfg) - print_flow(ip, ip->fd_cfg, n); - if (ip->opt.c) - dotty(ip, n, print_flow); - if (ip->opt.x) - run_jit(ip, n); - else if (!ip->opt.n) { - run_cfg(ip); - } - return node ? node : n; -} - -void bip_eval(bip_t *ip, char *s, char **res) -{ - eval_str(ip, NULL, s, strlen(s)); - *res = ip->out; -} diff --git a/_gi_c/init_go.h b/_gi_c/init_go.h deleted file mode 100644 index e80ec78d..00000000 --- a/_gi_c/init_go.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef INIT_H -#define INIT_H - -#include "node.h" - -bip_t *bip_init(int trace_opt); -node_t *eval_str(bip_t *ip, node_t *node, char *s, int len); - -#endif /* INIT_H */ diff --git a/_gi_c/l2.go b/_gi_c/l2.go deleted file mode 100644 index f4c5d505..00000000 --- a/_gi_c/l2.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -func main() { - for a := 0; a < 20000; a++ { - if (a & 0x8ff) == 0x800 { - println(a) - } - } -} diff --git a/_gi_c/l3.go b/_gi_c/l3.go deleted file mode 100644 index b278374c..00000000 --- a/_gi_c/l3.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -func main() { - for a := 0; a < 20000000; a++ { - if (a & 0x8ffff) == 0x80000 { - println(a) - } - } -} diff --git a/_gi_c/loop2.go b/_gi_c/loop2.go deleted file mode 100644 index 45063901..00000000 --- a/_gi_c/loop2.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -func main() { - for a := 0; a < 2000000000; a++ { - if (a & 0x8ffff) == 0x80000 { - println(a) - } - } -} diff --git a/_gi_c/node.c b/_gi_c/node.c deleted file mode 100644 index 0de4932b..00000000 --- a/_gi_c/node.c +++ /dev/null @@ -1,247 +0,0 @@ -/* generic node utility functions */ -#include -#include - -#include "node.h" -#include "trace.h" - -/* Maintain the following in consistency with enum nodetype_t */ -const char *nodetype[NODETYPE_LEN] = { - "UNDEF", "SL", "IF", "WHILE", "BREAK", "CONTINUE", "DEF", "FOR", - "RETURN", "LOCAL", "MAP", "OPS", "OP", "TERM", "VAR", "FUN", - "LVAR", "ARRAY", "COND_BRANCH", "NAMESPACE" -}; - -/* Recursive implementation of tree walk, depth first */ -void tree_walk(bip_t *ip, node_t *node, tw_fun_t in, tw_fun_t out, void *data) -{ - int i; - if (in) - in(ip, node, data); - for (i = 0; node && i < node->nchild; i++) - tree_walk(ip, node->child[i], in, out, data); - if (out) - out(ip, node, data); -} - -/* Non recursive tree walk */ -void new_tree_walk(bip_t *ip, node_t *node, tw_fun_t in, tw_fun_t out, void *data) -{ - ip->cur = node; - if (in) - in(ip, ip->cur, NULL); - while (1) { - ++ip->cur->visits; - if (ip->cur->nchild > 0 && ip->cur->visits <= ip->cur->nchild) { - ip->cur = ip->cur->child[ip->cur->visits - 1]; - if (in) - in(ip, ip->cur, NULL); - } else { - ip->cur->visits = 0; - if (out) - out(ip, ip->cur, NULL); - if (ip->cur == node) - break; - else - ip->cur = ip->cur->anc; - } - } -} - -/* append child node to the list of anc children node */ -void appchild(node_t *anc, node_t *child) -{ - if (child == NULL) { - //t_s("nil child"); - return; - } - anc->child = (node_t **)realloc(anc->child, - ++anc->nchild * sizeof(node_t *)); - anc->child[anc->nchild - 1] = child; - child->anc = anc; -} - -/* insert child node at first position in anc children list */ -void inschild(node_t *anc, node_t *child) -{ - node_t **ochild = anc->child; - int onchild = anc->nchild, i; - - anc->nchild = 0; - anc->child = NULL; - appchild(anc, child); - for (i = 0; i < onchild; i++) - appchild(anc, ochild[i]); - free(ochild); -} - -void delchild(node_t *anc, node_t *child) -{ - node_t **ochild = anc->child; - int onchild = anc->nchild, i; - - anc->nchild = 0; - anc->child = NULL; - for (i = 0; i < onchild; i++) - if (ochild[i] != child) - appchild(anc, ochild[i]); - free(ochild); -} - -void print_val(FILE *fd, val_t *pv, int quote) -{ - switch ((int)pv->type) { - case VINT: - fprintf(fd, "%ld", pv->u.num); - break; - case VFLOAT: - fprintf(fd, "%g", pv->u.fnum); - break; - case VSTR: - if (quote == 0) - fprintf(fd, "\\\"%s\\\"", pv->u.str); - else if (quote == 2) - fprintf(fd, "\"%s\"", pv->u.str); - else - fprintf(fd, "%s", pv->u.str); - break; - default: - break; - } -} - -void print_node_label(FILE *fd, node_t *node, int flow) -{ - switch ((int)node->type) { - case TERM: - fprintf(fd, " %d: ", node->num); - //fprintf(fd, " "); - print_val(fd, node->pv, flow); - break; - case SL: - fprintf(fd, " %d: %s", node->num, nodetype[node->type]); - //fprintf(fd, " %s", nodetype[node->type]); - break; - case VAR: - fprintf(fd, " %d: %s", node->num, node->sym->name); - //fprintf(fd, " %s", node->sym->name); - break; - default: - if (flow) - fprintf(fd, " $%d:", node->num); - //fprintf(fd, " "); - else - if (node->sym) - fprintf(fd, " %d: %s", node->num, node->sym->name); - //fprintf(fd, " %s", node->sym->name); - else - fprintf(fd, " %d: undefined", node->num); - break; - } -} - -static void pnode(bip_t *ip, node_t *node, void *data) -{ - FILE *fd = (FILE *)data; - fprintf(fd, "%d [type=\"%s\", label=\"", node->num, - nodetype[node->type]); - print_node_label(fd, node, 0); - fprintf(fd, "\"]\n"); - if (node->anc) - fprintf(fd, "%d -> %d\n", node->anc->num, node->num); -} - -void print_tree(bip_t *ip, FILE *fd, node_t *node) -{ - fprintf(fd, "digraph ast {\n"); - tree_walk(ip, node, pnode, NULL, fd); - fprintf(fd, "}\n"); -} - -static void pflow(bip_t *ip, node_t *node, void *data) -{ - int i, start = 0; - FILE *fd = (FILE *)data; - - if (node == NULL || node->type == TERM || node->type == VAR || - node->type == BREAK || node->type == CONTINUE) - return; - fprintf(fd, "%d [label=\"%d:", node->num, node->num); - if (node->type == OP) { - print_node_label(fd, node->child[0], 1); - start = 1; - } - print_node_label(fd, node, 0); - for (i = start; i < node->nchild; i++) - print_node_label(fd, node->child[i], 1); - fprintf(fd, "\"]\n"); - if (!node->snext) - return; - - if (node->snext->next[TRUE]) { - fprintf(fd, "%d -> %d [color=green]\n", node->num, - node->snext->next[TRUE]->num); - } - if (node->snext->next[FALSE]) { - fprintf(fd, "%d -> %d [color=red]\n", node->num, - node->snext->next[FALSE]->num); - } - if (!node->snext->next[TRUE] && !node->snext->next[FALSE]) { - fprintf(fd, "%d -> %d\n", node->num, node->snext->num); - } -} - -void print_flow(bip_t *ip, FILE *fd, node_t *node) -{ - int i; - - fprintf(fd, "digraph cfg {\n"); - tree_walk(ip, node, NULL, pflow, fd); - for (i = 0; i < ip->nentry_points; i++) - fprintf(fd, "%d [color=red]", ip->entry_points[i]->num); - fprintf(fd, "}\n"); -} - -void dotty(bip_t *ip, node_t *node, dotty_fun_t dotty_fun) -{ - FILE *fd = popen("dotty -", "w"); - if (fd == NULL) { - perror("dotty"); - return; - } - dotty_fun(ip, fd, node); - fflush(fd); - //getchar(); -} - -/* Add a new entry (start of thread) for parallel execution */ -void addentry(bip_t *ip, node_t *node) -{ - ip->entry = (node_t **)realloc(ip->entry, ++ip->nentry * sizeof(node)); - ip->entry[ip->nentry - 1] = node; -} - -/* Add node at end of list, increase list_len */ -void appnode(node_t ***list, node_t *node, int *list_len) -{ - *list = (node_t **)realloc(*list, ++(*list_len) * sizeof(node)); - (*list)[*list_len - 1] = node; -} - -sym_t *newsym(hash_t *h, const char *s, nodetype_t type, int prio, fun_t ifun, - fun_t cfun) -{ - sym_t *sym = (sym_t *)calloc(1, sizeof(*sym)); - sym->name = (char *)s; - sym->type = type; - sym->prio = prio; - sym->f = ifun; - sym->jf = cfun; - return (sym_t *)hadd(h, hkey(sym->name), sym->name, sym); -} - -sym_t *getsym(bip_t *ip, const char *s, int len) -{ - unsigned int key = hnkey(s, len, 0); - return (sym_t *)hlookup(ip->gsym, key, (void *)s, len); -} diff --git a/_gi_c/node.h b/_gi_c/node.h deleted file mode 100644 index 6e22701f..00000000 --- a/_gi_c/node.h +++ /dev/null @@ -1,140 +0,0 @@ -#ifndef NODE_H -#define NODE_H - -#include -#include - -#include "hash.h" -#include "scan.h" - -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif - -#define UP 0 -#define DOWN 1 -#define RD 0 -#define WR 1 - -// types which could be part of expressions must be defined after OP -typedef enum nodetype_t { - UNDEF, SL, IF, WHILE, BREAK, CONTINUE, DEF, FOR, RETURN, LOCAL, MAP, OPS, - OP, TERM, VAR, FUN, LVAR, ARRAY, COND_BRANCH, NAMESPACE, - NODETYPE_LEN -} nodetype_t; - -// String version of above, for debug -extern const char *nodetype[NODETYPE_LEN]; - -typedef enum valtype_t { - VINT, VSTR, VFUN, VTAB, VPTR, VFLOAT, VSYM, VVAR, VPINT, VPFLOAT, - VVOID, VSHORT, VQUAD, VBIN -} valtype_t; - -typedef struct bip_t bip_t; -typedef struct node_t node_t; -typedef void (*fun_t)(node_t *n); -typedef struct jit_node jit_node_t; /* from lightning.h */ - -typedef struct val_t { - int len; - valtype_t type; /* type of following field */ - union { - long num; /* integer value */ - double fnum; /* floating point value */ - char *str; /* string value */ - void *data; /* user data value */ - // unsigned char *bin; /* binary data */ - // struct sym_t *sym; /* symbol value */ - // fun_t fun; /* function value */ - } u; -} val_t; - -typedef struct sym_t { - char *name; /* symbol unique name */ - nodetype_t type; /* symbol type */ - int prio; /* operator priority */ - node_t *assign; /* node which sets this symbol */ - val_t v; /* data value */ - fun_t f; /* function to run during execution */ - fun_t jf; /* jit compiler callback */ - node_t **access[2]; - int naccess[2]; - int reg; /* jit register number */ -} sym_t; - -struct node_t { - node_t *anc; /* unique ancestor */ - node_t **child; /* array of children */ - sym_t *sym; /* symbol (variable, function, op) */ - nodetype_t type; - int num; /* unique serial number */ - int nchild; /* number of children */ - int prio; /* operator precedence (from sym) */ - val_t v; /* value during execution */ - val_t *pv; /* pointer on above or sym value */ - fun_t f; /* function to run during execution */ - int visits; /* Number of node visits for non rec tree_walk */ - - node_t *start; /* entry point in subtree (CFG) */ - node_t *snext; /* next node to eval (CFG) */ - node_t *next[2]; /* false and true branches in CFG */ - - jit_node_t *label; /* label to jump to (JIT) */ - int reg; /* register number (JIT) */ -}; - -/* Interpreter state, used during compilation and execution */ -struct bip_t { - scan_fun_t *scanfun; /* lexical scanner table of functions */ - hash_t *gsym; /* parse: global hashed symbol table */ - hash_t *lsym; /* parse: local hashed symbol table */ - node_t *root; - node_t *cur; - node_t *prev; - node_t **entry; /* run: array of entry points */ - int nentry; /* number of entry points (threads) */ - int nc; /* node counter */ - int last_direction; - node_t *fork_node; /* To replace jump stack */ - node_t *ctx_node; /* context ID */ - node_t **entry_points; - int nentry_points; - node_t *global_fork_node; - struct { - unsigned int a : 1; /* AST option */ - unsigned int c : 1; /* CFG option */ - unsigned int n : 1; /* no-run option */ - unsigned int p : 1; /* parallel option */ - unsigned int v : 1; /* trace option */ - unsigned int x : 1; /* native exec option */ - } opt; - FILE *fd_ast; /* file to write AST */ - FILE *fd_cfg; /* file to write CFG */ - char *out; - int outlen; - pthread_mutex_t outm; -}; - -#define is_leaf(node) ((node)->type == TERM || (node)->type == VAR) - -typedef void (*tw_fun_t)(bip_t *, node_t *, void *data); -typedef void (*dotty_fun_t)(bip_t *ip, FILE *fd, node_t *node); - -void tree_walk(bip_t *ip, node_t *node, tw_fun_t in, tw_fun_t out, void *data); -void new_tree_walk(bip_t *ip, node_t *node, tw_fun_t in, tw_fun_t out, void *data); -void appchild(node_t *anc, node_t *child); -void inschild(node_t *anc, node_t *child); -void delchild(node_t *anc, node_t *child); -void print_val(FILE *fd, val_t *pv, int quote); -void print_node_label(FILE *fd, node_t *node, int flow); -void print_tree(bip_t *ip, FILE *fd, node_t *node); -void print_flow(bip_t *ip, FILE *fd, node_t *node); -void dotty(bip_t *ip, node_t *node, dotty_fun_t dotty_fun); -void addentry(bip_t *ip, node_t *node); -void appnode(node_t ***list, node_t *node, int *list_len); -sym_t *newsym(hash_t *h, const char *s, nodetype_t type, int prio, fun_t ifun, fun_t cfun); -sym_t *getsym(bip_t *ip, const char *s, int len); - -#endif /* NODE_H */ diff --git a/_gi_c/parse_go.c b/_gi_c/parse_go.c deleted file mode 100644 index 339d8842..00000000 --- a/_gi_c/parse_go.c +++ /dev/null @@ -1,278 +0,0 @@ -#include -#include -#include - -#include "node.h" -#include "scan.h" -#include "run_cfg.h" -#include "trace.h" - -static node_t *parse_1(bip_t *ip, char **pstr, int *plen); -static node_t *parse_statement(bip_t *ip, char **pstr, int *plen); -node_t *parse_sl(bip_t *ip, char **pstr, int *plen); - -static char *strdupn(char *str, int len) -{ - char *s = (char *)malloc(len + 1); - strncpy(s, str, len); - s[len] = '\0'; - return s; -} - -static node_t *parse_int(bip_t *ip, scan_t *ps, char **pstr, int *plen) -{ - node_t *node = (node_t *)calloc(1, sizeof(node_t)); - node->type = TERM; - node->num = ++ip->nc; - node->pv = &node->v; - node->pv->type = VINT; - node->pv->u.num = ps->num; - return node; -} - -static node_t *parse_float(bip_t *ip, scan_t *ps, char **pstr, int *plen) -{ - node_t *node = (node_t *)calloc(1, sizeof(node_t)); - node->type = TERM; - node->num = ++ip->nc; - node->pv = &node->v; - node->pv->type = VFLOAT; - node->pv->u.fnum = ps->fnum; - return node; -} - -static node_t *parse_str(bip_t *ip, scan_t *ps, char **pstr, int *plen) -{ - node_t *node = (node_t *)calloc(1, sizeof(node_t)); - node->type = TERM; - node->num = ++ip->nc; - node->pv = &node->v; - node->pv->type = VSTR; - node->pv->len = ps->len; - node->pv->u.str = strdupn(ps->tok, ps->len); - return node; -} - -static node_t *parse_parenthesis(bip_t *ip, scan_t *ps, char **pstr, int *plen) -{ - node_t *node = (node_t *)calloc(1, sizeof(node_t)); - node->num = ++ip->nc; - node->type = SL; - node->pv = &node->v; - appchild(node, parse_statement(ip, &ps->tok, &ps->len)); - return node; -} - -static node_t *parse_paren(bip_t *ip, scan_t *ps, char **pstr, int *plen) -{ - node_t *node = parse_statement(ip, &ps->tok, &ps->len); - node->prio = 20; // override precedence - return node; -} - -static node_t *parse_bracket(bip_t *ip, scan_t *ps, char **pstr, int *plen) -{ - node_t *node = (node_t *)calloc(1, sizeof(node_t)); - node->num = ++ip->nc; - node->type = ARRAY; - appchild(node, parse_statement(ip, &ps->tok, &ps->len)); - return node; -} - -static node_t *parse_oper(bip_t *ip, scan_t *ps, char **pstr, int *plen) -{ - node_t *node = (node_t *)calloc(1, sizeof(node_t)); - node->num = ++ip->nc; - node->pv = &node->v; - if ((node->sym = getsym(ip, ps->tok, ps->len))) { - node->type = node->sym->type; - node->f = node->sym->f; - } - if (node->type != OPS) - appchild(node, parse_1(ip, pstr, plen)); - return node; -} - -static node_t *parse_id(bip_t *ip, scan_t *ps, char **pstr, int *plen) -{ - node_t *node = (node_t *)calloc(1, sizeof(node_t)), *n; - scan_t sc; - char *s; - int l; - - node->num = ++ip->nc; - if ((node->sym = getsym(ip, ps->tok, ps->len))) { - node->type = node->sym->type; - } else { - node->type = VAR; - node->sym = newsym(ip->gsym, strdupn(ps->tok, ps->len), - VAR, 0, nop, NULL); - } - node->f = node->sym->f; - switch ((int)node->sym->type) { - case NAMESPACE: - appchild(node, parse_1(ip, pstr, plen)); - break; - case DEF: - // FIXME: handle all variants of DEF - // function name - appchild(node, parse_1(ip, pstr, plen)); - - - // function args - l = *plen; - s = *pstr; - scan(ip->scanfun, &sc, &s, &l); - appchild(node, parse_parenthesis(ip, &sc, pstr, plen)); - *pstr = s; - *plen = l; - - // function body - appchild(node, parse_1(ip, pstr, plen)); - break; - case FOR: - // FIXME: handle all variants of FOR - appchild(node, parse_statement(ip, pstr, plen)); - appchild(node, parse_statement(ip, pstr, plen)); - appchild(node, parse_statement(ip, pstr, plen)); - appchild(node, parse_statement(ip, pstr, plen)); - break; - case IF: - appchild(node, parse_statement(ip, pstr, plen)); - appchild(node, parse_statement(ip, pstr, plen)); - s = *pstr; - l = *plen; - scan(ip->scanfun, &sc, &s, &l); - if (sc.type == ID && sc.len == 4 && - strncmp(sc.tok, "else", 4) == 0) { - *pstr = s; - *plen = l; - appchild(node, parse_statement(ip, pstr, plen)); - } - break; - case OP: - appchild(node, parse_1(ip, pstr, plen)); - break; - case RETURN: - appchild(node, parse_statement(ip, pstr, plen)); - break; - case FUN: - node->pv = &node->v; - while ((n = parse_1(ip, pstr, plen))) - appchild(node, n); - break; - case VAR: - node->pv = &node->sym->v; - s = *pstr; - l = *plen; - scan(ip->scanfun, &sc, &s, &l); - if (sc.type == OPER) { - sym_t *sym = getsym(ip, sc.tok, sc.len); - if (sym && sym->type == OPS) { - n = parse_1(ip, pstr, plen); - appchild(n, node); - node = n; - } - } - break; - default: - t_s(nodetype[node->sym->type]); - break; - } - return node; -} - -static node_t *parse_brace(bip_t *ip, scan_t *ps, char **pstr, int *plen) -{ - return parse_sl(ip, &ps->tok, &ps->len); -} - -static node_t *parse_bad(bip_t *ip, scan_t *ps, char **pstr, int *plen) -{ - return NULL; -} - -typedef node_t *(*parse_fun_t) (bip_t *, scan_t *, char **, int *); - -// Table indiced by scan_token_t -static const parse_fun_t parse_fun[] = { - parse_bad, parse_brace, parse_bracket, parse_bad, parse_bad, - parse_float, parse_id, parse_int, parse_bad, parse_oper, - parse_paren, parse_str, -}; - -/* Return a single node, possibly a complex subtree. */ -static node_t *parse_1(bip_t *ip, char **pstr, int *plen) -{ - scan_t sc; - scan(ip->scanfun, &sc, pstr, plen); - return parse_fun[sc.type](ip, &sc, pstr, plen); -} - -/* Return a statement node. Apply operator precedence rules (reordering nodes). */ -static node_t *parse_statement(bip_t *ip, char **pstr, int *plen) -{ - scan_t sc = {}; - char *s = *pstr; - int len = *plen; - node_t *first = NULL, *node = NULL, *n, *n1; - -start: - while (len > 0 && scan(ip->scanfun, &sc, &s, &len) != CSEP) { - if (first && sc.type == BRACE) { - unscan(&sc, &s, &len); - break; - } - node = parse_fun[sc.type](ip, &sc, &s, &len); - if (!first) { - first = node; - } else if (node->type == OP) { - node->prio = node->sym->prio; - for (n = first; n; n = n->nchild > 1 ? n->child[1] : NULL) { - if (n->type != OP || node->prio <= n->prio - || (n->type == OP && n->nchild == 1)) { - if (n == first) { - first = node; - } else { - n1 = n->anc; - delchild(n1, n); - appchild(n1, node); - } - inschild(node, n); - break; - } - } - } else { - unscan(&sc, &s, &len); - break; - } - // If node is a kind of statement not part of an expression, stop here - if (node->type < OP) - break; - } - if (!first) { - // FIXME: handle parse error - if (len > 0 && sc.type == CSEP) { - (*pstr)++; - (*plen)--; - goto start; - } - //t_s(scan_token[sc.type]); - } - *pstr = s; - *plen = len; - return first; -} - -/* Return a statement list node */ -node_t *parse_sl(bip_t *ip, char **pstr, int *plen) -{ - node_t *node = (node_t *)calloc(1, sizeof(node_t)); - node->type = SL; - node->num = ++ip->nc; - node->sym = getsym(ip, "SL", 2); - node->f = node->sym->f; - while (*plen > 0) - appchild(node, parse_statement(ip, pstr, plen)); - return node; -} diff --git a/_gi_c/parse_go.h b/_gi_c/parse_go.h deleted file mode 100644 index 6efe55db..00000000 --- a/_gi_c/parse_go.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef PARSE_GO_HH -#define PARSE_GO_HH - -#include "node.h" - -node_t *parse_sl(bip_t *ip, char **pstr, int *plen); - -#endif /* PARSE_GO_H */ diff --git a/_gi_c/run_cfg.c b/_gi_c/run_cfg.c deleted file mode 100644 index 0670e5ee..00000000 --- a/_gi_c/run_cfg.c +++ /dev/null @@ -1,186 +0,0 @@ -#include -#include -#include - -#include "node.h" -#include "trace.h" - -#define FALSE 0 -#define TRUE 1 - -void nop(node_t *n) -{ - return; -} - -void assign(node_t *n) -{ - *n->pv = *n->child[0]->pv = *n->child[1]->pv; -} - -void cond_branch(node_t *n) -{ - n->snext = n->pv->u.num ? n->next[TRUE] : n->next[FALSE]; -} - -void inc(node_t *n) -{ - n->child[0]->pv->u.num++; -} - -void bprintf_val(val_t *pv) -{ - switch((int)pv->type) { - case VINT: - printf("%ld", pv->u.num); - break; - case VFLOAT: - printf("%g", pv->u.fnum); - case VSTR: - printf("%s", pv->u.str); - default: - break; - } -} - -void bprint_val(bip_t *ip, val_t *pv, int quote) -{ - char s[100]; - - switch ((int)pv->type) { - case VINT: - snprintf(s, sizeof(s), "%ld", pv->u.num); - break; - case VFLOAT: - snprintf(s, sizeof(s), "%g", pv->u.fnum); - break; - case VSTR: - snprintf(s, sizeof(s), "%s", pv->u.str); - break; - if (quote == 0) - snprintf(s, sizeof(s), "\\\"%s\\\"", pv->u.str); - else if (quote == 2) - snprintf(s, sizeof(s), "\"%s\"", pv->u.str); - else - snprintf(s, sizeof(s), "%s", pv->u.str); - break; - default: - break; - } - strcat(ip->out, s); -} - -void bprint_node_label(bip_t *ip, node_t *node, int flow) -{ - char s[100]; - - switch ((int)node->type) { - case TERM: - strcat(ip->out, " "); - bprint_val(ip, node->pv, flow); - break; - case SL: - snprintf(s, sizeof(s), " %s", nodetype[node->type]); - strcat(ip->out, s); - break; - case VAR: - snprintf(s, sizeof(s), " %s", node->sym->name); - strcat(ip->out, s); - break; - default: - if (flow) - snprintf(s, sizeof(s), " $%d", node->num); - else - snprintf(s, sizeof(s), " %s", node->sym->name); - strcat(ip->out, s); - break; - } -} - -void echo(node_t *n) -{ - int i; - for (i = 0; i < n->nchild; i++) - bprintf_val(n->child[i]->pv); - printf("\n"); - //bprint_val(ip, n->child[i]->pv, 1); - //strcat(ip->out, "\n"); -} - -void trace(FILE *fd, bip_t *ip, node_t *node, int tid) -{ - int i, start = 0; - char s[100]; - - if (node->sym->f == nop || node->type == SL) - return; - snprintf(s, sizeof(s), "[%d] $%d:", tid, node->num); - strcat(ip->out, s); - if (node->type == OP) { - bprint_node_label(ip, node->child[0], 2); - start = 1; - } - bprint_node_label(ip, node, 0); - for (i = start; i < node->nchild; i++) - bprint_node_label(ip, node->child[i], 2); - strcat(ip->out, ": "); - bprint_val(ip, node->pv, 2); - strcat(ip->out, "\n"); -} - -void run_cfg(bip_t *ip) -{ - node_t *n = ip->entry[0]; - while (n) { - n->f(n); - n = n->snext; - } -} - -#define define_arithmetic_opfun(name, op) \ -void name(node_t *n) \ -{ \ - val_t *v0, *v1; \ - const static val_t v = {0}; \ - if (n->nchild == 1) { \ - v0 = (val_t *)&v; \ - v1 = n->child[0]->pv; \ - } else { \ - v0 = n->child[0]->pv; \ - v1 = n->child[1]->pv; \ - } \ - n->pv->u.num = v0->u.num op v1->u.num; \ -} - -#define define_comparison_opfun(name, op) \ -void name(node_t *n) \ -{ \ - n->pv->u.num = n->child[0]->pv->u.num op n->child[1]->pv->u.num;\ -} - -#define define_bitwise_opfun(name, op) \ -void name(node_t *n) \ -{ \ - n->pv->u.num = n->child[0]->pv->u.num op n->child[1]->pv->u.num;\ -} - -/* Generate code for common operators */ -#define check_zero_div(v) \ - {if (v == 0) fprintf(stderr, "run error: divide by zero\n"); return;} -define_arithmetic_opfun(fdiv, /) -#undef check_zero_div -#define check_zero_div(v) -define_arithmetic_opfun(add, +) -define_arithmetic_opfun(sub, -) -define_arithmetic_opfun(mul, *) -define_bitwise_opfun(band, &) -define_bitwise_opfun(bor, |) -define_bitwise_opfun(lshift, <<) -define_bitwise_opfun(rshift, >>) -define_bitwise_opfun(mod, %) -define_comparison_opfun(eq, ==) -define_comparison_opfun(neq, !=) -define_comparison_opfun(ge, >=) -define_comparison_opfun(gt, >) -define_comparison_opfun(le, <=) -define_comparison_opfun(lt, <) diff --git a/_gi_c/run_cfg.h b/_gi_c/run_cfg.h deleted file mode 100644 index 1c30a5cc..00000000 --- a/_gi_c/run_cfg.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef RUN_CFG_H -#define RUN_CFG_H - -#include "node.h" - -void nop(node_t *n); -void assign(node_t *n); -void echo(node_t *n); -void cond_branch(node_t *n); - -void inc(node_t *n); -void add(node_t *n); -void sub(node_t *n); -void mul(node_t *n); -void fdiv(node_t *n); -void band(node_t *n); -void bor(node_t *n); -void lshift(node_t *n); -void rshift(node_t *n); -void mod(node_t *n); -void eq(node_t *n); -void neq(node_t *n); -void ge(node_t *n); -void gt(node_t *n); -void le(node_t *n); -void lt(node_t *n); - -void run_cfg(bip_t *ip); - -#endif /* RUN_CFG_H */ diff --git a/_gi_c/run_jit.c b/_gi_c/run_jit.c deleted file mode 100644 index 95ee4a3c..00000000 --- a/_gi_c/run_jit.c +++ /dev/null @@ -1,313 +0,0 @@ -/* jit runtime for bip */ - -#include -#include - -#include "node.h" -#include "run_jit.h" -#include "trace.h" - -typedef struct reg_t { - sym_t *sym; /* symbol associated to register */ -} reg_t; - -static reg_t regs[JIT_V_NUM]; - -static jit_state_t *_jit; /* XXX: should be in bip_t */ - -static inline void load(int reg, node_t *n) -{ - if (n->type == VAR) - n->reg = n->sym->reg; - if (n->reg) { - if (reg != n->reg) - jit_movr(reg, n->reg); - } else if (n->type == TERM) - jit_movi(reg, n->pv->u.num); - else if (reg != JIT_R0) - jit_movr(reg, JIT_R0); - //else if (0) - // jit_ldi(reg, &n->pv->u.num); -} - -static inline int is_if_cond(node_t *n) -{ - return (n->anc && n->anc->type == IF && n->anc->child[0] == n); -} - -static inline int is_for_cond(node_t *n) -{ - return (n->anc && n->anc->type == FOR && n->anc->child[1] == n); -} - -static inline int is_while_cond(node_t *n) -{ - return (n->anc && n->anc->type == WHILE && n->anc->child[0] == n); -} - -static inline int is_cond(node_t *n) -{ - return is_if_cond(n) || is_for_cond(n) || is_while_cond(n); -} - -static int regalloc(sym_t *sym) -{ - int i; - if (sym->reg) - return sym->reg; /* already allocated */ - for (i = 0; i < JIT_V_NUM; i++) { - if (regs[i].sym == NULL) { - regs[i].sym = sym; - sym->reg = JIT_V(i); - jit_ldi(sym->reg, &sym->v.u.num); - return i; - } - } - return 0; -} - -void j_assign(node_t *n) -{ - sym_t *var = n->child[0]->sym; - - if (regalloc(var)) { - n->reg = n->child[0]->reg = var->reg; - load(n->reg, n->child[1]); - } else { - load(JIT_R0, n->child[1]); - jit_sti(&n->child[0]->pv->u.num, JIT_R0); - } - return; -} - -static int gen_branch(node_t *n, int r1) -{ - jit_node_t **plabel; - node_t *c1; - - if (!is_cond(n)) - return 0; - plabel = (n->anc->nchild == 3) ? - &n->anc->child[2]->label : - &n->anc->label; - c1 = n->child[1]; - if (n->sym->jf == j_eq) { - *plabel = (c1->type == TERM) ? - jit_bnei(r1, c1->pv->u.num) : - jit_bner(r1, c1->reg); - } else if (n->sym->jf == j_ne) { - *plabel = (c1->type == TERM) ? - jit_beqi(r1, c1->pv->u.num) : - jit_beqr(r1, c1->reg); - } else if (n->sym->jf == j_le) { - *plabel = (c1->type == TERM) ? - jit_bgti(r1, c1->pv->u.num) : - jit_bgtr(r1, c1->reg); - } else if (n->sym->jf == j_gt) { - *plabel = (c1->type == TERM) ? - jit_blei(r1, c1->pv->u.num) : - jit_bler(r1, c1->reg); - } else if (n->sym->jf == j_lt) { - *plabel = (c1->type == TERM) ? - jit_bgei(r1, c1->pv->u.num) : - jit_bger(r1, c1->reg); - } else if (n->sym->jf == j_ge) { - *plabel = (c1->type == TERM) ? - jit_blti(r1, c1->pv->u.num) : - jit_bltr(r1, c1->reg); - } else { - t_s(n->sym->name); - *plabel = jit_beqi(r1, 0); - } - return 1; -} - -#define define_binary_operator(name) \ -void j_##name(node_t *n) \ -{ \ - int r0, r1; \ - if (n->anc->type == VAR) \ - n->reg = n->anc->reg = n->anc->sym->reg; \ - else if (n->anc->type == OP && n->anc->sym->jf == j_assign) \ - n->reg = n->anc->reg = n->anc->child[0]->sym->reg; \ - if (n->child[0]->type == VAR) \ - n->child[0]->reg = n->child[0]->sym->reg; \ - if (n->child[1]->type == VAR) \ - n->child[1]->reg = n->child[1]->sym->reg; \ - r0 = n->anc->reg; \ - r1 = n->child[0]->reg; \ - load(r1, n->child[0]); \ - if (gen_branch(n, r1)) \ - return; \ - if (n->child[1]->reg) { \ - jit_##name##r(r0, r1, JIT_V(n->child[1]->reg)); \ - } else if (n->child[1]->type == TERM) { \ - jit_##name##i(r0, r1, n->child[1]->pv->u.num); \ - } else { \ - jit_##name##r(r0, r1, JIT_R0); \ - } \ - if (0) jit_sti(&n->pv->u.num, JIT_V(n->anc->reg)); \ -} - -define_binary_operator(add) /* c0 + c1 */ -define_binary_operator(sub) /* c0 - c1 */ -define_binary_operator(mul) /* c0 * c1 */ -define_binary_operator(div) /* c0 / c1 */ -define_binary_operator(rem) /* c0 % c1 */ -define_binary_operator(lt) /* c0 < c1 */ -define_binary_operator(le) /* c0 <= c1 */ -define_binary_operator(eq) /* c0 == c1 */ -define_binary_operator(ne) /* c0 != c1 */ -define_binary_operator(gt) /* c0 > c1 */ -define_binary_operator(ge) /* c0 >= c1 */ -define_binary_operator(and) /* c0 & c1 */ -define_binary_operator(or) /* c0 | c1 */ -define_binary_operator(xor) /* c0 ^ c1 */ -define_binary_operator(lsh) /* c0 << c1 */ -define_binary_operator(rsh) /* c0 >> c1 */ - -#define define_unary_operator(name) \ -void j_##name(node_t *n) \ -{ \ - jit_ldi(JIT_V0, &n->child[0]->pv->u.num); \ - jit_##name##r(JIT_V0, JIT_V0); \ - jit_sti(&n->pv->u.num, JIT_V0); \ -} - -define_unary_operator(neg) -define_unary_operator(com) - -static void do_echo_i(int i) -{ - printf("%d\n", i); -} - -void j_echo(node_t *n) -{ - jit_prepare(); - load(JIT_R0, n->child[0]); - jit_pushargr(JIT_R0); - jit_finishi((jit_pointer_t)do_echo_i); -} - -void j_land(node_t *n) -{ - load(JIT_R0, n->child[0]); - n->label = jit_beqi(JIT_R0, 0); - load(JIT_R0, n->child[1]); - jit_patch(n->label); -} - -void j_lor(node_t *n) -{ - load(JIT_R0, n->child[0]); - n->label = jit_bnei(JIT_R0, 0); - load(JIT_R0, n->child[1]); - jit_patch(n->label); -} - -void j_nop(node_t *n) -{ - return; -} - -void j_inc(node_t *n) -{ - // Avoid costly (and useless in loops) load/store between memory and register - //jit_ldi(JIT_V0, &n->child[0]->pv->u.num); - //jit_addi(JIT_V0, JIT_V0, 1); - //jit_sti(&n->child[0]->pv->u.num, JIT_V0); - int reg = n->child[0]->sym->reg; - jit_addi(reg, reg, 1); -} - -void j_not(node_t *n) -{ - load(JIT_R0, n->child[0]); - jit_eqi(JIT_R0, JIT_R0, 0); - jit_sti(&n->pv->u.num, JIT_R0); -} - -/* code generated by postorder traveral of the abstract syntax tree */ -static void code_generation(bip_t *ip, node_t *n, void *data) -{ - node_t *anc = n->anc; - - if (is_leaf(n)) { - if (is_cond(n)) { - load(JIT_R0, n); - if (anc->nchild == 3) - anc->child[2]->label = jit_beqi(JIT_R0, 0); - else - anc->label = jit_beqi(JIT_R0, 0); - } - return; - } - if (n->label) - jit_patch(n->label); - if (is_for_cond(n)) - n->label = jit_label(); - if (is_while_cond(n)) - n->label = jit_label(); - n->sym->jf(n); - - if (anc == NULL) - return; - if (anc->type == IF) { - if (anc->child[1] == n) { /* in true block */ - if (anc->nchild == 3) - anc->child[1]->label = jit_jmpi(); - } else if (anc->nchild == 3 && anc->child[2] == n) { /* in false block */ - jit_patch_at(n->anc->child[1]->label, jit_label()); - } - } else if (anc->type == FOR) { - if (anc->child[3] == n) /* in true block */ - jit_patch_at(jit_jmpi(), anc->child[1]->label); - } else if (anc->type == WHILE) { - if (anc->child[1] == n) /* in true block */ - jit_patch_at(jit_jmpi(), anc->child[0]->label); - } -} - -/* compute necessary space for stack allocation, tag nodes using stack */ -static void stack_analysis(bip_t *ip, node_t *n, void *data) -{ - if (n->type == OP) { - t_s(n->sym->name); - if (!is_leaf(n->child[0])) { - t_d(n->num); - t_d(ip->prev->num); - t_d(n->child[0]->num); - t_s(n->child[0]->sym->name); - } - if (!is_leaf(n->child[1])) { - t_d(n->num); - t_d(ip->prev->num); - t_d(n->child[1]->num); - t_s(n->child[1]->sym->name); - } - } - ip->prev = n; -} - -void run_jit(bip_t *ip, node_t *node) -{ - void (*func)(void); - - init_jit("b1"); - _jit = jit_new_state(); - - jit_prolog(); - tree_walk(ip, node, NULL, stack_analysis, NULL); - tree_walk(ip, node, NULL, code_generation, NULL); - jit_epilog(); - - func = (void (*)(void))jit_emit(); - if (ip->opt.v) { - jit_print(); - jit_disassemble(); - } - if (!ip->opt.n) - func(); - finish_jit(); -} diff --git a/_gi_c/run_jit.h b/_gi_c/run_jit.h deleted file mode 100644 index 014b5252..00000000 --- a/_gi_c/run_jit.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef RUN_JIT_H -#define RUN_JIT_H - -#include "node.h" - -void j_assign(node_t *n); -void j_echo(node_t *n); -void j_nop(node_t *n); - -void j_inc(node_t *n); - -void j_add(node_t *n); /* c0 + c1 */ -void j_sub(node_t *n); /* c0 - c1 */ -void j_mul(node_t *n); /* c0 * c1 */ -void j_div(node_t *n); /* c0 / c1 */ -void j_rem(node_t *n); /* c0 % c1 */ -void j_lt(node_t *n); /* c0 < c1 */ -void j_le(node_t *n); /* c0 <= c1 */ -void j_eq(node_t *n); /* c0 == c1 */ -void j_ne(node_t *n); /* c0 != c1 */ -void j_gt(node_t *n); /* c0 > c1 */ -void j_ge(node_t *n); /* c0 >= c1 */ -void j_and(node_t *n); /* c0 & c1 */ -void j_or(node_t *n); /* c0 | c1 */ -void j_xor(node_t *n); /* c0 ^ c1 */ -void j_lsh(node_t *n); /* c0 << c1 */ -void j_rsh(node_t *n); /* c0 >> c1 */ -void j_land(node_t *n); /* c0 && c1 */ -void j_lor(node_t *n); /* c0 || c1 */ -void j_neg(node_t *n); -void j_com(node_t *n); -void j_not(node_t *n); /* ! c0 */ - -void run_jit(bip_t *ip, node_t *node); - -#endif /* RUN_JIT_H */ diff --git a/_gi_c/scan.c b/_gi_c/scan.c deleted file mode 100644 index c4754778..00000000 --- a/_gi_c/scan.c +++ /dev/null @@ -1,232 +0,0 @@ -/* scanner: lexical analysis functions */ - -/* - * Todo: - * - line counting - * - better error reporting - */ -#include - -#include "scan.h" -#include "trace.h" - -/* scan_token strings for debug. Keep in sync with scan_token_t in scan.h */ -const char *scan_token[SCAN_TOKEN_LEN] = { - "BAD", "BRACE", "BRACKET", "BSTR", "CSEP", "FLOAT", "ID", "INT", "LSEP", - "OPER", "PAREN", "STR" -}; - -#define isdigit(c) ('0' <= (c) && (c) <= '9') -#define isalpha(c) (('a' <= (c) && (c) <= 'z') || ('A' <= (c) && (c) <= 'Z')) -#define isalnum(c) (isdigit((c)) || isalpha((c))) - -/* Return a pointer on the first occurence of char c in string s of length len */ -static char *strnchr(char *s, int len, char c) -{ - int i; - for (i = 0; i < len; i++) - if (s[i] == c) - return &s[i]; - return NULL; -} - -/* Flat scan of block delimited by i.e (), [], or {} */ -int scan_block(scan_t *ps, char *s, scan_token_t type, int len, char bstart, char bend, char sdelim) -{ - char c; - int complete = 0, inquote = 0, level = 0; - - ps->tok = ++s; - c = *s; - while (len--) { - if (c == sdelim) - inquote = 1 - inquote; - else if (inquote && c == '\\') - s++; - else if (!inquote && c == bstart) - level++; - else if (!inquote && c == bend) { - if (--level < 0) { - complete = 1; - break; - } - } - c = *++s; - } - ps->type = complete ? type : BAD; - ps->end = s + 1; - ps->len = ps->end - ps->tok -1; - return 0; -} - -int scan_paren(scan_t *ps, char *s, int len) -{ - return scan_block(ps, s, PAREN, len, '(', ')', '"'); -} - -int scan_brace(scan_t *ps, char *s, int len) -{ - return scan_block(ps, s, BRACE, len, '{', '}', '"'); -} - -int scan_bracket(scan_t *ps, char *s, int len) -{ - return scan_block(ps, s, BRACKET, len, '[', ']', '"'); -} - -int scan_cmt(scan_t *ps, char *s, int len) -{ - char c, *smax = s + len; - for (c = *++s; s < smax && c != '\n'; c = *++s); - ps->end = s; - return 1; -} - -int scan_num(scan_t *ps, char *s, int len) -{ - ps->fnum = strtod(s, &ps->end); - ps->tok = s; - ps->len = ps->end - ps->tok; - if (strnchr(ps->tok, ps->len, '.')) - ps->type = FLOAT; - else { - if (ps->tok[0] == '0' && ps->tok[1] != 'x') - ps->num = strtol(ps->tok, &ps->end, 8); - else - ps->num = (long)ps->fnum; - ps->type = INT; - } - return 0; -} - -int scan_id(scan_t *ps, char *s, int len) -{ - char c, *smax = s + len; - ps->tok = s; - ps->type = ID; - for (c = *++s; s < smax; c = *++s) - if (!(isalnum(c) || c == '_')) /* XXX could be accelerated */ - break; - ps->end = s; - ps->len = s - ps->tok; - return 0; -} - -int scan_wsep(scan_t *ps, char *s, int len) -{ - char c, *smax = s + len; - for (c = *++s; s < smax; c = *++s) { - if (c != ' ' && c != '\t') - break; - } - ps->end = s; - return 1; -} - -int scan_lsep(scan_t *ps, char *s, int len) -{ - ps->type = LSEP; - ps->end = s + 1; - return 0; -} - -int scan_csep(scan_t *ps, char *s, int len) -{ - char c = *s, *smax = s + len; - - for (c = *++s; s < smax; c = *++s) - if (c != '\n' && c != ';' && c != ' ' && c != '\t') - break; - ps->type = CSEP; - ps->end = s; - return 0; -} - -int scan_str(scan_t *ps, char *s, int len) -{ - char *smax = s + len, c, delim = *s; - - ps->type = STR; - ps->tok = ++s; - for (c = *ps->tok; s < smax; c = *++s) - if (c == '\\') - s++, ps->type = BSTR; - else if (c == delim) - break; - if (s == smax && c != delim) - ps->type = BAD; - ps->len = s - ps->tok; - ps->end = s + 1; - return 0; -} - -int scan_c_op(scan_t *ps, char *s, int len) -{ - ps->tok = s; - ps->type = OPER; - switch (*s) { - case '!': if (s[1] == '=') s++; break; - case '=': if (s[1] == '=') s++; break; - case '<': if (s[1] == '=' || s[1] == '<') s++; break; - case '>': if (s[1] == '=' || s[1] == '>') s++; break; - case '&': if (s[1] == '&') s++; break; - case '|': if (s[1] == '|') s++; break; - case '+': if (s[1] == '+') s++; break; - case '-': if (s[1] == '-') s++; break; - } - ps->end = s + 1; - ps->len = ps->end - ps->tok; - return 0; -} - -int scan_go_op(scan_t *ps, char *s, int len) -{ - ps->tok = s; - ps->type = OPER; - switch (*s) { - case ':': if (s[1] == '=') s++; break; - case '!': if (s[1] == '=') s++; break; - case '=': if (s[1] == '=') s++; break; - case '<': if (s[1] == '=' || s[1] == '<') s++; break; - case '>': if (s[1] == '=' || s[1] == '>') s++; break; - case '&': if (s[1] == '&') s++; break; - case '|': if (s[1] == '|') s++; break; - case '+': if (s[1] == '+') s++; break; - case '-': if (s[1] == '-') s++; break; - } - ps->end = s + 1; - ps->len = ps->end - ps->tok; - return 0; -} - -/* return a bad token */ -int scan_bad(scan_t *ps, char *s, int len) -{ - t_c(*s); - ps->tok = s; - ps->end = s + 1; - ps->type = BAD; - return 0; -} - -/* scanner entry point */ -int scan(scan_fun_t *scanfun, scan_t *ps, char **pstr, int *plen) -{ - char *s = *pstr, *smax = s + *plen; - - ps->orig = s; - ps->len = 0; - ps->type = BAD; - while (s < smax && (*scanfun[(int)*s])(ps, s, *plen)) - s = ps->end; - *plen += *pstr - ps->end; - *pstr = ps->end; - return ps->type; -} - -/* undo scan operation, revert to previous state */ -void unscan(scan_t *ps, char **pstr, int *plen) -{ - *pstr = ps->orig; - *plen += ps->end - ps->orig; -} diff --git a/_gi_c/scan.h b/_gi_c/scan.h deleted file mode 100644 index 3ccc40bf..00000000 --- a/_gi_c/scan.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef SCAN_H -#define SCAN_H - -/* token types recognized by the scanner. For block operators, the - * opening char is used. - */ -typedef enum scan_token_t { - BAD, BRACE, BRACKET, BSTR, CSEP, FLOAT, ID, INT, LSEP, OPER, PAREN, STR, - SCAN_TOKEN_LEN -} scan_token_t; - -/* strings of above for debug */ -extern const char *scan_token[SCAN_TOKEN_LEN]; - -/* scanner state */ -typedef struct scan_t { - char *tok; /* token start position in input */ - char *end; /* next position in input */ - char *orig; /* previous position */ - scan_token_t type; /* token type */ - int len; /* token len */ - long num; /* scanner returned value if type is INT */ - double fnum; /* scanner returned value if type is FLOAT */ -} scan_t; - -typedef int (*scan_fun_t)(scan_t *ps, char *s, int len); - -int scan_block(scan_t *ps, char *s, scan_token_t type, int len, char bstart, char bend, char sdelim); - -int scan_paren(scan_t *ps, char *s, int len); -int scan_brace(scan_t *ps, char *s, int len); -int scan_bracket(scan_t *ps, char *s, int len); -int scan_cmt(scan_t *ps, char *s, int len); -int scan_num(scan_t *ps, char *s, int len); -int scan_id(scan_t *ps, char *s, int len); -int scan_wsep(scan_t *ps, char *s, int len); -int scan_lsep(scan_t *ps, char *s, int len); -int scan_csep(scan_t *ps, char *s, int len); -int scan_str(scan_t *ps, char *s, int len); -int scan_c_op(scan_t *ps, char *s, int len); -int scan_go_op(scan_t *ps, char *s, int len); -int scan_bad(scan_t *ps, char *s, int len); - -int scan(scan_fun_t *scanfun, scan_t *ps, char **pstr, int *plen); -void unscan(scan_t *ps, char **pstr, int *plen); - -#endif /* SCAN_H */ diff --git a/_gi_c/trace.h b/_gi_c/trace.h deleted file mode 100644 index 6a954db2..00000000 --- a/_gi_c/trace.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef TRACE_H -#define TRACE_H - -#include - -/* Macros for temporary internal debug traces */ -#define _tr(fmt, type, exp) fprintf(stderr, "[%s:%d %s] %s: " fmt, __FILE__,\ - __LINE__, __func__, #exp, (type)(exp)) -#define t_c(s) _tr("'%c'\n", char, s) -#define t_d(s) _tr("%ld\n", long int, s) -#define t_g(s) _tr("%g\n", double, s) -#define t_i(s) _tr("%d\n", int, s) -#define t_p(s) _tr("%p\n", void *, s) -#define t_s(s) _tr("'%s'\n", char *, s) -#define t_u(s) _tr("%lu\n", unsigned long int, s) -#define t_x(s) _tr("0x%lx\n", unsigned long int, s) -#define t_v(exp) {fprintf(stderr, "[%s:%d %s] %s\n", __FILE__, __LINE__, __func__, #exp); (void)(exp);} - -#define t_sn(s, n) do { \ - fprintf(stderr, "[%s:%d %s] %s: '", __FILE__, __LINE__, __func__, #s); \ - fwrite((s), (n), 1, stderr); fputs("'\n", stderr); } while (0) - -#endif /* TRACE_H */ diff --git a/example/test_plugin/plugin/plugin.go b/example/test_plugin/plugin/plugin.go index 1f56b25e..11f1e86b 100644 --- a/example/test_plugin/plugin/plugin.go +++ b/example/test_plugin/plugin/plugin.go @@ -11,7 +11,7 @@ var version = "v1" type Sample struct{ Name string } // Handler is a Sample method to processes HTTP requests -func (s *Sample) Handler(w http.ResponseWriter, r *http.Request) { +func (s *Sample) ServeHTTP(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Welcome to my website", s.Name, version) } @@ -19,11 +19,12 @@ func (s *Sample) Handler(w http.ResponseWriter, r *http.Request) { func NewSample(name string) func(http.ResponseWriter, *http.Request) { s := &Sample{"test"} fmt.Println("in NewSample", name, version, s) - return s.Handler + return s.ServeHTTP } -//func main() { -// s := &Sample{"Test"} -// http.HandleFunc("/", s.Handler) -// http.ListenAndServe(":8080", nil) -//} +// NewSampleHandler returns a new sample handler function +func NewSampleHandler(name string) http.Handler { + s := &Sample{"test"} + fmt.Println("in NewSample", name, version, s) + return s +} diff --git a/example/test_plugin/plugin_test.go b/example/test_plugin/plugin_test.go new file mode 100644 index 00000000..a46488ab --- /dev/null +++ b/example/test_plugin/plugin_test.go @@ -0,0 +1,77 @@ +package main + +import ( + "io/ioutil" + "log" + "net/http" + "net/http/httptest" + "testing" + + "github.com/containous/dyngo/interp" + "github.com/containous/dyngo/stdlib" +) + +func TestPlugin(t *testing.T) { + log.SetFlags(log.Lshortfile) // Debug: print source file locations in log output + + // Init go interpreter + i := interp.New(interp.Opt{}) + i.Use(stdlib.Value, stdlib.Type) // Use binary standard library + + // Load plugin from sources + if _, err := i.Eval(`import "github.com/containous/dyngo/example/test_plugin/plugin"`); err != nil { + t.Fatal(err) + } + + // Obtain a HTTP handler from the plugin + value, err := i.Eval(`plugin.NewSample("test")`) + if err != nil { + t.Fatal(err) + } + + handler := value.Interface().(func(http.ResponseWriter, *http.Request)) + + mux := http.NewServeMux() + mux.HandleFunc("/", handler) + + server := httptest.NewServer(mux) + defer server.Close() + + resp, err := http.DefaultClient.Get(server.URL) + if err != nil { + t.Fatal(err) + } + + bytes, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Fatal(err) + } + + expected := "Welcome to my website test v1\n" + if string(bytes) != expected { + t.Errorf("Got %s, want %s", string(bytes), expected) + } +} + +func TestPluginMethod(t *testing.T) { + log.SetFlags(log.Lshortfile) // Debug: print source file locations in log output + + // Init go interpreter + i := interp.New(interp.Opt{}) + i.Use(stdlib.Value, stdlib.Type) // Use binary standard library + + // Load plugin from sources + if _, err := i.Eval(`import "github.com/containous/dyngo/example/test_plugin/plugin"`); err != nil { + t.Fatal(err) + } + + // Obtain a HTTP handler from the plugin + value, err := i.Eval(`plugin.NewSampleHandler("test")`) + if err != nil { + t.Fatal(err) + } + + if _, ok := value.Interface().(http.Handler); ok { + t.Fatal("methods can be used, it's not possible") + } +} diff --git a/example/test_plugin/server.go b/example/test_plugin/server.go deleted file mode 100644 index 94468f07..00000000 --- a/example/test_plugin/server.go +++ /dev/null @@ -1,36 +0,0 @@ -package main - -import ( - "log" - "net/http" - - "github.com/containous/dyngo/interp" - "github.com/containous/dyngo/stdlib" -) - -// This program starts an interpreter which loads a plugin to handle HTTP requests - -func main() { - log.SetFlags(log.Lshortfile) // Debug: print source file locations in log output - - // Init go interpreter - i := interp.New(interp.Opt{}) - i.Use(stdlib.Value, stdlib.Type) // Use binary standard library - - // Load plugin from sources - if _, err := i.Eval(`import "github.com/containous/dyngo/example/test_plugin/plugin"`); err != nil { - log.Fatal(err) - } - - // Obtain a HTTP handler from the plugin - value, err := i.Eval(`plugin.NewSample("test")`) - if err != nil { - log.Fatal(err) - } - handler := value.Interface().(func(http.ResponseWriter, *http.Request)) - - http.HandleFunc("/", handler) - if err = http.ListenAndServe(":8080", nil); err != nil { - log.Fatal(err) - } -}