<commit_before>import Reference, { PathReference } from './reference';
import { Opaque, Option, Slice, LinkedListNode } from '@glimmer/util';

//////////

export interface EntityTag<T> extends Reference<T> {
  value(): T;
  validate(snapshot: T): boolean;
}

export interface EntityTagged<T> {
  tag: EntityTag<T>;
}

export interface Tagged {
  tag: Tag;
}

//////////

export type Revision = number;

export const CONSTANT: Revision = 0;
export const INITIAL: Revision = 1;
export const VOLATILE: Revision = NaN;

export abstract class RevisionTag implements EntityTag<Revision> {
  static id = 0;

  abstract value(): Revision;

  validate(snapshot: Revision): boolean {
    return this.value() === snapshot;
  }
}

const VALUE: ((tag: Option<RevisionTag>) => Revision)[] = [];
const VALIDATE: ((tag: Option<RevisionTag>, snapshot: Revision) => boolean)[] = [];

export class TagWrapper<T extends RevisionTag | null> {
  constructor(private type: number, public inner: T) {}

  value(): Revision {
    let func = VALUE[this.type];
    return func(this.inner);
  }

  validate(snapshot: Revision): boolean {
    let func = VALIDATE[this.type];
    return func(this.inner, snapshot);
  }
}

export type Tag = TagWrapper<RevisionTag | null>;

function register(Type: { create(...args: any[]): Tag; id: number }) {
  let type = VALUE.length;
  VALUE.push((tag: Option<RevisionTag>) => tag!.value());
  VALIDATE.push((tag: Option<RevisionTag>, snapshot: Revision) => tag!.validate(snapshot));
  Type.id = type;
}

///

// CONSTANT: 0
VALUE.push(() => CONSTANT);
VALIDATE.push((_tag, snapshot) => snapshot === CONSTANT);
export const CONSTANT_TAG = new TagWrapper(0, null);

// VOLATILE: 1
VALUE.push(() => VOLATILE);
VALIDATE.push((_tag, snapshot) => snapshot === VOLATILE);
export const VOLATILE_TAG = new TagWrapper(1, null);

// CURRENT: 2
VALUE.push(() => $REVISION);
VALIDATE.push((_tag, snapshot) => snapshot === $REVISION);
export const CURRENT_TAG = new TagWrapper(2, null);

export function isConst({ tag }: Tagged): boolean {
  return tag === CONSTANT_TAG;
}

export function isConstTag(tag: Tag): boolean {
  return tag === CONSTANT_TAG;
}

///

let $REVISION = INITIAL;

export function bump() {
  $REVISION++;
}

export class DirtyableTag extends RevisionTag {
  static create(revision = $REVISION) {
    return new TagWrapper(this.id, new DirtyableTag(revision));
  }

  private revision: Revision;

  constructor(revision = $REVISION) {
    super();
    this.revision = revision;
  }

  value(): Revision {
    return this.revision;
  }

  dirty() {
    this.revision = ++$REVISION;
  }
}

register(DirtyableTag);

export function combineTagged(tagged: ReadonlyArray<Tagged>): Tag {
  let optimized: Tag[] = [];

  for (let i = 0, l = tagged.length; i < l; i++) {
    let tag = tagged[i].tag;
    if (tag === VOLATILE_TAG) return VOLATILE_TAG;
    if (tag === CONSTANT_TAG) continue;
    optimized.push(tag);
  }

  return _combine(optimized);
}

export function combineSlice(slice: Slice<Tagged & LinkedListNode>): Tag {
  let optimized: Tag[] = [];

  let node = slice.head();

  while (node !== null) {
    let tag = node.tag;

    if (tag === VOLATILE_TAG) return VOLATILE_TAG;
    if (tag !== CONSTANT_TAG) optimized.push(tag);

    node = slice.nextNode(node);
  }

  return _combine(optimized);
}

export function combine(tags: Tag[]): Tag {
  let optimized: Tag[] = [];

  for (let i = 0, l = tags.length; i < l; i++) {
    let tag = tags[i];
    if (tag === VOLATILE_TAG) return VOLATILE_TAG;
    if (tag === CONSTANT_TAG) continue;
    optimized.push(tag);
  }

  return _combine(optimized);
}

function _combine(tags: Tag[]): Tag {
  switch (tags.length) {
    case 0:
      return CONSTANT_TAG;
    case 1:
      return tags[0];
    case 2:
      return TagsPair.create(tags[0], tags[1]);
    default:
      return TagsCombinator.create(tags);
  }
}

export abstract class CachedTag extends RevisionTag {
  private lastChecked: Option<Revision> = null;
  private lastValue: Option<Revision> = null;

  value(): Revision {
    let { lastChecked, lastValue } = this;

    if (lastChecked !== $REVISION) {
      this.lastChecked = $REVISION;
      this.lastValue = lastValue = this.compute();
    }

    return this.lastValue as Revision;
  }

  protected invalidate() {
    this.lastChecked = null;
  }

