SlideShare ist ein Scribd-Unternehmen logo
1 von 102
Downloaden Sie, um offline zu lesen
Integrating libSyntax into
the compiler pipeline
@kitasuke
Integrating libSyntax into the compiler pipeline
Problem
Semantic AST is completely ignored and wasted
when SwiftSyntax invokes the Swift parser to get the
libSyntax tree for some source text.
Existing pipeline
(Source) -> [Parser] -+-> (AST) -> [Sema] -> ...
| and
+-> (libSyntax) -> [SwiftSyntax, ...]
What's Parser doing?
Parser
Parser
→ Lexer
Parser
→ Lexer
→ SyntaxParsingContext
Parser
→ Lexer
→ SyntaxParsingContext
→ SyntaxParseActions
Parser
→ Lexer
→ SyntaxParsingContext
→ SyntaxParseActions
→ Parser
Parser
→ Lexer
→ SyntaxParsingContext
→ SyntaxParseActions
→ Parser
→ ParseDecl/Stmt/Expr etc
Parser
→ Lexer
→ SyntaxParsingContext
→ SyntaxParseActions
→ Parser
→ ParseDecl/Stmt/Expr etc
→ and more
Lexer
class Lexer {
/// Lex a token. If c TriviaRetentionMode is c WithTrivia, passed pointers
/// to trivias are populated.
void lex(Token &Result, ParsedTrivia &LeadingTriviaResult,
ParsedTrivia &TrailingTriviaResult);
void lexImpl();
void lexHash();
void lexIdentifier();
void lexOperatorIdentifier();
void lexNumber();
void lexTrivia(ParsedTrivia &T, bool IsForTrailingTrivia);
void lexStringLiteral(unsigned CustomDelimiterLen = 0);
...
}
SyntaxParsingContext
class alignas(1 << SyntaxAlignInBits) SyntaxParsingContext {
RootContextData *RootData;
// If false, context does nothing.
bool Enabled;
void addRawSyntax(ParsedRawSyntaxNode Raw);
void addToken(Token &Tok, const ParsedTrivia &LeadingTrivia,
const ParsedTrivia &TrailingTrivia);
void addSyntax(ParsedSyntax Node);
void setCreateSyntax(SyntaxKind kind);
/// Explicitly finalizing syntax tree creation.
/// This function will be called during the destroying of a root syntax
/// parsing context. However, we can explicitly call this function to get
/// the syntax tree before closing the root context.
ParsedRawSyntaxNode finalizeRoot();
...
}
SyntaxParseActions
class SyntaxParseActions {
virtual OpaqueSyntaxNode recordToken(tok tokenKind,
ArrayRef<ParsedTriviaPiece> leadingTrivia,
ArrayRef<ParsedTriviaPiece> trailingTrivia,
CharSourceRange range) = 0;
/// Record a missing token. c loc can be invalid or an approximate location
/// of where the token would be if not missing.
virtual OpaqueSyntaxNode recordMissingToken(tok tokenKind, SourceLoc loc) = 0;
/// The provided c elements are an exact layout appropriate for the syntax
/// c kind. Missing optional elements are represented with a null
/// OpaqueSyntaxNode object.
virtual OpaqueSyntaxNode recordRawSyntax(syntax::SyntaxKind kind,
ArrayRef<OpaqueSyntaxNode> elements,
CharSourceRange range) = 0;
}
Parser
class Parser {
SourceFile &SF;
Lexer *L;
ASTContext &Context;
SyntaxParsingContext *SyntaxContext;
Token Tok;
ConsumeTokenReceiver *TokReceiver;
...
/// Calling this function to finalize libSyntax tree creation without destroying
/// the parser instance.
ParsedRawSyntaxNode finalizeSyntaxTree() {
assert(Tok.is(tok::eof) && "not done parsing yet");
return SyntaxContext->finalizeRoot();
}
bool parseTopLevel();
}
SourceFile
class SourceFile final : public FileUnit {
/// The list of top-level declarations in the source file.
std::vector<Decl*> Decls;
SyntaxParsingCache *SyntaxParsingCache = nullptr;
ASTStage_t ASTStage = Parsing;
virtual bool walk(ASTWalker &walker) override;
void dump(raw_ostream &os) const;
bool shouldBuildSyntaxTree() const;
syntax::SourceFileSyntax getSyntaxRoot() const;
void setSyntaxRoot(syntax::SourceFileSyntax &&Root);
std::unique_ptr<SourceFileSyntaxInfo> SyntaxInfo;
}
ParseDecl/Stmt/Expr
bool Parser::parseTopLevel();
ParserStatus Parser::parseBraceItems(SmallVectorImpl<ASTNode> &Entries,
BraceItemListKind Kind,
BraceItemListKind ConditionalBlockKind);
ParserStatus Parser::parseExprOrStmt(ASTNode &Result);
ParserResult<Expr> parseExpr(Diag<> ID);
ParserResult<Expr> Parser::parseExprStringLiteral();
...
What's libSyntax doing?
libSyntax
libSyntax
→ Syntax
libSyntax
→ Syntax
→ SyntaxData
libSyntax
→ Syntax
→ SyntaxData
→ RawSyntax
libSyntax
→ Syntax
→ SyntaxData
→ RawSyntax
→ and more
Syntax
/// The main handle for syntax nodes - subclasses contain all public
/// structured editing APIs.
///
/// This opaque structure holds two pieces of data: a strong reference to a
/// root node and a weak reference to the node itself. The node of interest can
/// be weakly held because the data nodes contain strong references to
/// their children.
class Syntax {
/// A strong reference to the root node of the tree in which this piece of
/// syntax resides.
const RC<SyntaxData> Root;
/// A raw pointer to the data representing this syntax node.
/// This is mutable for being able to set cached child members, which are
/// lazily created.
mutable const SyntaxData *Data;
}
SyntaxData
/// The class for holding parented syntax.
///
/// This structure should not contain significant public
/// API or internal modification API.
///
/// This is only for holding a strong reference to the RawSyntax, a weak
/// reference to the parent, and, in subclasses, lazily created strong
/// references to non-terminal child nodes.
class SyntaxData final {
using RootDataPair = std::pair<RC<SyntaxData>, RC<SyntaxData>>;
/// The shared raw syntax representing this syntax data node.
const RC<RawSyntax> Raw;
/// The parent of this syntax.
const SyntaxData *Parent;
/// The index into the parent's child layout.
const CursorIndex IndexInParent;
}
RawSyntax
/// RawSyntax - the strictly immutable, shared backing nodes for all syntax.
///
/// This is implementation detail - do not expose it in public API.
class RawSyntax final {
/// An ID of this node that is stable across incremental parses
SyntaxNodeId NodeId;
union {
uint64_t OpaqueBits;
struct {...} Common;
struct {...} Layout;
struct {...} Token;
} Bits;
}
What's AST doing?
AST
AST
→ ASTContext
AST
→ ASTContext
→ ASTDumper
AST
→ ASTContext
→ ASTDumper
→ Decl/Stmt/Expr etc
AST
→ ASTContext
→ ASTDumper
→ Decl/Stmt/Expr etc
→ and more
ASTContext
/// ASTContext - This object creates and owns the AST objects.
/// However, this class does more than just maintain context within an AST.
/// It is the closest thing to thread-local or compile-local storage in this
/// code base. Why? SourceKit uses this code with multiple threads per Unix
/// process. Each thread processes a different source file. Each thread has its
/// own instance of ASTContext, and that instance persists for the duration of
/// the thread, throughout all phases of the compilation. (The name "ASTContext"
/// is a bit of a misnomer here.) Why not use thread-local storage? This code
/// may use DispatchQueues and pthread-style TLS won't work with code that uses
/// DispatchQueues. Summary: if you think you need a global or static variable,
/// you probably need to put it here instead.
class ASTContext final {...}
ASTDumper
class PrintPattern : public PatternVisitor<PrintPattern> {...}
class PrintDecl : public DeclVisitor<PrintDecl> {...}
class PrintStmt : public StmtVisitor<PrintStmt> {...}
class PrintExpr : public ExprVisitor<PrintExpr> {...}
class PrintType : public TypeVisitor<PrintType, void, StringRef> {...}
Decl/Stmt/Expr
/// TopLevelCodeDecl - This decl is used as a container for top-level
/// expressions and statements in the main module. It is always a direct
/// child of a SourceFile.
class TopLevelCodeDecl : public DeclContext, public Decl {...}
/// BraceStmt - A brace enclosed sequence of expressions, stmts, or decls, like
/// { var x = 10; print(10) }.
class BraceStmt final : public Stmt,
private llvm::TrailingObjects<BraceStmt, ASTNode> {...}
/// Integer literal with a '+' or '-' sign, like '+4' or '- 2'.
class IntegerLiteralExpr : public NumberLiteralExpr {...}
Let's look into how swift
source is parsed
sample.swift
1
parseTopLevel
// ParseDecl.cpp
bool Parser::parseTopLevel() {
SF.ASTStage = SourceFile::Parsing;
parseBraceItems(Items,
allowTopLevelCode() ? BraceItemListKind::TopLevelCode
: BraceItemListKind::TopLevelLibrary);
// Add newly parsed decls to the module.
SmallVector<ASTNode, 128> Items;
for (auto Item : Items)
if (auto *D = Item.dyn_cast<Decl*>())
SF.Decls.push_back(D);
// Note that the source file is fully parsed and verify it.
SF.ASTStage = SourceFile::Parsed;
verify(SF);
// If we are done parsing the whole file, finalize the token receiver.
if (Tok.is(tok::eof)) {
SyntaxContext->addToken(Tok, LeadingTrivia, TrailingTrivia);
TokReceiver->finalize();
}
}
parseTopLevel
// ParseDecl.cpp
bool Parser::parseTopLevel() {
SF.ASTStage = SourceFile::Parsing;
parseBraceItems(Items,
allowTopLevelCode() ? BraceItemListKind::TopLevelCode
: BraceItemListKind::TopLevelLibrary);
// Add newly parsed decls to the module.
SmallVector<ASTNode, 128> Items;
for (auto Item : Items)
if (auto *D = Item.dyn_cast<Decl*>())
SF.Decls.push_back(D);
// Note that the source file is fully parsed and verify it.
SF.ASTStage = SourceFile::Parsed;
verify(SF);
// If we are done parsing the whole file, finalize the token receiver.
if (Tok.is(tok::eof)) {
SyntaxContext->addToken(Tok, LeadingTrivia, TrailingTrivia);
TokReceiver->finalize();
}
}
parseBraceItems
// ParseStmt.cpp
ParserStatus Parser::parseBraceItems(SmallVectorImpl<ASTNode> &Entries,
BraceItemListKind Kind,
BraceItemListKind ConditionalBlockKind) {
SyntaxParsingContext ItemListContext(SyntaxContext,
SyntaxKind::CodeBlockItemList);
auto *TLCD = new (Context) TopLevelCodeDecl(CurDeclContext);
ContextChange CC(*this, TLCD, &State->getTopLevelContext());
ParserStatus BraceItemsStatus;
ParserStatus Status = parseExprOrStmt(Result);
BraceItemsStatus |= Status;
auto Brace = BraceStmt::create(Context, Result.getStartLoc(),
Result, Result.getEndLoc());
TLCD->setBody(Brace);
Entries.push_back(TLCD);
return BraceItemsStatus;
}
parseBraceItems
// ParseStmt.cpp
ParserStatus Parser::parseBraceItems(SmallVectorImpl<ASTNode> &Entries,
BraceItemListKind Kind,
BraceItemListKind ConditionalBlockKind) {
SyntaxParsingContext ItemListContext(SyntaxContext,
SyntaxKind::CodeBlockItemList);
auto *TLCD = new (Context) TopLevelCodeDecl(CurDeclContext);
ContextChange CC(*this, TLCD, &State->getTopLevelContext());
ParserStatus BraceItemsStatus;
ParserStatus Status = parseExprOrStmt(Result);
BraceItemsStatus |= Status;
auto Brace = BraceStmt::create(Context, Result.getStartLoc(),
Result, Result.getEndLoc());
TLCD->setBody(Brace);
Entries.push_back(TLCD);
return BraceItemsStatus;
}
parseBraceItems
// ParseStmt.cpp
ParserStatus Parser::parseBraceItems(SmallVectorImpl<ASTNode> &Entries,
BraceItemListKind Kind,
BraceItemListKind ConditionalBlockKind) {
SyntaxParsingContext ItemListContext(SyntaxContext,
SyntaxKind::CodeBlockItemList);
auto *TLCD = new (Context) TopLevelCodeDecl(CurDeclContext);
ContextChange CC(*this, TLCD, &State->getTopLevelContext());
ParserStatus BraceItemsStatus;
ParserStatus Status = parseExprOrStmt(Result);
BraceItemsStatus |= Status;
auto Brace = BraceStmt::create(Context, Result.getStartLoc(),
Result, Result.getEndLoc());
TLCD->setBody(Brace);
Entries.push_back(TLCD);
return BraceItemsStatus;
}
parseExpr
// ParseStmt.cpp
ParserStatus Parser::parseExprOrStmt(ASTNode &Result) {
ParserResult<Expr> ResultExpr = parseExpr(diag::expected_expr);
return ResultExpr;
}
// ParseExpr.cpp
ParserResult<Expr> parseExpr(Diag<> ID) {
return parseExprImpl(ID, /*isExprBasic=*/false);
}
ParserResult<Expr> Parser::parseExprImpl(Diag<> Message,
bool isExprBasic) {
SyntaxParsingContext ExprParsingContext(SyntaxContext, SyntaxContextKind::Expr);
auto expr = parseExprSequence(Message, isExprBasic,
/*forConditionalDirective*/false);
return makeParserResult(expr.get());
}
parseExpr
// ParseStmt.cpp
ParserStatus Parser::parseExprOrStmt(ASTNode &Result) {
ParserResult<Expr> ResultExpr = parseExpr(diag::expected_expr);
return ResultExpr;
}
// ParseExpr.cpp
ParserResult<Expr> parseExpr(Diag<> ID) {
return parseExprImpl(ID, /*isExprBasic=*/false);
}
ParserResult<Expr> Parser::parseExprImpl(Diag<> Message,
bool isExprBasic) {
SyntaxParsingContext ExprParsingContext(SyntaxContext, SyntaxContextKind::Expr);
auto expr = parseExprSequence(Message, isExprBasic,
/*forConditionalDirective*/false);
return makeParserResult(expr.get());
}
parseExpr
// ParseStmt.cpp
ParserStatus Parser::parseExprOrStmt(ASTNode &Result) {
ParserResult<Expr> ResultExpr = parseExpr(diag::expected_expr);
return ResultExpr;
}
// ParseExpr.cpp
ParserResult<Expr> parseExpr(Diag<> ID) {
return parseExprImpl(ID, /*isExprBasic=*/false);
}
ParserResult<Expr> Parser::parseExprImpl(Diag<> Message,
bool isExprBasic) {
SyntaxParsingContext ExprParsingContext(SyntaxContext, SyntaxContextKind::Expr);
auto expr = parseExprSequence(Message, isExprBasic,
/*forConditionalDirective*/false);
return makeParserResult(expr.get());
}
parseExprSequence
// ParseExpr.cpp
ParserResult<Expr> Parser::parseExprSequence(Diag<> Message,
bool isExprBasic,
bool isForConditionalDirective) {
SyntaxParsingContext ExprSequnceContext(SyntaxContext, SyntaxContextKind::Expr);
// Parse a unary expression.
ParserResult<Expr> Primary =
parseExprSequenceElement(Message, isExprBasic);
auto expr = Primary.get();
// If we saw no operators, don't build a sequence.
return makeParserResult(expr);
}
ParserResult<Expr> Parser::parseExprSequenceElement(Diag<> message,
bool isExprBasic) {
SyntaxParsingContext ElementContext(SyntaxContext,
SyntaxContextKind::Expr);
return parseExprUnary(message, isExprBasic);
}
parseExprSequence
// ParseExpr.cpp
ParserResult<Expr> Parser::parseExprSequence(Diag<> Message,
bool isExprBasic,
bool isForConditionalDirective) {
SyntaxParsingContext ExprSequnceContext(SyntaxContext, SyntaxContextKind::Expr);
// Parse a unary expression.
ParserResult<Expr> Primary =
parseExprSequenceElement(Message, isExprBasic);
auto expr = Primary.get();
// If we saw no operators, don't build a sequence.
return makeParserResult(expr);
}
ParserResult<Expr> Parser::parseExprSequenceElement(Diag<> message,
bool isExprBasic) {
SyntaxParsingContext ElementContext(SyntaxContext,
SyntaxContextKind::Expr);
return parseExprUnary(message, isExprBasic);
}
parseExprElement
// ParseExpr.cpp
ParserResult<Expr> Parser::parseExprUnary(Diag<> Message, bool isExprBasic) {
SyntaxParsingContext UnaryContext(SyntaxContext, SyntaxContextKind::Expr);
return parseExprPostfix(Message, isExprBasic);
}
ParserResult<Expr> Parser::parseExprPostfix(Diag<> ID, bool isExprBasic) {
SyntaxParsingContext ExprContext(SyntaxContext, SyntaxContextKind::Expr);
return parseExprPrimary(ID, isExprBasic);
}
parseExprElement
// ParseExpr.cpp
ParserResult<Expr> Parser::parseExprUnary(Diag<> Message, bool isExprBasic) {
SyntaxParsingContext UnaryContext(SyntaxContext, SyntaxContextKind::Expr);
return parseExprPostfix(Message, isExprBasic);
}
ParserResult<Expr> Parser::parseExprPostfix(Diag<> ID, bool isExprBasic) {
SyntaxParsingContext ExprContext(SyntaxContext, SyntaxContextKind::Expr);
return parseExprPrimary(ID, isExprBasic);
}
parseIntegerLiteralExpr
// ParseExpr.cpp
ParserResult<Expr> Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) {
SyntaxParsingContext ExprContext(SyntaxContext, SyntaxContextKind::Expr);
switch (Tok.getKind()) {
case tok::integer_literal: {
StringRef Text = copyAndStripUnderscores(Tok.getText());
SourceLoc Loc = consumeToken(tok::integer_literal);
ExprContext.setCreateSyntax(SyntaxKind::IntegerLiteralExpr);
return makeParserResult(new (Context)
IntegerLiteralExpr(Text, Loc,
/*Implicit=*/false));
}
}
}
parseIntegerLiteralExpr
// ParseExpr.cpp
ParserResult<Expr> Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) {
SyntaxParsingContext ExprContext(SyntaxContext, SyntaxContextKind::Expr);
switch (Tok.getKind()) {
case tok::integer_literal: {
StringRef Text = copyAndStripUnderscores(Tok.getText());
SourceLoc Loc = consumeToken(tok::integer_literal);
ExprContext.setCreateSyntax(SyntaxKind::IntegerLiteralExpr);
return makeParserResult(new (Context)
IntegerLiteralExpr(Text, Loc,
/*Implicit=*/false));
}
}
}
parseIntegerLiteralExpr
// ParseExpr.cpp
ParserResult<Expr> Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) {
SyntaxParsingContext ExprContext(SyntaxContext, SyntaxContextKind::Expr);
switch (Tok.getKind()) {
case tok::integer_literal: {
StringRef Text = copyAndStripUnderscores(Tok.getText());
SourceLoc Loc = consumeToken(tok::integer_literal);
ExprContext.setCreateSyntax(SyntaxKind::IntegerLiteralExpr);
return makeParserResult(new (Context)
IntegerLiteralExpr(Text, Loc,
/*Implicit=*/false));
}
}
}
parseIntegerLiteralExpr
// ParseExpr.cpp
ParserResult<Expr> Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) {
SyntaxParsingContext ExprContext(SyntaxContext, SyntaxContextKind::Expr);
switch (Tok.getKind()) {
case tok::integer_literal: {
StringRef Text = copyAndStripUnderscores(Tok.getText());
SourceLoc Loc = consumeToken(tok::integer_literal);
ExprContext.setCreateSyntax(SyntaxKind::IntegerLiteralExpr);
return makeParserResult(new (Context)
IntegerLiteralExpr(Text, Loc,
/*Implicit=*/false));
}
}
}
parseExprSequence
// ParseExpr.cpp
ParserResult<Expr> Parser::parseExprSequence(Diag<> Message,
bool isExprBasic,
bool isForConditionalDirective) {
SyntaxParsingContext ExprSequnceContext(SyntaxContext, SyntaxContextKind::Expr);
// Parse a unary expression.
ParserResult<Expr> Primary =
parseExprSequenceElement(Message, isExprBasic);
auto expr = Primary.get();
// If we saw no operators, don't build a sequence.
return makeParserResult(expr);
}
ParserResult<Expr> Parser::parseExprSequenceElement(Diag<> message,
bool isExprBasic) {
SyntaxParsingContext ElementContext(SyntaxContext,
SyntaxContextKind::Expr);
return parseExprUnary(message, isExprBasic);
}
parseBraceItems
// ParseStmt.cpp
ParserStatus Parser::parseBraceItems(SmallVectorImpl<ASTNode> &Entries,
BraceItemListKind Kind,
BraceItemListKind ConditionalBlockKind) {
SyntaxParsingContext ItemListContext(SyntaxContext,
SyntaxKind::CodeBlockItemList);
auto *TLCD = new (Context) TopLevelCodeDecl(CurDeclContext);
ContextChange CC(*this, TLCD, &State->getTopLevelContext());
ParserStatus BraceItemsStatus;
ParserStatus Status = parseExprOrStmt(Result);
BraceItemsStatus |= Status;
auto Brace = BraceStmt::create(Context, Result.getStartLoc(),
Result, Result.getEndLoc());
TLCD->setBody(Brace);
Entries.push_back(TLCD);
return BraceItemsStatus;
}
parseTopLevel
// ParseDecl.cpp
bool Parser::parseTopLevel() {
SF.ASTStage = SourceFile::Parsing;
parseBraceItems(Items,
allowTopLevelCode() ? BraceItemListKind::TopLevelCode
: BraceItemListKind::TopLevelLibrary);
// Add newly parsed decls to the module.
SmallVector<ASTNode, 128> Items;
for (auto Item : Items)
if (auto *D = Item.dyn_cast<Decl*>())
SF.Decls.push_back(D);
// Note that the source file is fully parsed and verify it.
SF.ASTStage = SourceFile::Parsed;
verify(SF);
// If we are done parsing the whole file, finalize the token receiver.
if (Tok.is(tok::eof)) {
SyntaxContext->addToken(Tok, LeadingTrivia, TrailingTrivia);
TokReceiver->finalize();
}
}
parseTopLevel
// ParseDecl.cpp
bool Parser::parseTopLevel() {
SF.ASTStage = SourceFile::Parsing;
parseBraceItems(Items,
allowTopLevelCode() ? BraceItemListKind::TopLevelCode
: BraceItemListKind::TopLevelLibrary);
// Add newly parsed decls to the module.
SmallVector<ASTNode, 128> Items;
for (auto Item : Items)
if (auto *D = Item.dyn_cast<Decl*>())
SF.Decls.push_back(D);
// Note that the source file is fully parsed and verify it.
SF.ASTStage = SourceFile::Parsed;
verify(SF);
// If we are done parsing the whole file, finalize the token receiver.
if (Tok.is(tok::eof)) {
SyntaxContext->addToken(Tok, LeadingTrivia, TrailingTrivia);
TokReceiver->finalize();
}
}
parseTopLevel
// ParseDecl.cpp
bool Parser::parseTopLevel() {
SF.ASTStage = SourceFile::Parsing;
parseBraceItems(Items,
allowTopLevelCode() ? BraceItemListKind::TopLevelCode
: BraceItemListKind::TopLevelLibrary);
// Add newly parsed decls to the module.
SmallVector<ASTNode, 128> Items;
for (auto Item : Items)
if (auto *D = Item.dyn_cast<Decl*>())
SF.Decls.push_back(D);
// Note that the source file is fully parsed and verify it.
SF.ASTStage = SourceFile::Parsed;
verify(SF);
// If we are done parsing the whole file, finalize the token receiver.
if (Tok.is(tok::eof)) {
SyntaxContext->addToken(Tok, LeadingTrivia, TrailingTrivia);
TokReceiver->finalize();
}
}
Recap
→ Syntax Tree is created by SyntaxParsingContext
Syntax Tree
parseExprParen() {
SyntaxParsingContext LocalCtxt(SyntaxKind::ParenExpr, SyntaxContext);
consumeToken(tok::l_paren) // In consumeToken(), a RawTokenSyntax is
// added to the context.
parseExpr(); // On returning from parseExpr(), a Expr Syntax node is
// created and added to the context.
consumeToken(tok::r_paren)
// Now the context holds { '(' Expr ')' }.
// From these parts, it creates ParenExpr node and add it to the parent.
}
Recap
→ Syntax Tree is created by SyntaxParsingContext
→ AST is produced by SF.Decls
AST
bool Parser::parseTopLevel() {
// Parse the body of the file.
SmallVector<ASTNode, 128> Items;
// Parse body
// Add newly parsed decls to the module.
for (auto Item : Items)
if (auto *D = Item.dyn_cast<Decl*>())
SF.Decls.push_back(D);
}
How compiler emits
syntax?
swift -frontend -emit-syntax sample.swift
emit-syntax
// FrontendTool.cpp
static bool emitSyntax(SourceFile *SF, LangOptions &LangOpts,
SourceManager &SM, StringRef OutputFilename) {
auto os = getFileOutputStream(OutputFilename, SF->getASTContext());
if (!os) return true;
json::Output jsonOut(*os, /*UserInfo=*/{}, /*PrettyPrint=*/false);
auto Root = SF->getSyntaxRoot().getRaw(); // Syntax Tree
jsonOut << *Root;
*os << "n";
return false;
}
emit-syntax
// FrontendTool.cpp
static bool emitSyntax(SourceFile *SF, LangOptions &LangOpts,
SourceManager &SM, StringRef OutputFilename) {
auto os = getFileOutputStream(OutputFilename, SF->getASTContext());
if (!os) return true;
json::Output jsonOut(*os, /*UserInfo=*/{}, /*PrettyPrint=*/false);
auto Root = SF->getSyntaxRoot().getRaw(); // Syntax Tree
jsonOut << *Root;
*os << "n";
return false;
}
Output
// 1
- SourceFile
- CodeBlockItemList
- CodeBlockItem
- IntegerLiteralExpr
- integer_literal
How compiler dumps
AST?
swiftc -dump-ast sample.swift
dump-ast
// FrontendTool.cpp
static void dumpAST(CompilerInvocation &Invocation,
CompilerInstance &Instance) {
getPrimaryOrMainSourceFile(Invocation, Instance)->dump(llvm::outs());
}
void SourceFile::dump(llvm::raw_ostream &OS) const {
llvm::SaveAndRestore<bool> X(getASTContext().LangOpts.DebugConstraintSolver,
true);
PrintDecl(OS).visitSourceFile(*this);
llvm::errs() << 'n';
}
ASTDumper
// ASTDumper.cpp
void visitSourceFile(const SourceFile &SF) {
OS.indent(Indent);
PrintWithColorRAII(OS, ParenthesisColor) << '(';
PrintWithColorRAII(OS, ASTNodeColor) << "source_file ";
PrintWithColorRAII(OS, LocationColor) << '"' << SF.getFilename() << '"';
for (Decl *D : SF.Decls) { // AST
if (D->isImplicit())
continue;
OS << 'n';
printRec(D);
}
PrintWithColorRAII(OS, ParenthesisColor) << ')';
}
Output
// 1
- source_file
- top_level_code_decl
- brace_stmt
- integer_literal_expr type='Int' value=1
How do we optionally
generate libSyntax tree
while also producing
semantic AST?
Option
// LangOptions.h
/// A collection of options that affect the language dialect and
/// provide compiler debugging facilities.
class LangOptions {
/// Whether to parse syntax tree. If the syntax tree is built, the generated
/// AST may not be correct when syntax nodes are reused as part of
/// incrementals parsing.
bool BuildSyntaxTree = false;
}
// SyntaxParsingContext.h
class alignas(1 << SyntaxAlignInBits) SyntaxParsingContext {
// If false, context does nothing.
bool Enabled;
}
SyntaxParsingContext
// SyntaxParsingContext.cpp
/// Add Token with Trivia to the parts.
void SyntaxParsingContext::addToken(Token &Tok,
const ParsedTrivia &LeadingTrivia,
const ParsedTrivia &TrailingTrivia) {
if (!Enabled)
return;
...
}
ParsedRawSyntaxNode SyntaxParsingContext::finalizeRoot() {
if (!Enabled)
...
}
!
Recap
Recap
→ if Enabled, compiler creates Syntax Tree AND
produces AST
Recap
→ if Enabled, compiler creates Syntax Tree AND
produces AST
→ if not, compiler only produces AST
Goal
To have the Swift parser fully embrace libSyntax and
stop emitting the semantic AST
New pipeline
(Source) -> [Parser] -> (libSyntax) -+-> [ASTGen] -> (AST) -> [Sema] -> ...
| or
+-> [SwiftSyntax, ...]
BeneïŹts
BeneïŹts
→ Robust architecture
BeneïŹts
→ Robust architecture
→ SwiftSyntax parsing performance improvements
BeneïŹts
→ Robust architecture
→ SwiftSyntax parsing performance improvements
→ Enable future work for making the compiler
pipeline more suitable for interactive contexts
!!!
Initial PR
[Parser] Decouple the parser from AST creation (part
1)
apple/swift/pull/26403
libSyntax
(LibSyntax) -+-> [ASTGen] -> ...
or
(SwiftSyntax) -+-> [SwiftSyntax, ...]
OpaqueSyntaxNodeKind
// SyntaxParseActions.h
enum class OpaqueSyntaxNodeKind {
SwiftSyntax,
LibSyntax,
};
SyntaxParseActions
// SyntaxTreeCreator.h
// LibSyntax
class SyntaxTreeCreator: public SyntaxParseActions {...}
// libSwiftSyntaxParser.cpp
// SwiftSyntax
class CLibParseActions : public SyntaxParseActions {...}
HiddenLibSyntaxAction
// HiddenLibSyntaxAction.h
/// Holds an explicitly provided action and uses it to handle all function
/// calls. Also hides an implicit SyntaxTreeCreator and ensures libSyntax nodes
/// are always created. Provides an interface to map results of the explicitly
/// provided action to the hidden libSyntax action.
class HiddenLibSyntaxAction : public SyntaxParseActions {
struct Node {
OpaqueSyntaxNode ExplicitActionNode;
OpaqueSyntaxNode LibSyntaxNode;
...
};
// I assume this can be `CLibParseActions` for SwiftSyntax?
std::shared_ptr<SyntaxParseActions> ExplicitAction;
std::shared_ptr<SyntaxTreeCreator> LibSyntaxAction;
...
}
LibSyntaxGenerator
/// Generates libSyntax nodes either by looking them up using
/// HiddenLibSyntaxAction (based on provided OpaqueSyntaxNode) or by recording
/// them with ParsedRawSyntaxRecorder.
class LibSyntaxGenerator {
std::shared_ptr<HiddenLibSyntaxAction> Actions;
ParsedRawSyntaxRecorder Recorder;
...
}
ASTGen
// ASTGen.h
class ASTGen {
ASTContext &Context;
IntegerLiteralExpr *generate(syntax::IntegerLiteralExprSyntax &Expr);
}
IntegerLiteralExpr *ASTGen::generate(IntegerLiteralExprSyntax &Expr) {
TokenSyntax Digits = Expr.getDigits();
StringRef Text = copyAndStripUnderscores(Digits.getText());
SourceLoc Loc = topLoc();
return new (Context) IntegerLiteralExpr(Text, Loc);
}
parseExprAST
template <typename SyntaxNode>
ParserResult<Expr> Parser::parseExprAST() {
auto ParsedExpr = parseExprSyntax<SyntaxNode>();
SyntaxContext->addSyntax(ParsedExpr);
...
auto Expr = SyntaxContext->topNode<SyntaxNode>();
auto ExprAST = Generator.generate(Expr);
return makeParserResult(ExprAST);
}
Recap
Recap
→ libSyntax always create syntax tree
Recap
→ libSyntax always create syntax tree
→ ASTGen generates AST node from syntax tree
Summary
Summary
→ libSyntax integration is still WIP
Summary
→ libSyntax integration is still WIP
→ DeïŹnitely better architecture
Summary
→ libSyntax integration is still WIP
→ DeïŹnitely better architecture
→ Huge performance improvements for SwiftSyntax

Weitere Àhnliche Inhalte

Was ist angesagt?

Nodejs í”„ëĄœê·žëž˜ë° ch.3
Nodejs í”„ëĄœê·žëž˜ë° ch.3Nodejs í”„ëĄœê·žëž˜ë° ch.3
Nodejs í”„ëĄœê·žëž˜ë° ch.3HyeonSeok Choi
 
Seeking Clojure
Seeking ClojureSeeking Clojure
Seeking Clojurechrisriceuk
 
PHP7 is coming
PHP7 is comingPHP7 is coming
PHP7 is comingjulien pauli
 
Riding the Overflow - Then and Now
Riding the Overflow - Then and NowRiding the Overflow - Then and Now
Riding the Overflow - Then and NowMiroslav Stampar
 
Runtime Symbol Resolution
Runtime Symbol ResolutionRuntime Symbol Resolution
Runtime Symbol ResolutionKen Kawamoto
 
Modern Java Workshop
Modern Java WorkshopModern Java Workshop
Modern Java WorkshopSimon Ritter
 
Bioinformatics v2014 wim_vancriekinge
Bioinformatics v2014 wim_vancriekingeBioinformatics v2014 wim_vancriekinge
Bioinformatics v2014 wim_vancriekingeProf. Wim Van Criekinge
 
