Skip to content

Commit

Permalink
[fortran] Support for Computed GO TO (#780)
Browse files Browse the repository at this point in the history
## Summary of Changes
- Adds CAST support for ingesting Computed GO TO
- Adds support for generating GroMEt for CAST files containing Computed
GO TOs.
- Adds a test script `test_goto_computed.py` that contains a unit test
for a small Fortran file that has a Computed GO TO.
- Fixes a small issue in the Annotated CAST generation in
`cast_to_annotated_cast.py`. This fix allows correct support of Computed
GO TOs.
- Updates CAST Visualizer to support visualizing GO TO and Label CAST
nodes.

### CAST Computed GO TO Conversion
Since the expression in Computed GO TOs evaluates to an index rather
than a label, we make a small conversion to the expression in the CAST
to support this. We utilize the _get Gromet function to handle this
indexing.

So:
```fortran
GO TO (100,200,300,400), x+y
```
gets converted to:
```python
_get(["100", "200", "300", "400"], x+y)
```

### Related issues

Resolves #698
Resolves #701
Resolves #773

---------

Co-authored-by: Tito Ferra <[email protected]> f899664
  • Loading branch information
github-actions[bot] committed Feb 2, 2024
1 parent ed60127 commit f34a021
Show file tree
Hide file tree
Showing 9,500 changed files with 243,959 additions and 238,253 deletions.
The diff you're trying to view is too large. We only load the first 3000 changed files.
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ <h3>Instance variables</h3>
<h3>Methods</h3>
<dl>
<dt id="skema.img2mml.models.decoders.xfmer_decoder.Transformer_Decoder.create_pad_mask"><code class="name flex">
<span>def <span class="ident">create_pad_mask</span></span>(<span>self, matrix: <built-in method tensor of type object at 0x7f819855b500>, pad_token: int) ‑> <built-in method tensor of type object at 0x7f819855b500></span>
<span>def <span class="ident">create_pad_mask</span></span>(<span>self, matrix: <built-in method tensor of type object at 0x7f1fce35b500>, pad_token: int) ‑> <built-in method tensor of type object at 0x7f1fce35b500></span>
</code></dt>
<dd>
<div class="desc"></div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ <h3>Class variables</h3>
<h3>Methods</h3>
<dl>
<dt id="skema.img2mml.models.encoding.positional_encoding_for_xfmer.PositionalEncoding.forward"><code class="name flex">
<span>def <span class="ident">forward</span></span>(<span>self, x: <built-in method tensor of type object at 0x7f819855b500>) ‑> <built-in method tensor of type object at 0x7f819855b500></span>
<span>def <span class="ident">forward</span></span>(<span>self, x: <built-in method tensor of type object at 0x7f1fce35b500>) ‑> <built-in method tensor of type object at 0x7f1fce35b500></span>
</code></dt>
<dd>
<div class="desc"><p>Defines the computation performed at every call.</p>
Expand Down
126 changes: 106 additions & 20 deletions api/python/skema/program_analysis/CAST/fortran/ts2cast.html
Original file line number Diff line number Diff line change
Expand Up @@ -409,15 +409,53 @@ <h1 class="title">Module <code>skema.program_analysis.CAST.fortran.ts2cast</code
source_refs=[self.node_helper.get_source_ref(node)],
)

&#34;&#34;&#34;
(keyword_statement [6, 6] - [6, 61]
(statement_label_reference [6, 13] - [6, 16])
(statement_label_reference [6, 18] - [6, 21])
(statement_label_reference [6, 23] - [6, 26])
(statement_label_reference [6, 28] - [6, 31])
(math_expression [6, 34] - [6, 61]
left: (call_expression [6, 34] - [6, 57]
(identifier [6, 34] - [6, 37])
(argument_list [6, 37] - [6, 57]
(math_expression [6, 38] - [6, 53]
left: (math_expression [6, 38] - [6, 49]
left: (parenthesized_expression [6, 38] - [6, 45]
(math_expression [6, 39] - [6, 44]
left: (identifier [6, 39] - [6, 40])
right: (identifier [6, 43] - [6, 44])))
right: (identifier [6, 48] - [6, 49]))
right: (number_literal [6, 52] - [6, 53]))
(number_literal [6, 55] - [6, 56])))
right: (number_literal [6, 60] - [6, 61])))
&#34;&#34;&#34;

def visit_keyword_statement(self, node):
# NOTE: RETURN is not the only Fortran keyword. GO TO and CONTINUE are also considered keywords
identifier = self.node_helper.get_identifier(node).lower()
if node.type == &#34;keyword_statement&#34;:
if &#34;go to&#34; in identifier:
statement_label_reference = get_first_child_by_type(node, &#34;statement_label_reference&#34;)
statement_labels = [
self.node_helper.get_identifier(child)
for child in get_children_by_types(
node, [&#34;statement_label_reference&#34;]
)
]
# If there are multiple statement labels, then this is a COMPUTED GO TO
# Those are handled as a &#34;_get&#34; access into a List of statement labels with the index determined by the expression
if len(statement_labels) &gt; 1:
expr = Call(
func=self.get_gromet_function_node(&#34;_get&#34;),
arguments=[
CASTLiteralValue(value_type=&#34;List&#34;, value=[CASTLiteralValue(value=label, value_type=&#34;List&#34;) for label in statement_labels]),
self.visit(node.children[-1]),
],
)
return Goto(label=None, expr=expr)
return Goto(
label=self.node_helper.get_identifier(statement_label_reference),
expr=None
label=statement_labels[0],
expr=None,
)
if &#34;continue&#34; in identifier:
return self._visit_no_op(node)
Expand Down Expand Up @@ -448,10 +486,8 @@ <h1 class="title">Module <code>skema.program_analysis.CAST.fortran.ts2cast</code

def visit_statement_label(self, node):
&#34;&#34;&#34;Visitor for fortran statement labels&#34;&#34;&#34;
return Label(
label=self.node_helper.get_identifier(node)
)

return Label(label=self.node_helper.get_identifier(node))

def visit_fortran_builtin_statement(self, node):
&#34;&#34;&#34;Visitor for Fortran keywords that are not classified as keyword_statement by tree-sitter&#34;&#34;&#34;
# All of the node types that fall into this category end with _statment.
Expand Down Expand Up @@ -1607,15 +1643,53 @@ <h2 class="section-title" id="header-classes">Classes</h2>
source_refs=[self.node_helper.get_source_ref(node)],
)

&#34;&#34;&#34;
(keyword_statement [6, 6] - [6, 61]
(statement_label_reference [6, 13] - [6, 16])
(statement_label_reference [6, 18] - [6, 21])
(statement_label_reference [6, 23] - [6, 26])
(statement_label_reference [6, 28] - [6, 31])
(math_expression [6, 34] - [6, 61]
left: (call_expression [6, 34] - [6, 57]
(identifier [6, 34] - [6, 37])
(argument_list [6, 37] - [6, 57]
(math_expression [6, 38] - [6, 53]
left: (math_expression [6, 38] - [6, 49]
left: (parenthesized_expression [6, 38] - [6, 45]
(math_expression [6, 39] - [6, 44]
left: (identifier [6, 39] - [6, 40])
right: (identifier [6, 43] - [6, 44])))
right: (identifier [6, 48] - [6, 49]))
right: (number_literal [6, 52] - [6, 53]))
(number_literal [6, 55] - [6, 56])))
right: (number_literal [6, 60] - [6, 61])))
&#34;&#34;&#34;

def visit_keyword_statement(self, node):
# NOTE: RETURN is not the only Fortran keyword. GO TO and CONTINUE are also considered keywords
identifier = self.node_helper.get_identifier(node).lower()
if node.type == &#34;keyword_statement&#34;:
if &#34;go to&#34; in identifier:
statement_label_reference = get_first_child_by_type(node, &#34;statement_label_reference&#34;)
statement_labels = [
self.node_helper.get_identifier(child)
for child in get_children_by_types(
node, [&#34;statement_label_reference&#34;]
)
]
# If there are multiple statement labels, then this is a COMPUTED GO TO
# Those are handled as a &#34;_get&#34; access into a List of statement labels with the index determined by the expression
if len(statement_labels) &gt; 1:
expr = Call(
func=self.get_gromet_function_node(&#34;_get&#34;),
arguments=[
CASTLiteralValue(value_type=&#34;List&#34;, value=[CASTLiteralValue(value=label, value_type=&#34;List&#34;) for label in statement_labels]),
self.visit(node.children[-1]),
],
)
return Goto(label=None, expr=expr)
return Goto(
label=self.node_helper.get_identifier(statement_label_reference),
expr=None
label=statement_labels[0],
expr=None,
)
if &#34;continue&#34; in identifier:
return self._visit_no_op(node)
Expand Down Expand Up @@ -1646,10 +1720,8 @@ <h2 class="section-title" id="header-classes">Classes</h2>

def visit_statement_label(self, node):
&#34;&#34;&#34;Visitor for fortran statement labels&#34;&#34;&#34;
return Label(
label=self.node_helper.get_identifier(node)
)

return Label(label=self.node_helper.get_identifier(node))

def visit_fortran_builtin_statement(self, node):
&#34;&#34;&#34;Visitor for Fortran keywords that are not classified as keyword_statement by tree-sitter&#34;&#34;&#34;
# All of the node types that fall into this category end with _statment.
Expand Down Expand Up @@ -3314,10 +3386,26 @@ <h3>Methods</h3>
identifier = self.node_helper.get_identifier(node).lower()
if node.type == &#34;keyword_statement&#34;:
if &#34;go to&#34; in identifier:
statement_label_reference = get_first_child_by_type(node, &#34;statement_label_reference&#34;)
statement_labels = [
self.node_helper.get_identifier(child)
for child in get_children_by_types(
node, [&#34;statement_label_reference&#34;]
)
]
# If there are multiple statement labels, then this is a COMPUTED GO TO
# Those are handled as a &#34;_get&#34; access into a List of statement labels with the index determined by the expression
if len(statement_labels) &gt; 1:
expr = Call(
func=self.get_gromet_function_node(&#34;_get&#34;),
arguments=[
CASTLiteralValue(value_type=&#34;List&#34;, value=[CASTLiteralValue(value=label, value_type=&#34;List&#34;) for label in statement_labels]),
self.visit(node.children[-1]),
],
)
return Goto(label=None, expr=expr)
return Goto(
label=self.node_helper.get_identifier(statement_label_reference),
expr=None
label=statement_labels[0],
expr=None,
)
if &#34;continue&#34; in identifier:
return self._visit_no_op(node)
Expand Down Expand Up @@ -3572,9 +3660,7 @@ <h3>Methods</h3>
</summary>
<pre><code class="python">def visit_statement_label(self, node):
&#34;&#34;&#34;Visitor for fortran statement labels&#34;&#34;&#34;
return Label(
label=self.node_helper.get_identifier(node)
)</code></pre>
return Label(label=self.node_helper.get_identifier(node))</code></pre>
</details>
</dd>
<dt id="skema.program_analysis.CAST.fortran.ts2cast.TS2CAST.visit_use_statement"><code class="name flex">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ <h1 class="title">Module <code>skema.program_analysis.CAST2FN.ann_cast.cast_to_a

@_visit.register
def visit_goto(self, node: Goto):
expr = node.expr
expr = self.visit(node.expr) if node.expr != None else None
label = node.label
return AnnCastGoto(expr, label, node.source_refs)

Expand Down Expand Up @@ -369,7 +369,7 @@ <h3>Ancestors</h3>

@_visit.register
def visit_goto(self, node: Goto):
expr = node.expr
expr = self.visit(node.expr) if node.expr != None else None
label = node.label
return AnnCastGoto(expr, label, node.source_refs)

Expand Down Expand Up @@ -579,7 +579,7 @@ <h3>Methods</h3>
</summary>
<pre><code class="python">@_visit.register
def visit_goto(self, node: Goto):
expr = node.expr
expr = self.visit(node.expr) if node.expr != None else None
label = node.label
return AnnCastGoto(expr, label, node.source_refs)</code></pre>
</details>
Expand Down
Loading

0 comments on commit f34a021

Please sign in to comment.