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 }))); }
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]); }
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)); }
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 }))); } }
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 }))); } }
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; } }
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)); } }
private static Object EvaluateFunctionExpression(Expression expression, IEnvironment env) { var obj = Object.Create(ObjectKind.Function, expression); obj.Environment = env; return(obj); }
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; } }
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 }))); } }
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()); }
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)); }
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); }
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)); }
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)); }
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)); } }
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)); } }
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); }
static Functions() { List = new List <BuiltIn> { new BuiltIn { Name = "len", Function = Object.Create(ObjectKind.BuiltIn, Len) }, new BuiltIn { Name = "first", Function = Object.Create(ObjectKind.BuiltIn, First) }, new BuiltIn { Name = "last", Function = Object.Create(ObjectKind.BuiltIn, Last) }, new BuiltIn { Name = "rest", Function = Object.Create(ObjectKind.BuiltIn, Rest) }, new BuiltIn { Name = "push", Function = Object.Create(ObjectKind.BuiltIn, Push) } }; }
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 }))); } }
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); }
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 }))); } }
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]); }
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; } }
private static Object EvaluateMinusOperatorExpression(Expression expression, IEnvironment env) { var value = EvaluateExpression(expression, env); if (value.Kind == ObjectKind.Error) { return(value); } if (value.Kind != ObjectKind.Integer) { return(Object.Create(ObjectKind.Error, Error.Create(new ErrorInfo { Code = ErrorCode.MinusOperatorExpressionEvaluation, Offenders = new List <object> { value }, Kind = ErrorKind.InvalidType, Source = ErrorSource.Evaluator }))); } return(Object.Create(ObjectKind.Integer, -(int)value.Value)); }
private static Object EvaluateIfElseExpression(Expression expression, IEnvironment env) { var ifElseExpression = (IfElseExpression)expression; var condition = EvaluateExpression(ifElseExpression.Condition, env); if (condition.Kind == ObjectKind.Error) { return(condition); } if (IsTruthy(condition)) { return(EvaluateStatements(ifElseExpression.Consequence.Statements, env)); } else if (ifElseExpression.Alternative != default(BlockStatement)) { return(EvaluateStatements(ifElseExpression.Alternative.Statements, env)); } else { return(Object.Create(ObjectKind.Null, null)); } }
private static Object EvaluateBangOperatorExpression(Expression expression, IEnvironment env) { var obj = EvaluateExpression(expression, env); switch (obj.Kind) { case ObjectKind.Integer: return(Object.Create(ObjectKind.Boolean, !((int)obj.Value != 0))); case ObjectKind.Boolean: return(Object.Create(ObjectKind.Boolean, !(bool)obj.Value)); default: return(Object.Create(ObjectKind.Error, Error.Create(new ErrorInfo { Code = ErrorCode.BangOperatorExpressionEvaluation, Offenders = new List <object> { obj }, Kind = ErrorKind.InvalidType, Source = ErrorSource.Evaluator }))); } }
private static Object EvaluateHashExpression(Expression expression, IEnvironment env) { var hashExpression = (HashExpression)expression; var hash = new Dictionary <string, Object>(); for (var i = 0; i < hashExpression.Keys.Count; i++) { var key = EvaluateExpression(hashExpression.Keys[i], env); var value = EvaluateExpression(hashExpression.Values[i], env); var previousKey = hash.Keys.Where(item => item == key.Value.ToString()).FirstOrDefault(); if (previousKey != default(string)) { hash[previousKey] = Object.Create(value.Kind, value.Value); } else { hash.Add(key.Value.ToString(), Object.Create(value.Kind, value.Value)); } } return(Object.Create(ObjectKind.Hash, hash)); }
private static Object EvaluateArrayExpression(Expression expression, IEnvironment env) { var arrayExpression = (ArrayExpression)expression; return(Object.Create(ObjectKind.Array, EvaluateExpressionList(arrayExpression.Elements, env))); }
private static Object EvaluateStringExpression(Expression expression) { return(Object.Create(ObjectKind.String, ((StringExpression)expression).Value)); }