From 05d8ec6a16acf88c5ae7521d86131f5ea7f9b4e4 Mon Sep 17 00:00:00 2001 From: "Andrew Gallant (Ocelot)" Date: Mon, 30 Apr 2012 02:40:55 -0400 Subject: complete and total overhaul like i promised. things are much easier to reason about. still not working yet though. --- nexgb/xgbgen/expression.go | 276 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 276 insertions(+) create mode 100644 nexgb/xgbgen/expression.go (limited to 'nexgb/xgbgen/expression.go') diff --git a/nexgb/xgbgen/expression.go b/nexgb/xgbgen/expression.go new file mode 100644 index 0000000..a163692 --- /dev/null +++ b/nexgb/xgbgen/expression.go @@ -0,0 +1,276 @@ +package main + +import ( + "fmt" + "log" +) + +type Expression interface { + Concrete() bool + Eval() uint + Reduce(prefix, fun string) string + String() string + Initialize(p *Protocol) +} + +type BinaryOp struct { + Op string + Expr1 Expression + Expr2 Expression +} + +func newBinaryOp(op string, expr1, expr2 Expression) Expression { + switch { + case expr1 != nil && expr2 != nil: + return &BinaryOp{ + Op: op, + Expr1: expr1, + Expr2: expr2, + } + case expr1 != nil && expr2 == nil: + return expr1 + case expr1 == nil && expr2 != nil: + return expr2 + case expr1 == nil && expr2 == nil: + return nil + } + panic("unreachable") +} + +func (e *BinaryOp) Concrete() bool { + return e.Expr1.Concrete() && e.Expr2.Concrete() +} + +func (e *BinaryOp) Eval() uint { + switch e.Op { + case "+": + return e.Expr1.Eval() + e.Expr2.Eval() + case "-": + return e.Expr1.Eval() - e.Expr2.Eval() + case "*": + return e.Expr1.Eval() * e.Expr2.Eval() + case "/": + return e.Expr1.Eval() / e.Expr2.Eval() + case "&": + return e.Expr1.Eval() & e.Expr2.Eval() + case "<<": + return e.Expr1.Eval() << e.Expr2.Eval() + } + + log.Fatalf("Invalid binary operator '%s' for expression.", e.Op) + panic("unreachable") +} + +func (e *BinaryOp) Reduce(prefix, fun string) string { + if e.Concrete() { + return fmt.Sprintf("%d", e.Eval()) + } + return fmt.Sprintf("(%s %s %s)", + e.Expr1.Reduce(prefix, fun), e.Op, e.Expr2.Reduce(prefix, fun)) +} + +func (e *BinaryOp) String() string { + return e.Reduce("", "") +} + +func (e *BinaryOp) Initialize(p *Protocol) { + e.Expr1.Initialize(p) + e.Expr2.Initialize(p) +} + +type UnaryOp struct { + Op string + Expr Expression +} + +func (e *UnaryOp) Concrete() bool { + return e.Expr.Concrete() +} + +func (e *UnaryOp) Eval() uint { + switch e.Op { + case "~": + return ^e.Expr.Eval() + } + + log.Fatalf("Invalid unary operator '%s' for expression.", e.Op) + panic("unreachable") +} + +func (e *UnaryOp) Reduce(prefix, fun string) string { + if e.Concrete() { + return fmt.Sprintf("%d", e.Eval()) + } + return fmt.Sprintf("(%s (%s))", e.Op, e.Expr.Reduce(prefix, fun)) +} + +func (e *UnaryOp) String() string { + return e.Reduce("", "") +} + +func (e *UnaryOp) Initialize(p *Protocol) { + e.Expr.Initialize(p) +} + +type PopCount struct { + Expr Expression +} + +func (e *PopCount) Concrete() bool { + return e.Expr.Concrete() +} + +func (e *PopCount) Eval() uint { + return popCount(e.Expr.Eval()) +} + +func (e *PopCount) Reduce(prefix, fun string) string { + if e.Concrete() { + return fmt.Sprintf("%d", e.Eval()) + } + return fmt.Sprintf("popCount(%s)", e.Expr.Reduce(prefix, fun)) +} + +func (e *PopCount) String() string { + return e.Reduce("", "") +} + +func (e *PopCount) Initialize(p *Protocol) { + e.Expr.Initialize(p) +} + +type Value struct { + v uint +} + +func (e *Value) Concrete() bool { + return true +} + +func (e *Value) Eval() uint { + return e.v +} + +func (e *Value) Reduce(prefix, fun string) string { + return fmt.Sprintf("%d", e.v) +} + +func (e *Value) String() string { + return e.Reduce("", "") +} + +func (e *Value) Initialize(p *Protocol) { } + +type Bit struct { + b uint +} + +func (e *Bit) Concrete() bool { + return true +} + +func (e *Bit) Eval() uint { + return 1 << e.b +} + +func (e *Bit) Reduce(prefix, fun string) string { + return fmt.Sprintf("%d", e.Eval()) +} + +func (e *Bit) String() string { + return e.Reduce("", "") +} + +func (e *Bit) Initialize(p *Protocol) { } + +type FieldRef struct { + Name string +} + +func (e *FieldRef) Concrete() bool { + return false +} + +func (e *FieldRef) Eval() uint { + log.Fatalf("Cannot evaluate a 'FieldRef'. It is not concrete.") + panic("unreachable") +} + +func (e *FieldRef) Reduce(prefix, fun string) string { + val := e.Name + if len(prefix) > 0 { + val = fmt.Sprintf("%s%s", prefix, val) + } + if len(fun) > 0 { + val = fmt.Sprintf("%s(%s)", fun, val) + } + return val +} + +func (e *FieldRef) String() string { + return e.Reduce("", "") +} + +func (e *FieldRef) Initialize(p *Protocol) { + e.Name = SrcName(e.Name) +} + +type EnumRef struct { + EnumKind Type + EnumItem string +} + +func (e *EnumRef) Concrete() bool { + return false +} + +func (e *EnumRef) Eval() uint { + log.Fatalf("Cannot evaluate an 'EnumRef'. It is not concrete.") + panic("unreachable") +} + +func (e *EnumRef) Reduce(prefix, fun string) string { + val := fmt.Sprintf("%s%s", e.EnumKind, e.EnumItem) + if len(fun) > 0 { + val = fmt.Sprintf("%s(%s)", fun, val) + } + return val +} + +func (e *EnumRef) String() string { + return e.Reduce("", "") +} + +func (e *EnumRef) Initialize(p *Protocol) { + e.EnumKind = e.EnumKind.(*Translation).RealType(p) + e.EnumItem = SrcName(e.EnumItem) +} + +type SumOf struct { + Name string +} + +func (e *SumOf) Concrete() bool { + return false +} + +func (e *SumOf) Eval() uint { + log.Fatalf("Cannot evaluate a 'SumOf'. It is not concrete.") + panic("unreachable") +} + +func (e *SumOf) Reduce(prefix, fun string) string { + if len(prefix) > 0 { + return fmt.Sprintf("sum(%s%s)", prefix, e.Name) + } + return fmt.Sprintf("sum(%s)", e.Name) +} + +func (e *SumOf) String() string { + return e.Reduce("", "") +} + +func (e *SumOf) Initialize(p *Protocol) { + e.Name = SrcName(e.Name) +} + -- cgit v1.2.3