  protected abstract compute(): Revision;<commit_msg>reference/validators: Remove unused `lastValue` variable<commit_after>import Reference, { PathReference } from './reference';
import { Opaque, Option, Slice, LinkedListNode } from '@glimmer/util';

//////////

export interface EntityTag<T> extends Reference<T> {
  value(): T;
  validate(snapshot: T): boolean;
}

export interface EntityTagged<T> {
  tag: EntityTag<T>;
}

export interface Tagged {
  tag: Tag;
}

//////////

export type Revision = number;

export const CONSTANT: Revision = 0;
export const INITIAL: Revision = 1;
export const VOLATILE: Revision = NaN;

export abstract class RevisionTag implements EntityTag<Revision> {
  static id = 0;

  abstract value(): Revision;

  validate(snapshot: Revision): boolean {
    return this.value() === snapshot;
  }
}

const VALUE: ((tag: Option<RevisionTag>) => Revision)[] = [];
const VALIDATE: ((tag: Option<RevisionTag>, snapshot: Revision) => boolean)[] = [];

export class TagWrapper<T extends RevisionTag | null> {
  constructor(private type: number, public inner: T) {}

  value(): Revision {
    let func = VALUE[this.type];
    return func(this.inner);
  }

  validate(snapshot: Revision): boolean {
    let func = VALIDATE[this.type];
    return func(this.inner, snapshot);
  }
}

export type Tag = TagWrapper<RevisionTag | null>;

function register(Type: { create(...args: any[]): Tag; id: number }) {
  let type = VALUE.length;
  VALUE.push((tag: Option<RevisionTag>) => tag!.value());
  VALIDATE.push((tag: Option<RevisionTag>, snapshot: Revision) => tag!.validate(snapshot));
  Type.id = type;
}

///

// CONSTANT: 0
VALUE.push(() => CONSTANT);
VALIDATE.push((_tag, snapshot) => snapshot === CONSTANT);
export const CONSTANT_TAG = new TagWrapper(0, null);

// VOLATILE: 1
VALUE.push(() => VOLATILE);
VALIDATE.push((_tag, snapshot) => snapshot === VOLATILE);
export const VOLATILE_TAG = new TagWrapper(1, null);

// CURRENT: 2
VALUE.push(() => $REVISION);
VALIDATE.push((_tag, snapshot) => snapshot === $REVISION);
export const CURRENT_TAG = new TagWrapper(2, null);

export function isConst({ tag }: Tagged): boolean {
  return tag === CONSTANT_TAG;
}

export function isConstTag(tag: Tag): boolean {
  return tag === CONSTANT_TAG;
}

///

let $REVISION = INITIAL;

export function bump() {
  $REVISION++;
}

export class DirtyableTag extends RevisionTag {
  static create(revision = $REVISION) {
    return new TagWrapper(this.id, new DirtyableTag(revision));
  }

  private revision: Revision;

  constructor(revision = $REVISION) {
    super();
    this.revision = revision;
  }

  value(): Revision {
    return this.revision;
  }

  dirty() {
    this.revision = ++$REVISION;
  }
}

register(DirtyableTag);

export function combineTagged(tagged: ReadonlyArray<Tagged>): Tag {
  let optimized: Tag[] = [];

  for (let i = 0, l = tagged.length; i < l; i++) {
    let tag = tagged[i].tag;
    if (tag === VOLATILE_TAG) return VOLATILE_TAG;
    if (tag === CONSTANT_TAG) continue;
    optimized.push(tag);
  }

  return _combine(optimized);
}

export function combineSlice(slice: Slice<Tagged & LinkedListNode>): Tag {
  let optimized: Tag[] = [];

  let node = slice.head();

  while (node !== null) {
    let tag = node.tag;

    if (tag === VOLATILE_TAG) return VOLATILE_TAG;
    if (tag !== CONSTANT_TAG) optimized.push(tag);

    node = slice.nextNode(node);
  }

  return _combine(optimized);
}

export function combine(tags: Tag[]): Tag {
  let optimized: Tag[] = [];

  for (let i = 0, l = tags.length; i < l; i++) {
    let tag = tags[i];
    if (tag === VOLATILE_TAG) return VOLATILE_TAG;
    if (tag === CONSTANT_TAG) continue;
    optimized.push(tag);
  }

  return _combine(optimized);
}

function _combine(tags: Tag[]): Tag {
  switch (tags.length) {
    case 0:
      return CONSTANT_TAG;
    case 1:
      return tags[0];
    case 2:
      return TagsPair.create(tags[0], tags[1]);
    default:
      return TagsCombinator.create(tags);
  }
}

export abstract class CachedTag extends RevisionTag {
  private lastChecked: Option<Revision> = null;
  private lastValue: Option<Revision> = null;

  value(): Revision {
    let { lastChecked } = this;

    if (lastChecked !== $REVISION) {
      this.lastChecked = $REVISION;
      this.lastValue = this.compute();
    }

    return this.lastValue as Revision;
  }

  protected invalidate() {
    this.lastChecked = null;
  }

  protected abstract compute(): Revision;
{'fraction_non_alphanumeric': 0.1498861047835991, 'fraction_numerical': 0.0038724373576309794, 'mean_word_length': 3.764514378730331, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 53, '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': '4617659', 'n_tokens_mistral': 3018, 'n_tokens_neox': 2916, 'n_words': 773}