A compiler targeting CSH scripts with csp_proc from .json source syntax files.
Setup a virtual environment and install requirements:
python3 -m venv .venv
source venv/bin/activate
pip install -r requirements.txt
pip install --editable .proc_comp is developed as a Python package. This allows splitting it into multiple modules (files).
Below, the steps done by the compiler is described. Cleanup still needed and function names might not be correct, but this is the main idea:
---From frontend--> General language/JSON
---parser--> intermediary representation/abstract syntax
---codegen--> CSH command representation split into proc functions, and building a control flow graph
---cfg.calc_liveness--> Analyse the control flow graph for parameter liveness. Calculate a colored graph for reuse of general purpose parameters.
---codegen.assign_params--> Replace placeholder params with general purpose params found with coloring
---codegen.assign_slots--> Analyse which slots are available and update the slot names correspondingly
---codegen.output--> Generate and output list of resulting CSH script
To add compiler support for a new type of block, the following modifications should be made:
- Add a new expression type (can be omitted if the new block reuses existing types)
- Define attributes and the constructor as necessary
- Define
__str__()to help debugging the parser output - Implement
__pprint__()if additional data or lines should be printed when pretty printing
- Add an item to the expression map in
parser.py. Define the expression's attributes and set the expression as a lambda function that takes the parser function and expression block object and returns the Expression. - If the expression uses an undefined CSH command, define it in
csh.py. If the command uses or sets any (general purpose) parameters, set theself._cfg_instructioncorrespondingly -- see e.g.ProcUnopfor an example. - Lastly, create a new match case in
codegen.py's_code_gen(), and add the corresponding procedure instructions. If branching control flow is introduced, it is important to keep the control flow graph up to date. Most importantly is ensuring it actually branches properly out and that predecessors and successors are correct. Whilecfg.block_nextsets the immediate predecessor automatically others still need to be handled manually. This is done in theif-elsecase as an example.
usage: proc_comp.py [-h] [--output OUTPUT] [--verbose] [--log-file LOG_FILE] input
positional arguments:
input Input file
options:
-h, --help show this help message and exit
--output OUTPUT, -o OUTPUT
Output file
--verbose, -v Enable verbose mode
--log-file LOG_FILE, -l LOG_FILE
Set logging to file instead of stdout/stderr
- (GPIO) Set GPIO high/low
- (CSH) custom code
- (CSH) get param
- (CSH) set param
- (proc) management
proc newproc delproc pullproc pushproc sizeproc popproc listproc slotsproc run
- (proc) Control flow
proc block <param a> <binop> <param b>proc ifelse <param a> <binop> <param b>proc noopproc set <param> <value>proc unop <param> <unop> <result>proc binop <param a> <binop> <param b> <result>proc call <procedure slot>