Exemple #1
0
        private static MonkeyObject evalInfixExpression(string op, MonkeyObject left, MonkeyObject right)
        {
            if (left.Type == MonkeyObjectType.INTEGER && right.Type == MonkeyObjectType.INTEGER)
            {
                return(evalIntegerInfixExpression(op, left, right));
            }

            if (left.Type == MonkeyObjectType.STRING && right.Type == MonkeyObjectType.STRING)
            {
                return(evalStringInfixExpression(op, left, right));
            }

            if (op == "==")
            {
                return(nativeBoolToMonkeyBoolean(left == right));
            }

            if (op == "!=")
            {
                return(nativeBoolToMonkeyBoolean(left != right));
            }

            if (left.Type != right.Type)
            {
                return(new MonkeyError {
                    Message = $"type mismatch: {left.Type} {op} {right.Type}"
                });
            }

            return(new MonkeyError {
                Message = $"unknown operator: {left.Type} {op} {right.Type}"
            });
        }
Exemple #2
0
 private static MonkeyObject unwrapReturnValue(MonkeyObject obj)
 {
     if (obj is MonkeyReturnValue rv)
     {
         return(rv.Value);
     }
     return(obj);
 }
Exemple #3
0
        private static bool IsTruthy(this MonkeyObject value)
        {
            if (value == NULL || value == FALSE)
            {
                return(false);
            }

            return(true);
        }
 public bool Get(string name, out MonkeyObject value)
 {
     if (_store.TryGetValue(name, out value))
     {
         return(true);
     }
     if (_outer != null)
     {
         return(_outer.Get(name, out value));
     }
     return(false);
 }
Exemple #5
0
        private static MonkeyObject evalArrayIndexExpression(MonkeyObject array, MonkeyObject index)
        {
            var arrayObject = array as MonkeyArray;
            var idx         = (index as MonkeyInteger).Value;
            var max         = arrayObject.Elements.Count - 1;

            if (idx < 0 || idx > max)
            {
                return(NULL);
            }

            return(arrayObject.Elements[(int)idx]);
        }
Exemple #6
0
        private static MonkeyObject evalMinusPrefixOperatorExpression(MonkeyObject right)
        {
            if (right.Type != MonkeyObjectType.INTEGER)
            {
                return(new MonkeyError {
                    Message = $"unknown operator: -{right.Type}"
                });
            }

            var value = (MonkeyInteger)(right);

            return(new MonkeyInteger {
                Value = -value.Value
            });
        }
Exemple #7
0
        private static MonkeyObject evalIndexExpression(MonkeyObject left, MonkeyObject index)
        {
            if (left.Type == MonkeyObjectType.ARRAY && index.Type == MonkeyObjectType.INTEGER)
            {
                return(evalArrayIndexExpression(left, index));
            }
            if (left.Type == MonkeyObjectType.HASH)
            {
                return(evalHashIndexExpression(left, index));
            }

            return(new MonkeyError {
                Message = $"index operator not supported: {left.Type}"
            });
        }
Exemple #8
0
        private static MonkeyObject evalBlockStatement(BlockStatement blockStatement, Object.Environment environment)
        {
            MonkeyObject result = NULL;

            foreach (var statement in blockStatement.Statements)
            {
                result = Eval(statement, environment);

                if (result?.Type == MonkeyObjectType.RETURN_VALUE || result?.Type == MonkeyObjectType.ERROR)
                {
                    return(result);
                }
            }

            return(result);
        }
Exemple #9
0
        private static MonkeyObject evalStringInfixExpression(string op, MonkeyObject left, MonkeyObject right)
        {
            if (op != "+")
            {
                return(new MonkeyError {
                    Message = $"unknown operator: {left.Type} {op} {right.Type}"
                });
            }

            var leftVal  = (left as MonkeyString).Value;
            var rightVal = (right as MonkeyString).Value;

            return(new MonkeyString {
                Value = leftVal + rightVal
            });
        }
