diff options
Diffstat (limited to 'sjs/backend/sjs/ScopedVar.scala')
-rw-r--r-- | sjs/backend/sjs/ScopedVar.scala | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/sjs/backend/sjs/ScopedVar.scala b/sjs/backend/sjs/ScopedVar.scala new file mode 100644 index 000000000..0e47f7b79 --- /dev/null +++ b/sjs/backend/sjs/ScopedVar.scala @@ -0,0 +1,38 @@ +package dotty.tools.backend.sjs + +import language.implicitConversions + +class ScopedVar[A](init: A) { + import ScopedVar.Assignment + + private var value = init + + def this()(implicit ev: Null <:< A) = this(ev(null)) + + def get: A = value + def :=(newValue: A): Assignment[A] = new Assignment(this, newValue) +} + +object ScopedVar { + class Assignment[T](scVar: ScopedVar[T], value: T) { + private[ScopedVar] def push(): AssignmentStackElement[T] = { + val stack = new AssignmentStackElement(scVar, scVar.value) + scVar.value = value + stack + } + } + + private class AssignmentStackElement[T](scVar: ScopedVar[T], oldValue: T) { + private[ScopedVar] def pop(): Unit = { + scVar.value = oldValue + } + } + + implicit def toValue[T](scVar: ScopedVar[T]): T = scVar.get + + def withScopedVars[T](ass: Assignment[_]*)(body: => T): T = { + val stack = ass.map(_.push()) + try body + finally stack.reverse.foreach(_.pop()) + } +} |