All Downloads are FREE. Search and download functionalities are using the official Maven repository.

sjsonnet.ValScope.scala Maven / Gradle / Ivy

The newest version!
package sjsonnet

import java.util.Arrays

/**
 * [[ValScope]]s which model the lexical scopes within a Jsonnet file that bind variable names to
 * [[Val]]s, as well as other contextual information like `self` `this` or `super`.
 *
 * Note that scopes are standalone, and nested scopes are done by copying and updating the array of
 * bindings rather than using a linked list. This is because the bindings array is typically pretty
 * small and the constant factor overhead from a cleverer data structure dominates any algorithmic
 * improvements
 *
 * The bindings array is private and only copy-on-write, so for nested scopes which do not change it
 * (e.g. those just updating `dollar0` or `self0`) the bindings array can be shared cheaply.
 */
final class ValScope private (val bindings: Array[Lazy]) extends AnyVal {

  def length: Int = bindings.length

  def extend(
      newBindingsF: Array[(Val.Obj, Val.Obj) => Lazy] = null,
      newSelf: Val.Obj,
      newSuper: Val.Obj): ValScope = {
    val by = if (newBindingsF == null) 2 else newBindingsF.length + 2
    val b = Arrays.copyOf(bindings, bindings.length + by)
    b(bindings.length) = newSelf
    b(bindings.length + 1) = newSuper
    if (newBindingsF != null) {
      var i = 0
      var j = bindings.length + 2
      while (i < newBindingsF.length) {
        b(j) = newBindingsF(i).apply(newSelf, newSuper)
        i += 1
        j += 1
      }
    }
    new ValScope(b)
  }

  def extendSimple(newBindingsV: Array[? <: Lazy]): ValScope = {
    if (newBindingsV == null || newBindingsV.length == 0) this
    else {
      val b = Arrays.copyOf(bindings, bindings.length + newBindingsV.length)
      System.arraycopy(newBindingsV, 0, b, bindings.length, newBindingsV.length)
      new ValScope(b)
    }
  }

  def extendBy(num: Int): ValScope =
    if (num == 0) this
    else new ValScope(Arrays.copyOf(bindings, bindings.length + num))

  def extendSimple(l1: Lazy): ValScope = {
    val b = Arrays.copyOf(bindings, bindings.length + 1)
    b(bindings.length) = l1
    new ValScope(b)
  }

  def extendSimple(l1: Lazy, l2: Lazy): ValScope = {
    val b = Arrays.copyOf(bindings, bindings.length + 2)
    b(bindings.length) = l1
    b(bindings.length + 1) = l2
    new ValScope(b)
  }

  def extendSimple(l1: Lazy, l2: Lazy, l3: Lazy): ValScope = {
    val b = Arrays.copyOf(bindings, bindings.length + 3)
    b(bindings.length) = l1
    b(bindings.length + 1) = l2
    b(bindings.length + 2) = l3
    new ValScope(b)
  }
}

object ValScope {
  private val emptyArr = new Array[Lazy](0)
  def empty = new ValScope(emptyArr)
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy