Re: [eclipse-clp-users] Macro expansion, C interface

From: Joachim Schimpf <>
Date: Mon, 26 Jul 2010 14:38:35 +1000 wrote:
> Hi Eclipse users,
> I have a question about macro expansion, is there a way to make macro
> expansion work while creating terms or calling a goal via the C interface ?

Macro expansion normally happens in the parser, i.e. immediately when text
(from a file, string, etc) is converted into term structures.  When you
use the C interface, then there is no parsing, thus no macro expansion.

> If I compile the code below and call the main/2 (like in the commented
> line) through the TCL/Tk gui or command line it works fine,
> but if I load the code by the C interface, construct the very same goal
> and invoke it, the macro expansion does not get triggered.
> Is there a way to make it work without explicit macro expansion or
> explicitly calling update_struct/4?

No, the C interface has no way of constructing a declared structure "directly".
But I suppose you are aware that something like test_struct{field2:foo} is
just pretty syntax for test_struct(_,foo), and the transformation is done
according to the struct-declaration.

Although it is possible to make your code work (see below), I'd recommend
that for the interfacing between C and ECLiPSe you choose simple data structures,
list flat lists or arrays of numbers.  These are easy to construct and analyse
in C, and can then be easily converted from/to more complex ECLiPSe structures
on the ECLiPSe side.  In your example, you may want to pass a list of field1
parameters, and a list of field2 parameters, and create a list of structures
on the ECLiPSe side.

Our standard advice on this mailing list: do not try to program ECLiPSe through
the C/Java/etc interface - use it only to pass parameters in and results out.

> :-module(main).
> tr_structure(structure(StructName,FieldList),Struct):-
> 	update_struct(StructName, FieldList, _Old, Struct), true.
> :- export macro(structure/2, tr_structure/2, []).
> :- export struct(test_struct(field1,field2)).
> %main(structure(test_struct, [field1 : 1, field2 : 2]), Out)
> main(TestStruct,Field2):-
> 	writeln(TestStruct),
> 	TestStruct = test_struct{ field2:Field2 }.

Although not recommended, you could make this work with an explicit call to
expand_macros/2 in the following way:

:- export struct(test_struct(field1,field2)).

%main(structure(test_struct, [field1 : 1, field2 : 2]), Out)
main(StructName, Fields, Field2) :-
	expand_macros(no_macro_expansion(with(StructName,Fields)), TestStruct),
	TestStruct = test_struct{ field2:Field2 }.

[see for an explanation of with/2]

However, this is not very different from what I recommended above, because
you have to construct an auxiliary list [field1 : 1, field2 : 2] on the C side,
which then needs to be converted to a list of structures on the ECLiPSe side.

If you really wanted to construct the structures directly in the C code, you
would have to query the struct declaration:

?- current_struct(test_struct, Prototype).
Prototype = test_struct(field1, field2)

and use that information in your C code to construct test_struct structures with
correct arity and argument positions according to the prototype.

-- Joachim
Received on Mon Jul 26 2010 - 04:36:14 CEST

This archive was generated by hypermail 2.2.0 : Thu Feb 02 2012 - 02:31:58 CET