Ejemplo n.º 1
0
        private static Object EvaluateFunctionExpression(Expression expression, IEnvironment env)
        {
            var obj = Object.Create(ObjectKind.Function, expression);

            obj.Environment = env;
            return(obj);
        }
Ejemplo n.º 2
0
        private void ExecuteHashOperation()
        {
            var count  = DecodeOperand(2);
            var hash   = new Dictionary <string, Object>();
            var keys   = new List <string>();
            var values = new List <Object>();

            internalState.CurrentFrame.InstructionPointer += 2;

            for (var i = 0; i < count; i++)
            {
                values.Add(internalState.Stack.Pop());
                keys.Add(internalState.Stack.Pop().Value.ToString().ToLower());
            }

            keys.Reverse();
            values.Reverse();

            for (var i = 0; i < keys.Count; i++)
            {
                hash.Add(keys[i], values[i]);
            }

            internalState.Stack.Push(Object.Create(ObjectKind.Hash, hash));
        }
Ejemplo n.º 3
0
        private static Object EvaluateHashIndexExpression(Object hash, Object key)
        {
            if (key.Kind != ObjectKind.Integer && key.Kind != ObjectKind.Boolean && key.Kind != ObjectKind.String)
            {
                return(Object.Create(ObjectKind.Error, Error.Create(new ErrorInfo
                {
                    Code = ErrorCode.HashIndexExpressionEvaluation,
                    Offenders = new List <object> {
                        hash, key
                    },
                    Kind = ErrorKind.InvalidType,
                    Source = ErrorSource.Evaluator
                })));
            }

            var hashtable = (Dictionary <string, Object>)hash.Value;
            var keyValue  = key.Value.ToString();

            if (hashtable.Count == 0 || keyValue == String.Empty)
            {
                return(Object.Create(ObjectKind.Null, null));
            }

            var hashKey = hashtable.Keys.Where(item => item == keyValue).FirstOrDefault();

            if (hashKey == default(string))
            {
                return(Object.Create(ObjectKind.Null, null));
            }

            return(hashtable[keyValue]);
        }
Ejemplo n.º 4
0
        private static Object EvaluateIdentifierExpression(Expression expression, IEnvironment env)
        {
            var value      = (string)((IdentifierExpression)expression).Value;
            var identifier = env.Get(value);

            if (identifier != default(Object))
            {
                return(identifier);
            }

            var builtIn = Functions.GetByName(value);

            if (builtIn != default(Object))
            {
                return(builtIn);
            }

            return(Object.Create(ObjectKind.Error, Error.Create(new ErrorInfo
            {
                Code = ErrorCode.IdentifierExpressionEvaluation,
                Offenders = new List <object> {
                    value
                },
                Kind = ErrorKind.InvalidIdentifier,
                Source = ErrorSource.Evaluator
            })));
        }
Ejemplo n.º 5
0
        private void ExecuteBinaryIntegerOperation(byte op, int left, int right)
        {
            switch (op)
            {
            case 2:      // Opcode.Add
                internalState.Stack.Push(Object.Create(ObjectKind.Integer, left + right));
                break;

            case 4:      // Opcode.Subtract
                internalState.Stack.Push(Object.Create(ObjectKind.Integer, left - right));
                break;

            case 5:      // Opcode.Multiply
                internalState.Stack.Push(Object.Create(ObjectKind.Integer, left * right));
                break;

            case 6:      // Opcode.Divide
                internalState.Stack.Push(Object.Create(ObjectKind.Integer, left / right));
                break;

            case 9:      // Opcode.Equal
                internalState.Stack.Push(left == right ? Invariants[true] : Invariants[false]);
                break;

            case 10:     // Opcode.NotEqual
                internalState.Stack.Push(left != right ? Invariants[true] : Invariants[false]);
                break;

            case 11:     // Opcode.GreaterThan
                internalState.Stack.Push(left > right ? Invariants[true] : Invariants[false]);
                break;
            }
        }
