// NewPattern returns a new Pattern from the given definition values. // "ops" is a sequence of op codes. "pool" is a constant pool. // "verb" is the verb part of the pattern. It is empty if the pattern does not have the part. // "version" must be 1 for now. // It returns an error if the given definition is invalid. func NewPattern(version int, ops []int, pool []string, verb string) (Pattern, error) { if version != 1 { grpclog.Printf("unsupported version: %d", version) return Pattern{}, ErrInvalidPattern } l := len(ops) if l%2 != 0 { grpclog.Printf("odd number of ops codes: %d", l) return Pattern{}, ErrInvalidPattern } var ( typedOps []op stack, maxstack int tailLen int pushMSeen bool vars []string ) for i := 0; i < l; i += 2 { op := op{code: utilities.OpCode(ops[i]), operand: ops[i+1]} switch op.code { case utilities.OpNop: continue case utilities.OpPush: if pushMSeen { tailLen++ } stack++ case utilities.OpPushM: if pushMSeen { grpclog.Printf("pushM appears twice") return Pattern{}, ErrInvalidPattern } pushMSeen = true stack++ case utilities.OpLitPush: if op.operand < 0 || len(pool) <= op.operand { grpclog.Printf("negative literal index: %d", op.operand) return Pattern{}, ErrInvalidPattern } if pushMSeen { tailLen++ } stack++ case utilities.OpConcatN: if op.operand <= 0 { grpclog.Printf("negative concat size: %d", op.operand) return Pattern{}, ErrInvalidPattern } stack -= op.operand if stack < 0 { grpclog.Print("stack underflow") return Pattern{}, ErrInvalidPattern } stack++ case utilities.OpCapture: if op.operand < 0 || len(pool) <= op.operand { grpclog.Printf("variable name index out of bound: %d", op.operand) return Pattern{}, ErrInvalidPattern } v := pool[op.operand] op.operand = len(vars) vars = append(vars, v) stack-- if stack < 0 { grpclog.Printf("stack underflow") return Pattern{}, ErrInvalidPattern } default: grpclog.Printf("invalid opcode: %d", op.code) return Pattern{}, ErrInvalidPattern } if maxstack < stack { maxstack = stack } typedOps = append(typedOps, op) } return Pattern{ ops: typedOps, pool: pool, vars: vars, stacksize: maxstack, tailLen: tailLen, verb: verb, }, nil }
// NewPattern returns a new Pattern from the given definition values. // "ops" is a sequence of op codes. "pool" is a constant pool. // "verb" is the verb part of the pattern. It is empty if the pattern does not have the part. // "version" must be 1 for now. // It returns an error if the given definition is invalid. func NewPattern(version int, ops []int, pool []string, verb string) (Pattern, error) { if version != 1 { glog.V(2).Infof("unsupported version: %d", version) return Pattern{}, ErrInvalidPattern } l := len(ops) if l%2 != 0 { glog.V(2).Infof("odd number of ops codes: %d", l) return Pattern{}, ErrInvalidPattern } var typedOps []op var stack, maxstack int var vars []string for i := 0; i < l; i += 2 { op := op{code: utilities.OpCode(ops[i]), operand: ops[i+1]} switch op.code { case utilities.OpNop: continue case utilities.OpPush, utilities.OpPushM: stack++ case utilities.OpLitPush: if op.operand < 0 || len(pool) <= op.operand { glog.V(2).Infof("negative literal index: %d", op.operand) return Pattern{}, ErrInvalidPattern } stack++ case utilities.OpConcatN: if op.operand <= 0 { glog.V(2).Infof("negative concat size: %d", op.operand) return Pattern{}, ErrInvalidPattern } stack -= op.operand if stack < 0 { glog.V(2).Info("stack underflow") return Pattern{}, ErrInvalidPattern } stack++ case utilities.OpCapture: if op.operand < 0 || len(pool) <= op.operand { glog.V(2).Infof("variable name index out of bound: %d", op.operand) return Pattern{}, ErrInvalidPattern } v := pool[op.operand] op.operand = len(vars) vars = append(vars, v) stack-- if stack < 0 { glog.V(2).Info("stack underflow") return Pattern{}, ErrInvalidPattern } default: glog.V(2).Infof("invalid opcode: %d", op.code) return Pattern{}, ErrInvalidPattern } if maxstack < stack { maxstack = stack } typedOps = append(typedOps, op) } glog.V(3).Info("pattern successfully built") return Pattern{ ops: typedOps, pool: pool, vars: vars, stacksize: maxstack, verb: verb, }, nil }