about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@mozilla.com>2012-10-17 16:40:18 -0700
committerGraydon Hoare <graydon@mozilla.com>2012-10-17 16:40:34 -0700
commitfdd7b4d8f4df135f30a3f04ff2f777bce1277d2a (patch)
treebefe5d4f34659285dbcfbcc60e2d02765c865ca5
parente7e1bab27fa8341467b5160506bbd580b5f6bbb7 (diff)
downloadrust-fdd7b4d8f4df135f30a3f04ff2f777bce1277d2a.tar.gz
rust-fdd7b4d8f4df135f30a3f04ff2f777bce1277d2a.zip
core: first working sketch of a condition system.
-rw-r--r--src/libcore/condition.rs117
-rw-r--r--src/libcore/core.rc1
2 files changed, 118 insertions, 0 deletions
diff --git a/src/libcore/condition.rs b/src/libcore/condition.rs
new file mode 100644
index 00000000000..5f61f2cd53b
--- /dev/null
+++ b/src/libcore/condition.rs
@@ -0,0 +1,117 @@
+// helper for transmutation, shown below.
+type RustClosure = (int,int);
+
+struct Condition {
+    key: task::local_data::LocalDataKey<Handler>
+}
+
+struct Handler {
+    // Handler should link to previous handler and
+    // reinstall it when popped.
+    handle: RustClosure
+}
+
+
+struct ProtectBlock {
+    cond: &Condition,
+    inner: RustClosure
+}
+
+struct PopHandler {
+    cond: &Condition,
+    drop {
+        unsafe {
+            task::local_data::local_data_pop(self.cond.key);
+        }
+    }
+}
+
+struct HandleBlock {
+    pb: &ProtectBlock,
+    handler: @Handler,
+    drop {
+        unsafe {
+            task::local_data::local_data_set(self.pb.cond.key,
+                                             self.handler);
+            let _pop = PopHandler { cond: self.pb.cond };
+            // transmutation to avoid copying non-copyable, should
+            // be fixable by tracking closure pointees in regionck.
+            let f : &fn() = ::cast::transmute(self.pb.inner);
+            f();
+        }
+    }
+}
+
+impl ProtectBlock {
+    fn handle<T, U: Copy>(&self, h: &self/fn(&T) ->U) -> HandleBlock/&self {
+        unsafe {
+            let p : *RustClosure = ::cast::transmute(&h);
+            HandleBlock { pb: self,
+                          handler: @Handler{handle: *p} }
+        }
+    }
+}
+
+
+impl Condition {
+
+    fn protect(&self, inner: &self/fn()) -> ProtectBlock/&self {
+        unsafe {
+            // transmutation to avoid copying non-copyable, should
+            // be fixable by tracking closure pointees in regionck.
+            let p : *RustClosure = ::cast::transmute(&inner);
+            ProtectBlock { cond: self,
+                           inner: *p } }
+    }
+
+    fn raise<T, U: Copy>(t:&T) -> U {
+        unsafe {
+            match task::local_data::local_data_get(self.key) {
+                None => fail,
+                Some(handler) => {
+                    io::println("got handler");
+                    let f : &fn(&T) -> U = ::cast::transmute(handler.handle);
+                    f(t)
+                }
+            }
+        }
+    }
+}
+
+
+#[test]
+fn happiness_key(_x: @Handler) { }
+
+#[test]
+fn sadness_key(_x: @Handler) { }
+
+#[test]
+fn trouble(i: int) {
+    // Condition should work as a const, just limitations in consts.
+    let sadness_condition : Condition = Condition { key: sadness_key };
+    io::println("raising");
+    let j = sadness_condition.raise(&i);
+    io::println(fmt!("handler recovered with %d", j));
+}
+
+#[test]
+fn test() {
+
+    let sadness_condition : Condition = Condition { key: sadness_key };
+
+    let mut i = 10;
+
+    let b = do sadness_condition.protect {
+        io::println("in protected block");
+        trouble(1);
+        trouble(2);
+        trouble(3);
+    };
+
+    do b.handle |j| {
+        i += *j;
+        i
+    };
+
+    assert i == 16;
+}
\ No newline at end of file
diff --git a/src/libcore/core.rc b/src/libcore/core.rc
index 484c5875032..9ebdad3521e 100644
--- a/src/libcore/core.rc
+++ b/src/libcore/core.rc
@@ -200,6 +200,7 @@ pub mod flate;
 pub mod repr;
 pub mod cleanup;
 pub mod reflect;
+pub mod condition;
 
 // Modules supporting compiler-generated code
 // Exported but not part of the public interface