Merge pull request #8735 from redsun82/swift-dbscheme-gen

Swift: dbscheme generator
This commit is contained in:
AlexDenisov
2022-04-22 08:26:59 +02:00
committed by GitHub
16 changed files with 3420 additions and 9 deletions

View File

@@ -2,28 +2,41 @@
# See https://pre-commit.com/hooks.html for more hooks
exclude: /test/.*$(?<!\.ql)(?<!\.qll)(?<!\.qlref)
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.2.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: trailing-whitespace
- id: end-of-file-fixer
- repo: local
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: v13.0.1
hooks:
- id: codeql-format
- id: clang-format
files: ^swift/.*\.(h|c|cpp)$
- repo: local
hooks:
- id: codeql-format
name: Fix QL file formatting
files: \.qll?$
language: system
entry: codeql query format --in-place
- id: sync-files
- id: sync-files
name: Fix files required to be identical
language: system
entry: python3 config/sync-files.py --latest
pass_filenames: false
- id: qhelp
- id: qhelp
name: Check query help generation
files: \.qhelp$
language: system
entry: python3 misc/scripts/check-qhelp.py
- id: swift-codegen
name: Run Swift checked in code generation
files: ^swift/(codegen/|.*/generated/|ql/lib/swift\.dbscheme$)
language: system
entry: bazel run //swift/codegen
pass_filenames: false

View File

@@ -4,6 +4,32 @@ The Swift codeql package is an experimental and unsupported work in progress.
## Usage
Run `bazel run //swift:create-extractor-pack`, which will install `swift/extractor-pack`.
Run
```bash
bazel run //swift:create-extractor-pack
```
which will install `swift/extractor-pack`.
Using `--search-path=swift/extractor-pack` will then pick up the Swift extractor. You can also use
`--search-path=swift`, as the extractor pack is mentioned in `swift/.codeqlmanifest.json`.
Notice you can run `bazel run :create-extractor-pack` if you already are in the `swift` directory.
## Code generation
Make sure to install the [pip requirements](./codegen/requirements.txt) via
```bash
python3 -m pip install -r codegen/requirements.txt
```
Run
```bash
bazel run //swift/codegen
```
to update generated files. This can be shortened to
`bazel run codegen` if you are in the `swift` directory.

View File

@@ -0,0 +1,4 @@
py_binary(
name = "codegen",
srcs = glob(["**/*.py"]),
)

8
swift/codegen/codegen.py Executable file
View File

@@ -0,0 +1,8 @@
#!/usr/bin/env python3
""" Driver script to run all checked in code generation """
from lib import generator
import dbschemegen
if __name__ == "__main__":
generator.run(dbschemegen.generate)

90
swift/codegen/dbschemegen.py Executable file
View File

@@ -0,0 +1,90 @@
#!/usr/bin/env python3
import pathlib
import inflection
from lib import paths, schema, generator
from lib.dbscheme import *
log = logging.getLogger(__name__)
def dbtype(typename):
""" translate a type to a dbscheme counterpart, using `@lower_underscore` format for classes """
if typename[0].isupper():
return "@" + inflection.underscore(typename)
return typename
def cls_to_dbscheme(cls: schema.Class):
""" Yield all dbscheme entities needed to model class `cls` """
if cls.derived:
yield DbUnion(dbtype(cls.name), (dbtype(c) for c in cls.derived))
# output a table specific to a class only if it is a leaf class or it has 1-to-1 properties
# Leaf classes need a table to bind the `@` ids
# 1-to-1 properties are added to a class specific table
# in other cases, separate tables are used for the properties, and a class specific table is unneeded
if not cls.derived or any(f.is_single for f in cls.properties):
binding = not cls.derived
keyset = DbKeySet(["id"]) if cls.derived else None
yield DbTable(
keyset=keyset,
name=inflection.tableize(cls.name),
columns=[
DbColumn("id", type=dbtype(cls.name), binding=binding),
] + [
DbColumn(f.name, dbtype(f.type)) for f in cls.properties if f.is_single
]
)
# use property-specific tables for 1-to-many and 1-to-at-most-1 properties
for f in cls.properties:
if f.is_optional:
yield DbTable(
keyset=DbKeySet(["id"]),
name=inflection.tableize(f"{cls.name}_{f.name}"),
columns=[
DbColumn("id", type=dbtype(cls.name)),
DbColumn(f.name, dbtype(f.type)),
],
)
elif f.is_repeated:
yield DbTable(
keyset=DbKeySet(["id", "index"]),
name=inflection.tableize(f"{cls.name}_{f.name}"),
columns=[
DbColumn("id", type=dbtype(cls.name)),
DbColumn("index", type="int"),
DbColumn(inflection.singularize(f.name), dbtype(f.type)),
]
)
def get_declarations(data: schema.Schema):
return [d for cls in data.classes.values() for d in cls_to_dbscheme(cls)]
def get_includes(data: schema.Schema, include_dir: pathlib.Path):
includes = []
for inc in data.includes:
inc = include_dir / inc
with open(inc) as inclusion:
includes.append(DbSchemeInclude(src=inc.relative_to(paths.swift_dir), data=inclusion.read()))
return includes
def generate(opts, renderer):
input = opts.schema.resolve()
out = opts.dbscheme.resolve()
with open(input) as src:
data = schema.load(src)
dbscheme = DbScheme(src=input.relative_to(paths.swift_dir),
includes=get_includes(data, include_dir=input.parent),
declarations=get_declarations(data))
renderer.render(dbscheme, out)
if __name__ == "__main__":
generator.run(generate, tags=["schema", "dbscheme"])

