# Term\_expansion; order of execution with DCG

**URL:** <https://swi-prolog.discourse.group/t/term-expansion-order-of-execution-with-dcg/3747>\
**Category:** Help!\
**Created:** [March 20, 2021, 10:54pm UTC](https://swi-prolog.discourse.group/t/term-expansion-order-of-execution-with-dcg/3747 "2021-03-20T22:54:04Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![emacstheviking](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/emacstheviking/32/228_2.png) [@emacstheviking](https://swi-prolog.discourse.group/u/emacstheviking)\
**Post date:** [March 20, 2021, 10:54pm UTC](https://swi-prolog.discourse.group/t/term-expansion-order-of-execution-with-dcg/3747/1 "2021-03-20T22:54:04Z")

</div>

Hello,

If in a module I create some term\_expansion/2 expansions that contain DCG rules, will that work? Does term\_expansion get called repeatedly until, as I understand it, a fix(ed?)-point is reached i.e. the expansion is complete?

This is an area I have only dabbled with many months ago just to get a feel for the concept but now I return with the aim of creating some kind of DSL that can hopefully allow me to express the syntactic requirements of each reserved word in my language rather than having to crack out all the code. The language has over 80 instructions, each with its own rules and forms and I want to leverage as much power as I can get out of the Prolog machine.

I have completed the AST syntax/parse/error checking for a good half-dozen keywords and now the commonalities are beginning to make themselves known and I’d like to capitalise on that.

Any references, examples etc would be great. I have all the major Prolog books, and one of them (I forget which) has an old but understandable DCG implementation which I studied.

Thank you,  
Sean.

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [March 21, 2021, 12:09am UTC](https://swi-prolog.discourse.group/t/term-expansion-order-of-execution-with-dcg/3747/2 "2021-03-21T00:09:00Z")

</div>

The DCG rules are pre-defined as something like `system:term_expansion(Head-->Body, ...).`).

When a file is consulted, term\_expansion/2 is called on all terms repeatedly until there’s no change (see the description of expand\_term/2).

As a trivial example:

```prolog
term_expansion(foo(X), (foo(X) --> [X], bar(X))).

foo(a). % expanded to foo(a) --> [a], bar(X).
bar(X) --> [X].

```

and look at the resulting predicates:

```prolog
?- listing(foo).
foo(a, [a|A], B) :-
    bar(a, A, B).

?- listing(bar).
bar(X, [X|A], A).

```

If you want something more powerful than DCGs, you might be interested in [EDCGs](https://www.swi-prolog.org/pack/list?p=edcg) and [DCTGs](http://www.cs.cmu.edu/afs/cs/project/ai-repository/ai/lang/prolog/code/syntax/dctg/0.html) (the latter is described in [Logic Grammars](https://www.google.com/books/edition/Logic_Grammars/aCjUBwAAQBAJ?hl=en&gbpv=0) by Dahl&Abramson, with an implementation [here](http://www.cs.cmu.edu/afs/cs/project/ai-repository/ai/lang/prolog/code/syntax/dctg/)).

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [March 21, 2021, 8:09am UTC](https://swi-prolog.discourse.group/t/term-expansion-order-of-execution-with-dcg/3747/3 "2021-03-21T08:09:17Z")

</div>

> [@peter.ludemann](#):
>
> When a file is consulted, [term\_expansion/2](https://www.swi-prolog.org/pldoc/doc_for?object=term_expansion/2) is called on all terms repeatedly until there’s no change

Hmmm. Where do you read this? It is not correct, so if you found this somewhere it should be fixed. I think the description of expand\_term/2 gives the overall picture. The term expansion mechanism is a pipeline of different translation steps, each of which performs just one rewrite step. The term\_expansion/2 hooks are also handled as a pipeline. This starts at the module being loaded, followed by the `user` and finally the `system` module.

In contrast, expand\_goal/2 is also a pipeline following the same module hierarchy, but each step is executed until fixed point is reached.

---

<div class="post-metadata">

**Author:** ![emacstheviking](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/emacstheviking/32/228_2.png) [@emacstheviking](https://swi-prolog.discourse.group/u/emacstheviking)\
**Post date:** [March 21, 2021, 8:09am UTC](https://swi-prolog.discourse.group/t/term-expansion-order-of-execution-with-dcg/3747/4 "2021-03-21T08:09:56Z")

</div>

Thanks Peter!  
I checked out EDCG many months back but I have already rolled my own solution for that, it was good learning material though!

Thank you for confirming my thoughts about the repetition etc. I missed expand\_term/2 and expand\_goal/2 in the excitement!  
what a 🍋

I was deliberating as to the exact -reason- to use term\_expansion/2 instead of just creating common code and if you have any advice on that I’ll listen!

Thanks 👍

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [March 21, 2021, 7:06pm UTC](https://swi-prolog.discourse.group/t/term-expansion-order-of-execution-with-dcg/3747/5 "2021-03-21T19:06:58Z")

</div>

> [@jan](#):
>
> [expand\_goal/2](https://www.swi-prolog.org/pldoc/doc_for?object=expand_goal/2) is also a pipeline following the same module hierarchy, but each step is executed until fixed point is reached.

Oops; I got expand\_term/2 mixed up with expand\_goal/2.

Back to OP’s question: you can always do something like the following (although it’s not necessary for handling DCGs) to recursively apply term expansion to what you generate, although - unlike expand\_goal/2 - you’re responsible for it not getting into an infinite recursion

```prolog
term_expansion(foo(X), Expanded) :-
    expand_term((foo(X) --> [X], bar(X)), 
                Expanded).

```
