summaryrefslogtreecommitdiff
path: root/docs/examples/actors/fringe.scala
blob: 2026628cb31e4631d5358b08480a6e1bb3d97d5e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package examples.actors

import scala.actors.Actor._
import scala.actors.{Channel, OutputChannel}

/**
 @author Philipp Haller
 @version 1.1, 09/21/2007
 */
object fringe extends Application {

  abstract class Tree
  case class Node(left: Tree, right: Tree) extends Tree
  case class Leaf(v: Int) extends Tree

  case class CompareFringe(t1: Tree, t2: Tree)
  case class ComputeFringe(t1: Tree, atoms: OutputChannel[Option[Leaf]])
  case class Equal(atom1: Option[Leaf], atom2: Option[Leaf])
  case class Extract(tree: Tree)

  val comparator = actor {
    val extractor1 = actor(extractorBehavior())
    val extractor2 = actor(extractorBehavior())
    val ch1 = new Channel[Option[Leaf]]
    val ch2 = new Channel[Option[Leaf]]
    loop {
      react {
        case CompareFringe(tree1, tree2) =>
          extractor1 ! ComputeFringe(tree1, ch1)
          extractor2 ! ComputeFringe(tree2, ch2)
          self ! Equal(ch1.?, ch2.?)

        case Equal(atom1, atom2) =>
          if (atom1 == atom2) atom1 match {
            case None =>
              println("same fringe")
              exit()
            case _ =>
              self ! Equal(ch1.?, ch2.?)
          } else {
            println("fringes differ")
            exit()
          }
      }
    }
  }

  val extractorBehavior = () => {
    var output: OutputChannel[Option[Leaf]] = null
    loop {
      react {
        case ComputeFringe(tree, leafSink) =>
          output = leafSink
          self ! Extract(tree)

        case Extract(tree) => tree match {
          case atom @ Leaf(_) =>
            output ! Some(atom)
            sender ! 'Continue

          case Node(left, right) =>
            val outer = self
            val outerCont = sender
            val cont = actor {
              react {
                case 'Continue =>
                  outer.send(Extract(right), outerCont)
              }
            }
            self.send(Extract(left), cont)
        }

        case 'Continue =>
          output ! None
          exit()
      }
    }
  }

  comparator ! CompareFringe(Node(Leaf(5), Node(Leaf(7), Leaf(3))),
                Node(Leaf(5), Node(Leaf(7), Leaf(3))))
}