aboutsummaryrefslogtreecommitdiff
path: root/sjs/backend/sjs/ScopedVar.scala
diff options
context:
space:
mode:
Diffstat (limited to 'sjs/backend/sjs/ScopedVar.scala')
-rw-r--r--sjs/backend/sjs/ScopedVar.scala38
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())
+ }
+}