// <-- Name
        //   | FN Name TupleType
        //   | BOOL_LITERAL
        //   | INT_LITERAL
        //   | STRING_LITERAL
        //   | LPAREN (Expression)? RPAREN
        private IUnboundExpr PrimaryExpr()
        {
            IUnboundExpr expression;

            if (CurrentIs(TokenType.Name))
            {
                var name = Consume();
                expression = new NameExpr(name.Position, name.StringValue, TypeArgs());
            }
            else if (CurrentIs(TokenType.Fn))
            {
                expression = FuncExpr();
            }
            else if (CurrentIs(TokenType.Bool))
            {
                expression = new BoolExpr(Consume(TokenType.Bool));
            }
            else if (CurrentIs(TokenType.Int))
            {
                expression = new IntExpr(Consume(TokenType.Int));
            }
            else if (CurrentIs(TokenType.String))
            {
                expression = new StringExpr(Consume(TokenType.String));
            }
            else if (CurrentIs(TokenType.LeftParen))
            {
                Token leftParen = Consume(TokenType.LeftParen);

                if (CurrentIs(TokenType.RightParen))
                {
                    // () -> unit
                    expression = new UnitExpr(leftParen.Position);
                }
                else if (CurrentIs(TokenType.Operator))
                {
                    // ( OPERATOR ) -> an operator in prefix form
                    Token op = Consume(TokenType.Operator);
                    expression = new NameExpr(op.Position, op.StringValue);
                }
                else
                {
                    // anything else is a regular parenthesized expression
                    expression = Expression();
                }

                Consume(TokenType.RightParen);
            }
            else
            {
                expression = null;
            }

            return(expression);
        }
 bool IBoundExprVisitor <bool> .Visit(UnitExpr expr)
 {
     return(true);
 }                                                                  // do nothing
 public virtual IUnboundExpr Transform(UnitExpr expr)
 {
     return(expr);
 }
 IBoundExpr IUnboundExprVisitor<IBoundExpr>.Visit(UnitExpr expr)
 {
     return expr;
 }
        /// <summary>
        /// Resolves and binds a reference to a name.
        /// </summary>
        /// <param name="function">The function being compiled.</param>
        /// <param name="scope">The scope in which the name is being bound.</param>
        /// <param name="name">The name being resolved. May or may not be fully-qualified.</param>
        /// <param name="typeArgs">The type arguments being applied to the name. For
        /// example, resolving "foo'(int, bool)" would pass in {int, bool} here.</param>
        /// <param name="arg">The argument being applied to the name.</param>
        /// <returns></returns>
        public IBoundExpr ResolveName(Function function,
                                      Scope scope, Position position, string name,
                                      IList <IUnboundDecl> typeArgs, IBoundExpr arg)
        {
            IBoundDecl argType = null;

            if (arg != null)
            {
                argType = arg.Type;
            }

            IBoundExpr resolved = null;

            // see if it's an argument
            if (function.ParamNames.Contains(name))
            {
                // load the argument
                resolved = new LoadExpr(new LocalsExpr(), function.ParameterType, 0);

                if (function.ParamNames.Count > 1)
                {
                    // function takes multiple parameters, so load it from the tuple
                    var paramTuple = (BoundTupleType)function.ParameterType;

                    var argIndex = (byte)function.ParamNames.IndexOf(name);
                    resolved = new LoadExpr(resolved, paramTuple.Fields[argIndex], argIndex);
                }
            }

            // see if it's a local
            if (scope.Contains(name))
            {
                var local = scope[name];

                // just load the value
                resolved = new LoadExpr(new LocalsExpr(), scope[name]);
            }

            // if we resolved to a local name, handle it
            if (resolved != null)
            {
                if (typeArgs.Count > 0)
                {
                    throw new CompileException(position, "Cannot apply type arguments to a local variable or function argument.");
                }

                // if the local or argument is holding a function reference and we're passed args, call it
                if (argType != null)
                {
                    var funcType = resolved.Type as FuncType;

                    if (funcType != null)
                    {
                        // check that args match
                        if (!DeclComparer.TypesMatch(funcType.Parameter.Bound, argType))
                        {
                            throw new CompileException(position, "Argument types passed to local function reference do not match function's parameter types.");
                        }

                        // call it
                        resolved = new BoundCallExpr(resolved, arg);
                    }
                    else
                    {
                        // not calling a function, so try to desugar to a __Call
                        var callArg = new BoundTupleExpr(new IBoundExpr[] { resolved, arg });

                        resolved = ResolveFunction(function, position,
                                                   "__Call", new IUnboundDecl[0], callArg);

                        if (resolved == null)
                        {
                            throw new CompileException(position, "Cannot call a local variable or argument that is not a function reference, and could not find a matching __Call.");
                        }
                    }
                }

                return(resolved);
            }

            // implicitly apply () as the argument if no other argument was provided.
            // note that we do this *after* checking for locals because locals aren't
            // implicitly applied. since most locals aren't functions anyway, it won't
            // matter in most cases, and in cases where a local holds a function, the
            // user will mostly likely want to treat that function like a value: return
            // it, pass it around, etc.
            if (arg == null)
            {
                arg     = new UnitExpr(Position.None);
                argType = arg.Type;
            }

            return(ResolveFunction(function, position, name, typeArgs, arg));
        }
Beispiel #6
0
 IUnboundExpr IUnboundExprVisitor <IUnboundExpr> .Visit(UnitExpr expr)
 {
     return(Call("UnitExpr", Unit()));
 }