Ejemplo n.º 6
0
        private static Object EvaluatePrefixExpression(Expression expression, IEnvironment env)
        {
            var prefixExpression = (PrefixExpression)expression;
            var op = ((InfixExpression)prefixExpression.Left).Operator;

            switch (op.Kind)
            {
            case SyntaxKind.Bang:
                return(EvaluateBangOperatorExpression(prefixExpression.Right, env));

            case SyntaxKind.Minus:
                return(EvaluateMinusOperatorExpression(prefixExpression.Right, env));

            default:
                return(Object.Create(ObjectKind.Error, Error.Create(new ErrorInfo
                {
                    Code = ErrorCode.UnknownOperator,
                    Offenders = new List <object> {
                        op
                    },
                    Kind = ErrorKind.UnknownOperator,
                    Source = ErrorSource.Evaluator
                })));
            }
        }
Ejemplo n.º 7
0
        private static Object EvaluateStringInfixExpression(string left, Token op, string right)
        {
            switch (op.Kind)
            {
            case SyntaxKind.Plus:
                return(Object.Create(ObjectKind.String, string.Join(String.Empty, left, right)));

            case SyntaxKind.Equal:
                return(Object.Create(ObjectKind.Boolean, left == right));

            case SyntaxKind.NotEqual:
                return(Object.Create(ObjectKind.Boolean, left != right));

            default:
                return(Object.Create(ObjectKind.Error, Error.Create(new ErrorInfo
                {
                    Code = ErrorCode.StringExpressionOperatorEvaluation,
                    Offenders = new List <object> {
                        left, op, right
                    },
                    Kind = ErrorKind.UnknownOperator,
                    Source = ErrorSource.Evaluator
                })));
            }
        }
Ejemplo n.º 8
0
        private static Object EvaluateCallExpression(Expression expression, IEnvironment env)
        {
            List <Object>  args           = new List <Object>();
            CallExpression callExpression = (CallExpression)expression;
            Object         obj;

            if (callExpression.Identifier != default(Token))
            {
                obj = env.Get(callExpression.Identifier.Literal);
                obj = obj == default(Object) ? Functions.GetByName(callExpression.Identifier.Literal) : obj;
            }
            else
            {
                obj = Object.Create(ObjectKind.Function, callExpression.Function);
            }

            if (callExpression.Arguments != default(List <Expression>))
            {
                args = EvaluateExpressionList(callExpression.Arguments, env);
            }

            if (obj.Kind == ObjectKind.BuiltIn)
            {
                var fn = (Func <List <Object>, Object>)obj.Value;
                return(fn(args));
            }
            else
            {
                return(ApplyFunction(obj, args));
            }
        }
Ejemplo n.º 9
0
        private void ExecuteFunctionCallOperation(Object fn, int arity, int basePointer)
        {
            PushFrame(new Frame((Closure)fn.Value, basePointer));
            PushArguments(arity);

            // Merge closure (free) variables into locals, since we are doing
            // the same in the symbol table
            internalState.CurrentFrame.Locals.AddRange(internalState.CurrentFrame.Closure.Frees);
        }
Ejemplo n.º 10
0
 private void ExecuteBinaryStringOperation(byte op, string left, string right)
 {
     switch (op)
     {
     case 2:     // Opcode.Add
         internalState.Stack.Push(Object.Create(ObjectKind.String, string.Join(String.Empty, left, right)));
         break;
     }
 }
Ejemplo n.º 11
0
                public CompilerStateFactory Constant(int index, Object obj)
                {
                    if (index < constants.Count)
                    {
                        return(this);
                    }

                    constants.Add(obj);

                    return(this);
                }
Ejemplo n.º 12
0
        private static Object EvaluateInfixExpression(Expression expression, IEnvironment env)
        {
            var infixExpression = (InfixExpression)expression;

            var left = EvaluateExpression(infixExpression.Left, env);

            if (left.Kind == ObjectKind.Error)
            {
                return(left);
            }

            var right = EvaluateExpression(infixExpression.Right, env);

            if (right.Kind == ObjectKind.Error)
            {
                return(right);
            }

            if (left.Kind != right.Kind)
            {
                return(Object.Create(ObjectKind.Error, Error.Create(new ErrorInfo
                {
                    Code = ErrorCode.InfixExpressionEvaluation,
                    Offenders = new List <object> {
                        left, right
                    },
                    Kind = ErrorKind.InvalidType,
                    Source = ErrorSource.Evaluator
                })));
            }

            switch (left.Kind)
            {
            case ObjectKind.Integer:
                return(EvaluateIntegerInfixExpression((int)left.Value, infixExpression.Operator, (int)right.Value));

            case ObjectKind.Boolean:
                return(EvaluateBooleanInfixExpression((bool)left.Value, infixExpression.Operator, (bool)right.Value));

            case ObjectKind.String:
                return(EvaluateStringInfixExpression((string)left.Value, infixExpression.Operator, (string)right.Value));

            default:
                return(Object.Create(ObjectKind.Error, Error.Create(new ErrorInfo
                {
                    Code = ErrorCode.InfixExpressionOperatorEvaluation,
                    Offenders = new List <object> {
                        left, infixExpression.Operator, right
                    },
                    Kind = ErrorKind.UnknownOperator,
                    Source = ErrorSource.Evaluator
                })));
            }
        }
