Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@
_build/
comp_opts.mk
erl_crash.dump
rebar.lock
src/erlog_scan.erl
55 changes: 38 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,19 @@ This is a low level interface, which is meant to built upon as much as used dire
To create an Erlog instance in a closure use `erlog:new()` this will
return `{ok, State}` Where state is the current state of the Erlog
system. You should treat it as an opaque data structure. To prove a
clause or run Prolog code you can then run `erlog:prove(State, {...})`
clause or run Prolog code you can then run `erlog:prove({...}, State)`
This will return a new closure and a return of type
`erlog_return()`. To consult a file you can run `erlog:consult(State,
FILE)` which will return a new closure and 'ok' or an error.
`erlog_return()`. To consult a file you can run `erlog:consult(FILE, State)`
which will return a new closure and 'ok' or an error.

For example take this code:
We start by creating a new instance of the Erlog engine, then we
We start by creating a new instance of the Erlog engine, then we
it starts with an append statement which ask it to append lists `A`
and `B`. The return value is designated with a 1 tuple with an atom
value for the return variable, in this case `{'Z'}`.
value for the return variable, in this case `{'Z'}`.

If the Prolog code works correctly it will return the tuple `{{succeed,
[{'Z', Value}]}, NewState}`.
[{'Z', Value}]}, NewState}`.



Expand All @@ -46,6 +46,27 @@ If the Prolog code works correctly it will return the tuple `{{succeed,
end
````

### The simple Erlog shell.

This is a simple shell similar to a "normal" Prolog shell.
An example, using a file from Erlog repository.

````erlang
1> erlog_shell:server().
Erlog Shell V14.2.1 (abort with ^G)
| ?- consult("examples/family.pl").
Yes
| ?- parent(pam, B).
B = bob
:
Yes
| ?- halt
.
ok
2>
````


The dialyzer types of some of Erlog's functions are as such

````erlang
Expand All @@ -66,15 +87,15 @@ If you have questions about Erlog post them tagged with Erlog on Stack Overflow

If you want to pass data between Erlang and Prolog it is pretty easy
to do so. Data types map pretty cleanly between the two languages due
to the fact that Erlang evolved from Prolog.
to the fact that Erlang evolved from Prolog.

### Atoms
Atoms are the same in Erlang and Prolog, and can be passed back and
forth without problem.

### Numeric Data
### Numeric Data
Integer and floating point numbers similarly can be passed back and
forth.
forth.

### Opaque data

Expand All @@ -87,17 +108,17 @@ comparisons on them.
It is possible to send structured Erlang data to Prolog, and this is
often very useful. Lists can be sent directly back and forth. Maps are
not (Yet) supported, we will be looking into how to support them in
the future.
the future.

Erlog understands Erlang tuples to be facts. So the Erlang tuple
`{foo, 1, 2, 3}` would show up in Erlog as the fact `foo(1,2,3)`. The
upshot of this is that all tuples that are passed to Erlog must have
an atom as the first element and must have more than 1 element. The
tuple `{atom()}` will be understood to be a Prolog variable.
tuple `{atom()}` will be understood to be a Prolog variable.

Records in Erlang are just tuples with an initial atom. So it is
possible to pass records between Erlog and Erlang. The record
definition here and the Prolog fact are equivalent.
definition here and the Prolog fact are equivalent.

````erlang
-record(person, {name, phone, address}).
Expand All @@ -112,8 +133,8 @@ standard prolog arg/3 predicate. If you want to create functors that
can access fields in an Erlang record by name, you can create functors
for that Automaticly with the code in the file
https://github.com/zkessin/erlog/blob/master/priv/records.pl. just
call `erlog:prove(State, {record, person, record_info(fields,
person)})`. Note that the record fields must be created in Erlang at
call `erlog:prove({record, person, record_info(fields, person)}, State)`.
Note that the record fields must be created in Erlang at
compile time.

## Using ETS
Expand All @@ -124,7 +145,7 @@ ETS table. It should also be possible to work with mnesia tables, but
this has not yet been done.

If you want to use Erlog with ETS you need to load the erlog_ets
module into Erlog. To do that you call `erlog:load(PID,erlog_ets)` or
module into Erlog. To do that you call `erlog:load(erlog_ets, PID)` or
`E({load,erlog_ets})`. You can match on an ETS table with
`ets_match(TableId, Value)`.

Expand All @@ -151,8 +172,8 @@ If you want to run the tests you will need to install quickcheck mini

to run the tests then run `rebar eunit`

## Licence
## Licence

Erlog was created by Robert Virding and can be used under the
Apache 2.0 Licence.
Apache 2.0 Licence.

13 changes: 13 additions & 0 deletions src/erlog_shell.erl
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ server(M, A) ->
server_loop(Erl0) ->
case erlog_io:read('| ?- ') of
{ok,halt} -> ok;
{ok,{consult, File}} ->
Erl1 = consult(erlog:consult(File,Erl0), Erl0),
server_loop(Erl1);
{ok,{reconsult, File}} ->
Erl1 = consult(erlog:reconsult(File,Erl0), Erl0),
server_loop(Erl1);
{ok,Files} when is_list(Files) ->
case reconsult_files(Files, Erl0) of
{ok,Erl1} ->
Expand Down Expand Up @@ -70,6 +76,13 @@ server_loop(Erl0) ->
server_loop(Erl0)
end.

consult({ok, State}, _) ->
io:fwrite("Yes\n"),
State;
consult({error, Error}, State) ->
io:fwrite("Error: ~s\n", [erlog_io:write1(Error)]),
State.

reconsult_files([F|Fs], Erl0) ->
case erlog:reconsult(F, Erl0) of
{ok,Erl1} -> reconsult_files(Fs, Erl1);
Expand Down