Exemple #10
0
        private static MonkeyObject evalPrefixExpression(string op, MonkeyObject right)
        {
            switch (op)
            {
            case "!":
                return(evalBangOperatorExpression(right));

            case "-":
                return(evalMinusPrefixOperatorExpression(right));

            default:
                return(new MonkeyError {
                    Message = $"unknown operator: {op}{right.Type}"
                });
            }
        }
Exemple #11
0
        private static MonkeyObject evalIntegerInfixExpression(string op, MonkeyObject left, MonkeyObject right)
        {
            var leftVal  = ((MonkeyInteger)left).Value;
            var rightVal = ((MonkeyInteger)right).Value;

            switch (op)
            {
            case "+":
                return(new MonkeyInteger {
                    Value = leftVal + rightVal
                });

            case "-":
                return(new MonkeyInteger {
                    Value = leftVal - rightVal
                });

            case "*":
                return(new MonkeyInteger {
                    Value = leftVal * rightVal
                });

            case "/":
                return(new MonkeyInteger {
                    Value = leftVal / rightVal
                });

            case "<":
                return(nativeBoolToMonkeyBoolean(leftVal < rightVal));

            case ">":
                return(nativeBoolToMonkeyBoolean(leftVal > rightVal));

            case "==":
                return(nativeBoolToMonkeyBoolean(leftVal == rightVal));

            case "!=":
                return(nativeBoolToMonkeyBoolean(leftVal != rightVal));

            default:
                return(new MonkeyError {
                    Message = $"unknown operator: {left.Type} {op} {right.Type}"
                });
            }
        }
Exemple #12
0
        private static MonkeyObject applyFunction(MonkeyObject function, IImmutableList <MonkeyObject> args)
        {
            if (function is Function fn)
            {
                var extendedEnv = extendFunctionEnv(fn, args);
                var evaluated   = Eval(fn.Body, extendedEnv);
                return(unwrapReturnValue(evaluated));
            }

            if (function is Builtin builtin)
            {
                return(builtin.Fn(args));
            }

            return(new MonkeyError {
                Message = $"not a function: {function.Type}"
            });
        }
Exemple #13
0
        private static MonkeyObject evalHashIndexExpression(MonkeyObject left, MonkeyObject index)
        {
            var hashObject = left as MonkeyHash;

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

            if (!hashObject.Pairs.TryGetValue(key.HashKey(), out var pair))
            {
                return(NULL);
            }

            return(pair.Value);
        }
Exemple #14
0
        private static MonkeyObject evalBangOperatorExpression(MonkeyObject right)
        {
            if (right == FALSE)
            {
                return(TRUE);
            }

            if (right == TRUE)
            {
                return(FALSE);
            }

            if (right == NULL)
            {
                return(TRUE);
            }

            return(FALSE);
        }
Exemple #15
0
        private static MonkeyObject evalProgram(Program p, Object.Environment environment)
        {
            MonkeyObject result = NULL;

            foreach (var statement in p.Statements)
            {
                result = Eval(statement, environment);

                switch (result)
                {
                case MonkeyReturnValue rv:
                    return(rv.Value);

                case MonkeyError:
                    return(result);

                default:
                    break;
                }
            }

            return(result);
        }
        private void TestBooleanObject(MonkeyObject evaluated, bool expected)
        {
            var b = Assert.IsType <MonkeyBoolean>(evaluated);

            Assert.Equal(expected, b.Value);
        }
        private void TestIntegerObject(MonkeyObject evaluated, Int64 expected)
        {
            var result = Assert.IsType <MonkeyInteger>(evaluated);

            Assert.Equal(expected, result.Value);
        }
 private void TestNullObject(MonkeyObject evaluated)
 {
     Assert.Equal(Evaluator.NULL, evaluated);
 }
 public MonkeyObject Set(string name, MonkeyObject value)
 {
     _store.Add(name, value);
     return(value);
 }