View File

@@ -0,0 +1,104 @@
""" dbscheme format representation """
import logging
from dataclasses import dataclass
from typing import ClassVar, List
log = logging.getLogger(__name__)
dbscheme_keywords = {"case", "boolean", "int", "string", "type"}
@dataclass
class DbColumn:
schema_name: str
type: str
binding: bool = False
first: bool = False
@property
def name(self):
if self.schema_name in dbscheme_keywords:
return self.schema_name + "_"
return self.schema_name
@property
def lhstype(self):
if self.type[0] == "@":
return "unique int" if self.binding else "int"
return self.type
@property
def rhstype(self):
if self.type[0] == "@" and self.binding:
return self.type
return self.type + " ref"
@dataclass
class DbKeySetId:
id: str
first: bool = False
@dataclass
class DbKeySet:
ids: List[DbKeySetId]
def __post_init__(self):
assert self.ids
self.ids = [DbKeySetId(x) for x in self.ids]
self.ids[0].first = True
class DbDecl:
is_table = False
is_union = False
@dataclass
class DbTable(DbDecl):
is_table: ClassVar = True
name: str
columns: List[DbColumn]
keyset: DbKeySet = None
def __post_init__(self):
if self.columns:
self.columns[0].first = True
@dataclass
class DbUnionCase:
type: str
first: bool = False
@dataclass
class DbUnion(DbDecl):
is_union: ClassVar = True
lhs: str
rhs: List[DbUnionCase]
def __post_init__(self):
assert self.rhs
self.rhs = [DbUnionCase(x) for x in self.rhs]
self.rhs.sort(key=lambda c: c.type)
self.rhs[0].first = True
@dataclass
class DbSchemeInclude:
src: str
data: str
@dataclass
class DbScheme:
template: ClassVar = 'dbscheme'
src: str
includes: List[DbSchemeInclude]
declarations: List[DbDecl]

View File

@@ -0,0 +1,29 @@
""" generator script scaffolding """
import argparse
import logging
import sys
from . import options, render
def _parse(tags):
parser = argparse.ArgumentParser()
for opt in options.get(tags):
opt.add_to(parser)
ret = parser.parse_args()
log_level = logging.DEBUG if ret.verbose else logging.INFO
logging.basicConfig(format="{levelname} {message}", style='{', level=log_level)
return ret
def run(*generators, tags=None):
""" run generation functions in `generators`, parsing options tagged with `tags` (all if unspecified)
`generators` should be callables taking as input an option namespace and a `render.Renderer` instance
"""
opts = _parse(tags)
renderer = render.Renderer(dryrun=opts.check)
for g in generators:
g(opts, renderer)
sys.exit(1 if opts.check and renderer.done_something else 0)

View File

