| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 | package exprimport (    `fmt`)// Type is tyep expression type.type Type intconst (    // 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 uint8const (    // 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")    }}
 |