// tracing: off
import "../Operator"
import { fromNullable, none } from "../Option"

const makeTag = (def = false, key = Symbol()) => ({
  _tag: "Tag",
  _T: undefined,
  key,
  def,
  of: (t) => ({
    [key]: t
  }),
  overridable: () => makeTag(true, key),
  fixed: () => makeTag(false, key),
  refine: () => makeTag(def, key),
  read: (r) => r[key],
  readOption: (r) =>
    typeof r === "object" && r !== null ? fromNullable(r[key]) : none,
  setKey: (s) => makeTag(def, s)
})

export function tag(_) {
  return makeTag()
}
/**
 * Replaces the service with the required Service Entry, in the specified environment
 */

export const replaceServiceIn = (_, f) => (r) => ({ ...r, [_.key]: f(r[_.key]) })
/**
 * Replaces the service with the required Service Entry, in the specified environment
 */

export const replaceServiceIn_ = (r, _, f) => ({ ...r, [_.key]: f(r[_.key]) })
/**
 * Flags the current Has to be overridable, when this is used subsequently provided
 * environments will override pre-existing. Useful to provide defaults.
 */

export const overridable = (h) => ({ ...h, def: true })
export function mergeEnvironments(_, r, t) {
  return _.def && r[_.key] ? r : { ...r, [_.key]: t }
}
export class DerivationContext {
  constructor() {
    this.hasMap = new Map()
  }

  derive(has, f) {
    const inMap = this.hasMap.get(has)

    if (inMap) {
      return inMap
    }

    const computed = f()
    this.hasMap.set(has, computed)
    return computed
  }
}
//# sourceMappingURL=index.js.map
