/* File: prolog2hilog.c
** Author(s): kifer
** Contact: flora-users@lists.sourceforge.net
**
** Copyright (C) The Research Foundation of SUNY, 2000
**
** FLORA-2 is free software; you can redistribute it and/or modify it under the
** terms of the GNU Library General Public License as published by the Free
** Software Foundation; either version 2 of the License, or (at your option)
** any later version.
**
** FLORA-2 is distributed in the hope that it will be useful, but WITHOUT ANY
** WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
** FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for
** more details.
**
** You should have received a copy of the GNU Library General Public License
** along with FLORA-2; if not, write to the Free Software Foundation,
** Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
** $Id: prolog2hilog.c,v 1.14 2003/06/18 07:01:26 kifer Exp $
**
*/
#include "xsb_config.h"
#include <stdio.h>
#include <string.h>
#ifdef WIN_NT
#define XSB_DLL
#endif
#include "auxlry.h"
#include "cell_xsb.h"
#include "error_xsb.h"
#include "cinterf.h"
#define FLORA_META_PREFIX "_$_$_flora'mod"
#define FLORA_LIB_PREFIX "fllib"
#define FLORA_META_PREFIX_LEN 14
#define FLORA_LIB_PREFIX_LEN 5
#if 0
#define P2HDEBUG
#define P2HDEBUG_VERBOSE
#endif
/* take hilog term and a hilog apply op and return prolog term.
If the apply term is != the one used in the hilog term, assume it is already
a prolog term and don't convert */
static prolog_term hilog2prolog(prolog_term hterm, char *apply, int unify_vars);
/* take prolog term and a symbol name of the apply operator and return hilog
term. If prolog term already has the main functor==hilog apply, then don't
convert. */
static prolog_term prolog2hilog(prolog_term pterm, char *apply, int unify_vars);
static char *pterm2string(prolog_term term);
inline static int is_hilog(prolog_term term, char *apply_funct);
inline static int is_special_form(prolog_term term);
inline static int is_formula(prolog_term term);
static prolog_term map_special_form(prolog_term (*func)(), prolog_term term, char *apply, int unify_vars);
static prolog_term map_list(prolog_term func(), prolog_term term, char *apply, int unify_vars);
/*
When called from Prolog, takes 3 args:
- Pterm: Prolog term
- Hterm: HiLog term
- Apply: Symbol name for the HiLog apply predicate
- UnifyGlag: If true, unify if both Pterm and Hterm are variables
If Pterm is a variable, then it is unified with Hterm.
If Hterm is a variable, then it is unified with Pterm.
If both Pterm and Hterm are scalar (int, float, string), then they are
unified.
If Pterm or Hterm is a list or a commalist (a,b,c,), then the function is
applied to each element and the results are returned as a list or a commalist
(whichever applies).
If Hterm is term (and not a list or a commalist), then Hterm is assumed to be
a HiLog term of the kind that converts to Prolog. Hterm is then converted to
Prolog and the result is unified with Pterm. If the main functor is !=
Apply, then it is assumed to be a prolog term and the term is returned
without conversion.
If Pterm is a term that is not a list or a commalist, then it is assumed to
be a prolog term. It is converted to HiLog using the apply-functor name given
in Apply (which must be an atom). The result then unifies with Hterm. If
the main functor is = Apply, then we assume that the term is already a HiLog
term and the term is simply returned without change.
For instance,
flora_plg2hlg(f(a,g(b,X)),Y,abc)
Y = abc(f,a,abc(g,b,_h123))
flora_plg2hlg(X, cde(f,a,cde(g,b,Y))),Z)
X = abc(f,a,abc(g,b,_h123))
Z = abc
Doesn't do occur-check!!! Something like
flora_plg2hlg(X, cde(f,a,cde(g,b,X))),Z)
Will loop and eventually crash because X occurs in Pterm and in Hterm.
*/
DllExport xsbBool call_conv flora_plg2hlg () {
prolog_term pterm = reg_term(1);
prolog_term hterm = reg_term(2);
prolog_term apply_t = reg_term(3);
int unify_vars = ptoc_int(4); /* whether to unify if both args are vars */
prolog_term temp_term;
char *apply;
#ifdef P2HDEBUG_VERBOSE
xsb_dbgmsg("flora_plg2hlg: Arg1=%s", pterm2string(pterm));
xsb_dbgmsg("flora_plg2hlg: Arg2=%s", pterm2string(hterm));
xsb_dbgmsg("flora_plg2hlg: Arg3=%s", pterm2string(apply_t));
#endif
if (!is_atom(apply_t))
xsb_abort("PLG2HLG: Arg 3 = `%s' (the `apply' functor) isn't an atom.",
pterm2string(apply_t));
apply = string_val(apply_t);
/* both are variables */
if (is_var(pterm) && is_var(hterm)) {
if (unify_vars)
return p2p_unify(pterm,hterm);
else
return TRUE;
}
/* if hilog is instantiated, convert from hilog to prolog
and unify, because hilog->prolog conversion is more accurate */
if (!is_var(hterm)) {
temp_term = hilog2prolog(hterm, apply,unify_vars);
return p2p_unify(temp_term, pterm);
}
/* hterm is a variable and pterm is not */
temp_term = prolog2hilog(pterm, apply, unify_vars);
return p2p_unify(temp_term, hterm);
}
static inline xsbBool is_scalar(prolog_term pterm)
{
if (is_atom(pterm) || is_int(pterm) || is_float(pterm))
return TRUE;
return FALSE;
}
static prolog_term hilog2prolog(prolog_term hterm, char *apply, int unify_vars)
{
prolog_term pterm = p2p_new();
prolog_term pfunctor;
int arity, i;
if (is_var(hterm)){
if (unify_vars)
return hterm;
else
return pterm; /* don't reuse input vars: make new ones */
}
if (is_scalar(hterm)) return hterm;
if (is_list(hterm))
return map_list(hilog2prolog,hterm,apply,unify_vars);
else if (is_special_form(hterm))
return map_special_form(hilog2prolog,hterm,apply,unify_vars);
#ifdef P2HDEBUG
if (!is_functor(hterm))
xsb_abort("PLG2HLG: Arg 2 =`%s' is not a HiLog term.",
pterm2string(hterm));
#endif
/* Don't convert if already Prolog */
if (!is_hilog(hterm,apply)) return hterm;
/* Don't convert if formula (predicate or molecule) */
if (is_formula(hterm)) return hterm;
arity=p2c_arity(hterm);
pfunctor = p2p_arg(hterm,1);
if (!is_atom(pfunctor))
xsb_abort("PLG2HLG: HiLog term `%s' not convertible to Prolog.",
pterm2string(hterm));
if (arity > 1)
c2p_functor(string_val(pfunctor), arity-1, pterm);
else
return pfunctor;
#ifdef P2HDEBUG_VERBOSE
xsb_dbgmsg("h2p start: Pterm=%s", pterm2string(pterm));
xsb_dbgmsg("h2p start: Hterm=%s", pterm2string(hterm));
xsb_dbgmsg("h2p start: Apply=%s", apply);
#endif
for (i=2; i<=arity; i++) {
p2p_unify(hilog2prolog(p2p_arg(hterm,i), apply,unify_vars),
p2p_arg(pterm, i-1));
#ifdef P2HDEBUG_VERBOSE
xsb_dbgmsg("h2p loop: Pterm=%s", pterm2string(pterm));
#endif
}
return pterm;
}
static prolog_term prolog2hilog(prolog_term pterm, char *apply, int unify_vars)
{
prolog_term hterm = p2p_new();
int arity, i;
if (is_var(pterm)) {
if (unify_vars)
return pterm;
else
return hterm; /* don't reuse input vars: create new */
}
if (is_scalar(pterm)) return pterm;
if (is_list(pterm))
return map_list(prolog2hilog,pterm,apply, unify_vars);
else if (is_special_form(pterm))
return map_special_form(prolog2hilog,pterm,apply, unify_vars);
if (!is_functor(pterm))
xsb_abort("PLG2HLG: Arg 1 = `%s' (the Prolog term) must be a var, a const, or a functor.",
pterm2string(pterm));
/* Don't convert if already HiLog */
if (is_hilog(pterm,apply)) return pterm;
/* Don't convert if formula (predicate or molecule) */
if (is_formula(pterm)) return pterm;
arity = p2c_arity(pterm);
c2p_functor(apply,arity+1,hterm);
c2p_string(p2c_functor(pterm), p2p_arg(hterm,1)); /* set the functor arg */
#ifdef P2HDEBUG_VERBOSE
xsb_dbgmsg("p2h start: Pterm=%s", pterm2string(pterm));
xsb_dbgmsg("p2h start: Hterm=%s", pterm2string(hterm));
xsb_dbgmsg("p2h start: Apply=%s", apply);
#endif
/* set the rest of the args */
for (i=1; i<=arity; i++) {
p2p_unify(prolog2hilog(p2p_arg(pterm,i),apply, unify_vars), p2p_arg(hterm,i+1));
#ifdef P2HDEBUG_VERBOSE
xsb_dbgmsg("p2h loop: Hterm=%s", pterm2string(hterm));
#endif
}
return hterm;
}
static prolog_term map_list(prolog_term func(), prolog_term termList, char *apply, int unify_vars)
{
prolog_term listHead, listTail;
prolog_term outList=p2p_new(), outListHead, outListTail;
prolog_term temp_term;
xsbBool mustExit=FALSE;
listTail = termList;
outListTail = outList;
while (!is_nil(listTail) && !mustExit) {
if (is_list(listTail)) {
c2p_list(outListTail);
listHead = p2p_car(listTail);
outListHead = p2p_car(outListTail);
temp_term = func(listHead,apply, unify_vars);
p2p_unify(outListHead, temp_term);
listTail = p2p_cdr(listTail);
outListTail = p2p_cdr(outListTail);
} else {
p2p_unify(listTail,outListTail);
mustExit = TRUE;
}
}
if (is_nil(listTail))
c2p_nil(outListTail); /* bind tail to nil */
return outList;
}
static prolog_term map_special_form(prolog_term (*func)(), prolog_term special_form, char *apply, int unify_vars)
{
prolog_term formArg1_temp, formArg2_temp;
prolog_term out_form=p2p_new(), formArg1_out, formArg2_out;
char *functor = p2c_functor(special_form);
c2p_functor(functor, 2, out_form);
formArg1_out = p2p_arg(out_form,1);
formArg2_out = p2p_arg(out_form,2);
formArg1_temp = func(p2p_arg(special_form,1),apply, unify_vars);
formArg2_temp = func(p2p_arg(special_form,2),apply, unify_vars);
p2p_unify(formArg1_out,formArg1_temp);
p2p_unify(formArg2_out,formArg2_temp);
return out_form;
}
static char *pterm2string(prolog_term term)
{
static VarString *StrArgBuf;
prolog_term term2 = p2p_deref(term);
XSB_StrCreate(&StrArgBuf);
XSB_StrSet(StrArgBuf,"");
print_pterm(term2, 1, StrArgBuf);
return StrArgBuf->string;
}
/* This detects both HiLog terms and predicates, but we really need to check
for HiLog terms only */
static int is_hilog(prolog_term term, char *apply_funct)
{
size_t length_diff;
char *func = p2c_functor(term); /* term functor */
length_diff = strlen(func) - strlen(apply_funct);
if (0 > length_diff) return FALSE;
/* Match apply_funct to the end of the term functor.
HiLog terms have functor=apply_functor.
HiLog predicates have complex functor, whose tail matches flapply */
return (strcmp(apply_funct, func+length_diff)==0);
}
/* Check if term represents a formula rather than a term */
static int is_formula(prolog_term term)
{
char *functor;
if (is_scalar(term) || is_list(term)) return FALSE;
functor = p2c_functor(term);
return
(strncmp(functor, FLORA_META_PREFIX, FLORA_META_PREFIX_LEN)==0)
||
(strncmp(functor, FLORA_LIB_PREFIX, FLORA_LIB_PREFIX_LEN)==0);
}
/* Note: this only treats 2-ary 1-character functors that are treated as
prolog in Flora. We don't do it for others due to speed considerations. */
static int is_special_form(prolog_term term)
{
char *functor;
if (is_scalar(term) || is_list(term)) return FALSE;
functor = p2c_functor(term);
if (strlen(functor)==1) {
switch (*functor) {
case ',':
case ';':
case '+':
case '-':
case '/':
case '*':
case '>':
case '<':
case '~': return TRUE;
default: return FALSE;
}
}
return FALSE;
}
/*
flora_plg2hlg(a(qq,b(c,4),b(c,5,d(X,U))),Y,aaa,1).
Y = aaa(a,qq,aaa(b,c,4),aaa(b,c,5,aaa(d,_h312,_h313)))
flora_plg2hlg(aaa(qq,b(c,4)),X,aaa,1).
X = aaa(qq,b(c,4))
flora_plg2hlg(X, aaa(qq,b(c,4),aaa(kkk,Bbb,aaa(ppp,aaa(uuu,Aaa),Ooo))),aaa,1).
X = qq(b(c,4),kkk(_h356,ppp(uuu(_h365),_h362)))
flora_plg2hlg(X, aaa(qq,aaa(aaa,4)),aaa,1).
X = qq(aaa(4))
flora_plg2hlg(X, [], aaa,1).
X = []
flora_plg2hlg([], X, aaa,1).
X = []
flora_plg2hlg(X, [aaa(qq,b(c,4)), f(abc), aaa(b,c(K),aaa(bbb,aaa(ccc,aaa(ddd))))],aaa,1).
X = [qq(b(c,4)),f(abc),b(c(_h185),bbb(ccc(ddd)))]
flora_plg2hlg(X, [aaa(qq,b(c,4)), f(abc), aaa(b,c(K))],aaa,1).
X = [qq(b(c,4)),f(abc),b(c(_h185))]
flora_plg2hlg(X, [[aaa(qq,b(c,4)), f(abc)], aaa(b,c(K))],aaa,1).
X = [[qq(b(c,4)),f(abc)],b(c(_h193))]
flora_plg2hlg([aaa(qq,b(c,4)), a(qq,b(c,4)), f(q(a),b,c(p,q(Y)))], X, aaa,1).
X = [aaa(qq,b(c,4)),aaa(a,qq,aaa(b,c,4)),aaa(f,aaa(q,a),b,aaa(c,p,aaa(q,_h423)))]
flora_plg2hlg([aaa(qq,b(c,4)), [a(qq,b(c,4))], [f(q(a),b,c(p,q(Y))), b(_)]], X, aaa,1).
X = [aaa(qq,b(c,4)),[aaa(a,qq,aaa(b,c,4))],[aaa(f,aaa(q,a),b,aaa(c,p,aaa(q,_h480))),aaa(b,_h487)]]
flora_plg2hlg(X, (aaa(qq,b(c,4)), f(abc), aaa(b,c(K),aaa(bbb,aaa(ccc,aaa(ddd))))),aaa,1).
X = (qq(b(c,4)) ',' f(abc) ',' b(c(_h185),bbb(ccc(ddd))))
flora_plg2hlg(X, (aaa(qq,b(c,4)), f(abc), aaa(b,c(K))),aaa,1).
X = (qq(b(c,4)) ',' f(abc) ',' b(c(_h185)))
flora_plg2hlg(X, ((aaa(qq,b(c,4)); f(abc)), aaa(b,c(K))),aaa,1).
X = ((qq(b(c,4)) ';' f(abc)) ',' b(c(_h193)))
flora_plg2hlg((aaa(qq,b(c,4)); a(qq,b(c,4)), f(q(a),b,c(p,q(Y)))), X,aaa,1).
X = (aaa(qq,b(c,4)) ';' aaa(a,qq,aaa(b,c,4)) ',' aaa(f,aaa(q,a),b,aaa(c,p,aaa(q,_h427))))
flora_plg2hlg((aaa(qq,b(c,4)), a(qq,b(c,4)), f(q(a),b,c(p,q(Y)))), X,aaa,1).
X = (aaa(qq,b(c,4)) ',' aaa(a,qq,aaa(b,c,4)) ',' aaa(f,aaa(q,a),b,aaa(c,p,aaa(q,_h427))))
flora_plg2hlg(((aaa(qq,b(c,4)), a(qq,b(c,4))); (f(q(a),b,c(p,q(Y))), b(_))), X, aaa,1).
X= (aaa(qq,b(c,4)) ',' aaa(a,qq,aaa(b,c,4)) ';' aaa(f,aaa(q,a),b,aaa(c,p,aaa(q,_h480))) ',' aaa(b,_h485))
*/
syntax highlighted by Code2HTML, v. 0.9.1