| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 |
- #define _GNU_SOURCE /* asprintf */
- #include <assert.h>
- #include <errno.h>
- #include <stdlib.h>
- #include <string.h>
- #include "arch.h"
- #include "func.h"
- #include "node.h"
- #include "ply.h"
- #include "sym.h"
- #include "type.h"
- static struct type *global_map_ktype(struct node *n)
- {
- struct node *map, *key;
- struct type *ktype;
- struct tfield *kfields, *f;
- int i, nargs = node_nargs(n);
- char *kname;
- map = n->expr.args;
- if (node_nargs(n) == 2)
- return map->next->sym->type;
- ktype = calloc(1, sizeof(*ktype));
- assert(ktype);
- kfields = calloc(nargs, sizeof(*kfields));
- assert(kfields);
- for (key = map->next, f = kfields, i = 0; key; key = key->next, f++, i++) {
- asprintf(&f->name, "k%d", i);
- f->type = key->sym->type;
- }
- f->type = &t_void;
- asprintf(&ktype->sou.name, ":%s_key", map->ident.name);
- ktype->ttype = T_STRUCT;
- ktype->sou.fields = kfields;
- type_add(ktype);
- return ktype;
- }
- static int global_assign_type_infer_map(struct node *n)
- {
- struct node *map, *key;
- struct type *ktype;
- map = n->expr.args;
- for (key = map->next; key; key = key->next) {
- if (type_sizeof(key->sym->type) < 0)
- return 0;
- }
- map->sym->type = type_map_of(global_map_ktype(n), n->sym->type);
- return 0;
- }
- static int global_assign_type_infer(struct prog *prog, struct node *n)
- {
- struct node *lval, *rval;
- lval = n->expr.args;
- rval = lval->next;
- if (!rval->sym->type)
- return 0;
- if (!lval->sym->type) {
- lval->sym->type = rval->sym->type;
- if (node_is_map(lval))
- return global_assign_type_infer_map(lval);
- return 0;
- }
- if (type_compatible(lval->sym->type, rval->sym->type))
- return 0;
- if (lval->ntype == N_IDENT) {
- node_error(n, stderr, "conflicting types for '%s'",
- lval->ident.name);
- } else {
- node_error(n, stderr, "conflicting types for '%s'",
- lval->expr.args->ident.name);
- }
- return -EINVAL;
- }
- static int global_assign_static_verify(struct node *n)
- {
- struct node *lval;
- int nargs = node_nargs(n);
- if (nargs != 2) {
- node_error(n, stderr, "assignment operator expects 2 arguments,"
- " %d given", nargs);
- return -EINVAL;
- }
- lval = n->expr.args;
- if (node_is_map(lval) || (lval->ntype == N_IDENT))
- return 0;
- node_error(n, stderr, "assignment destination must be a variable or map");
- return -EINVAL;
- }
- struct type t_pid = {
- .ttype = T_TYPEDEF,
- .tdef = { .name = ":pid", .type = &t_u32 },
- };
- struct type t_time = {
- .ttype = T_TYPEDEF,
- .tdef = { .name = ":time", .type = &t_s64 },
- };
- static const struct func global_funcs[] = {
- { .name = ":block", .type = &t_void, },
- { .name = "+", },
- { .name = "-", },
-
- {
- .name = ":assign",
- .static_verify = global_assign_static_verify,
- .type_infer = global_assign_type_infer,
- },
- {
- .name = ":map",
- /* .static_verify = global_map_static_verify, */
- /* .type_infer = global_map_type_infer, */
- },
- { .name = "pid", .type = &t_pid, },
- { .name = "time", .type = &t_time, },
- { .name = "quantize", },
-
- { .name = NULL }
- };
- static const struct func global_num_func = {
- .name = ":num",
- .type = &t_int,
- };
- struct type t_string_array = {
- .ttype = T_ARRAY,
- .array = { .type = &t_char, .len = 64 }, /* TODO: tunable */
- };
- struct type t_string = {
- .ttype = T_TYPEDEF,
- .tdef = { .name = ":string", .type = &t_string_array },
- };
- static const struct func global_string_func = {
- .name = ":string",
- .type = &t_string,
- };
- static const struct func global_ident_func = {
- .name = ":ident",
- };
- static const struct func *global_sym_alloc_expr(struct node *n)
- {
- const struct func *func;
- int err;
- for (func = global_funcs; func->name; func++) {
- if (strcmp(func->name, n->expr.func))
- continue;
- return func;
- }
- return NULL;
- }
- int global_sym_alloc(struct prog *prog, struct node *n)
- {
- const struct func *func;
- struct symtab *st = prog->locals;
- int err;
- switch (n->ntype) {
- case N_EXPR:
- func = global_sym_alloc_expr(n);
- break;
- case N_IDENT:
- st = prog->globals;
- func = &global_ident_func;
- break;
- case N_NUM:
- func = &global_num_func;
- break;
- case N_STRING:
- func = &global_string_func;
- break;
- }
- if (!func)
- return -ENOENT;
- if (func->static_verify) {
- err = func->static_verify(n);
- if (err)
- return err;
- }
- n->sym = sym_alloc(st, n, func);
- if (func->type)
- /* return type is static, fill it now */
- n->sym->type = func->type;
- return 0;
- }
- int global_probe(struct prog *prog)
- {
- return 0;
- }
- struct provider global = {
- .name = ":",
- .sym_alloc = global_sym_alloc,
- .probe = global_probe,
- };
- __attribute__((constructor))
- static void global_init(void)
- {
- provider_register(&global);
- }
|