mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Revise the language design for function argument clause syntax.
A function argument clause is now one or more patterns (which must be parenthesized and explicitly type all positions) not separated by arrows; the first arrow then separates off the return type. Revisions to language reference forthcoming. Swift SVN r1099
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
#include "Decl.h"
|
||||
#include "Expr.h"
|
||||
#include "Module.h"
|
||||
#include "Pattern.h"
|
||||
#include "Stmt.h"
|
||||
#include "Types.h"
|
||||
|
||||
|
||||
@@ -195,6 +195,17 @@ ERROR(expected_lbrace_protocol_type,type_parsing,none,
|
||||
ERROR(expected_protocol_member,type_parsing,none,
|
||||
"expected a function or variable declaration in protocol", ())
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Pattern parsing diagnostics
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
ERROR(expected_pattern,pattern_parsing,none,
|
||||
"expected pattern", ())
|
||||
ERROR(untyped_pattern_in_function_signature,pattern_parsing,none,
|
||||
"function parameter must have an explicit type", ())
|
||||
ERROR(expected_rparen_tuple_pattern_list,pattern_parsing,non,
|
||||
"expected ')' at end of tuple pattern", ())
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Statement parsing diagnostics
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -496,6 +507,21 @@ ERROR(expression_unresolved_function,sema_tcs,none,
|
||||
ERROR(assignment_lhs_not_lvalue,sema_tcs,none,
|
||||
"cannot assign to the result of this expression", ())
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Type Check Patterns
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
ERROR(cannot_infer_type_for_pattern,sema_tcp,none,
|
||||
"cannot infer a type for this pattern", ())
|
||||
ERROR(pattern_type_mismatch_context,sema_tcp,none,
|
||||
"type annotation does not match contextual type %0", (Type))
|
||||
ERROR(tuple_pattern_in_non_tuple_context,sema_tcp,none,
|
||||
"tuple pattern cannot match values of the non-tuple type %0", (Type))
|
||||
ERROR(tuple_pattern_length_mismatch,sema_tcp,none,
|
||||
"tuple pattern has the wrong length for tuple type %0", (Type))
|
||||
ERROR(coerced_tuple_pattern_has_init,sema_tcp,none,
|
||||
"tuple element in pattern cannot have a default initializer", ())
|
||||
|
||||
//==============================================================================
|
||||
// IR Generation Diagnostics
|
||||
//==============================================================================
|
||||
|
||||
@@ -32,6 +32,7 @@ namespace swift {
|
||||
class ArgDecl;
|
||||
class ValueDecl;
|
||||
class Decl;
|
||||
class Pattern;
|
||||
class Stmt;
|
||||
class BraceStmt;
|
||||
class TypeAliasDecl;
|
||||
@@ -646,18 +647,34 @@ public:
|
||||
/// e.g. func(a : int) -> int { return a+1 }
|
||||
class FuncExpr : public Expr, public DeclContext {
|
||||
SourceLoc FuncLoc;
|
||||
unsigned NumPatterns;
|
||||
|
||||
BraceStmt *Body;
|
||||
|
||||
Pattern **getParamsBuffer() {
|
||||
return reinterpret_cast<Pattern**>(this+1);
|
||||
}
|
||||
Pattern * const *getParamsBuffer() const {
|
||||
return reinterpret_cast<Pattern*const*>(this+1);
|
||||
}
|
||||
|
||||
public:
|
||||
FuncExpr(SourceLoc FuncLoc, Type FnType, BraceStmt *Body, DeclContext *Parent)
|
||||
FuncExpr(SourceLoc FuncLoc, unsigned NumPatterns, Type FnType,
|
||||
BraceStmt *Body, DeclContext *Parent)
|
||||
: Expr(ExprKind::Func, TypeJudgement(FnType, ValueKind::RValue)),
|
||||
DeclContext(DeclContextKind::FuncExpr, Parent),
|
||||
FuncLoc(FuncLoc), Body(Body) {}
|
||||
FuncLoc(FuncLoc), NumPatterns(NumPatterns), Body(Body) {}
|
||||
public:
|
||||
static FuncExpr *create(ASTContext &Context, SourceLoc FuncLoc,
|
||||
ArrayRef<Pattern*> Params, Type FnType,
|
||||
BraceStmt *Body, DeclContext *Parent);
|
||||
|
||||
SourceRange getSourceRange() const;
|
||||
SourceLoc getLoc() const { return FuncLoc; }
|
||||
|
||||
ArrayRef<Pattern*> getParamPatterns() const {
|
||||
return ArrayRef<Pattern*>(getParamsBuffer(), NumPatterns);
|
||||
}
|
||||
|
||||
/// Returns the location of the 'func' keyword.
|
||||
SourceLoc getFuncLoc() const { return FuncLoc; }
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ class Pattern {
|
||||
class TuplePatternBitfields {
|
||||
friend class TuplePattern;
|
||||
unsigned : NumPatternBits;
|
||||
unsigned NumElements : NumBitsAllocated - NumPatternBits;
|
||||
unsigned NumFields : NumBitsAllocated - NumPatternBits;
|
||||
};
|
||||
|
||||
protected:
|
||||
@@ -75,6 +75,10 @@ public:
|
||||
/// type-checked.
|
||||
void setType(Type ty) { assert(!hasType()); Ty = ty; }
|
||||
|
||||
/// Returns the name directly bound by this pattern, or the null
|
||||
/// identifier if the pattern does not bind a name directly.
|
||||
Identifier getBoundName() const;
|
||||
|
||||
SourceRange getSourceRange() const;
|
||||
SourceLoc getStartLoc() const { return getSourceRange().Start; }
|
||||
SourceLoc getEndLoc() const { return getSourceRange().End; }
|
||||
@@ -104,12 +108,12 @@ public:
|
||||
: Pattern(PatternKind::Paren, type),
|
||||
LPLoc(lp), RPLoc(rp), SubPattern(sub) {}
|
||||
|
||||
Pattern *getSubPattern() const { return SubPattern; }
|
||||
|
||||
SourceLoc getLParenLoc() const { return LPLoc; }
|
||||
SourceLoc getRParenLoc() const { return RPLoc; }
|
||||
SourceRange getSourceRange() const { return SourceRange(LPLoc, RPLoc); }
|
||||
SourceLoc getLoc() const { return LPLoc; }
|
||||
|
||||
Pattern *getSubPattern() const { return SubPattern; }
|
||||
SourceLoc getLoc() const { return SubPattern->getLoc(); }
|
||||
|
||||
static bool classof(const Pattern *P) {
|
||||
return P->getKind() == PatternKind::Paren;
|
||||
@@ -117,84 +121,124 @@ public:
|
||||
static bool classof(const ParenPattern *P) { return true; }
|
||||
};
|
||||
|
||||
/// An element of a tuple pattern.
|
||||
class TuplePatternElt {
|
||||
Pattern *ThePattern;
|
||||
Expr *Init;
|
||||
|
||||
public:
|
||||
TuplePatternElt() = default;
|
||||
explicit TuplePatternElt(Pattern *P, Expr *init = nullptr)
|
||||
: ThePattern(P), Init(init) {}
|
||||
|
||||
Pattern *getPattern() const { return ThePattern; }
|
||||
Expr *getInit() const { return Init; }
|
||||
void setInit(Expr *E) { Init = E; }
|
||||
};
|
||||
|
||||
/// A pattern consisting of a tuple of patterns.
|
||||
class TuplePattern : public Pattern {
|
||||
SourceLoc LPLoc, RPLoc;
|
||||
// TuplePatternBits.NumElements
|
||||
// TuplePatternBits.NumFields
|
||||
|
||||
Pattern **getElementsBuffer() {
|
||||
return reinterpret_cast<Pattern**>(this+1);
|
||||
TuplePatternElt *getFieldsBuffer() {
|
||||
return reinterpret_cast<TuplePatternElt *>(this+1);
|
||||
}
|
||||
Pattern * const *getElementsBuffer() const {
|
||||
return reinterpret_cast<Pattern * const *>(this + 1);
|
||||
const TuplePatternElt *getFieldsBuffer() const {
|
||||
return reinterpret_cast<const TuplePatternElt *>(this + 1);
|
||||
}
|
||||
|
||||
TuplePattern(SourceLoc lp, unsigned numElements, SourceLoc rp)
|
||||
TuplePattern(SourceLoc lp, unsigned numFields, SourceLoc rp)
|
||||
: Pattern(PatternKind::Tuple), LPLoc(lp), RPLoc(rp) {
|
||||
TuplePatternBits.NumElements = numElements;
|
||||
TuplePatternBits.NumFields = numFields;
|
||||
}
|
||||
|
||||
public:
|
||||
TuplePattern *create(ASTContext &C, SourceLoc lp,
|
||||
ArrayRef<Pattern*> elements, SourceLoc rp);
|
||||
static TuplePattern *create(ASTContext &C, SourceLoc lp,
|
||||
ArrayRef<TuplePatternElt> elements,
|
||||
SourceLoc rp);
|
||||
|
||||
unsigned getNumFields() const {
|
||||
return TuplePatternBits.NumFields;
|
||||
}
|
||||
|
||||
MutableArrayRef<TuplePatternElt> getFields() {
|
||||
return MutableArrayRef<TuplePatternElt>(getFieldsBuffer(),
|
||||
getNumFields());
|
||||
}
|
||||
ArrayRef<TuplePatternElt> getFields() const {
|
||||
return ArrayRef<TuplePatternElt>(getFieldsBuffer(), getNumFields());
|
||||
}
|
||||
|
||||
SourceLoc getLParenLoc() const { return LPLoc; }
|
||||
SourceLoc getRParenLoc() const { return RPLoc; }
|
||||
SourceRange getSourceRange() const { return SourceRange(LPLoc, RPLoc); }
|
||||
SourceLoc getLoc() const { return LPLoc; }
|
||||
|
||||
unsigned getNumElements() const {
|
||||
return TuplePatternBits.NumElements;
|
||||
}
|
||||
|
||||
ArrayRef<Pattern*> getElements() const {
|
||||
return ArrayRef<Pattern*>(getElementsBuffer(), getNumElements());
|
||||
}
|
||||
|
||||
static bool classof(const Pattern *P) {
|
||||
return P->getKind() == PatternKind::Tuple;
|
||||
}
|
||||
static bool classof(const TuplePattern *P) { return true; }
|
||||
};
|
||||
|
||||
/// A pattern which binds a top-level name. That is, this pattern
|
||||
/// binds a name and is not contained within a pattern that also binds
|
||||
/// a name. It may still be contained within a pattern that does not
|
||||
/// bind a name.
|
||||
class VarPattern : public Pattern {
|
||||
VarDecl *const Var;
|
||||
/// A pattern which binds a name to an arbitrary value of its type.
|
||||
class NamedPattern : public Pattern {
|
||||
ValueDecl *const TheDecl;
|
||||
|
||||
public:
|
||||
VarPattern(VarDecl *var) : Pattern(PatternKind::Var), Var(var) {}
|
||||
NamedPattern(ValueDecl *D)
|
||||
: Pattern(PatternKind::Named), TheDecl(D) {}
|
||||
|
||||
SourceLoc getLoc() const { return Var->getLocStart(); }
|
||||
ValueDecl *getDecl() const { return TheDecl; }
|
||||
Identifier getBoundName() const { return TheDecl->getName(); }
|
||||
|
||||
SourceLoc getLoc() const { return TheDecl->getLocStart(); }
|
||||
SourceRange getSourceRange() const { return getLoc(); }
|
||||
|
||||
VarDecl *getDecl() const { return Var; }
|
||||
|
||||
static bool classof(const Pattern *P) {
|
||||
return P->getKind() == PatternKind::Var;
|
||||
return P->getKind() == PatternKind::Named;
|
||||
}
|
||||
static bool classof(const VarPattern *P) { return true; }
|
||||
static bool classof(const NamedPattern *P) { return true; }
|
||||
};
|
||||
|
||||
/// A pattern which binds a name other than at the top-level.
|
||||
class ElementRefPattern : public Pattern {
|
||||
ElementRefDecl *const ElementRef;
|
||||
/// A pattern which matches an arbitrary value of a type, but does not
|
||||
/// bind a name to it.
|
||||
class AnyPattern : public Pattern {
|
||||
SourceLoc Loc;
|
||||
|
||||
public:
|
||||
ElementRefPattern(ElementRefDecl *elementRef)
|
||||
: Pattern(PatternKind::ElementRef), ElementRef(elementRef) {}
|
||||
AnyPattern(SourceLoc loc) : Pattern(PatternKind::Any), Loc(loc) {}
|
||||
|
||||
SourceLoc getLoc() const { return ElementRef->getLocStart(); }
|
||||
SourceRange getSourceRange() const { return getLoc(); }
|
||||
|
||||
ElementRefDecl *getDecl() const { return ElementRef; }
|
||||
SourceLoc getLoc() const { return Loc; }
|
||||
SourceRange getSourceRange() const { return Loc; }
|
||||
|
||||
static bool classof(const Pattern *P) {
|
||||
return P->getKind() == PatternKind::ElementRef;
|
||||
return P->getKind() == PatternKind::Any;
|
||||
}
|
||||
static bool classof(const ElementRefPattern *P) { return true; }
|
||||
static bool classof(const AnyPattern *P) { return true; }
|
||||
};
|
||||
|
||||
/// A pattern which matches a sub-pattern and annotates it with a
|
||||
/// type.
|
||||
class TypedPattern : public Pattern {
|
||||
Pattern *SubPattern;
|
||||
|
||||
public:
|
||||
TypedPattern(Pattern *pattern, Type type)
|
||||
: Pattern(PatternKind::Typed, type), SubPattern(pattern) {}
|
||||
|
||||
Pattern *getSubPattern() const { return SubPattern; }
|
||||
|
||||
SourceLoc getLoc() const { return SubPattern->getLoc(); }
|
||||
SourceRange getSourceRange() const {
|
||||
// FIXME: end location for type!
|
||||
return SubPattern->getSourceRange();
|
||||
}
|
||||
|
||||
static bool classof(const Pattern *P) {
|
||||
return P->getKind() == PatternKind::Typed;
|
||||
}
|
||||
static bool classof(const TypedPattern *P) { return true; }
|
||||
};
|
||||
|
||||
} // end namespace swift
|
||||
|
||||
@@ -23,7 +23,8 @@
|
||||
|
||||
PATTERN(Paren, Pattern)
|
||||
PATTERN(Tuple, Pattern)
|
||||
PATTERN(Var, Pattern)
|
||||
PATTERN(ElementRef, Pattern)
|
||||
PATTERN(Named, Pattern)
|
||||
PATTERN(Any, Pattern)
|
||||
PATTERN(Typed, Pattern)
|
||||
|
||||
#undef PATTERN
|
||||
|
||||
@@ -343,14 +343,10 @@ class TupleTypeElt {
|
||||
/// value is not specified.
|
||||
Expr *Init;
|
||||
|
||||
/// Arg - The argument declaration formed from this tuple element.
|
||||
/// This is only meaningful in the parameter clause of a function type.
|
||||
ArgDecl *Arg;
|
||||
|
||||
public:
|
||||
TupleTypeElt() = default;
|
||||
TupleTypeElt(Type ty, Identifier name, Expr *init = nullptr)
|
||||
: Name(name), Ty(ty), Init(init), Arg(nullptr) { }
|
||||
: Name(name), Ty(ty), Init(init) { }
|
||||
|
||||
bool hasName() const { return !Name.empty(); }
|
||||
Identifier getName() const { return Name; }
|
||||
@@ -360,9 +356,6 @@ public:
|
||||
bool hasInit() const { return Init != nullptr; }
|
||||
Expr *getInit() const { return Init; }
|
||||
void setInit(Expr *E) { Init = E; }
|
||||
|
||||
ArgDecl *getArgDecl() const { return Arg; }
|
||||
void setArgDecl(ArgDecl *arg) { Arg = arg; }
|
||||
};
|
||||
|
||||
/// TupleType - A tuple is a parenthesized list of types where each name has an
|
||||
|
||||
@@ -159,6 +159,18 @@ SourceRange TupleExpr::getSourceRange() const {
|
||||
return SourceRange(Start, End);
|
||||
}
|
||||
|
||||
FuncExpr *FuncExpr::create(ASTContext &C, SourceLoc funcLoc,
|
||||
ArrayRef<Pattern*> params, Type fnType,
|
||||
BraceStmt *body, DeclContext *parent) {
|
||||
unsigned nParams = params.size();
|
||||
void *buf = C.Allocate(sizeof(FuncExpr) + nParams * sizeof(Pattern*),
|
||||
Expr::Alignment);
|
||||
FuncExpr *fn = ::new(buf) FuncExpr(funcLoc, nParams, fnType, body, parent);
|
||||
for (unsigned i = 0; i != nParams; ++i)
|
||||
fn->getParamsBuffer()[i] = params[i];
|
||||
return fn;
|
||||
}
|
||||
|
||||
SourceRange FuncExpr::getSourceRange() const {
|
||||
return SourceRange(FuncLoc, Body->getEndLoc());
|
||||
}
|
||||
@@ -174,10 +186,11 @@ SourceRange FuncExpr::getSourceRange() const {
|
||||
/// func(x : int) -> (y : int) -> (int -> int)
|
||||
/// The body result type is '(int -> int)'.
|
||||
Type FuncExpr::getBodyResultType() const {
|
||||
Type ty = cast<FunctionType>(getType())->Result;
|
||||
while (FunctionType *fn = dyn_cast<FunctionType>(ty)) {
|
||||
ty = fn->Result;
|
||||
}
|
||||
unsigned n = getParamPatterns().size();
|
||||
Type ty = getType();
|
||||
do {
|
||||
ty = cast<FunctionType>(ty)->Result;
|
||||
} while (--n);
|
||||
return ty;
|
||||
}
|
||||
|
||||
|
||||
@@ -74,14 +74,27 @@ void *Pattern::operator new(size_t numBytes, ASTContext &C) throw() {
|
||||
return C.Allocate(numBytes, Pattern::Alignment);
|
||||
}
|
||||
|
||||
/// Find the name directly bound by this pattern. When used as a
|
||||
/// tuple element in a function signature, such names become part of
|
||||
/// the type.
|
||||
Identifier Pattern::getBoundName() const {
|
||||
const Pattern *P = this;
|
||||
if (const TypedPattern *TP = dyn_cast<TypedPattern>(P))
|
||||
P = TP->getSubPattern();
|
||||
|
||||
if (const NamedPattern *NP = dyn_cast<NamedPattern>(P))
|
||||
return NP->getBoundName();
|
||||
return Identifier();
|
||||
}
|
||||
|
||||
/// Allocate a new pattern that matches a tuple.
|
||||
TuplePattern *TuplePattern::create(ASTContext &C, SourceLoc lp,
|
||||
ArrayRef<Pattern*> patterns, SourceLoc rp) {
|
||||
unsigned n = patterns.size();
|
||||
void *buffer = C.Allocate(sizeof(TuplePattern) + n * sizeof(Pattern*),
|
||||
ArrayRef<TuplePatternElt> elts,
|
||||
SourceLoc rp) {
|
||||
unsigned n = elts.size();
|
||||
void *buffer = C.Allocate(sizeof(TuplePattern) + n * sizeof(TuplePatternElt),
|
||||
Pattern::Alignment);
|
||||
TuplePattern *pattern = ::new(buffer) TuplePattern(lp, n, rp);
|
||||
for (unsigned i = 0; i != n; ++i)
|
||||
pattern->getElementsBuffer()[i] = patterns[i];
|
||||
memcpy(pattern->getFieldsBuffer(), elts.data(), n * sizeof(TuplePatternElt));
|
||||
return pattern;
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
#include "swift/AST/Decl.h"
|
||||
#include "swift/AST/Expr.h"
|
||||
#include "swift/AST/Module.h"
|
||||
#include "swift/AST/Pattern.h"
|
||||
#include "swift/AST/PrettyStackTrace.h"
|
||||
#include "swift/AST/Types.h"
|
||||
#include "swift/Basic/Optional.h"
|
||||
@@ -87,6 +88,9 @@ static unsigned getNumCurries(FunctionType *type) {
|
||||
/// is the number of additional parameter clauses that are uncurried
|
||||
/// in the function body.
|
||||
static unsigned getNaturalUncurryLevel(FuncDecl *func) {
|
||||
if (func->getBody())
|
||||
return func->getBody()->getParamPatterns().size() - 1;
|
||||
|
||||
FunctionType *type = func->getType()->castTo<FunctionType>();
|
||||
unsigned count = 0;
|
||||
do {
|
||||
@@ -805,54 +809,54 @@ static void emitParameter(IRGenFunction &IGF, ArgDecl *param,
|
||||
|
||||
/// Emit a specific parameter clause by walking into any literal tuple
|
||||
/// types and matching
|
||||
static void emitParameterClause(IRGenFunction &IGF, Type paramType,
|
||||
static void emitParameterClause(IRGenFunction &IGF, Pattern *param,
|
||||
Explosion ¶mValues) {
|
||||
// Walk into tuple types.
|
||||
if (TupleType *tuple = dyn_cast<TupleType>(paramType)) {
|
||||
for (const TupleTypeElt &field : tuple->Fields) {
|
||||
// If this element is bound to a name (i.e. has an ArgDecl), load it
|
||||
// into a variable and map that as as local declaration.
|
||||
if (ArgDecl *param = field.getArgDecl()) {
|
||||
emitParameter(IGF, param, paramValues);
|
||||
// TODO: bind sub-elements when necessary.
|
||||
switch (param->getKind()) {
|
||||
// Explode tuple patterns.
|
||||
case PatternKind::Tuple:
|
||||
for (auto &field : cast<TuplePattern>(param)->getFields())
|
||||
emitParameterClause(IGF, field.getPattern(), paramValues);
|
||||
return;
|
||||
|
||||
// Otherwise, recurse on the type in case it's a tuple and
|
||||
// provides its own ArgDecls.
|
||||
} else {
|
||||
emitParameterClause(IGF, field.getType(), paramValues);
|
||||
}
|
||||
}
|
||||
// Look through a couple kinds of patterns.
|
||||
case PatternKind::Paren:
|
||||
return emitParameterClause(IGF, cast<ParenPattern>(param)->getSubPattern(),
|
||||
paramValues);
|
||||
case PatternKind::Typed:
|
||||
return emitParameterClause(IGF, cast<TypedPattern>(param)->getSubPattern(),
|
||||
paramValues);
|
||||
|
||||
// Bind names.
|
||||
case PatternKind::Named:
|
||||
emitParameter(IGF, cast<ArgDecl>(cast<NamedPattern>(param)->getDecl()),
|
||||
paramValues);
|
||||
return;
|
||||
|
||||
// Ignore ignored parameters by consuming the right number of values.
|
||||
case PatternKind::Any: {
|
||||
ExplosionSchema paramSchema(paramValues.getKind());
|
||||
IGF.IGM.getExplosionSchema(param->getType(), paramSchema);
|
||||
paramValues.claim(paramSchema.size());
|
||||
return;
|
||||
}
|
||||
|
||||
// Look through paren types.
|
||||
if (ParenType *paren = dyn_cast<ParenType>(paramType)) {
|
||||
return emitParameterClause(IGF, paren->getUnderlyingType(), paramValues);
|
||||
}
|
||||
|
||||
// Otherwise, we're ignoring this argument, but we still need to
|
||||
// consume the right number of values.
|
||||
ExplosionSchema paramSchema(paramValues.getKind());
|
||||
IGF.IGM.getExplosionSchema(paramType, paramSchema);
|
||||
paramValues.claim(paramSchema.size());
|
||||
llvm_unreachable("bad pattern kind!");
|
||||
}
|
||||
|
||||
/// Emit all the parameter clauses of the given function type. This
|
||||
/// is basically making sure that we have mappings for all the
|
||||
/// ArgDecls.
|
||||
static void emitParameterClauses(IRGenFunction &IGF, Type fnType,
|
||||
unsigned uncurryLevel,
|
||||
static void emitParameterClauses(IRGenFunction &IGF,
|
||||
llvm::ArrayRef<Pattern*> params,
|
||||
Explosion ¶mValues) {
|
||||
// We never uncurry into something that's not written immediately as
|
||||
// a function type.
|
||||
FunctionType *fn = cast<FunctionType>(fnType);
|
||||
assert(!params.empty());
|
||||
|
||||
// When uncurrying, later argument clauses are emitted first.
|
||||
if (uncurryLevel)
|
||||
emitParameterClauses(IGF, fn->Result, uncurryLevel - 1, paramValues);
|
||||
if (params.size() != 1)
|
||||
emitParameterClauses(IGF, params.slice(1), paramValues);
|
||||
|
||||
// Finally, emit this clause.
|
||||
emitParameterClause(IGF, fn->Input, paramValues);
|
||||
emitParameterClause(IGF, params[0], paramValues);
|
||||
}
|
||||
|
||||
/// Emit the prologue for the function.
|
||||
@@ -899,7 +903,8 @@ void IRGenFunction::emitPrologue() {
|
||||
}
|
||||
|
||||
// Set up the parameters.
|
||||
emitParameterClauses(*this, CurFuncExpr->getType(), CurUncurryLevel, values);
|
||||
auto params = CurFuncExpr->getParamPatterns().slice(0, CurUncurryLevel + 1);
|
||||
emitParameterClauses(*this, params, values);
|
||||
|
||||
// TODO: set up the data pointer.
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "swift/AST/Decl.h"
|
||||
#include "swift/AST/Expr.h"
|
||||
#include "swift/AST/Module.h"
|
||||
#include "swift/AST/Pattern.h"
|
||||
#include "swift/AST/Stmt.h"
|
||||
#include "swift/AST/Types.h"
|
||||
#include "llvm/Module.h"
|
||||
@@ -62,10 +63,15 @@ static bool isTrivialGlobalInit(llvm::Function *fn) {
|
||||
void IRGenModule::emitTranslationUnit(TranslationUnit *tunit) {
|
||||
Type emptyTuple = TupleType::getEmpty(Context);
|
||||
FunctionType *unitToUnit = FunctionType::get(emptyTuple, emptyTuple, Context);
|
||||
FuncExpr func(SourceLoc(), unitToUnit, nullptr, tunit);
|
||||
Pattern *params[] = {
|
||||
TuplePattern::create(Context, SourceLoc(),
|
||||
llvm::ArrayRef<TuplePatternElt>(), SourceLoc())
|
||||
};
|
||||
FuncExpr *func = FuncExpr::create(Context, SourceLoc(), params,
|
||||
unitToUnit, nullptr, tunit);
|
||||
|
||||
llvm::Function *fn = createGlobalInitFunction(*this, tunit);
|
||||
IRGenFunction(*this, &func, ExplosionKind::Minimal, /*uncurry*/ 0, fn)
|
||||
IRGenFunction(*this, func, ExplosionKind::Minimal, /*uncurry*/ 0, fn)
|
||||
.emitGlobalTopLevel(tunit->Body);
|
||||
|
||||
// Not all translation units need a global initialization function.
|
||||
|
||||
@@ -4,6 +4,7 @@ add_swift_library(swiftParse
|
||||
Parser.h
|
||||
ParseDecl.cpp
|
||||
ParseExpr.cpp
|
||||
ParsePattern.cpp
|
||||
ParseResult.h
|
||||
ParseStmt.cpp
|
||||
ParseType.cpp
|
||||
|
||||
@@ -586,25 +586,27 @@ FuncDecl *Parser::parseDeclFunc(Type ReceiverTy) {
|
||||
diagnose(Tok, diag::func_decl_without_paren);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Type FuncTy;
|
||||
if (parseType(FuncTy))
|
||||
return 0;
|
||||
|
||||
// If the parsed type is not spelled as a function type (i.e., has no '->' in
|
||||
// it), then it is implicitly a function that returns ().
|
||||
if (!isa<FunctionType>(FuncTy.getPointer()))
|
||||
FuncTy = FunctionType::get(FuncTy, TupleType::getEmpty(Context), Context);
|
||||
|
||||
// If a receiver type was specified and this isn't a plus method, install the
|
||||
// first type as the receiver, as a tuple with element named 'this'. This
|
||||
// turns "int->int" on FooTy into "(this : FooTy)->(int->int)".
|
||||
|
||||
SmallVector<Pattern*, 8> Params;
|
||||
|
||||
// If a receiver type was specified and this isn't a plus method,
|
||||
// add an implicit first pattern to match the receiver type as an
|
||||
// element named 'this'. This turns "int->int" on FooTy into
|
||||
// "(this : FooTy)->(int->int)".
|
||||
if (!ReceiverTy.isNull() && !PlusLoc.isValid()) {
|
||||
TupleTypeElt ReceiverElt(ReceiverTy, Context.getIdentifier("this"));
|
||||
FuncTy = FunctionType::get(TupleType::get(ReceiverElt, Context),
|
||||
FuncTy, Context);
|
||||
ArgDecl *D =
|
||||
new (Context) ArgDecl(SourceLoc(), Context.getIdentifier("this"),
|
||||
ReceiverTy, CurDeclContext);
|
||||
Pattern *P = new (Context) NamedPattern(D);
|
||||
P = new (Context) TypedPattern(P, ReceiverTy);
|
||||
Params.push_back(P);
|
||||
}
|
||||
|
||||
|
||||
Type FuncTy;
|
||||
if (parseFunctionSignature(Params, FuncTy))
|
||||
return 0;
|
||||
|
||||
// Enter the arguments for the function into a new function-body scope. We
|
||||
// need this even if there is no function body to detect argument name
|
||||
// duplication.
|
||||
@@ -612,7 +614,7 @@ FuncDecl *Parser::parseDeclFunc(Type ReceiverTy) {
|
||||
{
|
||||
Scope FnBodyScope(this);
|
||||
|
||||
FE = actOnFuncExprStart(FuncLoc, FuncTy);
|
||||
FE = actOnFuncExprStart(FuncLoc, FuncTy, Params);
|
||||
|
||||
// Establish the new context.
|
||||
ContextChange CC(*this, FE);
|
||||
@@ -620,7 +622,7 @@ FuncDecl *Parser::parseDeclFunc(Type ReceiverTy) {
|
||||
// Then parse the expression.
|
||||
NullablePtr<Stmt> Body;
|
||||
|
||||
// Check to see if we have a "{" which is a brace expr.
|
||||
// Check to see if we have a "{" to start a brace statement.
|
||||
if (Tok.is(tok::l_brace)) {
|
||||
ParseResult<BraceStmt> Body = parseStmtBrace(diag::invalid_diagnostic);
|
||||
if (Body.isSuccess())
|
||||
@@ -636,8 +638,8 @@ FuncDecl *Parser::parseDeclFunc(Type ReceiverTy) {
|
||||
}
|
||||
|
||||
// Create the decl for the func and add it to the parent scope.
|
||||
FuncDecl *FD = new (Context) FuncDecl(PlusLoc, FuncLoc, Name, FuncTy, FE,
|
||||
CurDeclContext);
|
||||
FuncDecl *FD = new (Context) FuncDecl(PlusLoc, FuncLoc, Name,
|
||||
FuncTy, FE, CurDeclContext);
|
||||
if (Attributes.isValid()) FD->getMutableAttrs() = Attributes;
|
||||
ScopeInfo.addToScope(FD);
|
||||
return FD;
|
||||
|
||||
@@ -397,24 +397,24 @@ ParseResult<Expr> Parser::parseExprParen() {
|
||||
ParseResult<Expr> Parser::parseExprFunc() {
|
||||
SourceLoc FuncLoc = consumeToken(tok::kw_func);
|
||||
|
||||
SmallVector<Pattern*, 4> Params;
|
||||
Type Ty;
|
||||
if (Tok.is(tok::l_brace)) {
|
||||
Params.push_back(TuplePattern::create(Context, SourceLoc(),
|
||||
llvm::ArrayRef<TuplePatternElt>(),
|
||||
SourceLoc()));
|
||||
Ty = TupleType::getEmpty(Context);
|
||||
Ty = FunctionType::get(Ty, Ty, Context);
|
||||
} else if (!Tok.is(tok::l_paren) && !Tok.is(tok::l_paren_space)) {
|
||||
diagnose(Tok, diag::func_decl_without_paren);
|
||||
return true;
|
||||
} else if (parseType(Ty)) {
|
||||
} else if (parseFunctionSignature(Params, Ty)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the parsed type is not spelled as a function type (i.e., has no '->' in
|
||||
// it), then it is implicitly a function that returns ().
|
||||
if (!isa<FunctionType>(Ty.getPointer()))
|
||||
Ty = FunctionType::get(Ty, TupleType::getEmpty(Context), Context);
|
||||
|
||||
// The arguments to the func are defined in their own scope.
|
||||
Scope FuncBodyScope(this);
|
||||
FuncExpr *FE = actOnFuncExprStart(FuncLoc, Ty);
|
||||
FuncExpr *FE = actOnFuncExprStart(FuncLoc, Ty, Params);
|
||||
|
||||
// Establish the new context.
|
||||
ContextChange CC(*this, FE);
|
||||
@@ -431,79 +431,46 @@ ParseResult<Expr> Parser::parseExprFunc() {
|
||||
}
|
||||
|
||||
|
||||
/// FuncTypePiece - This little enum is used by AddFuncArgumentsToScope to keep
|
||||
/// track of where in a function type it is currently looking. This affects how
|
||||
/// the decls are processed and created.
|
||||
enum class FuncTypePiece {
|
||||
Function, // Looking at the initial functiontype itself.
|
||||
Input, // Looking at the input to the function type
|
||||
Output // Looking at the output to the function type.
|
||||
};
|
||||
|
||||
/// AddFuncArgumentsToScope - Walk the type specified for a Func object (which
|
||||
/// is known to be a FunctionType on the outer level) creating and adding named
|
||||
/// arguments to the current scope. This causes redefinition errors to be
|
||||
/// emitted.
|
||||
static void AddFuncArgumentsToScope(Type Ty,
|
||||
FuncTypePiece Mode,
|
||||
FuncExpr *FE,
|
||||
Parser &P) {
|
||||
// Handle the function case first.
|
||||
if (Mode == FuncTypePiece::Function) {
|
||||
FunctionType *FT = cast<FunctionType>(Ty);
|
||||
AddFuncArgumentsToScope(FT->Input, FuncTypePiece::Input, FE, P);
|
||||
|
||||
// If this is a->b->c then we treat b as an input, not (b->c) as an output.
|
||||
if (isa<FunctionType>(FT->Result.getPointer()))
|
||||
AddFuncArgumentsToScope(FT->Result, FuncTypePiece::Function, FE, P);
|
||||
else
|
||||
AddFuncArgumentsToScope(FT->Result, FuncTypePiece::Output, FE, P);
|
||||
static void AddFuncArgumentsToScope(Pattern *pat, FuncExpr *FE, Parser &P) {
|
||||
switch (pat->getKind()) {
|
||||
case PatternKind::Named: {
|
||||
// Reparent the decl and add it to the scope.
|
||||
ArgDecl *AD = cast<ArgDecl>(cast<NamedPattern>(pat)->getDecl());
|
||||
AD->setDeclContext(FE);
|
||||
P.ScopeInfo.addToScope(AD);
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, we're looking at an input or output to the func. The only type
|
||||
// we currently dive into is the humble tuple, which can be recursive. This
|
||||
// should dive in syntactically.
|
||||
///
|
||||
/// Note that we really *do* want dyn_cast here, not getAs, because we do not
|
||||
/// want to look through type aliases or other sugar, we want to see what the
|
||||
/// user wrote in the func declaration.
|
||||
TupleType *TT = dyn_cast<TupleType>(Ty.getPointer());
|
||||
if (TT == 0) return;
|
||||
|
||||
// For tuples, recursively processes their elements (to handle cases like:
|
||||
// (x : (a : int, b : int), y : int) -> ...
|
||||
// and create decls for any named elements.
|
||||
for (const TupleTypeElt &Field : TT->Fields) {
|
||||
AddFuncArgumentsToScope(Field.getType(), Mode, FE, P);
|
||||
|
||||
// If this field is named, create the argument decl for it.
|
||||
// Otherwise, ignore unnamed fields.
|
||||
if (!Field.hasName()) continue;
|
||||
|
||||
// Create the argument decl for this named argument.
|
||||
ArgDecl *AD = new (P.Context) ArgDecl(FE->getFuncLoc(), Field.getName(),
|
||||
Field.getType(), FE);
|
||||
case PatternKind::Any:
|
||||
return;
|
||||
|
||||
// Modify the TupleType in-place. This is okay, as we're
|
||||
// essentially still processing it.
|
||||
const_cast<TupleTypeElt&>(Field).setArgDecl(AD);
|
||||
|
||||
// Eventually we should mark the input/outputs as readonly vs writeonly.
|
||||
//bool isInput = Mode == FuncTypePiece::Input;
|
||||
|
||||
P.ScopeInfo.addToScope(AD);
|
||||
case PatternKind::Paren:
|
||||
AddFuncArgumentsToScope(cast<ParenPattern>(pat)->getSubPattern(), FE, P);
|
||||
return;
|
||||
|
||||
case PatternKind::Typed:
|
||||
AddFuncArgumentsToScope(cast<TypedPattern>(pat)->getSubPattern(), FE, P);
|
||||
return;
|
||||
|
||||
case PatternKind::Tuple:
|
||||
for (const TuplePatternElt &field : cast<TuplePattern>(pat)->getFields())
|
||||
AddFuncArgumentsToScope(field.getPattern(), FE, P);
|
||||
return;
|
||||
}
|
||||
llvm_unreachable("bad pattern kind!");
|
||||
}
|
||||
|
||||
FuncExpr *Parser::actOnFuncExprStart(SourceLoc FuncLoc, Type FuncTy,
|
||||
ArrayRef<Pattern*> Params) {
|
||||
FuncExpr *FE = FuncExpr::create(Context, FuncLoc, Params, FuncTy, 0,
|
||||
CurDeclContext);
|
||||
|
||||
FuncExpr *Parser::actOnFuncExprStart(SourceLoc FuncLoc, Type FuncTy) {
|
||||
FuncExpr *FE = new (Context) FuncExpr(FuncLoc, FuncTy, 0, CurDeclContext);
|
||||
|
||||
AddFuncArgumentsToScope(FuncTy, FuncTypePiece::Function, FE, *this);
|
||||
for (Pattern *P : Params)
|
||||
AddFuncArgumentsToScope(P, FE, *this);
|
||||
|
||||
return FE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
224
lib/Parse/ParsePattern.cpp
Normal file
224
lib/Parse/ParsePattern.cpp
Normal file
@@ -0,0 +1,224 @@
|
||||
//===--- ParsePattern.cpp - Swift Language Parser for Patterns ------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Pattern Parsing and AST Building
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Parser.h"
|
||||
using namespace swift;
|
||||
|
||||
/// Check that the given pattern is fully-typed.
|
||||
static bool checkFullyTyped(Parser &P, Pattern *pattern) {
|
||||
switch (pattern->getKind()) {
|
||||
// Any type with an explicit annotation is okay.
|
||||
case PatternKind::Typed:
|
||||
return false;
|
||||
|
||||
// Paren types depend on their parenthesized pattern.
|
||||
case PatternKind::Paren: {
|
||||
Pattern *sub = cast<ParenPattern>(pattern)->getSubPattern();
|
||||
if (checkFullyTyped(P, sub)) return true;
|
||||
pattern->setType(sub->getType());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Tuple types can be built up from their components.
|
||||
case PatternKind::Tuple: {
|
||||
TuplePattern *tuple = cast<TuplePattern>(pattern);
|
||||
SmallVector<TupleTypeElt, 8> typeElts;
|
||||
typeElts.reserve(tuple->getNumFields());
|
||||
for (const TuplePatternElt &elt : tuple->getFields()) {
|
||||
Pattern *subpattern = elt.getPattern();
|
||||
if (checkFullyTyped(P, subpattern))
|
||||
return true;
|
||||
typeElts.push_back(TupleTypeElt(subpattern->getType(),
|
||||
subpattern->getBoundName(),
|
||||
elt.getInit()));
|
||||
}
|
||||
tuple->setType(TupleType::get(typeElts, P.Context));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Everything else is uninferrable.
|
||||
case PatternKind::Named:
|
||||
case PatternKind::Any:
|
||||
P.diagnose(pattern->getLoc(), diag::untyped_pattern_in_function_signature)
|
||||
<< pattern->getSourceRange();
|
||||
return true;
|
||||
}
|
||||
llvm_unreachable("bad pattern kind");
|
||||
}
|
||||
|
||||
/// Parse a function definition signature.
|
||||
bool Parser::parseFunctionSignature(SmallVectorImpl<Pattern*> ¶ms,
|
||||
Type &type) {
|
||||
// Parse curried function argument clauses as long as we can.
|
||||
bool hasSemaError = false;
|
||||
do {
|
||||
ParseResult<Pattern> pattern = parsePatternTuple();
|
||||
if (pattern.isParseError()) {
|
||||
return true;
|
||||
} else if (pattern.isSemaError()) {
|
||||
hasSemaError = true;
|
||||
} else {
|
||||
params.push_back(pattern.get());
|
||||
}
|
||||
} while (Tok.is(tok::l_paren) || Tok.is(tok::l_paren_space));
|
||||
|
||||
// If there's a trailing arrow, parse the rest as the result type.
|
||||
if (consumeIf(tok::arrow)) {
|
||||
if (parseType(type))
|
||||
return true;
|
||||
|
||||
// Otherwise, we implicitly return ().
|
||||
} else {
|
||||
type = TupleType::getEmpty(Context);
|
||||
}
|
||||
|
||||
// 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.
|
||||
for (unsigned i = params.size(); i != 0; --i) {
|
||||
Pattern *param = params[i - 1];
|
||||
|
||||
Type paramType;
|
||||
if (checkFullyTyped(*this, param)) {
|
||||
// Recover by ignoring everything.
|
||||
paramType = TupleType::getEmpty(Context);
|
||||
} else {
|
||||
paramType = param->getType();
|
||||
}
|
||||
type = FunctionType::get(paramType, type, Context);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Parse a pattern.
|
||||
/// pattern ::= pattern-atom
|
||||
/// pattern ::= pattern-atom ':' type
|
||||
ParseResult<Pattern> Parser::parsePattern() {
|
||||
// First, parse the pattern atom.
|
||||
ParseResult<Pattern> pattern = parsePatternAtom();
|
||||
if (pattern.isParseError()) return true;
|
||||
|
||||
// Now parse an optional type annotation.
|
||||
if (consumeIf(tok::colon)) {
|
||||
Type type;
|
||||
if (parseType(type))
|
||||
return true;
|
||||
|
||||
if (!pattern.isSemaError())
|
||||
pattern = new (Context) TypedPattern(pattern.get(), type);
|
||||
}
|
||||
|
||||
return pattern;
|
||||
}
|
||||
|
||||
/// Parse a pattern "atom", meaning the part that precedes the
|
||||
/// optional type annotation.
|
||||
///
|
||||
/// pattern-atom ::= identifier
|
||||
/// pattern-atom ::= pattern-tuple
|
||||
ParseResult<Pattern> Parser::parsePatternAtom() {
|
||||
switch (Tok.getKind()) {
|
||||
case tok::l_paren:
|
||||
case tok::l_paren_space:
|
||||
return parsePatternTuple();
|
||||
|
||||
case tok::identifier: {
|
||||
SourceLoc loc = Tok.getLoc();
|
||||
StringRef text = Tok.getText();
|
||||
consumeToken(tok::identifier);
|
||||
|
||||
// '_' is a special case which means 'ignore this'.
|
||||
if (text == "_") {
|
||||
return new (Context) AnyPattern(loc);
|
||||
} else {
|
||||
Identifier ident = Context.getIdentifier(text);
|
||||
ArgDecl *arg = new (Context) ArgDecl(loc, ident, Type(), CurDeclContext);
|
||||
return new (Context) NamedPattern(arg);
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
diagnose(Tok, diag::expected_pattern);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a tuple pattern.
|
||||
///
|
||||
/// pattern-tuple:
|
||||
//// '(' pattern-tuple-body? ')'
|
||||
/// pattern-tuple-body:
|
||||
/// pattern-tuple-element (',' pattern-tuple-body)*
|
||||
/// pattern-tuple-element:
|
||||
/// pattern ('=' expr)?
|
||||
ParseResult<Pattern> Parser::parsePatternTuple() {
|
||||
assert(Tok.is(tok::l_paren) || Tok.is(tok::l_paren_space));
|
||||
|
||||
// We're looking at the left parenthesis; consume it.
|
||||
SourceLoc lp = consumeToken();
|
||||
|
||||
// Parse all the elements.
|
||||
SmallVector<TuplePatternElt, 8> elts;
|
||||
bool hasSemaError = false;
|
||||
if (Tok.isNot(tok::r_paren)) {
|
||||
do {
|
||||
ParseResult<Pattern> pattern = parsePattern();
|
||||
Expr *init = nullptr;
|
||||
|
||||
if (pattern.isParseError()) {
|
||||
skipUntil(tok::r_paren);
|
||||
return true;
|
||||
} else if (consumeIf(tok::equal)) {
|
||||
ParseResult<Expr> initR = parseExpr(diag::expected_initializer_expr);
|
||||
if (initR.isParseError()) {
|
||||
skipUntil(tok::r_paren);
|
||||
return true;
|
||||
} else if (initR.isSemaError()) {
|
||||
hasSemaError = true;
|
||||
} else {
|
||||
init = initR.get();
|
||||
}
|
||||
}
|
||||
|
||||
if (pattern.isSemaError()) {
|
||||
hasSemaError = true;
|
||||
} else {
|
||||
elts.push_back(TuplePatternElt(pattern.get(), init));
|
||||
}
|
||||
} while (consumeIf(tok::comma));
|
||||
|
||||
if (Tok.isNot(tok::r_paren)) {
|
||||
diagnose(Tok, diag::expected_rparen_tuple_pattern_list);
|
||||
skipUntil(tok::r_paren);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Consume the right parenthesis.
|
||||
SourceLoc rp = consumeToken(tok::r_paren);
|
||||
|
||||
if (hasSemaError)
|
||||
return ParseResult<Pattern>::getSemaError();
|
||||
|
||||
// A pattern which wraps a single anonymous pattern is not a tuple.
|
||||
if (elts.size() == 1 &&
|
||||
elts[0].getInit() == nullptr &&
|
||||
elts[0].getPattern()->getBoundName().empty())
|
||||
return new (Context) ParenPattern(lp, elts[0].getPattern(), rp);
|
||||
|
||||
return TuplePattern::create(Context, lp, elts, rp);
|
||||
}
|
||||
@@ -222,6 +222,14 @@ public:
|
||||
bool parseTypeTupleBody(SourceLoc LPLoc, Type &Result);
|
||||
|
||||
bool parseTypeArray(SourceLoc LSquareLoc, Type &Result);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Pattern Parsing
|
||||
|
||||
bool parseFunctionSignature(SmallVectorImpl<Pattern*> ¶ms, Type &type);
|
||||
ParseResult<Pattern> parsePattern();
|
||||
ParseResult<Pattern> parsePatternTuple();
|
||||
ParseResult<Pattern> parsePatternAtom();
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Expression Parsing
|
||||
@@ -238,7 +246,8 @@ public:
|
||||
ParseResult<Expr> parseExprFunc();
|
||||
|
||||
Expr *actOnIdentifierExpr(Identifier Text, SourceLoc Loc);
|
||||
FuncExpr *actOnFuncExprStart(SourceLoc FuncLoc, Type FuncTy);
|
||||
FuncExpr *actOnFuncExprStart(SourceLoc FuncLoc, Type FuncTy,
|
||||
ArrayRef<Pattern*> Patterns);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Statement Parsing
|
||||
@@ -255,7 +264,7 @@ public:
|
||||
Expr *actOnCondition(Expr *Cond);
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // end namespace swift
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,6 +5,7 @@ add_swift_library(swiftSema
|
||||
TypeCheckCoercion.cpp
|
||||
TypeCheckExpr.cpp
|
||||
TypeCheckDecl.cpp
|
||||
TypeCheckPattern.cpp
|
||||
TypeCheckStmt.cpp
|
||||
TypeCheckType.cpp
|
||||
DEPENDS swiftAST swiftParse)
|
||||
|
||||
@@ -1051,3 +1051,15 @@ bool TypeChecker::typeCheckExpression(Expr *&E, Type ConvertType) {
|
||||
E = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TypeChecker::semaFunctionSignature(FuncExpr *FE) {
|
||||
bool hadError = false;
|
||||
for (unsigned i = FE->getParamPatterns().size(); i != 0; --i) {
|
||||
Pattern *pattern = FE->getParamPatterns()[i - 1];
|
||||
if (typeCheckPattern(pattern)) {
|
||||
hadError = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return hadError;
|
||||
}
|
||||
|
||||
@@ -193,7 +193,7 @@ void swift::performTypeChecking(TranslationUnit *TU) {
|
||||
|
||||
// Type check the body of each of the FuncExpr in turn.
|
||||
for (FuncExpr *FE : FuncExprs) {
|
||||
if (!FE->getBody()) continue;
|
||||
TC.semaFunctionSignature(FE);
|
||||
|
||||
PrettyStackTraceExpr StackEntry(TC.Context, "type-checking", FE);
|
||||
|
||||
|
||||
@@ -35,13 +35,15 @@ public:
|
||||
|
||||
bool validateType(ValueDecl *VD);
|
||||
bool validateType(Type T);
|
||||
|
||||
|
||||
bool semaFunctionSignature(FuncExpr *FE);
|
||||
bool semaTupleExpr(TupleExpr *TE);
|
||||
Expr *semaApplyExpr(ApplyExpr *E);
|
||||
|
||||
bool typeCheckExpression(Expr *&E, Type ConvertType = Type());
|
||||
void typeCheckDecl(Decl *D);
|
||||
|
||||
bool typeCheckPattern(Pattern *P);
|
||||
bool convertToType(Pattern *P, Type Ty);
|
||||
|
||||
bool bindAndValidateClosureArgs(Expr *Body, Type FuncInput);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user