private object NewDo(NewAst ast)
        {
            var className = Resolve(ast);

            var classType = (className as ClassSymbol).Src as ClassAst;

            var space = new MemorySpace();

            var oldSpace = MemorySpaces.Current;

            MemorySpaces.Current = space;

            foreach (var symbol in classType.Body.ScopedStatements)
            {
                Exec(symbol);
            }

            if (classType.Constructor != null)
            {
                var funcInvoke = new FuncInvoke(classType.Constructor.Token, ast.Args);

                funcInvoke.CurrentScope = classType.Body.CurrentScope;

                Exec(funcInvoke);
            }

            MemorySpaces.Current = oldSpace;

            return(space);
        }
        public void Visit(FuncInvoke ast)
        {
            if (ast.CallingScope != null)
            {
                ast.Arguments.ForEach(arg => arg.CallingScope = ast.CallingScope);
            }

            ast.Arguments.ForEach(arg => arg.Visit(this));

            SetScope(ast);

            var functionType = Resolve(ast.FunctionName) as MethodSymbol;

            if (functionType != null && ast.Arguments.Count < functionType.MethodDeclr.Arguments.Count)
            {
                var curriedMethod = CreateCurriedMethod(ast, functionType);

                curriedMethod.Visit(this);

                var methodSymbol = ScopeUtil.DefineMethod(curriedMethod);

                Current.Define(methodSymbol);

                ast.ConvertedExpression = curriedMethod;
            }
            else if (ResolvingTypes)
            {
                ast.AstSymbolType = ResolveType(ast.FunctionName, ast.CurrentScope);
            }
        }
        private object InvokeFunction(FuncInvoke funcInvoke)
        {
            var method = Resolve(funcInvoke);

            if (method != null)
            {
                var invoker = method as MethodSymbol;

                if (invoker == null)
                {
                    invoker = MemorySpaces.Current.Get(method.Name) as MethodSymbol;
                }

                // arguments should always be resolved from the current calling space
                // so make sure the invoking function knows which space it comes from
                if (funcInvoke.CallingMemory == null)
                {
                    funcInvoke.CallingMemory = MemorySpaces.Current;
                }

                if (funcInvoke.CallingMemory != null && !CollectionUtil.IsNullOrEmpty(funcInvoke.Arguments))
                {
                    funcInvoke.Arguments.ForEach(arg => arg.CallingMemory = funcInvoke.CallingMemory);
                }

                var oldMemory = MemorySpaces.Current;

                try
                {
                    // if we're a lambda and we have some sort of closure
                    // set our working space to be that.
                    if (invoker.Environment != null)
                    {
                        MemorySpaces.Current = invoker.Environment;
                    }

                    var value = InvokeMethodSymbol(invoker, funcInvoke.Arguments);

                    return(value);
                }
                finally
                {
                    MemorySpaces.Current = oldMemory;
                }
            }

            throw new UndefinedElementException("Undefined method");
        }
        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);
        }
 public void Visit(FuncInvoke ast)
 {
     Exec(ast);
 }
        public void Visit(FuncInvoke ast)
        {
            ast.FunctionName.Visit(this);

            ast.Arguments.ForEach(arg => arg.Visit(this));
        }