@@ -0,0 +1,48 @@
""" generator options, categorized by tags """
import argparse
import collections
import pathlib
from typing import Tuple
from . import paths
def _init_options():
Option("--check", "-c", action="store_true")
Option("--verbose", "-v", action="store_true")
Option("--schema", tags=["schema"], type=pathlib.Path, default=paths.swift_dir / "codegen/schema.yml")
Option("--dbscheme", tags=["dbscheme"], type=pathlib.Path, default=paths.swift_dir / "ql/lib/swift.dbscheme")
_options = collections.defaultdict(list)
class Option:
def __init__(self, *args, tags=None, **kwargs):
tags = tags or []
self.args = args
self.kwargs = kwargs
if tags:
for t in tags:
_options[t].append(self)
else:
_options["*"].append(self)
def add_to(self, parser: argparse.ArgumentParser):
parser.add_argument(*self.args, **self.kwargs)
_init_options()
def get(tags: Tuple[str]):
""" get options marked by `tags`
Return all options if tags is falsy. Options tagged by wildcard '*' are always returned
"""
if not tags:
return (o for tagged_opts in _options.values() for o in tagged_opts)
else:
# use specifically tagged options + those tagged with wildcard *
return (o for tag in ('*',) + tags for o in _options[tag])

View File

@@ -0,0 +1,17 @@
""" module providing useful filesystem paths """
import pathlib
import sys
import os
try:
_workspace_dir = pathlib.Path(os.environ['BUILD_WORKSPACE_DIRECTORY']) # <- means we are using bazel run
swift_dir = _workspace_dir / 'swift'
lib_dir = swift_dir / 'codegen' / 'lib'
except KeyError:
_this_file = pathlib.Path(__file__).resolve()
swift_dir = _this_file.parents[2]
lib_dir = _this_file.parent
exe_file = pathlib.Path(sys.argv[0]).resolve()

View File

@@ -0,0 +1,76 @@
""" template renderer module, wrapping around `pystache.Renderer`
`pystache` is a python mustache engine, and mustache is a template language. More information on
https://mustache.github.io/
"""
import hashlib
import logging
import pathlib
import pystache
from . import paths
log = logging.getLogger(__name__)
def _md5(data):
return hashlib.md5(data).digest()
class Renderer:
""" Template renderer using mustache templates in the `templates` directory """
def __init__(self, dryrun=False):
""" Construct the renderer, which will not write anything if `dryrun` is `True` """
self.r = pystache.Renderer(search_dirs=str(paths.lib_dir / "templates"), escape=lambda u: u)
self.generator = paths.exe_file.relative_to(paths.swift_dir)
self.dryrun = dryrun
self.written = set()
self.skipped = set()
self.erased = set()
@property
def done_something(self):
return bool(self.written or self.erased)
@property
def rendered(self):
return self.written | self.skipped
def render(self, data, output: pathlib.Path):
""" Render `data` to `output`.
`data` must have a `template` attribute denoting which template to use from the template directory.
If the file is unchanged, then no write is performed (and `done_something` remains unchanged)
"""
mnemonic = type(data).__name__
output.parent.mkdir(parents=True, exist_ok=True)
data = self.r.render_name(data.template, data, generator=self.generator)
if output.is_file():
with open(output, "rb") as file:
if _md5(data.encode()) == _md5(file.read()):
log.debug(f"skipped {output.name}")
self.skipped.add(output)
return
if self.dryrun:
log.error(f"would have generated {mnemonic} {output.name}")
else:
with open(output, "w") as out:
out.write(data)
log.info(f"generated {mnemonic} {output.name}")
self.written.add(output)
def cleanup(self, existing):
""" Remove files in `existing` for which no `render` has been called """
for f in existing - self.written - self.skipped:
if f.is_file():
if self.dryrun:
log.error(f"would have removed {f.name}")
else:
f.unlink()
log.info(f"removed {f.name}")
self.erased.add(f)

104
swift/codegen/lib/schema.py Normal file
View File

@@ -0,0 +1,104 @@
""" schema.yml format representation """
import pathlib
import re
from dataclasses import dataclass, field
from enum import Enum, auto
from typing import List, Set, Dict, ClassVar
import yaml
root_class_name = "Element"
@dataclass
class Property:
is_single: ClassVar = False
is_optional: ClassVar = False
is_repeated: ClassVar = False
name: str
type: str
@dataclass
class SingleProperty(Property):
is_single: ClassVar = True
@dataclass
class OptionalProperty(Property):
is_optional: ClassVar = True
@dataclass
class RepeatedProperty(Property):
is_repeated: ClassVar = True
@dataclass
class Class:
name: str
bases: Set[str] = field(default_factory=set)
derived: Set[str] = field(default_factory=set)
properties: List[Property] = field(default_factory=list)
dir: pathlib.Path = pathlib.Path()
@dataclass
class Schema:
classes: Dict[str, Class]
includes: Set[str] = field(default_factory=set)
def _parse_property(name, type):
if type.endswith("*"):
cls = RepeatedProperty
type = type[:-1]
elif type.endswith("?"):
cls = OptionalProperty
type = type[:-1]
else:
cls = SingleProperty
return cls(name, type)
class _DirSelector:
""" Default output subdirectory selector for generated QL files, based on the `_directories` global field"""
def __init__(self, dir_to_patterns):
self.selector = [(re.compile(p), pathlib.Path(d)) for d, p in dir_to_patterns]
self.selector.append((re.compile(""), pathlib.Path()))
def get(self, name):
return next(d for p, d in self.selector if p.search(name))
def load(file):
""" Parse the schema from `file` """
data = yaml.load(file, Loader=yaml.SafeLoader)
grouper = _DirSelector(data.get("_directories", {}).items())
ret = Schema(classes={cls: Class(cls, dir=grouper.get(cls)) for cls in data if not cls.startswith("_")},
includes=set(data.get("_includes", [])))
assert root_class_name not in ret.classes
ret.classes[root_class_name] = Class(root_class_name)
for name, info in data.items():
if name.startswith("_"):
continue
assert name[0].isupper()
cls = ret.classes[name]
for k, v in info.items():
if not k.startswith("_"):
cls.properties.append(_parse_property(k, v))
elif k == "_extends":
if not isinstance(v, list):
v = [v]
for base in v:
cls.bases.add(base)
ret.classes[base].derived.add(name)
elif k == "_dir":
cls.dir = pathlib.Path(v)
if not cls.bases:
cls.bases.add(root_class_name)
ret.classes[root_class_name].derived.add(name)
return ret

View File

