Goose  Artifact [6ca4ddaa93]

Artifact 6ca4ddaa93b91ff55e1d4230d8d4b77ef929b7f74207d4687d42f3ef3c0f0199:

  • File bs/builtins/operators/dollar.cpp — part of check-in [23e0cd5dc7] at 2019-02-18 21:54:23 on branch trunk — Parser:
    • Make the resolver skip newlines by default, and provide an additional "raw" api to retrieve unresolved tokens without skipping newlines.
    • Parsing rules now only return a bool to indicate whether they were successful, and can push any number of values themselves as needed.
    • Stop trying to shoehorn implicit separators in the pratt parser. Instead, use the pratt parser only for expressions, and use a different parsing loop for sequences of expressions (ie for brace blocks and top level).
    (user: achavasse size: 2211)

#include "builtins/builtins.h"
#include "parse/parse.h"
#include "precedence.h"

using namespace empathy;
using namespace empathy::ir;
using namespace empathy::parse;

namespace empathy::builtins
{
    void SetupDollarOp( Env& e )
    {
        // Dollar is a low level operator: it doesn't expect a value rhs operand, but just an identifier ir element.
        // So we can't use the convenient operator wrapper rule.
        Rule r( []( Parser& p, const Term& t, uint32_t prec )
        {
            auto nameTerm = p.resolver()->consumeUnresolved();
            if( !nameTerm )
            {
                cout << t.location() << ": expected an identifier after '$'.\n";
                return false;
            }

            const auto* name = get_if< StringId >( &nameTerm->content() );
            if( !name )
            {
                cout << nameTerm->location() << ": expected an identifier after '$'.\n";
                return false;
            }

            const auto& c = p.resolver()->context();

            // Template name bindings are stored with a "$$" prefix so they don't
            // collide with regular names.
            auto captureIdentity = AppendToVectorTerm( c.identity(),
                TERM( "$$"_sid ), TERM( *name ) );

            // Look up the TVar name. If it exists, then we're inside of a template function
            // body, refering to a bound TVar, so we just return the stored value.
            // Otherwise, we're in a template declaration and have to construct a new TVar.
            Term result;

            switch( c.env()->retrieveValue( captureIdentity, c, result ) )
            {
                case sema::Env::Status::Success:
                    p.push( ValueFromIRExpr( result ) );
                    return true;

                case sema::Env::Status::AmbiguousMatch:
                    cout << t.location() << ": unexpected ambiguous match when resolving '$" << *name << "'.\n";
                    return false;
            }

            // No bound value was found: construct a TVar.
            p.push( ToValue( TVar( *name ) ) );
            return true;
        } );

        RegisterRule( e, "$"_sid, move( r ) );
    }
}