Add a basic TypeLoc; start threading it through the parser.

Doug, please double-check that this is going in the right direction...



Swift SVN r2146
This commit is contained in:
Eli Friedman
2012-06-05 00:11:59 +00:00
parent 0ca4d69ab5
commit ecc56538b3
8 changed files with 162 additions and 58 deletions

View File

@@ -0,0 +1,49 @@
//===--- TypeLoc.h - Swift Language Type Locations --------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines the TypeLoc class.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_TYPELOC_H
#define SWIFT_TYPELOC_H
#include "swift/Basic/SourceLoc.h"
namespace swift {
class ASTContext;
/// TypeLoc - Provides source location information for a parsed type.
/// A TypeLoc* is stored in AST nodes which use an explicitly written type.
class TypeLoc {
private:
TypeLoc(SourceRange Range);
// FIXME: Currently, there's only one kind of TypeLoc; we need multiple kinds
// for more accurate source location information.
SourceRange Range;
void *operator new(size_t Bytes) throw() = delete;
void operator delete(void *Data) throw() = delete;
void *operator new(size_t Bytes, void *Mem) throw() = delete;
void *operator new(size_t Bytes, ASTContext &C,
unsigned Alignment = 8);
public:
SourceRange getSourceRange() {
return Range;
}
static TypeLoc *get(ASTContext &Context, SourceRange Range);
};
} // end namespace llvm
#endif

View File

@@ -17,6 +17,7 @@
#include "swift/AST/Types.h"
#include "swift/AST/Decl.h"
#include "swift/AST/AST.h"
#include "swift/AST/TypeLoc.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/SmallMap.h"
#include "llvm/ADT/SmallPtrSet.h"
@@ -831,3 +832,17 @@ void SubstArchetypeType::print(raw_ostream &OS) const {
getSubstType()->print(OS);
}
//===----------------------------------------------------------------------===//
// TypeLoc implementation
//===----------------------------------------------------------------------===//
TypeLoc::TypeLoc(SourceRange Range) : Range(Range) {}
void *TypeLoc::operator new(size_t Bytes, ASTContext &C,
unsigned Alignment) {
return C.Allocate(Bytes, Alignment);
}
TypeLoc *TypeLoc::get(ASTContext &Context, SourceRange Range) {
return new (Context) TypeLoc(Range);
}

View File

