Skip to content

Commit

Permalink
wip: count bytes read
Browse files Browse the repository at this point in the history
doing this as a wip commit, because we probably don't want to count
ourselves, but rather send a PR to do the counting in the ExprLexer,
because currently this approach feels rather hacky and also doesn't
work in all cases..
  • Loading branch information
ZauberNerd committed Dec 10, 2021
1 parent 12d6674 commit 67b9bed
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 15 deletions.
77 changes: 68 additions & 9 deletions pkg/exprparser/interpreter.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,16 @@ type Interpreter interface {
}

type interperterImpl struct {
env *EvaluationEnvironment
config Config
env *EvaluationEnvironment
config Config
bytesRead int
}

func NewInterpeter(env *EvaluationEnvironment, config Config) Interpreter {
return &interperterImpl{
env: env,
config: config,
env: env,
config: config,
bytesRead: 0,
}
}

Expand All @@ -51,29 +53,38 @@ func (impl *interperterImpl) Evaluate(input string) (interface{}, int, error) {
return nil, 0, fmt.Errorf("Failed to parse: %s", err.Message)
}

impl.bytesRead = exprNode.Token().Offset

result, err2 := impl.evaluateNode(exprNode)

// todo: this does not work and we need to calculate/track the
// node end position
fmt.Printf("read text: %s offset: %d line %d column %d\n",
exprNode.Token().Value, exprNode.Token().Offset, exprNode.Token().Line, exprNode.Token().Column)
fmt.Printf("initial bytes read: %d, kind: %+v\n", impl.bytesRead, exprNode)

return result, len(exprNode.Token().Value), err2
return result, impl.bytesRead, err2
}

