aboutsummaryrefslogtreecommitdiff
path: root/evaluator/evaluator.go
diff options
context:
space:
mode:
Diffstat (limited to 'evaluator/evaluator.go')
-rw-r--r--evaluator/evaluator.go47
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: