private Ast.IExpression ParseHashLiteral()
        {
            var hash = new Ast.HashLiteral {
                Token = _curToken,
                Pairs = new Dictionary <Ast.IExpression, Ast.IExpression>()
            };

            while (!PeekTokenIs(TokenType.Rbrace))
            {
                NextToken();
                var key = ParseExpression(Precedence.Lowest);

                if (!ExpectPeek(TokenType.Colon))
                {
                    return(null);
                }

                NextToken();
                var value = ParseExpression(Precedence.Lowest);

                hash.Pairs[key] = value;

                if (!PeekTokenIs(TokenType.Rbrace) && !ExpectPeek(TokenType.Comma))
                {
                    return(null);
                }
            }

            if (!ExpectPeek(TokenType.Rbrace))
            {
                return(null);
            }

            return(hash);
        }
        private static IObject EvalHashLiteral(Ast.HashLiteral node, Environment env)
        {
            var pairs = new Dictionary <HashKey, HashPair>();

            foreach (var pair in node.Pairs)
            {
                var key = Eval(pair.Key, env);
                if (IsError(key))
                {
                    return(key);
                }

                if (!(key is IHashable hashKey))
                {
                    return new Error {
                               Message = $"unusable as hash key: {key.getType()}"
                    }
                }
                ;

                var value = Eval(pair.Value, env);
                if (IsError(value))
                {
                    return(value);
                }

                var hashed = hashKey.HashKey();
                pairs[hashed] = new HashPair {
                    Key = key, Value = value
                };
            }

            return(new Hash {
                Pairs = pairs
            });
        }
    }