Ejemplo n.º 13
0
        private void ExecuteMinusOperation()
        {
            Object operand = internalState.Stack.Pop();

            if (operand.Kind != ObjectKind.Integer)
            {
                return;
            }

            int value = (int)operand.Value;

            internalState.Stack.Push(Object.Create(ObjectKind.Integer, -value));
        }
Ejemplo n.º 14
0
        private CompilerState CompileStringExpression(Expression expression, CompilerState previousState)
        {
            var stringExpression = (StringExpression)expression;

            var index = DetermineConstantIndex(expression, previousState);

            return(Factory.CompilerState()
                   .Assign(Emit((byte)Opcode.Name.Constant, new List <int> {
                index
            }, previousState))
                   .Constant(index, Object.Create(ObjectKind.String, stringExpression.Value))
                   .Create());
        }
Ejemplo n.º 15
0
        private void ExecuteBuiltInCallOperation(Object obj, int arity, int basePointer)
        {
            List <Object> args = new List <Object>();
            var           end  = basePointer + arity + 1;

            for (var i = basePointer + 1; i < end; i++)
            {
                args.Add(internalState.Stack[i]);
            }

            var fn     = (Func <List <Object>, Object>)obj.Value;
            var result = fn(args);

            internalState.Stack.Push(result);
        }
Ejemplo n.º 16
0
        private static Object EvaluateStatements(List <Statement> statements, IEnvironment env)
        {
            var obj = Object.Create(ObjectKind.Null, null);

            foreach (var statement in statements)
            {
                obj = EvaluateNode(statement, env);

                if (obj.Kind == ObjectKind.Error || obj.Kind == ObjectKind.Return)
                {
                    return(obj);
                }
            }

            return(obj);
        }
Ejemplo n.º 17
0
        private void ExecuteArrayOperation()
        {
            var count    = DecodeOperand(2);
            var elements = new List <Object>();

            internalState.CurrentFrame.InstructionPointer += 2;

            for (var i = 0; i < count; i++)
            {
                elements.Add(internalState.Stack.Pop());
            }

            elements.Reverse();

            internalState.Stack.Push(Object.Create(ObjectKind.Array, elements));
        }
Ejemplo n.º 18
0
        private static Object ApplyFunction(Object obj, List <Object> args)
        {
            var          functionExpression = (FunctionExpression)obj.Value;
            IEnvironment env = obj.Environment;

            if (functionExpression.Parameters != default(List <Token>) && args != default(List <Object>))
            {
                env = EncloseEnvironment(functionExpression.Parameters, args, env);
            }

            if (functionExpression.Body != default(BlockStatement))
            {
                return(EvaluateStatements(functionExpression.Body.Statements, env));
            }

            return(Object.Create(ObjectKind.Null, null));
        }
Ejemplo n.º 19
0
        private void ExecuteArrayIndexOperation(Object obj, Object index)
        {
            if (obj.Kind != ObjectKind.Array)
            {
                internalState.Stack.Push(Invariants["null"]);
                return;
            }

            var array = (List <Object>)obj.Value;

            if (index.Kind != ObjectKind.Integer || (int)index.Value < 0 || (int)index.Value >= array.Count)
            {
                internalState.Stack.Push(Invariants["null"]);
                return;
            }

            internalState.Stack.Push(array[(int)index.Value]);
        }
