Skip to content

Commit

Permalink
change starting comment into module doctring
Browse files Browse the repository at this point in the history
  • Loading branch information
Forthoney committed Oct 26, 2023
1 parent 55bd4df commit 4ab14e5
Showing 1 changed file with 62 additions and 36 deletions.
98 changes: 62 additions & 36 deletions compiler/shell_ast/ast_to_ast.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
"""
AST to AST transformation
The preprocessing pass replaces all _candidate_ dataflow regions with
calls to PaSh's runtime to let it establish if they are actually dataflow
regions. The pass serializes all candidate dataflow regions:
- A list of ASTs if at the top level or
- an AST subtree if at a lower level
The PaSh runtime then deserializes the(m, compiles them (if safe) and optimizes them.
"""

from env_var_names import *
from shell_ast.ast_util import *
from shell_ast.preprocess_ast_cases import preprocess_node
from shell_ast.transformation_options import AbstractTransformationState

##
## Preprocessing
##

## The preprocessing pass replaces all _candidate_ dataflow regions with
## calls to PaSh's runtime to let it establish if they are actually dataflow
## regions. The pass serializes all candidate dataflow regions:
## - A list of ASTs if at the top level or
## - an AST subtree if at a lower level
##
## The PaSh runtime then deserializes the(m, compiles them (if safe) and optimizes them.


## Replace candidate dataflow AST regions with calls to PaSh's runtime.
def replace_ast_regions(ast_objects, trans_options: AbstractTransformationState):
"""
Replace candidate dataflow AST regions with calls to PaSh's runtime.
"""
preprocessed_asts = []
candidate_dataflow_region = []
last_object = False
Expand All @@ -27,12 +30,12 @@ def replace_ast_regions(ast_objects, trans_options: AbstractTransformationState)
## If we are working on the last object we need to keep that in mind when replacing.
##
## The last df-region should not be executed in parallel no matter what (to not lose its exit code.)
if (i == len(ast_objects) - 1):
if i == len(ast_objects) - 1:
# log("Last object")
last_object = True

ast, original_text, _linno_before, _linno_after = ast_object
assert(isinstance(ast, AstNode))
assert isinstance(ast, AstNode)

## Goals: This transformation can approximate in several directions.
## 1. Not replacing a candidate dataflow region.
Expand All @@ -51,60 +54,83 @@ def replace_ast_regions(ast_objects, trans_options: AbstractTransformationState)
## then the second output is true.
## - If the next AST needs to be replaced too (e.g. if the current one is a background)
## then the third output is true
preprocessed_ast_object = preprocess_node(ast, trans_options, last_object=last_object)
preprocessed_ast_object = preprocess_node(
ast, trans_options, last_object=last_object
)
## If the dataflow region is not maximal then it implies that the whole
## AST should be replaced.
assert(not preprocessed_ast_object.is_non_maximal()
or preprocessed_ast_object.should_replace_whole_ast())
assert (
not preprocessed_ast_object.is_non_maximal()
or preprocessed_ast_object.should_replace_whole_ast()
)

## If the whole AST needs to be replaced then it implies that
## something will be replaced
assert(not preprocessed_ast_object.should_replace_whole_ast()
or preprocessed_ast_object.will_anything_be_replaced())
assert (
not preprocessed_ast_object.should_replace_whole_ast()
or preprocessed_ast_object.will_anything_be_replaced()
)

## If it isn't maximal then we just add it to the candidate
if(preprocessed_ast_object.is_non_maximal()):
candidate_dataflow_region.append((preprocessed_ast_object.ast,
original_text))
if preprocessed_ast_object.is_non_maximal():
candidate_dataflow_region.append(
(preprocessed_ast_object.ast, original_text)
)
else:
## If the current candidate dataflow region is non-empty
## it means that the previous AST was in the background so
## the current one has to be included in the process no matter what
if (len(candidate_dataflow_region) > 0):
candidate_dataflow_region.append((preprocessed_ast_object.ast,
original_text))
if len(candidate_dataflow_region) > 0:
candidate_dataflow_region.append(
(preprocessed_ast_object.ast, original_text)
)
## Since the current one is maximal (or not wholy replaced)
## we close the candidate.
dataflow_region_asts, dataflow_region_lines = unzip(candidate_dataflow_region)
dataflow_region_asts, dataflow_region_lines = unzip(
candidate_dataflow_region
)
dataflow_region_text = join_original_text_lines(dataflow_region_lines)
replaced_ast = trans_options.replace_df_region(dataflow_region_asts,
ast_text=dataflow_region_text, disable_parallel_pipelines=last_object)
replaced_ast = trans_options.replace_df_region(
dataflow_region_asts,
ast_text=dataflow_region_text,
disable_parallel_pipelines=last_object,
)
candidate_dataflow_region = []
preprocessed_asts.append(replaced_ast)
else:
if(preprocessed_ast_object.should_replace_whole_ast()):
replaced_ast = trans_options.replace_df_region([preprocessed_ast_object.ast],
ast_text=original_text, disable_parallel_pipelines=last_object)
if preprocessed_ast_object.should_replace_whole_ast():
replaced_ast = trans_options.replace_df_region(
[preprocessed_ast_object.ast],
ast_text=original_text,
disable_parallel_pipelines=last_object,
)
preprocessed_asts.append(replaced_ast)
else:
## In this case, it is possible that no replacement happened,
## meaning that we can simply return the original parsed text as it was.
if(preprocessed_ast_object.will_anything_be_replaced() or original_text is None):
if (
preprocessed_ast_object.will_anything_be_replaced()
or original_text is None
):
preprocessed_asts.append(preprocessed_ast_object.ast)
else:
preprocessed_asts.append(UnparsedScript(original_text))

## Close the final dataflow region
if(len(candidate_dataflow_region) > 0):
if len(candidate_dataflow_region) > 0:
dataflow_region_asts, dataflow_region_lines = unzip(candidate_dataflow_region)
dataflow_region_text = join_original_text_lines(dataflow_region_lines)
replaced_ast = trans_options.replace_df_region(dataflow_region_asts,
ast_text=dataflow_region_text, disable_parallel_pipelines=True)
replaced_ast = trans_options.replace_df_region(
dataflow_region_asts,
ast_text=dataflow_region_text,
disable_parallel_pipelines=True,
)
candidate_dataflow_region = []
preprocessed_asts.append(replaced_ast)

return preprocessed_asts


## This function joins original unparsed shell source in a safe way
## so as to deal with the case where some of the text is None (e.g., in case of stdin parsing).
def join_original_text_lines(shell_source_lines_or_none):
Expand Down

0 comments on commit 4ab14e5

Please sign in to comment.