# adl-rewrite-raw-syntax-parsetree.api
#
# Motivation
# ==========
#
# One of the most useful of the standard-library list
# functions is 'map', which does a pointwise transform
# of a given list via a client-supplied function which
# supplies the per-element transform.
#
# 'map' is useful because it encapsulates the busywork
# of traversing the original list and constructing the
# result list -- work common to all pointwise list
# transformations -- exposing only the per-element transform
# function itself, which is the part which changes from
# on list transform to another. (This is the opposite
# of the OOP dictum to "encapsulate the part that changes"!)
#
#
# Overview
# ========
#
# Our idea here is to similarly provide support for doing
# pointwise transforms of raw syntax parsetrees, encapsulating
# all the busywork of doing a recursive dagwalk of the original
# parsetree and building up the replacement parsetree, leaving
# the client code only to supply the pointwise per-element
# transformation.
#
# A critical difference is that all the elements
# of a list are of the same type, whereas our raw
# syntax parsetrees have elements of five different
# types:
#
# Expression
# Decl
# Pattern
# Package_Exp
# Type
#
# We handle this by having the client supply us with
# five transform functions, one for each element type.
#
# In practice, typically the client is only interested
# in transforming one of the five node types, hence
# provides only one "real" transform function; we supply
# a "no-op" function for client use in the other four
# cases.
#
# As a final twist, it turns out that sometimes the client
# per-element function needs to be able to do a recursive
# rewrite of a complete subtree rather than just a single
# element, perhaps because a replacement subtree is being
# pulled out of a symboltable or whatever.
# Strictly speaking this doesn't fit our paradigm, but
# it is pragmatically useful to support this need, so when
# we call client pointwise functions we supply not only the
# element to be transformed, but also the internal transform-a-subtree
# dagwalk function for elements of this type.
#
# Anyhow, in summary, typical protocol for using this library looks like
#
# package rrs = adl_rewrite_raw_syntax_parsetree; # adl_rewrite_raw_syntax_parsetree is from
src/lib/compiler/back/low/tools/adl-syntax/adl-rewrite-raw-syntax-parsetree.pkg# ...
# fun rewrite_type_node recursive_tree_rewrite typenode # 'recursive_tree_rewrite' does a recursive rewrite of a raw syntax parsetree with a typenode as root.
# = # 'recursive_tree_rewrite' is usually ignored (_) but occasionally useful when a fresh recursive parsetree rewrite is needed.
# ...
#
# new_typetree
# =
# fns.rewrite_type_parsetree old_typetree
# where
# fns = rrs::make_raw_syntax_parsetree_rewriters [ rrs::REWRITE_TYPE_NODE rewrite_type_node ];
# end;
#
# See also:
#
src/lib/compiler/front/parser/raw-syntax/map-raw-syntax.api# Compiled by:
#
src/lib/compiler/back/low/tools/sml-ast.libstipulate
package raw = adl_raw_syntax_form; # adl_raw_syntax_form is from
src/lib/compiler/back/low/tools/adl-syntax/adl-raw-syntax-form.pkgherein
# This api is implemented in:
#
src/lib/compiler/back/low/tools/adl-syntax/adl-rewrite-raw-syntax-parsetree.pkg #
api Adl_Rewrite_Raw_Syntax_Parsetree {
#
# This is the type of a client-supplied function
# performing some application-specific transform
# on raw syntax tree nodes of a given type:
#
Node_Rewrite_Fn(X) # X will be one of raw::Expression, raw::Decl, raw::Package_Exp, raw::Pattern, raw::Type
=
(X -> X) # Recursive parsetree-rewriter function synthesized by our package. (Usually ignored.)
-> X # The parsetree node to transform. This is (normally) a node-local operation, not a recursive dagwalk.
-> X; # The transformed parsetree node.
# These are the five types of functions which a client package
# can supply to customize the operation of the synthesized
# parsetree recursive-rewrite functions:
#
Rewrite_Node_Fn
= REWRITE_EXPRESSION_NODE Node_Rewrite_Fn( raw::Expression )
| REWRITE_DECLARATION_NODE Node_Rewrite_Fn( raw::Declaration )
| REWRITE_STATEMENT_NODE Node_Rewrite_Fn( raw::Package_Exp )
| REWRITE_PATTERN_NODE Node_Rewrite_Fn( raw::Pattern )
| REWRITE_TYPE_NODE Node_Rewrite_Fn( raw::Type )
;
# These are the five parsetree recursive-rewrite functions which
# we synthesize and return to the client:
#
Rewrite_Parsetree_Fns
=
{ rewrite_expression_parsetree: raw::Expression -> raw::Expression,
rewrite_declaration_parsetree: raw::Declaration -> raw::Declaration,
rewrite_statement_parsetree: raw::Package_Exp -> raw::Package_Exp,
rewrite_pattern_parsetree: raw::Pattern -> raw::Pattern,
rewrite_type_parsetree: raw::Type -> raw::Type
};
# This is our actual client-callable entrypoint:
#
make_raw_syntax_parsetree_rewriters: List(Rewrite_Node_Fn) -> Rewrite_Parsetree_Fns; # Given fns which rewrite individual parsetree nodes, produce fns which recursively rewrite complete parsetrees.
};
end;