<commit_before><commit_msg>Some more work on implicit attributes.<commit_after>package coconut.ui.internal;

import tink.state.ObservableMap;

class ImplicitContext {
  final parent:Null<ImplicitContext>;
  final values:ObservableMap<TypeKey<Dynamic>, Dynamic> = new ObservableMap(cast new haxe.ds.ObjectMap());

  public function new(?parent) {
    this.parent = parent;
  }

  public function get<T>(key:TypeKey<T>, getDefault:()->T)
    return switch [values.get(key), parent] {
      case [null, null]: getDefault();
      case [null, p]: p.get(key, getDefault);
      case [v, _]: v;
    }

  public function update(values:ImplicitValues) {
    // TODO: this makes me realize that an atomic update for the whole map content would be nice
    {
      var old = [for (v in this.values.keys()) if (!values.exists(v)) v];
      for (o in old)
        this.values.remove(o);
    }
    for (k => v in values)
      this.values.set(k, v);
  }
}

abstract TypeKey<T>({}) to {} {
  @:from static function ofClass<T>(t:Class<T>):TypeKey<T>
    return cast t;
  @:from static function ofEnum<T>(t:Enum<T>):TypeKey<T>
    return cast t;
}

@:pure
@:forward(exists, keyValueIterator)
abstract ImplicitValues(Map<TypeKey<Dynamic>, Dynamic>) {
  inline function new(v) this = v;
}
{'fraction_non_alphanumeric': 0.14330708661417324, 'fraction_numerical': 0.0, 'mean_word_length': 3.832699619771863, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5384477', 'n_tokens_mistral': 427, 'n_tokens_neox': 416, 'n_words': 114}