PHPcon Poland - Static Analysis of PHP Code – How the Heck did I write so man...
PHPcon Poland - Static Analysis of PHP Code – How the Heck did I write so man...PHPcon Poland - Static Analysis of PHP Code – How the Heck did I write so man...
PHPcon Poland - Static Analysis of PHP Code – How the Heck did I write so man...Rouven Weßling
 
Getting the Most From Modern Java
Getting the Most From Modern JavaGetting the Most From Modern Java
Getting the Most From Modern JavaSimon Ritter
 
Java Keeps Throttling Up!
Java Keeps Throttling Up!Java Keeps Throttling Up!
Java Keeps Throttling Up!José Paumard
 
Handling inline assembly in Clang and LLVM
Handling inline assembly in Clang and LLVMHandling inline assembly in Clang and LLVM
Handling inline assembly in Clang and LLVMMin-Yih Hsu
 
Rust Workshop - NITC FOSSMEET 2017
Rust Workshop - NITC FOSSMEET 2017 Rust Workshop - NITC FOSSMEET 2017
Rust Workshop - NITC FOSSMEET 2017 pramode_ce
 
Course lecture - An introduction to the Return Oriented Programming
Course lecture - An introduction to the Return Oriented ProgrammingCourse lecture - An introduction to the Return Oriented Programming
Course lecture - An introduction to the Return Oriented ProgrammingJonathan Salwan
 
