#include #include #include #include #include #include "ply.h" struct providers { provider_t **prov; size_t len; } providers; provider_t *provider_get(const char *name) { size_t i; for (i = 0; i < providers.len; i++) { if (strstr(providers.prov[i]->name, name) == providers.prov[i]->name) return providers.prov[i]; } return NULL; } void provider_register(provider_t *prov) { assert(prov); assert(prov->probe); assert(prov->resolve); providers.prov = realloc(providers.prov, ++providers.len * sizeof(*providers.prov)); providers.prov[providers.len - 1] = prov; } typedef struct pass pass_t; struct pass { int (*run)(pass_t *, prog_t *); walk_fn pre; walk_fn post; }; symtab_t globals = { .sym = NULL, .len = 0 }; symtab_t locals = { .sym = NULL, .len = 0 }; prog_t *prog_get(void) { prog_t *prog; prog = calloc(1, sizeof(*prog)); prog->locals = &locals; prog->globals = &globals; prog->probe = "k:SyS_read"; /* { reads{pid()} @ quantize(arg2) } */ prog->ast = node_expr('@', node_cons( node_expr('m', node_cons( node_ident("reads"), node_expr('(', node_ident("pid")) ) ), node_expr('(', node_cons( node_ident("quantize"), node_ident("arg2") ) ) ) ); prog->provider = provider_get("k"); prog->provider->probe(prog); return prog; } int symtab_populate(node_t *n, void *_prog) { prog_t *prog = _prog; provider_t *global = provider_get(":"); int err; if ((n->ntype != N_ATOM) || (n->atom.atype != A_IDENT)) return 0; /* .IDENT/->IDENT is a struct/union member, skip */ if (n->up && (n->up->ntype == N_EXPR) && ((n->up->expr.etype == E_DOT) || (n->up->expr.etype == E_DEREF)) && (n != n->up->expr.arg)) return 0; err = prog->provider->resolve(prog, n); if (!err || err != -ENOENT) return err; return global->resolve(prog, n); } int pass_walk(pass_t *pass, prog_t *prog) { return node_walk(prog->ast, pass->pre, pass->post, prog); } pass_t passes[] = { { .run = pass_walk, .pre = symtab_populate }, { NULL } }; int main(void) { node_dump_info_t info = { .indent = 2, .fp = stdout, }; prog_t *prog = prog_get(); pass_t *pass; int err; for (pass = passes; pass->run; pass++) { err = pass->run(pass, prog); if (err) break; } printf("AST\n===\n"); node_dump(prog->ast, &info); printf("\nLOCALS\n======\n"); symtab_dump(prog->locals, stdout); printf("\nGLOBALS\n=======\n"); symtab_dump(prog->globals, stdout); printf("\nTYPES\n=====\n"); types_dump_cdecl(stdout); return err; }