@@ -0,0 +1,25 @@
// generated by {{generator}}
{{#includes}}
// from {{src}}
{{data}}
{{/includes}}
// from {{src}}
{{#declarations}}
{{#is_union}}
{{lhs}} =
{{#rhs}}
{{#first}} {{/first}}{{^first}}| {{/first}}{{type}}
{{/rhs}};
{{/is_union}}
{{#is_table}}
{{#keyset}}
#keyset[{{#ids}}{{^first}}, {{/first}}{{id}}{{/ids}}]
{{/keyset}}
{{name}}({{#columns}}{{^first}},{{/first}}
{{lhstype}} {{name}}: {{rhstype}}{{/columns}}
);
{{/is_table}}
{{/declarations}}

View File

@@ -0,0 +1,10 @@
/**
* The source location of the snapshot.
*/
sourceLocationPrefix(
string prefix: string ref
);
answer_to_life_the_universe_and_everything(
int answer: int ref
)

View File

@@ -0,0 +1,3 @@
pystache
pyyaml
inflection

997
swift/codegen/schema.yml Normal file
View File

@@ -0,0 +1,997 @@
# add dbscheme files to be added verbatim
_includes:
- prefix.dbscheme
# organize generated class files in subdirectories according to these regexp rules
# a class can override this specifying `_dir`
_directories:
decl: Decl$|Context$
pattern: Pattern$
type: Type$
typerepr: TypeRepr$
expr: Expr$
stmt: Stmt$
File:
name: string
IterableDeclContext:
members: Decl*
Locatable:
location: Location
Location:
file: File
begin_line: int
begin_column: int
end_line: int
end_column: int
Type:
diagnostics_name: string
canonical_type: Type
ExtensionDecl:
_extends:
- GenericContext
- IterableDeclContext
- Decl
NominalTypeDecl:
_extends:
- IterableDeclContext
- GenericTypeDecl
type: Type
AstNode:
_extends: Locatable
ConditionElement:
_extends: Locatable
boolean: Expr?
pattern: Pattern?
initializer: Expr?
_dir: stmt
AnyFunctionType:
_extends: Type
result: Type
param_types: Type*
param_labels: string*
AnyGenericType:
_extends: Type
parent: Type?
declaration: Decl
AnyMetatypeType:
_extends: Type
BuiltinType:
_extends: Type
DependentMemberType:
_extends: Type
DynamicSelfType:
_extends: Type
ErrorType:
_extends: Type
InOutType:
_extends: Type
LValueType:
_extends: Type
object_type: Type
ModuleType:
_extends: Type
PlaceholderType:
_extends: Type
ProtocolCompositionType:
_extends: Type
ExistentialType:
_extends: Type
ReferenceStorageType:
_extends: Type
SilBlockStorageType:
_extends: Type
SilBoxType:
_extends: Type
SilFunctionType:
_extends: Type
SilTokenType:
_extends: Type
SubstitutableType:
_extends: Type
SugarType:
_extends: Type
TupleType:
_extends: Type
TypeVariableType:
_extends: Type
UnknownType:
_extends: Type
name: string
UnresolvedType:
_extends: Type
ClassDecl:
_extends: NominalTypeDecl
EnumDecl:
_extends: NominalTypeDecl
ProtocolDecl:
_extends: NominalTypeDecl
StructDecl:
_extends: NominalTypeDecl
Decl:
_extends: AstNode
Expr:
_extends: AstNode
type: Type?
Pattern:
_extends: AstNode
Stmt:
_extends: AstNode
TypeRepr:
_extends: AstNode
FunctionType:
_extends: AnyFunctionType
GenericFunctionType:
_extends: AnyFunctionType
generic_params: GenericTypeParamType*
NominalOrBoundGenericNominalType:
_extends: AnyGenericType
UnboundGenericType:
_extends: AnyGenericType
ExistentialMetatypeType:
_extends: AnyMetatypeType
MetatypeType:
_extends: AnyMetatypeType
AnyBuiltinIntegerType:
_extends: BuiltinType
BuiltinBridgeObjectType:
_extends: BuiltinType
BuiltinDefaultActorStorageType:
_extends: BuiltinType
BuiltinExecutorType:
_extends: BuiltinType
BuiltinFloatType:
_extends: BuiltinType
BuiltinJobType:
_extends: BuiltinType
BuiltinNativeObjectType:
_extends: BuiltinType
BuiltinRawPointerType:
_extends: BuiltinType
BuiltinRawUnsafeContinuationType:
_extends: BuiltinType
BuiltinUnsafeValueBufferType:
_extends: BuiltinType
BuiltinVectorType:
_extends: BuiltinType
UnmanagedStorageType:
_extends: ReferenceStorageType
UnownedStorageType:
_extends: ReferenceStorageType
WeakStorageType:
_extends: ReferenceStorageType
ArchetypeType:
_extends: SubstitutableType
GenericTypeParamType:
_extends: SubstitutableType
name: string
ParenType:
_extends: SugarType
SyntaxSugarType:
_extends: SugarType
TypeAliasType:
_extends: SugarType
EnumCaseDecl:
_extends: Decl
elements: EnumElementDecl*
IfConfigDecl:
_extends: Decl
ImportDecl:
_extends: Decl
MissingMemberDecl:
_extends: Decl
OperatorDecl:
_extends: Decl
PatternBindingDecl:
_extends: Decl
inits: Expr*
patterns: Pattern*
PoundDiagnosticDecl:
_extends: Decl
PrecedenceGroupDecl:
_extends: Decl
TopLevelCodeDecl:
_extends: Decl
body: BraceStmt
UnknownAstNode:
_extends:
- Decl
- Expr
- Pattern
- Stmt
- TypeRepr
name: string
ValueDecl:
_extends: Decl
interface_type: Type
AbstractClosureExpr:
_extends: Expr
AnyTryExpr:
_extends: Expr
sub_expr: Expr
AppliedPropertyWrapperExpr:
_extends: Expr
Argument:
label: string
expr: Expr
_dir: expr
ApplyExpr:
_extends: Expr
function: Expr
arguments: Argument*
ArrowExpr:
_extends: Expr
AssignExpr:
_extends: Expr
dest: Expr
src: Expr
BindOptionalExpr:
_extends: Expr
CaptureListExpr:
_extends: Expr
CodeCompletionExpr:
_extends: Expr
CollectionExpr:
_extends: Expr
DeclRefExpr:
_extends: Expr
decl: Decl
replacement_types: Type*
DefaultArgumentExpr:
_extends: Expr
param_decl: ParamDecl
param_index: int
caller_side_default: Expr?
DiscardAssignmentExpr:
_extends: Expr
DotSyntaxBaseIgnoredExpr:
_extends: Expr
DynamicTypeExpr:
_extends: Expr
EditorPlaceholderExpr:
_extends: Expr
EnumIsCaseExpr:
_extends: Expr
ErrorExpr:
_extends: Expr
ExplicitCastExpr:
_extends: Expr
sub_expr: Expr
ForceValueExpr:
_extends: Expr
sub_expr: Expr
IdentityExpr:
_extends: Expr
sub_expr: Expr
IfExpr:
_extends: Expr
ImplicitConversionExpr:
_extends: Expr
sub_expr: Expr
InOutExpr:
_extends: Expr
sub_expr: Expr
KeyPathApplicationExpr:
_extends: Expr
KeyPathDotExpr:
_extends: Expr
KeyPathExpr:
_extends: Expr
parsed_root: Expr?
parsed_path: Expr?
LazyInitializerExpr:
_extends: Expr
LiteralExpr:
_extends: Expr
LookupExpr:
_extends: Expr
MakeTemporarilyEscapableExpr:
_extends: Expr
ObjCSelectorExpr:
_extends: Expr
OneWayExpr:
_extends: Expr
OpaqueValueExpr:
_extends: Expr
OpenExistentialExpr:
_extends: Expr
OptionalEvaluationExpr:
_extends: Expr
OtherConstructorDeclRefExpr:
_extends: Expr
OverloadSetRefExpr:
_extends: Expr
PropertyWrapperValuePlaceholderExpr:
_extends: Expr
RebindSelfInConstructorExpr:
_extends: Expr
SequenceExpr:
_extends: Expr
SuperRefExpr:
_extends: Expr
TapExpr:
_extends: Expr
sub_expr: Expr?
var: VarDecl
body: BraceStmt
TupleElementExpr:
_extends: Expr
TupleExpr:
_extends: Expr
elements: Expr*
TypeExpr:
_extends: Expr
type_repr: UnknownAstNode?
UnresolvedDeclRefExpr:
_extends: Expr
UnresolvedDotExpr:
_extends: Expr
UnresolvedMemberExpr:
_extends: Expr
UnresolvedPatternExpr:
_extends: Expr
UnresolvedSpecializeExpr:
_extends: Expr
VarargExpansionExpr:
_extends: Expr
sub_expr: Expr
AnyPattern:
_extends: Pattern
BindingPattern:
_extends: Pattern
sub_pattern: Pattern
BoolPattern:
_extends: Pattern
value: boolean
EnumElementPattern:
_extends: Pattern
element: EnumElementDecl
sub_pattern: Pattern?
ExprPattern:
_extends: Pattern
sub_expr: Expr
IsPattern:
_extends: Pattern
cast_type_repr: TypeRepr
sub_pattern: Pattern?
NamedPattern:
_extends: Pattern
name: string
OptionalSomePattern:
_extends: Pattern
sub_pattern: Pattern
ParenPattern:
_extends: Pattern
sub_pattern: Pattern
TuplePattern:
_extends: Pattern
elements: Pattern*
TypedPattern:
_extends: Pattern
sub_pattern: Pattern
type_repr: TypeRepr?
BraceStmt:
_extends: Stmt
elements: AstNode*
BreakStmt:
_extends: Stmt
target_name: string?
target: Stmt?
CaseStmt:
_extends: Stmt
body: Stmt
labels: CaseLabelItem*
variables: VarDecl*
CaseLabelItem:
_extends: AstNode
pattern: Pattern
guard: Expr?
_dir: stmt
ContinueStmt:
_extends: Stmt
target_name: string?
target: Stmt?
DeferStmt:
_extends: Stmt
body: BraceStmt
FailStmt:
_extends: Stmt
FallthroughStmt:
_extends: Stmt
fallthrough_source: CaseStmt
fallthrough_dest: CaseStmt
LabeledStmt:
_extends: Stmt
label: string?
PoundAssertStmt:
_extends: Stmt
ReturnStmt:
_extends: Stmt
result: Expr?
ThrowStmt:
_extends: Stmt
sub_expr: Expr
YieldStmt:
_extends: Stmt
BoundGenericType:
_extends: NominalOrBoundGenericNominalType
NominalType:
_extends: NominalOrBoundGenericNominalType
BuiltinIntegerLiteralType:
_extends: AnyBuiltinIntegerType
BuiltinIntegerType:
_extends: AnyBuiltinIntegerType
NestedArchetypeType:
_extends: ArchetypeType
SequenceArchetypeType:
_extends: ArchetypeType
OpaqueTypeArchetypeType:
_extends: ArchetypeType
OpenedArchetypeType:
_extends: ArchetypeType
PrimaryArchetypeType:
_extends: ArchetypeType
interface_type: GenericTypeParamType
DictionaryType:
_extends: SyntaxSugarType
UnarySyntaxSugarType:
_extends: SyntaxSugarType
InfixOperatorDecl:
_extends: OperatorDecl
PostfixOperatorDecl:
_extends: OperatorDecl
PrefixOperatorDecl:
_extends: OperatorDecl
AbstractFunctionDecl:
_extends:
- GenericContext
- ValueDecl
name: string
body: BraceStmt?
params: ParamDecl*
AbstractStorageDecl:
_extends: ValueDecl
EnumElementDecl:
_extends: ValueDecl
name: string
params: ParamDecl*
TypeDecl:
_extends: ValueDecl
name: string
AutoClosureExpr:
_extends: AbstractClosureExpr
ClosureExpr:
_extends: AbstractClosureExpr
body: BraceStmt
ForceTryExpr:
_extends: AnyTryExpr
OptionalTryExpr:
_extends: AnyTryExpr
TryExpr:
_extends: AnyTryExpr
BinaryExpr:
_extends: ApplyExpr
CallExpr:
_extends: ApplyExpr
PostfixUnaryExpr:
_extends: ApplyExpr
PrefixUnaryExpr:
_extends: ApplyExpr
SelfApplyExpr:
_extends: ApplyExpr
base: Expr
ArrayExpr:
_extends: CollectionExpr
elements: Expr*
DictionaryExpr:
_extends: CollectionExpr
elements: Expr*
CheckedCastExpr:
_extends: ExplicitCastExpr
CoerceExpr:
_extends: ExplicitCastExpr
AwaitExpr:
_extends: IdentityExpr
DotSelfExpr:
_extends: IdentityExpr
ParenExpr:
_extends: IdentityExpr
UnresolvedMemberChainResultExpr:
_extends: IdentityExpr
AnyHashableErasureExpr:
_extends: ImplicitConversionExpr
ArchetypeToSuperExpr:
_extends: ImplicitConversionExpr
ArrayToPointerExpr:
_extends: ImplicitConversionExpr
BridgeFromObjCExpr:
_extends: ImplicitConversionExpr
BridgeToObjCExpr:
_extends: ImplicitConversionExpr
ClassMetatypeToObjectExpr:
_extends: ImplicitConversionExpr
CollectionUpcastConversionExpr:
_extends: ImplicitConversionExpr
ConditionalBridgeFromObjCExpr:
_extends: ImplicitConversionExpr
CovariantFunctionConversionExpr:
_extends: ImplicitConversionExpr
CovariantReturnConversionExpr:
_extends: ImplicitConversionExpr
DerivedToBaseExpr:
_extends: ImplicitConversionExpr
DestructureTupleExpr:
_extends: ImplicitConversionExpr
DifferentiableFunctionExpr:
_extends: ImplicitConversionExpr
DifferentiableFunctionExtractOriginalExpr:
_extends: ImplicitConversionExpr
ErasureExpr:
_extends: ImplicitConversionExpr
ExistentialMetatypeToObjectExpr:
_extends: ImplicitConversionExpr
ForeignObjectConversionExpr:
_extends: ImplicitConversionExpr
FunctionConversionExpr:
_extends: ImplicitConversionExpr
InOutToPointerExpr:
_extends: ImplicitConversionExpr
InjectIntoOptionalExpr:
_extends: ImplicitConversionExpr
LinearFunctionExpr:
_extends: ImplicitConversionExpr
LinearFunctionExtractOriginalExpr:
_extends: ImplicitConversionExpr
LinearToDifferentiableFunctionExpr:
_extends: ImplicitConversionExpr
LoadExpr:
_extends: ImplicitConversionExpr
MetatypeConversionExpr:
_extends: ImplicitConversionExpr
PointerToPointerExpr:
_extends: ImplicitConversionExpr
ProtocolMetatypeToObjectExpr:
_extends: ImplicitConversionExpr
StringToPointerExpr:
_extends: ImplicitConversionExpr
UnderlyingToOpaqueExpr:
_extends: ImplicitConversionExpr
UnevaluatedInstanceExpr:
_extends: ImplicitConversionExpr
UnresolvedTypeConversionExpr:
_extends: ImplicitConversionExpr
BuiltinLiteralExpr:
_extends: LiteralExpr
InterpolatedStringLiteralExpr:
_extends: LiteralExpr
interpolation_expr: OpaqueValueExpr?
interpolation_count_expr: Expr?
literal_capacity_expr: Expr?
appending_expr: TapExpr?
RegexLiteralExpr:
_extends: LiteralExpr
NilLiteralExpr:
_extends: LiteralExpr
ObjectLiteralExpr:
_extends: LiteralExpr
DynamicLookupExpr:
_extends: LookupExpr
MemberRefExpr:
_extends: LookupExpr
base_expr: Expr
SubscriptExpr:
_extends:
- GenericContext
- LookupExpr
base_expr: Expr
arguments: Argument*
OverloadedDeclRefExpr:
_extends: OverloadSetRefExpr
DoCatchStmt:
_extends: LabeledStmt
body: Stmt
catches: CaseStmt*
DoStmt:
_extends: LabeledStmt
body: BraceStmt
ForEachStmt:
_extends: LabeledStmt
body: BraceStmt
where: Expr?
LabeledConditionalStmt:
_extends: LabeledStmt
condition: StmtCondition
StmtCondition:
_extends: AstNode
elements: ConditionElement*
_dir: stmt
RepeatWhileStmt:
_extends: LabeledStmt
cond: Expr
body: Stmt
SwitchStmt:
_extends: LabeledStmt
subject_expr: Expr
cases: CaseStmt*
BoundGenericClassType:
_extends: BoundGenericType
BoundGenericEnumType:
_extends: BoundGenericType
BoundGenericStructType:
_extends: BoundGenericType
ClassType:
_extends: NominalType
decl: ClassDecl
EnumType:
_extends: NominalType
ProtocolType:
_extends: NominalType
StructType:
_extends: NominalType
decl: StructDecl
ArraySliceType:
_extends: UnarySyntaxSugarType
OptionalType:
_extends: UnarySyntaxSugarType
VariadicSequenceType:
_extends: UnarySyntaxSugarType
ConstructorDecl:
_extends: AbstractFunctionDecl
DestructorDecl:
_extends: AbstractFunctionDecl
FuncDecl:
_extends: AbstractFunctionDecl
SubscriptDecl:
_extends: AbstractStorageDecl
VarDecl:
_extends: AbstractStorageDecl
name: string
type: Type
AbstractTypeParamDecl:
_extends: TypeDecl
GenericContext:
generic_type_params: GenericTypeParamDecl*
GenericTypeDecl:
_extends:
- GenericContext
- TypeDecl
ModuleDecl:
_extends: TypeDecl
ConstructorRefCallExpr:
_extends: SelfApplyExpr
DotSyntaxCallExpr:
_extends: SelfApplyExpr
ConditionalCheckedCastExpr:
_extends: CheckedCastExpr
ForcedCheckedCastExpr:
_extends: CheckedCastExpr
IsExpr:
_extends: CheckedCastExpr
BooleanLiteralExpr:
_extends: BuiltinLiteralExpr
value: boolean
MagicIdentifierLiteralExpr:
_extends: BuiltinLiteralExpr
kind: string
NumberLiteralExpr:
_extends: BuiltinLiteralExpr
StringLiteralExpr:
_extends: BuiltinLiteralExpr
value: string
DynamicMemberRefExpr:
_extends: DynamicLookupExpr
DynamicSubscriptExpr:
_extends: DynamicLookupExpr
GuardStmt:
_extends: LabeledConditionalStmt
body: BraceStmt
IfStmt:
_extends: LabeledConditionalStmt
then: Stmt
else: Stmt?
WhileStmt:
_extends: LabeledConditionalStmt
body: Stmt
AccessorDecl:
_extends: FuncDecl
ConcreteFuncDecl:
_extends: FuncDecl
ConcreteVarDecl:
_extends: VarDecl
introducer_int: int
ParamDecl:
_extends: VarDecl
AssociatedTypeDecl:
_extends: AbstractTypeParamDecl
GenericTypeParamDecl:
_extends: AbstractTypeParamDecl
OpaqueTypeDecl:
_extends: GenericTypeDecl
TypeAliasDecl:
_extends: GenericTypeDecl
FloatLiteralExpr:
_extends: NumberLiteralExpr
string_value: string
IntegerLiteralExpr:
_extends: NumberLiteralExpr
string_value: string

File diff suppressed because it is too large Load Diff