Esempio n. 1
0
 void ASTVisitor.Accept(NodeFnExpr value)
 {
     Accept(value);
 }
Esempio n. 2
0
        internal void Accept(NodeFnExpr fn)
        {
            // COMPILERRRRRRRR! DUDUDUDU DUN DUNNNNN DU DU-UNNN DU DU-UNNN DU DU-UNN (guitar noises) (Dope - Nothing For Me Here (listening to music is fun (just wait till Reol comes on (you won't regret it (れをる <3 (Japanese input is too fun (I'm done now)))))))
            var compiler = new FunctionCompiler(log, builder);

            compiler.builder.trulyAnon = fn.fullAnon;
            compiler.builder.hasVargs = fn.hasVargs;
            compiler.builder.isGenerator = fn.isGenerator;

            // params/vargs
            if (fn.fullAnon)
                fn.paramNames.ForEach(param => compiler.builder.ReserveParameter());
            else fn.paramNames.ForEach(param => compiler.builder.AddParameter(param));

            // Now do codeee
            fn.body.isResultRequired = !fn.isVoid;
            fn.body.inTailPosition = true;
            fn.body.Visit(compiler);

            // Now, we should have a completely compiled function!
            var proto = compiler.GetPrototype();
            // Load the default param values
            fn.defaultParams.ForEach(def => def.Visit(this));
            // Push that to the stack plz
            builder.OpClosure(proto, (uint)fn.defaultParams.Count);
            // If this is a generator, make it so.
            if (fn.isGenerator)
                builder.OpGenerator();
        }
Esempio n. 3
0
 private void SetCurrentFunction(NodeFnExpr fn)
 {
     holder = new FunctionHolder(holder, fn);
 }
Esempio n. 4
0
        private Node ParseFn(bool isGenerator = false)
        {
            // Use the location of 'fn' as the location of this function.
            // The end of the function can be determined by the end of
            // it's body, so it's only expected to rely on the
            // line/col fields for functions.
            var loc = Location;
            // The first token we'll have is 'fn', so skip it.
            Advance();

            // We'll use this later, after checking for a name
            NodeFnExpr fn;

            // Next, check if there's an open brace.
            // If an open brace follows 'fn', it must be a lambda,
            // otherwise it's a definition, we need a location.
            if (Check(ASSIGN) || Check(OPEN_CURLY_BRACE))
            {
                fn = new NodeFnExpr(loc);
                fn.fullAnon = true;
            }
            else if (!Check(OPEN_BRACE))
            {
                fn = new NodeFnDef(loc);
                (fn as NodeFnDef).target = PrimaryExpression(false);
            }
            else fn = new NodeFnExpr(loc);
            fn.isGenerator = isGenerator;

            if (!fn.fullAnon)
            {
                // Hope that this is the open brace we seek.
                // TODO If not, maybe I should try to recover better.
                Expect(OPEN_BRACE,
                    "Expected an open brace ('(') to start the function parameter list.");

                // Now, we need to get the argument list.
                while (true)
                {
                    if (!TokensRemain)
                    {
                        log.Error(tokens[-1].location, "End of file reached, expected a parameter declaration.");
                        break;
                    }

                    // Break out early if we see a close brace.
                    // Even if it's not at the right time, it's
                    // a safe place to break.
                    if (Check(CLOSE_BRACE))
                        break;
                    // Next check for a parameter.
                    string paramName;
                    // If there's an identifier, it's a param
                    if (ExpectIdentifier(out paramName, "Expected identifier to name function parameter."))
                        fn.paramNames.Add(paramName);
                    // Otherwise, let's try to get the next param immediately
                    // rather than skipping or fumbling with more tokens.
                    else continue;
                    if (Check(ASSIGN))
                    {
                        Advance();
                        if (!TokensRemain)
                        {
                            log.Error(tokens[-1].location, "Expected expression for default parameter value, but the end of the file was reached.");
                            return fn;
                        }
                        fn.defaultParams.Add(Expression());
                    }
                    else if (fn.defaultParams.Count > 0)
                        fn.defaultParams.Add(new NodeNull(null));
                    // TODO check for vargs.
                    // If there's a comma, we expect there to be more parameters.
                    // Simply skip the comma and prepare for more.
                    if (Check(COMMA))
                        Advance();
                    // No more parameters, break out.
                    else break;
                }

                // Param lists end with ')', so look for it.
                Expect(CLOSE_BRACE,
                    "Expected a close brace (')') to end the function parameter list.");
            }

            // If the function is declared with an assign operator, it shouldn't be void.
            if (TokensRemain && Current.type == ASSIGN)
            {
                if (fn.isGenerator)
                    log.Error(Location, "Generators must be declared void.");
                Advance();
                fn.isVoid = false;
            }
            else fn.isVoid = true;

            // Finally, we get the body of the function.
            // Whether or not a function is void, its body is always an expression.

            if (!TokensRemain)
            {
                log.Error(fn.location, "Expected expression for function body, but the end of the file was reached.");
                return fn;
            }

            SetCurrentFunction(fn);
            fn.body = Expression();
            ReleaseCurrentFunction();

            return fn;
        }
Esempio n. 5
0
 internal FunctionHolder(FunctionHolder previous, NodeFnExpr current)
 {
     this.previous = previous;
     this.current = current;
 }