Skip to content

Commit

Permalink
Precalculate tail length of pattern
Browse files Browse the repository at this point in the history
Tail length means the length of fixed-size segements after a deep wildcard in
the  pattern.
This helps us to care of #23 on pattern matching.
  • Loading branch information
yugui committed Aug 30, 2015
1 parent b735491 commit 6b028af
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 6 deletions.
28 changes: 24 additions & 4 deletions runtime/pattern.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ type Pattern struct {
vars []string
// stacksize is the max depth of the stack
stacksize int
// tailLen is the length of the fixed-size segments after a deep wildcard
tailLen int
// verb is the VERB part of the path pattern. It is empty if the pattern does not have VERB part.
verb string
}
Expand All @@ -52,21 +54,38 @@ func NewPattern(version int, ops []int, pool []string, verb string) (Pattern, er
return Pattern{}, ErrInvalidPattern
}

var typedOps []op
var stack, maxstack int
var vars []string
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, utilities.OpPushM:
case utilities.OpPush:
if pushMSeen {
tailLen++
}
stack++
case utilities.OpPushM:
if pushMSeen {
glog.V(2).Info("pushM appears twice")
return Pattern{}, ErrInvalidPattern
}
pushMSeen = true
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
}
if pushMSeen {
tailLen++
}
stack++
case utilities.OpConcatN:
if op.operand <= 0 {
Expand Down Expand Up @@ -108,6 +127,7 @@ func NewPattern(version int, ops []int, pool []string, verb string) (Pattern, er
pool: pool,
vars: vars,
stacksize: maxstack,
tailLen: tailLen,
verb: verb,
}, nil
}
Expand Down
50 changes: 48 additions & 2 deletions runtime/pattern_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,32 +20,37 @@ func TestNewPattern(t *testing.T) {
pool []string
verb string

stackSizeWant int
stackSizeWant, tailLenWant int
}{
{},
{
ops: []int{int(utilities.OpNop), anything},
stackSizeWant: 0,
tailLenWant: 0,
},
{
ops: []int{int(utilities.OpPush), anything},
stackSizeWant: 1,
tailLenWant: 0,
},
{
ops: []int{int(utilities.OpLitPush), 0},
pool: []string{"abc"},
stackSizeWant: 1,
tailLenWant: 0,
},
{
ops: []int{int(utilities.OpPushM), anything},
stackSizeWant: 1,
tailLenWant: 0,
},
{
ops: []int{
int(utilities.OpPush), anything,
int(utilities.OpConcatN), 1,
},
stackSizeWant: 1,
tailLenWant: 0,
},
{
ops: []int{
Expand All @@ -55,6 +60,7 @@ func TestNewPattern(t *testing.T) {
},
pool: []string{"abc"},
stackSizeWant: 1,
tailLenWant: 0,
},
{
ops: []int{
Expand All @@ -67,12 +73,40 @@ func TestNewPattern(t *testing.T) {
},
pool: []string{"lit1", "lit2", "var1"},
stackSizeWant: 4,
tailLenWant: 0,
},
{
ops: []int{
int(utilities.OpPushM), anything,
int(utilities.OpConcatN), 1,
int(utilities.OpCapture), 2,
int(utilities.OpLitPush), 0,
int(utilities.OpLitPush), 1,
},
pool: []string{"lit1", "lit2", "var1"},
stackSizeWant: 2,
tailLenWant: 2,
},
{
ops: []int{
int(utilities.OpLitPush), 0,
int(utilities.OpLitPush), 1,
int(utilities.OpPushM), anything,
int(utilities.OpLitPush), 2,
int(utilities.OpConcatN), 3,
int(utilities.OpLitPush), 3,
int(utilities.OpCapture), 4,
},
pool: []string{"lit1", "lit2", "lit3", "lit4", "var1"},
stackSizeWant: 4,
tailLenWant: 2,
},
{
ops: []int{int(utilities.OpLitPush), 0},
pool: []string{"abc"},
stackSizeWant: 1,
verb: "LOCK",
stackSizeWant: 1,
tailLenWant: 0,
},
} {
pat, err := NewPattern(validVersion, spec.ops, spec.pool, spec.verb)
Expand All @@ -83,6 +117,9 @@ func TestNewPattern(t *testing.T) {
if got, want := pat.stacksize, spec.stackSizeWant; got != want {
t.Errorf("pat.stacksize = %d; want %d", got, want)
}
if got, want := pat.tailLen, spec.tailLenWant; got != want {
t.Errorf("pat.stacksize = %d; want %d", got, want)
}
}
}

Expand Down Expand Up @@ -129,6 +166,15 @@ func TestNewPatternWithWrongOp(t *testing.T) {
ops: []int{int(utilities.OpCapture), 1},
pool: []string{"abc"},
},
{
// pushM appears twice
ops: []int{
int(utilities.OpPushM), anything,
int(utilities.OpLitPush), 0,
int(utilities.OpPushM), anything,
},
pool: []string{"abc"},
},
} {
_, err := NewPattern(validVersion, spec.ops, spec.pool, spec.verb)
if err == nil {
Expand Down

0 comments on commit 6b028af

Please sign in to comment.