@@ -476,7 +476,8 @@ bool Parser::parseInheritance(SmallVectorImpl<Type> &Inherited) {
do {
// Parse the inherited type (which must be a protocol).
Type Ty;
if (parseTypeIdentifier(Ty))
TypeLoc *Loc;
if (parseTypeIdentifier(Ty, Loc))
return true;
// Record the type.
@@ -503,9 +504,10 @@ Decl *Parser::parseDeclExtension() {
SourceLoc ExtensionLoc = consumeToken(tok::kw_extension);
Type Ty;
SourceLoc TyLoc = Tok.getLoc();
SourceLoc TyStartLoc = Tok.getLoc();
TypeLoc *TyLoc;
SourceLoc LBLoc, RBLoc;
if (parseTypeIdentifier(Ty))
if (parseTypeIdentifier(Ty, TyLoc))
return nullptr;
// Parse optional inheritance clause.
@@ -517,7 +519,7 @@ Decl *Parser::parseDeclExtension() {
return nullptr;
ExtensionDecl *ED
= new (Context) ExtensionDecl(ExtensionLoc, Ty, TyLoc,
= new (Context) ExtensionDecl(ExtensionLoc, Ty, TyStartLoc,
Context.AllocateCopy(Inherited),
CurDeclContext);
ContextChange CC(*this, ED);
@@ -547,6 +549,7 @@ TypeAliasDecl *Parser::parseDeclTypeAlias(bool WantDefinition) {
Identifier Id;
Type Ty;
TypeLoc *TyLoc;
SourceLoc IdLoc = Tok.getLoc();
if (parseIdentifier(Id, diag::expected_identifier_in_decl, "typealias"))
return nullptr;
@@ -558,7 +561,7 @@ TypeAliasDecl *Parser::parseDeclTypeAlias(bool WantDefinition) {
if (WantDefinition || Tok.is(tok::equal)) {
if (parseToken(tok::equal, diag::expected_equal_in_typealias) ||
parseType(Ty, diag::expected_type_in_typealias))
parseType(Ty, TyLoc, diag::expected_type_in_typealias))
return nullptr;
if (!WantDefinition) {
@@ -760,7 +763,8 @@ bool Parser::parseGetSet(bool HasContainerType, Pattern *Indices,
// Getter has type: () -> T.
Type FuncTy = ElementTy;
if (buildFunctionSignature(Params, FuncTy)) {
TypeLoc *FuncLoc = nullptr;
if (buildFunctionSignature(Params, FuncTy, FuncLoc)) {
skipUntilDeclRBrace();
Invalid = true;
break;
@@ -882,7 +886,8 @@ bool Parser::parseGetSet(bool HasContainerType, Pattern *Indices,
// Getter has type: (value : T) -> ()
Type FuncTy = TupleType::getEmpty(Context);
if (buildFunctionSignature(Params, FuncTy)) {
TypeLoc *FuncLoc = nullptr;
if (buildFunctionSignature(Params, FuncTy, FuncLoc)) {
skipUntilDeclRBrace();
Invalid = true;
break;
@@ -1137,7 +1142,8 @@ FuncDecl *Parser::parseDeclFunc(bool hasContainerType) {
Params.push_back(buildImplicitThisParameter());
Type FuncTy;
if (parseFunctionSignature(Params, FuncTy))
TypeLoc *FuncTyLoc;
if (parseFunctionSignature(Params, FuncTy, FuncTyLoc))
return 0;
// Enter the arguments for the function into a new function-body scope. We
@@ -1226,6 +1232,7 @@ bool Parser::parseDeclOneOf(SmallVectorImpl<Decl*> &Decls) {
SourceLoc NameLoc;
StringRef Name;
Type EltType;
TypeLoc *EltTypeLoc;
};
SmallVector<OneOfElementInfo, 8> ElementInfos;
@@ -1244,7 +1251,7 @@ bool Parser::parseDeclOneOf(SmallVectorImpl<Decl*> &Decls) {
// See if we have a type specifier for this oneof element. If so, parse it.
if (consumeIf(tok::colon) &&
parseTypeAnnotation(ElementInfo.EltType,
parseTypeAnnotation(ElementInfo.EltType, ElementInfo.EltTypeLoc,
diag::expected_type_oneof_element)) {
skipUntil(tok::r_brace);
return true;
@@ -1563,7 +1570,9 @@ bool Parser::parseDeclSubscript(bool HasContainerType,
// type
Type ElementTy;
if (parseTypeAnnotation(ElementTy, diag::expected_type_subscript))
TypeLoc *ElementTyLoc;
if (parseTypeAnnotation(ElementTy, ElementTyLoc,
diag::expected_type_subscript))
return true;
if (checkFullyTyped(ElementTy))
Invalid = true;

View File

@@ -131,7 +131,8 @@ NullablePtr<Expr> Parser::parseExprNew() {
// FIXME: this should probably be type-simple.
Type elementTy;
if (parseTypeIdentifier(elementTy))
TypeLoc *elementLoc;
if (parseTypeIdentifier(elementTy, elementLoc))
return nullptr;
// TODO: we should probably allow a tuple-expr here as an initializer.
@@ -584,6 +585,7 @@ NullablePtr<Expr> Parser::parseExprFunc() {
SmallVector<Pattern*, 4> Params;
Type Ty;
TypeLoc *Loc;
if (Tok.is(tok::l_brace)) {
// If the func-signature isn't present, then this is a ()->() function.
Params.push_back(TuplePattern::create(Context, SourceLoc(),
@@ -594,7 +596,7 @@ NullablePtr<Expr> Parser::parseExprFunc() {
} else if (Tok.isNotAnyLParen()) {
diagnose(Tok, diag::func_decl_without_paren);
return 0;
} else if (parseFunctionSignature(Params, Ty)) {
} else if (parseFunctionSignature(Params, Ty, Loc)) {
return 0;
}

View File

@@ -156,7 +156,7 @@ bool Parser::checkFullyTyped(Pattern *pattern, Type &funcTy) {
/// func-signature-result:
/// '->' type
bool Parser::parseFunctionSignature(SmallVectorImpl<Pattern*> &params,
Type &type) {
Type &type, TypeLoc *&loc) {
// Parse curried function argument clauses as long as we can.
do {
NullablePtr<Pattern> pattern = parsePatternTuple();
@@ -168,7 +168,7 @@ bool Parser::parseFunctionSignature(SmallVectorImpl<Pattern*> &params,
// If there's a trailing arrow, parse the rest as the result type.
if (consumeIf(tok::arrow)) {
if (parseType(type))
if (parseType(type, loc))
return true;
checkFullyTyped(type);
@@ -176,16 +176,17 @@ bool Parser::parseFunctionSignature(SmallVectorImpl<Pattern*> &params,
// Otherwise, we implicitly return ().
} else {
type = TupleType::getEmpty(Context);
loc = nullptr;
}
// Now build up the function type. We require all function
// signatures to be fully-typed: that is, all top-down paths to a
// leaf pattern must pass through a TypedPattern.
return buildFunctionSignature(params, type);
return buildFunctionSignature(params, type, loc);
}
bool Parser::buildFunctionSignature(SmallVectorImpl<Pattern*> &params,
Type &type) {
Type &type, TypeLoc *&loc) {
// Now build up the function type. We require all function
// signatures to be fully-typed: that is, all top-down paths to a
// leaf pattern must pass through a TypedPattern.
@@ -215,7 +216,8 @@ NullablePtr<Pattern> Parser::parsePattern() {
// Now parse an optional type annotation.
if (consumeIf(tok::colon)) {
Type type;
if (parseTypeAnnotation(type))
TypeLoc *loc;
if (parseTypeAnnotation(type, loc))
return nullptr;
pattern = new (Context) TypedPattern(pattern.get(), type);

View File

@@ -16,25 +16,27 @@
#include "Parser.h"
#include "swift/AST/Attr.h"
#include "swift/AST/TypeLoc.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
using namespace swift;
bool Parser::parseTypeAnnotation(Type &result) {
return parseTypeAnnotation(result, diag::expected_type);
bool Parser::parseTypeAnnotation(Type &result, TypeLoc *&resultLoc) {
return parseTypeAnnotation(result, resultLoc, diag::expected_type);
}
/// parseTypeAnnotation
/// type-annotation:
/// attribute-list type
bool Parser::parseTypeAnnotation(Type &result, Diag<> message) {
bool Parser::parseTypeAnnotation(Type &result, TypeLoc *&resultLoc,
Diag<> message) {
// Parse attributes.
DeclAttributes attrs;
parseAttributeList(attrs);
// Parse the type.
if (parseType(result, message))
if (parseType(result, resultLoc, message))
return true;
// Apply those attributes that do apply.
@@ -45,6 +47,9 @@ bool Parser::parseTypeAnnotation(Type &result, Diag<> message) {
if (!attrs.isByrefHeap()) quals |= LValueType::Qual::NonHeap;
result = LValueType::get(result, quals, Context);
attrs.Byref = false; // so that the empty() check below works
resultLoc = TypeLoc::get(Context,
SourceRange(attrs.LSquareLoc,
resultLoc->getSourceRange().End));
}
// Handle the auto_closure attribute.
@@ -73,8 +78,8 @@ bool Parser::parseTypeAnnotation(Type &result, Diag<> message) {
return false;
}
bool Parser::parseType(Type &Result) {
return parseType(Result, diag::expected_type);
bool Parser::parseType(Type &Result, TypeLoc *&ResultLoc) {
return parseType(Result, ResultLoc, diag::expected_type);
}
/// parseType
@@ -91,24 +96,24 @@ bool Parser::parseType(Type &Result) {
/// type-tuple
/// type-composition
///
bool Parser::parseType(Type &Result, Diag<> MessageID) {
bool Parser::parseType(Type &Result, TypeLoc *&ResultLoc, Diag<> MessageID) {
// Parse type-simple first.
SourceLoc TypeLoc = Tok.getLoc();
SourceLoc StartLoc = Tok.getLoc();
bool isTupleType = false;
switch (Tok.getKind()) {
case tok::identifier:
if (parseTypeIdentifier(Result))
if (parseTypeIdentifier(Result, ResultLoc))
return true;
break;
case tok::kw_protocol:
if (parseTypeComposition(Result))
if (parseTypeComposition(Result, ResultLoc))
return true;
break;
case tok::l_paren:
case tok::l_paren_space: {
isTupleType = true;
SourceLoc LPLoc = consumeToken(), RPLoc;
if (parseTypeTupleBody(LPLoc, Result) ||
if (parseTypeTupleBody(LPLoc, Result, ResultLoc) ||
parseMatchingToken(tok::r_paren, RPLoc,
diag::expected_rparen_tuple_type_list,
LPLoc, diag::opening_paren))
@@ -124,19 +129,24 @@ bool Parser::parseType(Type &Result, Diag<> MessageID) {
if (consumeIf(tok::arrow)) {
// If the argument was not syntactically a tuple type, report an error.
if (!isTupleType) {
diagnose(TypeLoc, diag::expected_function_argument_must_be_paren);
diagnose(StartLoc, diag::expected_function_argument_must_be_paren);
}
Type SecondHalf;
if (parseType(SecondHalf, diag::expected_type_function_result))
TypeLoc *SecondHalfLoc;
if (parseType(SecondHalf, SecondHalfLoc,
diag::expected_type_function_result))
return true;
Result = FunctionType::get(Result, SecondHalf, Context);
SourceRange FnTypeRange{ ResultLoc->getSourceRange().Start,
SecondHalfLoc->getSourceRange().End };
ResultLoc = TypeLoc::get(Context, FnTypeRange);
return false;
}
// If there is a square bracket without a space, we have an array.
if (Tok.is(tok::l_square))
return parseTypeArray(Result);
return parseTypeArray(Result, ResultLoc);
return false;
}
@@ -146,7 +156,8 @@ bool Parser::parseType(Type &Result, Diag<> MessageID) {
/// type-identifier:
/// identifier ('.' identifier)*
///
bool Parser::parseTypeIdentifier(Type &Result) {
bool Parser::parseTypeIdentifier(Type &Result, TypeLoc *&ResultLoc) {
SourceLoc StartLoc = Tok.getLoc();
if (Tok.isNot(tok::identifier)) {
diagnose(Tok.getLoc(), diag::expected_identifier_for_type);
return true;
@@ -155,7 +166,7 @@ bool Parser::parseTypeIdentifier(Type &Result) {
SmallVector<IdentifierType::Component, 4> Components;
Components.push_back(IdentifierType::Component(Tok.getLoc(),
Context.getIdentifier(Tok.getText())));
consumeToken(tok::identifier);
SourceLoc EndLoc = consumeToken(tok::identifier);
while (consumeIf(tok::period)) {
SourceLoc Loc = Tok.getLoc();
@@ -163,6 +174,7 @@ bool Parser::parseTypeIdentifier(Type &Result) {
if (parseIdentifier(Name, diag::expected_identifier_in_dotted_type))
return true;
Components.push_back(IdentifierType::Component(Loc, Name));
EndLoc = Loc;
}
// Lookup element #0 through our current scope chains in case it is some thing
@@ -172,6 +184,7 @@ bool Parser::parseTypeIdentifier(Type &Result) {
auto Ty = IdentifierType::getNew(Context, Components);
UnresolvedIdentifierTypes.emplace_back(Ty, CurDeclContext);
Result = Ty;
ResultLoc = TypeLoc::get(Context, SourceRange(StartLoc, EndLoc));
return false;
}
@@ -183,7 +196,7 @@ bool Parser::parseTypeIdentifier(Type &Result) {
/// type-composition-list:
/// type-identifier (',' type-identifier)*
///
bool Parser::parseTypeComposition(Type &Result) {
bool Parser::parseTypeComposition(Type &Result, TypeLoc *&ResultLoc) {
SourceLoc ProtocolLoc = consumeToken(tok::kw_protocol);
// Check for the starting '<'.
@@ -207,7 +220,8 @@ bool Parser::parseTypeComposition(Type &Result) {
do {
// Parse the type-identifier.
Type Protocol;
if (parseTypeIdentifier(Protocol)) {
TypeLoc *ProtocolLoc;
if (parseTypeIdentifier(Protocol, ProtocolLoc)) {
Invalid = true;
break;
}
@@ -223,6 +237,7 @@ bool Parser::parseTypeComposition(Type &Result) {
} while (true);
// Check for the terminating '>'.
SourceLoc EndLoc = Tok.getLoc();
if (!startsWithGreater(Tok)) {
if (!Invalid) {
diagnose(Tok.getLoc(), diag::expected_rangle_protocol);
@@ -232,14 +247,15 @@ bool Parser::parseTypeComposition(Type &Result) {
// Skip until we hit the '>'.
skipUntil(tok::oper);
if (startsWithGreater(Tok))
consumeStartingGreater();
EndLoc = consumeStartingGreater();
} else {
consumeStartingGreater();
EndLoc = consumeStartingGreater();
}
Result = ProtocolCompositionType::get(Context, ProtocolLoc,
Context.AllocateCopy(Protocols));
ResultLoc = TypeLoc::get(Context, SourceRange(ProtocolLoc, EndLoc));
return false;
}
@@ -251,7 +267,7 @@ bool Parser::parseTypeComposition(Type &Result) {
/// type-tuple-element:
/// identifier value-specifier
/// type-annotation
bool Parser::parseTypeTupleBody(SourceLoc LPLoc, Type &Result) {
bool Parser::parseTypeTupleBody(SourceLoc LPLoc, Type &Result, TypeLoc *&ResultLoc) {
SmallVector<TupleTypeElt, 8> Elements;
bool HadExpr = false;
@@ -269,7 +285,8 @@ bool Parser::parseTypeTupleBody(SourceLoc LPLoc, Type &Result) {
NullablePtr<Expr> init;
Type type;
if ((HadError = parseValueSpecifier(type, init)))
TypeLoc *loc;
if ((HadError = parseValueSpecifier(type, loc, init)))
break;
HadExpr |= init.isNonNull();
@@ -279,7 +296,8 @@ bool Parser::parseTypeTupleBody(SourceLoc LPLoc, Type &Result) {
// Otherwise, this has to be a type.
Type type;
if ((HadError = parseTypeAnnotation(type)))
TypeLoc *typeLoc;
if ((HadError = parseTypeAnnotation(type, typeLoc)))
break;
Elements.push_back(TupleTypeElt(type, Identifier(), nullptr));
@@ -304,6 +322,7 @@ bool Parser::parseTypeTupleBody(SourceLoc LPLoc, Type &Result) {
if (Elements.size() == 1 && !Elements.back().hasName() && !HadEllipsis) {
assert(!HadExpr && "Only TupleTypes have default values");
Result = ParenType::get(Context, Elements.back().getType());
ResultLoc = TypeLoc::get(Context, SourceRange(LPLoc, Tok.getLoc()));
return false;
}
@@ -327,6 +346,7 @@ bool Parser::parseTypeTupleBody(SourceLoc LPLoc, Type &Result) {
if (HadExpr)
TypesWithDefaultValues.emplace_back(TT, CurDeclContext);
Result = TT;
ResultLoc = TypeLoc::get(Context, SourceRange(LPLoc, Tok.getLoc()));
return false;
}
@@ -340,14 +360,16 @@ bool Parser::parseTypeTupleBody(SourceLoc LPLoc, Type &Result) {
/// type-array '[' ']'
/// type-array '[' expr ']'
///
bool Parser::parseTypeArray(Type &result) {
bool Parser::parseTypeArray(Type &result, TypeLoc *&resultLoc) {
SourceLoc lsquareLoc = Tok.getLoc();
consumeToken(tok::l_square);
// Handle the [] production, meaning an array slice.
if (consumeIf(tok::r_square)) {
if (Tok.is(tok::r_square)) {
SourceLoc rsquareLoc = consumeToken(tok::r_square);
// If we're starting another square-bracket clause, recurse.
if (Tok.is(tok::l_square) && parseTypeArray(result)) {
if (Tok.is(tok::l_square) && parseTypeArray(result, resultLoc)) {
return true;
// Propagate an error type out.
@@ -357,6 +379,8 @@ bool Parser::parseTypeArray(Type &result) {
// Just build a normal array slice type.
result = ArraySliceType::get(result, lsquareLoc, Context);
SourceRange arrayRange{ resultLoc->getSourceRange().Start, rsquareLoc };
resultLoc = TypeLoc::get(Context, arrayRange);
return false;
}
@@ -370,7 +394,7 @@ bool Parser::parseTypeArray(Type &result) {
return true;
// If we're starting another square-bracket clause, recurse.
if (Tok.is(tok::l_square) && parseTypeArray(result)) {
if (Tok.is(tok::l_square) && parseTypeArray(result, resultLoc)) {
return true;
// If we had a semantic error on the size or if the base type is invalid,

View File

@@ -260,7 +260,8 @@ bool Parser::parseMatchingToken(tok K, SourceLoc &TokLoc, Diag<> ErrorDiag,
/// ':' type-annotation
/// ':' type-annotation '=' expr
/// '=' expr
bool Parser::parseValueSpecifier(Type &Ty, NullablePtr<Expr> &Init) {
bool Parser::parseValueSpecifier(Type &Ty, TypeLoc *&Loc,
NullablePtr<Expr> &Init) {
// Diagnose when we don't have a type or an expression.
if (Tok.isNot(tok::colon) && Tok.isNot(tok::equal)) {
diagnose(Tok, diag::expected_type_or_init);
@@ -271,7 +272,7 @@ bool Parser::parseValueSpecifier(Type &Ty, NullablePtr<Expr> &Init) {
// Parse the type if present.
if (consumeIf(tok::colon) &&
parseTypeAnnotation(Ty, diag::expected_type))
parseTypeAnnotation(Ty, Loc, diag::expected_type))
return true;
// Parse the initializer, if present.

View File

@@ -34,6 +34,7 @@ namespace swift {
class DiagnosticEngine;
class Lexer;
class ScopeInfo;
class TypeLoc;
class TupleType;
struct OneOfElementInfo;
@@ -201,7 +202,7 @@ public:
SourceLoc OtherLoc, Diag<> OtherNote,
tok SkipToTok = tok::unknown);
bool parseValueSpecifier(Type &Ty, NullablePtr<Expr> &Init);
bool parseValueSpecifier(Type &Ty, TypeLoc *&Loc, NullablePtr<Expr> &Init);
void parseBraceItemList(SmallVectorImpl<ExprStmtOrDecl> &Decls,
bool IsTopLevel);
@@ -262,21 +263,22 @@ public:
//===--------------------------------------------------------------------===//
// Type Parsing
bool parseType(Type &Result);
bool parseType(Type &Result, Diag<> ID);
bool parseTypeAnnotation(Type &Result);
bool parseTypeAnnotation(Type &Result, Diag<> ID);
bool parseTypeIdentifier(Type &Result);
bool parseTypeComposition(Type &Result);
bool parseTypeTupleBody(SourceLoc LPLoc, Type &Result);
bool parseTypeArray(Type &result);
bool parseType(Type &Result, TypeLoc *&ResultLoc);
bool parseType(Type &Result, TypeLoc *&ResultLoc, Diag<> ID);
bool parseTypeAnnotation(Type &Result, TypeLoc *&ResultLoc);
bool parseTypeAnnotation(Type &Result, TypeLoc *&ResultLoc, Diag<> ID);
bool parseTypeIdentifier(Type &Result, TypeLoc *&ResultLoc);
bool parseTypeComposition(Type &Result, TypeLoc *&ResultLoc);
bool parseTypeTupleBody(SourceLoc LPLoc, Type &Result, TypeLoc *&ResultLoc);
bool parseTypeArray(Type &result, TypeLoc *&ResultLoc);
//===--------------------------------------------------------------------===//
// Pattern Parsing
bool parseFunctionSignature(SmallVectorImpl<Pattern*> &params, Type &type);
bool buildFunctionSignature(SmallVectorImpl<Pattern*> &params, Type &type);
bool parseFunctionSignature(SmallVectorImpl<Pattern*> &params, Type &type,
TypeLoc *&loc);
bool buildFunctionSignature(SmallVectorImpl<Pattern*> &params, Type &type,
TypeLoc *&loc);
NullablePtr<Pattern> parsePattern();
NullablePtr<Pattern> parsePatternTuple();
NullablePtr<Pattern> parsePatternAtom();