One of the cool things about Edinborough syntax Prolog is the use of 'operators' - they are just syntactic sugar for function terms. (Cambridge syntax prolog looks like Lisp - I don't think any implementations still exist that use this syntax.) foo(a - b, c + d, e = f) is semantically equivalent to foo(-(a, b), +(c, d), =(e,f)) '-(a,b)' does not have a particular interpretation in Prolog, it's meaning is determined (in this case) by what 'foo' does with it and what other clauses referencing 'foo' do with it.
Even the 'neck' operator and 'and' operators of clauses are just syntactic sugar:
foo(X) :- bar(X), baz(X). is equivalent to :-(foo(X), ,(bar(X), baz(X))).
(This shows the unfortunate overloading of the comma token as both an operator used for 'and' in clauses and as a term separator.)
This is how arithmetic operations are defined using the 'is' builtin. The 'is' builtin gets a nested function term that uses functors that it interprets as arithmetic operations: X is 3 + 4 * 2 * 7. is the same as X is +(3, *(4, *(2, 7))). The 'is' builtin applies common arithmetic processing to this nested structure to unify a numeric value 59 with X.
Outside of 'is' and some special comparison builtins, the functors that look like arithmetic operators have no particular semantics: Y = 3 + 4 * 2 * 7, (Z + W) = Y. binds Z to '3' and W to '4 * 2 * 7'. There is no arithmetic processing done in this case.
Programmers are free to use whatever operator makes sense in the context of a particular program to identify pairs of values.
And if none of the pre-defined operators ('-', '+', '=', etc) are appropriate, you can always define your own: :- op(&=&>, xfy, 500). :- op(<++, yfx, 250). for foo(a &=&> b, c <++ d, e = f). is the same as foo(&=&>(a, b), <++(c, d), =(e, f)).
This is great fun for designing domain-specific languages in Prolog.
Lindsey Spratt Some clarificaation…. a while back you helped me write a testing framework…here is the code: get_all_tests(Tests) :- setof(Line-Name, get_one_test(Name, Line), Tests).
get_one_test(Name, Line) :- current_predicate(Name/0), atom_concat('test_', _, Name), predicate_property(Name, prolog_line(Line)).
It uses ‘pairs’ as I understand them, using the ‘-‘ to combine the key and value, so in your response, what is ‘=‘ doing in this context in the list of flags????
Just when I thouthgh I was beginning to understand! LMAO
Thanks once again,
Sean.
Hello Sean,
you can do this with your own loop or use findall like this:
flag(public, 0x0001).
flag(final, 0x0010).
flag(super, 0x0020).
flag(interface, 0x0200).
flag(abstract, 0x0400).
flag(synthetic, 0x1000).
flag(annotation, 0x2000).
flag(enum, 0x4000).
get_java_flags(Value, Flags) :-
findall(Name, has_flag(Value, Name), Flags).
has_flag(Value, Name) :-
flag(Name, Mask),
Value /\ Mask =\= 0.
then call it with:
| ?- get_java_flags(0x421, Flags).
Flags = [public,super,abstract]
I have detailed a bit to be more comprehensive: the has_flag/2
predicate could be inlined inside the findall surrounding with ().
If you prefer to have the flags as a parameter pass them as a list
and use member to handle backtracking (done by get_flags/3 here):
get_java_flags(Value, Flags) :-
FlagNames = [public = 0x0001,
final = 0x0010,
super = 0x0020,
interface = 0x0200,
abstract = 0x0400,
synthetic = 0x1000,
annotation = 0x2000,
enum = 0x4000],
get_flags(FlagNames, Value, Flags).
get_flags(FlagNames, Value, Flags) :-
findall(Name, has_flag(FlagNames, Value, Name),
Flags).
has_flag(NameFlags, Value, Name) :-
member(Name=Mask, NameFlags),
Value /\ Mask =\= 0.
Daniel
Le 09/04/2014 01:02, Sean Charles a écrit :
Hello list,
I have almost completed a predicate called ‘jread’ which
parses a Java .class file into a term that will allow me to
create a database of all of the methods, fields, superclass and
interfaces for that class and ultimately create a database for a
complete “android.jar” file of any required API level.
I am, for educational purposes and my own learning, trying
to build a system like Hoogle/Hayoo for Android. I do a lot of
Android and I wanted to create a sytem I can wire into
Emacs/IntelliJ or anything for that matter, a simple HTTP
server that can supply a list of methods that have a certain
type signature using a si mple query language. Searching by
types it very very useful when using Haskell and I wanted to
improve my Prolog so I figured why not do something like that
in GNU Prolog? I have already started a simple HTTP library in
pure GNU Prolog as well but this comes first now.
Progress so far is good…if I run it like this from a folder
containing the unpacked android.jar file...
| ?-
jread('javax/net/SocketFactory.class',X).
X =
javaclass(super('java/lang/Object'),class('javax/net/SocketFactory'),implements([]),
methods([method(access_flags(4),name('<init>'),returns('()V'),[attr(9,
[0,3,0,1,0,0,0,14,42,183,0,1,187,0,2,89,18,3,183,0,4,191,0,0,0,2,0,10,0,0,0,6,0,1,0,0,0
,4,0,11,0,0,0,12,0,1,0,0,0,14,0,12,0,13,0,0])]),method(access_flags(41),name(getDefault)
,returns('()Ljavax/net/SocketFactory;'),attr(9,0,3,0,0,0,0,0,10,187,0,2,89,18,3,183,0,4,
191,0,0,0,1,0,10,0,0,0,6,0,1,0,0,0,5])]),method(access_flags(1),name(createSocket),
returns('()Ljava/net/Socket;'),[attr(9,0,3,0,1,0,0,0,10,187,0,2,89,18,3,183,0,4,191,
0,0,0,2,0,10,0,0,0,6,0,1,0,0,0,6,0,11,0,0,0,12,0,1,0,0,0,10,0,12,0,13,0,0]),
attr(18,0,1,0,19])]),method(access_flags(1025),name(createSocket),
returns('(Ljava/lang/String;I)Ljava/net/Socket;'),[attr(18,[0,2,0,19,0,21])]),
method(access_flags(1025),name(createSocket),
returns('(Ljava/lang/String;ILjava/net/InetAddress;I)Ljava/net/Socket;’),
[attr(18,[0,2,0,19,0,21])]),method(access_flags(1025),name(createSocket),
returns('(Ljava/net/InetAddress;I)Ljava/net/Socket;’),[attr(18[0,1,0,19])]),method(access_flags(1025),name(createSocket),
returns('(Ljava/net/InetAddress;ILjava/net/InetAddress;I)Ljava/net/Socket;'),[attr(18,[0,1,0,19])])]))
?
The place I am at now is decoding the bit flags for the
class (and eventually the methods etc) into a term.
A typical value would be “1057” decimal, 0x421, this
contains the flags:
ACC_PUBLIC |
0x0001 |
Declared public ; may
be accessed from outside its package. |
ACC_FINAL |
0x0010 |
Declared final ; no
subclasses allowed. |
ACC_SUPER |
0x0020 |
Treat superclass methods specially when invoked by
the invokespecial
instruction. |
ACC_INTERFACE |
0x0200 |
Is an interface, not a class. |
ACC_ABSTRACT |
0x0400 |
Declared abstract ;
must not be instantiated. |
ACC_SYNTHETIC |
0x1000 |
Declared synthetic; not present in the source code.
|
ACC_ANNOTATION |
0x2000 |
Declared as an annotation type. |
ACC_ENUM |
0x4000 |
Declared as an enum
type. |
So you can see that 0x421 means “ACC_PUBLIC, ACC_SUPER and
ACC_ABSTRACT”. I would like to produce a term something like
this:
access_flags(public,super,abstract)
It’s not that I don’t know how to do it or that I can’t do
it but I am not sure what is the *most elegant* way to do it
in Prolog! Heaven knows I have written bit shifting loops to
test for flags in a dozen languages but not in Prolog.
So, there’s the challenge, what is the most elegant way to
turn a list of bits into a list of atom terms. Ideally I would
make the list of atoms a parameter so that I can reuse it for
the other flag based values.
Consider the gauntlet thrown! In the meantime I am
continuing to research the possibilities for myself. I will of
course put it all on GitHub along with my Redis client. I may
even create a Redis database with the information!
:)
Sean.
--
Ce message a été vérifié par
MailScanner
pour des virus ou des polluriels et rien de
suspect n'a été trouvé.
_______________________________________________ Users-prolog mailing list address@hidden https://lists.gnu.org/mailman/listinfo/users-prolog
|