pub const STACK_GRAPHS_TSG_SOURCE: &str = ";; -*- coding: utf-8 -*-\n;; ------------------------------------------------------------------------------------------------\n;; Copyright \u{a9} 2023, stack-graphs authors.\n;; Licensed under either of Apache License, Version 2.0, or MIT license, at your option.\n;; Please see the LICENSE-APACHE or LICENSE-MIT files in this distribution for license details.\n;; ------------------------------------------------------------------------------------------------\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;; Stack graphs definition for Python\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n;; Global Variables\n;; ^^^^^^^^^^^^^^^^\n\nglobal FILE_PATH\nglobal ROOT_PATH = \"\"\nglobal ROOT_NODE\nglobal JUMP_TO_SCOPE_NODE\n\n;; Attribute Shorthands\n;; ^^^^^^^^^^^^^^^^^^^^\n\nattribute node_definition = node => type = \"pop_symbol\", node_symbol = node, is_definition\nattribute node_reference = node => type = \"push_symbol\", node_symbol = node, is_reference\nattribute pop_node = node => type = \"pop_symbol\", node_symbol = node\nattribute pop_scoped_node = node => type = \"pop_scoped_symbol\", node_symbol = node\nattribute pop_scoped_symbol = symbol => type = \"pop_scoped_symbol\", symbol = symbol\nattribute pop_symbol = symbol => type = \"pop_symbol\", symbol = symbol\nattribute push_node = node => type = \"push_symbol\", node_symbol = node\nattribute push_scoped_node = node => type = \"push_scoped_symbol\", node_symbol = node\nattribute push_scoped_symbol = symbol => type = \"push_scoped_symbol\", symbol = symbol\nattribute push_symbol = symbol => type = \"push_symbol\", symbol = symbol\nattribute scoped_node_definition = node => type = \"pop_scoped_symbol\", node_symbol = node, is_definition\nattribute scoped_node_reference = node => type = \"push_scoped_symbol\", node_symbol = node, is_reference\nattribute symbol_definition = symbol => type = \"pop_symbol\", symbol = symbol, is_definition\nattribute symbol_reference = symbol => type = \"push_symbol\", symbol = symbol, is_reference\n\nattribute node_symbol = node => symbol = (source-text node), source_node = node\n\n;; Nodes\n;; ^^^^^\n\n(module) @node {\n node @node.after_scope\n node @node.before_scope\n}\n\n[\n ; _statement\n ; _simple_statement\n (future_import_statement)\n (import_statement)\n (import_from_statement)\n (print_statement)\n (assert_statement)\n (expression_statement)\n (return_statement)\n (delete_statement)\n (raise_statement)\n (pass_statement)\n (break_statement)\n (continue_statement)\n (global_statement)\n (nonlocal_statement)\n (exec_statement)\n (type_alias_statement)\n ; _compound_statement\n (if_statement)\n (for_statement)\n (while_statement)\n (try_statement)\n (with_statement)\n (function_definition)\n (class_definition)\n (decorated_definition)\n (match_statement)\n ; block\n (block)\n ; statement clauses\n (if_clause)\n (elif_clause)\n (else_clause)\n (except_group_clause)\n (except_clause)\n (finally_clause)\n (with_clause)\n (case_clause)\n] @node {\n node @node.after_scope\n node @node.before_scope\n}\n\n[\n (parameters)\n (lambda_parameters)\n] @node {\n node @node.after_scope\n node @node.before_scope\n}\n\n[\n (identifier)\n] @node {\n node @node.def\n node @node.def_dot\n node @node.ref\n node @node.ref_dot\n}\n\n[\n (dotted_name)\n (aliased_import)\n (relative_import)\n (wildcard_import)\n (import_prefix)\n] @node {\n node @node.after_scope\n node @node.before_scope\n node @node.def\n node @node.ref\n}\n\n[\n ; expressions\n (comparison_operator)\n (not_operator)\n (boolean_operator)\n (lambda)\n ;(primary_expression) ; unfolded below\n (conditional_expression)\n (named_expression)\n (as_pattern)\n ; primary_expression\n (await)\n (binary_operator)\n (identifier)\n ;(keyword_identifier) ; invalid query pattern?\n (string)\n (concatenated_string)\n (integer)\n (float)\n (true)\n (false)\n (none)\n (unary_operator)\n (attribute)\n (subscript)\n (call)\n (list)\n (list_comprehension)\n (dictionary)\n (dictionary_comprehension)\n (set)\n (set_comprehension)\n (tuple)\n (pair)\n (parenthesized_expression)\n (generator_expression)\n (ellipsis)\n (list_splat)\n\n ; expression list\n (expression_list)\n\n ; pattern\n (pattern/identifier)\n ;(keyword_identifier) ; invalid query pattern?\n ;(subscript)\n ;(attribute)\n (list_splat_pattern)\n (tuple_pattern)\n (list_pattern)\n ; _simple_patterns\n (class_pattern)\n (splat_pattern)\n (union_pattern)\n ;(list_pattern) ; already in pattern\n ;(tuple_pattern) ; already in pattern\n (dict_pattern)\n ;(string) ; already in primary_expression\n ;(concatenated_string) ; already in primary_expression\n ;(true) ; already in primary_expression\n ;(false) ; already in primary_expression\n ;(none) ; already in primary_expression\n ;(integer) ; already in primary_expression\n ;(float) ; already in primary_expression\n (complex_pattern)\n (dotted_name)\n ; _as_attern\n (as_pattern)\n ; keyword pattern\n (keyword_pattern)\n ; case pattern\n (case_pattern)\n ; with item\n (with_item)\n\n ; pattern list\n (pattern_list)\n\n ; parameter\n ;(identifier) ; already in expressions\n (typed_parameter)\n (default_parameter)\n (typed_default_parameter)\n ;(list_splat_pattern) ; already in patterns\n ;(tuple_pattern) ; already in patterns\n (keyword_separator)\n (positional_separator)\n (dictionary_splat_pattern)\n\n ; parameters\n (parameters)\n] @node {\n node @node.input\n node @node.new_bindings\n node @node.output\n}\n\n(comment) @node {\n node @node.after_scope\n node @node.before_scope\n node @node.def\n node @node.def_dot\n node @node.input\n node @node.new_bindings\n node @node.output\n node @node.ref\n node @node.ref_dot\n}\n\n;; Inherited Variables\n;; ^^^^^^^^^^^^^^^^^^^\n\ninherit .bottom\ninherit .class_member_attr_scope\ninherit .class_parent_scope\ninherit .class_self_scope\ninherit .class_super_scope\ninherit .function_returns\ninherit .global\ninherit .global_dot\ninherit .grandparent_module\ninherit .local_scope\ninherit .parent_module\n\n;;\n;; # #\n;; ## ## #### ##### # # # ###### ####\n;; # # # # # # # # # # # # #\n;; # # # # # # # # # # ##### ####\n;; # # # # # # # # # # #\n;; # # # # # # # # # # # #\n;; # # #### ##### #### ###### ###### ####\n;;\n;; Modules\n\n(module) @mod\n{\n node mod_file_def\n node mod_file_ref\n\n var module_def = mod_file_def\n\n node parent_module_def_node\n var parent_module_def = parent_module_def_node\n\n var module_ref = mod_file_ref\n\n node parent_module_ref_node\n var parent_module_ref = parent_module_ref_node\n\n node grandparent_module_ref_node\n var grandparent_module_ref = grandparent_module_ref_node\n\n ; get the file path relative to the root path\n let rel_path = (replace FILE_PATH ROOT_PATH \"\")\n scan rel_path {\n \"([^/]+)/\"\n {\n node def_dot\n attr (def_dot) pop_symbol = \".\"\n node next_def\n ;\n edge module_def -> def_dot\n edge def_dot -> next_def\n ;\n attr (module_def) pop_symbol = $1\n ;\n set parent_module_def = module_def\n set module_def = next_def\n\n node ref_dot\n attr (ref_dot) push_symbol = \".\"\n node next_ref\n ;\n edge next_ref -> ref_dot\n edge ref_dot -> module_ref\n ;\n attr (module_ref) push_symbol = $1\n ;\n set grandparent_module_ref = parent_module_ref\n set parent_module_ref = module_ref\n set module_ref = next_ref\n }\n\n \"__init__\\.py$\"\n {\n attr (parent_module_def) is_definition, source_node = @mod, empty_source_span\n }\n\n \"([^/]+)\\.py$\"\n {\n node def_dot\n attr (def_dot) pop_symbol = \".\"\n node next_def\n ;\n edge module_def -> def_dot\n edge def_dot -> next_def\n ;\n attr (module_def) pop_symbol = $1, is_definition, source_node = @mod, empty_source_span\n ;\n set module_def = next_def\n }\n }\n\n edge ROOT_NODE -> mod_file_def\n edge mod_file_ref -> ROOT_NODE\n edge module_def -> @mod.after_scope\n\n node global\n node global_dot\n\n edge @mod.before_scope -> global_dot\n edge global -> ROOT_NODE\n attr (global) push_symbol = \"<builtins>\"\n\n edge global_dot -> global\n attr (global_dot) push_symbol = \".\"\n\n let @mod.parent_module = parent_module_ref\n let @mod.grandparent_module = grandparent_module_ref\n let @mod.bottom = @mod.after_scope\n let @mod.global = global\n let @mod.global_dot = global_dot\n\n ;; add a dummy nodes for inherited variables\n node @mod.class_member_attr_scope\n node @mod.class_parent_scope\n node @mod.class_self_scope\n node @mod.class_super_scope\n node @mod.function_returns\n node @mod.local_scope\n}\n\n;;\n;; ###\n;; # # # ##### #### ##### ##### ####\n;; # ## ## # # # # # # # #\n;; # # ## # # # # # # # # ####\n;; # # # ##### # # ##### # #\n;; # # # # # # # # # # #\n;; ### # # # #### # # # ####\n;;\n;; Imports\n\n;; Import References\n;; ^^^^^^^^^^^^^^^^^\n\n;;;; Dotted Names\n;;\n;; (dotted_name).ref node to connect to to use the reference\n;; (dotted_name).before_scope node to connect from to ensure the reference resolves\n\n;; all names are references\n[\n (import_statement name: (dotted_name (identifier) @name))\n (future_import_statement name: (dotted_name (identifier) @name))\n (import_from_statement name: (dotted_name (identifier) @name))\n (import_statement name: (aliased_import name: (dotted_name (identifier) @name)))\n (future_import_statement name: (aliased_import name: (dotted_name (identifier) @name)))\n (import_from_statement name: (aliased_import name: (dotted_name (identifier) @name)))\n (import_from_statement module_name: (dotted_name (identifier) @name))\n (import_from_statement module_name: (relative_import (dotted_name (identifier) @name)))\n] {\n attr (@name.ref) node_reference = @name\n}\n\n;; references are chained\n[\n (import_statement name: (dotted_name (identifier) @left . (identifier) @right))\n (future_import_statement name: (dotted_name (identifier) @left . (identifier) @right))\n (import_from_statement name: (dotted_name (identifier) @left . (identifier) @right))\n (import_statement name: (aliased_import name: (dotted_name (identifier) @left . (identifier) @right)))\n (future_import_statement name: (aliased_import name: (dotted_name (identifier) @left . (identifier) @right)))\n (import_from_statement name: (aliased_import name: (dotted_name (identifier) @left . (identifier) @right)))\n (import_from_statement module_name: (dotted_name (identifier) @left . (identifier) @right))\n (import_from_statement module_name: (relative_import (dotted_name (identifier) @left . (identifier) @right)))\n] {\n node push_dot\n attr (push_dot) push_symbol = \".\"\n\n edge @right.ref -> push_dot\n edge push_dot -> @left.ref\n}\n\n;; lookup first reference\n[\n (import_statement name: (dotted_name . (identifier) @first) @dotted)\n (future_import_statement name: (dotted_name . (identifier) @first) @dotted)\n (import_from_statement name: (dotted_name . (identifier) @first) @dotted)\n (import_statement name: (aliased_import name: (dotted_name . (identifier) @first) @dotted))\n (future_import_statement name: (aliased_import name: (dotted_name . (identifier) @first) @dotted))\n (import_from_statement name: (aliased_import name: (dotted_name . (identifier) @first) @dotted))\n (import_from_statement module_name: (dotted_name . (identifier) @first) @dotted)\n (import_from_statement module_name: (relative_import (dotted_name . (identifier) @first) @dotted))\n] {\n edge @first.ref -> @dotted.before_scope\n}\n\n;; expose last reference\n[\n (import_statement name: (dotted_name (identifier) @last .) @dotted)\n (future_import_statement name: (dotted_name (identifier) @last .) @dotted)\n (import_from_statement name: (dotted_name (identifier) @last .) @dotted)\n (import_statement name: (aliased_import name: (dotted_name (identifier) @last .) @dotted))\n (future_import_statement name: (aliased_import name: (dotted_name (identifier) @last .) @dotted))\n (import_from_statement name: (aliased_import name: (dotted_name (identifier) @last .) @dotted))\n (import_from_statement module_name: (dotted_name (identifier) @last .) @dotted)\n (import_from_statement module_name: (relative_import (dotted_name (identifier) @last .) @dotted))\n] {\n edge @dotted.ref -> @last.ref\n}\n\n;;;; Aliased Import\n;;\n;; An aliased import behaves like its wrapped dotted_name as a reference\n;;\n;; (aliased_import).ref node to connect to, to use the reference\n;; (aliased_import).before_scope node to connect from to ensure the reference resolves\n\n(aliased_import name: (dotted_name) @dotted) @aliased {\n edge @aliased.ref -> @dotted.ref\n edge @dotted.before_scope -> @aliased.before_scope\n}\n\n;;;; Relative Import\n;;\n;; A relative import behaves like its wrapped dotted_name as a reference\n;;\n;; (relative_import).ref node to connect to, to use the reference\n;; (relative_import).before_scope node to connect from to ensure the reference resolves\n\n(relative_import (import_prefix) . (dotted_name) @dotted) @relative {\n edge @relative.ref -> @dotted.ref\n\n node push_dot\n attr (push_dot) push_symbol = \".\"\n\n edge @dotted.before_scope -> push_dot\n edge push_dot -> @relative.before_scope\n}\n\n(relative_import (import_prefix) .) @relative {\n edge @relative.ref -> @relative.before_scope\n}\n\n;;;; Wildcard Import\n;;\n;; A wildcard import simply passes through\n;;\n;; (wildcard_import).ref node to connect to, to use the reference\n;; (wildcard_import).before_scope node to connect from to ensure the reference resolves\n\n(wildcard_import) @wildcard {\n edge @wildcard.ref -> @wildcard.before_scope\n}\n\n;;;; Import from\n;;\n;; The imported references are resolved in the from module\n\n[\n (import_from_statement module_name: (_) @left name: (_) @right)\n (import_from_statement module_name: (_) @left (wildcard_import) @right)\n] {\n node push_dot\n attr (push_dot) push_symbol = \".\"\n\n edge @right.before_scope -> push_dot\n edge push_dot -> @left.ref\n}\n\n;;;; Non-relative Imports\n;;\n;; Non-relative imports are resolved in the root scope\n\n[\n (import_statement name: (_) @name)\n (import_from_statement module_name: (dotted_name) @name)\n] {\n edge @name.before_scope -> ROOT_NODE\n}\n\n;;;; Relative Imports\n;;\n;; Relative imports are resolved in scopes related to the current module\n\n;; . imports resolve in parent module scope\n(import_from_statement module_name: (relative_import (import_prefix) @prefix (#eq? @prefix \".\")) @relative) {\n edge @relative.before_scope -> @prefix.parent_module\n}\n\n;; .. imports resolve in grandparent module scope\n(import_from_statement module_name: (relative_import (import_prefix) @prefix (#eq? @prefix \"..\")) @relative) {\n edge @relative.before_scope -> @prefix.grandparent_module\n}\n\n;;;; Future Imports\n;;\n;; We don\'t know the future, so we cannot connect references of future imports anywhere. Maybe one day?\n\n;; Import Definitions\n;; ^^^^^^^^^^^^^^^^^^\n\n;;;; Dotted Names & Aliased Imports\n;;\n;; (dotted_name).after_scope node to connect to, to expose the definition\n;; (dotted_name).def node to connect from, to give definition content\n\n;; unaliased names and aliases are definitions\n[\n (import_statement name: (dotted_name (identifier) @name))\n (future_import_statement name: (dotted_name (identifier) @name))\n (import_from_statement name: (dotted_name (identifier) @name))\n (import_statement name: (aliased_import alias: (identifier) @name))\n (future_import_statement name: (aliased_import alias: (identifier) @name))\n (import_from_statement name: (aliased_import alias: (identifier) @name))\n] {\n attr (@name.def) node_definition = @name\n}\n\n;; definitions are chained\n[\n (import_statement name: (dotted_name (identifier) @left . (identifier) @right))\n (future_import_statement name: (dotted_name (identifier) @left . (identifier) @right))\n (import_from_statement name: (dotted_name (identifier) @left . (identifier) @right))\n] {\n node pop_dot\n attr (pop_dot) pop_symbol = \".\"\n\n edge @left.def -> pop_dot\n edge pop_dot -> @right.def\n}\n\n;; connect last definition\n[\n (import_statement name: (dotted_name (identifier) @last .) @outer)\n (future_import_statement name: (dotted_name (identifier) @last .) @outer)\n (import_from_statement name: (dotted_name (identifier) @last .) @outer)\n (import_statement name: (aliased_import alias: (identifier) @last ) @outer)\n (future_import_statement name: (aliased_import alias: (identifier) @last ) @outer)\n (import_from_statement name: (aliased_import alias: (identifier) @last ) @outer)\n] {\n edge @last.def -> @outer.def\n}\n\n;; expose first definition\n[\n (import_statement name: (dotted_name . (identifier) @first) @outer)\n (future_import_statement name: (dotted_name . (identifier) @first) @outer)\n (import_from_statement name: (dotted_name . (identifier) @first) @outer)\n (import_statement name: (aliased_import alias: (identifier) @first ) @outer)\n (future_import_statement name: (aliased_import alias: (identifier) @first ) @outer)\n (import_from_statement name: (aliased_import alias: (identifier) @first ) @outer)\n] {\n edge @outer.after_scope -> @first.def\n}\n\n;;;; Wildcard Import\n;;\n;; Wildcard imports simply pass through\n\n(wildcard_import) @wildcard {\n edge @wildcard.after_scope -> @wildcard.def\n}\n\n;;;; Import Definitions -> References\n;;\n;; The definitions introduced by imports are connected to the corresponding references\n\n[\n (import_statement name: (_) @name)\n (future_import_statement name: (_) @name)\n (import_from_statement name: (_) @name)\n (import_from_statement (wildcard_import) @name)\n] {\n edge @name.def -> @name.ref\n}\n\n;;;; Imports\n;;\n;; The definitions introduced by imports are visible after the import statement\n\n[\n (import_statement name: (_) @name)\n (future_import_statement name: (_) @name)\n (import_from_statement name: (_) @name)\n (import_from_statement (wildcard_import) @name)\n] @stmt {\n edge @stmt.after_scope -> @name.after_scope\n attr (@stmt.after_scope -> @name.after_scope) precedence = 1\n}\n\n;;\n;; ######\n;; # # # #### #### # # ####\n;; # # # # # # # # # #\n;; ###### # # # # #### ####\n;; # # # # # # # # #\n;; # # # # # # # # # # #\n;; ###### ###### #### #### # # ####\n;;\n;; Blocks\n\n[\n (module (_) @last_stmt .)\n (block (_) @last_stmt .)\n] @block\n{\n edge @block.after_scope -> @last_stmt.after_scope\n}\n\n[\n (module (_) @stmt1 . (_) @stmt2)\n (block (_) @stmt1 . (_) @stmt2)\n]\n{\n edge @stmt2.before_scope -> @stmt1.after_scope\n}\n\n[\n (module (_) @stmt)\n (block (_) @stmt)\n]\n{\n edge @stmt.after_scope -> @stmt.before_scope\n let @stmt.local_scope = @stmt.before_scope\n}\n\n[\n (block . (_) @stmt)\n (module . (_) @stmt)\n] @block\n{\n edge @stmt.before_scope -> @block.before_scope\n}\n\n(function_definition (block) @block)\n{\n edge @block.before_scope -> @block.local_scope\n}\n\n[\n (while_statement (block) @block)\n (if_statement (block) @block)\n (with_statement (block) @block)\n (try_statement (block) @block)\n (for_statement (block) @block)\n (_ [\n (else_clause (block) @block)\n (elif_clause (block) @block)\n (except_clause (block) @block)\n (finally_clause (block) @block)\n ])\n] @stmt\n{\n edge @block.before_scope -> @block.local_scope\n edge @stmt.after_scope -> @block.after_scope\n}\n\n(match_statement body: (_) @block) @stmt\n{\n let @block.local_scope = @block.before_scope\n edge @block.before_scope -> @stmt.before_scope\n edge @stmt.after_scope -> @block.after_scope\n}\n\n[\n (for_statement)\n (while_statement)\n] @stmt\n{\n edge @stmt.before_scope -> @stmt.after_scope\n}\n\n;;\n;; #####\n;; # # ##### ## ##### ###### # # ###### # # ##### ####\n;; # # # # # # ## ## # ## # # #\n;; ##### # # # # ##### # ## # ##### # # # # ####\n;; # # ###### # # # # # # # # # #\n;; # # # # # # # # # # # ## # # #\n;; ##### # # # # ###### # # ###### # # # ####\n;;\n;; Statements\n\n;;;; Simple Statements\n\n(print_statement) {}\n\n(assert_statement) {}\n\n(expression_statement) {}\n\n(return_statement (_) @expr) @stmt\n{\n edge @stmt.function_returns -> @expr.output\n}\n\n(delete_statement) {}\n\n(raise_statement) {}\n\n(pass_statement) {}\n\n(break_statement) {}\n\n(continue_statement) {}\n\n(global_statement) {}\n\n(nonlocal_statement) {}\n\n(exec_statement) {}\n\n(type_alias_statement) {}\n\n;;;; Compound Statements\n\n(if_statement) {}\n\n(if_clause) {}\n\n(elif_clause) {}\n\n(else_clause) {}\n\n(for_statement) {}\n\n(while_statement) {}\n\n(try_statement) {}\n\n(except_group_clause) {}\n\n(except_clause) {}\n\n(finally_clause) {}\n\n(with_statement) {}\n\n(with_clause) {}\n\n[\n (function_definition\n parameters: (_) @params\n body: (_) @body\n ) @func\n (lambda\n parameters: (_) @params\n body: (_) @body\n )@func\n] {\n node @func.call\n node return_value\n node drop_scope\n\n edge @func.call -> return_value\n edge @body.before_scope -> @params.after_scope\n edge @body.before_scope -> drop_scope\n edge drop_scope -> @func.bottom\n attr (drop_scope) type = \"drop_scopes\"\n attr (@func.call) pop_scoped_symbol = \"()\"\n edge @params.before_scope -> JUMP_TO_SCOPE_NODE\n attr (return_value) is_exported\n let @func.function_returns = return_value\n}\n\n(function_definition\n name: (identifier) @name\n body: (_) @body\n) @func {\n attr (@name.def) node_definition = @name\n attr (@name.def) definiens_node = @func\n edge @func.after_scope -> @name.def\n edge @name.def -> @func.call\n\n ; Prevent functions defined inside of method bodies from being treated like methods\n let @body.class_self_scope = #null\n let @body.class_member_attr_scope = #null\n}\n\n; method definition\n(class_definition\n body: (block\n (function_definition\n parameters: \n (parameters . (identifier) @first_param)\n body: (block) @method_body\n )\n )\n) \n{\n edge @first_param.def -> @first_param.class_self_scope\n edge @first_param.class_member_attr_scope -> @first_param.output\n edge @first_param.output -> @method_body.after_scope\n attr (@first_param.output) push_node = @first_param\n}\n\n[\n (parameters (_) @param) @params\n (lambda_parameters (_) @param) @params\n]\n{\n node @param.param_index\n node @param.param_name\n\n attr (@param.param_index) push_symbol = (named-child-index @param)\n edge @param.param_index -> @params.before_scope\n edge @params.after_scope -> @param.input\n edge @param.param_name -> @params.before_scope\n}\n\n\n(parameter/identifier) @param @name\n{\n attr (@name.def) node_definition = @name\n attr (@param.param_name) push_node = @param\n edge @name.def -> @param.param_name\n edge @name.def -> @param.param_index\n edge @param.input -> @name.def\n}\n\n[\n (parameter/default_parameter\n name: (_) @name\n value: (_) @value) @param\n (parameter/typed_default_parameter\n name: (_) @name\n value: (_) @value) @param\n] {\n attr (@name.def) node_definition = @name\n attr (@param.param_name) push_node = @name\n edge @name.def -> @param.param_name\n edge @name.def -> @param.param_index\n edge @param.input -> @name.def\n edge @name.def -> @value.output\n}\n\n[\n (parameter/typed_parameter\n . (_) @name) @param\n (parameter/list_splat_pattern\n (_) @name) @param\n (parameter/dictionary_splat_pattern\n (_) @name) @param\n] {\n attr (@name.def) node_definition = @name\n attr (@param.param_name) push_node = @name\n edge @name.def -> @param.param_name\n edge @name.def -> @param.param_index\n edge @param.input -> @name.def\n}\n\n(class_definition) @class {\n node @class.call_drop\n node @class.member_attrs\n node @class.members\n node @class.super_scope\n}\n\n(class_definition\n name: (identifier) @name) {\n attr (@name.def) node_definition = @name\n}\n\n(class_definition\n name: (identifier) @name) @class\n{\n node call\n node self_dot\n node self_scope\n node members_dot\n\n attr (@name.def) definiens_node = @class\n attr (@name.def) syntax_type = \"class\"\n edge @class.after_scope -> @name.def\n edge @name.def -> call\n edge @name.def -> members_dot\n edge members_dot -> @class.members\n edge call -> @class.call_drop\n edge @class.call_drop -> self_scope\n edge self_scope -> @class.super_scope\n edge self_scope -> self_dot\n edge self_dot -> @class.members\n edge @class.members -> @class.member_attrs\n attr (call) pop_scoped_symbol = \"()\"\n attr (@class.call_drop) type = \"drop_scopes\"\n attr (members_dot) pop_symbol = \".\"\n attr (self_dot) pop_symbol = \".\"\n attr (@class.member_attrs) push_symbol = \".\"\n attr (self_scope) is_exported\n}\n\n(class_definition\n body: (_) @body) @class\n{\n let @body.class_member_attr_scope = @class.member_attrs\n node @body.class_parent_scope\n edge @body.class_parent_scope -> @class.class_parent_scope\n edge @body.class_parent_scope -> @class.local_scope\n let @body.class_self_scope = @class.call_drop\n let @body.class_super_scope = @class.super_scope\n}\n\n(class_definition\n body: (block\n (_) @last_stmt .)) @class\n{\n edge @class.members -> @last_stmt.after_scope\n}\n\n(class_definition\n superclasses: (argument_list\n (_) @superclass)) @class\n{\n edge @class.super_scope -> @superclass.output\n}\n\n(decorated_definition\n definition: (_) @def) @stmt\n{\n edge @def.before_scope -> @stmt.before_scope\n edge @stmt.after_scope -> @def.after_scope\n}\n\n(match_statement) {}\n\n(case_clause\n (case_pattern) @pattern\n consequence: (_) @consequence)\n{\n edge @consequence.before_scope -> @pattern.new_bindings\n}\n\n(case_clause\n consequence: (_) @consequence) @clause\n{\n edge @consequence.before_scope -> @clause.before_scope\n edge @clause.after_scope -> @consequence.after_scope\n}\n\n;;\n;; #######\n;; # # # ##### ##### ###### #### #### # #### # # ####\n;; # # # # # # # # # # # # # ## # #\n;; ##### ## # # # # ##### #### #### # # # # # # ####\n;; # ## ##### ##### # # # # # # # # # #\n;; # # # # # # # # # # # # # # # ## # #\n;; ####### # # # # # ###### #### #### # #### # # ####\n;;\n;; Expressions\n\n(lambda\n body: (_) @body\n)@lam {\n ;; TODO Unify .before_scope, .local_scope, and .input to simplify\n ;; uniform treatment of lambdas and function definitions.\n node @body.before_scope\n let @body.local_scope = @body.before_scope\n edge @body.input -> @body.before_scope\n\n edge @lam.output -> @lam.call\n}\n\n(conditional_expression) {}\n\n(named_expression) {}\n\n(as_pattern) {}\n\n(await) {}\n\n(binary_operator\n (_) @left\n (_) @right) @binop\n{\n edge @binop.new_bindings -> @left.new_bindings\n edge @binop.new_bindings -> @right.new_bindings\n}\n\n(primary_expression/identifier) @name {\n attr (@name.ref) node_reference = @name\n}\n\n(primary_expression/identifier) @name\n{\n edge @name.output -> @name.local_scope\n edge @name.output -> @name.class_parent_scope\n edge @name.local_scope -> @name.input\n attr (@name.input) pop_node = @name\n attr (@name.output) node_reference = @name\n\n edge @name.new_bindings -> @name.def\n}\n\n(string) {}\n\n(concatenated_string) {}\n\n(integer) {}\n\n(float) {}\n\n(true) {}\n\n(false) {}\n\n(none) {}\n\n(unary_operator) {}\n\n(attribute\n object: (_) @object\n attribute: (identifier) @name) @expr\n{\n node input_dot\n node output_dot\n\n edge @expr.output -> @name.output\n edge @name.output -> output_dot\n edge output_dot -> @object.output\n edge @object.input -> input_dot\n edge input_dot -> @name.input\n edge @name.input -> @expr.input\n attr (output_dot) push_symbol = \".\"\n attr (input_dot) pop_symbol = \".\"\n attr (@name.input) pop_node = @name\n attr (@name.output) push_node = @name\n}\n\n(primary_expression/attribute\n attribute: (identifier) @name)\n{\n attr (@name.output) is_reference\n}\n\n(subscript) {}\n\n(call\n function: (_) @fn\n arguments: (argument_list) @args) @call\n{\n node output_args\n\n edge @call.output -> output_args\n edge output_args -> @fn.output\n attr (output_args) push_scoped_symbol = \"()\", scope = @args.args\n}\n\n(call\n function: (attribute\n object: (_) @receiver)\n arguments: (argument_list\n (expression) @arg) @args)\n{\n node receiver_arg_index\n attr (receiver_arg_index) pop_symbol = \"0\"\n edge @args.args -> receiver_arg_index\n edge receiver_arg_index -> @receiver.output\n\n ;; FIXME the arguments will also exist with their unshifted indices because of the general\n ;; rule below!\n node arg_index\n attr (arg_index) pop_symbol = (plus 1 (named-child-index @arg))\n edge arg_index -> @arg.output\n}\n\n(call\n arguments: (argument_list\n (keyword_argument\n name: (identifier) @name\n value: (_) @val)) @args)\n{\n node arg_name\n edge @args.args -> arg_name\n attr (arg_name) pop_node = @name\n edge arg_name -> @val.output\n}\n\n(argument_list) @args {\n node @args.args\n attr (@args.args) is_exported\n}\n\n(argument_list\n (expression) @arg) @args\n{\n node arg_index\n edge @args.args -> arg_index\n attr (arg_index) pop_symbol = (named-child-index @arg)\n edge arg_index -> @arg.output\n}\n\n(\n (call\n function: (identifier) @_fn_name) @call\n (#eq? @_fn_name \"super\")\n)\n{\n edge @call.output -> @call.class_super_scope\n}\n\n(list) @list\n{\n node called\n\n edge @list.output -> called\n edge called -> @list.global_dot\n attr (called) push_symbol = \"list\"\n}\n\n(list (_) @el) @list\n{\n edge @list.new_bindings -> @el.new_bindings\n}\n\n(list_comprehension) {}\n\n(dictionary (pair) @pair) @dict\n{\n edge @dict.new_bindings -> @pair.new_bindings\n}\n\n(pair\n value: (_) @value) @pair\n{\n edge @pair.new_bindings -> @value.new_bindings\n}\n\n(dictionary_comprehension) {}\n\n(set (_) @el) @set\n{\n edge @set.new_bindings -> @el.new_bindings\n}\n\n(set_comprehension) {}\n\n[\n (tuple (_) @element)\n (expression_list (_) @element)\n] @tuple\n{\n node el_index\n\n edge @tuple.output -> el_index\n attr (el_index) pop_symbol = (named-child-index @element)\n edge el_index -> @element.output\n\n edge @tuple.new_bindings -> @element.new_bindings\n}\n\n(parenthesized_expression) {}\n\n(generator_expression) {}\n\n(ellipsis) {}\n\n(list_splat (_) @splatted) @splat\n{\n edge @splat.new_bindings -> @splatted.new_bindings\n}\n\n;;\n;; ######\n;; # # ## ##### ##### ###### ##### # # ####\n;; # # # # # # # # # ## # #\n;; ###### # # # # ##### # # # # # ####\n;; # ###### # # # ##### # # # #\n;; # # # # # # # # # ## # #\n;; # # # # # ###### # # # # ####\n;;\n;; Patterns\n\n\n[\n (pattern/identifier) @name @pattern\n ; identifiers in patterns\n (as_pattern (identifier) @name .) @pattern\n (keyword_pattern (identifier) @name) @pattern\n (splat_pattern (identifier) @name) @pattern\n ; every context where _simple_pattern is used, because matching\n ; pattern/dotted_name does not work\n (case_pattern (dotted_name . (_) @name .) @pattern)\n (keyword_pattern (dotted_name . (_) @name .) @pattern)\n (union_pattern (dotted_name . (_) @name .) @pattern)\n] {\n attr (@name.def) node_definition = @name\n edge @pattern.output -> @pattern.local_scope\n edge @pattern.output -> @pattern.class_parent_scope\n edge @pattern.local_scope -> @pattern.input\n attr (@pattern.local_scope -> @pattern.input) precedence = 1\n attr (@pattern.input) node_definition = @name\n attr (@pattern.output) push_node = @name\n\n edge @pattern.new_bindings -> @name.def\n}\n\n(pattern/subscript) {}\n\n(pattern/attribute\n attribute: (identifier) @name)\n{\n attr (@name.input) is_definition\n}\n\n\n(list_splat_pattern (_) @pattern) @list {\n edge @list.new_bindings -> @pattern.new_bindings\n}\n\n[\n (pattern_list (_) @pattern)\n (tuple_pattern (_) @pattern)\n (list_pattern (_) @pattern)\n] @list\n{\n node pattern_index\n\n let statement_scope = @list.local_scope\n node @pattern.local_scope\n edge statement_scope -> @pattern.local_scope\n attr (statement_scope -> @pattern.local_scope) precedence = (plus 1 (named-child-index @pattern))\n\n edge pattern_index -> @list.input\n edge @pattern.input -> pattern_index\n attr (pattern_index) push_symbol = (named-child-index @pattern)\n}\n\n(class_pattern (case_pattern) @pattern) @class {\n edge @class.new_bindings -> @pattern.new_bindings\n}\n\n(splat_pattern (_) @pattern) @splat {\n edge @splat.new_bindings -> @pattern.new_bindings\n}\n\n(union_pattern (_) @pattern) @union {\n edge @union.new_bindings -> @pattern.new_bindings\n}\n\n(dict_pattern (_) @pattern) @dict {\n edge @dict.new_bindings -> @pattern.new_bindings\n}\n\n(complex_pattern) {}\n\n(as_pattern\n (expression) @value\n alias: (as_pattern_target (identifier) @name)) @as_pattern\n{\n attr (@name.local_scope -> @name.input) precedence = 1\n attr (@name.input) is_definition\n\n edge @as_pattern.new_bindings -> @value.new_bindings\n edge @as_pattern.new_bindings -> @name.new_bindings\n}\n\n(keyword_pattern) {}\n\n(case_pattern (_) @pattern) @case\n{\n edge @case.new_bindings -> @pattern.new_bindings\n}\n\n[\n (assignment\n left: (_) @pattern\n right: (_) @value)\n (with_item\n value:\n (as_pattern\n (_) @value\n alias: (as_pattern_target (_) @pattern)))\n]\n{\n edge @pattern.input -> @value.output\n}\n\n;;\n;; ##### #######\n;; # # # # # # ##### ## # # # # # ##### ###### ####\n;; # # # ## # # # # # # # # # # # # #\n;; ##### # # # # # # # ## # # # # ##### ####\n;; # # # # # # ###### ## # # ##### # #\n;; # # # # ## # # # # # # # # # # #\n;; ##### # # # # # # # # # # # ###### ####\n;;\n;; Syntax Types\n\n;;\n;; BEGIN BIG GNARLY DISJUNCTION\n;;\n;; The following pair of rules is intended to capture the following behavior:\n;;\n;; If a function definition is used to define a method, by being inside a class\n;; definition, then we make its syntax type `method`. Otherwise, we make it\'s\n;; syntax type `function`. Unfortunately, because of the limitations on negation\n;; and binding in tree sitter queries, we cannot negate `class_definition` or\n;; similar things directly. Instead, we have to manually push the negation down\n;; to form the finite disjunction it corresponds to.\n;;\n\n[\n (class_definition (block (decorated_definition (function_definition name: (_)@name))))\n (class_definition (block (function_definition name: (_)@name)))\n]\n{\n attr (@name.def) syntax_type = \"method\"\n}\n\n[\n (module (decorated_definition (function_definition name: (_)@name)))\n (module (function_definition name: (_)@name))\n\n (if_statement (block (decorated_definition (function_definition name: (_)@name))))\n (if_statement (block (function_definition name: (_)@name)))\n\n (elif_clause (block (decorated_definition (function_definition name: (_)@name))))\n (elif_clause (block (function_definition name: (_)@name)))\n\n (else_clause (block (decorated_definition (function_definition name: (_)@name))))\n (else_clause (block (function_definition name: (_)@name)))\n\n (case_clause (block (decorated_definition (function_definition name: (_)@name))))\n (case_clause (block (function_definition name: (_)@name)))\n\n (for_statement (block (decorated_definition (function_definition name: (_)@name))))\n (for_statement (block (function_definition name: (_)@name)))\n\n (while_statement (block (decorated_definition (function_definition name: (_)@name))))\n (while_statement (block (function_definition name: (_)@name)))\n\n (try_statement (block (decorated_definition (function_definition name: (_)@name))))\n (try_statement (block (function_definition name: (_)@name)))\n\n (except_clause (block (decorated_definition (function_definition name: (_)@name))))\n (except_clause (block (function_definition name: (_)@name)))\n\n (finally_clause (block (decorated_definition (function_definition name: (_)@name))))\n (finally_clause (block (function_definition name: (_)@name)))\n\n (with_statement (block (decorated_definition (function_definition name: (_)@name))))\n (with_statement (block (function_definition name: (_)@name)))\n\n (function_definition (block (decorated_definition (function_definition name: (_)@name))))\n (function_definition (block (function_definition name: (_)@name)))\n]\n{\n attr (@name.def) syntax_type = \"function\"\n}\n\n;;\n;; END BIG GNARLY DISJUNCTION\n;;\n";
Expand description
The stack graphs tsg source for this language.