diff options
Diffstat (limited to 'evaluator/evaluator.go')
| -rw-r--r-- | evaluator/evaluator.go | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/evaluator/evaluator.go b/evaluator/evaluator.go index 913138b..5e988cc 100644 --- a/evaluator/evaluator.go +++ b/evaluator/evaluator.go @@ -110,6 +110,9 @@ func Eval(node ast.Node, env *object.Environment) object.Object { case *ast.StringLiteral: return &object.String{Value: node.Value} + case *ast.HashLiteral: + return evalHashLiteral(node, env) + case *ast.ReturnStatement: val := Eval(node.ReturnValue, env) if isError(val) { @@ -319,6 +322,8 @@ func evalIndexExpression(left, index object.Object) object.Object { switch { case left.Type() == object.ARRAY_OBJ && index.Type() == object.INTEGER_OBJ: return evalArrayIndexExpression(left, index) + case left.Type() == object.HASH_OBJ: + return evalHashIndexExpression(left, index) default: return newError("index operator not supported: %s", left.Type()) } @@ -348,6 +353,48 @@ func evalIdentifier(node *ast.Identifier, env *object.Environment) object.Object return newError("identifier not found: " + node.Value) } +func evalHashLiteral(node *ast.HashLiteral, env *object.Environment) object.Object { + pairs := make(map[object.HashKey]object.HashPair) + + for keyNode, valueNode := range node.Pairs { + key := Eval(keyNode, env) + if isError(key) { + return key + } + + hashKey, ok := key.(object.Hashable) + if !ok { + return newError("unusable as hash key: %s", key.Type()) + } + + value := Eval(valueNode, env) + if isError(value) { + return value + } + + hashed := hashKey.HashKey() + pairs[hashed] = object.HashPair{Key: key, Value: value} + } + + return &object.Hash{Pairs: pairs} +} + +func evalHashIndexExpression(hash, index object.Object) object.Object { + hashObject := hash.(*object.Hash) + + key, ok := index.(object.Hashable) + if !ok { + return newError("unusable as hash key: %s", index.Type()) + } + + pair, ok := hashObject.Pairs[key.HashKey()] + if !ok { + return NULL + } + + return pair.Value +} + func isTruthy(obj object.Object) bool { switch obj { case NULL: |
