Here is a small example of debugging with this feature:

signature
constructors
Foo: Bar -> Foo
Bar: Integer -> Bar

strategies
constructor-build-Foo(build-Bar) = // user-defined strategy to Build a Foo contructor
![<build-Bar; ?Bar(_)>]

constructor-build-Bar(build-Integer) = // user-defined strategy to Build a Bar contructor
![<build-Integer; (is-int <+ is-string; string-to-int)>]

// same could exists for
// constructor-match-* and constructor-congruence-*

main =
 !Foo(Bar(4))  // works

; debug
; !Foo(Bar(“4”)) // works
; debug
; !Foo(Bar([])) // fails
; debug

will print:
Foo(Bar(4))
Foo(Bar(4))
rewriting failed: …

This feature could be helpful to handle some strategies:

hashtable-init = !Hashtable([]) // will call constructor-build-Hashtable
hashtable-getlist = ?Hashtable(list); !list // will call constructor-match-Hashtable
hashtable-modify(s) = Hashtable(s) // will call constructor-congruence-Hashtable

or to handle references by working with the Ref constructor only and using congruences to modify the content of the Reference without creating a new reference.

Submitted on 17 April 2008 at 16:30

On 17 April 2008 at 17:32 Jira commented:

STR-755, karltk:
Being able to hook into many of Stratego’s basic operations, including ! and ?, is very useful.

For example, by hooking into ?, we can get active patterns. By hooking into ! and ? at the same time, we can get term views (i.e., we can abstract over terms at runtime in a manner complementary to overlays).

By hooking into one/some/all, we can traverse over non-ATerm structures.

By hooking into the combinators, variable binding, and traversal operators, we can arrive at various variants of graph rewriting that do or do not have side-effects.

We’ve been investigating this path to some extent before. Using aspects, such as that provided AspectStratego, we can reach the hooks/variation points in a relatively principled manner. The example you show above can be expressed and dealt with pretty easily with AspectStratego, in fact:)

However, I think we should spend some time thinking and exploring this design space as found in other languages. I take some inspiration from Python and Ruby, where it is possible to (dynamically) override the basic operations necessary for calling, indexing, derefencing, hashing, etc, of “normal” objects. In other words, those languages expose their meta-model so that users may override and augment existing behaviour. There is nothing stopping us from providing a similar level of support for Stratego, but despite the immortal words of Lennart, we’re still in a pretty preformance-sensitive domain.

For Python/Ruby the hooking is done dynamically, so there is a price in performance. I think playing around with a staged approach, where we pre-compile as much as possible, and leave the rest dynamic, would be very interesting.

In my opinion, the main issue preventing us from going this direction, is the tight reliance on the ATerm interface in current C runtime, and a missing high-level compiler API to experiment with Stratego meta-programming. Thanks to Eelco’s libstrc, the second issue is quickly becoming a non-issue, and I’ve started work on the first in the pom-adapter branch. Also, we have some experience with this from Stratego/J that will come in handy.

I see that we can get both this “hookable” functionality and interesting graph-rewritings from the same basic extensions to the Stratego “meta-model”, and that these shouldn’t be that difficult to reach.

Log in to post comments