Ejemplo n.º 20
0
        private static Object EvaluateExpression(Expression expression, IEnvironment env)
        {
            switch (expression.Kind)
            {
            case ExpressionKind.Integer:
                return(EvaluateIntegerExpression(expression));

            case ExpressionKind.Boolean:
                return(EvaluateBooleanExpression(expression));

            case ExpressionKind.String:
                return(EvaluateStringExpression(expression));

            case ExpressionKind.Identifier:
                return(EvaluateIdentifierExpression(expression, env));

            case ExpressionKind.Prefix:
                return(EvaluatePrefixExpression(expression, env));

            case ExpressionKind.Infix:
                return(EvaluateInfixExpression(expression, env));

            case ExpressionKind.IfElse:
                return(EvaluateIfElseExpression(expression, env));

            case ExpressionKind.Function:
                return(EvaluateFunctionExpression(expression, env));

            case ExpressionKind.Call:
                return(EvaluateCallExpression(expression, env));

            case ExpressionKind.Array:
                return(EvaluateArrayExpression(expression, env));

            case ExpressionKind.Hash:
                return(EvaluateHashExpression(expression, env));

            case ExpressionKind.Index:
                return(EvaluateIndexExpression(expression, env));

            default:
                return(Object.Create(ObjectKind.Null, null));
            }
        }
Ejemplo n.º 21
0
        private void ExecuteBangOperation()
        {
            Object operand = internalState.Stack.Pop();

            switch (operand.Kind)
            {
            case ObjectKind.Boolean:
                internalState.Stack.Push(Invariants[!(bool)operand.Value]);
                break;

            case ObjectKind.Null:
                internalState.Stack.Push(Invariants[true]);
                break;

            default:
                internalState.Stack.Push(Invariants[false]);
                break;
            }
        }
Ejemplo n.º 22
0
        private static Object EvaluateNode(Node node, IEnvironment env)
        {
            switch (node.Kind)
            {
            case NodeKind.Program:
                return(EvaluateStatements(((Program)node).Statements, env));

            case NodeKind.Let:
                return(EvaluateLetStatement((Statement)node, env));

            case NodeKind.Return:
                return(EvaluateReturnStatement((Statement)node, env));

            case NodeKind.Expression:
                return(EvaluateExpression(((Statement)node).Expression, env));

            default:
                return(Object.Create(ObjectKind.Null, null));
            }
        }
Ejemplo n.º 23
0
            public static bool IsTruthy(Object obj)
            {
                switch (obj.Kind)
                {
                case ObjectKind.Boolean:
                    return((bool)obj.Value);

                case ObjectKind.Integer:
                    return((int)obj.Value != 0 ? true : false);

                case ObjectKind.String:
                    return((string)obj.Value != String.Empty ? true : false);

                case ObjectKind.Null:
                    return(false);

                default:
                    return(false);
                }
            }
Ejemplo n.º 24
0
        private void ExecuteHashIndexOperation(Object obj, Object index)
        {
            if (obj.Kind != ObjectKind.Hash)
            {
                internalState.Stack.Push(Invariants["null"]);
                return;
            }

            var hash = (Dictionary <string, Object>)obj.Value;

            if (index.Kind != ObjectKind.Integer && index.Kind != ObjectKind.Boolean && index.Kind != ObjectKind.String)
            {
                internalState.Stack.Push(Invariants["null"]);
                return;
            }

            var key = hash.Keys.Where(item => item == index.Value.ToString().ToLower()).FirstOrDefault();

            internalState.Stack.Push(key != default(string) ? hash[key] : Invariants["null"]);
        }
Ejemplo n.º 25
0
        private static Object EvaluateLetStatement(Statement statement, IEnvironment env)
        {
            var obj = Object.Create(ObjectKind.Null, null);

            if (statement.Identifier == default(Token) || statement.Expression == default(Expression))
            {
                return(obj);
            }

            var value = EvaluateExpression(statement.Expression, env);

            if (value.Kind == ObjectKind.Error)
            {
                return(value);
            }

            env.Set(statement.Identifier.Literal, value);

            return(obj);
        }
Ejemplo n.º 26
0
        private static Object EvaluateIntegerInfixExpression(int left, Token op, int right)
        {
            switch (op.Kind)
            {
            case SyntaxKind.Plus:
                return(Object.Create(ObjectKind.Integer, left + right));

            case SyntaxKind.Minus:
                return(Object.Create(ObjectKind.Integer, left - right));

            case SyntaxKind.Asterisk:
                return(Object.Create(ObjectKind.Integer, left * right));

            case SyntaxKind.Slash:
                return(Object.Create(ObjectKind.Integer, left / right));

            case SyntaxKind.GreaterThan:
                return(Object.Create(ObjectKind.Boolean, left > right));

            case SyntaxKind.LessThan:
                return(Object.Create(ObjectKind.Boolean, left < right));

            case SyntaxKind.Equal:
                return(Object.Create(ObjectKind.Boolean, left == right));

            case SyntaxKind.NotEqual:
                return(Object.Create(ObjectKind.Boolean, left != right));

            default:
                return(Object.Create(ObjectKind.Error, Error.Create(new ErrorInfo
                {
                    Code = ErrorCode.InfixExpressionOperatorEvaluation,
                    Offenders = new List <object> {
                        left, op, right
                    },
                    Kind = ErrorKind.UnknownOperator,
                    Source = ErrorSource.Evaluator
                })));
            }
        }
