Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion evaluator/evaluator.go
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,7 @@ func evalIndexExpression(node *ast.IndexExpression, left object.Object, index ob
switch {
case left.Type() == object.STRING_OBJ && index.Type() == object.NUMBER_OBJ:
return evalStringIndexExpression(node, left, index)
case left.Type() == object.LIST_OBJ && index.Type() == object.NUMBER_OBJ:
case left.Type() == object.LIST_OBJ:
return evalListIndexExpression(node, left, index)
case left.Type() == object.MAP_OBJ:
return evalMapIndexExpression(node.Token.Line, left, index)
Expand Down Expand Up @@ -707,6 +707,18 @@ func evalForInExpression(fie *ast.ForInExpression, env *object.Environment) obje
}
}

return value.NULL
case *object.Map:
for _, p := range i.Pairs {
env.Set(fie.Key, p.Key)
env.Set(fie.Value, p.Value)
block := Eval(fie.Block, env)

if error.IsError(block) {
return block
}
}

return value.NULL
default:
return error.NewError(fie.Token.Line, error.UnusableForLoop, i.Inspect())
Expand Down
33 changes: 33 additions & 0 deletions object/object.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"bytes"
"fmt"
"hash/fnv"
"regexp"
"strconv"
"strings"
"unicode/utf8"
Expand Down Expand Up @@ -336,12 +337,44 @@ func (rv *ReturnValue) CallMethod(method string, args []Object) Object {

func (s *String) CallMethod(method string, args []Object) Object {
switch method {
case "matches":
matches, err := regexp.Match(s.Value, []byte(args[0].(*String).Value))

if err != nil {
return &Error{Message: err.Error()}
}

return &Boolean{Value: matches}
case "find":
re := regexp.MustCompile(s.Value)

found := re.FindStringSubmatch(args[0].(*String).Value)

if len(found) > 0 {
return &String{Value: found[1]}
}

return &String{}
case "findAll":
re := regexp.MustCompile(s.Value)
list := &List{}
found := re.FindStringSubmatch(args[0].(*String).Value)

for _, f := range found {
list.Elements = append(list.Elements, &String{Value: f})
}

return list
case "endsWith":
hasPrefix := strings.HasSuffix(s.Value, args[0].(*String).Value)

return &Boolean{Value: hasPrefix}
case "length":
return &Number{Value: decimal.NewFromInt(int64(utf8.RuneCountInString(s.Value)))}
case "replace":
value := strings.Replace(s.Value, args[0].(*String).Value, args[1].(*String).Value, -1)

return &String{Value: value}
case "split":
split := strings.Split(s.Value, args[0].(*String).Value)
list := &List{}
Expand Down
16 changes: 10 additions & 6 deletions utilities/utilities.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,17 @@ func NativeBoolToBooleanObject(input bool) *object.Boolean {

// IsTruthy returns the truthy value of the passed object.
func IsTruthy(obj object.Object) bool {
switch obj {
case value.NULL:
return false
case value.TRUE:
return true
case value.FALSE:
switch obj := obj.(type) {
case *object.Null:
return false
case *object.Boolean:
return obj.Value
case *object.String:
return len(obj.Value) > 0
case *object.List:
return len(obj.Elements) > 0
case *object.Map:
return len(obj.Pairs) > 0
default:
return true
}
Expand Down