123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 |
- package expr
- import (
- `fmt`
- )
- // Type is tyep expression type.
- type Type int
- const (
- // CONST indicates that the expression is a constant.
- CONST Type = iota
- // TERM indicates that the expression is a Term reference.
- TERM
- // EXPR indicates that the expression is a unary or binary expression.
- EXPR
- )
- var typeNames = map[Type]string {
- EXPR : "Expr",
- TERM : "Term",
- CONST : "Const",
- }
- // String returns the string representation of a Type.
- func (self Type) String() string {
- if v, ok := typeNames[self]; ok {
- return v
- } else {
- return fmt.Sprintf("expr.Type(%d)", self)
- }
- }
- // Operator represents an operation to perform when Type is EXPR.
- type Operator uint8
- const (
- // ADD performs "Add Expr.Left and Expr.Right".
- ADD Operator = iota
- // SUB performs "Subtract Expr.Left by Expr.Right".
- SUB
- // MUL performs "Multiply Expr.Left by Expr.Right".
- MUL
- // DIV performs "Divide Expr.Left by Expr.Right".
- DIV
- // MOD performs "Modulo Expr.Left by Expr.Right".
- MOD
- // AND performs "Bitwise AND Expr.Left and Expr.Right".
- AND
- // OR performs "Bitwise OR Expr.Left and Expr.Right".
- OR
- // XOR performs "Bitwise XOR Expr.Left and Expr.Right".
- XOR
- // SHL performs "Bitwise Shift Expr.Left to the Left by Expr.Right Bits".
- SHL
- // SHR performs "Bitwise Shift Expr.Left to the Right by Expr.Right Bits".
- SHR
- // POW performs "Raise Expr.Left to the power of Expr.Right"
- POW
- // NOT performs "Bitwise Invert Expr.Left".
- NOT
- // NEG performs "Negate Expr.Left".
- NEG
- )
- var operatorNames = map[Operator]string {
- ADD : "Add",
- SUB : "Subtract",
- MUL : "Multiply",
- DIV : "Divide",
- MOD : "Modulo",
- AND : "And",
- OR : "Or",
- XOR : "ExclusiveOr",
- SHL : "ShiftLeft",
- SHR : "ShiftRight",
- POW : "Power",
- NOT : "Invert",
- NEG : "Negate",
- }
- // String returns the string representation of a Type.
- func (self Operator) String() string {
- if v, ok := operatorNames[self]; ok {
- return v
- } else {
- return fmt.Sprintf("expr.Operator(%d)", self)
- }
- }
- // Expr represents an expression node.
- type Expr struct {
- Type Type
- Term Term
- Op Operator
- Left *Expr
- Right *Expr
- Const int64
- }
- // Ref creates an expression from a Term.
- func Ref(t Term) (p *Expr) {
- p = newExpression()
- p.Term = t
- p.Type = TERM
- return
- }
- // Int creates an expression from an integer.
- func Int(v int64) (p *Expr) {
- p = newExpression()
- p.Type = CONST
- p.Const = v
- return
- }
- func (self *Expr) clear() {
- if self.Term != nil { self.Term.Free() }
- if self.Left != nil { self.Left.Free() }
- if self.Right != nil { self.Right.Free() }
- }
- // Free returns the Expr into pool.
- // Any operation performed after Free is undefined behavior.
- func (self *Expr) Free() {
- self.clear()
- freeExpression(self)
- }
- // Evaluate evaluates the expression into an integer.
- // It also implements the Term interface.
- func (self *Expr) Evaluate() (int64, error) {
- switch self.Type {
- case EXPR : return self.eval()
- case TERM : return self.Term.Evaluate()
- case CONST : return self.Const, nil
- default : panic("invalid expression type: " + self.Type.String())
- }
- }
- /** Expression Combinator **/
- func combine(a *Expr, op Operator, b *Expr) (r *Expr) {
- r = newExpression()
- r.Op = op
- r.Type = EXPR
- r.Left = a
- r.Right = b
- return
- }
- func (self *Expr) Add(v *Expr) *Expr { return combine(self, ADD, v) }
- func (self *Expr) Sub(v *Expr) *Expr { return combine(self, SUB, v) }
- func (self *Expr) Mul(v *Expr) *Expr { return combine(self, MUL, v) }
- func (self *Expr) Div(v *Expr) *Expr { return combine(self, DIV, v) }
- func (self *Expr) Mod(v *Expr) *Expr { return combine(self, MOD, v) }
- func (self *Expr) And(v *Expr) *Expr { return combine(self, AND, v) }
- func (self *Expr) Or (v *Expr) *Expr { return combine(self, OR , v) }
- func (self *Expr) Xor(v *Expr) *Expr { return combine(self, XOR, v) }
- func (self *Expr) Shl(v *Expr) *Expr { return combine(self, SHL, v) }
- func (self *Expr) Shr(v *Expr) *Expr { return combine(self, SHR, v) }
- func (self *Expr) Pow(v *Expr) *Expr { return combine(self, POW, v) }
- func (self *Expr) Not() *Expr { return combine(self, NOT, nil) }
- func (self *Expr) Neg() *Expr { return combine(self, NEG, nil) }
- /** Expression Evaluator **/
- var binaryEvaluators = [256]func(int64, int64) (int64, error) {
- ADD: func(a, b int64) (int64, error) { return a + b, nil },
- SUB: func(a, b int64) (int64, error) { return a - b, nil },
- MUL: func(a, b int64) (int64, error) { return a * b, nil },
- DIV: idiv,
- MOD: imod,
- AND: func(a, b int64) (int64, error) { return a & b, nil },
- OR: func(a, b int64) (int64, error) { return a | b, nil },
- XOR: func(a, b int64) (int64, error) { return a ^ b, nil },
- SHL: func(a, b int64) (int64, error) { return a << b, nil },
- SHR: func(a, b int64) (int64, error) { return a >> b, nil },
- POW: ipow,
- }
- func (self *Expr) eval() (int64, error) {
- var lhs int64
- var rhs int64
- var err error
- var vfn func(int64, int64) (int64, error)
- /* evaluate LHS */
- if lhs, err = self.Left.Evaluate(); err != nil {
- return 0, err
- }
- /* check for unary operators */
- switch self.Op {
- case NOT: return self.unaryNot(lhs)
- case NEG: return self.unaryNeg(lhs)
- }
- /* check for operators */
- if vfn = binaryEvaluators[self.Op]; vfn == nil {
- panic("invalid operator: " + self.Op.String())
- }
- /* must be a binary expression */
- if self.Right == nil {
- panic("operator " + self.Op.String() + " is a binary operator")
- }
- /* evaluate RHS, and call the operator */
- if rhs, err = self.Right.Evaluate(); err != nil {
- return 0, err
- } else {
- return vfn(lhs, rhs)
- }
- }
- func (self *Expr) unaryNot(v int64) (int64, error) {
- if self.Right == nil {
- return ^v, nil
- } else {
- panic("operator Invert is an unary operator")
- }
- }
- func (self *Expr) unaryNeg(v int64) (int64, error) {
- if self.Right == nil {
- return -v, nil
- } else {
- panic("operator Negate is an unary operator")
- }
- }
|