How Functions Work
How Functions WorkHow Functions Work
How Functions WorkSaumil Shah
 

Was ist angesagt? (20)

Nodejs í”„ëĄœê·žëž˜ë° ch.3
Nodejs í”„ëĄœê·žëž˜ë° ch.3Nodejs í”„ëĄœê·žëž˜ë° ch.3
Nodejs í”„ëĄœê·žëž˜ë° ch.3
 
Seeking Clojure
Seeking ClojureSeeking Clojure
Seeking Clojure
 
PHP7 is coming
PHP7 is comingPHP7 is coming
PHP7 is coming
 
Riding the Overflow - Then and Now
Riding the Overflow - Then and NowRiding the Overflow - Then and Now
Riding the Overflow - Then and Now
 
Smashing the Buffer
Smashing the BufferSmashing the Buffer
Smashing the Buffer
 
FreeRTOS
FreeRTOSFreeRTOS
FreeRTOS
 
Runtime Symbol Resolution
Runtime Symbol ResolutionRuntime Symbol Resolution
Runtime Symbol Resolution
 
Modern Java Workshop
Modern Java WorkshopModern Java Workshop
Modern Java Workshop
 
Bioinformatics v2014 wim_vancriekinge
Bioinformatics v2014 wim_vancriekingeBioinformatics v2014 wim_vancriekinge
Bioinformatics v2014 wim_vancriekinge
 
System Programming and Administration
System Programming and AdministrationSystem Programming and Administration
System Programming and Administration
 
Advance ROP Attacks
Advance ROP AttacksAdvance ROP Attacks
Advance ROP Attacks
 
Java Class Design
Java Class DesignJava Class Design
Java Class Design
 
PHPcon Poland - Static Analysis of PHP Code – How the Heck did I write so man...
PHPcon Poland - Static Analysis of PHP Code – How the Heck did I write so man...PHPcon Poland - Static Analysis of PHP Code – How the Heck did I write so man...
PHPcon Poland - Static Analysis of PHP Code – How the Heck did I write so man...
 
Getting the Most From Modern Java
Getting the Most From Modern JavaGetting the Most From Modern Java
Getting the Most From Modern Java
 
Shell Script Tutorial
Shell Script TutorialShell Script Tutorial
Shell Script Tutorial
 
Java Keeps Throttling Up!
Java Keeps Throttling Up!Java Keeps Throttling Up!
Java Keeps Throttling Up!
 
Handling inline assembly in Clang and LLVM
Handling inline assembly in Clang and LLVMHandling inline assembly in Clang and LLVM
Handling inline assembly in Clang and LLVM
 
Rust Workshop - NITC FOSSMEET 2017
Rust Workshop - NITC FOSSMEET 2017 Rust Workshop - NITC FOSSMEET 2017
Rust Workshop - NITC FOSSMEET 2017
 
Course lecture - An introduction to the Return Oriented Programming
Course lecture - An introduction to the Return Oriented ProgrammingCourse lecture - An introduction to the Return Oriented Programming
Course lecture - An introduction to the Return Oriented Programming
 
How Functions Work
How Functions WorkHow Functions Work
How Functions Work
 

Ähnlich wie [Deprecated] Integrating libSyntax into the compiler pipeline

Binary Studio Academy PRO: ANTLR course by Alexander Vasiltsov (lesson 3)
Binary Studio Academy PRO: ANTLR course by Alexander Vasiltsov (lesson 3)Binary Studio Academy PRO: ANTLR course by Alexander Vasiltsov (lesson 3)
Binary Studio Academy PRO: ANTLR course by Alexander Vasiltsov (lesson 3)Binary Studio
 
Generating parsers using Ragel and Lemon
Generating parsers using Ragel and LemonGenerating parsers using Ragel and Lemon
Generating parsers using Ragel and LemonTristan Penman
 
finalprojtemplatev5finalprojtemplate.gitignore# Ignore the b
finalprojtemplatev5finalprojtemplate.gitignore# Ignore the bfinalprojtemplatev5finalprojtemplate.gitignore# Ignore the b
finalprojtemplatev5finalprojtemplate.gitignore# Ignore the bChereCheek752
 
General Functions
General FunctionsGeneral Functions
General FunctionsBabuDevanandam
 
Summary of C++17 features
Summary of C++17 featuresSummary of C++17 features
Summary of C++17 featuresBartlomiej Filipek
 
The Swift Compiler and Standard Library
The Swift Compiler and Standard LibraryThe Swift Compiler and Standard Library
The Swift Compiler and Standard LibrarySantosh Rajan
 
Don't Be Afraid of Abstract Syntax Trees
Don't Be Afraid of Abstract Syntax TreesDon't Be Afraid of Abstract Syntax Trees
Don't Be Afraid of Abstract Syntax TreesJamund Ferguson
 
Integrating libSyntax into the compiler pipeline
Integrating libSyntax into the compiler pipelineIntegrating libSyntax into the compiler pipeline
Integrating libSyntax into the compiler pipelineYusuke Kita
 
Ast transformation
Ast transformationAst transformation
Ast transformationGagan Agrawal
 
Sax Dom Tutorial
Sax Dom TutorialSax Dom Tutorial
Sax Dom Tutorialvikram singh
 
Apidays Paris 2023 - Forget TypeScript, Choose Rust to build Robust, Fast and...
Apidays Paris 2023 - Forget TypeScript, Choose Rust to build Robust, Fast and...Apidays Paris 2023 - Forget TypeScript, Choose Rust to build Robust, Fast and...
Apidays Paris 2023 - Forget TypeScript, Choose Rust to build Robust, Fast and...apidays
 
Scaladroids: Developing Android Apps with Scala
Scaladroids: Developing Android Apps with ScalaScaladroids: Developing Android Apps with Scala
Scaladroids: Developing Android Apps with ScalaOstap Andrusiv
 
From HelloWorld to Configurable and Reusable Apache Spark Applications in Sca...
From HelloWorld to Configurable and Reusable Apache Spark Applications in Sca...From HelloWorld to Configurable and Reusable Apache Spark Applications in Sca...
From HelloWorld to Configurable and Reusable Apache Spark Applications in Sca...Databricks
 
introduction_to_antlr 3.ppt
introduction_to_antlr 3.pptintroduction_to_antlr 3.ppt
introduction_to_antlr 3.pptTathagatoBose
 
