Beispiel #1
0
 protected void ResolveFunCallExpr(AstFunCallExpr expr)
 {
     ResolveExpr(expr.m_callee);
     foreach (AstExpr arg in expr.m_args)
     {
         ResolveExpr(arg);
     }
 }
Beispiel #2
0
    protected object EvaluateFunCallExpr(AstFunCallExpr expr)
    {
        if (HadErrorOrReturn())
        {
            return(null);
        }

        object    calleeObj = EvaluateExpr(expr.m_callee);
        IFunction callee    = calleeObj as IFunction;

        if (callee != null)
        {
            if (expr.m_args.Count != callee.ArgCount())
            {
                // TODO: print function name in the error

                m_runtimeError = true;
                Lox.Error(expr.m_startLine, "Function expected " + callee.ArgCount() + " arguments, but was passed " + expr.m_args.Count);
                return(null);
            }

            List <object> args = new List <object>();
            foreach (AstExpr argExpr in expr.m_args)
            {
                args.Add(EvaluateExpr(argExpr));
            }

            return(callee.Call(this, args));
        }
        else
        {
            // TODO: Distinguish between someUnknownFunction() and (3 + 1)() ?
            //  It would be nice to be able to print the name of the function in the former case

            m_runtimeError = true;
            Lox.Error(expr.m_startLine, "Invalid function call");
            return(null);
        }
    }
Beispiel #3
0
    protected AstExpr ParseFunCallExpr()
    {
        AstExpr expr = ParsePrimaryExpr();

        if (expr == null)
        {
            return(EmptyErrorExpr());
        }

        Token token;

        // NOTE (andrews) While loop handles chained function calls and member access like this:
        //  some.member.functionThatReturnsFunction()();

        while (true)
        {
            if ((token = TryMatch(TOKENK.OpenParen)) != null)
            {
                bool           isFirstArg = true;
                List <AstExpr> args       = new List <AstExpr>();
                while ((token = TryMatch(TOKENK.CloseParen)) == null)
                {
                    if (!isFirstArg)
                    {
                        AstExpr prevArg = args[args.Count - 1];

                        if ((token = TryMatch(TOKENK.Comma)) == null)
                        {
                            return(ErrorExpr(prevArg.m_startLine, "Expected ',' in argument list"));
                        }

                        if (args.Count == AstFunCallExpr.s_maxArgCount)
                        {
                            // NOTE (andrews) This isn't a parse error so we don't return ErrorExpr like we do for other parse errors.
                            //  This lets us report it while continuing the parse in case we find other errors.

                            Lox.Error(prevArg.m_startLine, "Cannot exceed " + AstFunCallExpr.s_maxArgCount + " arguments");
                        }
                    }

                    AstExpr arg = ParseExpr();
                    if (arg == null)
                    {
                        return(EmptyErrorExpr());
                    }

                    args.Add(arg);
                    isFirstArg = false;
                }

                expr = new AstFunCallExpr(expr, args);
            }
            else if ((token = TryMatch(TOKENK.Dot)) != null)
            {
                if ((token = TryMatch(TOKENK.Identifier)) != null)
                {
                    expr = new AstVarExpr(expr, token);
                }
            }
            else
            {
                return(expr);
            }
        }
    }