static val_ptr eval_assign(tree_ptr t) { tree_ptr tid = (tree_ptr)darray_at(t->child, 0); val_ptr v = tree_eval((tree_ptr)darray_at(t->child, 1)); if (symtab_at(reserved, tid->id)) { return val_new_error("%s is reserved", tid->id); } symtab_put(tab, v, tid->id); return v; }
static val_ptr eval_ternary(tree_ptr t) { val_ptr x = tree_eval((tree_ptr)darray_at(t->child, 0)); if (v_error == x->type) { return x; } if (x->type != v_elem) { return val_new_error("element expected in ternary operator"); } if (!element_is0(x->elem)) { return tree_eval((tree_ptr)darray_at(t->child, 1)); } return tree_eval((tree_ptr)darray_at(t->child, 2)); }
static val_ptr v_field_cast(val_ptr v, tree_ptr t) { // TODO: Check args, x is an element. val_ptr x = tree_eval((tree_ptr)darray_at(t->child, 0)); element_ptr e = x->elem; if (e->field == M) { if (v->field == M) return x; element_ptr e2 = element_new(v->field); if (element_is0(e)) // if 'set0' is not 'set1' in base field of GT, but we hope 'GT(0)' calls 'set1', we may directly call 'element_set0' here element_set0(e2); else if (element_is1(e)) // reason is same as above element_set1(e2); else element_set_multiz(e2, (multiz)e->data); x->elem = e2; return x; } if (v->field == M) { // Map to/from integer. TODO: Map to/from multiz instead. mpz_t z; mpz_init(z); element_to_mpz(z, e); element_clear(e); element_init(e, v->field); element_set_mpz(e, z); mpz_clear(z); } return x; }
int hash_insert(struct hash *hash, const char *key, void *mem, free_func *freer) { unsigned i, h; struct hash_bucket *bucket = malloc(sizeof *bucket), *iter; if (!bucket) return -1; bucket->key = string_dup(key); if (!bucket->key) { free(bucket); return -1; } bucket->mem = mem; h = hashstr(key, hash->max_size); for (i = 0; i < hash->buckets[h].length; ++i) { darray_at(&hash->buckets[h], i, (void **)&iter); if (!strcmp(iter->key, bucket->key)) { if (freer) freer(hash->buckets[h].mem[i]); hash->buckets[h].mem[i] = bucket; return 0; } } darray_push_back(&hash->buckets[h], bucket); return 0; }
static val_ptr eval_define(tree_ptr t) { val_ptr v = (val_ptr)pbc_malloc(sizeof(*v)); v->type = v_def; v->def = t; symtab_put(tab, v, ((tree_ptr)darray_at(t->child, 0))->id); return v; }
static val_ptr v_def_call(val_ptr v, tree_ptr t) { int i; const char* name = ((tree_ptr)darray_at(v->def->child, 0))->id; darray_ptr parm = ((tree_ptr)darray_at(v->def->child, 1))->child; int n = darray_count(parm); if (1 + n != darray_count(t->child)) { return val_new_error("%s: wrong number of arguments", name); } for (i = 0; i < n; i++) { const char *id = ((tree_ptr)darray_at(parm, i))->id; val_ptr v1 = tree_eval((tree_ptr)darray_at(t->child, i)); // TODO: Stack frames for recursion. symtab_put(tab, v1, id); } // Evaluate function body. darray_ptr a = ((tree_ptr)darray_at(v->def->child, 2))->child; darray_forall(a, eval_stmt); return NULL; }
void hash_values(struct hash *hash, struct darray *arr) { unsigned i, j; struct hash_bucket *iter; for (i = 0; i < hash->max_size; ++i) { for (j = 0; j < hash->buckets[i].length; ++j) { darray_at(&hash->buckets[i], j, (void **)&iter); darray_push_back(arr, iter->mem); } } }
void hash_remove(struct hash *hash, const char *key, free_func *freer) { unsigned i, h; struct hash_bucket *iter; h = hashstr(key, hash->max_size); for (i = 0; i < hash->buckets[h].length; ++i) { darray_at(&hash->buckets[h], i, (void **)&iter); if (!strcmp(iter->key, key)) { darray_remove(&hash->buckets[h], freer, i); break; } } }
int hash_exists(struct hash *hash, const char *key) { unsigned i, h; struct hash_bucket *iter; h = hashstr(key, hash->max_size); for (i = 0; i < hash->buckets[h].length; ++i) { darray_at(&hash->buckets[h], i, (void **)&iter); if (!strcmp(iter->key, key)) { return 1; } } return 0; }
static val_ptr v_builtin(val_ptr v, tree_ptr t) { fun_ptr fun = v->fun; int n = fun->arity; if (1 + n != darray_count(t->child)) { return val_new_error("%s: wrong number of arguments", fun->name); } val_ptr arg[n]; int i; for(i = 0; i < n; i++) { arg[i] = tree_eval(darray_at(t->child, i)); if (fun->sig[i] && arg[i]->type != fun->sig[i]) { return val_new_error("%s: argument %d type mismatch", fun->name, i + 1); } } return fun->run(arg); }
void hash_at(struct hash *hash, const char *key, void **mem) { unsigned i, h; struct hash_bucket *iter; h = hashstr(key, hash->max_size); for (i = 0; i < hash->buckets[h].length; ++i) { darray_at(&hash->buckets[h], i, (void **)&iter); if (!strcmp(iter->key, key)) { *mem = iter->mem; return; } } *mem = NULL; }
void hash_uninit(struct hash *hash, free_func *freer) { unsigned i, j; struct hash_bucket *iter; for (i = 0; i < hash->max_size; ++i) { for (j = 0; j < hash->buckets[i].length; ++j) { darray_at(&hash->buckets[i], j, (void **)&iter); free(iter->key); if (freer) freer(iter->mem); } darray_uninit(&hash->buckets[i], free); } free(hash->buckets); }
static val_ptr eval_list(tree_ptr t) { element_ptr e = NULL; int n = darray_count(t->child); int i; for (i = 0; i < n; i++) { val_ptr x = tree_eval((tree_ptr)darray_at(t->child, i)); // TODO: Also check x is a multiz. if (v_error == x->type) { return x; } if (v_elem != x->type) { return val_new_error("element expected in list"); } if (!i) e = multiz_new_list(x->elem); else multiz_append(e, x->elem); } return val_new_element(e); }
static val_ptr v_builtin(val_ptr v, tree_ptr t) { fun_ptr fun = v->fun; int n = fun->arity; if (1 + n != darray_count(t->child)) { return val_new_error("%s: wrong number of arguments", fun->name); } #ifdef _MSC_VER // for VC++ compatibility val_ptr arg[MAX_LIMBS]; #else val_ptr arg[n]; #endif int i; for (i = 0; i < n; i++) { arg[i] = tree_eval((tree_ptr)darray_at(t->child, i)); if (fun->sig[i] && arg[i]->type != fun->sig[i]) { return val_new_error("%s: argument %d type mismatch", fun->name, i + 1); } } return fun->run(arg); }
static val_ptr v_field_cast(val_ptr v, tree_ptr t) { // TODO: Check args, x is an element. val_ptr x = tree_eval(darray_at(t->child, 0)); element_ptr e = x->elem; if (e->field == M) { if (v->field == M) return x; element_ptr e2 = element_new(v->field); element_set_multiz(e2, e->data); x->elem = e2; return x; } if (v->field == M) { // Map to/from integer. TODO: Map to/from multiz instead. mpz_t z; mpz_init(z); element_to_mpz(z, e); element_clear(e); element_init(e, v->field); element_set_mpz(e, z); mpz_clear(z); } return x; }
uint32_t zdd_intersection() { vmax_check(); if (darray_count(stack) == 0) return 0; if (darray_count(stack) == 1) return (uint32_t) darray_last(stack); uint32_t z0 = (uint32_t) darray_at(stack, darray_count(stack) - 2); uint32_t z1 = (uint32_t) darray_remove_last(stack); struct node_template_s { uint16_t v; // NULL means this template have been instantiated. // Otherwise it points to the LO template. memo_it lo; union { // Points to HI template when template is not yet instantiated. memo_it hi; // During template instantiation we set n to the pool index // of the newly created node. uint32_t n; }; }; typedef struct node_template_s *node_template_ptr; typedef struct node_template_s node_template_t[1]; node_template_t top, bot; bot->v = 0; bot->lo = NULL; bot->n = 0; top->v = 1; top->lo = NULL; top->n = 1; // Naive implementation with two tries. One stores templates, the other // unique nodes. See Knuth for how to meld using just memory allocated // for a pool of nodes. memo_t tab; memo_init(tab); memo_it insert_template(uint32_t k0, uint32_t k1) { uint32_t key[2]; // Taking advantage of symmetry of intersection appears to help a tiny bit. if (k0 < k1) { key[0] = k0; key[1] = k1; } else { key[0] = k1; key[1] = k0; } memo_it it; int just_created = memo_it_insert_u(&it, tab, (void *) key, 8); if (!just_created) return it; if (!k0 || !k1) { memo_it_put(it, bot); return it; } if (k0 == 1 && k1 == 1) { memo_it_put(it, top); return it; } node_ptr n0 = pool[k0]; node_ptr n1 = pool[k1]; if (n0->v == n1->v) { node_template_ptr t = malloc(sizeof(*t)); t->v = n0->v; if (n0->lo == n0->hi && n1->lo == n0->hi) { t->lo = t->hi = insert_template(n0->lo, n1->lo); } else { t->lo = insert_template(n0->lo, n1->lo); t->hi = insert_template(n0->hi, n1->hi); } memo_it_put(it, t); return it; } else if (n0->v < n1->v) { memo_it it2 = insert_template(n0->lo, k1); memo_it_put(it, memo_it_data(it2)); return it2; } else { memo_it it2 = insert_template(k0, n1->lo); memo_it_put(it, memo_it_data(it2)); return it2; } }
static void v_define_out(FILE* stream, val_ptr v) { fprintf(stream, "user-defined function %s", ((tree_ptr)darray_at(v->def->child, 0))->id); }