private object InvokeMethodSymbol(MethodSymbol method, List<Ast> args)
        {
            // create a new memory scope. this is where arguments will get defined
            // we wont overwrite any memory values since they will all be local here
            MemorySpaces.CreateScope();

            var count = 0;

            if (method.MethodDeclr.Arguments.Count != args.Count)
            {
                throw new InvalidSyntax(String.Format("Wrong number of arguments passed to method {0}. Got {1}, expected {2}",
                    method.MethodDeclr.MethodName.Token.TokenValue,
                    args.Count, method.MethodDeclr.Arguments.Count));
            }

            foreach (VarDeclrAst expectedArgument in method.MethodDeclr.Arguments)
            {
                var currentArgument = args[count];

                var oldmemory = MemorySpaces.Current;

                // if the argument is coming from somewhere else, make sure to be able to
                // load the argument from its preferred space.
                if (currentArgument.CallingMemory != null)
                {
                    MemorySpaces.Current = currentArgument.CallingMemory;
                }

                var value = GetValue(Exec(currentArgument));

                // since we were just loading values from the argument space
                // switch back to the current space so we can assign the argument value
                // into our local working memory
                MemorySpaces.Current = oldmemory;

                if (expectedArgument.VariableValue == null)
                {
                    MemorySpaces.Current.Define(expectedArgument.Token.TokenValue, value);
                }
                else
                {
                    MemorySpaces.Current.Assign(expectedArgument.Token.TokenValue, value);
                }

                // if the passed in argument is a word and not a literal (like string or bool) then
                // pull its value from memory so we can match type to the target type
                var resolvedSymbol = (currentArgument.Token.TokenType == TokenType.Word ?
                                                MemorySpaces.Current.Get(currentArgument.Token.TokenValue)
                                            :   args[count]) as Symbol;

                var resolvedType = resolvedSymbol != null ? resolvedSymbol.Type : currentArgument.AstSymbolType;

                if (currentArgument is MethodDeclr)
                {
                    resolvedType = new BuiltInType(ExpressionTypes.Method);
                }

                if (!TokenUtil.EqualOrPromotable(expectedArgument.AstSymbolType, resolvedType))
                {
                    throw new InvalidSyntax(String.Format("Cannot pass argument {0} of type {1} to function {2} as argument {3} of type {4}",
                        currentArgument.Token.TokenValue,
                        currentArgument.AstSymbolType.TypeName,
                        method.MethodDeclr.MethodName.Token.TokenValue,
                        expectedArgument.VariableName.Token.TokenValue,
                        expectedArgument.AstSymbolType.TypeName));
                }

                count++;
            }

            var val = Exec(method.MethodDeclr.Body);

            MemorySpaces.PopScope();

            return val;
        }
        private void VariableDeclaration(VarDeclrAst varDeclrAst)
        {
            if (varDeclrAst.VariableValue == null)
            {
                var symbol = varDeclrAst.CurrentScope.Resolve(varDeclrAst.VariableName.Token.TokenValue);

                var space = MemorySpaces.Current;

                space.Define(symbol.Name, TokenType.Nil);

                return;
            }

            var variableValue = varDeclrAst.VariableValue.ConvertedExpression ?? varDeclrAst.VariableValue;

            // if the rhs of a variable is not a method, then execute it,
            if (variableValue.AstType != AstTypes.MethodDeclr)
            {
                var value = GetValue(Exec(variableValue));

                if (value != null)
                {
                    var symbol = varDeclrAst.CurrentScope.Resolve(varDeclrAst.VariableName.Token.TokenValue);

                    var space = MemorySpaces.Current;

                    if (variableValue.IsLink)
                    {
                        space.Link(symbol.Name, variableValue.Token.TokenValue);
                    }
                    else
                    {
                        space.Define(symbol.Name, value);
                    }
                }
            }
            else
            {
                var symbol = varDeclrAst.CurrentScope.Resolve(varDeclrAst.VariableName.Token.TokenValue);

                var resolvedMethod = varDeclrAst.CurrentScope.Resolve(variableValue.Token.TokenValue) as MethodSymbol;

                // make sure to create a NEW method symbol. this way each time we declare this item
                // it will create a local copy and get its own memory space for closures.
                // if we shared the same method symbol then all instances of the same declaration would share the memory space,
                // which may not be what we want given class instances having their own spaces

                var localMethodCopy = new MethodSymbol(resolvedMethod.Name, resolvedMethod.Type,
                                                       resolvedMethod.MethodDeclr);

                var space = MemorySpaces.Current;

                if (variableValue is LambdaDeclr)
                {
                    localMethodCopy.Environment = space;
                }

                space.Define(symbol.Name, localMethodCopy);
            }
        }
        private LambdaDeclr CreateCurriedMethod(FuncInvoke ast, MethodSymbol functionType)
        {
            var srcMethod = functionType.MethodDeclr;

            var fixedAssignments = new List<VarDeclrAst>();

            var count = 0;
            foreach (var argValue in ast.Arguments)
            {
                var srcArg = srcMethod.Arguments[count] as VarDeclrAst;

                var token = new Token(srcArg.DeclarationType.Token.TokenType, argValue.Token.TokenValue);

                var declr = new VarDeclrAst(token, srcArg.Token, new Expr(argValue.Token));

                // if we're creating a curry using a variable then we need to resolve the variable type
                // otherwise we can make a symbol for the literal
                var newArgType = argValue.Token.TokenType == TokenType.Word ?
                                        ast.CurrentScope.Resolve(argValue).Type
                                    :   ScopeUtil.CreateSymbolType(argValue);

                // create a symbol type for the target we're invoking on so we can do type checking
                var targetArgType = ScopeUtil.CreateSymbolType(srcArg.DeclarationType);

                if (!TokenUtil.EqualOrPromotable(newArgType, targetArgType))
                {
                    throw new InvalidSyntax(String.Format("Cannot pass argument {0} of type {1} to partial function {2} as argument {3} of type {4}",
                        argValue.Token.TokenValue,
                        newArgType.TypeName,
                        srcMethod.MethodName.Token.TokenValue,
                        srcArg.VariableName.Token.TokenValue,
                        targetArgType.TypeName));
                }

                fixedAssignments.Add(declr);

                count++;
            }

            var newBody = fixedAssignments.Concat(srcMethod.Body.ScopedStatements).ToList();

            var curriedMethod = new LambdaDeclr(srcMethod.Arguments.Skip(ast.Arguments.Count).ToList(), new ScopeDeclr(newBody));

            SetScope(curriedMethod);

            return curriedMethod;
        }