Tau Prolog
๐ Josรฉ Antonio Riaza Valverde (@jariazavalverde)
| HTML | โ | ๐ Structure |
| CSS | โ | ๐ฆ Presentation |
| JavaScript | โ | ๐ช Behaviour |
<script type="text/javascript" src="tau-prolog.js"></script>
const pl = require("tau-prolog");

const session = pl.create(options);
session.consult(program, options);
session.query(goal, options);
session.answer(options);
/* Consult */
session.consult(program, {
success: function() {
/* Query */
session.query(goal, {
success: function(goal) {
/* Answers */
session.answer({
success: function(answer) { /* Answer */ },
error: function(err) { /* Uncaught error */ },
fail: function() { /* Fail */ },
limit: function() { /* Limit exceeded */ }
})
},
error: function(err) { /* Error parsing goal */ }
});
},
error: function(err) { /* Error parsing program */ }
});
Type elements separated with commas and press Enter:
:- use_module(library(dom)).
:- use_module(library(js)).
powerset([], []).
powerset([_|T], P) :- powerset(T, P).
powerset([H|T], [H|P]) :- powerset(T, P).
main :-
get_by_id(powerset_input, Input),
get_by_id(powerset_output, Output),
bind(Input, keypress, Event,
( event_property(Event, code, 'Enter'),
set_html(Output, ''),
get_attr(Input, value, Value),
apply(Value, split, [','], Xs),
forall(powerset(Xs, P),
( create(div, Div),
atomic_list_concat(P, S),
set_html(Div, S),
append_child(Output, Div)
)
)
)
).
:- use_module(library(dom)).
external_links(Domain) :-
forall(
( get_by_tag(a, A),
get_attr(A, href, Href),
\+atom_concat(Domain, _, Href)
),
( set_attr(A, target, '_blank')
)
).
bind(+HTML, +EventType, -Event, +Goal)
unbind(+HTML, +EventType)
event_property(+Event, +Property, ?Value)
:- use_module(library(dom)).
:- use_module(library(js)).
:- dynamic(draggable/1).
main :-
once(get_by_tag(body, Body)),
bind(Body, mousemove, Event,
( draggable(Elem),
event_property(Event, pageX, X),
event_property(Event, pageY, Y),
move(Elem, X, Y)
)
),
bind(Body, mouseup, _,
( retract(draggable(Elem)),
set_style(Elem, 'z-index', 0)
)
),
forall(
get_by_class(draggable, Elem),
bind(Elem, mousedown, _,
( asserta(draggable(Elem)),
set_style(Elem, 'z-index', 999)
)
)
).
move(Elem, X, Y) :-
set_style(Elem, position, absolute),
get_prop(Elem, offsetWidth, Width),
get_prop(Elem, offsetHeight, Height),
Top is Y - Height/2,
Left is X - Width/2,
set_style(Elem, top, px(Top)),
set_style(Elem, left, px(Left)).
:- use_module(library(dom)).
% Zero or more
some(G) --> call(G), !, some(G).
some(_) --> [].
% One or more
many(G) --> call(G), some(G).
% Alphabetical char
alpha -->
[X],
{ char_code(X, C),
C >= 65,
C =< 122
}.
% Numeric char
num -->
[X],
{ char_code(X, C),
C >= 48,
C =< 57
}.
% Alphanumeric char
alphanum --> alpha ; num.
% Natural number
natural -->
many(num).
% Email
email -->
many(alphanum), [@],
many(alphanum), ['.'],
many(alphanum).
main :-
forall(
( get_by_class(form_check, Input),
get_attr(Input, 'data-grammar', DCG)
),
( bind(Input, change, _,
( get_attr(Input, value, Value),
atom_chars(Value, Chars),
remove_class(Input, form_success),
remove_class(Input, form_error),
( phrase(DCG, Chars)
-> add_class(Input, form_success)
; add_class(Input, form_error)
)
)
)
)
).
Mechanism allowing a program written in a programming language to call routines written in another
:- use_module(library(dom)).
:- use_module(library(js)).
:- use_module(library(os)).
rose(Petals, Step) :-
get_by_id(rose, Rose),
apply(Rose, getContext, ['2d'], Ctx),
point(0.0, Petals, (X,Y)),
apply(Ctx, clearRect, [0, 0, 200, 200], _),
apply(Ctx, beginPath, [], _),
apply(Ctx, moveTo, [X,Y], _),
rose(Ctx, Petals, Step, 0.0).
rose(Ctx, Petals, Step, T0) :-
point(T0, Petals, (X,Y)),
apply(Ctx, lineTo, [X,Y], _),
apply(Ctx, stroke, [], _),
apply(Ctx, beginPath, [], _),
apply(Ctx, moveTo, [X,Y], _),
sleep(1),
T1 is T0 + Step,
rose(Ctx, Petals, Step, T1).
point(T, Petals, (X,Y)) :-
X is 100 + 90 * cos(Petals * T) * cos(T),
Y is 100 + 90 * cos(Petals * T) * sin(T).
:- use_module(library(lists)).
:- use_module(library(random)).
:- use_module(library(dom)).
:- use_module(library(js)).
:- use_module(library(os)).
:- dynamic(direction/1).
direction(down).
key_direction(w, up) :-
direction(Direction),
Direction \== down.
key_direction(a, left) :-
direction(Direction),
Direction \== right.
key_direction(d, right) :-
direction(Direction),
Direction \== left.
key_direction(s, down) :-
direction(Direction),
Direction \== up.
snake :-
once(get_by_tag(body, Body)),
bind(Body, keydown, Event, (
event_property(Event, key, Key),
key_direction(Key, Direction),
prevent_default(Event),
retractall(direction(_)),
asserta(direction(Direction))
)),
get_by_id(snake, Canvas),
apply(Canvas, getContext, ['2d'], Ctx),
random_between(1, 20, X),
random_between(1, 20, Y),
snake(Ctx, [(1,1)], (X,Y)).
snake(Ctx, Snake, Point) :-
get_time(T0),
draw(Ctx, Snake, Point),
direction(Direction),
update(Snake, Point, Direction, Snake1, Point1),
get_time(T1),
Timeout is max(0, 60-round(T1-T0)),
set_timeout(Timeout, snake(Ctx, Snake1, Point1), _).
next_position(left, (1,Y), (20,Y)).
next_position(left, (X0,Y), (X1,Y)) :-
succ(X1, X0).
next_position(right, (20,Y), (1,Y)).
next_position(right, (X0,Y), (X1,Y)) :-
succ(X0, X1).
next_position(up, (X,1), (X,20)).
next_position(up, (X,Y0), (X,Y1)) :-
succ(Y1, Y0).
next_position(down, (X,20), (X,1)).
next_position(down, (X,Y0), (X,Y1)) :-
succ(Y0, Y1).
inits([_], []).
inits([X,Y|T], [X|S]) :-
inits([Y|T], S).
update(Snake0, Point0, Direction, [Head1|Snake1], Point1) :-
Snake0 = [Head0|_],
next_position(Direction, Head0, Head1),
( member(Head1, Snake0) ->
Snake1 = [],
Point1 = Point0 ;
( Head1 == Point0 ->
Snake1 = Snake0,
Point1 = (X,Y),
random_between(1,20,X),
random_between(1,20,Y)
; inits(Snake0, Snake1),
Point1 = Point0
)
).
draw(Ctx, Snake, Point) :-
apply(Ctx, clearRect, [0,0,200,200], _),
draw_point(Ctx, Point, red),
forall(
member(Body, Snake),
draw_point(Ctx, Body, black)
).
draw_point(Ctx, (X,Y), Color) :-
PointX is (X-1)*10,
PointY is (Y-1)*10,
set_prop(Ctx, fillStyle, Color),
apply(Ctx, beginPath, [], _),
apply(Ctx, rect, [PointX,PointY,10,10], _),
apply(Ctx, fill, [], _).
Asynchronous operations let programs complete work while waiting for another operations to finish
:- use_module(library(dom)).
:- use_module(library(random)).
fruit(F) :-
random_member(F, ['๐','๐','๐','๐','๐','๐','๐']).
fruit_roulette(Roulette) :-
fruit(Fruit),
set_html(Roulette, Fruit),
fruit_roulette(Roulette).
Future objects represent the eventual completion or failure of asynchronous tasks
future(+Template, +Goal, -Future)
await(+Future, ?Value)
future_done(+Future)
future_all(+List, -Future)
future_any(+List, -Future)
Type the number of horses and press Enter:
:- use_module(library(dom)).
:- use_module(library(js)).
:- use_module(library(os)).
:- use_module(library(concurrent)).
:- use_module(library(random)).
hippodrome :-
get_by_id(horses, Input),
get_by_id(hippodrome, Hippodrome),
bind(Input, keypress, Event,
( event_property(Event, code, 'Enter'),
set_html(Hippodrome, ''),
get_attr(Input, value, Value),
atom_chars(Value, Chars),
number_chars(N, Chars),
findall(F,
( between(1, N, _),
make_horse(Hippodrome, Horse),
future(Horse, run_horse(Horse), F)
), Fs),
future_any(Fs, F),
await(F, Winner),
set_html(Winner, '๐')
)
).
make_horse(Hippodrome, Horse) :-
create(div, Horse),
set_html(Horse, '๐'),
add_class(Horse, horse),
append_child(Hippodrome, Horse).
run_horse(Horse) :-
get_style(Horse, left, px(Left)),
( Left =< 0 ->
true
; random_between(1, 10, Jump),
Left2 is max(0, Left - Jump),
set_style(Horse, left, px(Left2)),
random_between(5, 15, Sleep),
sleep(Sleep),
run_horse(Horse)
).
Tau Prolog