Skip to content

Instantly share code, notes, and snippets.

@hsk
Last active August 29, 2015 14:24
Show Gist options
  • Save hsk/57652e9382eac1e77ef6 to your computer and use it in GitHub Desktop.
Save hsk/57652e9382eac1e77ef6 to your computer and use it in GitHub Desktop.
named visitor
package a
trait E {
def visit[T](v:EVisitor[T]):T
}
class EInt(a:Int) extends E {
def visit[T](v:EVisitor[T]):T = v.EInt(a)
}
class EBin(a:E,op:String,b:E) extends E {
def visit[T](v:EVisitor[T]):T = v.EBin(a,op,b)
}
trait EVisitor[T] {
def EInt(a:Int):T
def EBin(a:E,op:String,b:E):T
}
class Trans extends EVisitor[E] {
def EInt(a:Int):E = new EInt(a)
def EBin(a:E,op:String,b:E):E = new EBin(a.visit(this),op,b.visit(this))
}
class Eval extends EVisitor[Int] {
def EInt(a:Int):Int = a
def EBin(a:E,op:String,b:E):Int = {
op match {
case "+" => a.visit(this) + b.visit(this)
case "-" => a.visit(this) - b.visit(this)
case "*" => a.visit(this) * b.visit(this)
case "/" => a.visit(this) / b.visit(this)
}
}
}
object a extends App {
println(new EBin(new EInt(1),"+",new EInt(2)).visit(new Trans()).visit(new Eval()))
}
package main
import "fmt"
type A interface {}
type E interface {
visit(v Visitor) A
}
type EInt struct {a int;}
func(e EInt) visit(v Visitor) A {
return v.EInt(e.a)
}
type EBin struct {a E;op string;b E;}
func(e EBin) visit(v Visitor) A {
return v.EBin(e.a,e.op,e.b)
}
type Visitor interface {
EInt(a int) A
EBin(a E,op string,b E) A
}
type Trans struct{}
func (this Trans) EInt(a int) A {
return EInt{a}
}
func (this Trans) EBin(a E,op string,b E) A {
return EBin{a.visit(this).(E),op,b.visit(this).(E)}
}
type Eval struct {}
func (this Eval) EInt(a int) A { return a }
func (this Eval) EBin(a E,op string,b E) A {
switch op {
case "+" : return a.visit(this).(int) + b.visit(this).(int)
case "-" : return a.visit(this).(int) - b.visit(this).(int)
case "*" : return a.visit(this).(int) * b.visit(this).(int)
case "/" : return a.visit(this).(int) / b.visit(this).(int)
default: return 0;
}
}
func main() {
fmt.Printf("%#v\n", EBin{EInt{1},"+",EInt{2}}.visit(Trans{}).(E).visit(Eval{}))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment