示例#1
0
        private static Object.Object EvalHashLiteral(HashLiteral node, Object.Environment env)
        {
            var pairs = new Dictionary <HashKey, HashPair>();

            foreach (KeyValuePair <Expression, Expression> pair in node.Pairs)
            {
                Object.Object key = Eval(pair.Key, env);
                if (IsError(key))
                {
                    return(key);
                }
                var hashKey = key as IHash;
                if (hashKey == null)
                {
                    return(new Error {
                        Message = $"unusable as hash key: {key.Type()}"
                    });
                }
                var value = Eval(pair.Value, env);
                if (IsError(value))
                {
                    return(value);
                }
                var hashed = hashKey.HashKey();
                pairs.Add(hashed, new HashPair {
                    Key = key, Value = value
                });
            }
            return(new Hash {
                Pairs = pairs
            });
        }
示例#2
0
        private IExpression ParseHashLiteral()
        {
            var hash = new HashLiteral {
                Token = currentToken
            };

            hash.Pairs = new Dictionary <IExpression, 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.Add(key, value);

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

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

            return(hash);
        }
示例#3
0
        private Ast.Expression ParseHashLiteral()
        {
            var hash = new HashLiteral {
                Token = this._curToken
            };

            hash.Pairs = new Dictionary <Expression, Expression>();
            while (!this.PeekTokenIs(TokenType.RBRACE))
            {
                this.NextToken();
                var key = this.ParseExpression(Precedence.LOWEST);
                if (!this.ExpectPeek(TokenType.COLON))
                {
                    throw new ParserException($"want {TokenType.COLON} but got {this._peekToken}");
                }
                this.NextToken();
                var value = this.ParseExpression(Precedence.LOWEST);
                hash.Pairs[key] = value;
                if (!this.PeekTokenIs(TokenType.RBRACE) && !this.ExpectPeek(TokenType.COMMA))
                {
                    throw new ParserException($"want {TokenType.RBRACE} or {TokenType.COMMA}  but got {this._peekToken}");
                }
            }
            if (!this.ExpectPeek(TokenType.RBRACE))
            {
                throw new ParserException($"want {TokenType.RBRACE} but got {this._peekToken}");
            }
            return(hash);
        }
示例#4
0
        public void Parser_CanParseHashLiterals()
        {
            string input = @"{""one"":1, ""two"": 2, ""three"": 3}";

            AST result = this.subject.ParseProgram(input);

            Assert.Empty(result.Errors);
            Assert.Equal(1, result.Program.Statements.Count);
            ExpressionStatement expr     = this.AssertAndCast <ExpressionStatement>(result.Program.Statements[0]);
            HashLiteral         hashExpr = this.AssertAndCast <HashLiteral>(expr.Expression);

            Assert.Equal(3, hashExpr.Pairs.Count);

            var expected = new Dictionary <string, string>()
            {
                { "one", "1" },
                { "two", "2" },
                { "three", "3" }
            }.ToImmutableDictionary();

            var actual = ImmutableDictionary.CreateRange <string, string>(
                hashExpr.Pairs.Select(kv =>
                                      new KeyValuePair <string, string>(kv.Key.StringValue, kv.Value.StringValue)
                                      )
                );
        }
示例#5
0
        private IExpression ParseHashLiteral()
        {
            var hash = new HashLiteral {
                Token = CurrentToken, Pairs = new Dictionary <IExpression, IExpression>()
            };

            while (!PeekTokenIs(Token.Rbrace))
            {
                NextToken();
                var key = ParseExpression(Enums.Precedences.Lowest);

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

                NextToken();

                var value = ParseExpression(Enums.Precedences.Lowest);

                hash.Pairs.Add(key, value);

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

            return(!ExpectPeek(Token.Rbrace) ? null : hash);
        }
示例#6
0
        public void Parser_CanParseEmptyHashes()
        {
            string input = "{}";

            AST result = this.subject.ParseProgram(input);

            Assert.Empty(result.Errors);
            Assert.Equal(1, result.Program.Statements.Count);
            ExpressionStatement expr     = this.AssertAndCast <ExpressionStatement>(result.Program.Statements[0]);
            HashLiteral         hashExpr = this.AssertAndCast <HashLiteral>(expr.Expression);

            Assert.Equal(0, hashExpr.Pairs.Count);
        }
示例#7
0
        private IExpression ParseHashLiteral()
        {
            var hash = new HashLiteral
            {
                Token = _currentToken,
                Pairs = new Dictionary <IExpression, IExpression>()
            };

            while (!PeekTokenIs(TokenType.RBRACE))
            {
                NextToken();
                var key = ParseExpression(Precedences.LOWEST);

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

                NextToken();
                var value = ParseExpression(Precedences.LOWEST);

                hash.Pairs.Add(key, value);

                if (!PeekTokenIs(TokenType.RBRACE) && !ExpectPeek(TokenType.COMMA))
                {
                    return(null);
                }
            }

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

            return(hash);
        }
示例#8
0
        private static MonkeyObject evalHashLiteral(HashLiteral hl, Object.Environment environment)
        {
            var pairs = new Dictionary <HashKey, HashPair>();

            foreach (var(keyNode, valueNode) in hl.Pairs)
            {
                var key = Eval(keyNode, environment);
                if (key?.Type == MonkeyObjectType.ERROR)
                {
                    return(key);
                }

                if (!(key is Hashable))
                {
                    return(new MonkeyError {
                        Message = $"unusable as hash key: {key.Type}"
                    });
                }

                var hashKey = key as Hashable;
                var value   = Eval(valueNode, environment);
                if (value?.Type == MonkeyObjectType.ERROR)
                {
                    return(value);
                }

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

            return(new MonkeyHash {
                Pairs = pairs
            });
        }
示例#9
0
        public void Modify_Replaces_Nodes()
        {
            var token1             = new Token(Token.Int, "1");
            var token2             = new Token(Token.Int, "2");
            Func <IExpression> one = () => new IntegerLiteral(null)
            {
                Value = 1
            };
            Func <IExpression> two = () => new IntegerLiteral(null)
            {
                Value = 2
            };
            Func <INode, INode> turnOneIntoTwo = (node) =>
            {
                if (node is IntegerLiteral integer)
                {
                    if (integer.Value != 1)
                    {
                        return(node);
                    }
                    integer.Value = 2;
                    return(integer);
                }

                return(node);
            };
            var tests = new Dictionary <INode, INode>
            {
                { one(),
                  two() },

                { new ProgramNode()
                  {
                      Statements = new List <IStatement> {
                          new ExpressionStatement(null)
                          {
                              Expression = one()
                          }
                      }
                  },
                  new ProgramNode()
                  {
                      Statements = new List <IStatement> {
                          new ExpressionStatement(null)
                          {
                              Expression = two()
                          }
                      }
                  } },

                { new InfixExpression(null)
                  {
                      Left = one(), Operator = "+", Right = two()
                  },
                  new InfixExpression(null)
                  {
                      Left = two(), Operator = "+", Right = two()
                  } },

                { new InfixExpression(null)
                  {
                      Left = two(), Operator = "+", Right = one()
                  },
                  new InfixExpression(null)
                  {
                      Left = two(), Operator = "+", Right = two()
                  } },

                { new PrefixExpression(null)
                  {
                      Operator = "-", Right = one()
                  },
                  new PrefixExpression(null)
                  {
                      Operator = "-", Right = two()
                  } },

                { new IndexExpression(null)
                  {
                      Left = one(), Index = one()
                  },
                  new IndexExpression(null)
                  {
                      Left = two(), Index = two()
                  } },

                { new IfExpression(null)
                  {
                      Condition   = one(),
                      Consequence = new BlockStatement(null)
                      {
                          Statements = new List <IStatement>()
                          {
                              new ExpressionStatement(null)
                              {
                                  Expression = one()
                              }
                          }
                      },
                      Alternative = new BlockStatement(null)
                      {
                          Statements = new List <IStatement>()
                          {
                              new ExpressionStatement(null)
                              {
                                  Expression = one()
                              }
                          }
                      }
                  },
                  new IfExpression(null)
                  {
                      Condition   = two(),
                      Consequence = new BlockStatement(null)
                      {
                          Statements = new List <IStatement>()
                          {
                              new ExpressionStatement(null)
                              {
                                  Expression = two()
                              }
                          }
                      },
                      Alternative = new BlockStatement(null)
                      {
                          Statements = new List <IStatement>()
                          {
                              new ExpressionStatement(null)
                              {
                                  Expression = two()
                              }
                          }
                      }
                  } },

                { new ForExpression(null)
                  {
                      Body = new BlockStatement(null)
                      {
                          Statements = new List <IStatement>()
                          {
                              new ExpressionStatement(null)
                              {
                                  Expression = one()
                              }
                          }
                      },
                      Collection = new ArrayLiteral(null)
                      {
                          Elements = new List <IExpression>()
                          {
                              one()
                          }
                      },
                      KeyIdentifier = new Identifier(null)
                      {
                          Value = "item"
                      }
                  },
                  new ForExpression(null)
                  {
                      Body = new BlockStatement(null)
                      {
                          Statements = new List <IStatement>()
                          {
                              new ExpressionStatement(null)
                              {
                                  Expression = two()
                              }
                          }
                      },
                      Collection = new ArrayLiteral(null)
                      {
                          Elements = new List <IExpression>()
                          {
                              two()
                          }
                      },
                      KeyIdentifier = new Identifier(null)
                      {
                          Value = "item"
                      }
                  } },

                { new ReturnStatement(null)
                  {
                      ReturnValue = one()
                  },
                  new ReturnStatement(null)
                  {
                      ReturnValue = two()
                  } },

                { new LetStatement(null)
                  {
                      Value = one()
                  },
                  new LetStatement(null)
                  {
                      Value = two()
                  } },

                { new FunctionLiteral(null)
                  {
                      Parameters = new List <Identifier>(),
                      Body       = new BlockStatement(null)
                      {
                          Statements = new List <IStatement>()
                          {
                              new ExpressionStatement(null)
                              {
                                  Expression = one()
                              }
                          }
                      }
                  },
                  new FunctionLiteral(null)
                  {
                      Parameters = new List <Identifier>(),
                      Body       = new BlockStatement(null)
                      {
                          Statements = new List <IStatement>()
                          {
                              new ExpressionStatement(null)
                              {
                                  Expression = two()
                              }
                          }
                      }
                  } },

                { new ArrayLiteral(null)
                  {
                      Elements = new List <IExpression>()
                      {
                          one(), one()
                      }
                  },
                  new ArrayLiteral(null)
                  {
                      Elements = new List <IExpression>()
                      {
                          two(), two()
                      }
                  } },
            };

            foreach (var test in tests)
            {
                var modified     = Parser.Modify(test.Key, turnOneIntoTwo);
                var jsonModified = Newtonsoft.Json.JsonConvert.SerializeObject(modified);
                var jsonExpected = Newtonsoft.Json.JsonConvert.SerializeObject(test.Value);

                Assert.Equal(jsonExpected, jsonModified);
            }

            var hashLiteral = new HashLiteral(null)
            {
                Pairs = new Dictionary <IExpression, IExpression>()
                {
                    { one(), one() },
                    { one(), one() }
                }
            };

            Parser.Modify(hashLiteral, turnOneIntoTwo);

            foreach (var kvp in hashLiteral.Pairs)
            {
                var key = Assert.IsType <IntegerLiteral>(kvp.Key);
                var val = Assert.IsType <IntegerLiteral>(kvp.Value);

                Assert.Equal(2, key.Value);
                Assert.Equal(2, val.Value);
            }
        }