How to turn Prolog into preprocessor (kinda m4, gpp)? - prolog

m4 can be used with different programming languages because its default policy on unrecognised text is to output and it has a quoting mechanism required for convenient preprocessor usage. I mean, I can write preprocessed code in such a way that my IDE thinks it's Ada. m4 macro invocations (include, define) are hidden in Ada comments. Ada comments start with --, Prolog comments start with % or inside /* */. I can't mix Ada and Prolog easily.
m4 does preprocessing well enough, but its programming side sucks. I thought: why don't me try a general purpose language instead? Prolog looks like being appropriate for my tasks. Prolog has ISO standard, and logic programming looks being useful for reasoning about source generation.
So here we are: we have an arbitrary output language (Ada, then JavaScript, then maybe something else), and it would be nice to write source code in native IDEs for corresponding languages most of the time. I need preprocessor to have a proper parser (like m4 has). This parser shouldn't have Ada syntax knowledge, instead it should only know Ada lexical, and it should be possible to make its macro invocations look like Ada functions invocations.
Its command line interface should look similar to m4 or gcc -E. It should be possible to do both kinds of includes: pure Prolog source code and preprocessed code.
If you know how can I shortly achieve these goals, please write here. I can probably accept non-Prolog solutions, but among the others I prefer standard languages. m4 is part of POSIX, for example.

Prolog is an unusual choice for this task. Indeed, SWI-Prolog used to have the possibility to invoke C preprocessor - should has been removed now, because of its little usefulness.
Anyway, a DCG could be used. I would advice against it if you are not really proficient in Prolog, because debugging can be difficult:
prep(I, O) :-
phrase(exp, I, O).
exp --> mac, !, exp.
exp, [C] --> [C], exp.
exp --> [].
% macro definitions, use 'pushback' argument to change text
mac, "AAA" --> "a".
mac, "G" --> "goal".
example
?- prep("my goal is mars", X).
X = "my G is mAAArs" .
edit: from SWI-Prolog mailing list, WRT the latest release 6.3.18
MODIFIED: Deleted preprocessor/2 after discussion on the
mailinglist. Code relying on this (we hope none) can use the hook
user:prolog_load_file/2 to achieve the same result.
I think the functionality available is more or less that of #include <...>.
For macro expansion (or better, term rewrite) in Prolog there is goal_expansion or term_expansion
edit: latest release brings quasiquotations. Together with a parser in DCG could help to achieve the transformation.

Have you looked at StringTemplate? It's a part of ANTLR (compiler construction toolket). It's written in Java (though there's a C# port, among others). An ANTLR grammar can be written to target many different languages. StringTemplate is what it uses to generate code for the different target languages.
Check it out.
http://antlr.org
http://stringtemplate.org
http://www.cs.usfca.edu/~parrt/

I use DCGs to generate python scripts for FontForge (to create and maintain candlestick fonts for forex trading); I tried M4 scripts but they are not easily amenable to programming (as you mention) and difficult to merge with my glyph definitions that reside in a Prolog database.
DCGs are perceived to be mainly for parsing; but I find they are like a templating engine on their own.

Related

SWI-prolog semweb library processing of URI

Being new to prolog I am reading existing code (as well as trying to write some code). Having some prior background in semweb I started to play with it and see something that is confusing me. Example assertion:
?- rdf_assert(ex:bob, rdf:type, foaf:'Person').
I also did find the following in the documentation:
Remember: Internally, all resources are atoms. The transformations
above are realised at compile-time using rules for goal_expansion/2
provided by the rdf_db library
Am I correct in assuming that somehow the library is treating the three URIs as atoms? I thought that the compiler would treat this as module_name:predicate, but that does not seem to be the case. If that is true, could you please provide a simple example on how this could be done in prolog?
Thanks
Prolog is not a functional language. This implies 2+3 does not evaluate to 5 and is just a term that gets meaning from the predicate that processes it. Likewise, ex:bob is just a term that has no direct relations to modules or
predicates. Only predicates such call/1 will interpret this as "call bob in the module ex".
Next to that, (SWI-)Prolog (most Prolog's, but not all) have term expansion that allows you to rewrite the term that is read before it is handed to the compiler. That is used to rewrite the argument of rdf/3: each appearance of prefix:local is expanded to a full atom. You can check that by using listing/1 on predicates that call rdf/3 using the prefix notation.
See also rdf_meta

CL/Scheme DSELs with non-lisp syntax

I have been curious lately about DSLs, specifically, how to implement them in Lisp,
since it looks like a piece of cake compare to the alternatives.
Looking for information I cannot find any evidence of a non-lisp DSEL in Lisp in internet.
So my question is:
Is it possible to implement a DSL with non-lisp syntax in lisp with the use of macros?
How is this achieved?
Can the reader of lisp be replaced by a custom reader that translates code to lisp structure?
If the former is true: is this a common way to implement "non-lispy" DSELs?
Short version: Racket does this.
In more detail: Racket, a descendant of Scheme, has a really well-thought-out story here. A Racket module/file can begin with a language declaration, e.g.
#lang algol60
... and then the rest of the file can be written in the given language. (Yes, algol60 is built in.)
In order to develop your own language, you need to write a package that is a language specification, that shows how to expand the syntax of this language into the syntax of the underlying language (in this case, Racket). Anyone can write such packages, and then distribute them to allow others to write programs in this language. There are examples of such language specifications included with Racket, e.g. the algol 60 example mentioned earlier.
I think this is exactly what you're asking for?
ObDisclaimer: Yes, I am a Racket developer.
How do you implement the surface language of a programming language? You write a parser or use a parser generator. You can do that in Lisp, too.
There are many examples of general purpose and domain specific languages written in Lisp - not using s-expression syntax.
Historically the first ML (an extension language for a theorem prover) was written in Lisp. Macsyma (a language for computer algebra) is written in Lisp. In many cases there is some kind of 'end user', for which a non-s-expression language needs to be written/supported. Sometimes there are languages which exist and need to be supported.
Using macros and read macros you can implement some languages or extend the Lisp language. For example it is easy to add JSON syntax to Lisp using a read macro. Also some kind of infix syntax. XML (example: XMLisp).
There's no problem in supporing non-Lisp syntax DSLs in Lisp. You'll need to use some parser/parser generator library as Rainer has mentioned. A good example is esrap that is used to parse markdown (see 3bmd) and also for the pgloader command language which is just an example of an external DSL you're asking about.
From Let Over Lambda, there is an implementation of Perl style regular expressions: http://letoverlambda.com/index.cl/guest/chap4.html#sec_4.
Also there are several attempts at making a "non-lispy" version of Lisp, the main one being the Readable Lisp S-expression Project: http://readable.sourceforge.net/.
One implementation-specific solution that sticks out (if you want to use Scheme rather than CL) is Gambit Scheme's built-in support for infix syntax via its SIX-script extension.
This provides a rich set of loosely C-like operators and syntax forms, which can either be used out-of-the-box to write code in a C-like style, or redefined to mean whatever you want (you can easily redefine e.g. the function definition format, if you aren't a fan of type name(args) {}). for, case, := and so on (even goto) are all already present and ready to mean whatever you need.
The actual core of the syntax (operator precedence, expressions vs. statements) is fixed, but you can assign things like a Scheme binding construct to the s-expression produced by an operator for a reasonably large amount of freedom.
a = b * c;
is translated by the reader into
(six.x=y (six.identifier a) (six.x*y (six.identifier b) (six.identifier c)))
You can then override the definitions of those macros with your own to make the syntax do whatever you want. Turning the C-style base into a Haskell-looking functional language isn't too hard (strategically redefine = and -> and you're halfway there...).

Workaround ensure_loaded/1 GNU Prolog?

Is there a workaround to make ensure_loaded/1 work
in GNU Prolog as it works in many other Prolog systems?
The goal is to have a preamble so that the rest of
code can use ensure_loaded/1 independent of whether which
Prolog system I use.
I tried the following:
:- multifile(term_expansion/2).
term_expansion((:- ensure_loaded(X)),
(:- atom_concat('<base>\\', X, Y),
include(Y))).
But the following query doesn't work:
:- ensure_loaded('suite.p').
The path calculation itself is not the issue of the question,
but the redefinition of a directive in GNU Prolog. There is
another directive that causes problems: meta_predicate/1. The
byte code crashes as follows:
Bye
A partial solution is:
ensure_loaded(File) :-
absolute_file_name(File, Path),
( predicate_property(_, prolog_file(Path)) ->
true
; consult(Path)
).
It assumes that the file defines at least one predicate but that's a sensible assumption. However, there's seems to be no way to override the native, non-functional, definition of the ensure_loaded/1 directive. A workaround would be to wrap the ensure_loaded/1 directive within an initialization/1 directive. For example:
:- initialization(ensure_loaded('suite.pl')).
Hence this being a partial solution as we're really defining an ensure_loaded/1 predicate, not a directive.
My current speculation is, that it is impossible with
the standard distribution of GNU Prolog 1.4.4. The
docu says:
The GNU Prolog compiler (section 4.4) automatically calls
expand_term/2 on each Term1 read in. However, in the current release,
only DCG transformation are done by the compiler (i.e.
term_expansion/2 cannot be used). To use term_expansion/2, it is
necessary to call expand_term/2 explicitly.
I also tried to inject some Prolog code for term_expansion/2
via the command line, but to no awail. Although the tool chain
has options such as -O, -L, -A that pass options to other tools.
There is not really an option that passes a Prolog text to the
pl2wam, in course of the execution of a consult/1 issued inside
the top-level.
At least this are my results so far.
Bye

Is it acceptable for a prolog procedure to work only one way?

I have a prolog program:
link(liverpool,preston).
link(liverpool,manchester).
link(preston,lancaster).
link(preston,manchester).
link(lancaster,carlisle).
link(lancaster,leeds).
link(carlisle,leeds).
link(manchester,leeds).
%checks to see if X is in the supplied list
inlist( X, [X|_]).
inlist( X, [_|Ys]) :- inlist( X, Ys).
merge([],L,L).
merge([H|T],BList,CList):-
inlist(H,BList),
merge(T,BList,CList).
merge([H|T],BList,[H|CList]):-
merge(T,BList,CList),
not(inlist(H,BList)).
Merge works if I call it like this:
merge([a,b,c],[d,e,f],Result). --> [a,b,c,d,e,f]
or more importantly, what it was designed to solve:
merge([a,b,c],[a,d,e,f],Result). --> [a,b,c,d,e,f]
but if I call merge like this:
merge(X,[d,e,f],[a,b,c,d,e,f]).
There is a stack overflow. Is this generally acceptable behavior for a function that is designed to work one way? Or is there some convention that functions should work in both ways?
Edit: merge works if you call it like this:
merge([a,b,c],X,[a,b,c,d,e,f]). --> [d,e,f]
First, you should not call these "functions". "Predicates" is the correct term.
It's generally desirable for Prolog predicates to work "both ways". But it's not always possible or worth the effort in a particular situation.
To inform about ways a predicate is intended to be used mode-declarations can be used. These declarations conventions are different from system to system. These declarations are mostly serve as a documentation for programmers and rarely used by compilers, but can be used by testing frameworks and other helper tools.
Examples of conventions for mode declarations:
SWI-Prolog: http://www.swi-prolog.org/pldoc/man?section=modes
ECLiPSe CLP: http://eclipseclp.org/doc/applications/tutorial003.html#toc10 (scroll to 2.7.3 Mode declaration)
Also there is a convention (described in "The Craft of Prolog", for example) that input parameters of a predicate come first, output parameters come last.

Writing ontologies in DL syntax?

I just discovered OWL and Protege. Upon reading through this reference page (which I quote below), I am left wondering whether it is possible to not use the abstract OWL syntax, and rather to write in DL syntax. My background is in logic, so it sounds like it would be more fun even if I would have to translate the ontologies later (though I am sure there must be applications to do this--besides, don't reasoners use DL?).
If it is possible, what configuration of settings should I use in Protege (or other software of your suggestion) in order to do this? I suspect it's not possible, but I want to be sure, as I see no good reason for this other than the awkwardness of special symbols.
EDIT: If it is NOT possible, how exactly are DL languages used?
OWL DL is the description logic SHOIN with support of data values, data types
and datatype properties, i.e., SHOIN(D), but since OWL is based on RDF(S), the
terminology slightly differs. ... For description of OWL ontology or knowledge
base, the DL syntax can be used. There is an "abstract" LISP-like syntax
defined that is easier to write in ASCII character set.
Here's a very brief working example of the two syntax styles for the same data.
don't reasoners use DL?
Not necessarily. They use all kinds of logics, some of which are DLs, some are not.
If it is possible, what configuration of settings should I use in Protege (or other software of your suggestion) in order to do this?
I'm pretty sure there is no such pluggin for Protégé. But if you really want some fun, use a text editor and write your ontology by hand. There are many syntaxes you can use: the functional syntax, the OWL/XML syntax, the RDF/XML syntax are all normative. In addition, you can use the Manchester syntax, Turtle, N-Triples, JSON-LD, that will be future recommendations for writing RDF (and therefore OWL). Or the more exotic RDF/JSON, HDT. Or again, more "powerful" syntaxes like Notation3, TriG, TriX, NQuads. Plenty of fun!
In any case, if you would like to write in the DL syntax, you would need to use special Unicode characters or special commands like in LaTeX for instance. And the parser that deals with it would have to read those characters or commands. Not ideal if you are programming. But you can always use the DL syntax in your writings.
BTW, the current standard Web Ontology Language is OWL 2. Its DL variant (viz., OWL 2 DL) is based on the even more irresistible SROIQ.

Resources