Files
swift-mirror/lib/Parse/Scope.cpp
Joe Groff 6449655e21 Implement selector-style function definition syntax.
rdar://12315571
Allow a function to be defined with this syntax:

  func doThing(a:Thing) withItem(b:Item) -> Result { ... }

This allows the keyword names in the function type (in this case
`(_:Thing, withItem:Item) -> Result`) to differ from the names bound in the
function body (in this case `(a:Thing, b:Item) -> Result`, which allows
for Cocoa-style `verbingNoun` keyword idioms to be used without requiring
those keywords to also be used as awkward variable names. In addition
to modifying the parser, this patch extends the FuncExpr type by replacing
the former `getParamPatterns` accessor with separate `getArgParamPatterns`
and `getBodyParamPatterns`, which retrieve the argument name patterns and
body parameter binding patterns respectively.



Swift SVN r3098
2012-11-01 21:53:15 +00:00

92 lines
3.5 KiB
C++

//===--- Scope.cpp - Scope Implementation ---------------------------------===//
//
// 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 implements semantic analysis for Swift declarations.
//
//===----------------------------------------------------------------------===//
#include "swift/AST/Attr.h"
#include "Scope.h"
#include "Parser.h"
#include "llvm/ADT/Twine.h"
using namespace swift;
//===----------------------------------------------------------------------===//
// Scope Implementation
//===----------------------------------------------------------------------===//
Scope::Scope(Parser *P, bool ResolvableScope)
: SI(P->ScopeInfo), ValueHTScope(SI.ValueScopeHT), PrevScope(SI.CurScope),
PrevResolvableDepth(SI.ResolvableDepth) {
if (SI.CurScope)
Depth = SI.CurScope->Depth+1;
else
Depth = 0;
SI.CurScope = this;
if (!ResolvableScope)
SI.ResolvableDepth = Depth + 1;
}
//===----------------------------------------------------------------------===//
// ScopeInfo Implementation
//===----------------------------------------------------------------------===//
/// checkValidOverload - Check whether it is ok for D1 and D2 to be declared at
/// the same scope. This check is a transitive relationship, so if "D1 is a
/// valid overload of D2" and "D2 is a valid overload of D3" then we know that
/// D1/D3 are valid overloads and we don't have to check all permutations.
static bool checkValidOverload(const ValueDecl *D1, const ValueDecl *D2,
Parser &P) {
if (D1->getAttrs().isInfix() && D2->getAttrs().isInfix() &&
D1->getAttrs().getInfixData() != D2->getAttrs().getInfixData()) {
P.diagnose(D1->getLoc(), diag::precedence_overload);
// FIXME: Pass identifier through, when the diagnostics system can handle
// it.
P.diagnose(D2->getLoc(), diag::previous_declaration, D2->getName());
return true;
}
// Otherwise, everything is fine.
return false;
}
/// addToScope - Register the specified decl as being in the current lexical
/// scope.
void ScopeInfo::addToScope(ValueDecl *D) {
// If we have a shadowed variable definition, check to see if we have a
// redefinition: two definitions in the same scope with the same name.
ValueScopeHTTy::iterator EntryI = ValueScopeHT.begin(D->getName());
// A redefinition is a hit in the scoped table at the same depth.
if (EntryI != ValueScopeHT.end() && EntryI->first == CurScope->getDepth()) {
ValueDecl *PrevDecl = EntryI->second;
// If this is in a resolvable scope, diagnose redefinitions. Later
// phases will handle scopes like module-scope, etc.
if (CurScope->getDepth() >= ResolvableDepth)
return TheParser.diagnoseRedefinition(PrevDecl, D);
// If this is at top-level scope, validate that the members of the overload
// set all agree.
// Check to see if D and PrevDecl are valid in the same overload set.
if (checkValidOverload(D, PrevDecl, TheParser))
return;
// Note: we don't check whether all of the elements of the overload set have
// different argument types. This is checked later.
}
ValueScopeHT.insert(D->getName(), std::make_pair(CurScope->getDepth(), D));
}