import vec:* import str:* // for decent to string // should be fixed by UFCS or decent scoping on template types import ast:* import type2:* adt binding_epoch { pre_ref, post_ref, all } var bindings: *vec<*void> fun binding(): *binding { return binding(null(), binding_epoch::all()) } fun binding_p(it: T, epoch: binding_epoch): *binding { var p = new() p->copy_construct(&it) return binding(p, epoch) } fun binding(it: *T, epoch: binding_epoch): *binding { var to_ret = new>()->construct(it, epoch) if (bindings == null>()) bindings = new>()->construct() bindings->add( (to_ret) cast *void ) return to_ret } obj binding (Object) { var bound_to_pre_ref: *T var bound_to_post_ref: *T fun construct(): *binding { bound_to_pre_ref = null() bound_to_post_ref = null() return this } fun construct(it: *T, epoch: binding_epoch): *binding { bound_to_pre_ref = null() bound_to_post_ref = null() set_single(it, epoch) return this } fun copy_construct(old: *binding): void { bound_to_pre_ref = old->bound_to_pre_ref bound_to_post_ref = old->bound_to_post_ref } fun destruct() { bound_to_pre_ref = null() bound_to_post_ref = null() } fun bound(epoch: binding_epoch): bool { return bound_to_pre_ref != null() || bound_to_post_ref != null() } fun set(to: T, epoch: binding_epoch) { var p = new() p->copy_construct(&to) set(p, epoch) } fun set(to: *T, epoch: binding_epoch) { var pre_ref_from = bound_to_pre_ref var post_ref_from = bound_to_post_ref if epoch == binding_epoch::pre_ref() || epoch == binding_epoch::all() { bound_to_pre_ref = to // don't set null, that will set all unbound ones if pre_ref_from != null() { for (var i = 0; i < bindings->size; i++;) if ( ((bindings->get(i)) cast *binding)->bound_to_pre_ref == pre_ref_from) ((bindings->get(i)) cast *binding)->bound_to_pre_ref = to } } if epoch == binding_epoch::post_ref() || epoch == binding_epoch::all() { bound_to_post_ref = to // don't set null, that will set all unbound ones if post_ref_from != null() { for (var i = 0; i < bindings->size; i++;) if ( ((bindings->get(i)) cast *binding)->bound_to_post_ref == post_ref_from) ((bindings->get(i)) cast *binding)->bound_to_post_ref = to } } } fun set_single(to: T, epoch: binding_epoch) { var p = new() p->copy_construct(&to) set_single(p, epoch) } fun set_single(to: *T, epoch: binding_epoch) { match (epoch) { binding_epoch::pre_ref() { bound_to_pre_ref = to; } binding_epoch::post_ref() { bound_to_post_ref = to; } binding_epoch::all() { bound_to_pre_ref = to; bound_to_post_ref = to; } } } fun bound(): bool { return bound_to_pre_ref != null() || bound_to_post_ref != null() } fun get_bound_to(epoch: binding_epoch): *T { match (epoch) { binding_epoch::pre_ref() { return bound_to_pre_ref; } binding_epoch::post_ref() if bound_to_post_ref != null() { return bound_to_post_ref; } else { return bound_to_pre_ref; } binding_epoch::all() { error("trying to get_bound_to for all, which doesn't make any sense"); } } } fun to_string(): str { /*return "binding(" + to_string(bound_to) + ")"*/ return "binding(pre_ref:" + deref_to_string(bound_to_pre_ref) + "/post_ref:" + deref_to_string(bound_to_post_ref) + ")" } }