mirror of
https://github.com/github/codeql.git
synced 2026-07-29 06:46:46 +02:00
Merge pull request #22233 from github/tausbn/swift-syntax-rs-sequenced
unified: Switch over to using `swift-syntax` for parsing
This commit is contained in:
BIN
ql/Cargo.lock
generated
BIN
ql/Cargo.lock
generated
Binary file not shown.
@@ -29,28 +29,24 @@ pub fn run(options: Options) -> std::io::Result<()> {
|
||||
prefix: "ql",
|
||||
ts_language: tree_sitter_ql::LANGUAGE.into(),
|
||||
node_types: tree_sitter_ql::NODE_TYPES,
|
||||
desugar: None,
|
||||
file_globs: vec!["*.ql".into(), "*.qll".into()],
|
||||
},
|
||||
simple::LanguageSpec {
|
||||
prefix: "dbscheme",
|
||||
ts_language: tree_sitter_ql_dbscheme::LANGUAGE.into(),
|
||||
node_types: tree_sitter_ql_dbscheme::NODE_TYPES,
|
||||
desugar: None,
|
||||
file_globs: vec!["*.dbscheme".into()],
|
||||
},
|
||||
simple::LanguageSpec {
|
||||
prefix: "json",
|
||||
ts_language: tree_sitter_json::LANGUAGE.into(),
|
||||
node_types: tree_sitter_json::NODE_TYPES,
|
||||
desugar: None,
|
||||
file_globs: vec!["*.json".into(), "*.jsonl".into(), "*.jsonc".into()],
|
||||
},
|
||||
simple::LanguageSpec {
|
||||
prefix: "blame",
|
||||
ts_language: tree_sitter_blame::LANGUAGE.into(),
|
||||
node_types: tree_sitter_blame::NODE_TYPES,
|
||||
desugar: None,
|
||||
file_globs: vec!["*.blame".into()],
|
||||
},
|
||||
],
|
||||
|
||||
@@ -94,7 +94,9 @@ pub fn run(options: Options) -> std::io::Result<()> {
|
||||
node_types::read_node_types_str("erb", tree_sitter_embedded_template::NODE_TYPES)?;
|
||||
let lines: std::io::Result<Vec<String>> = std::io::BufReader::new(file_list).lines().collect();
|
||||
let lines = lines?;
|
||||
let source_root = std::env::current_dir().ok().and_then(|d| d.canonicalize().ok());
|
||||
let source_root = std::env::current_dir()
|
||||
.ok()
|
||||
.and_then(|d| d.canonicalize().ok());
|
||||
lines
|
||||
.par_iter()
|
||||
.try_for_each(|line| {
|
||||
@@ -126,7 +128,6 @@ pub fn run(options: Options) -> std::io::Result<()> {
|
||||
&path,
|
||||
&source,
|
||||
&[],
|
||||
None,
|
||||
);
|
||||
|
||||
let (ranges, line_breaks) = scan_erb(
|
||||
@@ -215,7 +216,6 @@ pub fn run(options: Options) -> std::io::Result<()> {
|
||||
&path,
|
||||
&source,
|
||||
&code_ranges,
|
||||
None,
|
||||
);
|
||||
std::fs::create_dir_all(src_archive_file.parent().unwrap())?;
|
||||
if needs_conversion {
|
||||
|
||||
104
shared/tree-sitter-extractor/src/extractor/desugaring.rs
Normal file
104
shared/tree-sitter-extractor/src/extractor/desugaring.rs
Normal file
@@ -0,0 +1,104 @@
|
||||
//! Extraction for languages that rewrite their syntax tree before extraction.
|
||||
//!
|
||||
//! Unlike [`crate::extractor::simple`] (direct tree-sitter extraction), a
|
||||
//! desugaring language parses source into a [`ParsedTree`] — a `yeast::Ast`
|
||||
//! plus side-channel `extra` tokens (comments and similar) — and rewrites the
|
||||
//! AST through a [`yeast::Desugarer`] before emitting TRAP. The parser is a
|
||||
//! closure, so both tree-sitter grammars (via
|
||||
//! [`crate::extractor::tree_sitter_parser`]) and fully custom parsers plug in
|
||||
//! the same way.
|
||||
|
||||
use crate::trap;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::diagnostics;
|
||||
use crate::extractor::ParsedTree;
|
||||
use crate::extractor::driver::{self, LanguageExtractor};
|
||||
use crate::node_types::{self, NodeTypeMap};
|
||||
|
||||
/// A parser turns source bytes into a [`ParsedTree`]. Tree-sitter grammars plug
|
||||
/// in via [`crate::extractor::tree_sitter_parser`]; custom (non-tree-sitter)
|
||||
/// parsers supply their own closure.
|
||||
pub type Parser = Box<dyn Fn(&[u8]) -> Result<ParsedTree, String> + Send + Sync>;
|
||||
|
||||
pub struct LanguageSpec {
|
||||
pub prefix: &'static str,
|
||||
/// The parser: source -> `yeast::Ast` + `extra` tokens (see [`Parser`]).
|
||||
pub parser: Parser,
|
||||
/// Fallback TRAP schema, used only when `desugarer` does not supply its own
|
||||
/// output schema (via [`yeast::Desugarer::output_node_types_yaml`]). May be
|
||||
/// empty for a custom parser whose desugarer always provides the schema.
|
||||
pub node_types: &'static str,
|
||||
/// The desugarer applied to the parsed AST before extraction. Its
|
||||
/// `output_node_types_yaml()` (when set) provides the TRAP schema.
|
||||
///
|
||||
/// `Box<dyn yeast::Desugarer>` so the shared extractor is agnostic to the
|
||||
/// user-defined context type the desugarer uses internally.
|
||||
pub desugarer: Box<dyn yeast::Desugarer>,
|
||||
pub file_globs: Vec<String>,
|
||||
}
|
||||
|
||||
impl LanguageExtractor for LanguageSpec {
|
||||
fn file_globs(&self) -> &[String] {
|
||||
&self.file_globs
|
||||
}
|
||||
|
||||
fn build_schema(&self) -> std::io::Result<NodeTypeMap> {
|
||||
let effective_node_types: String = match self.desugarer.output_node_types_yaml() {
|
||||
Some(yaml) => yeast::node_types_yaml::convert(yaml).map_err(|e| {
|
||||
std::io::Error::other(format!(
|
||||
"Failed to convert YAML node-types to JSON for {}: {e}",
|
||||
self.prefix
|
||||
))
|
||||
})?,
|
||||
None => self.node_types.to_string(),
|
||||
};
|
||||
node_types::read_node_types_str(self.prefix, &effective_node_types)
|
||||
}
|
||||
|
||||
fn extract_file(
|
||||
&self,
|
||||
schema: &NodeTypeMap,
|
||||
diagnostics_writer: &mut diagnostics::LogWriter,
|
||||
trap_writer: &mut trap::Writer,
|
||||
path: &std::path::Path,
|
||||
source: &[u8],
|
||||
) {
|
||||
crate::extractor::extract_parsed(
|
||||
self.parser.as_ref(),
|
||||
self.prefix,
|
||||
schema,
|
||||
diagnostics_writer,
|
||||
trap_writer,
|
||||
None,
|
||||
path,
|
||||
source,
|
||||
self.desugarer.as_ref(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Extractor {
|
||||
pub prefix: String,
|
||||
pub languages: Vec<LanguageSpec>,
|
||||
pub trap_dir: PathBuf,
|
||||
pub source_archive_dir: PathBuf,
|
||||
pub file_lists: Vec<PathBuf>,
|
||||
// Typically constructed via `trap::Compression::from_env`.
|
||||
// This allow us to report the error using our diagnostics system
|
||||
// without exposing it to consumers.
|
||||
pub trap_compression: Result<trap::Compression, String>,
|
||||
}
|
||||
|
||||
impl Extractor {
|
||||
pub fn run(&self) -> std::io::Result<()> {
|
||||
driver::run_extractor(
|
||||
&self.prefix,
|
||||
&self.languages,
|
||||
&self.trap_dir,
|
||||
&self.source_archive_dir,
|
||||
&self.file_lists,
|
||||
&self.trap_compression,
|
||||
)
|
||||
}
|
||||
}
|
||||
210
shared/tree-sitter-extractor/src/extractor/driver.rs
Normal file
210
shared/tree-sitter-extractor/src/extractor/driver.rs
Normal file
@@ -0,0 +1,210 @@
|
||||
//! Shared multi-file extraction driver.
|
||||
//!
|
||||
//! The `simple` (direct tree-sitter) and `desugaring` (parse + desugar)
|
||||
//! extractors differ only in how a language's schema is built and how a single
|
||||
//! file is extracted. Everything else — threading, matching files to languages
|
||||
//! by glob, writing TRAP, and copying into the source archive — is identical
|
||||
//! and lives here, parameterised over the [`LanguageExtractor`] trait.
|
||||
|
||||
use globset::{GlobBuilder, GlobSetBuilder};
|
||||
use rayon::prelude::*;
|
||||
use std::fs::File;
|
||||
use std::io::BufRead;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use crate::diagnostics;
|
||||
use crate::file_paths;
|
||||
use crate::node_types::NodeTypeMap;
|
||||
use crate::trap;
|
||||
|
||||
/// A language that [`run_extractor`] can process: it knows its file globs, its
|
||||
/// TRAP schema, and how to extract a single file. Implemented by
|
||||
/// [`super::simple::LanguageSpec`] (direct tree-sitter extraction) and
|
||||
/// [`super::desugaring::LanguageSpec`] (parse into an AST and desugar it).
|
||||
pub(crate) trait LanguageExtractor: Sync {
|
||||
/// The file-name globs that select files for this language.
|
||||
fn file_globs(&self) -> &[String];
|
||||
/// Build the TRAP node-type schema used to validate emitted tuples.
|
||||
fn build_schema(&self) -> std::io::Result<NodeTypeMap>;
|
||||
/// Extract a single file's `source` into `trap_writer`.
|
||||
fn extract_file(
|
||||
&self,
|
||||
schema: &NodeTypeMap,
|
||||
diagnostics_writer: &mut diagnostics::LogWriter,
|
||||
trap_writer: &mut trap::Writer,
|
||||
path: &Path,
|
||||
source: &[u8],
|
||||
);
|
||||
}
|
||||
|
||||
/// Drive extraction over `languages` for every file listed in `file_lists`.
|
||||
///
|
||||
/// Sets up the thread pool, builds a combined glob set, and for each input file
|
||||
/// dispatches to the matching language's [`LanguageExtractor::extract_file`],
|
||||
/// writing the resulting TRAP and a source-archive copy.
|
||||
pub(crate) fn run_extractor<L: LanguageExtractor>(
|
||||
prefix: &str,
|
||||
languages: &[L],
|
||||
trap_dir: &Path,
|
||||
source_archive_dir: &Path,
|
||||
file_lists: &[PathBuf],
|
||||
trap_compression: &Result<trap::Compression, String>,
|
||||
) -> std::io::Result<()> {
|
||||
tracing::info!("Extraction started");
|
||||
let diagnostics = diagnostics::DiagnosticLoggers::new(prefix);
|
||||
let mut main_thread_logger = diagnostics.logger();
|
||||
let num_threads = match crate::options::num_threads() {
|
||||
Ok(num) => num,
|
||||
Err(e) => {
|
||||
main_thread_logger.write(
|
||||
main_thread_logger
|
||||
.new_entry("configuration-error", "Configuration error")
|
||||
.message(
|
||||
"{}; defaulting to 1 thread.",
|
||||
&[diagnostics::MessageArg::Code(&e)],
|
||||
)
|
||||
.severity(diagnostics::Severity::Warning),
|
||||
);
|
||||
1
|
||||
}
|
||||
};
|
||||
tracing::info!(
|
||||
"Using {} {}",
|
||||
num_threads,
|
||||
if num_threads == 1 {
|
||||
"thread"
|
||||
} else {
|
||||
"threads"
|
||||
}
|
||||
);
|
||||
let trap_compression = match trap_compression {
|
||||
Ok(x) => *x,
|
||||
Err(e) => {
|
||||
main_thread_logger.write(
|
||||
main_thread_logger
|
||||
.new_entry("configuration-error", "Configuration error")
|
||||
.message("{}; using gzip.", &[diagnostics::MessageArg::Code(e)])
|
||||
.severity(diagnostics::Severity::Warning),
|
||||
);
|
||||
trap::Compression::Gzip
|
||||
}
|
||||
};
|
||||
drop(main_thread_logger);
|
||||
|
||||
rayon::ThreadPoolBuilder::new()
|
||||
.num_threads(num_threads)
|
||||
.build_global()
|
||||
.unwrap();
|
||||
|
||||
let file_lists: Vec<File> = file_lists
|
||||
.iter()
|
||||
.map(|file_list| {
|
||||
File::open(file_list)
|
||||
.unwrap_or_else(|_| panic!("Unable to open file list at {file_list:?}"))
|
||||
})
|
||||
.collect();
|
||||
|
||||
let mut schemas = vec![];
|
||||
for lang in languages {
|
||||
schemas.push(lang.build_schema()?);
|
||||
}
|
||||
|
||||
// Construct a single globset containing all language globs,
|
||||
// and a mapping from glob index to language index.
|
||||
let (globset, glob_language_mapping) = {
|
||||
let mut builder = GlobSetBuilder::new();
|
||||
let mut glob_lang_mapping = vec![];
|
||||
for (i, lang) in languages.iter().enumerate() {
|
||||
for glob_str in lang.file_globs() {
|
||||
let glob = GlobBuilder::new(glob_str)
|
||||
.literal_separator(true)
|
||||
.build()
|
||||
.expect("invalid glob");
|
||||
builder.add(glob);
|
||||
glob_lang_mapping.push(i);
|
||||
}
|
||||
}
|
||||
(
|
||||
builder.build().expect("failed to build globset"),
|
||||
glob_lang_mapping,
|
||||
)
|
||||
};
|
||||
|
||||
let path_transformer = file_paths::load_path_transformer()?;
|
||||
|
||||
let lines: std::io::Result<Vec<String>> = file_lists
|
||||
.iter()
|
||||
.flat_map(|file_list| std::io::BufReader::new(file_list).lines())
|
||||
.collect();
|
||||
let lines = lines?;
|
||||
|
||||
lines
|
||||
.par_iter()
|
||||
.try_for_each(|line| {
|
||||
let mut diagnostics_writer = diagnostics.logger();
|
||||
let path = PathBuf::from(line).canonicalize()?;
|
||||
let src_archive_file = crate::file_paths::path_for(
|
||||
source_archive_dir,
|
||||
&path,
|
||||
"",
|
||||
path_transformer.as_ref(),
|
||||
);
|
||||
let source = std::fs::read(&path)?;
|
||||
let mut trap_writer = trap::Writer::new();
|
||||
|
||||
match path.file_name() {
|
||||
None => {
|
||||
tracing::error!(?path, "No file name found, skipping file.");
|
||||
}
|
||||
Some(filename) => {
|
||||
let matches = globset.matches(filename);
|
||||
if matches.is_empty() {
|
||||
tracing::error!(?path, "No matching language found, skipping file.");
|
||||
} else {
|
||||
let mut languages_processed = vec![false; languages.len()];
|
||||
|
||||
for m in matches {
|
||||
let i = glob_language_mapping[m];
|
||||
if languages_processed[i] {
|
||||
continue;
|
||||
}
|
||||
languages_processed[i] = true;
|
||||
let lang = &languages[i];
|
||||
|
||||
lang.extract_file(
|
||||
&schemas[i],
|
||||
&mut diagnostics_writer,
|
||||
&mut trap_writer,
|
||||
&path,
|
||||
&source,
|
||||
);
|
||||
std::fs::create_dir_all(src_archive_file.parent().unwrap())?;
|
||||
std::fs::copy(&path, &src_archive_file)?;
|
||||
write_trap(trap_dir, &path, &trap_writer, trap_compression)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(()) as std::io::Result<()>
|
||||
})
|
||||
.expect("failed to extract files");
|
||||
|
||||
let path = PathBuf::from("extras");
|
||||
let mut trap_writer = trap::Writer::new();
|
||||
crate::extractor::populate_empty_location(&mut trap_writer);
|
||||
|
||||
let res = write_trap(trap_dir, &path, &trap_writer, trap_compression);
|
||||
tracing::info!("Extraction complete");
|
||||
res
|
||||
}
|
||||
|
||||
fn write_trap(
|
||||
trap_dir: &Path,
|
||||
path: &Path,
|
||||
trap_writer: &trap::Writer,
|
||||
trap_compression: trap::Compression,
|
||||
) -> std::io::Result<()> {
|
||||
let trap_file = crate::file_paths::path_for(trap_dir, path, trap_compression.extension(), None);
|
||||
std::fs::create_dir_all(trap_file.parent().unwrap())?;
|
||||
trap_writer.write_to_file(&trap_file, trap_compression)
|
||||
}
|
||||
@@ -16,6 +16,8 @@ use tracing_subscriber::layer::SubscriberExt;
|
||||
use tracing_subscriber::util::SubscriberInitExt;
|
||||
use tree_sitter::{Language, Node, Parser, Range, Tree};
|
||||
|
||||
pub mod desugaring;
|
||||
mod driver;
|
||||
pub mod simple;
|
||||
|
||||
/// Trait abstracting over tree-sitter and yeast node types for extraction.
|
||||
@@ -294,6 +296,10 @@ pub fn location_label(writer: &mut trap::Writer, location: trap::Location) -> tr
|
||||
/// caller's responsibility, allowing it to be done once and shared across
|
||||
/// files.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
/// Extract a file with a tree-sitter grammar, walking the parse tree directly.
|
||||
/// Comments and other `extra` nodes are emitted inline as tokens. This is the
|
||||
/// path for languages that don't desugar their syntax tree (and hence have no
|
||||
/// `extra` side channel); desugaring languages use [`extract_parsed`] instead.
|
||||
pub fn extract(
|
||||
language: &Language,
|
||||
language_prefix: &str,
|
||||
@@ -304,7 +310,6 @@ pub fn extract(
|
||||
path: &Path,
|
||||
source: &[u8],
|
||||
ranges: &[Range],
|
||||
desugarer: Option<&dyn yeast::Desugarer>,
|
||||
) {
|
||||
let path_str = file_paths::normalize_and_transform_path(path, transformer);
|
||||
let source_root = std::env::current_dir()
|
||||
@@ -337,21 +342,173 @@ pub fn extract(
|
||||
schema,
|
||||
);
|
||||
|
||||
if let Some(desugarer) = desugarer {
|
||||
let ast = desugarer
|
||||
.run_from_tree(&tree, source)
|
||||
.unwrap_or_else(|e| panic!("Desugaring failed for {path_str}: {e}"));
|
||||
traverse_yeast(&ast, &mut visitor);
|
||||
// Comments and other `extra` nodes are not represented in the desugared
|
||||
// AST, so recover them directly from the original parse tree.
|
||||
traverse_extras(&tree, &mut visitor);
|
||||
} else {
|
||||
traverse(&tree, &mut visitor);
|
||||
}
|
||||
traverse(&tree, &mut visitor);
|
||||
|
||||
parser.reset();
|
||||
}
|
||||
|
||||
/// A source tree produced by a parser: the raw `yeast::Ast` (pre-desugaring)
|
||||
/// plus side-channel `extra` tokens (comments and similar) that are not
|
||||
/// attached to the AST proper.
|
||||
pub struct ParsedTree {
|
||||
pub ast: yeast::Ast,
|
||||
pub extras: Vec<ExtraToken>,
|
||||
}
|
||||
|
||||
/// A piece of side-channel `extra` content (a comment or unexpected text)
|
||||
/// recovered by a parser. `kind` is a language-defined id written verbatim into
|
||||
/// the `<lang>_trivia_tokeninfo` table (the tree-sitter parser uses the
|
||||
/// grammar's node kind id here; a custom parser supplies its own stable
|
||||
/// enumeration).
|
||||
pub struct ExtraToken {
|
||||
pub kind: usize,
|
||||
pub range: yeast::Range,
|
||||
pub text: String,
|
||||
}
|
||||
|
||||
/// Build a parser closure that parses `source` with a tree-sitter `language`,
|
||||
/// producing a [`ParsedTree`]: a `yeast::Ast` (via [`yeast::Ast::from_tree`])
|
||||
/// plus the `extra` nodes (comments and similar) recovered as side-channel
|
||||
/// tokens. This lets a tree-sitter language plug into the same
|
||||
/// `ParsedTree`-producing interface as a custom parser.
|
||||
pub fn tree_sitter_parser(
|
||||
language: tree_sitter::Language,
|
||||
) -> impl Fn(&[u8]) -> Result<ParsedTree, String> + Send + Sync {
|
||||
move |source: &[u8]| {
|
||||
let mut parser = Parser::new();
|
||||
parser
|
||||
.set_language(&language)
|
||||
.map_err(|e| format!("failed to set tree-sitter language: {e}"))?;
|
||||
let tree = parser
|
||||
.parse(source, None)
|
||||
.ok_or_else(|| "tree-sitter failed to parse".to_string())?;
|
||||
let ast = yeast::Ast::from_tree_with_schema_and_source(
|
||||
yeast::schema::from_language(&language),
|
||||
&tree,
|
||||
&language,
|
||||
source.to_vec(),
|
||||
);
|
||||
let mut extras = Vec::new();
|
||||
collect_extras(tree.root_node(), source, &mut extras);
|
||||
Ok(ParsedTree { ast, extras })
|
||||
}
|
||||
}
|
||||
|
||||
/// Collect `extra` nodes (comments and similar) under `node` into `out` as
|
||||
/// [`ExtraToken`]s, keyed by the grammar's node kind id, for a desugaring
|
||||
/// language whose rewritten AST won't retain them.
|
||||
fn collect_extras(node: Node<'_>, source: &[u8], out: &mut Vec<ExtraToken>) {
|
||||
let mut cursor = node.walk();
|
||||
for child in node.children(&mut cursor) {
|
||||
if child.is_extra() {
|
||||
let text = String::from_utf8_lossy(&source[child.byte_range()]).into_owned();
|
||||
out.push(ExtraToken {
|
||||
kind: child.kind_id() as usize,
|
||||
range: child.range().into(),
|
||||
text,
|
||||
});
|
||||
} else {
|
||||
collect_extras(child, source, out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract a file from a [`ParsedTree`]-producing parser that desugars. The
|
||||
/// parser yields a `yeast::Ast` plus side-channel `extra` tokens; the AST is
|
||||
/// rewritten through `desugarer` ([`yeast::Desugarer::run_from_ast`]) before
|
||||
/// TRAP extraction, and the `extra` tokens (comments and similar, which the
|
||||
/// desugared AST does not carry) are emitted from the side channel. Both
|
||||
/// tree-sitter grammars (via [`tree_sitter_parser`]) and custom parsers plug in
|
||||
/// here; languages that don't desugar use [`extract`] instead.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn extract_parsed(
|
||||
parse: &(dyn Fn(&[u8]) -> Result<ParsedTree, String> + Send + Sync),
|
||||
language_prefix: &str,
|
||||
schema: &NodeTypeMap,
|
||||
diagnostics_writer: &mut diagnostics::LogWriter,
|
||||
trap_writer: &mut trap::Writer,
|
||||
transformer: Option<&file_paths::PathTransformer>,
|
||||
path: &Path,
|
||||
source: &[u8],
|
||||
desugarer: &dyn yeast::Desugarer,
|
||||
) {
|
||||
let path_str = file_paths::normalize_and_transform_path(path, transformer);
|
||||
let source_root = std::env::current_dir()
|
||||
.ok()
|
||||
.and_then(|d| d.canonicalize().ok());
|
||||
let diagnostics_path = file_paths::relativize_for_diagnostic(path, source_root.as_deref());
|
||||
let span = tracing::span!(tracing::Level::TRACE, "extract", file = %path_str);
|
||||
let _enter = span.enter();
|
||||
tracing::debug!("extracting: {}", path_str);
|
||||
|
||||
trap_writer.comment(format!("Auto-generated TRAP file for {path_str}"));
|
||||
let file_label = populate_file(trap_writer, path, transformer);
|
||||
let mut visitor = Visitor::new(
|
||||
source,
|
||||
diagnostics_writer,
|
||||
trap_writer,
|
||||
&diagnostics_path,
|
||||
file_label,
|
||||
language_prefix,
|
||||
schema,
|
||||
);
|
||||
|
||||
let parsed = parse(source).unwrap_or_else(|e| panic!("Parsing failed for {path_str}: {e}"));
|
||||
let ast = desugarer
|
||||
.run_from_ast(parsed.ast)
|
||||
.unwrap_or_else(|e| panic!("Desugaring failed for {path_str}: {e}"));
|
||||
traverse_yeast(&ast, &mut visitor);
|
||||
// Comments and other `extra` tokens are not part of the desugared AST; emit
|
||||
// them directly from the parser's side channel.
|
||||
for extra in &parsed.extras {
|
||||
visitor.emit_extra(extra);
|
||||
}
|
||||
}
|
||||
|
||||
/// A lightweight [`AstNode`] over a piece of side-channel `extra` content
|
||||
/// recovered by a custom parser, so it can reuse the tree-sitter location
|
||||
/// machinery.
|
||||
struct ExtraNode {
|
||||
range: yeast::Range,
|
||||
text: String,
|
||||
}
|
||||
|
||||
impl AstNode for ExtraNode {
|
||||
fn kind(&self) -> &str {
|
||||
"extra"
|
||||
}
|
||||
fn is_named(&self) -> bool {
|
||||
false
|
||||
}
|
||||
fn is_missing(&self) -> bool {
|
||||
false
|
||||
}
|
||||
fn is_error(&self) -> bool {
|
||||
false
|
||||
}
|
||||
fn is_extra(&self) -> bool {
|
||||
true
|
||||
}
|
||||
fn start_position(&self) -> tree_sitter::Point {
|
||||
tree_sitter::Point {
|
||||
row: self.range.start_point.row,
|
||||
column: self.range.start_point.column,
|
||||
}
|
||||
}
|
||||
fn end_position(&self) -> tree_sitter::Point {
|
||||
tree_sitter::Point {
|
||||
row: self.range.end_point.row,
|
||||
column: self.range.end_point.column,
|
||||
}
|
||||
}
|
||||
fn byte_range(&self) -> std::ops::Range<usize> {
|
||||
self.range.start_byte..self.range.end_byte
|
||||
}
|
||||
fn opt_string_content(&self) -> Option<String> {
|
||||
Some(self.text.clone())
|
||||
}
|
||||
}
|
||||
|
||||
struct ChildNode {
|
||||
field_name: Option<&'static str>,
|
||||
label: trap::Label,
|
||||
@@ -415,10 +572,11 @@ impl<'a> Visitor<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Emits a `TriviaToken` for the given `extra` node (e.g. a comment) from
|
||||
/// the original parse tree. Trivia tokens carry a location and their source
|
||||
/// text, but are not attached to a parent in the (possibly desugared) AST.
|
||||
fn emit_trivia_token(&mut self, node: &Node) {
|
||||
/// Emit an `extra` token (a location row plus a `trivia_tokeninfo` row) for
|
||||
/// any [`AstNode`], with an explicit `kind` id. Shared by the tree-sitter
|
||||
/// path (kind = the grammar's node kind id) and the custom-parser path
|
||||
/// (kind = a language-defined `extra` kind id).
|
||||
fn emit_extra_from<N: AstNode>(&mut self, node: &N, kind: usize) {
|
||||
let id = self.trap_writer.fresh_id();
|
||||
let loc = location_for(self, self.file_label, node);
|
||||
let loc_label = location_label(self.trap_writer, loc);
|
||||
@@ -430,12 +588,21 @@ impl<'a> Visitor<'a> {
|
||||
&self.trivia_tokeninfo_table_name,
|
||||
vec![
|
||||
trap::Arg::Label(id),
|
||||
trap::Arg::Int(node.kind_id() as usize),
|
||||
trap::Arg::Int(kind),
|
||||
sliced_source_arg(self.source, node),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// Emit an `extra` token recovered from a parser's side channel.
|
||||
fn emit_extra(&mut self, extra: &ExtraToken) {
|
||||
let node = ExtraNode {
|
||||
range: extra.range,
|
||||
text: extra.text.clone(),
|
||||
};
|
||||
self.emit_extra_from(&node, extra.kind);
|
||||
}
|
||||
|
||||
fn record_parse_error(&mut self, loc: trap::Label, mesg: &diagnostics::DiagnosticMessage) {
|
||||
self.diagnostics_writer.write(mesg);
|
||||
let id = self.trap_writer.fresh_id();
|
||||
@@ -871,24 +1038,6 @@ fn traverse(tree: &Tree, visitor: &mut Visitor) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Walks the original tree-sitter tree and emits a `TriviaToken` for every
|
||||
/// `extra` node (e.g. a comment). Used to preserve comments that would
|
||||
/// otherwise be lost after a desugaring pass rewrites the tree.
|
||||
fn traverse_extras(tree: &Tree, visitor: &mut Visitor) {
|
||||
emit_extras_in(visitor, tree.root_node());
|
||||
}
|
||||
|
||||
fn emit_extras_in(visitor: &mut Visitor, node: Node<'_>) {
|
||||
let mut cursor = node.walk();
|
||||
for child in node.children(&mut cursor) {
|
||||
if child.is_extra() {
|
||||
visitor.emit_trivia_token(&child);
|
||||
} else {
|
||||
emit_extras_in(visitor, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn traverse_yeast(tree: &yeast::Ast, visitor: &mut Visitor) {
|
||||
let mut cursor = tree.walk();
|
||||
visitor.enter_node(cursor.node());
|
||||
|
||||
@@ -1,29 +1,52 @@
|
||||
use crate::{file_paths, trap};
|
||||
use globset::{GlobBuilder, GlobSetBuilder};
|
||||
use rayon::prelude::*;
|
||||
use std::fs::File;
|
||||
use std::io::BufRead;
|
||||
use std::path::{Path, PathBuf};
|
||||
use crate::trap;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::diagnostics;
|
||||
use crate::node_types;
|
||||
use yeast;
|
||||
use crate::extractor::driver::{self, LanguageExtractor};
|
||||
use crate::node_types::{self, NodeTypeMap};
|
||||
|
||||
/// A tree-sitter language extracted directly from its parse tree, with no
|
||||
/// desugaring. Comments and other `extra` nodes are emitted inline as tokens.
|
||||
/// Languages that rewrite their syntax tree use
|
||||
/// [`crate::extractor::desugaring`] instead.
|
||||
pub struct LanguageSpec {
|
||||
pub prefix: &'static str,
|
||||
pub ts_language: tree_sitter::Language,
|
||||
pub node_types: &'static str,
|
||||
/// Optional desugarer. When set, the parsed tree is rewritten through
|
||||
/// the desugarer before TRAP extraction. The desugarer's
|
||||
/// `output_node_types_yaml()` (if set) provides the schema used both
|
||||
/// at runtime (for the rewriter) and for TRAP validation.
|
||||
///
|
||||
/// `Box<dyn yeast::Desugarer>` so the shared extractor is agnostic to
|
||||
/// the user-defined context type the desugarer uses internally.
|
||||
pub desugar: Option<Box<dyn yeast::Desugarer>>,
|
||||
pub file_globs: Vec<String>,
|
||||
}
|
||||
|
||||
impl LanguageExtractor for LanguageSpec {
|
||||
fn file_globs(&self) -> &[String] {
|
||||
&self.file_globs
|
||||
}
|
||||
|
||||
fn build_schema(&self) -> std::io::Result<NodeTypeMap> {
|
||||
node_types::read_node_types_str(self.prefix, self.node_types)
|
||||
}
|
||||
|
||||
fn extract_file(
|
||||
&self,
|
||||
schema: &NodeTypeMap,
|
||||
diagnostics_writer: &mut diagnostics::LogWriter,
|
||||
trap_writer: &mut trap::Writer,
|
||||
path: &std::path::Path,
|
||||
source: &[u8],
|
||||
) {
|
||||
crate::extractor::extract(
|
||||
&self.ts_language,
|
||||
self.prefix,
|
||||
schema,
|
||||
diagnostics_writer,
|
||||
trap_writer,
|
||||
None,
|
||||
path,
|
||||
source,
|
||||
&[],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Extractor {
|
||||
pub prefix: String,
|
||||
pub languages: Vec<LanguageSpec>,
|
||||
@@ -38,182 +61,13 @@ pub struct Extractor {
|
||||
|
||||
impl Extractor {
|
||||
pub fn run(&self) -> std::io::Result<()> {
|
||||
tracing::info!("Extraction started");
|
||||
let diagnostics = diagnostics::DiagnosticLoggers::new(&self.prefix);
|
||||
let mut main_thread_logger = diagnostics.logger();
|
||||
let num_threads = match crate::options::num_threads() {
|
||||
Ok(num) => num,
|
||||
Err(e) => {
|
||||
main_thread_logger.write(
|
||||
main_thread_logger
|
||||
.new_entry("configuration-error", "Configuration error")
|
||||
.message(
|
||||
"{}; defaulting to 1 thread.",
|
||||
&[diagnostics::MessageArg::Code(&e)],
|
||||
)
|
||||
.severity(diagnostics::Severity::Warning),
|
||||
);
|
||||
1
|
||||
}
|
||||
};
|
||||
tracing::info!(
|
||||
"Using {} {}",
|
||||
num_threads,
|
||||
if num_threads == 1 {
|
||||
"thread"
|
||||
} else {
|
||||
"threads"
|
||||
}
|
||||
);
|
||||
let trap_compression = match &self.trap_compression {
|
||||
Ok(x) => *x,
|
||||
Err(e) => {
|
||||
main_thread_logger.write(
|
||||
main_thread_logger
|
||||
.new_entry("configuration-error", "Configuration error")
|
||||
.message("{}; using gzip.", &[diagnostics::MessageArg::Code(e)])
|
||||
.severity(diagnostics::Severity::Warning),
|
||||
);
|
||||
trap::Compression::Gzip
|
||||
}
|
||||
};
|
||||
drop(main_thread_logger);
|
||||
|
||||
rayon::ThreadPoolBuilder::new()
|
||||
.num_threads(num_threads)
|
||||
.build_global()
|
||||
.unwrap();
|
||||
|
||||
let file_lists: Vec<File> = self
|
||||
.file_lists
|
||||
.iter()
|
||||
.map(|file_list| {
|
||||
File::open(file_list)
|
||||
.unwrap_or_else(|_| panic!("Unable to open file list at {file_list:?}"))
|
||||
})
|
||||
.collect();
|
||||
|
||||
let mut schemas = vec![];
|
||||
for lang in &self.languages {
|
||||
let effective_node_types: String = match lang
|
||||
.desugar
|
||||
.as_ref()
|
||||
.and_then(|d| d.output_node_types_yaml())
|
||||
{
|
||||
Some(yaml) => yeast::node_types_yaml::convert(yaml).map_err(|e| {
|
||||
std::io::Error::other(format!(
|
||||
"Failed to convert YAML node-types to JSON for {}: {e}",
|
||||
lang.prefix
|
||||
))
|
||||
})?,
|
||||
None => lang.node_types.to_string(),
|
||||
};
|
||||
let schema = node_types::read_node_types_str(lang.prefix, &effective_node_types)?;
|
||||
schemas.push(schema);
|
||||
}
|
||||
|
||||
// Construct a single globset containing all language globs,
|
||||
// and a mapping from glob index to language index.
|
||||
let (globset, glob_language_mapping) = {
|
||||
let mut builder = GlobSetBuilder::new();
|
||||
let mut glob_lang_mapping = vec![];
|
||||
for (i, lang) in self.languages.iter().enumerate() {
|
||||
for glob_str in &lang.file_globs {
|
||||
let glob = GlobBuilder::new(glob_str)
|
||||
.literal_separator(true)
|
||||
.build()
|
||||
.expect("invalid glob");
|
||||
builder.add(glob);
|
||||
glob_lang_mapping.push(i);
|
||||
}
|
||||
}
|
||||
(
|
||||
builder.build().expect("failed to build globset"),
|
||||
glob_lang_mapping,
|
||||
)
|
||||
};
|
||||
|
||||
let path_transformer = file_paths::load_path_transformer()?;
|
||||
|
||||
let lines: std::io::Result<Vec<String>> = file_lists
|
||||
.iter()
|
||||
.flat_map(|file_list| std::io::BufReader::new(file_list).lines())
|
||||
.collect();
|
||||
let lines = lines?;
|
||||
|
||||
lines
|
||||
.par_iter()
|
||||
.try_for_each(|line| {
|
||||
let mut diagnostics_writer = diagnostics.logger();
|
||||
let path = PathBuf::from(line).canonicalize()?;
|
||||
let src_archive_file = crate::file_paths::path_for(
|
||||
&self.source_archive_dir,
|
||||
&path,
|
||||
"",
|
||||
path_transformer.as_ref(),
|
||||
);
|
||||
let source = std::fs::read(&path)?;
|
||||
let mut trap_writer = trap::Writer::new();
|
||||
|
||||
match path.file_name() {
|
||||
None => {
|
||||
tracing::error!(?path, "No file name found, skipping file.");
|
||||
}
|
||||
Some(filename) => {
|
||||
let matches = globset.matches(filename);
|
||||
if matches.is_empty() {
|
||||
tracing::error!(?path, "No matching language found, skipping file.");
|
||||
} else {
|
||||
let mut languages_processed = vec![false; self.languages.len()];
|
||||
|
||||
for m in matches {
|
||||
let i = glob_language_mapping[m];
|
||||
if languages_processed[i] {
|
||||
continue;
|
||||
}
|
||||
languages_processed[i] = true;
|
||||
let lang = &self.languages[i];
|
||||
|
||||
crate::extractor::extract(
|
||||
&lang.ts_language,
|
||||
lang.prefix,
|
||||
&schemas[i],
|
||||
&mut diagnostics_writer,
|
||||
&mut trap_writer,
|
||||
None,
|
||||
&path,
|
||||
&source,
|
||||
&[],
|
||||
lang.desugar.as_deref(),
|
||||
);
|
||||
std::fs::create_dir_all(src_archive_file.parent().unwrap())?;
|
||||
std::fs::copy(&path, &src_archive_file)?;
|
||||
write_trap(&self.trap_dir, &path, &trap_writer, trap_compression)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(()) as std::io::Result<()>
|
||||
})
|
||||
.expect("failed to extract files");
|
||||
|
||||
let path = PathBuf::from("extras");
|
||||
let mut trap_writer = trap::Writer::new();
|
||||
crate::extractor::populate_empty_location(&mut trap_writer);
|
||||
|
||||
let res = write_trap(&self.trap_dir, &path, &trap_writer, trap_compression);
|
||||
tracing::info!("Extraction complete");
|
||||
res
|
||||
driver::run_extractor(
|
||||
&self.prefix,
|
||||
&self.languages,
|
||||
&self.trap_dir,
|
||||
&self.source_archive_dir,
|
||||
&self.file_lists,
|
||||
&self.trap_compression,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn write_trap(
|
||||
trap_dir: &Path,
|
||||
path: &Path,
|
||||
trap_writer: &trap::Writer,
|
||||
trap_compression: trap::Compression,
|
||||
) -> std::io::Result<()> {
|
||||
let trap_file = crate::file_paths::path_for(trap_dir, path, trap_compression.extension(), None);
|
||||
std::fs::create_dir_all(trap_file.parent().unwrap())?;
|
||||
trap_writer.write_to_file(&trap_file, trap_compression)
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ fn simple_extractor() {
|
||||
prefix: "ql",
|
||||
ts_language: tree_sitter_ql::LANGUAGE.into(),
|
||||
node_types: tree_sitter_ql::NODE_TYPES,
|
||||
desugar: None,
|
||||
file_globs: vec!["*.qll".into()],
|
||||
};
|
||||
|
||||
|
||||
@@ -13,14 +13,12 @@ fn multiple_language_extractor() {
|
||||
prefix: "ql",
|
||||
ts_language: tree_sitter_ql::LANGUAGE.into(),
|
||||
node_types: tree_sitter_ql::NODE_TYPES,
|
||||
desugar: None,
|
||||
file_globs: vec!["*.qll".into()],
|
||||
};
|
||||
let lang_json = simple::LanguageSpec {
|
||||
prefix: "json",
|
||||
ts_language: tree_sitter_json::LANGUAGE.into(),
|
||||
node_types: tree_sitter_json::NODE_TYPES,
|
||||
desugar: None,
|
||||
file_globs: vec!["*.json".into(), "*Jsonfile".into()],
|
||||
};
|
||||
|
||||
|
||||
@@ -252,6 +252,41 @@ pub fn extend_schema_from_yaml(
|
||||
let yaml: YamlNodeTypes =
|
||||
serde_yaml::from_str(yaml_input).map_err(|e| format!("Failed to parse YAML: {e}"))?;
|
||||
apply_yaml_to_schema(&yaml, schema);
|
||||
// The typed `YamlNodeTypes` stores each node's fields in a `BTreeMap`
|
||||
// (alphabetical), losing the authored order. Re-parse as an ordered value to
|
||||
// record the declared field order for presentation (see the AST dump).
|
||||
record_field_order(schema, yaml_input)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Record each node kind's declared (named) field order from the source YAML,
|
||||
/// which `serde`'s `BTreeMap`-based deserialization does not preserve.
|
||||
/// `serde_yaml::Value` mappings keep insertion (source) order.
|
||||
fn record_field_order(schema: &mut crate::schema::Schema, yaml_input: &str) -> Result<(), String> {
|
||||
let value: serde_yaml::Value = serde_yaml::from_str(yaml_input)
|
||||
.map_err(|e| format!("Failed to parse YAML for field order: {e}"))?;
|
||||
let Some(named) = value.get("named").and_then(|v| v.as_mapping()) else {
|
||||
return Ok(());
|
||||
};
|
||||
for (node_name, fields) in named {
|
||||
let Some(node_name) = node_name.as_str() else {
|
||||
continue;
|
||||
};
|
||||
let Some(fields) = fields.as_mapping() else {
|
||||
continue; // node with no fields (null)
|
||||
};
|
||||
let mut order = Vec::new();
|
||||
for (raw_field_name, _) in fields {
|
||||
let Some(raw) = raw_field_name.as_str() else {
|
||||
continue;
|
||||
};
|
||||
// Skip the unnamed/`child` slot; the dump handles it separately.
|
||||
if let Some(name) = parse_field_name(raw).name {
|
||||
order.push(schema.register_field(&name));
|
||||
}
|
||||
}
|
||||
schema.set_field_order(node_name, order);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,11 @@ pub struct Schema {
|
||||
field_types: BTreeMap<(String, FieldId), Vec<NodeType>>,
|
||||
field_cardinalities: BTreeMap<(String, FieldId), FieldCardinality>,
|
||||
supertypes: BTreeMap<String, Vec<NodeType>>,
|
||||
/// Per-node-kind declared field order (named fields only), as written in
|
||||
/// the source node-types YAML. Field ids are not a stable ordering key
|
||||
/// across front-ends, so this preserves the authored order for
|
||||
/// presentation (see the AST dump).
|
||||
field_order: BTreeMap<String, Vec<FieldId>>,
|
||||
}
|
||||
|
||||
impl Default for Schema {
|
||||
@@ -65,6 +70,7 @@ impl Schema {
|
||||
field_types: BTreeMap::new(),
|
||||
field_cardinalities: BTreeMap::new(),
|
||||
supertypes: BTreeMap::new(),
|
||||
field_order: BTreeMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,6 +275,17 @@ impl Schema {
|
||||
.get(&(parent_kind.to_string(), field_id))
|
||||
}
|
||||
|
||||
/// Record the declared (named) field order for a node kind, as authored in
|
||||
/// the source node-types YAML.
|
||||
pub fn set_field_order(&mut self, kind: &str, field_ids: Vec<FieldId>) {
|
||||
self.field_order.insert(kind.to_string(), field_ids);
|
||||
}
|
||||
|
||||
/// The declared (named) field order for a node kind, if known.
|
||||
pub fn field_order(&self, kind: &str) -> Option<&Vec<FieldId>> {
|
||||
self.field_order.get(kind)
|
||||
}
|
||||
|
||||
pub fn set_field_cardinality(
|
||||
&mut self,
|
||||
parent_kind: &str,
|
||||
|
||||
@@ -108,6 +108,17 @@ impl<'a, C> BuildCtx<'a, C> {
|
||||
self.captures.get_all(name)
|
||||
}
|
||||
|
||||
/// Read the source text of a captured (or any other) node.
|
||||
///
|
||||
/// Convenience for the common `ctx.ast.source_text(id)` reach-through used
|
||||
/// by Rust-block rules that branch on, or embed, a raw capture's spelling
|
||||
/// (e.g. an operator or keyword token). Resolves against the stored source
|
||||
/// bytes, so it works for both parsed nodes and synthesized ones (via their
|
||||
/// inherited source range).
|
||||
pub fn source_text(&self, id: Id) -> String {
|
||||
self.ast.source_text(id)
|
||||
}
|
||||
|
||||
/// Create a named AST node with the given kind and fields.
|
||||
pub fn node(&mut self, kind: &str, fields: Vec<(&str, Vec<Id>)>) -> Id {
|
||||
let kind_id = self
|
||||
|
||||
@@ -162,8 +162,12 @@ fn type_error_for_node(
|
||||
fn expected_for_field<'a>(
|
||||
schema: &'a Schema,
|
||||
parent_kind: &str,
|
||||
field_id: u16,
|
||||
field_name: &str,
|
||||
) -> Option<&'a [crate::schema::NodeType]> {
|
||||
// Resolve the field NAME in the validation schema's own id space, so the
|
||||
// AST being dumped and the validation schema stay completely independent:
|
||||
// they need not share field ids, only field names.
|
||||
let field_id = schema.field_id_for_name(field_name)?;
|
||||
schema
|
||||
.field_types(parent_kind, field_id)
|
||||
.map(|v| v.as_slice())
|
||||
@@ -223,15 +227,49 @@ fn dump_node(
|
||||
|
||||
writeln!(out).unwrap();
|
||||
|
||||
// Named fields first
|
||||
for (&field_id, children) in &node.fields {
|
||||
if field_id == CHILD_FIELD {
|
||||
continue; // Handle unnamed children last
|
||||
// Named fields first, in the schema's declared order when available
|
||||
// (front-end-independent), else in field-id order. Any present fields not
|
||||
// covered by the declared order are appended in field-id order.
|
||||
//
|
||||
// The declared order lives in the validation schema, keyed by *its* field
|
||||
// ids; the AST being dumped may key the same field names under different
|
||||
// ids. So map the declared order through field NAMES into this AST's own id
|
||||
// space, keeping the two schemas independent (they share names, not ids).
|
||||
let named_field_ids: Vec<u16> = {
|
||||
let present: Vec<u16> = node
|
||||
.fields
|
||||
.keys()
|
||||
.copied()
|
||||
.filter(|&f| f != CHILD_FIELD)
|
||||
.collect();
|
||||
match type_check.and_then(|(schema, _, _)| {
|
||||
schema
|
||||
.field_order(node.kind_name())
|
||||
.map(|order| (schema, order))
|
||||
}) {
|
||||
Some((schema, order)) => {
|
||||
let mut result: Vec<u16> = order
|
||||
.iter()
|
||||
.filter_map(|&f| schema.field_name_for_id(f))
|
||||
.filter_map(|name| ast.field_id_for_name(name))
|
||||
.filter(|&f| f != CHILD_FIELD && node.fields.contains_key(&f))
|
||||
.collect();
|
||||
for &f in &present {
|
||||
if !result.contains(&f) {
|
||||
result.push(f);
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
None => present,
|
||||
}
|
||||
};
|
||||
for field_id in named_field_ids {
|
||||
let children = &node.fields[&field_id];
|
||||
let field_name = ast.field_name_for_id(field_id).unwrap_or("?");
|
||||
let child_type_check = type_check.map(|(schema, _, _)| {
|
||||
let expected =
|
||||
expected_for_field(schema, node.kind_name(), field_id).or(Some(EMPTY_NODE_TYPES));
|
||||
let expected = expected_for_field(schema, node.kind_name(), field_name)
|
||||
.or(Some(EMPTY_NODE_TYPES));
|
||||
let parent_field = Some((node.kind_name(), field_name));
|
||||
(schema, expected, parent_field)
|
||||
});
|
||||
@@ -273,8 +311,14 @@ fn dump_node(
|
||||
|
||||
// Check for required fields that are absent
|
||||
if let Some((schema, _, _)) = type_check {
|
||||
for (field_id, field_name) in schema.required_fields_for_kind(node.kind_name()) {
|
||||
if !node.fields.contains_key(&field_id) {
|
||||
for (_field_id, field_name) in schema.required_fields_for_kind(node.kind_name()) {
|
||||
let present = match field_name {
|
||||
Some(n) => ast
|
||||
.field_id_for_name(n)
|
||||
.is_some_and(|fid| node.fields.contains_key(&fid)),
|
||||
None => node.fields.contains_key(&CHILD_FIELD),
|
||||
};
|
||||
if !present {
|
||||
let name = field_name.unwrap_or("child");
|
||||
writeln!(out, "{prefix} <-- ERROR: missing required field '{name}'").unwrap();
|
||||
}
|
||||
@@ -284,7 +328,9 @@ fn dump_node(
|
||||
// Unnamed children — skip unnamed tokens (keywords, punctuation)
|
||||
if let Some(children) = node.fields.get(&CHILD_FIELD) {
|
||||
let child_type_check = type_check.map(|(schema, _, _)| {
|
||||
let expected = expected_for_field(schema, node.kind_name(), CHILD_FIELD)
|
||||
let expected = schema
|
||||
.field_types(node.kind_name(), CHILD_FIELD)
|
||||
.map(|v| v.as_slice())
|
||||
.or(Some(EMPTY_NODE_TYPES));
|
||||
let parent_field = Some((node.kind_name(), "children"));
|
||||
(schema, expected, parent_field)
|
||||
|
||||
@@ -1329,10 +1329,27 @@ impl<C> DesugaringConfig<C> {
|
||||
None => Ok(schema::from_language(language)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Build the yeast `Schema` from the output YAML alone, with no input
|
||||
/// tree-sitter grammar. Requires `output_node_types_yaml` to be set (there
|
||||
/// is no grammar to fall back to). Used by custom (non-tree-sitter)
|
||||
/// front-ends whose input schema is supplied by their own parser/adapter.
|
||||
pub fn build_schema_no_language(&self) -> Result<schema::Schema, String> {
|
||||
match self.output_node_types_yaml {
|
||||
Some(yaml) => node_types_yaml::schema_from_yaml(yaml),
|
||||
None => Err(
|
||||
"a language-free desugarer requires output_node_types_yaml to be set".to_string(),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Runner<'a, C = ()> {
|
||||
language: tree_sitter::Language,
|
||||
/// The input tree-sitter language, used only when parsing (`run_from_tree`
|
||||
/// / `run`). `None` for pipelines that only ever run over an
|
||||
/// externally-built AST (`run_from_ast`), so no tree-sitter grammar is
|
||||
/// required.
|
||||
language: Option<tree_sitter::Language>,
|
||||
schema: schema::Schema,
|
||||
phases: &'a [Phase<C>],
|
||||
}
|
||||
@@ -1342,7 +1359,7 @@ impl<'a, C> Runner<'a, C> {
|
||||
pub fn new(language: tree_sitter::Language, phases: &'a [Phase<C>]) -> Self {
|
||||
let schema = schema::from_language(&language);
|
||||
Self {
|
||||
language,
|
||||
language: Some(language),
|
||||
schema,
|
||||
phases,
|
||||
}
|
||||
@@ -1355,7 +1372,18 @@ impl<'a, C> Runner<'a, C> {
|
||||
phases: &'a [Phase<C>],
|
||||
) -> Self {
|
||||
Self {
|
||||
language,
|
||||
language: Some(language),
|
||||
schema: schema.clone(),
|
||||
phases,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a runner with no input tree-sitter language, for pipelines that
|
||||
/// only run over an externally-built AST (`run_from_ast`). The parsing
|
||||
/// entry points (`run_from_tree` / `run`) will error if called.
|
||||
pub fn with_schema_no_language(schema: &schema::Schema, phases: &'a [Phase<C>]) -> Self {
|
||||
Self {
|
||||
language: None,
|
||||
schema: schema.clone(),
|
||||
phases,
|
||||
}
|
||||
@@ -1368,7 +1396,7 @@ impl<'a, C> Runner<'a, C> {
|
||||
) -> Result<Self, String> {
|
||||
let schema = config.build_schema(&language)?;
|
||||
Ok(Self {
|
||||
language,
|
||||
language: Some(language),
|
||||
schema,
|
||||
phases: &config.phases,
|
||||
})
|
||||
@@ -1388,7 +1416,9 @@ impl<'a, C: Clone> Runner<'a, C> {
|
||||
let mut ast = Ast::from_tree_with_schema_and_source(
|
||||
self.schema.clone(),
|
||||
tree,
|
||||
&self.language,
|
||||
self.language
|
||||
.as_ref()
|
||||
.ok_or("run_from_tree requires a tree-sitter language")?,
|
||||
source.to_vec(),
|
||||
);
|
||||
self.run_phases(&mut ast, user_ctx)?;
|
||||
@@ -1398,9 +1428,13 @@ impl<'a, C: Clone> Runner<'a, C> {
|
||||
/// Parse `input` and run all phases, threading `user_ctx` through
|
||||
/// every rule transform. The caller owns the initial context state.
|
||||
pub fn run_with_ctx(&self, input: &str, user_ctx: &mut C) -> Result<Ast, String> {
|
||||
let language = self
|
||||
.language
|
||||
.as_ref()
|
||||
.ok_or("run requires a tree-sitter language")?;
|
||||
let mut parser = tree_sitter::Parser::new();
|
||||
parser
|
||||
.set_language(&self.language)
|
||||
.set_language(language)
|
||||
.map_err(|e| format!("Failed to set language: {e}"))?;
|
||||
let tree = parser
|
||||
.parse(input, None)
|
||||
@@ -1408,7 +1442,7 @@ impl<'a, C: Clone> Runner<'a, C> {
|
||||
let mut ast = Ast::from_tree_with_schema_and_source(
|
||||
self.schema.clone(),
|
||||
&tree,
|
||||
&self.language,
|
||||
language,
|
||||
input.as_bytes().to_vec(),
|
||||
);
|
||||
self.run_phases(&mut ast, user_ctx)?;
|
||||
@@ -1506,7 +1540,10 @@ pub trait Desugarer: Send + Sync {
|
||||
/// schema so that per-call cost is bounded to constructing a transient
|
||||
/// [`Runner`] and cloning the schema (no YAML re-parsing).
|
||||
pub struct ConcreteDesugarer<C: Default + Clone + Send + Sync + 'static> {
|
||||
language: tree_sitter::Language,
|
||||
/// The input tree-sitter language, or `None` for a custom (non-tree-sitter)
|
||||
/// front-end that only ever desugars an externally-built AST
|
||||
/// (`run_from_ast`).
|
||||
language: Option<tree_sitter::Language>,
|
||||
schema: schema::Schema,
|
||||
config: DesugaringConfig<C>,
|
||||
}
|
||||
@@ -1520,7 +1557,20 @@ impl<C: Default + Clone + Send + Sync + 'static> ConcreteDesugarer<C> {
|
||||
) -> Result<Self, String> {
|
||||
let schema = config.build_schema(&language)?;
|
||||
Ok(Self {
|
||||
language,
|
||||
language: Some(language),
|
||||
schema,
|
||||
config,
|
||||
})
|
||||
}
|
||||
|
||||
/// Build a desugarer with no input tree-sitter language, for a custom
|
||||
/// front-end whose parser supplies the input AST directly. Only
|
||||
/// [`run_from_ast`](Desugarer::run_from_ast) is supported; the schema comes
|
||||
/// from the config's `output_node_types_yaml` (which must be set).
|
||||
pub fn without_language(config: DesugaringConfig<C>) -> Result<Self, String> {
|
||||
let schema = config.build_schema_no_language()?;
|
||||
Ok(Self {
|
||||
language: None,
|
||||
schema,
|
||||
config,
|
||||
})
|
||||
@@ -1533,7 +1583,11 @@ impl<C: Default + Clone + Send + Sync + 'static> Desugarer for ConcreteDesugarer
|
||||
}
|
||||
|
||||
fn run_from_tree(&self, tree: &tree_sitter::Tree, source: &[u8]) -> Result<Ast, String> {
|
||||
let runner = Runner::with_schema(self.language.clone(), &self.schema, &self.config.phases);
|
||||
let language = self
|
||||
.language
|
||||
.clone()
|
||||
.ok_or("run_from_tree requires a tree-sitter language")?;
|
||||
let runner = Runner::with_schema(language, &self.schema, &self.config.phases);
|
||||
runner.run_from_tree(tree, source)
|
||||
}
|
||||
|
||||
@@ -1541,7 +1595,8 @@ impl<C: Default + Clone + Send + Sync + 'static> Desugarer for ConcreteDesugarer
|
||||
// The AST was built against its own (external) schema; make sure the
|
||||
// output kind/field names the rules build are resolvable in it.
|
||||
ast.register_names_from_schema(&self.schema);
|
||||
let runner = Runner::with_schema(self.language.clone(), &self.schema, &self.config.phases);
|
||||
// `run_from_ast` never parses, so no tree-sitter language is needed.
|
||||
let runner = Runner::with_schema_no_language(&self.schema, &self.config.phases);
|
||||
runner.run_from_ast(ast)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
load("@rules_pkg//pkg:mappings.bzl", "pkg_filegroup")
|
||||
load("//misc/bazel:pkg.bzl", "codeql_pack", "codeql_pkg_files")
|
||||
load("//misc/bazel:utils.bzl", "select_os")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
@@ -46,12 +47,26 @@ codeql_pkg_files(
|
||||
prefix = "tools/{CODEQL_PLATFORM}",
|
||||
)
|
||||
|
||||
# The Swift front-end parser (wrapper + real binary + bundled Swift runtime),
|
||||
# shipped next to the extractor. Only on platforms where swift-syntax builds
|
||||
# (Linux/macOS); elsewhere the group is empty so the pack still builds (Swift
|
||||
# extraction is simply unavailable there).
|
||||
pkg_filegroup(
|
||||
name = "swift-syntax-parse-arch",
|
||||
srcs = select_os(
|
||||
otherwise = [],
|
||||
posix = ["//unified/swift-syntax-rs:swift-syntax-parse-pkg"],
|
||||
),
|
||||
prefix = "tools/{CODEQL_PLATFORM}",
|
||||
)
|
||||
|
||||
codeql_pack(
|
||||
name = "unified",
|
||||
srcs = [
|
||||
":codeql-extractor-yml",
|
||||
":dbscheme-group",
|
||||
":extractor-arch",
|
||||
":swift-syntax-parse-arch",
|
||||
"//unified/tools",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -7,7 +7,10 @@ codeql_rust_binary(
|
||||
name = "extractor",
|
||||
srcs = glob(["src/**/*.rs"]),
|
||||
aliases = aliases(),
|
||||
compile_data = ["ast_types.yml"],
|
||||
compile_data = [
|
||||
"ast_types.yml",
|
||||
"swift_node_types.yml",
|
||||
],
|
||||
proc_macro_deps = all_crate_deps(
|
||||
proc_macro = True,
|
||||
),
|
||||
|
||||
@@ -31,6 +31,7 @@ supertypes:
|
||||
- throw_expr
|
||||
- try_expr
|
||||
- switch_expr
|
||||
- unresolved_operator_sequence
|
||||
- unsupported_node
|
||||
expr_or_pattern:
|
||||
- expr
|
||||
@@ -38,6 +39,11 @@ supertypes:
|
||||
expr_or_type:
|
||||
- expr
|
||||
- type_expr
|
||||
# An element of an `unresolved_operator_sequence`: either an operand (`expr`)
|
||||
# or one of the infix operators separating the operands.
|
||||
expr_or_operator:
|
||||
- expr
|
||||
- infix_operator
|
||||
pattern:
|
||||
- name_pattern
|
||||
- tuple_pattern
|
||||
@@ -137,6 +143,19 @@ named:
|
||||
operand: expr
|
||||
operator: operator
|
||||
|
||||
# A flat, unresolved operator sequence such as `a <+> b <+> c`.
|
||||
#
|
||||
# Swift's grammar doesn't encode operator precedence, so an operator chain is
|
||||
# first parsed as a flat list of operands and operators. The parser front-end
|
||||
# resolves this into structured `binary_expr` trees when it knows the
|
||||
# operators' precedence (standard-library operators, and operators declared in
|
||||
# the same file). When it encounters an operator whose precedence it can't
|
||||
# determine (e.g. one imported from another module), it leaves that chain
|
||||
# unresolved and emits it here rather than guessing a (possibly wrong)
|
||||
# structure. The `element`s alternate operands (`expr`) and infix operators.
|
||||
unresolved_operator_sequence:
|
||||
element*: expr_or_operator
|
||||
|
||||
# Plain assignment
|
||||
assign_expr:
|
||||
target: expr_or_pattern
|
||||
|
||||
@@ -2,7 +2,7 @@ use clap::Args;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::languages;
|
||||
use codeql_extractor::extractor::simple;
|
||||
use codeql_extractor::extractor::desugaring;
|
||||
use codeql_extractor::trap;
|
||||
|
||||
#[derive(Args)]
|
||||
@@ -31,7 +31,7 @@ pub fn run(options: Options) -> std::io::Result<()> {
|
||||
lang.prefix = "unified";
|
||||
}
|
||||
|
||||
let extractor = simple::Extractor {
|
||||
let extractor = desugaring::Extractor {
|
||||
prefix: "unified".to_string(),
|
||||
languages,
|
||||
trap_dir: options.output_dir,
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
use codeql_extractor::extractor::simple;
|
||||
use codeql_extractor::extractor::desugaring;
|
||||
|
||||
#[path = "swift/swift.rs"]
|
||||
mod swift;
|
||||
|
||||
/// swift-syntax JSON -> `yeast::Ast` adapter for the Swift front-end.
|
||||
///
|
||||
/// Currently exercised by tests and the forthcoming runtime extraction path;
|
||||
/// `allow(dead_code)` because this is a binary crate, so its public API isn't
|
||||
/// counted as used until the binary itself calls it.
|
||||
#[path = "swift/adapter.rs"]
|
||||
#[allow(dead_code)]
|
||||
pub mod swift_adapter;
|
||||
|
||||
/// Swift front-end parser: shells out to `swift-syntax-parse` and adapts its
|
||||
/// JSON output via [`swift_adapter`]. This is the live Swift front-end used by
|
||||
/// [`all_language_specs`].
|
||||
#[path = "swift/parse.rs"]
|
||||
pub mod swift_parse;
|
||||
|
||||
/// Shared YEAST output AST schema for all languages.
|
||||
pub(crate) const OUTPUT_AST_SCHEMA: &str = include_str!("../../ast_types.yml");
|
||||
|
||||
pub fn all_language_specs() -> Vec<simple::LanguageSpec> {
|
||||
pub fn all_language_specs() -> Vec<desugaring::LanguageSpec> {
|
||||
vec![swift::language_spec(OUTPUT_AST_SCHEMA)]
|
||||
}
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
//! in-memory format the CodeQL desugaring rules operate on.
|
||||
//!
|
||||
//! The JSON tree is produced by the `swift-syntax-rs` crate's Swift FFI shim
|
||||
//! (`parse_to_json`). This module is pure Rust (only `yeast` + `serde_json`),
|
||||
//! so the extractor consumes swift-syntax output without pulling in the Swift
|
||||
//! toolchain (the JSON is produced out-of-process).
|
||||
//! (`parse_to_json`). This module needs no Swift toolchain, so the extractor
|
||||
//! consumes swift-syntax output out-of-process.
|
||||
//!
|
||||
//! The mapping mirrors tree-sitter's node model, which is what yeast (and the
|
||||
//! extractor's rewrite rules) expect:
|
||||
@@ -24,31 +23,19 @@
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use codeql_extractor::extractor::ExtraToken;
|
||||
use serde_json::Value;
|
||||
use yeast::schema::Schema;
|
||||
use yeast::{Ast, Id, NodeContent, Point, Range};
|
||||
|
||||
/// A comment (or `unexpectedText`) recovered from the syntax tree's trivia.
|
||||
///
|
||||
/// These are collected into a side channel rather than embedded in the
|
||||
/// [`yeast::Ast`], mirroring how the extractor treats tree-sitter `extra`
|
||||
/// nodes: they carry a location and text but are not attached to a parent.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct TriviaToken {
|
||||
/// The trivia kind (e.g. `lineComment`, `blockComment`, `docLineComment`,
|
||||
/// `docBlockComment`, `unexpectedText`).
|
||||
pub kind: String,
|
||||
/// The verbatim source text of the piece (e.g. `// comment`).
|
||||
pub text: String,
|
||||
/// The source range the piece occupies.
|
||||
pub range: Range,
|
||||
}
|
||||
|
||||
/// The result of adapting a swift-syntax JSON tree: the [`yeast::Ast`] plus the
|
||||
/// comment/`unexpectedText` trivia harvested from it (in source order).
|
||||
/// comment/`unexpectedText` [`ExtraToken`]s harvested from it (in source order).
|
||||
///
|
||||
/// The extra tokens are collected into a side channel rather than embedded in
|
||||
/// the [`yeast::Ast`], mirroring how the extractor treats tree-sitter `extra`
|
||||
/// nodes: they carry a location and text but are not attached to a parent.
|
||||
pub struct AdaptedTree {
|
||||
pub ast: Ast,
|
||||
pub trivia: Vec<TriviaToken>,
|
||||
pub extras: Vec<ExtraToken>,
|
||||
}
|
||||
|
||||
/// swift-syntax `TokenKind` cases whose text is *not* determined by the kind
|
||||
@@ -170,17 +157,18 @@ fn children_of(value: &Value) -> Vec<&Value> {
|
||||
/// in the schema on the fly, immediately before the node is created. Children
|
||||
/// are built first so a parent's field lists reference existing ids. Any
|
||||
/// comment/`unexpectedText` trivia carried by a token is harvested into
|
||||
/// `trivia` during the same pass rather than embedded in the tree.
|
||||
fn build(node: &Value, ast: &mut Ast, trivia: &mut Vec<TriviaToken>) -> Result<Id, String> {
|
||||
/// `extras` (as [`ExtraToken`]s) during the same pass rather than embedded in
|
||||
/// the tree.
|
||||
fn build(node: &Value, ast: &mut Ast, extras: &mut Vec<ExtraToken>) -> Result<Id, String> {
|
||||
let info = classify(node)?;
|
||||
collect_trivia(node, trivia);
|
||||
collect_extras(node, extras);
|
||||
|
||||
let mut fields: BTreeMap<u16, Vec<Id>> = BTreeMap::new();
|
||||
for (field, value) in field_entries(node) {
|
||||
let field_id = ast.register_field(field);
|
||||
let mut ids = Vec::new();
|
||||
for child in children_of(value) {
|
||||
ids.push(build(child, ast, trivia)?);
|
||||
ids.push(build(child, ast, extras)?);
|
||||
}
|
||||
fields.insert(field_id, ids);
|
||||
}
|
||||
@@ -201,9 +189,10 @@ fn build(node: &Value, ast: &mut Ast, trivia: &mut Vec<TriviaToken>) -> Result<I
|
||||
}
|
||||
|
||||
/// Harvest a token's `leadingTrivia`/`trailingTrivia` pieces (each already
|
||||
/// filtered to comments/`unexpectedText` upstream) into `out`. Non-token nodes
|
||||
/// have no trivia keys, so this is a no-op for them.
|
||||
fn collect_trivia(node: &Value, out: &mut Vec<TriviaToken>) {
|
||||
/// filtered to comments/`unexpectedText` upstream) into `out` as
|
||||
/// [`ExtraToken`]s. Non-token nodes have no trivia keys, so this is a no-op for
|
||||
/// them.
|
||||
fn collect_extras(node: &Value, out: &mut Vec<ExtraToken>) {
|
||||
for key in ["leadingTrivia", "trailingTrivia"] {
|
||||
let Some(Value::Array(pieces)) = node.get(key) else {
|
||||
continue;
|
||||
@@ -220,8 +209,8 @@ fn collect_trivia(node: &Value, out: &mut Vec<TriviaToken>) {
|
||||
.and_then(Value::as_str)
|
||||
.unwrap_or("")
|
||||
.to_string();
|
||||
out.push(TriviaToken {
|
||||
kind: kind.to_string(),
|
||||
out.push(ExtraToken {
|
||||
kind: trivia_kind_id(kind),
|
||||
text,
|
||||
range,
|
||||
});
|
||||
@@ -229,6 +218,21 @@ fn collect_trivia(node: &Value, out: &mut Vec<TriviaToken>) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Map a swift-syntax trivia kind name to the stable integer id stored in an
|
||||
/// [`ExtraToken`]'s `kind` (and written to the `unified_trivia_tokeninfo`
|
||||
/// table). The value is opaque to the QL library (which reads only the text),
|
||||
/// but is kept stable and meaningful.
|
||||
fn trivia_kind_id(kind: &str) -> usize {
|
||||
match kind {
|
||||
"lineComment" => 1,
|
||||
"blockComment" => 2,
|
||||
"docLineComment" => 3,
|
||||
"docBlockComment" => 4,
|
||||
"unexpectedText" => 5,
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a node's `range` into a [`yeast::Range`].
|
||||
///
|
||||
/// The JSON carries, for `start` and `end`, a 0-based UTF-8 file byte `offset`,
|
||||
@@ -258,21 +262,29 @@ fn parse_range(node: &Value) -> Option<Range> {
|
||||
})
|
||||
}
|
||||
|
||||
/// The authoritative swift-syntax input node-types schema.
|
||||
/// [`json_to_ast`] seeds every parse with the schema built from this,
|
||||
/// pre-registering every input kind and field so rule matching never references
|
||||
/// a name absent from a given file's tree.
|
||||
const SWIFT_NODE_TYPES: &str = include_str!("../../../swift_node_types.yml");
|
||||
|
||||
/// Convert a swift-syntax JSON tree (as produced by [`crate::parse_to_json`])
|
||||
/// into a [`yeast::Ast`] plus the comment/`unexpectedText` trivia harvested
|
||||
/// from it. Both are produced in a single traversal.
|
||||
/// from it. Both are produced in a single traversal. The AST is seeded with the
|
||||
/// authoritative swift-syntax schema ([`SWIFT_NODE_TYPES`]); the adapter only
|
||||
/// ever consumes swift-syntax input, so the schema is not a parameter.
|
||||
pub fn json_to_ast(json: &str) -> Result<AdaptedTree, String> {
|
||||
let root: Value = serde_json::from_str(json).map_err(|e| format!("invalid JSON: {e}"))?;
|
||||
|
||||
let mut ast = Ast::with_schema(Schema::new());
|
||||
let mut trivia = Vec::new();
|
||||
let root_id = build(&root, &mut ast, &mut trivia)?;
|
||||
let mut ast = Ast::with_schema(yeast::node_types_yaml::schema_from_yaml(SWIFT_NODE_TYPES)?);
|
||||
let mut extras = Vec::new();
|
||||
let root_id = build(&root, &mut ast, &mut extras)?;
|
||||
ast.set_root(root_id);
|
||||
|
||||
// Emit trivia in source order (the traversal visits nodes bottom-up).
|
||||
trivia.sort_by_key(|t| t.range.start_byte);
|
||||
// Emit extras in source order (the traversal visits nodes bottom-up).
|
||||
extras.sort_by_key(|t| t.range.start_byte);
|
||||
|
||||
Ok(AdaptedTree { ast, trivia })
|
||||
Ok(AdaptedTree { ast, extras })
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -373,7 +385,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn collects_trivia_into_side_channel() {
|
||||
fn collects_extras_into_side_channel() {
|
||||
// A token carrying a trailing line comment in its trivia.
|
||||
let json = r#"{
|
||||
"kind": "sourceFile",
|
||||
@@ -395,9 +407,10 @@ mod tests {
|
||||
let adapted = json_to_ast(json).expect("adapter should succeed");
|
||||
|
||||
// The comment is in the side channel, with its text and location.
|
||||
assert_eq!(adapted.trivia.len(), 1);
|
||||
let comment = &adapted.trivia[0];
|
||||
assert_eq!(comment.kind, "lineComment");
|
||||
assert_eq!(adapted.extras.len(), 1);
|
||||
let comment = &adapted.extras[0];
|
||||
// `lineComment` maps to extra kind id 1.
|
||||
assert_eq!(comment.kind, 1);
|
||||
assert_eq!(comment.text, "// c");
|
||||
assert_eq!(comment.range.start_byte, 2);
|
||||
assert_eq!(comment.range.end_byte, 6);
|
||||
|
||||
121
unified/extractor/src/languages/swift/parse.rs
Normal file
121
unified/extractor/src/languages/swift/parse.rs
Normal file
@@ -0,0 +1,121 @@
|
||||
//! Swift front-end parser: shells out to the separate `swift-syntax-parse`
|
||||
//! binary (which links swift-syntax) to obtain a JSON syntax tree, then adapts
|
||||
//! that JSON into a `yeast::Ast` via the pure-Rust [`swift_adapter`] module.
|
||||
//!
|
||||
//! Running the parser in a separate process keeps the Swift toolchain out of
|
||||
//! the extractor's own build: the extractor never links Swift, so working on
|
||||
//! other (e.g. tree-sitter based) languages needs no Swift toolchain. Each call
|
||||
//! spawns the parser afresh; a longer-lived parser process could be swapped in
|
||||
//! behind this same seam later without touching the extraction pipeline.
|
||||
|
||||
use std::io::Write;
|
||||
use std::process::{Command, Stdio};
|
||||
|
||||
use codeql_extractor::extractor::ParsedTree;
|
||||
|
||||
use super::swift_adapter;
|
||||
|
||||
/// Environment variable naming the `swift-syntax-parse` executable. When unset,
|
||||
/// the parser is resolved next to the extractor executable, then on `PATH`.
|
||||
const PARSE_BIN_ENV: &str = "CODEQL_EXTRACTOR_UNIFIED_SWIFT_SYNTAX_PARSE";
|
||||
|
||||
/// Base name of the `swift-syntax-parse` executable as shipped / looked up.
|
||||
const PARSE_BIN_NAME: &str = "swift-syntax-parse";
|
||||
|
||||
/// Parse Swift `source` into a [`ParsedTree`] (a raw `yeast::Ast` plus
|
||||
/// side-channel `extra` tokens), ready to be desugared via `run_from_ast`.
|
||||
pub fn parse(source: &[u8]) -> Result<ParsedTree, String> {
|
||||
let source =
|
||||
std::str::from_utf8(source).map_err(|e| format!("Swift source is not valid UTF-8: {e}"))?;
|
||||
let json = run_parser(source)?;
|
||||
let mut adapted = swift_adapter::json_to_ast(&json)?;
|
||||
adapted.ast.set_source(source.as_bytes().to_vec());
|
||||
Ok(ParsedTree {
|
||||
ast: adapted.ast,
|
||||
extras: adapted.extras,
|
||||
})
|
||||
}
|
||||
|
||||
/// The `swift-syntax-parse` executable to invoke, resolved in priority order:
|
||||
///
|
||||
/// 1. the `CODEQL_EXTRACTOR_UNIFIED_SWIFT_SYNTAX_PARSE` override, if set;
|
||||
/// 2. a copy shipped next to the extractor executable — this is how the CodeQL
|
||||
/// extractor pack lays it out (`tools/<platform>/{extractor,
|
||||
/// swift-syntax-parse}`), so a packaged extractor is self-contained with no
|
||||
/// environment setup;
|
||||
/// 3. a bare `swift-syntax-parse`, looked up on `PATH`.
|
||||
fn parse_bin() -> String {
|
||||
if let Ok(bin) = std::env::var(PARSE_BIN_ENV) {
|
||||
if !bin.is_empty() {
|
||||
return bin;
|
||||
}
|
||||
}
|
||||
if let Ok(exe) = std::env::current_exe() {
|
||||
if let Some(sibling) = exe.parent().map(|dir| dir.join(PARSE_BIN_NAME)) {
|
||||
if sibling.is_file() {
|
||||
return sibling.to_string_lossy().into_owned();
|
||||
}
|
||||
}
|
||||
}
|
||||
PARSE_BIN_NAME.to_string()
|
||||
}
|
||||
|
||||
/// Whether the `swift-syntax-parse` executable can be launched at all.
|
||||
///
|
||||
/// This reports availability of the *executable*, deliberately not whether
|
||||
/// parsing succeeds: a binary that launches but then crashes or emits invalid
|
||||
/// JSON is still "available", so callers run and surface the failure rather
|
||||
/// than silently skipping. Only a genuinely missing/unlaunchable binary (e.g.
|
||||
/// no Swift toolchain is installed) reports `false`.
|
||||
pub fn binary_available() -> bool {
|
||||
match Command::new(parse_bin())
|
||||
.stdin(Stdio::null())
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.spawn()
|
||||
{
|
||||
Ok(mut child) => {
|
||||
let _ = child.wait();
|
||||
true
|
||||
}
|
||||
Err(e) if e.kind() == std::io::ErrorKind::NotFound => false,
|
||||
// Any other spawn failure (e.g. a permissions problem) is a genuine
|
||||
// issue worth surfacing, so treat the parser as available and let the
|
||||
// caller fail rather than masking it as "unavailable".
|
||||
Err(_) => true,
|
||||
}
|
||||
}
|
||||
|
||||
/// Run the external parser, feeding `source` on stdin and returning its JSON
|
||||
/// stdout.
|
||||
fn run_parser(source: &str) -> Result<String, String> {
|
||||
let bin = parse_bin();
|
||||
let mut child = Command::new(&bin)
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()
|
||||
.map_err(|e| format!("failed to spawn Swift parser `{bin}`: {e}"))?;
|
||||
|
||||
// The parser reads all of stdin before writing any stdout, so writing the
|
||||
// whole source and then closing stdin (by dropping it) cannot deadlock.
|
||||
child
|
||||
.stdin
|
||||
.take()
|
||||
.expect("child stdin was piped")
|
||||
.write_all(source.as_bytes())
|
||||
.map_err(|e| format!("failed to write source to Swift parser `{bin}`: {e}"))?;
|
||||
|
||||
let output = child
|
||||
.wait_with_output()
|
||||
.map_err(|e| format!("failed to run Swift parser `{bin}`: {e}"))?;
|
||||
if !output.status.success() {
|
||||
return Err(format!(
|
||||
"Swift parser `{bin}` failed ({}): {}",
|
||||
output.status,
|
||||
String::from_utf8_lossy(&output.stderr).trim()
|
||||
));
|
||||
}
|
||||
String::from_utf8(output.stdout)
|
||||
.map_err(|e| format!("Swift parser produced non-UTF-8 output: {e}"))
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
1280
unified/extractor/swift_node_types.yml
Normal file
1280
unified/extractor/swift_node_types.yml
Normal file
File diff suppressed because it is too large
Load Diff
@@ -2,41 +2,61 @@ let f = { [weak self] in self?.doThing() }
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
property_declaration
|
||||
binding:
|
||||
value_binding_pattern
|
||||
mutability: let
|
||||
declarator:
|
||||
property_binding
|
||||
name:
|
||||
pattern
|
||||
bound_identifier: simple_identifier "f"
|
||||
value:
|
||||
lambda_literal
|
||||
captures:
|
||||
capture_list
|
||||
item:
|
||||
capture_list_item
|
||||
name: simple_identifier "self"
|
||||
ownership:
|
||||
ownership_modifier
|
||||
statement:
|
||||
call_expression
|
||||
function:
|
||||
navigation_expression
|
||||
suffix:
|
||||
navigation_suffix
|
||||
suffix: simple_identifier "doThing"
|
||||
target:
|
||||
optional_chain_marker
|
||||
expr:
|
||||
self_expression
|
||||
suffix:
|
||||
call_suffix
|
||||
arguments:
|
||||
value_arguments
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
variableDecl
|
||||
attributes:
|
||||
modifiers:
|
||||
bindingSpecifier: let
|
||||
bindings:
|
||||
patternBinding
|
||||
initializer:
|
||||
initializerClause
|
||||
equal: =
|
||||
value:
|
||||
closureExpr
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
signature:
|
||||
closureSignature
|
||||
attributes:
|
||||
capture:
|
||||
closureCaptureClause
|
||||
leftSquare: [
|
||||
rightSquare: ]
|
||||
items:
|
||||
closureCapture
|
||||
name: self
|
||||
specifier:
|
||||
closureCaptureSpecifier
|
||||
specifier: weak
|
||||
inKeyword: in
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
memberAccessExpr
|
||||
period: .
|
||||
declName:
|
||||
declReferenceExpr
|
||||
baseName: identifier "doThing"
|
||||
base:
|
||||
optionalChainingExpr
|
||||
expression:
|
||||
declReferenceExpr
|
||||
baseName: self
|
||||
questionMark: ?
|
||||
pattern:
|
||||
identifierPattern
|
||||
identifier: identifier "f"
|
||||
|
||||
---
|
||||
|
||||
@@ -51,6 +71,12 @@ top_level
|
||||
identifier: identifier "f"
|
||||
value:
|
||||
function_expr
|
||||
capture_declaration:
|
||||
variable_declaration
|
||||
modifier: modifier "weak"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "self"
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
@@ -61,9 +87,3 @@ top_level
|
||||
name_expr
|
||||
identifier: identifier "self"
|
||||
member: identifier "doThing"
|
||||
capture_declaration:
|
||||
variable_declaration
|
||||
modifier: modifier "weak"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "self"
|
||||
|
||||
@@ -2,45 +2,63 @@ let f = { (x: Int) -> Int in x * 2 }
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
property_declaration
|
||||
binding:
|
||||
value_binding_pattern
|
||||
mutability: let
|
||||
declarator:
|
||||
property_binding
|
||||
name:
|
||||
pattern
|
||||
bound_identifier: simple_identifier "f"
|
||||
value:
|
||||
lambda_literal
|
||||
statement:
|
||||
multiplicative_expression
|
||||
lhs: simple_identifier "x"
|
||||
op: *
|
||||
rhs: integer_literal "2"
|
||||
type:
|
||||
lambda_function_type
|
||||
params:
|
||||
lambda_function_type_parameters
|
||||
parameter:
|
||||
lambda_parameter
|
||||
name: simple_identifier "x"
|
||||
type:
|
||||
type
|
||||
name:
|
||||
user_type
|
||||
part:
|
||||
simple_user_type
|
||||
name: type_identifier "Int"
|
||||
return_type:
|
||||
type
|
||||
name:
|
||||
user_type
|
||||
part:
|
||||
simple_user_type
|
||||
name: type_identifier "Int"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
variableDecl
|
||||
attributes:
|
||||
modifiers:
|
||||
bindingSpecifier: let
|
||||
bindings:
|
||||
patternBinding
|
||||
initializer:
|
||||
initializerClause
|
||||
equal: =
|
||||
value:
|
||||
closureExpr
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
signature:
|
||||
closureSignature
|
||||
attributes:
|
||||
inKeyword: in
|
||||
parameterClause:
|
||||
closureParameterClause
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
parameters:
|
||||
closureParameter
|
||||
colon: :
|
||||
attributes:
|
||||
modifiers:
|
||||
type:
|
||||
identifierType
|
||||
name: identifier "Int"
|
||||
firstName: identifier "x"
|
||||
returnClause:
|
||||
returnClause
|
||||
arrow: ->
|
||||
type:
|
||||
identifierType
|
||||
name: identifier "Int"
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator "*"
|
||||
leftOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "x"
|
||||
rightOperand:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "2"
|
||||
pattern:
|
||||
identifierPattern
|
||||
identifier: identifier "f"
|
||||
|
||||
---
|
||||
|
||||
@@ -55,23 +73,23 @@ top_level
|
||||
identifier: identifier "f"
|
||||
value:
|
||||
function_expr
|
||||
parameter:
|
||||
parameter
|
||||
type:
|
||||
named_type_expr
|
||||
name: identifier "Int"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "x"
|
||||
return_type:
|
||||
named_type_expr
|
||||
name: identifier "Int"
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
binary_expr
|
||||
operator: infix_operator "*"
|
||||
left:
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
operator: infix_operator "*"
|
||||
right: int_literal "2"
|
||||
parameter:
|
||||
parameter
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "x"
|
||||
type:
|
||||
named_type_expr
|
||||
name: identifier "Int"
|
||||
return_type:
|
||||
named_type_expr
|
||||
name: identifier "Int"
|
||||
|
||||
@@ -2,24 +2,40 @@ let f = { $0 + $1 }
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
property_declaration
|
||||
binding:
|
||||
value_binding_pattern
|
||||
mutability: let
|
||||
declarator:
|
||||
property_binding
|
||||
name:
|
||||
pattern
|
||||
bound_identifier: simple_identifier "f"
|
||||
value:
|
||||
lambda_literal
|
||||
statement:
|
||||
additive_expression
|
||||
lhs: simple_identifier "$0"
|
||||
op: +
|
||||
rhs: simple_identifier "$1"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
variableDecl
|
||||
attributes:
|
||||
modifiers:
|
||||
bindingSpecifier: let
|
||||
bindings:
|
||||
patternBinding
|
||||
initializer:
|
||||
initializerClause
|
||||
equal: =
|
||||
value:
|
||||
closureExpr
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator "+"
|
||||
leftOperand:
|
||||
declReferenceExpr
|
||||
baseName: dollarIdentifier "$0"
|
||||
rightOperand:
|
||||
declReferenceExpr
|
||||
baseName: dollarIdentifier "$1"
|
||||
pattern:
|
||||
identifierPattern
|
||||
identifier: identifier "f"
|
||||
|
||||
---
|
||||
|
||||
@@ -38,10 +54,10 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
binary_expr
|
||||
operator: infix_operator "+"
|
||||
left:
|
||||
name_expr
|
||||
identifier: identifier "$0"
|
||||
operator: infix_operator "+"
|
||||
right:
|
||||
name_expr
|
||||
identifier: identifier "$1"
|
||||
|
||||
@@ -5,62 +5,91 @@ let f = { (x: Int) -> Int in
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
property_declaration
|
||||
binding:
|
||||
value_binding_pattern
|
||||
mutability: let
|
||||
declarator:
|
||||
property_binding
|
||||
name:
|
||||
pattern
|
||||
bound_identifier: simple_identifier "f"
|
||||
value:
|
||||
lambda_literal
|
||||
statement:
|
||||
property_declaration
|
||||
binding:
|
||||
value_binding_pattern
|
||||
mutability: let
|
||||
declarator:
|
||||
property_binding
|
||||
name:
|
||||
pattern
|
||||
bound_identifier: simple_identifier "y"
|
||||
value:
|
||||
additive_expression
|
||||
lhs: simple_identifier "x"
|
||||
op: +
|
||||
rhs: integer_literal "1"
|
||||
control_transfer_statement
|
||||
kind: return
|
||||
result:
|
||||
multiplicative_expression
|
||||
lhs: simple_identifier "y"
|
||||
op: *
|
||||
rhs: integer_literal "2"
|
||||
type:
|
||||
lambda_function_type
|
||||
params:
|
||||
lambda_function_type_parameters
|
||||
parameter:
|
||||
lambda_parameter
|
||||
name: simple_identifier "x"
|
||||
type:
|
||||
type
|
||||
name:
|
||||
user_type
|
||||
part:
|
||||
simple_user_type
|
||||
name: type_identifier "Int"
|
||||
return_type:
|
||||
type
|
||||
name:
|
||||
user_type
|
||||
part:
|
||||
simple_user_type
|
||||
name: type_identifier "Int"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
variableDecl
|
||||
attributes:
|
||||
modifiers:
|
||||
bindingSpecifier: let
|
||||
bindings:
|
||||
patternBinding
|
||||
initializer:
|
||||
initializerClause
|
||||
equal: =
|
||||
value:
|
||||
closureExpr
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
signature:
|
||||
closureSignature
|
||||
attributes:
|
||||
inKeyword: in
|
||||
parameterClause:
|
||||
closureParameterClause
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
parameters:
|
||||
closureParameter
|
||||
colon: :
|
||||
attributes:
|
||||
modifiers:
|
||||
type:
|
||||
identifierType
|
||||
name: identifier "Int"
|
||||
firstName: identifier "x"
|
||||
returnClause:
|
||||
returnClause
|
||||
arrow: ->
|
||||
type:
|
||||
identifierType
|
||||
name: identifier "Int"
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
variableDecl
|
||||
attributes:
|
||||
modifiers:
|
||||
bindingSpecifier: let
|
||||
bindings:
|
||||
patternBinding
|
||||
initializer:
|
||||
initializerClause
|
||||
equal: =
|
||||
value:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator "+"
|
||||
leftOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "x"
|
||||
rightOperand:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "1"
|
||||
pattern:
|
||||
identifierPattern
|
||||
identifier: identifier "y"
|
||||
codeBlockItem
|
||||
item:
|
||||
returnStmt
|
||||
expression:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator "*"
|
||||
leftOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "y"
|
||||
rightOperand:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "2"
|
||||
returnKeyword: return
|
||||
pattern:
|
||||
identifierPattern
|
||||
identifier: identifier "f"
|
||||
|
||||
---
|
||||
|
||||
@@ -75,6 +104,17 @@ top_level
|
||||
identifier: identifier "f"
|
||||
value:
|
||||
function_expr
|
||||
parameter:
|
||||
parameter
|
||||
type:
|
||||
named_type_expr
|
||||
name: identifier "Int"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "x"
|
||||
return_type:
|
||||
named_type_expr
|
||||
name: identifier "Int"
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
@@ -85,27 +125,16 @@ top_level
|
||||
identifier: identifier "y"
|
||||
value:
|
||||
binary_expr
|
||||
operator: infix_operator "+"
|
||||
left:
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
operator: infix_operator "+"
|
||||
right: int_literal "1"
|
||||
return_expr
|
||||
value:
|
||||
binary_expr
|
||||
operator: infix_operator "*"
|
||||
left:
|
||||
name_expr
|
||||
identifier: identifier "y"
|
||||
operator: infix_operator "*"
|
||||
right: int_literal "2"
|
||||
parameter:
|
||||
parameter
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "x"
|
||||
type:
|
||||
named_type_expr
|
||||
name: identifier "Int"
|
||||
return_type:
|
||||
named_type_expr
|
||||
name: identifier "Int"
|
||||
|
||||
@@ -2,24 +2,40 @@ xs.map { $0 * 2 }
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
call_expression
|
||||
function:
|
||||
navigation_expression
|
||||
suffix:
|
||||
navigation_suffix
|
||||
suffix: simple_identifier "map"
|
||||
target: simple_identifier "xs"
|
||||
suffix:
|
||||
call_suffix
|
||||
lambda:
|
||||
lambda_literal
|
||||
statement:
|
||||
multiplicative_expression
|
||||
lhs: simple_identifier "$0"
|
||||
op: *
|
||||
rhs: integer_literal "2"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionCallExpr
|
||||
arguments:
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
memberAccessExpr
|
||||
period: .
|
||||
declName:
|
||||
declReferenceExpr
|
||||
baseName: identifier "map"
|
||||
base:
|
||||
declReferenceExpr
|
||||
baseName: identifier "xs"
|
||||
trailingClosure:
|
||||
closureExpr
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator "*"
|
||||
leftOperand:
|
||||
declReferenceExpr
|
||||
baseName: dollarIdentifier "$0"
|
||||
rightOperand:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "2"
|
||||
|
||||
---
|
||||
|
||||
@@ -28,6 +44,12 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
callee:
|
||||
member_access_expr
|
||||
base:
|
||||
name_expr
|
||||
identifier: identifier "xs"
|
||||
member: identifier "map"
|
||||
argument:
|
||||
argument
|
||||
value:
|
||||
@@ -36,14 +58,8 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
binary_expr
|
||||
operator: infix_operator "*"
|
||||
left:
|
||||
name_expr
|
||||
identifier: identifier "$0"
|
||||
operator: infix_operator "*"
|
||||
right: int_literal "2"
|
||||
callee:
|
||||
member_access_expr
|
||||
base:
|
||||
name_expr
|
||||
identifier: identifier "xs"
|
||||
member: identifier "map"
|
||||
|
||||
@@ -2,23 +2,42 @@ let xs = [1, 2, 3]
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
property_declaration
|
||||
binding:
|
||||
value_binding_pattern
|
||||
mutability: let
|
||||
declarator:
|
||||
property_binding
|
||||
name:
|
||||
pattern
|
||||
bound_identifier: simple_identifier "xs"
|
||||
value:
|
||||
array_literal
|
||||
element:
|
||||
integer_literal "1"
|
||||
integer_literal "2"
|
||||
integer_literal "3"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
variableDecl
|
||||
attributes:
|
||||
modifiers:
|
||||
bindingSpecifier: let
|
||||
bindings:
|
||||
patternBinding
|
||||
initializer:
|
||||
initializerClause
|
||||
equal: =
|
||||
value:
|
||||
arrayExpr
|
||||
elements:
|
||||
arrayElement
|
||||
expression:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "1"
|
||||
trailingComma: ,
|
||||
arrayElement
|
||||
expression:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "2"
|
||||
trailingComma: ,
|
||||
arrayElement
|
||||
expression:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "3"
|
||||
leftSquare: [
|
||||
rightSquare: ]
|
||||
pattern:
|
||||
identifierPattern
|
||||
identifier: identifier "xs"
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,30 +2,53 @@ let d = ["a": 1, "b": 2]
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
property_declaration
|
||||
binding:
|
||||
value_binding_pattern
|
||||
mutability: let
|
||||
declarator:
|
||||
property_binding
|
||||
name:
|
||||
pattern
|
||||
bound_identifier: simple_identifier "d"
|
||||
value:
|
||||
dictionary_literal
|
||||
element:
|
||||
dictionary_literal_item
|
||||
key:
|
||||
line_string_literal
|
||||
text: line_str_text "a"
|
||||
value: integer_literal "1"
|
||||
dictionary_literal_item
|
||||
key:
|
||||
line_string_literal
|
||||
text: line_str_text "b"
|
||||
value: integer_literal "2"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
variableDecl
|
||||
attributes:
|
||||
modifiers:
|
||||
bindingSpecifier: let
|
||||
bindings:
|
||||
patternBinding
|
||||
initializer:
|
||||
initializerClause
|
||||
equal: =
|
||||
value:
|
||||
dictionaryExpr
|
||||
leftSquare: [
|
||||
rightSquare: ]
|
||||
content:
|
||||
dictionaryElement
|
||||
colon: :
|
||||
trailingComma: ,
|
||||
value:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "1"
|
||||
key:
|
||||
stringLiteralExpr
|
||||
closingQuote: "
|
||||
openingQuote: "
|
||||
segments:
|
||||
stringSegment
|
||||
content: stringSegment "a"
|
||||
dictionaryElement
|
||||
colon: :
|
||||
value:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "2"
|
||||
key:
|
||||
stringLiteralExpr
|
||||
closingQuote: "
|
||||
openingQuote: "
|
||||
segments:
|
||||
stringSegment
|
||||
content: stringSegment "b"
|
||||
pattern:
|
||||
identifierPattern
|
||||
identifier: identifier "d"
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -4,31 +4,40 @@ let v = d["key"]
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
property_declaration
|
||||
binding:
|
||||
value_binding_pattern
|
||||
mutability: let
|
||||
declarator:
|
||||
property_binding
|
||||
name:
|
||||
pattern
|
||||
bound_identifier: simple_identifier "v"
|
||||
value:
|
||||
call_expression
|
||||
function: simple_identifier "d"
|
||||
suffix:
|
||||
call_suffix
|
||||
arguments:
|
||||
value_arguments
|
||||
argument:
|
||||
value_argument
|
||||
value:
|
||||
line_string_literal
|
||||
text: line_str_text "key"
|
||||
comment "// TODO: same parser issue as the array subscript case above —"
|
||||
comment "// `d[\"key\"]` is parsed as `call_expression(d, (\"key\"))`."
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
variableDecl
|
||||
attributes:
|
||||
modifiers:
|
||||
bindingSpecifier: let
|
||||
bindings:
|
||||
patternBinding
|
||||
initializer:
|
||||
initializerClause
|
||||
equal: =
|
||||
value:
|
||||
subscriptCallExpr
|
||||
leftSquare: [
|
||||
rightSquare: ]
|
||||
arguments:
|
||||
labeledExpr
|
||||
expression:
|
||||
stringLiteralExpr
|
||||
closingQuote: "
|
||||
openingQuote: "
|
||||
segments:
|
||||
stringSegment
|
||||
content: stringSegment "key"
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "d"
|
||||
pattern:
|
||||
identifierPattern
|
||||
identifier: identifier "v"
|
||||
|
||||
---
|
||||
|
||||
@@ -43,9 +52,9 @@ top_level
|
||||
identifier: identifier "v"
|
||||
value:
|
||||
call_expr
|
||||
argument:
|
||||
argument
|
||||
value: string_literal "\"key\""
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "d"
|
||||
argument:
|
||||
argument
|
||||
value: string_literal "\"key\""
|
||||
|
||||
@@ -2,32 +2,38 @@ let xs: [Int] = []
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
property_declaration
|
||||
binding:
|
||||
value_binding_pattern
|
||||
mutability: let
|
||||
declarator:
|
||||
property_binding
|
||||
name:
|
||||
pattern
|
||||
bound_identifier: simple_identifier "xs"
|
||||
type:
|
||||
type_annotation
|
||||
type:
|
||||
type
|
||||
name:
|
||||
array_type
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
variableDecl
|
||||
attributes:
|
||||
modifiers:
|
||||
bindingSpecifier: let
|
||||
bindings:
|
||||
patternBinding
|
||||
initializer:
|
||||
initializerClause
|
||||
equal: =
|
||||
value:
|
||||
arrayExpr
|
||||
elements:
|
||||
leftSquare: [
|
||||
rightSquare: ]
|
||||
pattern:
|
||||
identifierPattern
|
||||
identifier: identifier "xs"
|
||||
typeAnnotation:
|
||||
typeAnnotation
|
||||
colon: :
|
||||
type:
|
||||
arrayType
|
||||
leftSquare: [
|
||||
rightSquare: ]
|
||||
element:
|
||||
type
|
||||
name:
|
||||
user_type
|
||||
part:
|
||||
simple_user_type
|
||||
name: type_identifier "Int"
|
||||
value:
|
||||
array_literal
|
||||
identifierType
|
||||
name: identifier "Int"
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,41 +2,57 @@ let s: Set<Int> = [1, 2, 3]
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
property_declaration
|
||||
binding:
|
||||
value_binding_pattern
|
||||
mutability: let
|
||||
declarator:
|
||||
property_binding
|
||||
name:
|
||||
pattern
|
||||
bound_identifier: simple_identifier "s"
|
||||
type:
|
||||
type_annotation
|
||||
type:
|
||||
type
|
||||
name:
|
||||
user_type
|
||||
part:
|
||||
simple_user_type
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
variableDecl
|
||||
attributes:
|
||||
modifiers:
|
||||
bindingSpecifier: let
|
||||
bindings:
|
||||
patternBinding
|
||||
initializer:
|
||||
initializerClause
|
||||
equal: =
|
||||
value:
|
||||
arrayExpr
|
||||
elements:
|
||||
arrayElement
|
||||
expression:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "1"
|
||||
trailingComma: ,
|
||||
arrayElement
|
||||
expression:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "2"
|
||||
trailingComma: ,
|
||||
arrayElement
|
||||
expression:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "3"
|
||||
leftSquare: [
|
||||
rightSquare: ]
|
||||
pattern:
|
||||
identifierPattern
|
||||
identifier: identifier "s"
|
||||
typeAnnotation:
|
||||
typeAnnotation
|
||||
colon: :
|
||||
type:
|
||||
identifierType
|
||||
name: identifier "Set"
|
||||
genericArgumentClause:
|
||||
genericArgumentClause
|
||||
arguments:
|
||||
type_arguments
|
||||
genericArgument
|
||||
argument:
|
||||
type
|
||||
name:
|
||||
user_type
|
||||
part:
|
||||
simple_user_type
|
||||
name: type_identifier "Int"
|
||||
name: type_identifier "Set"
|
||||
value:
|
||||
array_literal
|
||||
element:
|
||||
integer_literal "1"
|
||||
integer_literal "2"
|
||||
integer_literal "3"
|
||||
identifierType
|
||||
name: identifier "Int"
|
||||
leftAngle: <
|
||||
rightAngle: >
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -5,30 +5,36 @@ let first = xs[0]
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
property_declaration
|
||||
binding:
|
||||
value_binding_pattern
|
||||
mutability: let
|
||||
declarator:
|
||||
property_binding
|
||||
name:
|
||||
pattern
|
||||
bound_identifier: simple_identifier "first"
|
||||
value:
|
||||
call_expression
|
||||
function: simple_identifier "xs"
|
||||
suffix:
|
||||
call_suffix
|
||||
arguments:
|
||||
value_arguments
|
||||
argument:
|
||||
value_argument
|
||||
value: integer_literal "0"
|
||||
comment "// TODO: tree-sitter-swift parses `xs[0]` as a call_expression (same shape"
|
||||
comment "// as `xs(0)`), so the mapping currently produces a call_expr. Update the"
|
||||
comment "// parser / add a separate subscript_expr node and remap when fixed."
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
variableDecl
|
||||
attributes:
|
||||
modifiers:
|
||||
bindingSpecifier: let
|
||||
bindings:
|
||||
patternBinding
|
||||
initializer:
|
||||
initializerClause
|
||||
equal: =
|
||||
value:
|
||||
subscriptCallExpr
|
||||
leftSquare: [
|
||||
rightSquare: ]
|
||||
arguments:
|
||||
labeledExpr
|
||||
expression:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "0"
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "xs"
|
||||
pattern:
|
||||
identifierPattern
|
||||
identifier: identifier "first"
|
||||
|
||||
---
|
||||
|
||||
@@ -43,9 +49,9 @@ top_level
|
||||
identifier: identifier "first"
|
||||
value:
|
||||
call_expr
|
||||
argument:
|
||||
argument
|
||||
value: int_literal "0"
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "xs"
|
||||
argument:
|
||||
argument
|
||||
value: int_literal "0"
|
||||
|
||||
@@ -2,28 +2,46 @@ let t = (1, "two", 3.0)
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
property_declaration
|
||||
binding:
|
||||
value_binding_pattern
|
||||
mutability: let
|
||||
declarator:
|
||||
property_binding
|
||||
name:
|
||||
pattern
|
||||
bound_identifier: simple_identifier "t"
|
||||
value:
|
||||
tuple_expression
|
||||
element:
|
||||
tuple_expression_item
|
||||
value: integer_literal "1"
|
||||
tuple_expression_item
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
variableDecl
|
||||
attributes:
|
||||
modifiers:
|
||||
bindingSpecifier: let
|
||||
bindings:
|
||||
patternBinding
|
||||
initializer:
|
||||
initializerClause
|
||||
equal: =
|
||||
value:
|
||||
line_string_literal
|
||||
text: line_str_text "two"
|
||||
tuple_expression_item
|
||||
value: real_literal "3.0"
|
||||
tupleExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
elements:
|
||||
labeledExpr
|
||||
expression:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "1"
|
||||
trailingComma: ,
|
||||
labeledExpr
|
||||
expression:
|
||||
stringLiteralExpr
|
||||
closingQuote: "
|
||||
openingQuote: "
|
||||
segments:
|
||||
stringSegment
|
||||
content: stringSegment "two"
|
||||
trailingComma: ,
|
||||
labeledExpr
|
||||
expression:
|
||||
floatLiteralExpr
|
||||
literal: floatLiteral "3.0"
|
||||
pattern:
|
||||
identifierPattern
|
||||
identifier: identifier "t"
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,23 +2,32 @@ let n = t.0
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
property_declaration
|
||||
binding:
|
||||
value_binding_pattern
|
||||
mutability: let
|
||||
declarator:
|
||||
property_binding
|
||||
name:
|
||||
pattern
|
||||
bound_identifier: simple_identifier "n"
|
||||
value:
|
||||
navigation_expression
|
||||
suffix:
|
||||
navigation_suffix
|
||||
suffix: integer_literal "0"
|
||||
target: simple_identifier "t"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
variableDecl
|
||||
attributes:
|
||||
modifiers:
|
||||
bindingSpecifier: let
|
||||
bindings:
|
||||
patternBinding
|
||||
initializer:
|
||||
initializerClause
|
||||
equal: =
|
||||
value:
|
||||
memberAccessExpr
|
||||
period: .
|
||||
declName:
|
||||
declReferenceExpr
|
||||
baseName: integerLiteral "0"
|
||||
base:
|
||||
declReferenceExpr
|
||||
baseName: identifier "t"
|
||||
pattern:
|
||||
identifierPattern
|
||||
identifier: identifier "n"
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -8,44 +8,79 @@ default:
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
property_declaration
|
||||
binding:
|
||||
value_binding_pattern
|
||||
mutability: let
|
||||
declarator:
|
||||
property_binding
|
||||
name:
|
||||
pattern
|
||||
bound_identifier: simple_identifier "x"
|
||||
value: integer_literal "1"
|
||||
switch_statement
|
||||
entry:
|
||||
switch_entry
|
||||
pattern:
|
||||
switch_pattern
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
variableDecl
|
||||
attributes:
|
||||
modifiers:
|
||||
bindingSpecifier: let
|
||||
bindings:
|
||||
patternBinding
|
||||
initializer:
|
||||
initializerClause
|
||||
equal: =
|
||||
value:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "1"
|
||||
pattern:
|
||||
pattern
|
||||
kind: simple_identifier "someConstant"
|
||||
statement:
|
||||
call_expression
|
||||
function: simple_identifier "print"
|
||||
suffix:
|
||||
call_suffix
|
||||
arguments:
|
||||
value_arguments
|
||||
argument:
|
||||
value_argument
|
||||
value:
|
||||
line_string_literal
|
||||
text: line_str_text "matched"
|
||||
switch_entry
|
||||
default: default_keyword "default"
|
||||
statement:
|
||||
control_transfer_statement
|
||||
kind: break
|
||||
expr: simple_identifier "y"
|
||||
identifierPattern
|
||||
identifier: identifier "x"
|
||||
codeBlockItem
|
||||
item:
|
||||
expressionStmt
|
||||
expression:
|
||||
switchExpr
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
cases:
|
||||
switchCase
|
||||
label:
|
||||
switchCaseLabel
|
||||
colon: :
|
||||
caseKeyword: case
|
||||
caseItems:
|
||||
switchCaseItem
|
||||
pattern:
|
||||
expressionPattern
|
||||
expression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "someConstant"
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
labeledExpr
|
||||
expression:
|
||||
stringLiteralExpr
|
||||
closingQuote: "
|
||||
openingQuote: "
|
||||
segments:
|
||||
stringSegment
|
||||
content: stringSegment "matched"
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "print"
|
||||
switchCase
|
||||
label:
|
||||
switchDefaultLabel
|
||||
colon: :
|
||||
defaultKeyword: default
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
breakStmt
|
||||
breakKeyword: break
|
||||
subject:
|
||||
declReferenceExpr
|
||||
baseName: identifier "y"
|
||||
switchKeyword: switch
|
||||
|
||||
---
|
||||
|
||||
@@ -60,27 +95,27 @@ top_level
|
||||
identifier: identifier "x"
|
||||
value: int_literal "1"
|
||||
switch_expr
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "y"
|
||||
case:
|
||||
switch_case
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
argument:
|
||||
argument
|
||||
value: string_literal "\"matched\""
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
pattern:
|
||||
expr_equality_pattern
|
||||
expr:
|
||||
name_expr
|
||||
identifier: identifier "someConstant"
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
argument:
|
||||
argument
|
||||
value: string_literal "\"matched\""
|
||||
switch_case
|
||||
body:
|
||||
block
|
||||
stmt: break_expr "break"
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "y"
|
||||
|
||||
@@ -2,25 +2,37 @@ guard let value = optional else { return }
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
guard_statement
|
||||
body:
|
||||
block
|
||||
statement:
|
||||
control_transfer_statement
|
||||
kind: return
|
||||
condition:
|
||||
if_condition
|
||||
kind:
|
||||
if_let_binding
|
||||
pattern:
|
||||
pattern
|
||||
binding:
|
||||
value_binding_pattern
|
||||
mutability: let
|
||||
bound_identifier: simple_identifier "value"
|
||||
value: simple_identifier "optional"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
guardStmt
|
||||
body:
|
||||
codeBlock
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
returnStmt
|
||||
returnKeyword: return
|
||||
conditions:
|
||||
conditionElement
|
||||
condition:
|
||||
optionalBindingCondition
|
||||
initializer:
|
||||
initializerClause
|
||||
equal: =
|
||||
value:
|
||||
declReferenceExpr
|
||||
baseName: identifier "optional"
|
||||
pattern:
|
||||
identifierPattern
|
||||
identifier: identifier "value"
|
||||
bindingSpecifier: let
|
||||
elseKeyword: else
|
||||
guardKeyword: guard
|
||||
|
||||
---
|
||||
|
||||
@@ -33,17 +45,17 @@ top_level
|
||||
pattern_guard_expr
|
||||
pattern:
|
||||
constructor_pattern
|
||||
element:
|
||||
pattern_element
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "value"
|
||||
constructor:
|
||||
member_access_expr
|
||||
base:
|
||||
named_type_expr
|
||||
name: identifier "Optional"
|
||||
member: identifier "some"
|
||||
element:
|
||||
pattern_element
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "value"
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "optional"
|
||||
|
||||
@@ -4,40 +4,59 @@ if case let x = x + 10 {
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
if_statement
|
||||
body:
|
||||
block
|
||||
statement:
|
||||
call_expression
|
||||
function: simple_identifier "print"
|
||||
suffix:
|
||||
call_suffix
|
||||
arguments:
|
||||
value_arguments
|
||||
argument:
|
||||
value_argument
|
||||
value: simple_identifier "x"
|
||||
condition:
|
||||
if_condition
|
||||
kind:
|
||||
if_let_binding
|
||||
pattern:
|
||||
pattern
|
||||
kind:
|
||||
binding_pattern
|
||||
binding:
|
||||
value_binding_pattern
|
||||
mutability: let
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
expressionStmt
|
||||
expression:
|
||||
ifExpr
|
||||
body:
|
||||
codeBlock
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
labeledExpr
|
||||
expression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "x"
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "print"
|
||||
conditions:
|
||||
conditionElement
|
||||
condition:
|
||||
matchingPatternCondition
|
||||
initializer:
|
||||
initializerClause
|
||||
equal: =
|
||||
value:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator "+"
|
||||
leftOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "x"
|
||||
rightOperand:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "10"
|
||||
pattern:
|
||||
pattern
|
||||
bound_identifier: simple_identifier "x"
|
||||
value:
|
||||
additive_expression
|
||||
lhs: simple_identifier "x"
|
||||
op: +
|
||||
rhs: integer_literal "10"
|
||||
valueBindingPattern
|
||||
pattern:
|
||||
identifierPattern
|
||||
identifier: identifier "x"
|
||||
bindingSpecifier: let
|
||||
caseKeyword: case
|
||||
ifKeyword: if
|
||||
|
||||
---
|
||||
|
||||
@@ -53,20 +72,20 @@ top_level
|
||||
identifier: identifier "x"
|
||||
value:
|
||||
binary_expr
|
||||
operator: infix_operator "+"
|
||||
left:
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
operator: infix_operator "+"
|
||||
right: int_literal "10"
|
||||
then:
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
argument:
|
||||
argument
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
|
||||
@@ -8,61 +8,103 @@ if x > 0 {
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
if_statement
|
||||
body:
|
||||
block
|
||||
statement:
|
||||
call_expression
|
||||
function: simple_identifier "print"
|
||||
suffix:
|
||||
call_suffix
|
||||
arguments:
|
||||
value_arguments
|
||||
argument:
|
||||
value_argument
|
||||
value: integer_literal "1"
|
||||
condition:
|
||||
if_condition
|
||||
kind:
|
||||
comparison_expression
|
||||
lhs: simple_identifier "x"
|
||||
op: >
|
||||
rhs: integer_literal "0"
|
||||
else_branch:
|
||||
if_statement
|
||||
body:
|
||||
block
|
||||
statement:
|
||||
call_expression
|
||||
function: simple_identifier "print"
|
||||
suffix:
|
||||
call_suffix
|
||||
arguments:
|
||||
value_arguments
|
||||
argument:
|
||||
value_argument
|
||||
value: integer_literal "2"
|
||||
condition:
|
||||
if_condition
|
||||
kind:
|
||||
comparison_expression
|
||||
lhs: simple_identifier "x"
|
||||
op: <
|
||||
rhs: integer_literal "0"
|
||||
else_branch:
|
||||
block
|
||||
statement:
|
||||
call_expression
|
||||
function: simple_identifier "print"
|
||||
suffix:
|
||||
call_suffix
|
||||
arguments:
|
||||
value_arguments
|
||||
argument:
|
||||
value_argument
|
||||
value: integer_literal "3"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
expressionStmt
|
||||
expression:
|
||||
ifExpr
|
||||
body:
|
||||
codeBlock
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
labeledExpr
|
||||
expression:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "1"
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "print"
|
||||
conditions:
|
||||
conditionElement
|
||||
condition:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator ">"
|
||||
leftOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "x"
|
||||
rightOperand:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "0"
|
||||
elseKeyword: else
|
||||
elseBody:
|
||||
ifExpr
|
||||
body:
|
||||
codeBlock
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
labeledExpr
|
||||
expression:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "2"
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "print"
|
||||
conditions:
|
||||
conditionElement
|
||||
condition:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator "<"
|
||||
leftOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "x"
|
||||
rightOperand:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "0"
|
||||
elseKeyword: else
|
||||
elseBody:
|
||||
codeBlock
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
labeledExpr
|
||||
expression:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "3"
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "print"
|
||||
ifKeyword: if
|
||||
ifKeyword: if
|
||||
|
||||
---
|
||||
|
||||
@@ -73,47 +115,47 @@ top_level
|
||||
if_expr
|
||||
condition:
|
||||
binary_expr
|
||||
operator: infix_operator ">"
|
||||
left:
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
operator: infix_operator ">"
|
||||
right: int_literal "0"
|
||||
else:
|
||||
if_expr
|
||||
condition:
|
||||
binary_expr
|
||||
operator: infix_operator "<"
|
||||
left:
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
right: int_literal "0"
|
||||
else:
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
argument:
|
||||
argument
|
||||
value: int_literal "3"
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
then:
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
argument:
|
||||
argument
|
||||
value: int_literal "2"
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
then:
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
argument:
|
||||
argument
|
||||
value: int_literal "1"
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
argument:
|
||||
argument
|
||||
value: int_literal "1"
|
||||
else:
|
||||
if_expr
|
||||
condition:
|
||||
binary_expr
|
||||
left:
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
operator: infix_operator "<"
|
||||
right: int_literal "0"
|
||||
then:
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
argument:
|
||||
argument
|
||||
value: int_literal "2"
|
||||
else:
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
argument:
|
||||
argument
|
||||
value: int_literal "3"
|
||||
|
||||
@@ -6,43 +6,70 @@ if x > 0 {
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
if_statement
|
||||
body:
|
||||
block
|
||||
statement:
|
||||
call_expression
|
||||
function: simple_identifier "print"
|
||||
suffix:
|
||||
call_suffix
|
||||
arguments:
|
||||
value_arguments
|
||||
argument:
|
||||
value_argument
|
||||
value: simple_identifier "x"
|
||||
condition:
|
||||
if_condition
|
||||
kind:
|
||||
comparison_expression
|
||||
lhs: simple_identifier "x"
|
||||
op: >
|
||||
rhs: integer_literal "0"
|
||||
else_branch:
|
||||
block
|
||||
statement:
|
||||
call_expression
|
||||
function: simple_identifier "print"
|
||||
suffix:
|
||||
call_suffix
|
||||
arguments:
|
||||
value_arguments
|
||||
argument:
|
||||
value_argument
|
||||
value:
|
||||
prefix_expression
|
||||
operation: -
|
||||
target: simple_identifier "x"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
expressionStmt
|
||||
expression:
|
||||
ifExpr
|
||||
body:
|
||||
codeBlock
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
labeledExpr
|
||||
expression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "x"
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "print"
|
||||
conditions:
|
||||
conditionElement
|
||||
condition:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator ">"
|
||||
leftOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "x"
|
||||
rightOperand:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "0"
|
||||
elseKeyword: else
|
||||
elseBody:
|
||||
codeBlock
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
labeledExpr
|
||||
expression:
|
||||
prefixOperatorExpr
|
||||
expression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "x"
|
||||
operator: prefixOperator "-"
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "print"
|
||||
ifKeyword: if
|
||||
|
||||
---
|
||||
|
||||
@@ -53,15 +80,30 @@ top_level
|
||||
if_expr
|
||||
condition:
|
||||
binary_expr
|
||||
operator: infix_operator ">"
|
||||
left:
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
operator: infix_operator ">"
|
||||
right: int_literal "0"
|
||||
then:
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
argument:
|
||||
argument
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
else:
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
argument:
|
||||
argument
|
||||
value:
|
||||
@@ -70,18 +112,3 @@ top_level
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
operator: prefix_operator "-"
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
then:
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
argument:
|
||||
argument
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
|
||||
@@ -4,32 +4,48 @@ if let value = optional {
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
if_statement
|
||||
body:
|
||||
block
|
||||
statement:
|
||||
call_expression
|
||||
function: simple_identifier "print"
|
||||
suffix:
|
||||
call_suffix
|
||||
arguments:
|
||||
value_arguments
|
||||
argument:
|
||||
value_argument
|
||||
value: simple_identifier "value"
|
||||
condition:
|
||||
if_condition
|
||||
kind:
|
||||
if_let_binding
|
||||
pattern:
|
||||
pattern
|
||||
binding:
|
||||
value_binding_pattern
|
||||
mutability: let
|
||||
bound_identifier: simple_identifier "value"
|
||||
value: simple_identifier "optional"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
expressionStmt
|
||||
expression:
|
||||
ifExpr
|
||||
body:
|
||||
codeBlock
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
labeledExpr
|
||||
expression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "value"
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "print"
|
||||
conditions:
|
||||
conditionElement
|
||||
condition:
|
||||
optionalBindingCondition
|
||||
initializer:
|
||||
initializerClause
|
||||
equal: =
|
||||
value:
|
||||
declReferenceExpr
|
||||
baseName: identifier "optional"
|
||||
pattern:
|
||||
identifierPattern
|
||||
identifier: identifier "value"
|
||||
bindingSpecifier: let
|
||||
ifKeyword: if
|
||||
|
||||
---
|
||||
|
||||
@@ -42,17 +58,17 @@ top_level
|
||||
pattern_guard_expr
|
||||
pattern:
|
||||
constructor_pattern
|
||||
element:
|
||||
pattern_element
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "value"
|
||||
constructor:
|
||||
member_access_expr
|
||||
base:
|
||||
named_type_expr
|
||||
name: identifier "Optional"
|
||||
member: identifier "some"
|
||||
element:
|
||||
pattern_element
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "value"
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "optional"
|
||||
@@ -60,11 +76,11 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
argument:
|
||||
argument
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "value"
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
|
||||
@@ -4,28 +4,47 @@ if x > 0 {
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
if_statement
|
||||
body:
|
||||
block
|
||||
statement:
|
||||
call_expression
|
||||
function: simple_identifier "print"
|
||||
suffix:
|
||||
call_suffix
|
||||
arguments:
|
||||
value_arguments
|
||||
argument:
|
||||
value_argument
|
||||
value: simple_identifier "x"
|
||||
condition:
|
||||
if_condition
|
||||
kind:
|
||||
comparison_expression
|
||||
lhs: simple_identifier "x"
|
||||
op: >
|
||||
rhs: integer_literal "0"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
expressionStmt
|
||||
expression:
|
||||
ifExpr
|
||||
body:
|
||||
codeBlock
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
labeledExpr
|
||||
expression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "x"
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "print"
|
||||
conditions:
|
||||
conditionElement
|
||||
condition:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator ">"
|
||||
leftOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "x"
|
||||
rightOperand:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "0"
|
||||
ifKeyword: if
|
||||
|
||||
---
|
||||
|
||||
@@ -36,20 +55,20 @@ top_level
|
||||
if_expr
|
||||
condition:
|
||||
binary_expr
|
||||
operator: infix_operator ">"
|
||||
left:
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
operator: infix_operator ">"
|
||||
right: int_literal "0"
|
||||
then:
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
argument:
|
||||
argument
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
|
||||
@@ -9,65 +9,114 @@ default:
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
switch_statement
|
||||
entry:
|
||||
switch_entry
|
||||
pattern:
|
||||
switch_pattern
|
||||
pattern:
|
||||
pattern
|
||||
kind: integer_literal "1"
|
||||
statement:
|
||||
call_expression
|
||||
function: simple_identifier "print"
|
||||
suffix:
|
||||
call_suffix
|
||||
arguments:
|
||||
value_arguments
|
||||
argument:
|
||||
value_argument
|
||||
value:
|
||||
line_string_literal
|
||||
text: line_str_text "one"
|
||||
switch_entry
|
||||
pattern:
|
||||
switch_pattern
|
||||
pattern:
|
||||
pattern
|
||||
kind: integer_literal "2"
|
||||
switch_pattern
|
||||
pattern:
|
||||
pattern
|
||||
kind: integer_literal "3"
|
||||
statement:
|
||||
call_expression
|
||||
function: simple_identifier "print"
|
||||
suffix:
|
||||
call_suffix
|
||||
arguments:
|
||||
value_arguments
|
||||
argument:
|
||||
value_argument
|
||||
value:
|
||||
line_string_literal
|
||||
text: line_str_text "two or three"
|
||||
switch_entry
|
||||
default: default_keyword "default"
|
||||
statement:
|
||||
call_expression
|
||||
function: simple_identifier "print"
|
||||
suffix:
|
||||
call_suffix
|
||||
arguments:
|
||||
value_arguments
|
||||
argument:
|
||||
value_argument
|
||||
value:
|
||||
line_string_literal
|
||||
text: line_str_text "other"
|
||||
expr: simple_identifier "x"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
expressionStmt
|
||||
expression:
|
||||
switchExpr
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
cases:
|
||||
switchCase
|
||||
label:
|
||||
switchCaseLabel
|
||||
colon: :
|
||||
caseKeyword: case
|
||||
caseItems:
|
||||
switchCaseItem
|
||||
pattern:
|
||||
expressionPattern
|
||||
expression:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "1"
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
labeledExpr
|
||||
expression:
|
||||
stringLiteralExpr
|
||||
closingQuote: "
|
||||
openingQuote: "
|
||||
segments:
|
||||
stringSegment
|
||||
content: stringSegment "one"
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "print"
|
||||
switchCase
|
||||
label:
|
||||
switchCaseLabel
|
||||
colon: :
|
||||
caseKeyword: case
|
||||
caseItems:
|
||||
switchCaseItem
|
||||
trailingComma: ,
|
||||
pattern:
|
||||
expressionPattern
|
||||
expression:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "2"
|
||||
switchCaseItem
|
||||
pattern:
|
||||
expressionPattern
|
||||
expression:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "3"
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
labeledExpr
|
||||
expression:
|
||||
stringLiteralExpr
|
||||
closingQuote: "
|
||||
openingQuote: "
|
||||
segments:
|
||||
stringSegment
|
||||
content: stringSegment "two or three"
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "print"
|
||||
switchCase
|
||||
label:
|
||||
switchDefaultLabel
|
||||
colon: :
|
||||
defaultKeyword: default
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
labeledExpr
|
||||
expression:
|
||||
stringLiteralExpr
|
||||
closingQuote: "
|
||||
openingQuote: "
|
||||
segments:
|
||||
stringSegment
|
||||
content: stringSegment "other"
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "print"
|
||||
subject:
|
||||
declReferenceExpr
|
||||
baseName: identifier "x"
|
||||
switchKeyword: switch
|
||||
|
||||
---
|
||||
|
||||
@@ -76,32 +125,25 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
switch_expr
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
case:
|
||||
switch_case
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
argument:
|
||||
argument
|
||||
value: string_literal "\"one\""
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
pattern:
|
||||
expr_equality_pattern
|
||||
expr: int_literal "1"
|
||||
switch_case
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
argument:
|
||||
argument
|
||||
value: string_literal "\"two or three\""
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
argument:
|
||||
argument
|
||||
value: string_literal "\"one\""
|
||||
switch_case
|
||||
pattern:
|
||||
or_pattern
|
||||
pattern:
|
||||
@@ -109,17 +151,24 @@ top_level
|
||||
expr: int_literal "2"
|
||||
expr_equality_pattern
|
||||
expr: int_literal "3"
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
argument:
|
||||
argument
|
||||
value: string_literal "\"two or three\""
|
||||
switch_case
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
argument:
|
||||
argument
|
||||
value: string_literal "\"other\""
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
argument:
|
||||
argument
|
||||
value: string_literal "\"other\""
|
||||
|
||||
@@ -7,77 +7,111 @@ case .square(let s):
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
switch_statement
|
||||
entry:
|
||||
switch_entry
|
||||
pattern:
|
||||
switch_pattern
|
||||
pattern:
|
||||
pattern
|
||||
kind:
|
||||
case_pattern
|
||||
arguments:
|
||||
tuple_pattern
|
||||
item:
|
||||
tuple_pattern_item
|
||||
pattern:
|
||||
pattern
|
||||
kind:
|
||||
binding_pattern
|
||||
binding:
|
||||
value_binding_pattern
|
||||
mutability: let
|
||||
pattern:
|
||||
pattern
|
||||
bound_identifier: simple_identifier "r"
|
||||
dot: .
|
||||
name: simple_identifier "circle"
|
||||
statement:
|
||||
call_expression
|
||||
function: simple_identifier "print"
|
||||
suffix:
|
||||
call_suffix
|
||||
arguments:
|
||||
value_arguments
|
||||
argument:
|
||||
value_argument
|
||||
value: simple_identifier "r"
|
||||
switch_entry
|
||||
pattern:
|
||||
switch_pattern
|
||||
pattern:
|
||||
pattern
|
||||
kind:
|
||||
case_pattern
|
||||
arguments:
|
||||
tuple_pattern
|
||||
item:
|
||||
tuple_pattern_item
|
||||
pattern:
|
||||
pattern
|
||||
kind:
|
||||
binding_pattern
|
||||
binding:
|
||||
value_binding_pattern
|
||||
mutability: let
|
||||
pattern:
|
||||
pattern
|
||||
bound_identifier: simple_identifier "s"
|
||||
dot: .
|
||||
name: simple_identifier "square"
|
||||
statement:
|
||||
call_expression
|
||||
function: simple_identifier "print"
|
||||
suffix:
|
||||
call_suffix
|
||||
arguments:
|
||||
value_arguments
|
||||
argument:
|
||||
value_argument
|
||||
value: simple_identifier "s"
|
||||
expr: simple_identifier "shape"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
expressionStmt
|
||||
expression:
|
||||
switchExpr
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
cases:
|
||||
switchCase
|
||||
label:
|
||||
switchCaseLabel
|
||||
colon: :
|
||||
caseKeyword: case
|
||||
caseItems:
|
||||
switchCaseItem
|
||||
pattern:
|
||||
expressionPattern
|
||||
expression:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
labeledExpr
|
||||
expression:
|
||||
patternExpr
|
||||
pattern:
|
||||
valueBindingPattern
|
||||
pattern:
|
||||
identifierPattern
|
||||
identifier: identifier "r"
|
||||
bindingSpecifier: let
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
memberAccessExpr
|
||||
period: .
|
||||
declName:
|
||||
declReferenceExpr
|
||||
baseName: identifier "circle"
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
labeledExpr
|
||||
expression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "r"
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "print"
|
||||
switchCase
|
||||
label:
|
||||
switchCaseLabel
|
||||
colon: :
|
||||
caseKeyword: case
|
||||
caseItems:
|
||||
switchCaseItem
|
||||
pattern:
|
||||
expressionPattern
|
||||
expression:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
labeledExpr
|
||||
expression:
|
||||
patternExpr
|
||||
pattern:
|
||||
valueBindingPattern
|
||||
pattern:
|
||||
identifierPattern
|
||||
identifier: identifier "s"
|
||||
bindingSpecifier: let
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
memberAccessExpr
|
||||
period: .
|
||||
declName:
|
||||
declReferenceExpr
|
||||
baseName: identifier "square"
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
labeledExpr
|
||||
expression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "s"
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "print"
|
||||
subject:
|
||||
declReferenceExpr
|
||||
baseName: identifier "shape"
|
||||
switchKeyword: switch
|
||||
|
||||
---
|
||||
|
||||
@@ -86,55 +120,55 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
switch_expr
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "shape"
|
||||
case:
|
||||
switch_case
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
argument:
|
||||
argument
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "r"
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
pattern:
|
||||
constructor_pattern
|
||||
constructor:
|
||||
member_access_expr
|
||||
base: inferred_type_expr "."
|
||||
member: identifier "circle"
|
||||
element:
|
||||
pattern_element
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "r"
|
||||
constructor:
|
||||
member_access_expr
|
||||
base: inferred_type_expr "."
|
||||
member: identifier "circle"
|
||||
switch_case
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
argument:
|
||||
argument
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "s"
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
identifier: identifier "r"
|
||||
switch_case
|
||||
pattern:
|
||||
constructor_pattern
|
||||
constructor:
|
||||
member_access_expr
|
||||
base: inferred_type_expr "."
|
||||
member: identifier "square"
|
||||
element:
|
||||
pattern_element
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "s"
|
||||
constructor:
|
||||
member_access_expr
|
||||
base: inferred_type_expr "."
|
||||
member: identifier "square"
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "shape"
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
argument:
|
||||
argument
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "s"
|
||||
|
||||
@@ -7,79 +7,119 @@ case .thread(threadRowId: _, let rowId):
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
switch_statement
|
||||
entry:
|
||||
switch_entry
|
||||
pattern:
|
||||
switch_pattern
|
||||
pattern:
|
||||
pattern
|
||||
kind:
|
||||
case_pattern
|
||||
arguments:
|
||||
tuple_pattern
|
||||
item:
|
||||
tuple_pattern_item
|
||||
name: simple_identifier "isAcknowledged"
|
||||
pattern:
|
||||
pattern
|
||||
kind:
|
||||
boolean_literal
|
||||
dot: .
|
||||
name: simple_identifier "implicit"
|
||||
statement:
|
||||
call_expression
|
||||
function: simple_identifier "print"
|
||||
suffix:
|
||||
call_suffix
|
||||
arguments:
|
||||
value_arguments
|
||||
argument:
|
||||
value_argument
|
||||
value:
|
||||
line_string_literal
|
||||
text: line_str_text "yes"
|
||||
switch_entry
|
||||
pattern:
|
||||
switch_pattern
|
||||
pattern:
|
||||
pattern
|
||||
kind:
|
||||
case_pattern
|
||||
arguments:
|
||||
tuple_pattern
|
||||
item:
|
||||
tuple_pattern_item
|
||||
name: simple_identifier "threadRowId"
|
||||
pattern:
|
||||
pattern
|
||||
kind: wildcard_pattern "_"
|
||||
tuple_pattern_item
|
||||
pattern:
|
||||
pattern
|
||||
kind:
|
||||
binding_pattern
|
||||
binding:
|
||||
value_binding_pattern
|
||||
mutability: let
|
||||
pattern:
|
||||
pattern
|
||||
bound_identifier: simple_identifier "rowId"
|
||||
dot: .
|
||||
name: simple_identifier "thread"
|
||||
statement:
|
||||
call_expression
|
||||
function: simple_identifier "print"
|
||||
suffix:
|
||||
call_suffix
|
||||
arguments:
|
||||
value_arguments
|
||||
argument:
|
||||
value_argument
|
||||
value: simple_identifier "rowId"
|
||||
expr: simple_identifier "x"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
expressionStmt
|
||||
expression:
|
||||
switchExpr
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
cases:
|
||||
switchCase
|
||||
label:
|
||||
switchCaseLabel
|
||||
colon: :
|
||||
caseKeyword: case
|
||||
caseItems:
|
||||
switchCaseItem
|
||||
pattern:
|
||||
expressionPattern
|
||||
expression:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
labeledExpr
|
||||
colon: :
|
||||
label: identifier "isAcknowledged"
|
||||
expression:
|
||||
booleanLiteralExpr
|
||||
literal: false
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
memberAccessExpr
|
||||
period: .
|
||||
declName:
|
||||
declReferenceExpr
|
||||
baseName: identifier "implicit"
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
labeledExpr
|
||||
expression:
|
||||
stringLiteralExpr
|
||||
closingQuote: "
|
||||
openingQuote: "
|
||||
segments:
|
||||
stringSegment
|
||||
content: stringSegment "yes"
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "print"
|
||||
switchCase
|
||||
label:
|
||||
switchCaseLabel
|
||||
colon: :
|
||||
caseKeyword: case
|
||||
caseItems:
|
||||
switchCaseItem
|
||||
pattern:
|
||||
expressionPattern
|
||||
expression:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
labeledExpr
|
||||
colon: :
|
||||
label: identifier "threadRowId"
|
||||
expression:
|
||||
discardAssignmentExpr
|
||||
wildcard: _
|
||||
trailingComma: ,
|
||||
labeledExpr
|
||||
expression:
|
||||
patternExpr
|
||||
pattern:
|
||||
valueBindingPattern
|
||||
pattern:
|
||||
identifierPattern
|
||||
identifier: identifier "rowId"
|
||||
bindingSpecifier: let
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
memberAccessExpr
|
||||
period: .
|
||||
declName:
|
||||
declReferenceExpr
|
||||
baseName: identifier "thread"
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
labeledExpr
|
||||
expression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "rowId"
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "print"
|
||||
subject:
|
||||
declReferenceExpr
|
||||
baseName: identifier "x"
|
||||
switchKeyword: switch
|
||||
|
||||
---
|
||||
|
||||
@@ -88,45 +128,40 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
switch_expr
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
case:
|
||||
switch_case
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
argument:
|
||||
argument
|
||||
value: string_literal "\"yes\""
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
pattern:
|
||||
constructor_pattern
|
||||
constructor:
|
||||
member_access_expr
|
||||
base: inferred_type_expr "."
|
||||
member: identifier "implicit"
|
||||
element:
|
||||
pattern_element
|
||||
key: identifier "isAcknowledged"
|
||||
pattern:
|
||||
expr_equality_pattern
|
||||
expr: boolean_literal "false"
|
||||
constructor:
|
||||
member_access_expr
|
||||
base: inferred_type_expr "."
|
||||
member: identifier "implicit"
|
||||
switch_case
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
argument:
|
||||
argument
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "rowId"
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
argument:
|
||||
argument
|
||||
value: string_literal "\"yes\""
|
||||
switch_case
|
||||
pattern:
|
||||
constructor_pattern
|
||||
constructor:
|
||||
member_access_expr
|
||||
base: inferred_type_expr "."
|
||||
member: identifier "thread"
|
||||
element:
|
||||
pattern_element
|
||||
key: identifier "threadRowId"
|
||||
@@ -135,10 +170,15 @@ top_level
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "rowId"
|
||||
constructor:
|
||||
member_access_expr
|
||||
base: inferred_type_expr "."
|
||||
member: identifier "thread"
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
argument:
|
||||
argument
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "rowId"
|
||||
|
||||
@@ -2,29 +2,47 @@ let y = x > 0 ? 1 : -1
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
property_declaration
|
||||
binding:
|
||||
value_binding_pattern
|
||||
mutability: let
|
||||
declarator:
|
||||
property_binding
|
||||
name:
|
||||
pattern
|
||||
bound_identifier: simple_identifier "y"
|
||||
value:
|
||||
ternary_expression
|
||||
condition:
|
||||
comparison_expression
|
||||
lhs: simple_identifier "x"
|
||||
op: >
|
||||
rhs: integer_literal "0"
|
||||
if_false:
|
||||
prefix_expression
|
||||
operation: -
|
||||
target: integer_literal "1"
|
||||
if_true: integer_literal "1"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
variableDecl
|
||||
attributes:
|
||||
modifiers:
|
||||
bindingSpecifier: let
|
||||
bindings:
|
||||
patternBinding
|
||||
initializer:
|
||||
initializerClause
|
||||
equal: =
|
||||
value:
|
||||
ternaryExpr
|
||||
colon: :
|
||||
condition:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator ">"
|
||||
leftOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "x"
|
||||
rightOperand:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "0"
|
||||
questionMark: ?
|
||||
elseExpression:
|
||||
prefixOperatorExpr
|
||||
expression:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "1"
|
||||
operator: prefixOperator "-"
|
||||
thenExpression:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "1"
|
||||
pattern:
|
||||
identifierPattern
|
||||
identifier: identifier "y"
|
||||
|
||||
---
|
||||
|
||||
@@ -41,13 +59,13 @@ top_level
|
||||
if_expr
|
||||
condition:
|
||||
binary_expr
|
||||
operator: infix_operator ">"
|
||||
left:
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
operator: infix_operator ">"
|
||||
right: int_literal "0"
|
||||
then: int_literal "1"
|
||||
else:
|
||||
unary_expr
|
||||
operand: int_literal "1"
|
||||
operator: prefix_operator "-"
|
||||
then: int_literal "1"
|
||||
|
||||
@@ -2,12 +2,21 @@
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
additive_expression
|
||||
lhs: integer_literal "1"
|
||||
op: +
|
||||
rhs: integer_literal "2"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator "+"
|
||||
leftOperand:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "1"
|
||||
rightOperand:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "2"
|
||||
|
||||
---
|
||||
|
||||
@@ -16,6 +25,6 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
binary_expr
|
||||
operator: infix_operator "+"
|
||||
left: int_literal "1"
|
||||
operator: infix_operator "+"
|
||||
right: int_literal "2"
|
||||
|
||||
@@ -2,12 +2,21 @@ foo + bar
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
additive_expression
|
||||
lhs: simple_identifier "foo"
|
||||
op: +
|
||||
rhs: simple_identifier "bar"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator "+"
|
||||
leftOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "foo"
|
||||
rightOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "bar"
|
||||
|
||||
---
|
||||
|
||||
@@ -16,10 +25,10 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
binary_expr
|
||||
operator: infix_operator "+"
|
||||
left:
|
||||
name_expr
|
||||
identifier: identifier "foo"
|
||||
operator: infix_operator "+"
|
||||
right:
|
||||
name_expr
|
||||
identifier: identifier "bar"
|
||||
|
||||
@@ -2,15 +2,24 @@ import Foundation.Networking.URLSession
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
import_declaration
|
||||
name:
|
||||
identifier
|
||||
part:
|
||||
simple_identifier "Foundation"
|
||||
simple_identifier "Networking"
|
||||
simple_identifier "URLSession"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
importDecl
|
||||
attributes:
|
||||
modifiers:
|
||||
importKeyword: import
|
||||
path:
|
||||
importPathComponent
|
||||
name: identifier "Foundation"
|
||||
trailingPeriod: .
|
||||
importPathComponent
|
||||
name: identifier "Networking"
|
||||
trailingPeriod: .
|
||||
importPathComponent
|
||||
name: identifier "URLSession"
|
||||
|
||||
---
|
||||
|
||||
@@ -19,7 +28,6 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
import_declaration
|
||||
pattern: bulk_importing_pattern "import Foundation.Networking.URLSession"
|
||||
imported_expr:
|
||||
member_access_expr
|
||||
base:
|
||||
@@ -29,3 +37,4 @@ top_level
|
||||
identifier: identifier "Foundation"
|
||||
member: identifier "Networking"
|
||||
member: identifier "URLSession"
|
||||
pattern: bulk_importing_pattern "import Foundation.Networking.URLSession"
|
||||
|
||||
@@ -2,14 +2,21 @@ import Foundation.Networking
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
import_declaration
|
||||
name:
|
||||
identifier
|
||||
part:
|
||||
simple_identifier "Foundation"
|
||||
simple_identifier "Networking"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
importDecl
|
||||
attributes:
|
||||
modifiers:
|
||||
importKeyword: import
|
||||
path:
|
||||
importPathComponent
|
||||
name: identifier "Foundation"
|
||||
trailingPeriod: .
|
||||
importPathComponent
|
||||
name: identifier "Networking"
|
||||
|
||||
---
|
||||
|
||||
@@ -18,10 +25,10 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
import_declaration
|
||||
pattern: bulk_importing_pattern "import Foundation.Networking"
|
||||
imported_expr:
|
||||
member_access_expr
|
||||
base:
|
||||
name_expr
|
||||
identifier: identifier "Foundation"
|
||||
member: identifier "Networking"
|
||||
pattern: bulk_importing_pattern "import Foundation.Networking"
|
||||
|
||||
@@ -2,15 +2,22 @@ import struct Foundation.Date
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
import_declaration
|
||||
name:
|
||||
identifier
|
||||
part:
|
||||
simple_identifier "Foundation"
|
||||
simple_identifier "Date"
|
||||
scoped_import_kind: struct
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
importDecl
|
||||
attributes:
|
||||
modifiers:
|
||||
importKeyword: import
|
||||
importKindSpecifier: struct
|
||||
path:
|
||||
importPathComponent
|
||||
name: identifier "Foundation"
|
||||
trailingPeriod: .
|
||||
importPathComponent
|
||||
name: identifier "Date"
|
||||
|
||||
---
|
||||
|
||||
@@ -20,12 +27,12 @@ top_level
|
||||
stmt:
|
||||
import_declaration
|
||||
modifier: modifier "struct"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "Date"
|
||||
imported_expr:
|
||||
member_access_expr
|
||||
base:
|
||||
name_expr
|
||||
identifier: identifier "Foundation"
|
||||
member: identifier "Date"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "Date"
|
||||
|
||||
@@ -2,12 +2,18 @@ import Foundation
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
import_declaration
|
||||
name:
|
||||
identifier
|
||||
part: simple_identifier "Foundation"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
importDecl
|
||||
attributes:
|
||||
modifiers:
|
||||
importKeyword: import
|
||||
path:
|
||||
importPathComponent
|
||||
name: identifier "Foundation"
|
||||
|
||||
---
|
||||
|
||||
@@ -16,7 +22,7 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
import_declaration
|
||||
pattern: bulk_importing_pattern "import Foundation"
|
||||
imported_expr:
|
||||
name_expr
|
||||
identifier: identifier "Foundation"
|
||||
pattern: bulk_importing_pattern "import Foundation"
|
||||
|
||||
@@ -2,22 +2,29 @@ greet(person: "Bob")
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
call_expression
|
||||
function: simple_identifier "greet"
|
||||
suffix:
|
||||
call_suffix
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
value_arguments
|
||||
argument:
|
||||
value_argument
|
||||
name:
|
||||
value_argument_label
|
||||
name: simple_identifier "person"
|
||||
value:
|
||||
line_string_literal
|
||||
text: line_str_text "Bob"
|
||||
labeledExpr
|
||||
colon: :
|
||||
label: identifier "person"
|
||||
expression:
|
||||
stringLiteralExpr
|
||||
closingQuote: "
|
||||
openingQuote: "
|
||||
segments:
|
||||
stringSegment
|
||||
content: stringSegment "Bob"
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "greet"
|
||||
|
||||
---
|
||||
|
||||
@@ -26,10 +33,10 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "greet"
|
||||
argument:
|
||||
argument
|
||||
name: identifier "person"
|
||||
value: string_literal "\"Bob\""
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "greet"
|
||||
|
||||
@@ -2,19 +2,28 @@ foo(1, 2)
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
call_expression
|
||||
function: simple_identifier "foo"
|
||||
suffix:
|
||||
call_suffix
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
value_arguments
|
||||
argument:
|
||||
value_argument
|
||||
value: integer_literal "1"
|
||||
value_argument
|
||||
value: integer_literal "2"
|
||||
labeledExpr
|
||||
expression:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "1"
|
||||
trailingComma: ,
|
||||
labeledExpr
|
||||
expression:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "2"
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "foo"
|
||||
|
||||
---
|
||||
|
||||
@@ -23,11 +32,11 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "foo"
|
||||
argument:
|
||||
argument
|
||||
value: int_literal "1"
|
||||
argument
|
||||
value: int_literal "2"
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "foo"
|
||||
|
||||
@@ -4,37 +4,60 @@ func greet(name: String = "world") {
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
function_declaration
|
||||
body:
|
||||
block
|
||||
statement:
|
||||
call_expression
|
||||
function: simple_identifier "print"
|
||||
suffix:
|
||||
call_suffix
|
||||
arguments:
|
||||
value_arguments
|
||||
argument:
|
||||
value_argument
|
||||
value: simple_identifier "name"
|
||||
name: simple_identifier "greet"
|
||||
parameter:
|
||||
function_parameter
|
||||
default_value:
|
||||
line_string_literal
|
||||
text: line_str_text "world"
|
||||
parameter:
|
||||
parameter
|
||||
name: simple_identifier "name"
|
||||
type:
|
||||
type
|
||||
name:
|
||||
user_type
|
||||
part:
|
||||
simple_user_type
|
||||
name: type_identifier "String"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionDecl
|
||||
attributes:
|
||||
body:
|
||||
codeBlock
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
labeledExpr
|
||||
expression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "name"
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "print"
|
||||
name: identifier "greet"
|
||||
modifiers:
|
||||
signature:
|
||||
functionSignature
|
||||
parameterClause:
|
||||
functionParameterClause
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
parameters:
|
||||
functionParameter
|
||||
colon: :
|
||||
attributes:
|
||||
modifiers:
|
||||
type:
|
||||
identifierType
|
||||
name: identifier "String"
|
||||
firstName: identifier "name"
|
||||
defaultValue:
|
||||
initializerClause
|
||||
equal: =
|
||||
value:
|
||||
stringLiteralExpr
|
||||
closingQuote: "
|
||||
openingQuote: "
|
||||
segments:
|
||||
stringSegment
|
||||
content: stringSegment "world"
|
||||
funcKeyword: func
|
||||
|
||||
---
|
||||
|
||||
@@ -43,22 +66,22 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
function_declaration
|
||||
name: identifier "greet"
|
||||
parameter:
|
||||
parameter
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "name"
|
||||
default: string_literal "\"world\""
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
argument:
|
||||
argument
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "name"
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
name: identifier "greet"
|
||||
parameter:
|
||||
parameter
|
||||
default: string_literal "\"world\""
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "name"
|
||||
|
||||
@@ -4,35 +4,51 @@ func greet(person name: String) {
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
function_declaration
|
||||
body:
|
||||
block
|
||||
statement:
|
||||
call_expression
|
||||
function: simple_identifier "print"
|
||||
suffix:
|
||||
call_suffix
|
||||
arguments:
|
||||
value_arguments
|
||||
argument:
|
||||
value_argument
|
||||
value: simple_identifier "name"
|
||||
name: simple_identifier "greet"
|
||||
parameter:
|
||||
function_parameter
|
||||
parameter:
|
||||
parameter
|
||||
external_name: simple_identifier "person"
|
||||
name: simple_identifier "name"
|
||||
type:
|
||||
type
|
||||
name:
|
||||
user_type
|
||||
part:
|
||||
simple_user_type
|
||||
name: type_identifier "String"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionDecl
|
||||
attributes:
|
||||
body:
|
||||
codeBlock
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
labeledExpr
|
||||
expression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "name"
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "print"
|
||||
name: identifier "greet"
|
||||
modifiers:
|
||||
signature:
|
||||
functionSignature
|
||||
parameterClause:
|
||||
functionParameterClause
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
parameters:
|
||||
functionParameter
|
||||
colon: :
|
||||
attributes:
|
||||
modifiers:
|
||||
type:
|
||||
identifierType
|
||||
name: identifier "String"
|
||||
firstName: identifier "person"
|
||||
secondName: identifier "name"
|
||||
funcKeyword: func
|
||||
|
||||
---
|
||||
|
||||
@@ -41,18 +57,6 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
function_declaration
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
argument:
|
||||
argument
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "name"
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
name: identifier "greet"
|
||||
parameter:
|
||||
parameter
|
||||
@@ -60,3 +64,15 @@ top_level
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "name"
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
argument:
|
||||
argument
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "name"
|
||||
|
||||
@@ -4,24 +4,46 @@ func greet() {
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
function_declaration
|
||||
body:
|
||||
block
|
||||
statement:
|
||||
call_expression
|
||||
function: simple_identifier "print"
|
||||
suffix:
|
||||
call_suffix
|
||||
arguments:
|
||||
value_arguments
|
||||
argument:
|
||||
value_argument
|
||||
value:
|
||||
line_string_literal
|
||||
text: line_str_text "hello"
|
||||
name: simple_identifier "greet"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionDecl
|
||||
attributes:
|
||||
body:
|
||||
codeBlock
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
labeledExpr
|
||||
expression:
|
||||
stringLiteralExpr
|
||||
closingQuote: "
|
||||
openingQuote: "
|
||||
segments:
|
||||
stringSegment
|
||||
content: stringSegment "hello"
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "print"
|
||||
name: identifier "greet"
|
||||
modifiers:
|
||||
signature:
|
||||
functionSignature
|
||||
parameterClause:
|
||||
functionParameterClause
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
parameters:
|
||||
funcKeyword: func
|
||||
|
||||
---
|
||||
|
||||
@@ -30,14 +52,14 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
function_declaration
|
||||
name: identifier "greet"
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
argument:
|
||||
argument
|
||||
value: string_literal "\"hello\""
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
name: identifier "greet"
|
||||
argument:
|
||||
argument
|
||||
value: string_literal "\"hello\""
|
||||
|
||||
@@ -4,52 +4,68 @@ func add(_ a: Int, _ b: Int) -> Int {
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
function_declaration
|
||||
body:
|
||||
block
|
||||
statement:
|
||||
control_transfer_statement
|
||||
kind: return
|
||||
result:
|
||||
additive_expression
|
||||
lhs: simple_identifier "a"
|
||||
op: +
|
||||
rhs: simple_identifier "b"
|
||||
name: simple_identifier "add"
|
||||
parameter:
|
||||
function_parameter
|
||||
parameter:
|
||||
parameter
|
||||
external_name: simple_identifier "_"
|
||||
name: simple_identifier "a"
|
||||
type:
|
||||
type
|
||||
name:
|
||||
user_type
|
||||
part:
|
||||
simple_user_type
|
||||
name: type_identifier "Int"
|
||||
function_parameter
|
||||
parameter:
|
||||
parameter
|
||||
external_name: simple_identifier "_"
|
||||
name: simple_identifier "b"
|
||||
type:
|
||||
type
|
||||
name:
|
||||
user_type
|
||||
part:
|
||||
simple_user_type
|
||||
name: type_identifier "Int"
|
||||
return_type:
|
||||
type
|
||||
name:
|
||||
user_type
|
||||
part:
|
||||
simple_user_type
|
||||
name: type_identifier "Int"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionDecl
|
||||
attributes:
|
||||
body:
|
||||
codeBlock
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
returnStmt
|
||||
expression:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator "+"
|
||||
leftOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "a"
|
||||
rightOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "b"
|
||||
returnKeyword: return
|
||||
name: identifier "add"
|
||||
modifiers:
|
||||
signature:
|
||||
functionSignature
|
||||
parameterClause:
|
||||
functionParameterClause
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
parameters:
|
||||
functionParameter
|
||||
colon: :
|
||||
attributes:
|
||||
modifiers:
|
||||
trailingComma: ,
|
||||
type:
|
||||
identifierType
|
||||
name: identifier "Int"
|
||||
firstName: _
|
||||
secondName: identifier "a"
|
||||
functionParameter
|
||||
colon: :
|
||||
attributes:
|
||||
modifiers:
|
||||
type:
|
||||
identifierType
|
||||
name: identifier "Int"
|
||||
firstName: _
|
||||
secondName: identifier "b"
|
||||
returnClause:
|
||||
returnClause
|
||||
arrow: ->
|
||||
type:
|
||||
identifierType
|
||||
name: identifier "Int"
|
||||
funcKeyword: func
|
||||
|
||||
---
|
||||
|
||||
@@ -58,19 +74,6 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
function_declaration
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
return_expr
|
||||
value:
|
||||
binary_expr
|
||||
operator: infix_operator "+"
|
||||
left:
|
||||
name_expr
|
||||
identifier: identifier "a"
|
||||
right:
|
||||
name_expr
|
||||
identifier: identifier "b"
|
||||
name: identifier "add"
|
||||
parameter:
|
||||
parameter
|
||||
@@ -86,3 +89,16 @@ top_level
|
||||
return_type:
|
||||
named_type_expr
|
||||
name: identifier "Int"
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
return_expr
|
||||
value:
|
||||
binary_expr
|
||||
left:
|
||||
name_expr
|
||||
identifier: identifier "a"
|
||||
operator: infix_operator "+"
|
||||
right:
|
||||
name_expr
|
||||
identifier: identifier "b"
|
||||
|
||||
@@ -4,41 +4,58 @@ func identity<T>(_ x: T) -> T {
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
function_declaration
|
||||
body:
|
||||
block
|
||||
statement:
|
||||
control_transfer_statement
|
||||
kind: return
|
||||
result: simple_identifier "x"
|
||||
name: simple_identifier "identity"
|
||||
parameter:
|
||||
function_parameter
|
||||
parameter:
|
||||
parameter
|
||||
external_name: simple_identifier "_"
|
||||
name: simple_identifier "x"
|
||||
type:
|
||||
type
|
||||
name:
|
||||
user_type
|
||||
part:
|
||||
simple_user_type
|
||||
name: type_identifier "T"
|
||||
return_type:
|
||||
type
|
||||
name:
|
||||
user_type
|
||||
part:
|
||||
simple_user_type
|
||||
name: type_identifier "T"
|
||||
type_parameters:
|
||||
type_parameters
|
||||
parameter:
|
||||
type_parameter
|
||||
name: type_identifier "T"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionDecl
|
||||
attributes:
|
||||
body:
|
||||
codeBlock
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
returnStmt
|
||||
expression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "x"
|
||||
returnKeyword: return
|
||||
name: identifier "identity"
|
||||
genericParameterClause:
|
||||
genericParameterClause
|
||||
parameters:
|
||||
genericParameter
|
||||
attributes:
|
||||
name: identifier "T"
|
||||
leftAngle: <
|
||||
rightAngle: >
|
||||
modifiers:
|
||||
signature:
|
||||
functionSignature
|
||||
parameterClause:
|
||||
functionParameterClause
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
parameters:
|
||||
functionParameter
|
||||
colon: :
|
||||
attributes:
|
||||
modifiers:
|
||||
type:
|
||||
identifierType
|
||||
name: identifier "T"
|
||||
firstName: _
|
||||
secondName: identifier "x"
|
||||
returnClause:
|
||||
returnClause
|
||||
arrow: ->
|
||||
type:
|
||||
identifierType
|
||||
name: identifier "T"
|
||||
funcKeyword: func
|
||||
|
||||
---
|
||||
|
||||
@@ -47,13 +64,6 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
function_declaration
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
return_expr
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
name: identifier "identity"
|
||||
parameter:
|
||||
parameter
|
||||
@@ -64,3 +74,10 @@ top_level
|
||||
return_type:
|
||||
named_type_expr
|
||||
name: identifier "T"
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
return_expr
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
|
||||
@@ -2,30 +2,39 @@ let y = .some(1)
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
property_declaration
|
||||
binding:
|
||||
value_binding_pattern
|
||||
mutability: let
|
||||
declarator:
|
||||
property_binding
|
||||
name:
|
||||
pattern
|
||||
bound_identifier: simple_identifier "y"
|
||||
value:
|
||||
call_expression
|
||||
function:
|
||||
prefix_expression
|
||||
operation: .
|
||||
target: simple_identifier "some"
|
||||
suffix:
|
||||
call_suffix
|
||||
arguments:
|
||||
value_arguments
|
||||
argument:
|
||||
value_argument
|
||||
value: integer_literal "1"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
variableDecl
|
||||
attributes:
|
||||
modifiers:
|
||||
bindingSpecifier: let
|
||||
bindings:
|
||||
patternBinding
|
||||
initializer:
|
||||
initializerClause
|
||||
equal: =
|
||||
value:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
labeledExpr
|
||||
expression:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "1"
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
memberAccessExpr
|
||||
period: .
|
||||
declName:
|
||||
declReferenceExpr
|
||||
baseName: identifier "some"
|
||||
pattern:
|
||||
identifierPattern
|
||||
identifier: identifier "y"
|
||||
|
||||
---
|
||||
|
||||
@@ -40,10 +49,10 @@ top_level
|
||||
identifier: identifier "y"
|
||||
value:
|
||||
call_expr
|
||||
argument:
|
||||
argument
|
||||
value: int_literal "1"
|
||||
callee:
|
||||
member_access_expr
|
||||
base: inferred_type_expr ".some"
|
||||
member: identifier "some"
|
||||
argument:
|
||||
argument
|
||||
value: int_literal "1"
|
||||
|
||||
@@ -2,21 +2,29 @@ let x = .foo
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
property_declaration
|
||||
binding:
|
||||
value_binding_pattern
|
||||
mutability: let
|
||||
declarator:
|
||||
property_binding
|
||||
name:
|
||||
pattern
|
||||
bound_identifier: simple_identifier "x"
|
||||
value:
|
||||
prefix_expression
|
||||
operation: .
|
||||
target: simple_identifier "foo"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
variableDecl
|
||||
attributes:
|
||||
modifiers:
|
||||
bindingSpecifier: let
|
||||
bindings:
|
||||
patternBinding
|
||||
initializer:
|
||||
initializerClause
|
||||
equal: =
|
||||
value:
|
||||
memberAccessExpr
|
||||
period: .
|
||||
declName:
|
||||
declReferenceExpr
|
||||
baseName: identifier "foo"
|
||||
pattern:
|
||||
identifierPattern
|
||||
identifier: identifier "x"
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,22 +2,29 @@ list.append(1)
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
call_expression
|
||||
function:
|
||||
navigation_expression
|
||||
suffix:
|
||||
navigation_suffix
|
||||
suffix: simple_identifier "append"
|
||||
target: simple_identifier "list"
|
||||
suffix:
|
||||
call_suffix
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
value_arguments
|
||||
argument:
|
||||
value_argument
|
||||
value: integer_literal "1"
|
||||
labeledExpr
|
||||
expression:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "1"
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
memberAccessExpr
|
||||
period: .
|
||||
declName:
|
||||
declReferenceExpr
|
||||
baseName: identifier "append"
|
||||
base:
|
||||
declReferenceExpr
|
||||
baseName: identifier "list"
|
||||
|
||||
---
|
||||
|
||||
@@ -26,12 +33,12 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
argument:
|
||||
argument
|
||||
value: int_literal "1"
|
||||
callee:
|
||||
member_access_expr
|
||||
base:
|
||||
name_expr
|
||||
identifier: identifier "list"
|
||||
member: identifier "append"
|
||||
argument:
|
||||
argument
|
||||
value: int_literal "1"
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
typealias NestedFunction = ((Int) -> Bool) -> Bool
|
||||
|
||||
typealias MixedParametersAndTuples = ((Int) -> Bool, String) -> (Bool, Int)
|
||||
|
||||
---
|
||||
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
typeAliasDecl
|
||||
attributes:
|
||||
name: identifier "NestedFunction"
|
||||
modifiers:
|
||||
initializer:
|
||||
typeInitializerClause
|
||||
equal: =
|
||||
value:
|
||||
functionType
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
parameters:
|
||||
tupleTypeElement
|
||||
type:
|
||||
functionType
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
parameters:
|
||||
tupleTypeElement
|
||||
type:
|
||||
identifierType
|
||||
name: identifier "Int"
|
||||
returnClause:
|
||||
returnClause
|
||||
arrow: ->
|
||||
type:
|
||||
identifierType
|
||||
name: identifier "Bool"
|
||||
returnClause:
|
||||
returnClause
|
||||
arrow: ->
|
||||
type:
|
||||
identifierType
|
||||
name: identifier "Bool"
|
||||
typealiasKeyword: typealias
|
||||
codeBlockItem
|
||||
item:
|
||||
typeAliasDecl
|
||||
attributes:
|
||||
name: identifier "MixedParametersAndTuples"
|
||||
modifiers:
|
||||
initializer:
|
||||
typeInitializerClause
|
||||
equal: =
|
||||
value:
|
||||
functionType
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
parameters:
|
||||
tupleTypeElement
|
||||
trailingComma: ,
|
||||
type:
|
||||
functionType
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
parameters:
|
||||
tupleTypeElement
|
||||
type:
|
||||
identifierType
|
||||
name: identifier "Int"
|
||||
returnClause:
|
||||
returnClause
|
||||
arrow: ->
|
||||
type:
|
||||
identifierType
|
||||
name: identifier "Bool"
|
||||
tupleTypeElement
|
||||
type:
|
||||
identifierType
|
||||
name: identifier "String"
|
||||
returnClause:
|
||||
returnClause
|
||||
arrow: ->
|
||||
type:
|
||||
tupleType
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
elements:
|
||||
tupleTypeElement
|
||||
trailingComma: ,
|
||||
type:
|
||||
identifierType
|
||||
name: identifier "Bool"
|
||||
tupleTypeElement
|
||||
type:
|
||||
identifierType
|
||||
name: identifier "Int"
|
||||
typealiasKeyword: typealias
|
||||
|
||||
---
|
||||
|
||||
top_level
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
type_alias_declaration
|
||||
name: identifier "NestedFunction"
|
||||
type:
|
||||
function_type_expr
|
||||
parameter:
|
||||
parameter
|
||||
type:
|
||||
function_type_expr
|
||||
parameter:
|
||||
parameter
|
||||
type:
|
||||
named_type_expr
|
||||
name: identifier "Int"
|
||||
return_type:
|
||||
named_type_expr
|
||||
name: identifier "Bool"
|
||||
return_type:
|
||||
named_type_expr
|
||||
name: identifier "Bool"
|
||||
type_alias_declaration
|
||||
name: identifier "MixedParametersAndTuples"
|
||||
type:
|
||||
function_type_expr
|
||||
parameter:
|
||||
parameter
|
||||
type:
|
||||
function_type_expr
|
||||
parameter:
|
||||
parameter
|
||||
type:
|
||||
named_type_expr
|
||||
name: identifier "Int"
|
||||
return_type:
|
||||
named_type_expr
|
||||
name: identifier "Bool"
|
||||
parameter
|
||||
type:
|
||||
named_type_expr
|
||||
name: identifier "String"
|
||||
return_type:
|
||||
tuple_type_expr
|
||||
element:
|
||||
tuple_type_element
|
||||
type:
|
||||
named_type_expr
|
||||
name: identifier "Bool"
|
||||
tuple_type_element
|
||||
type:
|
||||
named_type_expr
|
||||
name: identifier "Int"
|
||||
@@ -0,0 +1,3 @@
|
||||
typealias NestedFunction = ((Int) -> Bool) -> Bool
|
||||
|
||||
typealias MixedParametersAndTuples = ((Int) -> Bool, String) -> (Bool, Int)
|
||||
@@ -4,54 +4,72 @@ func sum(_ values: Int...) -> Int {
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
function_declaration
|
||||
body:
|
||||
block
|
||||
statement:
|
||||
control_transfer_statement
|
||||
kind: return
|
||||
result:
|
||||
call_expression
|
||||
function:
|
||||
navigation_expression
|
||||
suffix:
|
||||
navigation_suffix
|
||||
suffix: simple_identifier "reduce"
|
||||
target: simple_identifier "values"
|
||||
suffix:
|
||||
call_suffix
|
||||
arguments:
|
||||
value_arguments
|
||||
argument:
|
||||
value_argument
|
||||
value: integer_literal "0"
|
||||
value_argument
|
||||
value:
|
||||
referenceable_operator
|
||||
operator: +
|
||||
name: simple_identifier "sum"
|
||||
parameter:
|
||||
function_parameter
|
||||
parameter:
|
||||
parameter
|
||||
external_name: simple_identifier "_"
|
||||
name: simple_identifier "values"
|
||||
type:
|
||||
type
|
||||
name:
|
||||
user_type
|
||||
part:
|
||||
simple_user_type
|
||||
name: type_identifier "Int"
|
||||
return_type:
|
||||
type
|
||||
name:
|
||||
user_type
|
||||
part:
|
||||
simple_user_type
|
||||
name: type_identifier "Int"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionDecl
|
||||
attributes:
|
||||
body:
|
||||
codeBlock
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
returnStmt
|
||||
expression:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
labeledExpr
|
||||
expression:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "0"
|
||||
trailingComma: ,
|
||||
labeledExpr
|
||||
expression:
|
||||
declReferenceExpr
|
||||
baseName: binaryOperator "+"
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
memberAccessExpr
|
||||
period: .
|
||||
declName:
|
||||
declReferenceExpr
|
||||
baseName: identifier "reduce"
|
||||
base:
|
||||
declReferenceExpr
|
||||
baseName: identifier "values"
|
||||
returnKeyword: return
|
||||
name: identifier "sum"
|
||||
modifiers:
|
||||
signature:
|
||||
functionSignature
|
||||
parameterClause:
|
||||
functionParameterClause
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
parameters:
|
||||
functionParameter
|
||||
colon: :
|
||||
attributes:
|
||||
modifiers:
|
||||
type:
|
||||
identifierType
|
||||
name: identifier "Int"
|
||||
ellipsis: ...
|
||||
firstName: _
|
||||
secondName: identifier "values"
|
||||
returnClause:
|
||||
returnClause
|
||||
arrow: ->
|
||||
type:
|
||||
identifierType
|
||||
name: identifier "Int"
|
||||
funcKeyword: func
|
||||
|
||||
---
|
||||
|
||||
@@ -60,25 +78,6 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
function_declaration
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
return_expr
|
||||
value:
|
||||
call_expr
|
||||
argument:
|
||||
argument
|
||||
value: int_literal "0"
|
||||
argument
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "+"
|
||||
callee:
|
||||
member_access_expr
|
||||
base:
|
||||
name_expr
|
||||
identifier: identifier "values"
|
||||
member: identifier "reduce"
|
||||
name: identifier "sum"
|
||||
parameter:
|
||||
parameter
|
||||
@@ -89,3 +88,22 @@ top_level
|
||||
return_type:
|
||||
named_type_expr
|
||||
name: identifier "Int"
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
return_expr
|
||||
value:
|
||||
call_expr
|
||||
callee:
|
||||
member_access_expr
|
||||
base:
|
||||
name_expr
|
||||
identifier: identifier "values"
|
||||
member: identifier "reduce"
|
||||
argument:
|
||||
argument
|
||||
value: int_literal "0"
|
||||
argument
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "+"
|
||||
|
||||
@@ -3,10 +3,17 @@ false
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
boolean_literal
|
||||
boolean_literal
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
booleanLiteralExpr
|
||||
literal: true
|
||||
codeBlockItem
|
||||
item:
|
||||
booleanLiteralExpr
|
||||
literal: false
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,8 +2,13 @@
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement: real_literal "3.14"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
floatLiteralExpr
|
||||
literal: floatLiteral "3.14"
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,8 +2,13 @@
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement: integer_literal "42"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "42"
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,11 +2,16 @@
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
prefix_expression
|
||||
operation: -
|
||||
target: integer_literal "7"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
prefixOperatorExpr
|
||||
expression:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "7"
|
||||
operator: prefixOperator "-"
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,8 +2,13 @@ nil
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement: nil
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
nilLiteralExpr
|
||||
nilKeyword: nil
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,10 +2,17 @@
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
line_string_literal
|
||||
text: line_str_text "hello"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
stringLiteralExpr
|
||||
closingQuote: "
|
||||
openingQuote: "
|
||||
segments:
|
||||
stringSegment
|
||||
content: stringSegment "hello"
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,13 +2,28 @@
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
line_string_literal
|
||||
interpolation:
|
||||
interpolated_expression
|
||||
value: simple_identifier "name"
|
||||
text: line_str_text "hello "
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
stringLiteralExpr
|
||||
closingQuote: "
|
||||
openingQuote: "
|
||||
segments:
|
||||
stringSegment
|
||||
content: stringSegment "hello "
|
||||
expressionSegment
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
backslash: \
|
||||
expressions:
|
||||
labeledExpr
|
||||
expression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "name"
|
||||
stringSegment
|
||||
content: stringSegment
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -6,51 +6,95 @@ for x in xs {
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
for_statement
|
||||
body:
|
||||
block
|
||||
statement:
|
||||
if_statement
|
||||
body:
|
||||
block
|
||||
statement:
|
||||
control_transfer_statement
|
||||
kind: continue
|
||||
condition:
|
||||
if_condition
|
||||
kind:
|
||||
comparison_expression
|
||||
lhs: simple_identifier "x"
|
||||
op: <
|
||||
rhs: integer_literal "0"
|
||||
if_statement
|
||||
body:
|
||||
block
|
||||
statement:
|
||||
control_transfer_statement
|
||||
kind: break
|
||||
condition:
|
||||
if_condition
|
||||
kind:
|
||||
comparison_expression
|
||||
lhs: simple_identifier "x"
|
||||
op: >
|
||||
rhs: integer_literal "100"
|
||||
call_expression
|
||||
function: simple_identifier "print"
|
||||
suffix:
|
||||
call_suffix
|
||||
arguments:
|
||||
value_arguments
|
||||
argument:
|
||||
value_argument
|
||||
value: simple_identifier "x"
|
||||
collection: simple_identifier "xs"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
pattern
|
||||
bound_identifier: simple_identifier "x"
|
||||
forStmt
|
||||
body:
|
||||
codeBlock
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
expressionStmt
|
||||
expression:
|
||||
ifExpr
|
||||
body:
|
||||
codeBlock
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
continueStmt
|
||||
continueKeyword: continue
|
||||
conditions:
|
||||
conditionElement
|
||||
condition:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator "<"
|
||||
leftOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "x"
|
||||
rightOperand:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "0"
|
||||
ifKeyword: if
|
||||
codeBlockItem
|
||||
item:
|
||||
expressionStmt
|
||||
expression:
|
||||
ifExpr
|
||||
body:
|
||||
codeBlock
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
breakStmt
|
||||
breakKeyword: break
|
||||
conditions:
|
||||
conditionElement
|
||||
condition:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator ">"
|
||||
leftOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "x"
|
||||
rightOperand:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "100"
|
||||
ifKeyword: if
|
||||
codeBlockItem
|
||||
item:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
labeledExpr
|
||||
expression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "x"
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "print"
|
||||
pattern:
|
||||
identifierPattern
|
||||
identifier: identifier "x"
|
||||
inKeyword: in
|
||||
forKeyword: for
|
||||
sequence:
|
||||
declReferenceExpr
|
||||
baseName: identifier "xs"
|
||||
|
||||
---
|
||||
|
||||
@@ -59,16 +103,22 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
for_each_stmt
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "x"
|
||||
iterable:
|
||||
name_expr
|
||||
identifier: identifier "xs"
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
if_expr
|
||||
condition:
|
||||
binary_expr
|
||||
operator: infix_operator "<"
|
||||
left:
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
operator: infix_operator "<"
|
||||
right: int_literal "0"
|
||||
then:
|
||||
block
|
||||
@@ -76,26 +126,20 @@ top_level
|
||||
if_expr
|
||||
condition:
|
||||
binary_expr
|
||||
operator: infix_operator ">"
|
||||
left:
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
operator: infix_operator ">"
|
||||
right: int_literal "100"
|
||||
then:
|
||||
block
|
||||
stmt: break_expr "break"
|
||||
call_expr
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
argument:
|
||||
argument
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "x"
|
||||
iterable:
|
||||
name_expr
|
||||
identifier: identifier "xs"
|
||||
|
||||
@@ -4,30 +4,55 @@ for x in [1, 2, 3] {
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
for_statement
|
||||
body:
|
||||
block
|
||||
statement:
|
||||
call_expression
|
||||
function: simple_identifier "print"
|
||||
suffix:
|
||||
call_suffix
|
||||
arguments:
|
||||
value_arguments
|
||||
argument:
|
||||
value_argument
|
||||
value: simple_identifier "x"
|
||||
collection:
|
||||
array_literal
|
||||
element:
|
||||
integer_literal "1"
|
||||
integer_literal "2"
|
||||
integer_literal "3"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
pattern
|
||||
bound_identifier: simple_identifier "x"
|
||||
forStmt
|
||||
body:
|
||||
codeBlock
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
labeledExpr
|
||||
expression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "x"
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "print"
|
||||
pattern:
|
||||
identifierPattern
|
||||
identifier: identifier "x"
|
||||
inKeyword: in
|
||||
forKeyword: for
|
||||
sequence:
|
||||
arrayExpr
|
||||
elements:
|
||||
arrayElement
|
||||
expression:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "1"
|
||||
trailingComma: ,
|
||||
arrayElement
|
||||
expression:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "2"
|
||||
trailingComma: ,
|
||||
arrayElement
|
||||
expression:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "3"
|
||||
leftSquare: [
|
||||
rightSquare: ]
|
||||
|
||||
---
|
||||
|
||||
@@ -36,18 +61,6 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
for_each_stmt
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
argument:
|
||||
argument
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "x"
|
||||
@@ -57,3 +70,15 @@ top_level
|
||||
int_literal "1"
|
||||
int_literal "2"
|
||||
int_literal "3"
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
argument:
|
||||
argument
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
|
||||
@@ -4,29 +4,47 @@ for i in 0..<10 {
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
for_statement
|
||||
body:
|
||||
block
|
||||
statement:
|
||||
call_expression
|
||||
function: simple_identifier "print"
|
||||
suffix:
|
||||
call_suffix
|
||||
arguments:
|
||||
value_arguments
|
||||
argument:
|
||||
value_argument
|
||||
value: simple_identifier "i"
|
||||
collection:
|
||||
range_expression
|
||||
end: integer_literal "10"
|
||||
op: ..<
|
||||
start: integer_literal "0"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
pattern
|
||||
bound_identifier: simple_identifier "i"
|
||||
forStmt
|
||||
body:
|
||||
codeBlock
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
labeledExpr
|
||||
expression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "i"
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "print"
|
||||
pattern:
|
||||
identifierPattern
|
||||
identifier: identifier "i"
|
||||
inKeyword: in
|
||||
forKeyword: for
|
||||
sequence:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator "..<"
|
||||
leftOperand:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "0"
|
||||
rightOperand:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "10"
|
||||
|
||||
---
|
||||
|
||||
@@ -35,23 +53,23 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
for_each_stmt
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
argument:
|
||||
argument
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "i"
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "i"
|
||||
iterable:
|
||||
binary_expr
|
||||
operator: infix_operator "..<"
|
||||
left: int_literal "0"
|
||||
operator: infix_operator "..<"
|
||||
right: int_literal "10"
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
argument:
|
||||
argument
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "i"
|
||||
|
||||
@@ -4,33 +4,53 @@ for x in xs where x > 0 {
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
for_statement
|
||||
body:
|
||||
block
|
||||
statement:
|
||||
call_expression
|
||||
function: simple_identifier "print"
|
||||
suffix:
|
||||
call_suffix
|
||||
arguments:
|
||||
value_arguments
|
||||
argument:
|
||||
value_argument
|
||||
value: simple_identifier "x"
|
||||
collection: simple_identifier "xs"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
pattern
|
||||
bound_identifier: simple_identifier "x"
|
||||
where:
|
||||
where_clause
|
||||
expr:
|
||||
comparison_expression
|
||||
lhs: simple_identifier "x"
|
||||
op: >
|
||||
rhs: integer_literal "0"
|
||||
keyword: where_keyword "where"
|
||||
forStmt
|
||||
body:
|
||||
codeBlock
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
labeledExpr
|
||||
expression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "x"
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "print"
|
||||
pattern:
|
||||
identifierPattern
|
||||
identifier: identifier "x"
|
||||
whereClause:
|
||||
whereClause
|
||||
condition:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator ">"
|
||||
leftOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "x"
|
||||
rightOperand:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "0"
|
||||
whereKeyword: where
|
||||
inKeyword: in
|
||||
forKeyword: for
|
||||
sequence:
|
||||
declReferenceExpr
|
||||
baseName: identifier "xs"
|
||||
|
||||
---
|
||||
|
||||
@@ -39,28 +59,28 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
for_each_stmt
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "x"
|
||||
iterable:
|
||||
name_expr
|
||||
identifier: identifier "xs"
|
||||
guard:
|
||||
binary_expr
|
||||
left:
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
operator: infix_operator ">"
|
||||
right: int_literal "0"
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
argument:
|
||||
argument
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
pattern:
|
||||
name_pattern
|
||||
identifier: identifier "x"
|
||||
guard:
|
||||
binary_expr
|
||||
operator: infix_operator ">"
|
||||
left:
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
right: int_literal "0"
|
||||
iterable:
|
||||
name_expr
|
||||
identifier: identifier "xs"
|
||||
|
||||
@@ -4,25 +4,42 @@ repeat {
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
repeat_while_statement
|
||||
body:
|
||||
block
|
||||
statement:
|
||||
assignment
|
||||
operator: -=
|
||||
result: integer_literal "1"
|
||||
target:
|
||||
directly_assignable_expression
|
||||
expr: simple_identifier "x"
|
||||
condition:
|
||||
if_condition
|
||||
kind:
|
||||
comparison_expression
|
||||
lhs: simple_identifier "x"
|
||||
op: >
|
||||
rhs: integer_literal "0"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
repeatStmt
|
||||
body:
|
||||
codeBlock
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator "-="
|
||||
leftOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "x"
|
||||
rightOperand:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "1"
|
||||
condition:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator ">"
|
||||
leftOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "x"
|
||||
rightOperand:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "0"
|
||||
repeatKeyword: repeat
|
||||
whileKeyword: while
|
||||
|
||||
---
|
||||
|
||||
@@ -35,15 +52,15 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
compound_assign_expr
|
||||
operator: infix_operator "-="
|
||||
target:
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
operator: infix_operator "-="
|
||||
value: int_literal "1"
|
||||
condition:
|
||||
binary_expr
|
||||
operator: infix_operator ">"
|
||||
left:
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
operator: infix_operator ">"
|
||||
right: int_literal "0"
|
||||
|
||||
@@ -4,25 +4,43 @@ while x > 0 {
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
while_statement
|
||||
body:
|
||||
block
|
||||
statement:
|
||||
assignment
|
||||
operator: -=
|
||||
result: integer_literal "1"
|
||||
target:
|
||||
directly_assignable_expression
|
||||
expr: simple_identifier "x"
|
||||
condition:
|
||||
if_condition
|
||||
kind:
|
||||
comparison_expression
|
||||
lhs: simple_identifier "x"
|
||||
op: >
|
||||
rhs: integer_literal "0"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
whileStmt
|
||||
body:
|
||||
codeBlock
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator "-="
|
||||
leftOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "x"
|
||||
rightOperand:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "1"
|
||||
conditions:
|
||||
conditionElement
|
||||
condition:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator ">"
|
||||
leftOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "x"
|
||||
rightOperand:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "0"
|
||||
whileKeyword: while
|
||||
|
||||
---
|
||||
|
||||
@@ -31,19 +49,19 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
while_stmt
|
||||
condition:
|
||||
binary_expr
|
||||
left:
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
operator: infix_operator ">"
|
||||
right: int_literal "0"
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
compound_assign_expr
|
||||
operator: infix_operator "-="
|
||||
target:
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
operator: infix_operator "-="
|
||||
value: int_literal "1"
|
||||
condition:
|
||||
binary_expr
|
||||
operator: infix_operator ">"
|
||||
left:
|
||||
name_expr
|
||||
identifier: identifier "x"
|
||||
right: int_literal "0"
|
||||
|
||||
@@ -2,12 +2,21 @@ a + b
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
additive_expression
|
||||
lhs: simple_identifier "a"
|
||||
op: +
|
||||
rhs: simple_identifier "b"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator "+"
|
||||
leftOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "a"
|
||||
rightOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "b"
|
||||
|
||||
---
|
||||
|
||||
@@ -16,10 +25,10 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
binary_expr
|
||||
operator: infix_operator "+"
|
||||
left:
|
||||
name_expr
|
||||
identifier: identifier "a"
|
||||
operator: infix_operator "+"
|
||||
right:
|
||||
name_expr
|
||||
identifier: identifier "b"
|
||||
|
||||
@@ -2,12 +2,21 @@ a < b
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
comparison_expression
|
||||
lhs: simple_identifier "a"
|
||||
op: <
|
||||
rhs: simple_identifier "b"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator "<"
|
||||
leftOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "a"
|
||||
rightOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "b"
|
||||
|
||||
---
|
||||
|
||||
@@ -16,10 +25,10 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
binary_expr
|
||||
operator: infix_operator "<"
|
||||
left:
|
||||
name_expr
|
||||
identifier: identifier "a"
|
||||
operator: infix_operator "<"
|
||||
right:
|
||||
name_expr
|
||||
identifier: identifier "b"
|
||||
|
||||
@@ -2,12 +2,21 @@ a / b
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
multiplicative_expression
|
||||
lhs: simple_identifier "a"
|
||||
op: /
|
||||
rhs: simple_identifier "b"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator "/"
|
||||
leftOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "a"
|
||||
rightOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "b"
|
||||
|
||||
---
|
||||
|
||||
@@ -16,10 +25,10 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
binary_expr
|
||||
operator: infix_operator "/"
|
||||
left:
|
||||
name_expr
|
||||
identifier: identifier "a"
|
||||
operator: infix_operator "/"
|
||||
right:
|
||||
name_expr
|
||||
identifier: identifier "b"
|
||||
|
||||
@@ -2,12 +2,21 @@ a == b
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
equality_expression
|
||||
lhs: simple_identifier "a"
|
||||
op: ==
|
||||
rhs: simple_identifier "b"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator "=="
|
||||
leftOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "a"
|
||||
rightOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "b"
|
||||
|
||||
---
|
||||
|
||||
@@ -16,10 +25,10 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
binary_expr
|
||||
operator: infix_operator "=="
|
||||
left:
|
||||
name_expr
|
||||
identifier: identifier "a"
|
||||
operator: infix_operator "=="
|
||||
right:
|
||||
name_expr
|
||||
identifier: identifier "b"
|
||||
|
||||
@@ -2,12 +2,21 @@ a && b
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
conjunction_expression
|
||||
lhs: simple_identifier "a"
|
||||
op: &&
|
||||
rhs: simple_identifier "b"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator "&&"
|
||||
leftOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "a"
|
||||
rightOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "b"
|
||||
|
||||
---
|
||||
|
||||
@@ -16,10 +25,10 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
binary_expr
|
||||
operator: infix_operator "&&"
|
||||
left:
|
||||
name_expr
|
||||
identifier: identifier "a"
|
||||
operator: infix_operator "&&"
|
||||
right:
|
||||
name_expr
|
||||
identifier: identifier "b"
|
||||
|
||||
@@ -2,11 +2,16 @@
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
prefix_expression
|
||||
operation: bang "!"
|
||||
target: simple_identifier "a"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
prefixOperatorExpr
|
||||
expression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "a"
|
||||
operator: prefixOperator "!"
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,12 +2,21 @@ a || b
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
disjunction_expression
|
||||
lhs: simple_identifier "a"
|
||||
op: ||
|
||||
rhs: simple_identifier "b"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator "||"
|
||||
leftOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "a"
|
||||
rightOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "b"
|
||||
|
||||
---
|
||||
|
||||
@@ -16,10 +25,10 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
binary_expr
|
||||
operator: infix_operator "||"
|
||||
left:
|
||||
name_expr
|
||||
identifier: identifier "a"
|
||||
operator: infix_operator "||"
|
||||
right:
|
||||
name_expr
|
||||
identifier: identifier "b"
|
||||
|
||||
@@ -2,12 +2,21 @@ a * b
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
multiplicative_expression
|
||||
lhs: simple_identifier "a"
|
||||
op: *
|
||||
rhs: simple_identifier "b"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator "*"
|
||||
leftOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "a"
|
||||
rightOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "b"
|
||||
|
||||
---
|
||||
|
||||
@@ -16,10 +25,10 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
binary_expr
|
||||
operator: infix_operator "*"
|
||||
left:
|
||||
name_expr
|
||||
identifier: identifier "a"
|
||||
operator: infix_operator "*"
|
||||
right:
|
||||
name_expr
|
||||
identifier: identifier "b"
|
||||
|
||||
@@ -2,16 +2,29 @@ a + b * c
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
additive_expression
|
||||
lhs: simple_identifier "a"
|
||||
op: +
|
||||
rhs:
|
||||
multiplicative_expression
|
||||
lhs: simple_identifier "b"
|
||||
op: *
|
||||
rhs: simple_identifier "c"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator "+"
|
||||
leftOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "a"
|
||||
rightOperand:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator "*"
|
||||
leftOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "b"
|
||||
rightOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "c"
|
||||
|
||||
---
|
||||
|
||||
@@ -20,16 +33,16 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
binary_expr
|
||||
operator: infix_operator "+"
|
||||
left:
|
||||
name_expr
|
||||
identifier: identifier "a"
|
||||
operator: infix_operator "+"
|
||||
right:
|
||||
binary_expr
|
||||
operator: infix_operator "*"
|
||||
left:
|
||||
name_expr
|
||||
identifier: identifier "b"
|
||||
operator: infix_operator "*"
|
||||
right:
|
||||
name_expr
|
||||
identifier: identifier "c"
|
||||
|
||||
@@ -2,20 +2,35 @@
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
multiplicative_expression
|
||||
lhs:
|
||||
tuple_expression
|
||||
element:
|
||||
tuple_expression_item
|
||||
value:
|
||||
additive_expression
|
||||
lhs: simple_identifier "a"
|
||||
op: +
|
||||
rhs: simple_identifier "b"
|
||||
op: *
|
||||
rhs: simple_identifier "c"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator "*"
|
||||
leftOperand:
|
||||
tupleExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
elements:
|
||||
labeledExpr
|
||||
expression:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator "+"
|
||||
leftOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "a"
|
||||
rightOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "b"
|
||||
rightOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "c"
|
||||
|
||||
---
|
||||
|
||||
@@ -24,8 +39,8 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
binary_expr
|
||||
operator: infix_operator "*"
|
||||
left: tuple_expr "(a + b)"
|
||||
operator: infix_operator "*"
|
||||
right:
|
||||
name_expr
|
||||
identifier: identifier "c"
|
||||
|
||||
@@ -2,12 +2,21 @@
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
range_expression
|
||||
end: integer_literal "10"
|
||||
op: ...
|
||||
start: integer_literal "1"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator "..."
|
||||
leftOperand:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "1"
|
||||
rightOperand:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "10"
|
||||
|
||||
---
|
||||
|
||||
@@ -16,6 +25,6 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
binary_expr
|
||||
operator: infix_operator "..."
|
||||
left: int_literal "1"
|
||||
operator: infix_operator "..."
|
||||
right: int_literal "10"
|
||||
|
||||
@@ -2,12 +2,21 @@ a - b
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
additive_expression
|
||||
lhs: simple_identifier "a"
|
||||
op: -
|
||||
rhs: simple_identifier "b"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator "-"
|
||||
leftOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "a"
|
||||
rightOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "b"
|
||||
|
||||
---
|
||||
|
||||
@@ -16,10 +25,10 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
binary_expr
|
||||
operator: infix_operator "-"
|
||||
left:
|
||||
name_expr
|
||||
identifier: identifier "a"
|
||||
operator: infix_operator "-"
|
||||
right:
|
||||
name_expr
|
||||
identifier: identifier "b"
|
||||
|
||||
@@ -6,37 +6,54 @@ do {
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
do_statement
|
||||
body:
|
||||
block
|
||||
statement:
|
||||
try_expression
|
||||
expr:
|
||||
call_expression
|
||||
function: simple_identifier "foo"
|
||||
suffix:
|
||||
call_suffix
|
||||
arguments:
|
||||
value_arguments
|
||||
operator:
|
||||
try_operator
|
||||
catch:
|
||||
catch_block
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
doStmt
|
||||
body:
|
||||
block
|
||||
statement:
|
||||
call_expression
|
||||
function: simple_identifier "print"
|
||||
suffix:
|
||||
call_suffix
|
||||
arguments:
|
||||
value_arguments
|
||||
argument:
|
||||
value_argument
|
||||
value: simple_identifier "error"
|
||||
keyword: catch_keyword "catch"
|
||||
codeBlock
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
tryExpr
|
||||
expression:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "foo"
|
||||
tryKeyword: try
|
||||
catchClauses:
|
||||
catchClause
|
||||
body:
|
||||
codeBlock
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
labeledExpr
|
||||
expression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "error"
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "print"
|
||||
catchItems:
|
||||
catchKeyword: catch
|
||||
doKeyword: do
|
||||
|
||||
---
|
||||
|
||||
@@ -61,11 +78,11 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
call_expr
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
argument:
|
||||
argument
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "error"
|
||||
callee:
|
||||
name_expr
|
||||
identifier: identifier "print"
|
||||
|
||||
@@ -2,21 +2,29 @@ let n = opt!
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
property_declaration
|
||||
binding:
|
||||
value_binding_pattern
|
||||
mutability: let
|
||||
declarator:
|
||||
property_binding
|
||||
name:
|
||||
pattern
|
||||
bound_identifier: simple_identifier "n"
|
||||
value:
|
||||
postfix_expression
|
||||
operation: bang "!"
|
||||
target: simple_identifier "opt"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
variableDecl
|
||||
attributes:
|
||||
modifiers:
|
||||
bindingSpecifier: let
|
||||
bindings:
|
||||
patternBinding
|
||||
initializer:
|
||||
initializerClause
|
||||
equal: =
|
||||
value:
|
||||
forceUnwrapExpr
|
||||
expression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "opt"
|
||||
exclamationMark: !
|
||||
pattern:
|
||||
identifierPattern
|
||||
identifier: identifier "n"
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,21 +2,34 @@ let n = opt ?? 0
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
property_declaration
|
||||
binding:
|
||||
value_binding_pattern
|
||||
mutability: let
|
||||
declarator:
|
||||
property_binding
|
||||
name:
|
||||
pattern
|
||||
bound_identifier: simple_identifier "n"
|
||||
value:
|
||||
nil_coalescing_expression
|
||||
if_nil: integer_literal "0"
|
||||
value: simple_identifier "opt"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
variableDecl
|
||||
attributes:
|
||||
modifiers:
|
||||
bindingSpecifier: let
|
||||
bindings:
|
||||
patternBinding
|
||||
initializer:
|
||||
initializerClause
|
||||
equal: =
|
||||
value:
|
||||
infixOperatorExpr
|
||||
operator:
|
||||
binaryOperatorExpr
|
||||
operator: binaryOperator "??"
|
||||
leftOperand:
|
||||
declReferenceExpr
|
||||
baseName: identifier "opt"
|
||||
rightOperand:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "0"
|
||||
pattern:
|
||||
identifierPattern
|
||||
identifier: identifier "n"
|
||||
|
||||
---
|
||||
|
||||
@@ -31,8 +44,8 @@ top_level
|
||||
identifier: identifier "n"
|
||||
value:
|
||||
binary_expr
|
||||
operator: infix_operator "??"
|
||||
left:
|
||||
name_expr
|
||||
identifier: identifier "opt"
|
||||
operator: infix_operator "??"
|
||||
right: int_literal "0"
|
||||
|
||||
@@ -2,32 +2,44 @@ let n = obj?.foo?.bar
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
property_declaration
|
||||
binding:
|
||||
value_binding_pattern
|
||||
mutability: let
|
||||
declarator:
|
||||
property_binding
|
||||
name:
|
||||
pattern
|
||||
bound_identifier: simple_identifier "n"
|
||||
value:
|
||||
navigation_expression
|
||||
suffix:
|
||||
navigation_suffix
|
||||
suffix: simple_identifier "bar"
|
||||
target:
|
||||
optional_chain_marker
|
||||
expr:
|
||||
navigation_expression
|
||||
suffix:
|
||||
navigation_suffix
|
||||
suffix: simple_identifier "foo"
|
||||
target:
|
||||
optional_chain_marker
|
||||
expr: simple_identifier "obj"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
variableDecl
|
||||
attributes:
|
||||
modifiers:
|
||||
bindingSpecifier: let
|
||||
bindings:
|
||||
patternBinding
|
||||
initializer:
|
||||
initializerClause
|
||||
equal: =
|
||||
value:
|
||||
memberAccessExpr
|
||||
period: .
|
||||
declName:
|
||||
declReferenceExpr
|
||||
baseName: identifier "bar"
|
||||
base:
|
||||
optionalChainingExpr
|
||||
expression:
|
||||
memberAccessExpr
|
||||
period: .
|
||||
declName:
|
||||
declReferenceExpr
|
||||
baseName: identifier "foo"
|
||||
base:
|
||||
optionalChainingExpr
|
||||
expression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "obj"
|
||||
questionMark: ?
|
||||
questionMark: ?
|
||||
pattern:
|
||||
identifierPattern
|
||||
identifier: identifier "n"
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,29 +2,35 @@ let x: Int? = nil
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
property_declaration
|
||||
binding:
|
||||
value_binding_pattern
|
||||
mutability: let
|
||||
declarator:
|
||||
property_binding
|
||||
name:
|
||||
pattern
|
||||
bound_identifier: simple_identifier "x"
|
||||
type:
|
||||
type_annotation
|
||||
type:
|
||||
type
|
||||
name:
|
||||
optional_type
|
||||
wrapped:
|
||||
user_type
|
||||
part:
|
||||
simple_user_type
|
||||
name: type_identifier "Int"
|
||||
value: nil
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
variableDecl
|
||||
attributes:
|
||||
modifiers:
|
||||
bindingSpecifier: let
|
||||
bindings:
|
||||
patternBinding
|
||||
initializer:
|
||||
initializerClause
|
||||
equal: =
|
||||
value:
|
||||
nilLiteralExpr
|
||||
nilKeyword: nil
|
||||
pattern:
|
||||
identifierPattern
|
||||
identifier: identifier "x"
|
||||
typeAnnotation:
|
||||
typeAnnotation
|
||||
colon: :
|
||||
type:
|
||||
optionalType
|
||||
wrappedType:
|
||||
identifierType
|
||||
name: identifier "Int"
|
||||
questionMark: ?
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -4,25 +4,50 @@ func read() throws -> String {
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
function_declaration
|
||||
body:
|
||||
block
|
||||
statement:
|
||||
control_transfer_statement
|
||||
kind: return
|
||||
result:
|
||||
line_string_literal
|
||||
name: simple_identifier "read"
|
||||
return_type:
|
||||
type
|
||||
name:
|
||||
user_type
|
||||
part:
|
||||
simple_user_type
|
||||
name: type_identifier "String"
|
||||
throws: throws "throws"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
functionDecl
|
||||
attributes:
|
||||
body:
|
||||
codeBlock
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
returnStmt
|
||||
expression:
|
||||
stringLiteralExpr
|
||||
closingQuote: "
|
||||
openingQuote: "
|
||||
segments:
|
||||
stringSegment
|
||||
content: stringSegment
|
||||
returnKeyword: return
|
||||
name: identifier "read"
|
||||
modifiers:
|
||||
signature:
|
||||
functionSignature
|
||||
effectSpecifiers:
|
||||
functionEffectSpecifiers
|
||||
throwsClause:
|
||||
throwsClause
|
||||
throwsSpecifier: throws
|
||||
parameterClause:
|
||||
functionParameterClause
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
parameters:
|
||||
returnClause:
|
||||
returnClause
|
||||
arrow: ->
|
||||
type:
|
||||
identifierType
|
||||
name: identifier "String"
|
||||
funcKeyword: func
|
||||
|
||||
---
|
||||
|
||||
@@ -31,12 +56,12 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
function_declaration
|
||||
name: identifier "read"
|
||||
return_type:
|
||||
named_type_expr
|
||||
name: identifier "String"
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
return_expr
|
||||
value: string_literal "\"\""
|
||||
name: identifier "read"
|
||||
return_type:
|
||||
named_type_expr
|
||||
name: identifier "String"
|
||||
|
||||
@@ -2,28 +2,36 @@ let result = try! foo()
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
property_declaration
|
||||
binding:
|
||||
value_binding_pattern
|
||||
mutability: let
|
||||
declarator:
|
||||
property_binding
|
||||
name:
|
||||
pattern
|
||||
bound_identifier: simple_identifier "result"
|
||||
value:
|
||||
try_expression
|
||||
expr:
|
||||
call_expression
|
||||
function: simple_identifier "foo"
|
||||
suffix:
|
||||
call_suffix
|
||||
arguments:
|
||||
value_arguments
|
||||
operator:
|
||||
try_operator
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
variableDecl
|
||||
attributes:
|
||||
modifiers:
|
||||
bindingSpecifier: let
|
||||
bindings:
|
||||
patternBinding
|
||||
initializer:
|
||||
initializerClause
|
||||
equal: =
|
||||
value:
|
||||
tryExpr
|
||||
expression:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "foo"
|
||||
questionOrExclamationMark: !
|
||||
tryKeyword: try
|
||||
pattern:
|
||||
identifierPattern
|
||||
identifier: identifier "result"
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,28 +2,36 @@ let result = try? foo()
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
property_declaration
|
||||
binding:
|
||||
value_binding_pattern
|
||||
mutability: let
|
||||
declarator:
|
||||
property_binding
|
||||
name:
|
||||
pattern
|
||||
bound_identifier: simple_identifier "result"
|
||||
value:
|
||||
try_expression
|
||||
expr:
|
||||
call_expression
|
||||
function: simple_identifier "foo"
|
||||
suffix:
|
||||
call_suffix
|
||||
arguments:
|
||||
value_arguments
|
||||
operator:
|
||||
try_operator
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
variableDecl
|
||||
attributes:
|
||||
modifiers:
|
||||
bindingSpecifier: let
|
||||
bindings:
|
||||
patternBinding
|
||||
initializer:
|
||||
initializerClause
|
||||
equal: =
|
||||
value:
|
||||
tryExpr
|
||||
expression:
|
||||
functionCallExpr
|
||||
leftParen: (
|
||||
rightParen: )
|
||||
arguments:
|
||||
additionalTrailingClosures:
|
||||
calledExpression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "foo"
|
||||
questionOrExclamationMark: ?
|
||||
tryKeyword: try
|
||||
pattern:
|
||||
identifierPattern
|
||||
identifier: identifier "result"
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -11,54 +11,84 @@ var p: Int {
|
||||
|
||||
---
|
||||
|
||||
source_file
|
||||
statement:
|
||||
property_declaration
|
||||
binding:
|
||||
value_binding_pattern
|
||||
mutability: var
|
||||
declarator:
|
||||
property_binding
|
||||
computed_value:
|
||||
computed_property
|
||||
accessor:
|
||||
computed_getter
|
||||
body:
|
||||
block
|
||||
statement:
|
||||
switch_statement
|
||||
entry:
|
||||
switch_entry
|
||||
pattern:
|
||||
switch_pattern
|
||||
pattern:
|
||||
pattern
|
||||
kind: simple_identifier "someConstant"
|
||||
statement:
|
||||
control_transfer_statement
|
||||
kind: return
|
||||
result: integer_literal "1"
|
||||
switch_entry
|
||||
default: default_keyword "default"
|
||||
statement:
|
||||
control_transfer_statement
|
||||
kind: return
|
||||
result: integer_literal "2"
|
||||
expr: simple_identifier "y"
|
||||
specifier:
|
||||
getter_specifier
|
||||
name:
|
||||
pattern
|
||||
bound_identifier: simple_identifier "p"
|
||||
type:
|
||||
type_annotation
|
||||
type:
|
||||
type
|
||||
name:
|
||||
user_type
|
||||
part:
|
||||
simple_user_type
|
||||
name: type_identifier "Int"
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
variableDecl
|
||||
attributes:
|
||||
modifiers:
|
||||
bindingSpecifier: var
|
||||
bindings:
|
||||
patternBinding
|
||||
pattern:
|
||||
identifierPattern
|
||||
identifier: identifier "p"
|
||||
typeAnnotation:
|
||||
typeAnnotation
|
||||
colon: :
|
||||
type:
|
||||
identifierType
|
||||
name: identifier "Int"
|
||||
accessorBlock:
|
||||
accessorBlock
|
||||
accessors:
|
||||
accessorDecl
|
||||
accessorSpecifier: get
|
||||
attributes:
|
||||
body:
|
||||
codeBlock
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
expressionStmt
|
||||
expression:
|
||||
switchExpr
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
cases:
|
||||
switchCase
|
||||
label:
|
||||
switchCaseLabel
|
||||
colon: :
|
||||
caseKeyword: case
|
||||
caseItems:
|
||||
switchCaseItem
|
||||
pattern:
|
||||
expressionPattern
|
||||
expression:
|
||||
declReferenceExpr
|
||||
baseName: identifier "someConstant"
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
returnStmt
|
||||
expression:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "1"
|
||||
returnKeyword: return
|
||||
switchCase
|
||||
label:
|
||||
switchDefaultLabel
|
||||
colon: :
|
||||
defaultKeyword: default
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
returnStmt
|
||||
expression:
|
||||
integerLiteralExpr
|
||||
literal: integerLiteral "2"
|
||||
returnKeyword: return
|
||||
subject:
|
||||
declReferenceExpr
|
||||
baseName: identifier "y"
|
||||
switchKeyword: switch
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
|
||||
---
|
||||
|
||||
@@ -67,34 +97,34 @@ top_level
|
||||
block
|
||||
stmt:
|
||||
accessor_declaration
|
||||
modifier: modifier "var"
|
||||
name: identifier "p"
|
||||
accessor_kind: accessor_kind "get"
|
||||
type:
|
||||
named_type_expr
|
||||
name: identifier "Int"
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
switch_expr
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "y"
|
||||
case:
|
||||
switch_case
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
return_expr
|
||||
value: int_literal "1"
|
||||
pattern:
|
||||
expr_equality_pattern
|
||||
expr:
|
||||
name_expr
|
||||
identifier: identifier "someConstant"
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
return_expr
|
||||
value: int_literal "1"
|
||||
switch_case
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
return_expr
|
||||
value: int_literal "2"
|
||||
value:
|
||||
name_expr
|
||||
identifier: identifier "y"
|
||||
modifier: modifier "var"
|
||||
name: identifier "p"
|
||||
type:
|
||||
named_type_expr
|
||||
name: identifier "Int"
|
||||
accessor_kind: accessor_kind "get"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user