chapel-py¶
Python bindings for Chapel’s frontend library, Dyno.
The purpose of this library is to allow programmers to easily create tools for the Chapel programming language that would be more difficult to write using C++ (the native language in which the Chapel frontend library is written).
For example, here’s a toy program that prints the names of all things declared
anywhere in myfile.chpl
.
from chapel import *
ctx = Context()
ast = ctx.parse("myfile.chpl")
all_names = set()
for node in postorder(ast):
if isinstance(node, NamedDecl):
all_names.add(node.name())
for name in all_names:
print(name)
If myfile.chpl
contains the following:
module myfile {
var x = 1+1;
var y = x+1;
record R {
}
}
Then the program will print out something like the following:
R
y
x
myfile
Note
The Chapel Python bindings are not yet fully mature. The API is subject to change and is not considered stable. Users of this library should be prepared to update their code as the library evolves.
Installation¶
Make sure that you have a from-source build of Chapel available in your
CHPL_HOME
. Currently, the build script also requires having LLVM available
in your path. The build script also requires that the development package of
Python be installed (for many package managers this is called
python3-devel
). With those constraints met, you can just run make
chapel-py-venv
:
This will allow you to use the Python bindings from a Python script run with
$CHPL_HOME/util/config/run-in-venv-with-python-bindings.bash python3
,
instead of just python3
. If you wish to install the Python bindings in your
system Python, run python3 -m pip install $CHPL_HOME/tools/chapel-py
.
Usage¶
The library is split into several major components:
The
chapel
module provides the AST node class hierarchy and theContext
object. It also provides some higher-level, pure Python implementations of certain utility functions. For instance, it provides thepreorder
andpostorder
traversal iterators and amatch
function to perform AST pattern matching.The
chapel.replace
module provides the “replacer API”, which is intended to perform transformations on existing Chapel files for various reasons. For instance, deprecations and syntax changes can be performed automatically using the replacer API, by finding AST patterns and performing string substitution.The
chapel.lsp
module provides a few helpers to transform Dyno types to LSP (Language Server Protocol) types. This module requires the lsprotocol package.
chapel
¶
The main entry point to the Chapel Python API is the Context
object. This
is a wrapper around the C++ construct of the same name. The Context in Dyno
is responsible for memoizing computations, interning strings, and more. The
Python wrapper around this object has methods that can be used to get started
with processing Chapel programs; one such method is parse
, which accepts
a file path and returns a list of Chapel AST nodes that represent this file.
At compile-time, chapel-py
generates a class hierarchy of Python objects,
with base class AstNode
. A class is created for each of the AST nodes understood
by Dyno. Thus, one might write:
from chapel import *
ctx = Context()
asts = ctx.parse("myfile.chpl")
print("it's a module" if isinstance(asts[0], Module) else "it's not a module")
Here, the Python isinstance
builtin is used to determine if the first
AST node returned by parse
is a module (it should be!)
Because the AST nodes form a class hierarchy, it’s possible to perform a more
general check; the following example prints “It’s a loop!” for all loops
(do
- while
, for
, foreach
, etc.), and “It’s not a loop…” otherwise.
def check(node):
if isinstance(node, Loop):
print("It's a loop!")
else:
print("It's not a loop...")
The AST nodes from the Python API are iterable; iterating over a node yields its children. Thus, one might print all the declarations in a module as follows:
def print_decls(mod):
for child in mod:
if isinstance(child, NamedDecl):
print(child.name())
Full AST traversals can be built on top of this functionality. Below
is the definition for postorder
from the chapel
module:
def postorder(node):
"""
Recursively visit the given AST node, going in post-order (children-then-parent)
"""
for child in node:
yield from postorder(child)
yield node
To find the list of available methods for each AST node class, the current best
practice is to consult the generated
$CHPL_HOME/tools/chapel-py/src/chapel/core/__init__.pyi
file. This is
generated by default when the Python bindings are built and is the most
up-to-date source of information on the API.
The chapel
module also provides convenience functions for working with the library.
For instance, it provides the postorder
and preorder
iterators (the
implementation of the former is included above). It also provides a couple
of more advanced helpers for dealing with Chapel ASTs.
chapel.parse_attribute
¶
The parse_attribute
function, given a “description” of an attribute (its
name and formal list), tries to parse an Attribute
AST node. This function
accounts for named and unnamed actuals, reordering, etc. For instance, given
an “attribute schema”:
attr = ("doXYZ", ["x", "y", "z"])
And the following Chapel attribute:
@doXYZ("hello", z = "world", y = "!")
The function returns:
{"x": "hello", "y": "!", "z": "world"}
This function is used in the Chapel linter to handle silencing warnings:
def ignores_rule(node, rulename):
ag = node.attribute_group()
if ag is None: return False
for attr in ag:
attr_call = chapel.parse_attribute(attr, IgnoreAttr)
if attr_call is None: continue
ignored_rule = attr_call["rule"]
if ignored_rule is not None and ignored_rule.value() == rulename:
return True
return False
chapel.match_pattern
¶
This function provides general pattern matching functionality to enable users of the Python API to rapidly find “interesting” locations in the AST. It supports arbitrary levels of nesting, as well as “named variables” to easily retrieve deeply nested AST nodes after a pattern has matched.
Generally, a call to match_pattern
takes an AST node and a pattern (what
constitutes a pattern is explained below). If the pattern matches, the function
returns a Python dict
that maps pattern variables to their corresponding
AST nodes; an empty dict
is returned if no pattern variables were used. If
the pattern does not match, the function returns None
.
To explain the possible patterns, it’s helpful to have an example AST.
We will use the following Chapel function, and its AST myFn
, in the following
examples:
proc f(x: int, y: int) {
var z = 1+2;
return x+y+z;
}
The simplest example of pattern is an AST class. For instance:
print(chapel.match_pattern(myFn, Function)) # Prints "{}"
When a function AST node myFn
is matched against the Function
pattern,
the match is successful; since no pattern variables were used, this results
in an empty dictionary {}
.
A list can be used to represent patterns of AST nodes with children. To match a function with exactly two arguments:
print(chapel.match_pattern(myFn, [Function, Formal, Formal, Block])) # Prints "{}"
Since we still haven’t used any pattern variables, the result of
match_pattern
still returns {}
. However, having matched the pattern, it
would be cumbersome to attempt to retrieve each of the two formals from the
list: we’d need to access the function’s children again, by their index. Since
Formal
nodes are direct children of the Function
, this isn’t too
inconvenient; however, conceivably, the nodes of interest could be further down
in the AST from the parent. This is where pattern variables come in. Instead of
writing Formal
, we can write ("?f1", Formal)
. This will cause the
pattern matcher to save the AST node matching Formal
into the variable
f1
.
pat = [Function, ("?f1", Formal), ("?f2", Formal), Block]
print(chapel.match_pattern(myFn, pat)) # Prints "{ 'f1': ..., 'f2': ... }"
The dictionary returned by match_pattern
can then be queried by the variables
to retrieve the formals.
We can further restrict our pattern to require formals with ‘simple’ type expressions (identifiers).
pat = [Function, [Formal, Identifier], [Formal, Identifier], Block]
print(chapel.match_pattern(myFn, pat)) # Prints "{}"
Pattern variables can still be used with list patterns like [Formal,
Identifier]
. This is done by adding the pattern variable string to the front
of the list.
pat = [Function, ["?f1", Formal, Identifier], ["f2", Formal, Identifier], Block]
print(chapel.match_pattern(myFn, pat)) # Prints "{ 'f1': ..., 'f2': ... }"
Some other useful features of the pattern library:
The
rest
pattern can be used as part of a list to indicate that you don’t care about the remaining AST children, however many there are.A variable without an AST node, (
"?x"
) can be used by itself to match any AST node and store it inx
.A
set
can be used to represent a disjunctive or pattern. For example,set([Begin, Cobegin])
will match either aBegin
or aCobegin
node.
chapel.each_matching
¶
This function combines the operation of preorder
and match_pattern
to iterate
an AST and yield all nodes matching the given pattern. Concretely, given
a pattern, it yields the node and the variables resulting from the match.
The following snippet will print one line for each binary operation, listing
the operation itself and the operation’s two operands.
for (op, variables) in chapel.each_matching(myFn, [OpCall, "?l", "?r"]):
print("Found an operation ", op.op(), "with operands: ", variables["l"], variables["r"])
chapel.replace
¶
The chapel.replace
module is used for writing “replacer scripts”. The motivation
for this module is evolving the Chapel language. As the language develops, we
tend to shift the patterns we prefer, and modify unstable language syntax. When
modifying existing code to match the new standards, we either have to perform
the changes manually, or resort to “general” tools like sed
or awk
. However,
the trouble with these tools is that they are suited for modifying streams of
text. When modifying programs in a language, it is more natural to work with
a structured representation – the AST. Thus, the chapel.replacer
module
provides utilities to modify a file by traversing the ASTs contained within,
and generating a list of substitutions.
Although the AST is used to find places in the code where changes must be made, the changes themselves are performed using string operation. This is motivated by many reasons:
Dyno does not have good support for modifying ASTs (they are immutable).
If an AST is modified, it should be printed back to the file with only those modifications; however, this would require the Chapel syntax printer to be able to preserve most of the original format of the text.
Writing plain code, such as
1+1
, is often easier than creating an AST node (PlusNode(IntNode(1), IntNode(1))
).
The chapel.replace
module provides a driver function run
, which, when given
a source of changes (described below), takes over the execution of the program.
It registers and parses command line arguments, and handles file modifications.
Thus, given an AST traversal, you end up with a fully-featured command-line
script ready to be pointed at files.
usage: replace [-h] [--suffix SUFFIX] [--in-place] [filenames ...]
A tool to search-and-replace Chapel expressions with others
positional arguments:
filenames
options:
-h, --help show this help message and exit
--suffix SUFFIX
--in-place`
The ‘source of changes’ is a Python iterator that should accept two arguments:
rc
(for ‘replacement context’) and root
(for the AST node at which the
traversal begins). A very simple (albeit completely pointless and semantically
incorrect) example is the following script, which replaces all occurrences of
the number 42
with meaningOfLife
:
def replace_all_42(rc, root):
for (num, _) in each_matching(root, IntLiteral):
if num.text() == '42': yield (num, 'meaningOfLife')
run(replace_all_42)
A more practical example is renaming methods. Note that this is not
amenable to naive substitution: we don’t want to accidentally rename non-methods
that happen to have the same name, or even locally declared functions inside
other functions in a record or class. Consider renaming the enterThis
method to enterContext
(this is a real change that was performed in
the Chapel language in 1.32, though it was not done automatically with the
help of this tool). In the following snippet, only the proc
labeled (1)
should be renamed. This is because enterThis
is actually a method. On
the other hand, (2)
, even though it’s declared within R
’s curly braces,
is actually a locally defined function, and not a method on R
.
(3)
is a freestanding function, and thus should also not be renamed.
record R {
proc enterThis() {} // (1)
proc f() {
proc enterThis() {} // (2)
}
}
proc enterThis() {} // (3)
This can be implemented using the following iterator:
def replace_enter_this(rc, root):
for (fn, _) in each_matching(root, Function):
if fn.name() == "enterThis" and fn.is_method():
yield (fn, lambda txt: txt.replace("enterThis", "enterContext", 1))
In this case, instead of yielding a pair of the node-to-replace and the
replacement text, the iterator produces a lambda
, which will be fed the
node’s current string representation (proc enterThis() {...
). Using
this lambda, we perform a simple substitution, renaming enterThis
to
enterContext
with Python’s regular replace
method.
Finally, the following script was used to automatically insert interfaces into records and classes that provided the corresponding functionality. It was used to update about 150 files (including Chapel modules and tests). This script implements the following features:
Detecting particular signatures of the
init
method specific to deserializationAlways printing the supported interfaces in a specific order
Supporting both primary and secondary methods, including a mix of both
Adding a new interface list or modifying an existing one
def tag_aggregates_with_io_interfaces(rc, root):
aggrs_to_change = defaultdict(lambda: set())
names_to_tag = defaultdict(lambda: set())
for (fn, _) in chapel.each_matching(root, Function):
if not fn.is_method(): continue
name = fn.name()
if name == "serialize":
tag = "writeSerializable"
elif name == "deserialize":
tag = "readDeserializable"
elif name == "init":
formal_names = []
for child in fn:
if not isinstance(child, Formal): continue
if child.name() == "this": continue
formal_names.append(child.name())
if len(formal_names) >=2 and formal_names[-1] == "deserializer" and formal_names[-2] == "reader":
tag = "initDeserializable"
else:
continue
else:
continue
if fn.is_primary_method():
aggrs_to_change[fn.parent().unique_id()].add(tag)
continue
this_receiver = fn.this_formal()
names_to_tag[rc.node_exact_string(this_receiver)].add(tag)
def build_tag_str(tags):
if len(tags) == 3: return "serializable"
# tags have a preferred order, so just use an if-else chain to make that work
the_order = ["writeSerializable", "readDeserializable", "initDeserializable"]
return ", ".join(t for t in the_order if t in tags)
for (record, _) in chapel.each_matching(root, AggregateDecl):
tags = set()
if record.unique_id() in aggrs_to_change:
tags |= aggrs_to_change[record.unique_id()]
if record.name() in names_to_tag:
tags |= names_to_tag[record.name()]
if len(tags) == 0: continue
tag_str = build_tag_str(tags)
record_text = rc.node_exact_string(record)
curlypos = record_text.find("{")
colonpos = record_text.find(":")
if colonpos >= 0 and colonpos < curlypos:
new_text = record_text.replace(" {" , ", " + tag_str + " {" , 1)
else:
new_text = record_text.replace(record.name(), record.name() + " : " + tag_str, 1)
yield (record, new_text)
API¶
chapel¶
Chapel’s Python bindings provide an API to interact with Chapel’s frontend compiler from Python.
- chapel.preorder(node)¶
Recursively visit the given AST node, going in pre-order (parent-then-children)
- chapel.postorder(node)¶
Recursively visit the given AST node, going in post-order (children-then-parent)
- chapel.is_deprecated(node: AstNode) bool ¶
Returns true if node is marked with a @deprecated attribute
- chapel.is_docstring_comment(comment: Comment) bool ¶
comment is a docstring if it doesn’t begin with ‘//’
- class chapel.SiblingMap(top_level_modules: List[AstNode])¶
Represents a mapping of nodes to their siblings. This is most useful for finding the docstring of a node.
- chapel.get_docstring(node: AstNode, sibling_map: SiblingMap) str | None ¶
Get the docstring for a node, if it exists
- chapel.parse_attribute(attr: Attribute, attribute: Tuple[str, Sequence[str]])¶
Given an Attribute AST node, and a description of the attribute in the form (name, formal_names), return a mapping of formal names to their values in the attribute call. Raise errors if the call is malformed in some way.
- chapel.match_pattern(ast, pattern)¶
Matches the given AST against the given pattern. Patterns are specified as AST node classes, strings, or lists thereof. Here’s a summary:
A single node with any number of children:
chapel.Nodetype
Any node, saved in a variable:
“?x”
Any node at all, not saved in a variable:
“”
A single node with any number of children, saved in a variable:
(“?x”, chapel.Nodetype)
A single node with no children at all:
[chapel.Nodetype]
A single node with no children, saved in a variable:
[“?x”, chapel.Nodetype]
A single node with two children, expressed as patterns P1 and P2:
[chapel.Nodetype, P1, P2]
A single node with at least two children:
[chapel.Nodetype, P1, P2, rest]
An addition node in which both arguments are equal:
[chapel.OpCall, “?x”, “x”]
- chapel.each_matching(node, pattern, iterator=<function preorder>)¶
- chapel.files_with_contexts(files: List[str], setup: Callable[[Context], None] | None = None)¶
Some files might have the same name, which Dyno really doesn’t like. Stratify files into “buckets”; within each bucket, all filenames are unique. Between each bucket, re-create the Dyno context to avoid giving it conflicting files.
For each newly-created context, call the setup function with it.
Yields files from the argument, as well as the context created for them.
- chapel.files_with_stdlib_contexts(files: List[str], setup: Callable[[Context], None] | None = None)¶
Like files_with_contexts, but also includes the standard library in the context.
- chapel.range_to_tokens(rng: Location, lines: List[str]) List[Tuple[int, int, int]] ¶
Convert a Chapel location to a list of token-compatible ranges. If a location spans multiple lines, it gets split into multiple tokens. The lines and columns are zero-indexed.
Returns a list of (line, column, length).
- chapel.range_to_lines(rng: Location, lines: List[str]) List[str] ¶
Convert a Chapel location to a list of strings
- chapel.range_to_text(rng: Location, lines: List[str]) str ¶
Convert a Chapel location to a single string
- chapel.get_file_lines(context: Context, node: AstNode) List[str] ¶
Get the lines of the file containing the given node
- chapel.is_basic_literal_like(node: AstNode) Literal | None ¶
Check for “basic” literals: basically, 1, “hello”, -42, etc. Returns the “underlying” literal removing surrounding AST (1, “hello”, 42). This helps do type comparisons in more complex checks. If the node is not a basic literal, returns None.
- chapel.is_complex_literal(node: AstNode) Tuple[Literal, Literal] | None ¶
Check for complex number literals: 1+2i, -42-3i, etc. Returns a tuple of the “underlying” literals, removing surrounding AST ((1, 2i), (42, 3i), etc.). This helps do type comparisons in more complex checks. If the node is not a complex literal, returns None.
- chapel.is_literal_like(node: AstNode) bool ¶
Returns true if the node is a literal-like node: either a “true” literal (1, “hello”, etc.) or something that isn’t a literal in the AST, but is a literal mathematically (-10, 10 + 2i).
- chapel.is_unstable_module(node: AstNode)¶
Returns true if the given AST node is a module, and if it’s explicitly marked unstable.
- chapel.in_unstable_module(node: AstNode)¶
Returns true if the given AST node is inside a module marked as unstable.
- class chapel.AggregateDecl¶
A Chapel AggregateDecl AST node
- class chapel.AnonFormal¶
A Chapel AnonFormal AST node
- intent(self) str ¶
Get the intent for this AnonFormal node
- class chapel.AnyClassType¶
A Chapel AnyClassType AST node
- class chapel.AnyComplexType¶
A Chapel AnyComplexType AST node
- class chapel.AnyEnumType¶
A Chapel AnyEnumType AST node
- class chapel.AnyImagType¶
A Chapel AnyImagType AST node
- class chapel.AnyIntType¶
A Chapel AnyIntType AST node
- class chapel.AnyIntegralType¶
A Chapel AnyIntegralType AST node
- class chapel.AnyIteratorClassType¶
A Chapel AnyIteratorClassType AST node
- class chapel.AnyIteratorRecordType¶
A Chapel AnyIteratorRecordType AST node
- class chapel.AnyNumericType¶
A Chapel AnyNumericType AST node
- class chapel.AnyOwnedType¶
A Chapel AnyOwnedType AST node
- class chapel.AnyPodType¶
A Chapel AnyPodType AST node
- class chapel.AnyRealType¶
A Chapel AnyRealType AST node
- class chapel.AnyRecordType¶
A Chapel AnyRecordType AST node
A Chapel AnySharedType AST node
- class chapel.AnyThunkRecordType¶
A Chapel AnyThunkRecordType AST node
- class chapel.AnyType¶
A Chapel AnyType AST node
- class chapel.AnyUintType¶
A Chapel AnyUintType AST node
- class chapel.AnyUninstantiatedType¶
A Chapel AnyUninstantiatedType AST node
- class chapel.AnyUnionType¶
A Chapel AnyUnionType AST node
- class chapel.Array¶
A Chapel Array AST node
- has_trailing_comma(self) bool ¶
Check if this Array node has a trailing comma
- is_associative(self) bool ¶
Check if this Array node is associative
- class chapel.ArrayType¶
A Chapel ArrayType AST node
- class chapel.As¶
A Chapel As AST node
- class chapel.AstNode¶
The base type of Chapel AST nodes
- attribute_group(self) Optional[AttributeGroup] ¶
Get the attribute group, if any, associated with this node
- creates_scope(self) bool ¶
Returns true if this AST node creates a scope
- curly_braces_location(self) Optional[Location] ¶
Get the Location of the curly braces of this AstNode node
- dump(self) None ¶
Dump the internal representation of the given AST node
- parent_symbol(self) Optional[AstNode] ¶
Get the parent symbol of this AST node (e.g., module, variable, etc.)
- pragmas(self) Set[str] ¶
Get the pragmas of this AST node
- resolve(self) Optional[ResolvedExpression] ¶
Perform resolution on code surrounding this node to determine its type and other information.
- resolve_via(self, arg0: TypedSignature) Optional[ResolvedExpression] ¶
Use a given function’s type information to determine the information of this node.
- scope_resolve(self) Optional[ResolvedExpression] ¶
Perform scope resolution on code surrounding this node to retrieve its to-ID and collect errors.
- tag(self) str ¶
Get a string representation of the AST node’s type
- type(self) Optional[Tuple[str, Optional[ChapelType], Optional[Param]]] ¶
Get the type of this AST node, as a 3-tuple of (kind, type, param).
- unique_id(self) str ¶
Get a unique identifier for this AST node
- class chapel.Attribute¶
A Chapel Attribute AST node
- actuals()¶
Get the actuals for this Attribute node
- name(self) str ¶
Get the name of this Attribute node
- class chapel.AttributeGroup¶
A Chapel AttributeGroup AST node
- get_attribute_named(self, arg0: str) Optional[AstNode] ¶
Get the attribute with a particular name, if any
- is_deprecated(self) bool ¶
Check if this AttributeGroup contains the ‘deprecated’ attribute
- is_unstable(self) bool ¶
Check if this AttributeGroup contains the ‘unstable’ attribute
- class chapel.BasicClassType¶
A Chapel BasicClassType AST node
- class chapel.Begin¶
A Chapel Begin AST node
- with_clause(self) Optional[WithClause] ¶
Get the WithClause of this Begin node
- class chapel.Block¶
A Chapel Block AST node
- class chapel.BoolLiteral¶
A Chapel BoolLiteral AST node
- value(self) bool ¶
Get the value of this BoolLiteral node
- class chapel.BoolParam¶
A Chapel BoolParam AST node
- value(self) bool ¶
Get the value of this boolean Param
- class chapel.BoolType¶
A Chapel BoolType AST node
- class chapel.BracketLoop¶
A Chapel BracketLoop AST node
- is_maybe_array_type(self) bool ¶
Check if this BracketLoop node may actually be a type
- class chapel.Break¶
A Chapel Break AST node
- target(self) Optional[Identifier] ¶
Get the target from this Break node
- class chapel.BuiltinType¶
A Chapel BuiltinType AST node
- class chapel.BytesLiteral¶
A Chapel BytesLiteral AST node
- class chapel.CFnPtrType¶
A Chapel CFnPtrType AST node
- class chapel.CPtrType¶
A Chapel CPtrType AST node
- class chapel.CStringLiteral¶
A Chapel CStringLiteral AST node
- class chapel.CStringType¶
A Chapel CStringType AST node
- class chapel.CVoidPtrType¶
A Chapel CVoidPtrType AST node
- class chapel.Call¶
A Chapel Call AST node
- formal_actual_mapping(self) List[int] ¶
Get the index of the function’s formal for each of the call’s actuals.
- num_actuals(self) int ¶
Get the number of actuals for this Call node
- class chapel.Catch¶
A Chapel Catch AST node
- has_parens_around_error(self) bool ¶
Check if this Catch uses parentheses
- class chapel.ChapelType¶
The base type of Chapel types
- class chapel.Class¶
A Chapel Class AST node
- class chapel.ClassType¶
A Chapel ClassType AST node
- class chapel.Cobegin¶
A Chapel Cobegin AST node
- with_clause(self) Optional[WithClause] ¶
Get the WithClause from this Cobegin node
- class chapel.Coforall¶
A Chapel Coforall AST node
- class chapel.Comment¶
A Chapel Comment AST node
- text(self) str ¶
Get the text from this Comment node
- class chapel.ComplexParam¶
A Chapel ComplexParam AST node
- class chapel.ComplexType¶
A Chapel ComplexType AST node
- class chapel.CompositeType¶
A Chapel CompositeType AST node
- class chapel.Conditional¶
A Chapel Conditional AST node
- else_block(self) Optional[Block] ¶
Get the else block of this Conditional node or None if no else block
- is_expression_level(self) bool ¶
Checks if this Conditional node is expression-level
- class chapel.Context¶
The Chapel context object that tracks various frontend state
- advance_to_next_revision(self, arg0: bool) None ¶
Advance the context to the next revision
- get_file_text(self, arg0: str) str ¶
Get the text of the file at the given path
- introspect_parsed_files(self) List[str] ¶
Inspect the list of files that have been parsed by the Context
- is_bundled_path(self, arg0: str) bool ¶
Check if the given file path is within the bundled (built-in) Chapel files
- set_module_paths(self, arg0: List[str], arg1: List[str]) None ¶
Set the module path arguments to the given lists of module paths and filenames
- track_errors(self) ErrorManager ¶
Return a context manager that tracks errors emitted by this Context
- class chapel.Continue¶
A Chapel Continue AST node
- target(self) Optional[Identifier] ¶
Get the target from this Continue node
- class chapel.Decl¶
A Chapel Decl AST node
- linkage(self) str ¶
Get the linkage of this Decl node
- visibility(self) str ¶
Get the visibility of this Decl node
- class chapel.DeclaredType¶
A Chapel DeclaredType AST node
- class chapel.Defer¶
A Chapel Defer AST node
- class chapel.Delete¶
A Chapel Delete AST node
- class chapel.DoWhile¶
A Chapel DoWhile AST node
- class chapel.Domain¶
A Chapel Domain AST node
- used_curly_braces(self) bool ¶
Check if the Domain node used curly braces
- class chapel.DomainType¶
A Chapel DomainType AST node
- class chapel.EmptyStmt¶
A Chapel EmptyStmt AST node
- class chapel.Enum¶
A Chapel Enum AST node
- class chapel.EnumElement¶
A Chapel EnumElement AST node
- class chapel.EnumParam¶
A Chapel EnumParam AST node
- class chapel.EnumType¶
A Chapel EnumType AST node
- class chapel.ErroneousExpression¶
A Chapel ErroneousExpression AST node
- class chapel.ErroneousType¶
A Chapel ErroneousType AST node
- class chapel.Error¶
An error that occurred as part of processing a file with the Chapel compiler frontend
- code_snippets(self) List[Tuple[Location, List[Location]]] ¶
Get the locations of code snippets printed by this error
- kind(self) str ¶
Retrieve the kind (‘error’, ‘warning’) of this type of error
- message(self) str ¶
Retrieve the contents of this error message
- notes(self) List[Tuple[Location, str]] ¶
Get the locations and text of additional notes printed by this error
- type(self) Optional[str] ¶
Retrieve the unique name of this type of error
- class chapel.ErrorManager¶
A wrapper container to help track the errors from a Context.
- class chapel.ExternBlock¶
A Chapel ExternBlock AST node
- code(self) str ¶
Get C code of this ExternBlock node
- class chapel.ExternType¶
A Chapel ExternType AST node
- class chapel.FnCall¶
A Chapel FnCall AST node
- actuals()¶
Get the actuals of this FnCall node
- used_square_brackets(self) bool ¶
Check if this FnCall was made using square brackets
- class chapel.FnIteratorType¶
A Chapel FnIteratorType AST node
- class chapel.Forall¶
A Chapel Forall AST node
- class chapel.Foreach¶
A Chapel Foreach AST node
- class chapel.Formal¶
A Chapel Formal AST node
- class chapel.ForwardingDecl¶
A Chapel ForwardingDecl AST node
- class chapel.Function¶
A Chapel Function AST node
- is_anonymous(self) bool ¶
Check if this Function node is anonymous
- is_inline(self) bool ¶
Check if this Function node is marked inline
- is_method(self) bool ¶
Check if this Function node is a method
- is_override(self) bool ¶
Check if this Function node is an override
- is_parenless(self) bool ¶
Check if this Function node is parenless
- is_primary_method(self) bool ¶
Check if this Function node is a primary method
- kind(self) str ¶
Get the kind of this Function node
- num_formals(self) int ¶
Get the number of formals for this Function node
- return_intent(self) str ¶
Get the return intent of this Function node
- throws(self) bool ¶
Check if this Function node is marked throws
- class chapel.FunctionSignature¶
A Chapel FunctionSignature AST node
- is_parenless(self) bool ¶
Check if this FunctionSignature node is parenless
- kind(self) str ¶
Get the kind of this FunctionSignature node
- return_intent(self) str ¶
Get the return intent of this FunctionSignature node
- throws(self) bool ¶
Check if this FunctionSignature node is marked throws
- class chapel.FunctionType¶
A Chapel FunctionType AST node
- class chapel.HeapBufferType¶
A Chapel HeapBufferType AST node
- class chapel.Identifier¶
A Chapel Identifier AST node
- name(self) str ¶
Get the name of this Identifier node
- class chapel.ImagLiteral¶
A Chapel ImagLiteral AST node
- text(self) str ¶
Get the value of this ImagLiteral node
- class chapel.ImagType¶
A Chapel ImagType AST node
- class chapel.Implements¶
A Chapel Implements AST node
- interface_name(self) str ¶
Get the interface name of this Implements node
- is_expression_level(self) bool ¶
Check if this Implements node is expression level
- type_ident(self) Optional[Identifier] ¶
Get the type identifier from this Implements node
- class chapel.Import¶
A Chapel Import AST node
- visibility(self) str ¶
Get the visibility of this Import node
- visibility_clauses(self) Iterator[VisibilityClause] ¶
Get the visibility clauses of this Import node
- class chapel.Include¶
A Chapel Include AST node
- is_prototype(self) bool ¶
Check if this Include node is for a prototype module
- name(self) str ¶
Get the name of this Include node
- visibility(self) str ¶
Get the visibility of this Include node
- class chapel.IndexableLoop¶
A Chapel IndexableLoop AST node
- is_expression_level(self) bool ¶
Check if this IndexableLoop node is expression level
- with_clause(self) Optional[WithClause] ¶
Get the WithClause of this IndexableLoop node
- class chapel.Init¶
A Chapel Init AST node
- target(self) Identifier ¶
Get the target of this Init node
- class chapel.IntLiteral¶
A Chapel IntLiteral AST node
- text(self) str ¶
Get the value of this IntLiteral node
- class chapel.IntParam¶
A Chapel IntParam AST node
- value(self) int ¶
Get the value of this integer Param
- class chapel.IntType¶
A Chapel IntType AST node
- class chapel.Interface¶
A Chapel Interface AST node
- is_formal_list_explicit(self) bool ¶
Check if this Interface node has an explicit formal list
- class chapel.IteratorType¶
A Chapel IteratorType AST node
- class chapel.Let¶
A Chapel Let AST node
- class chapel.Literal¶
A Chapel Literal AST node
- class chapel.Local¶
A Chapel Local AST node
- class chapel.Location¶
An object that represents the location of an AST node in a source file.
- clamp_left(self, arg0: Location) Location ¶
Get a new Location removes the left part of the current Location based on another Location
- end(self) Tuple[int, int] ¶
Get the line-column pair where this Location ends
- path(self) str ¶
Get the file path of this Location
- start(self) Tuple[int, int] ¶
Get the line-column pair where this Location starts
- class chapel.Loop¶
A Chapel Loop AST node
- block_style(self) str ¶
Get the block style of this Loop node
- class chapel.LoopExprIteratorType¶
A Chapel LoopExprIteratorType AST node
- class chapel.Manage¶
A Chapel Manage AST node
- class chapel.ManageableType¶
A Chapel ManageableType AST node
- class chapel.MostSpecificCandidate¶
A candidate function returned from call resolution that represents the most specific overload matching the call.
- formal_actual_mapping(self) List[int] ¶
Get the index of the function’s formal for each of the call’s actuals.
- function(self) TypedSignature ¶
Get the signature of the function called by this candidate.
- class chapel.MultiDecl¶
A Chapel MultiDecl AST node
- class chapel.NamedDecl¶
A Chapel NamedDecl AST node
- name(self) str ¶
Get the name of this NamedDecl node
- class chapel.New¶
A Chapel New AST node
- management(self) str ¶
Get the management style for this New node
- class chapel.NilType¶
A Chapel NilType AST node
- class chapel.NoneParam¶
A Chapel NoneParam AST node
- class chapel.NothingType¶
A Chapel NothingType AST node
- class chapel.On¶
A Chapel On AST node
- class chapel.OpCall¶
A Chapel OpCall AST node
- is_binary_op(self) bool ¶
Check if this OpCall node is a binary op
- is_unary_op(self) bool ¶
Check if this OpCall node is an unary op
- op(self) str ¶
Get the op string for this OpCall node
- class chapel.OpaqueType¶
A Chapel OpaqueType AST node
- class chapel.Param¶
The base type of Chapel parameters (compile-time known values)
- class chapel.PrimCall¶
A Chapel PrimCall AST node
- prim(self) str ¶
Get the primitive name for this PrimCall node
- class chapel.PrimitiveType¶
A Chapel PrimitiveType AST node
- class chapel.PromotionIteratorType¶
A Chapel PromotionIteratorType AST node
- class chapel.PtrType¶
A Chapel PtrType AST node
- class chapel.RealLiteral¶
A Chapel RealLiteral AST node
- text(self) str ¶
Get the value of this RealLiteral node
- class chapel.RealParam¶
A Chapel RealParam AST node
- class chapel.RealType¶
A Chapel RealType AST node
- class chapel.Record¶
A Chapel Record AST node
- class chapel.RecordType¶
A Chapel RecordType AST node
- class chapel.Reduce¶
A Chapel Reduce AST node
- class chapel.ReduceIntent¶
A Chapel ReduceIntent AST node
- class chapel.Require¶
A Chapel Require AST node
- class chapel.ResolvedExpression¶
Container for type information about a particular AST node.
- most_specific_candidate(self) Optional[MostSpecificCandidate] ¶
If this node is a call, return the most specific overload selected by call resolution.
- type(self) Optional[Tuple[str, Optional[ChapelType], Optional[Param]]] ¶
Retrieve the type of the expression.
- class chapel.Return¶
A Chapel Return AST node
- class chapel.Scan¶
A Chapel Scan AST node
- class chapel.Scope¶
A scope in the Chapel program, such as a block.
- class chapel.Select¶
A Chapel Select AST node
- class chapel.Serial¶
A Chapel Serial AST node
- class chapel.SimpleBlockLike¶
A Chapel SimpleBlockLike AST node
- block_style(self) str ¶
Get the block style of this SimpleBlockLike node
- class chapel.StringLikeLiteral¶
A Chapel StringLikeLiteral AST node
- value(self) str ¶
Get the value of this StringLikeLiteral node
- class chapel.StringLiteral¶
A Chapel StringLiteral AST node
- class chapel.StringParam¶
A Chapel StringParam AST node
- value(self) str ¶
Get the value of this string Param
- class chapel.Sync¶
A Chapel Sync AST node
- class chapel.SyncAuxType¶
A Chapel SyncAuxType AST node
- class chapel.TaskIdType¶
A Chapel TaskIdType AST node
- class chapel.TaskVar¶
A Chapel TaskVar AST node
- class chapel.Throw¶
A Chapel Throw AST node
- class chapel.Try¶
A Chapel Try AST node
- is_expression_level(self) bool ¶
Check if this Try node is expression level
- is_try_bang(self) bool ¶
Check if this Try node is a ‘try!’
- class chapel.Tuple¶
A Chapel Tuple AST node
- class chapel.TupleDecl¶
A Chapel TupleDecl AST node
- intent_or_kind(self) str ¶
Get the intent or kind of this TupleDecl node
- class chapel.TupleType¶
A Chapel TupleType AST node
- class chapel.TypeDecl¶
A Chapel TypeDecl AST node
- class chapel.TypeQuery¶
A Chapel TypeQuery AST node
- class chapel.TypedSignature¶
The signature of a particular function. Could include types gathered when instantiating the function
- formal_type(self, arg0: int) Optional[Tuple[str, Optional[ChapelType], Optional[Param]]] ¶
Get the type of the nth formal of this function signature
- is_instantiation(self) bool ¶
Check if this function is an instantiation of a generic function
- class chapel.UintLiteral¶
A Chapel UintLiteral AST node
- text(self) str ¶
Get the value of this UintLiteral node
- class chapel.UintParam¶
A Chapel UintParam AST node
- class chapel.UintType¶
A Chapel UintType AST node
- class chapel.Union¶
A Chapel Union AST node
- class chapel.UnionType¶
A Chapel UnionType AST node
- class chapel.UnknownType¶
A Chapel UnknownType AST node
- class chapel.Use¶
A Chapel Use AST node
- visibility(self) str ¶
Get the visibility of this Use node
- visibility_clauses(self) Iterator[VisibilityClause] ¶
Get the visibility clauses of this Use node
- class chapel.VarArgFormal¶
A Chapel VarArgFormal AST node
- class chapel.VarLikeDecl¶
A Chapel VarLikeDecl AST node
- intent(self) str ¶
Get the intent for this VarLikeDecl node
- storage_kind(self) str ¶
Get the storage kind of this VarLikeDecl node
- class chapel.Variable¶
A Chapel Variable AST node
- is_config(self) bool ¶
Check if this Variable node is a config variable
- is_field(self) bool ¶
Check if this Variable node is a class field variable
- kind(self) str ¶
Get the kind of this Variable node
- class chapel.VisibilityClause¶
A Chapel VisibilityClause AST node
- limitation_kind(self) str ¶
Get the limitation kind of this VisibilityClause node
- class chapel.VoidType¶
A Chapel VoidType AST node
- class chapel.When¶
A Chapel When AST node
- block_style(self) str ¶
Get the block style of this When node
- is_otherwise(self) bool ¶
Check if this When node uses the otherwise keyword
- class chapel.While¶
A Chapel While AST node
- class chapel.WithClause¶
A Chapel WithClause AST node
- class chapel.Yield¶
A Chapel Yield AST node
- class chapel.Zip¶
A Chapel Zip AST node
Visitor¶
This module contains utilities for defining and using visitors for chapel.AstNode
hierarchies.
- chapel.visitor.enter(method)¶
Annotates a class method as being an ‘enter’ function. An ‘enter’ function is called on a node before its children are visited. If it returns a boolean, this boolean is used to determine whether or not the children are visited. Returning ‘False’ indicates that children should be skipped; returning ‘True’ indicates that children should be visited.
The ‘exit’ function is always called, even if the children were not visited.
- chapel.visitor.exit(method)¶
Annotates a class method as being an ‘exit’ function. An ‘exit’ function is called after a node’s children were (or would have been) visited.
- chapel.visitor.visitor(clazz)¶
Marks a class as being a visitor. This will add a ‘visit’ method to the class (overriding one if it exists), which can be used to recursively traverse an AST. The behavior of the ‘visit’ method is controlled via other methods defined on the class, particularly those annotated with @enter and @exit.
The traversal proceeds by means of ‘enter’ and ‘exit’ functions; see the documentation for those functions for more information. Enter and exit functions are both expected to take a single argument in addition to ‘self’: the node type being visited. A type annotation is required, and is used to determine what type of node the function should operate on.
Replace Utilities¶
A set of utilities for performing search-and-replace operations on Chapel code, informed by Chapel’s AST.
- class chapel.replace.ReplacementContext(path: str)¶
This class is given as an argument to ‘finder’ functions so that they are able to retrieve information about the nodes and the current file. While Dyno parses the file and reports locations using line and column numbers, it does not have mappings from lines and columns to offsets in the file (which is what we need to read text). This class contains that information.
- loc_to_idx(loc: Tuple[int, int]) int ¶
Given a location (as retrieved from an AST node), convert this location into an offset in the source file.
- node_idx_range(node: AstNode) Tuple[int, int] ¶
Given a node, determine where it starts and ends in the given source file.
- chapel.replace.rename_formals(rc: ReplacementContext, fn: Function, renames: Dict[str, str])¶
Helper iterator to be used in finder functions. Given a function and a map of (‘original formal name’ -> ‘new formal name’), yields updates that perform the formal renaming.
- chapel.replace.rename_named_actuals(rc: ReplacementContext, call: Call, renames: Dict[str, str])¶
Helper iterator to be used in finder functions. Given a function call expression, and a map of (‘original name’ -> ‘new name’), yields updates that rename named actuals like the x in f(x=…).
- chapel.replace.replace(finder: Generator, ctx: Context, filename: str) str ¶
Drives replacement of text based on matches found in finder.
- chapel.replace.run(finder: Generator, name: str = 'replace', description: str = 'A tool to search-and-replace Chapel expressions with others')¶
Start a command-line replacer program with the given ‘finder’ function. This program will automatically support accepting a list of files on the command line, and two command-line options.
The first option is ‘–suffix’, used for out-of-place substitutions: the new file will be called ‘.chpl.thesuffix’. The default suffix value is ‘new’.
The second option is ‘–in-place’, used to perform in-place (modifying) substitutions on files.
- chapel.replace.fuse(*args)¶
Combines multiple ‘finder’ iterators into one.
LSP Utilities¶
This module contains utility functions for working with Chapel compiler types and the Language Server Protocol.
- chapel.lsp.location_to_range(location) Range ¶
Convert a Chapel location into a lsprotocol.types Range, which is used for e.g. reporting diagnostics.
- chapel.lsp.error_to_diagnostic(error) Diagnostic ¶
Convert a Chapel error into a lsprotocol.types Diagnostic