Ejemplo n.º 27
0
        private void ExecuteClosureOperation()
        {
            var index = DecodeOperand(2);

            internalState.CurrentFrame.InstructionPointer += 2;

            var freeCount = DecodeOperand(1);

            internalState.CurrentFrame.InstructionPointer += 1;

            var frees = new List <Object>();

            for (var i = 0; i < freeCount; i++)
            {
                frees.Add(internalState.Stack[internalState.Stack.Count - freeCount + i]);
            }

            var fn      = internalState.Constants[index];
            var closure = Object.Create(ObjectKind.Closure, new Closure((List <byte>)fn.Value, frees));

            internalState.Stack.Push(closure);
        }
Ejemplo n.º 28
0
        private static Object EvaluateBooleanInfixExpression(bool left, Token op, bool right)
        {
            switch (op.Kind)
            {
            case SyntaxKind.Equal:
                return(Object.Create(ObjectKind.Boolean, left == right));

            case SyntaxKind.NotEqual:
                return(Object.Create(ObjectKind.Boolean, left != right));

            default:
                return(Object.Create(ObjectKind.Error, Error.Create(new ErrorInfo
                {
                    Code = ErrorCode.BooleanInfixExpressionEvaluation,
                    Offenders = new List <object> {
                        left, op, right
                    },
                    Kind = ErrorKind.UnknownOperator,
                    Source = ErrorSource.Evaluator
                })));
            }
        }
Ejemplo n.º 29
0
        private static Object EvaluateArrayIndexExpression(Object array, Object index)
        {
            if (array.Kind != ObjectKind.Array)
            {
                return(Object.Create(ObjectKind.Error, Error.Create(new ErrorInfo
                {
                    Code = ErrorCode.ArrayExpressionEvaluation,
                    Offenders = new List <object> {
                        array, index
                    },
                    Kind = ErrorKind.InvalidType,
                    Source = ErrorSource.Evaluator
                })));
            }

            if (index.Kind != ObjectKind.Integer)
            {
                return(Object.Create(ObjectKind.Error, Error.Create(new ErrorInfo
                {
                    Code = ErrorCode.ArrayIndexExpressionEvaluation,
                    Offenders = new List <object> {
                        array, index
                    },
                    Kind = ErrorKind.InvalidType,
                    Source = ErrorSource.Evaluator
                })));
            }

            var elements   = (List <Object>)array.Value;
            var indexValue = (int)index.Value;

            if (elements.Count == 0 || indexValue < 0 || indexValue > elements.Count - 1)
            {
                return(Object.Create(ObjectKind.Null, null));
            }

            return(elements[indexValue]);
        }
Ejemplo n.º 30
0
        private void ExecuteBinaryOperation(byte op)
        {
            Object right = internalState.Stack.Pop();
            Object left  = internalState.Stack.Pop();

            if (left.Kind != right.Kind)
            {
                var info = new ErrorInfo
                {
                    Code      = ErrorCode.BinaryOperationInvalidOperand,
                    Kind      = ErrorKind.InvalidType,
                    Offenders = new List <object> {
                        left, op, right
                    },
                    Position = 2, // Consider right side as the offender
                    Source   = ErrorSource.VM
                };

                internalState.Stack.Push(Object.Create(ObjectKind.Error, Error.Create(info)));
                return;
            }

            switch (left.Kind)
            {
            case ObjectKind.Boolean:
                ExecuteBinaryBooleanOperation(op, (bool)left.Value, (bool)right.Value);
                break;

            case ObjectKind.String:
                ExecuteBinaryStringOperation(op, left.Value.ToString(), right.Value.ToString());
                break;

            default:
                ExecuteBinaryIntegerOperation(op, (int)left.Value, (int)right.Value);
                break;
            }
        }