func (impl *interperterImpl) evaluateNode(exprNode actionlint.ExprNode) (interface{}, error) {
switch node := exprNode.(type) {
case *actionlint.VariableNode:
return impl.evaluateVariable(node)
case *actionlint.BoolNode:
if node.Value {
impl.bytesRead += 4
} else {
fmt.Printf("current bytes read: %d, offset: %d\n", impl.bytesRead, node.Token().Offset)
impl.bytesRead += 5
}
return node.Value, nil
case *actionlint.NullNode:
impl.bytesRead += 4
return nil, nil
case *actionlint.IntNode:
impl.bytesRead += len(fmt.Sprint(node.Value))
return node.Value, nil
case *actionlint.FloatNode:
impl.bytesRead += len(fmt.Sprint(node.Value))
return node.Value, nil
case *actionlint.StringNode:
impl.bytesRead += len(node.Value) + 2
return node.Value, nil
case *actionlint.IndexAccessNode:
return impl.evaluateIndexAccess(node)
Expand All @@ -98,28 +109,40 @@ func (impl *interperterImpl) evaluateNode(exprNode actionlint.ExprNode) (interfa
func (impl *interperterImpl) evaluateVariable(variableNode *actionlint.VariableNode) (interface{}, error) {
switch strings.ToLower(variableNode.Name) {
case "github":
impl.bytesRead += len("github")
return impl.env.Github, nil
case "env":
impl.bytesRead += len("env")
return impl.env.Env, nil
case "job":
impl.bytesRead += len("job")
return impl.env.Job, nil
case "steps":
impl.bytesRead += len("steps")
return impl.env.Steps, nil
case "runner":
impl.bytesRead += len("runner")
return impl.env.Runner, nil
case "secrets":
impl.bytesRead += len("secrets")
return impl.env.Secrets, nil
case "strategy":
impl.bytesRead += len("strategy")
return impl.env.Strategy, nil
case "matrix":
impl.bytesRead += len("matrix")
return impl.env.Matrix, nil
case "needs":
impl.bytesRead += len("needs")
return impl.env.Needs, nil
case "inputs":
impl.bytesRead += len("inputs")
return impl.env.Inputs, nil
case "infinity":
impl.bytesRead += len("infinity")
return math.Inf(1), nil
case "nan":
impl.bytesRead += len("nan")
return math.NaN(), nil
default:
// TODO better error message
Expand All @@ -142,6 +165,8 @@ func (impl *interperterImpl) evaluateIndexAccess(indexAccessNode *actionlint.Ind

rightValue := reflect.ValueOf(right)

impl.bytesRead += 2

switch rightValue.Kind() {
// TODO: is property access the only valid kind where rightValue is a string?
case reflect.String:
Expand All @@ -168,6 +193,8 @@ func (impl *interperterImpl) evaluateObjectDeref(objectDerefNode *actionlint.Obj
return nil, err
}

impl.bytesRead += 1

return impl.getPropertyValue(reflect.ValueOf(left), objectDerefNode.Property)
}

Expand All @@ -177,6 +204,8 @@ func (impl *interperterImpl) evaluateArrayDeref(arrayDerefNode *actionlint.Array
return nil, err
}

impl.bytesRead += 1

return reflect.ValueOf(left).Interface(), nil
}

Expand Down Expand Up @@ -259,6 +288,8 @@ func (impl *interperterImpl) evaluateNot(notNode *actionlint.NotOpNode) (interfa
return nil, err
}

impl.bytesRead += 1

return !impl.isTruthy(reflect.ValueOf(operand)), nil
}

Expand Down Expand Up @@ -370,16 +401,22 @@ func (impl *interperterImpl) coerceToString(value reflect.Value) reflect.Value {
func (impl *interperterImpl) compareString(left string, right string, kind actionlint.CompareOpNodeKind) (bool, error) {
switch kind {
case actionlint.CompareOpNodeKindLess:
impl.bytesRead += 1
return left < right, nil
case actionlint.CompareOpNodeKindLessEq:
impl.bytesRead += 2
return left <= right, nil
case actionlint.CompareOpNodeKindGreater:
impl.bytesRead += 1
return left > right, nil
case actionlint.CompareOpNodeKindGreaterEq:
impl.bytesRead += 2
return left >= right, nil
case actionlint.CompareOpNodeKindEq:
impl.bytesRead += 2
return left == right, nil
case actionlint.CompareOpNodeKindNotEq:
impl.bytesRead += 2
return left != right, nil
default:
return false, fmt.Errorf("TODO: not implemented to compare '%+v'", kind)
Expand All @@ -389,16 +426,22 @@ func (impl *interperterImpl) compareString(left string, right string, kind actio
func (impl *interperterImpl) compareNumber(left float64, right float64, kind actionlint.CompareOpNodeKind) (bool, error) {
switch kind {
case actionlint.CompareOpNodeKindLess:
impl.bytesRead += 1
return left < right, nil
case actionlint.CompareOpNodeKindLessEq:
impl.bytesRead += 2
return left <= right, nil
case actionlint.CompareOpNodeKindGreater:
impl.bytesRead += 1
return left > right, nil
case actionlint.CompareOpNodeKindGreaterEq:
impl.bytesRead += 2
return left >= right, nil
case actionlint.CompareOpNodeKindEq:
impl.bytesRead += 2
return left == right, nil
case actionlint.CompareOpNodeKindNotEq:
impl.bytesRead += 2
return left != right, nil
default:
return false, fmt.Errorf("TODO: not implemented to compare '%+v'", kind)
Expand Down Expand Up @@ -466,6 +509,10 @@ func (impl *interperterImpl) evaluateLogicalCompare(compareNode *actionlint.Logi

rightValue := reflect.ValueOf(right)

impl.bytesRead += 2

fmt.Printf("logical compare, left: %+v, right: %+v, offset: %d\n", left, right, compareNode.Token().Offset)

switch compareNode.Kind {
case actionlint.LogicalOpNodeKindAnd:
if impl.isTruthy(leftValue) {
Expand Down Expand Up @@ -499,28 +546,40 @@ func (impl *interperterImpl) evaluateFuncCall(funcCallNode *actionlint.FuncCallN

switch strings.ToLower(funcCallNode.Callee) {
case "contains":
impl.bytesRead += len("contains()")
return impl.contains(args[0], args[1])
case "startswith":
impl.bytesRead += len("startswith()")
return impl.startsWith(args[0], args[1])
case "endswith":
impl.bytesRead += len("endswith()")
return impl.endsWith(args[0], args[1])
case "format":
impl.bytesRead += len("format()")
return impl.format(args[0], args[1:]...)
case "join":
impl.bytesRead += len("join()")
return impl.join(args[0], args[1])
case "tojson":
impl.bytesRead += len("tojson()")
return impl.toJSON(args[0])
case "fromjson":
impl.bytesRead += len("fromjson()")
return impl.fromJSON(args[0])
case "hashfiles":
impl.bytesRead += len("hashfiles()")
return impl.hashFiles(args...)
case "always":
impl.bytesRead += len("always()")
return impl.always()
case "success":
impl.bytesRead += len("success()")
return impl.success()
case "failure":
impl.bytesRead += len("failure()")
return impl.failure()
case "cancelled":
impl.bytesRead += len("cancelled()")
return impl.cancelled()
default:
return nil, fmt.Errorf("TODO: '%s' not implemented", funcCallNode.Callee)
Expand Down
13 changes: 7 additions & 6 deletions pkg/runner/expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,21 +177,22 @@ func (ee expressionEvaluator) InterpolateWithStringCheck(in string) (string, boo
}

case expressionStartBracket2:
fmt.Printf("index: %d, character: %c, skip: %d\n", i, character, skip)
if skip == 0 {
result, pos, err := ee.interpreter.Evaluate(in[i:])
result, bytesRead, err := ee.interpreter.Evaluate(in[i:])
if err != nil {
fmt.Printf("Failed to eval: %s\n", err)
return "", false
}

output += ee.toString(result)

fmt.Printf("read %d in '%s'\n", pos, in[i:pos])
fmt.Printf("input: \"%s\", input to evaluate: \"%s\", index: %d, bytesRead: %d, consumed: \"%s\"\n", in, in[i:], i, bytesRead, in[i:i+bytesRead])

if (pos - 1) == 0 {
if (bytesRead - 1) == 0 {
state = expressionEndBracket1
} else {
skip = i + pos - 1
skip = i + bytesRead - 1
}
} else if i < skip {
// ignore
Expand All @@ -204,14 +205,14 @@ func (ee expressionEvaluator) InterpolateWithStringCheck(in string) (string, boo
// todo: handle error
switch character {
case '}':
fmt.Printf("first closing bracket\n")
fmt.Printf("first closing bracket %d\n", i)
state = expressionEndBracket2
}
case expressionEndBracket2:
// todo: handle error
switch character {
case '}':
fmt.Printf("second closing bracket\n")
fmt.Printf("second closing bracket %d\n", i)
state = passThrough
}
}
Expand Down

0 comments on commit 67b9bed

Please sign in to comment.