IQPC Canada XML 2001: How to Use XML Parsing to Enhance Electronic Communication
IQPC Canada XML 2001: How to Use XML Parsing to Enhance Electronic CommunicationIQPC Canada XML 2001: How to Use XML Parsing to Enhance Electronic Communication
IQPC Canada XML 2001: How to Use XML Parsing to Enhance Electronic CommunicationTed Leung
 

Ähnlich wie [Deprecated] Integrating libSyntax into the compiler pipeline (20)

Binary Studio Academy PRO: ANTLR course by Alexander Vasiltsov (lesson 3)
Binary Studio Academy PRO: ANTLR course by Alexander Vasiltsov (lesson 3)Binary Studio Academy PRO: ANTLR course by Alexander Vasiltsov (lesson 3)
Binary Studio Academy PRO: ANTLR course by Alexander Vasiltsov (lesson 3)
 
Antlr
AntlrAntlr
Antlr
 
Generating parsers using Ragel and Lemon
Generating parsers using Ragel and LemonGenerating parsers using Ragel and Lemon
Generating parsers using Ragel and Lemon
 
finalprojtemplatev5finalprojtemplate.gitignore# Ignore the b
finalprojtemplatev5finalprojtemplate.gitignore# Ignore the bfinalprojtemplatev5finalprojtemplate.gitignore# Ignore the b
finalprojtemplatev5finalprojtemplate.gitignore# Ignore the b
 
srgoc
srgocsrgoc
srgoc
 
General Functions
General FunctionsGeneral Functions
General Functions
 
Summary of C++17 features
Summary of C++17 featuresSummary of C++17 features
Summary of C++17 features
 
The Swift Compiler and Standard Library
The Swift Compiler and Standard LibraryThe Swift Compiler and Standard Library
The Swift Compiler and Standard Library
 
Solr @ Etsy - Apache Lucene Eurocon
Solr @ Etsy - Apache Lucene EuroconSolr @ Etsy - Apache Lucene Eurocon
Solr @ Etsy - Apache Lucene Eurocon
 
Don't Be Afraid of Abstract Syntax Trees
Don't Be Afraid of Abstract Syntax TreesDon't Be Afraid of Abstract Syntax Trees
Don't Be Afraid of Abstract Syntax Trees
 
Integrating libSyntax into the compiler pipeline
Integrating libSyntax into the compiler pipelineIntegrating libSyntax into the compiler pipeline
Integrating libSyntax into the compiler pipeline
 
Ast transformation
Ast transformationAst transformation
Ast transformation
 
Sax Dom Tutorial
Sax Dom TutorialSax Dom Tutorial
Sax Dom Tutorial
 
Apidays Paris 2023 - Forget TypeScript, Choose Rust to build Robust, Fast and...
Apidays Paris 2023 - Forget TypeScript, Choose Rust to build Robust, Fast and...Apidays Paris 2023 - Forget TypeScript, Choose Rust to build Robust, Fast and...
Apidays Paris 2023 - Forget TypeScript, Choose Rust to build Robust, Fast and...
 
Scaladroids: Developing Android Apps with Scala
Scaladroids: Developing Android Apps with ScalaScaladroids: Developing Android Apps with Scala
Scaladroids: Developing Android Apps with Scala
 
From HelloWorld to Configurable and Reusable Apache Spark Applications in Sca...
From HelloWorld to Configurable and Reusable Apache Spark Applications in Sca...From HelloWorld to Configurable and Reusable Apache Spark Applications in Sca...
From HelloWorld to Configurable and Reusable Apache Spark Applications in Sca...
 
Gunosy.go #4 go
Gunosy.go #4 goGunosy.go #4 go
Gunosy.go #4 go
 
introduction_to_antlr 3.ppt
introduction_to_antlr 3.pptintroduction_to_antlr 3.ppt
introduction_to_antlr 3.ppt
 
Extensible markup language attacks
Extensible markup language attacksExtensible markup language attacks
Extensible markup language attacks
 
IQPC Canada XML 2001: How to Use XML Parsing to Enhance Electronic Communication
IQPC Canada XML 2001: How to Use XML Parsing to Enhance Electronic CommunicationIQPC Canada XML 2001: How to Use XML Parsing to Enhance Electronic Communication
IQPC Canada XML 2001: How to Use XML Parsing to Enhance Electronic Communication
 

Mehr von Yusuke Kita

Making your own tool using SwiftSyntax
Making your own tool using SwiftSyntaxMaking your own tool using SwiftSyntax
Making your own tool using SwiftSyntaxYusuke Kita
 
Creating your own Bitrise step
Creating your own Bitrise stepCreating your own Bitrise step
Creating your own Bitrise stepYusuke Kita
 
Introducing swift-format
Introducing swift-formatIntroducing swift-format
Introducing swift-formatYusuke Kita
 
Unidirectional Data Flow Through SwiftUI
Unidirectional Data Flow Through SwiftUIUnidirectional Data Flow Through SwiftUI
Unidirectional Data Flow Through SwiftUIYusuke Kita
 
Open Source Swift Workshop
Open Source Swift WorkshopOpen Source Swift Workshop
Open Source Swift WorkshopYusuke Kita
 
Contributing to Swift Compiler
Contributing to Swift CompilerContributing to Swift Compiler
Contributing to Swift CompilerYusuke Kita
 
Writing a compiler in go
Writing a compiler in goWriting a compiler in go
Writing a compiler in goYusuke Kita
 
Writing an interpreter in swift
Writing an interpreter in swiftWriting an interpreter in swift
Writing an interpreter in swiftYusuke Kita
 
SIL Optimizations - AllocBoxToStack
SIL Optimizations - AllocBoxToStackSIL Optimizations - AllocBoxToStack
SIL Optimizations - AllocBoxToStackYusuke Kita
 
SIL for First Time Learners
SIL for First Time LearnersSIL for First Time Learners
SIL for First Time LearnersYusuke Kita
 
var, let in SIL
var, let in SILvar, let in SIL
var, let in SILYusuke Kita
 
SIL for First Time Leaners LT
SIL for First Time Leaners LTSIL for First Time Leaners LT
SIL for First Time Leaners LTYusuke Kita
 
How to try! Swift
How to try! SwiftHow to try! Swift
How to try! SwiftYusuke Kita
 
SIL for the first time
SIL for the first timeSIL for the first time
SIL for the first timeYusuke Kita
 
Introducing protobuf in Swift
Introducing protobuf in SwiftIntroducing protobuf in Swift
Introducing protobuf in SwiftYusuke Kita
 
Type-safe Web APIs with Protocol Buffers in Swift at AltConf
Type-safe Web APIs with Protocol Buffers in Swift at AltConfType-safe Web APIs with Protocol Buffers in Swift at AltConf
Type-safe Web APIs with Protocol Buffers in Swift at AltConfYusuke Kita
 
Type-safe Web APIs with Protocol Buffers in Swift at iOSCon
Type-safe Web APIs with Protocol Buffers in Swift at iOSConType-safe Web APIs with Protocol Buffers in Swift at iOSCon
Type-safe Web APIs with Protocol Buffers in Swift at iOSConYusuke Kita
 
Swift core
Swift coreSwift core
Swift coreYusuke Kita
 
SwiftCoreずFoundationをèȘ­ă‚“ă§ăżăŸ
SwiftCoreずFoundationをèȘ­ă‚“ă§ăżăŸSwiftCoreずFoundationをèȘ­ă‚“ă§ăżăŸ
SwiftCoreずFoundationをèȘ­ă‚“ă§ăżăŸYusuke Kita
 
Search APIs & Universal Links
Search APIs & Universal LinksSearch APIs & Universal Links
Search APIs & Universal LinksYusuke Kita
 

Mehr von Yusuke Kita (20)

Making your own tool using SwiftSyntax
Making your own tool using SwiftSyntaxMaking your own tool using SwiftSyntax
Making your own tool using SwiftSyntax
 
Creating your own Bitrise step
Creating your own Bitrise stepCreating your own Bitrise step
Creating your own Bitrise step
 
Introducing swift-format
Introducing swift-formatIntroducing swift-format
Introducing swift-format
 
Unidirectional Data Flow Through SwiftUI
Unidirectional Data Flow Through SwiftUIUnidirectional Data Flow Through SwiftUI
Unidirectional Data Flow Through SwiftUI
 
Open Source Swift Workshop
Open Source Swift WorkshopOpen Source Swift Workshop
Open Source Swift Workshop
 
Contributing to Swift Compiler
Contributing to Swift CompilerContributing to Swift Compiler
Contributing to Swift Compiler
 
Writing a compiler in go
Writing a compiler in goWriting a compiler in go
Writing a compiler in go
 
Writing an interpreter in swift
Writing an interpreter in swiftWriting an interpreter in swift
Writing an interpreter in swift
 
SIL Optimizations - AllocBoxToStack
SIL Optimizations - AllocBoxToStackSIL Optimizations - AllocBoxToStack
SIL Optimizations - AllocBoxToStack
 
SIL for First Time Learners
SIL for First Time LearnersSIL for First Time Learners
SIL for First Time Learners
 
var, let in SIL
var, let in SILvar, let in SIL
var, let in SIL
 
SIL for First Time Leaners LT
SIL for First Time Leaners LTSIL for First Time Leaners LT
SIL for First Time Leaners LT
 
How to try! Swift
How to try! SwiftHow to try! Swift
How to try! Swift
 
SIL for the first time
SIL for the first timeSIL for the first time
SIL for the first time
 
Introducing protobuf in Swift
Introducing protobuf in SwiftIntroducing protobuf in Swift
Introducing protobuf in Swift
 
Type-safe Web APIs with Protocol Buffers in Swift at AltConf
Type-safe Web APIs with Protocol Buffers in Swift at AltConfType-safe Web APIs with Protocol Buffers in Swift at AltConf
Type-safe Web APIs with Protocol Buffers in Swift at AltConf
 
Type-safe Web APIs with Protocol Buffers in Swift at iOSCon
Type-safe Web APIs with Protocol Buffers in Swift at iOSConType-safe Web APIs with Protocol Buffers in Swift at iOSCon
Type-safe Web APIs with Protocol Buffers in Swift at iOSCon
 
Swift core
Swift coreSwift core
Swift core
 
SwiftCoreずFoundationをèȘ­ă‚“ă§ăżăŸ
SwiftCoreずFoundationをèȘ­ă‚“ă§ăżăŸSwiftCoreずFoundationをèȘ­ă‚“ă§ăżăŸ
SwiftCoreずFoundationをèȘ­ă‚“ă§ăżăŸ
 
Search APIs & Universal Links
Search APIs & Universal LinksSearch APIs & Universal Links
Search APIs & Universal Links
 

KĂŒrzlich hochgeladen

Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024The Digital Insurer
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 

KĂŒrzlich hochgeladen (20)

Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 

[Deprecated] Integrating libSyntax into the compiler pipeline

  • 1. Integrating libSyntax into the compiler pipeline @kitasuke
  • 2. Integrating libSyntax into the compiler pipeline
  • 3. Problem Semantic AST is completely ignored and wasted when SwiftSyntax invokes the Swift parser to get the libSyntax tree for some source text.
  • 4. Existing pipeline (Source) -> [Parser] -+-> (AST) -> [Sema] -> ... | and +-> (libSyntax) -> [SwiftSyntax, ...]
  • 10. Parser → Lexer → SyntaxParsingContext → SyntaxParseActions → Parser
  • 11. Parser → Lexer → SyntaxParsingContext → SyntaxParseActions → Parser → ParseDecl/Stmt/Expr etc
  • 12. Parser → Lexer → SyntaxParsingContext → SyntaxParseActions → Parser → ParseDecl/Stmt/Expr etc → and more
  • 13. Lexer class Lexer { /// Lex a token. If c TriviaRetentionMode is c WithTrivia, passed pointers /// to trivias are populated. void lex(Token &Result, ParsedTrivia &LeadingTriviaResult, ParsedTrivia &TrailingTriviaResult); void lexImpl(); void lexHash(); void lexIdentifier(); void lexOperatorIdentifier(); void lexNumber(); void lexTrivia(ParsedTrivia &T, bool IsForTrailingTrivia); void lexStringLiteral(unsigned CustomDelimiterLen = 0); ... }
  • 14. SyntaxParsingContext class alignas(1 << SyntaxAlignInBits) SyntaxParsingContext { RootContextData *RootData; // If false, context does nothing. bool Enabled; void addRawSyntax(ParsedRawSyntaxNode Raw); void addToken(Token &Tok, const ParsedTrivia &LeadingTrivia, const ParsedTrivia &TrailingTrivia); void addSyntax(ParsedSyntax Node); void setCreateSyntax(SyntaxKind kind); /// Explicitly finalizing syntax tree creation. /// This function will be called during the destroying of a root syntax /// parsing context. However, we can explicitly call this function to get /// the syntax tree before closing the root context. ParsedRawSyntaxNode finalizeRoot(); ... }
  • 15. SyntaxParseActions class SyntaxParseActions { virtual OpaqueSyntaxNode recordToken(tok tokenKind, ArrayRef<ParsedTriviaPiece> leadingTrivia, ArrayRef<ParsedTriviaPiece> trailingTrivia, CharSourceRange range) = 0; /// Record a missing token. c loc can be invalid or an approximate location /// of where the token would be if not missing. virtual OpaqueSyntaxNode recordMissingToken(tok tokenKind, SourceLoc loc) = 0; /// The provided c elements are an exact layout appropriate for the syntax /// c kind. Missing optional elements are represented with a null /// OpaqueSyntaxNode object. virtual OpaqueSyntaxNode recordRawSyntax(syntax::SyntaxKind kind, ArrayRef<OpaqueSyntaxNode> elements, CharSourceRange range) = 0; }
  • 16. Parser class Parser { SourceFile &SF; Lexer *L; ASTContext &Context; SyntaxParsingContext *SyntaxContext; Token Tok; ConsumeTokenReceiver *TokReceiver; ... /// Calling this function to finalize libSyntax tree creation without destroying /// the parser instance. ParsedRawSyntaxNode finalizeSyntaxTree() { assert(Tok.is(tok::eof) && "not done parsing yet"); return SyntaxContext->finalizeRoot(); } bool parseTopLevel(); }
  • 17. SourceFile class SourceFile final : public FileUnit { /// The list of top-level declarations in the source file. std::vector<Decl*> Decls; SyntaxParsingCache *SyntaxParsingCache = nullptr; ASTStage_t ASTStage = Parsing; virtual bool walk(ASTWalker &walker) override; void dump(raw_ostream &os) const; bool shouldBuildSyntaxTree() const; syntax::SourceFileSyntax getSyntaxRoot() const; void setSyntaxRoot(syntax::SourceFileSyntax &&Root); std::unique_ptr<SourceFileSyntaxInfo> SyntaxInfo; }
  • 18. ParseDecl/Stmt/Expr bool Parser::parseTopLevel(); ParserStatus Parser::parseBraceItems(SmallVectorImpl<ASTNode> &Entries, BraceItemListKind Kind, BraceItemListKind ConditionalBlockKind); ParserStatus Parser::parseExprOrStmt(ASTNode &Result); ParserResult<Expr> parseExpr(Diag<> ID); ParserResult<Expr> Parser::parseExprStringLiteral(); ...
  • 25. Syntax /// The main handle for syntax nodes - subclasses contain all public /// structured editing APIs. /// /// This opaque structure holds two pieces of data: a strong reference to a /// root node and a weak reference to the node itself. The node of interest can /// be weakly held because the data nodes contain strong references to /// their children. class Syntax { /// A strong reference to the root node of the tree in which this piece of /// syntax resides. const RC<SyntaxData> Root; /// A raw pointer to the data representing this syntax node. /// This is mutable for being able to set cached child members, which are /// lazily created. mutable const SyntaxData *Data; }
  • 26. SyntaxData /// The class for holding parented syntax. /// /// This structure should not contain significant public /// API or internal modification API. /// /// This is only for holding a strong reference to the RawSyntax, a weak /// reference to the parent, and, in subclasses, lazily created strong /// references to non-terminal child nodes. class SyntaxData final { using RootDataPair = std::pair<RC<SyntaxData>, RC<SyntaxData>>; /// The shared raw syntax representing this syntax data node. const RC<RawSyntax> Raw; /// The parent of this syntax. const SyntaxData *Parent; /// The index into the parent's child layout. const CursorIndex IndexInParent; }
  • 27. RawSyntax /// RawSyntax - the strictly immutable, shared backing nodes for all syntax. /// /// This is implementation detail - do not expose it in public API. class RawSyntax final { /// An ID of this node that is stable across incremental parses SyntaxNodeId NodeId; union { uint64_t OpaqueBits; struct {...} Common; struct {...} Layout; struct {...} Token; } Bits; }
  • 29. AST
  • 33. AST → ASTContext → ASTDumper → Decl/Stmt/Expr etc → and more
  • 34. ASTContext /// ASTContext - This object creates and owns the AST objects. /// However, this class does more than just maintain context within an AST. /// It is the closest thing to thread-local or compile-local storage in this /// code base. Why? SourceKit uses this code with multiple threads per Unix /// process. Each thread processes a different source file. Each thread has its /// own instance of ASTContext, and that instance persists for the duration of /// the thread, throughout all phases of the compilation. (The name "ASTContext" /// is a bit of a misnomer here.) Why not use thread-local storage? This code /// may use DispatchQueues and pthread-style TLS won't work with code that uses /// DispatchQueues. Summary: if you think you need a global or static variable, /// you probably need to put it here instead. class ASTContext final {...}
  • 35. ASTDumper class PrintPattern : public PatternVisitor<PrintPattern> {...} class PrintDecl : public DeclVisitor<PrintDecl> {...} class PrintStmt : public StmtVisitor<PrintStmt> {...} class PrintExpr : public ExprVisitor<PrintExpr> {...} class PrintType : public TypeVisitor<PrintType, void, StringRef> {...}
  • 36. Decl/Stmt/Expr /// TopLevelCodeDecl - This decl is used as a container for top-level /// expressions and statements in the main module. It is always a direct /// child of a SourceFile. class TopLevelCodeDecl : public DeclContext, public Decl {...} /// BraceStmt - A brace enclosed sequence of expressions, stmts, or decls, like /// { var x = 10; print(10) }. class BraceStmt final : public Stmt, private llvm::TrailingObjects<BraceStmt, ASTNode> {...} /// Integer literal with a '+' or '-' sign, like '+4' or '- 2'. class IntegerLiteralExpr : public NumberLiteralExpr {...}
  • 37. Let's look into how swift source is parsed
  • 39. parseTopLevel // ParseDecl.cpp bool Parser::parseTopLevel() { SF.ASTStage = SourceFile::Parsing; parseBraceItems(Items, allowTopLevelCode() ? BraceItemListKind::TopLevelCode : BraceItemListKind::TopLevelLibrary); // Add newly parsed decls to the module. SmallVector<ASTNode, 128> Items; for (auto Item : Items) if (auto *D = Item.dyn_cast<Decl*>()) SF.Decls.push_back(D); // Note that the source file is fully parsed and verify it. SF.ASTStage = SourceFile::Parsed; verify(SF); // If we are done parsing the whole file, finalize the token receiver. if (Tok.is(tok::eof)) { SyntaxContext->addToken(Tok, LeadingTrivia, TrailingTrivia); TokReceiver->finalize(); } }
  • 40. parseTopLevel // ParseDecl.cpp bool Parser::parseTopLevel() { SF.ASTStage = SourceFile::Parsing; parseBraceItems(Items, allowTopLevelCode() ? BraceItemListKind::TopLevelCode : BraceItemListKind::TopLevelLibrary); // Add newly parsed decls to the module. SmallVector<ASTNode, 128> Items; for (auto Item : Items) if (auto *D = Item.dyn_cast<Decl*>()) SF.Decls.push_back(D); // Note that the source file is fully parsed and verify it. SF.ASTStage = SourceFile::Parsed; verify(SF); // If we are done parsing the whole file, finalize the token receiver. if (Tok.is(tok::eof)) { SyntaxContext->addToken(Tok, LeadingTrivia, TrailingTrivia); TokReceiver->finalize(); } }
  • 41. parseBraceItems // ParseStmt.cpp ParserStatus Parser::parseBraceItems(SmallVectorImpl<ASTNode> &Entries, BraceItemListKind Kind, BraceItemListKind ConditionalBlockKind) { SyntaxParsingContext ItemListContext(SyntaxContext, SyntaxKind::CodeBlockItemList); auto *TLCD = new (Context) TopLevelCodeDecl(CurDeclContext); ContextChange CC(*this, TLCD, &State->getTopLevelContext()); ParserStatus BraceItemsStatus; ParserStatus Status = parseExprOrStmt(Result); BraceItemsStatus |= Status; auto Brace = BraceStmt::create(Context, Result.getStartLoc(), Result, Result.getEndLoc()); TLCD->setBody(Brace); Entries.push_back(TLCD); return BraceItemsStatus; }
  • 42. parseBraceItems // ParseStmt.cpp ParserStatus Parser::parseBraceItems(SmallVectorImpl<ASTNode> &Entries, BraceItemListKind Kind, BraceItemListKind ConditionalBlockKind) { SyntaxParsingContext ItemListContext(SyntaxContext, SyntaxKind::CodeBlockItemList); auto *TLCD = new (Context) TopLevelCodeDecl(CurDeclContext); ContextChange CC(*this, TLCD, &State->getTopLevelContext()); ParserStatus BraceItemsStatus; ParserStatus Status = parseExprOrStmt(Result); BraceItemsStatus |= Status; auto Brace = BraceStmt::create(Context, Result.getStartLoc(), Result, Result.getEndLoc()); TLCD->setBody(Brace); Entries.push_back(TLCD); return BraceItemsStatus; }
  • 43. parseBraceItems // ParseStmt.cpp ParserStatus Parser::parseBraceItems(SmallVectorImpl<ASTNode> &Entries, BraceItemListKind Kind, BraceItemListKind ConditionalBlockKind) { SyntaxParsingContext ItemListContext(SyntaxContext, SyntaxKind::CodeBlockItemList); auto *TLCD = new (Context) TopLevelCodeDecl(CurDeclContext); ContextChange CC(*this, TLCD, &State->getTopLevelContext()); ParserStatus BraceItemsStatus; ParserStatus Status = parseExprOrStmt(Result); BraceItemsStatus |= Status; auto Brace = BraceStmt::create(Context, Result.getStartLoc(), Result, Result.getEndLoc()); TLCD->setBody(Brace); Entries.push_back(TLCD); return BraceItemsStatus; }
  • 44. parseExpr // ParseStmt.cpp ParserStatus Parser::parseExprOrStmt(ASTNode &Result) { ParserResult<Expr> ResultExpr = parseExpr(diag::expected_expr); return ResultExpr; } // ParseExpr.cpp ParserResult<Expr> parseExpr(Diag<> ID) { return parseExprImpl(ID, /*isExprBasic=*/false); } ParserResult<Expr> Parser::parseExprImpl(Diag<> Message, bool isExprBasic) { SyntaxParsingContext ExprParsingContext(SyntaxContext, SyntaxContextKind::Expr); auto expr = parseExprSequence(Message, isExprBasic, /*forConditionalDirective*/false); return makeParserResult(expr.get()); }
  • 45. parseExpr // ParseStmt.cpp ParserStatus Parser::parseExprOrStmt(ASTNode &Result) { ParserResult<Expr> ResultExpr = parseExpr(diag::expected_expr); return ResultExpr; } // ParseExpr.cpp ParserResult<Expr> parseExpr(Diag<> ID) { return parseExprImpl(ID, /*isExprBasic=*/false); } ParserResult<Expr> Parser::parseExprImpl(Diag<> Message, bool isExprBasic) { SyntaxParsingContext ExprParsingContext(SyntaxContext, SyntaxContextKind::Expr); auto expr = parseExprSequence(Message, isExprBasic, /*forConditionalDirective*/false); return makeParserResult(expr.get()); }
  • 46. parseExpr // ParseStmt.cpp ParserStatus Parser::parseExprOrStmt(ASTNode &Result) { ParserResult<Expr> ResultExpr = parseExpr(diag::expected_expr); return ResultExpr; } // ParseExpr.cpp ParserResult<Expr> parseExpr(Diag<> ID) { return parseExprImpl(ID, /*isExprBasic=*/false); } ParserResult<Expr> Parser::parseExprImpl(Diag<> Message, bool isExprBasic) { SyntaxParsingContext ExprParsingContext(SyntaxContext, SyntaxContextKind::Expr); auto expr = parseExprSequence(Message, isExprBasic, /*forConditionalDirective*/false); return makeParserResult(expr.get()); }
  • 47. parseExprSequence // ParseExpr.cpp ParserResult<Expr> Parser::parseExprSequence(Diag<> Message, bool isExprBasic, bool isForConditionalDirective) { SyntaxParsingContext ExprSequnceContext(SyntaxContext, SyntaxContextKind::Expr); // Parse a unary expression. ParserResult<Expr> Primary = parseExprSequenceElement(Message, isExprBasic); auto expr = Primary.get(); // If we saw no operators, don't build a sequence. return makeParserResult(expr); } ParserResult<Expr> Parser::parseExprSequenceElement(Diag<> message, bool isExprBasic) { SyntaxParsingContext ElementContext(SyntaxContext, SyntaxContextKind::Expr); return parseExprUnary(message, isExprBasic); }
  • 48. parseExprSequence // ParseExpr.cpp ParserResult<Expr> Parser::parseExprSequence(Diag<> Message, bool isExprBasic, bool isForConditionalDirective) { SyntaxParsingContext ExprSequnceContext(SyntaxContext, SyntaxContextKind::Expr); // Parse a unary expression. ParserResult<Expr> Primary = parseExprSequenceElement(Message, isExprBasic); auto expr = Primary.get(); // If we saw no operators, don't build a sequence. return makeParserResult(expr); } ParserResult<Expr> Parser::parseExprSequenceElement(Diag<> message, bool isExprBasic) { SyntaxParsingContext ElementContext(SyntaxContext, SyntaxContextKind::Expr); return parseExprUnary(message, isExprBasic); }
  • 49. parseExprElement // ParseExpr.cpp ParserResult<Expr> Parser::parseExprUnary(Diag<> Message, bool isExprBasic) { SyntaxParsingContext UnaryContext(SyntaxContext, SyntaxContextKind::Expr); return parseExprPostfix(Message, isExprBasic); } ParserResult<Expr> Parser::parseExprPostfix(Diag<> ID, bool isExprBasic) { SyntaxParsingContext ExprContext(SyntaxContext, SyntaxContextKind::Expr); return parseExprPrimary(ID, isExprBasic); }
  • 50. parseExprElement // ParseExpr.cpp ParserResult<Expr> Parser::parseExprUnary(Diag<> Message, bool isExprBasic) { SyntaxParsingContext UnaryContext(SyntaxContext, SyntaxContextKind::Expr); return parseExprPostfix(Message, isExprBasic); } ParserResult<Expr> Parser::parseExprPostfix(Diag<> ID, bool isExprBasic) { SyntaxParsingContext ExprContext(SyntaxContext, SyntaxContextKind::Expr); return parseExprPrimary(ID, isExprBasic); }
  • 51. parseIntegerLiteralExpr // ParseExpr.cpp ParserResult<Expr> Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) { SyntaxParsingContext ExprContext(SyntaxContext, SyntaxContextKind::Expr); switch (Tok.getKind()) { case tok::integer_literal: { StringRef Text = copyAndStripUnderscores(Tok.getText()); SourceLoc Loc = consumeToken(tok::integer_literal); ExprContext.setCreateSyntax(SyntaxKind::IntegerLiteralExpr); return makeParserResult(new (Context) IntegerLiteralExpr(Text, Loc, /*Implicit=*/false)); } } }
  • 52. parseIntegerLiteralExpr // ParseExpr.cpp ParserResult<Expr> Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) { SyntaxParsingContext ExprContext(SyntaxContext, SyntaxContextKind::Expr); switch (Tok.getKind()) { case tok::integer_literal: { StringRef Text = copyAndStripUnderscores(Tok.getText()); SourceLoc Loc = consumeToken(tok::integer_literal); ExprContext.setCreateSyntax(SyntaxKind::IntegerLiteralExpr); return makeParserResult(new (Context) IntegerLiteralExpr(Text, Loc, /*Implicit=*/false)); } } }
  • 53. parseIntegerLiteralExpr // ParseExpr.cpp ParserResult<Expr> Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) { SyntaxParsingContext ExprContext(SyntaxContext, SyntaxContextKind::Expr); switch (Tok.getKind()) { case tok::integer_literal: { StringRef Text = copyAndStripUnderscores(Tok.getText()); SourceLoc Loc = consumeToken(tok::integer_literal); ExprContext.setCreateSyntax(SyntaxKind::IntegerLiteralExpr); return makeParserResult(new (Context) IntegerLiteralExpr(Text, Loc, /*Implicit=*/false)); } } }
  • 54. parseIntegerLiteralExpr // ParseExpr.cpp ParserResult<Expr> Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) { SyntaxParsingContext ExprContext(SyntaxContext, SyntaxContextKind::Expr); switch (Tok.getKind()) { case tok::integer_literal: { StringRef Text = copyAndStripUnderscores(Tok.getText()); SourceLoc Loc = consumeToken(tok::integer_literal); ExprContext.setCreateSyntax(SyntaxKind::IntegerLiteralExpr); return makeParserResult(new (Context) IntegerLiteralExpr(Text, Loc, /*Implicit=*/false)); } } }
  • 55. parseExprSequence // ParseExpr.cpp ParserResult<Expr> Parser::parseExprSequence(Diag<> Message, bool isExprBasic, bool isForConditionalDirective) { SyntaxParsingContext ExprSequnceContext(SyntaxContext, SyntaxContextKind::Expr); // Parse a unary expression. ParserResult<Expr> Primary = parseExprSequenceElement(Message, isExprBasic); auto expr = Primary.get(); // If we saw no operators, don't build a sequence. return makeParserResult(expr); } ParserResult<Expr> Parser::parseExprSequenceElement(Diag<> message, bool isExprBasic) { SyntaxParsingContext ElementContext(SyntaxContext, SyntaxContextKind::Expr); return parseExprUnary(message, isExprBasic); }
  • 56. parseBraceItems // ParseStmt.cpp ParserStatus Parser::parseBraceItems(SmallVectorImpl<ASTNode> &Entries, BraceItemListKind Kind, BraceItemListKind ConditionalBlockKind) { SyntaxParsingContext ItemListContext(SyntaxContext, SyntaxKind::CodeBlockItemList); auto *TLCD = new (Context) TopLevelCodeDecl(CurDeclContext); ContextChange CC(*this, TLCD, &State->getTopLevelContext()); ParserStatus BraceItemsStatus; ParserStatus Status = parseExprOrStmt(Result); BraceItemsStatus |= Status; auto Brace = BraceStmt::create(Context, Result.getStartLoc(), Result, Result.getEndLoc()); TLCD->setBody(Brace); Entries.push_back(TLCD); return BraceItemsStatus; }
  • 57. parseTopLevel // ParseDecl.cpp bool Parser::parseTopLevel() { SF.ASTStage = SourceFile::Parsing; parseBraceItems(Items, allowTopLevelCode() ? BraceItemListKind::TopLevelCode : BraceItemListKind::TopLevelLibrary); // Add newly parsed decls to the module. SmallVector<ASTNode, 128> Items; for (auto Item : Items) if (auto *D = Item.dyn_cast<Decl*>()) SF.Decls.push_back(D); // Note that the source file is fully parsed and verify it. SF.ASTStage = SourceFile::Parsed; verify(SF); // If we are done parsing the whole file, finalize the token receiver. if (Tok.is(tok::eof)) { SyntaxContext->addToken(Tok, LeadingTrivia, TrailingTrivia); TokReceiver->finalize(); } }
  • 58. parseTopLevel // ParseDecl.cpp bool Parser::parseTopLevel() { SF.ASTStage = SourceFile::Parsing; parseBraceItems(Items, allowTopLevelCode() ? BraceItemListKind::TopLevelCode : BraceItemListKind::TopLevelLibrary); // Add newly parsed decls to the module. SmallVector<ASTNode, 128> Items; for (auto Item : Items) if (auto *D = Item.dyn_cast<Decl*>()) SF.Decls.push_back(D); // Note that the source file is fully parsed and verify it. SF.ASTStage = SourceFile::Parsed; verify(SF); // If we are done parsing the whole file, finalize the token receiver. if (Tok.is(tok::eof)) { SyntaxContext->addToken(Tok, LeadingTrivia, TrailingTrivia); TokReceiver->finalize(); } }
  • 59. parseTopLevel // ParseDecl.cpp bool Parser::parseTopLevel() { SF.ASTStage = SourceFile::Parsing; parseBraceItems(Items, allowTopLevelCode() ? BraceItemListKind::TopLevelCode : BraceItemListKind::TopLevelLibrary); // Add newly parsed decls to the module. SmallVector<ASTNode, 128> Items; for (auto Item : Items) if (auto *D = Item.dyn_cast<Decl*>()) SF.Decls.push_back(D); // Note that the source file is fully parsed and verify it. SF.ASTStage = SourceFile::Parsed; verify(SF); // If we are done parsing the whole file, finalize the token receiver. if (Tok.is(tok::eof)) { SyntaxContext->addToken(Tok, LeadingTrivia, TrailingTrivia); TokReceiver->finalize(); } }
  • 60. Recap → Syntax Tree is created by SyntaxParsingContext
  • 61. Syntax Tree parseExprParen() { SyntaxParsingContext LocalCtxt(SyntaxKind::ParenExpr, SyntaxContext); consumeToken(tok::l_paren) // In consumeToken(), a RawTokenSyntax is // added to the context. parseExpr(); // On returning from parseExpr(), a Expr Syntax node is // created and added to the context. consumeToken(tok::r_paren) // Now the context holds { '(' Expr ')' }. // From these parts, it creates ParenExpr node and add it to the parent. }
  • 62. Recap → Syntax Tree is created by SyntaxParsingContext → AST is produced by SF.Decls
  • 63. AST bool Parser::parseTopLevel() { // Parse the body of the file. SmallVector<ASTNode, 128> Items; // Parse body // Add newly parsed decls to the module. for (auto Item : Items) if (auto *D = Item.dyn_cast<Decl*>()) SF.Decls.push_back(D); }
  • 66. emit-syntax // FrontendTool.cpp static bool emitSyntax(SourceFile *SF, LangOptions &LangOpts, SourceManager &SM, StringRef OutputFilename) { auto os = getFileOutputStream(OutputFilename, SF->getASTContext()); if (!os) return true; json::Output jsonOut(*os, /*UserInfo=*/{}, /*PrettyPrint=*/false); auto Root = SF->getSyntaxRoot().getRaw(); // Syntax Tree jsonOut << *Root; *os << "n"; return false; }
  • 67. emit-syntax // FrontendTool.cpp static bool emitSyntax(SourceFile *SF, LangOptions &LangOpts, SourceManager &SM, StringRef OutputFilename) { auto os = getFileOutputStream(OutputFilename, SF->getASTContext()); if (!os) return true; json::Output jsonOut(*os, /*UserInfo=*/{}, /*PrettyPrint=*/false); auto Root = SF->getSyntaxRoot().getRaw(); // Syntax Tree jsonOut << *Root; *os << "n"; return false; }
  • 68. Output // 1 - SourceFile - CodeBlockItemList - CodeBlockItem - IntegerLiteralExpr - integer_literal
  • 71. dump-ast // FrontendTool.cpp static void dumpAST(CompilerInvocation &Invocation, CompilerInstance &Instance) { getPrimaryOrMainSourceFile(Invocation, Instance)->dump(llvm::outs()); } void SourceFile::dump(llvm::raw_ostream &OS) const { llvm::SaveAndRestore<bool> X(getASTContext().LangOpts.DebugConstraintSolver, true); PrintDecl(OS).visitSourceFile(*this); llvm::errs() << 'n'; }
  • 72. ASTDumper // ASTDumper.cpp void visitSourceFile(const SourceFile &SF) { OS.indent(Indent); PrintWithColorRAII(OS, ParenthesisColor) << '('; PrintWithColorRAII(OS, ASTNodeColor) << "source_file "; PrintWithColorRAII(OS, LocationColor) << '"' << SF.getFilename() << '"'; for (Decl *D : SF.Decls) { // AST if (D->isImplicit()) continue; OS << 'n'; printRec(D); } PrintWithColorRAII(OS, ParenthesisColor) << ')'; }
  • 73. Output // 1 - source_file - top_level_code_decl - brace_stmt - integer_literal_expr type='Int' value=1
  • 74. How do we optionally generate libSyntax tree while also producing semantic AST?
  • 75. Option // LangOptions.h /// A collection of options that affect the language dialect and /// provide compiler debugging facilities. class LangOptions { /// Whether to parse syntax tree. If the syntax tree is built, the generated /// AST may not be correct when syntax nodes are reused as part of /// incrementals parsing. bool BuildSyntaxTree = false; } // SyntaxParsingContext.h class alignas(1 << SyntaxAlignInBits) SyntaxParsingContext { // If false, context does nothing. bool Enabled; }
  • 76. SyntaxParsingContext // SyntaxParsingContext.cpp /// Add Token with Trivia to the parts. void SyntaxParsingContext::addToken(Token &Tok, const ParsedTrivia &LeadingTrivia, const ParsedTrivia &TrailingTrivia) { if (!Enabled) return; ... } ParsedRawSyntaxNode SyntaxParsingContext::finalizeRoot() { if (!Enabled) ... }
  • 77. !
  • 78. Recap
  • 79. Recap → if Enabled, compiler creates Syntax Tree AND produces AST
  • 80. Recap → if Enabled, compiler creates Syntax Tree AND produces AST → if not, compiler only produces AST
  • 81. Goal To have the Swift parser fully embrace libSyntax and stop emitting the semantic AST
  • 82. New pipeline (Source) -> [Parser] -> (libSyntax) -+-> [ASTGen] -> (AST) -> [Sema] -> ... | or +-> [SwiftSyntax, ...]
  • 85. BeneïŹts → Robust architecture → SwiftSyntax parsing performance improvements
  • 86. BeneïŹts → Robust architecture → SwiftSyntax parsing performance improvements → Enable future work for making the compiler pipeline more suitable for interactive contexts
  • 87. !!!
  • 88. Initial PR [Parser] Decouple the parser from AST creation (part 1) apple/swift/pull/26403
  • 89. libSyntax (LibSyntax) -+-> [ASTGen] -> ... or (SwiftSyntax) -+-> [SwiftSyntax, ...]
  • 90. OpaqueSyntaxNodeKind // SyntaxParseActions.h enum class OpaqueSyntaxNodeKind { SwiftSyntax, LibSyntax, };
  • 91. SyntaxParseActions // SyntaxTreeCreator.h // LibSyntax class SyntaxTreeCreator: public SyntaxParseActions {...} // libSwiftSyntaxParser.cpp // SwiftSyntax class CLibParseActions : public SyntaxParseActions {...}
  • 92. HiddenLibSyntaxAction // HiddenLibSyntaxAction.h /// Holds an explicitly provided action and uses it to handle all function /// calls. Also hides an implicit SyntaxTreeCreator and ensures libSyntax nodes /// are always created. Provides an interface to map results of the explicitly /// provided action to the hidden libSyntax action. class HiddenLibSyntaxAction : public SyntaxParseActions { struct Node { OpaqueSyntaxNode ExplicitActionNode; OpaqueSyntaxNode LibSyntaxNode; ... }; // I assume this can be `CLibParseActions` for SwiftSyntax? std::shared_ptr<SyntaxParseActions> ExplicitAction; std::shared_ptr<SyntaxTreeCreator> LibSyntaxAction; ... }
  • 93. LibSyntaxGenerator /// Generates libSyntax nodes either by looking them up using /// HiddenLibSyntaxAction (based on provided OpaqueSyntaxNode) or by recording /// them with ParsedRawSyntaxRecorder. class LibSyntaxGenerator { std::shared_ptr<HiddenLibSyntaxAction> Actions; ParsedRawSyntaxRecorder Recorder; ... }
  • 94. ASTGen // ASTGen.h class ASTGen { ASTContext &Context; IntegerLiteralExpr *generate(syntax::IntegerLiteralExprSyntax &Expr); } IntegerLiteralExpr *ASTGen::generate(IntegerLiteralExprSyntax &Expr) { TokenSyntax Digits = Expr.getDigits(); StringRef Text = copyAndStripUnderscores(Digits.getText()); SourceLoc Loc = topLoc(); return new (Context) IntegerLiteralExpr(Text, Loc); }
  • 95. parseExprAST template <typename SyntaxNode> ParserResult<Expr> Parser::parseExprAST() { auto ParsedExpr = parseExprSyntax<SyntaxNode>(); SyntaxContext->addSyntax(ParsedExpr); ... auto Expr = SyntaxContext->topNode<SyntaxNode>(); auto ExprAST = Generator.generate(Expr); return makeParserResult(ExprAST); }
  • 96. Recap
  • 97. Recap → libSyntax always create syntax tree
  • 98. Recap → libSyntax always create syntax tree → ASTGen generates AST node from syntax tree
  • 101. Summary → libSyntax integration is still WIP → DeïŹnitely better architecture
  • 102. Summary → libSyntax integration is still WIP → DeïŹnitely better architecture → Huge performance improvements for SwiftSyntax