-
Notifications
You must be signed in to change notification settings - Fork 0
/
newpl_server.pl
182 lines (138 loc) · 5.53 KB
/
newpl_server.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
% -*-Prolog-*-
:- use_module(library(socket)).
male(thomas).
male(rolf).
male(arne).
female(anna).
female(maria).
parent(thomas, anna).
parent(maria, anna).
parent(thomas, arne).
parent(rolf, maria).
father(X, Y) :- parent(X, Y), male(X).
mother(X, Y) :- parent(X, Y), female(X).
brother(X, Y) :- parent(Z, X), parent(Z, Y), male(X), X\=Y.
sister(X, Y) :- parent(Z, X), parent(Z, Y), female(X), X\=Y.
sibling(X, Y) :- brother(X, Y); sister(X, Y) .
uncle(X, Y) :- brother(X, Z), parent(Z, Y).
aunt(X, Y) :- sister(X, Z), parent(Z, Y).
grandfather(X, Z) :- father(X, Y), parent(Y, Z).
grandmother(X, Z) :- mother(X, Y), parent(Y, Z).
create_server(Port) :-
tcp_socket(Socket),
tcp_bind(Socket, localhost:Port),
tcp_listen(Socket, 5),
tcp_open_socket(Socket, AcceptFd, _), % master socket
dispatch(AcceptFd).
%print("TEST"),
%tcp_close_socket(Socket). % closes the master socket
dispatch(AcceptFd) :-
% Socket: identifier for client
% Peer: IP-address of client
% programmet stopper, men siden porten er åpna får man fortsatt tilgang til den
% via neg(father(maria,anna))telnet
tcp_accept(AcceptFd, Socket, Peer), % accepted socket
thread_create(process_client(Socket), _, [ detached(true)]),
dispatch(AcceptFd). % loops dispatch
process_client(Socket) :-
% setup_call_cleanup(Setup, Goal, Cleanup)
% If Setup succeeds, Cleanup will be called exactly once after Goal is finished.
setup_call_cleanup(
tcp_open_socket(Socket, StreamPair),
handle_service(StreamPair),
close(StreamPair)).
%tcp_open_socket(Socket, StreamPair),
%handle_service(StreamPair).
% this will accept one message from the client and then process_client() will close the socket
handle_service(StreamPair) :-
read_line_to_codes(StreamPair, Codes), % reads message into an array of character codes or something
%format(StreamPair, '~n~s~n', [Codes]), % send message back with newline before and after
%print(Codes),
%parse_message(String),
%handle_message(String),
% transforms codes into a term (which can be used as a query)
% Queries should be in the form of a list like [parent(A, B), sibling(A, B)]
read_term_from_codes(Codes, Queries, []),
writeln(Queries),
%maplist(handle_query, [StreamPair, Queries]),
maplist_const(handle_query, StreamPair, Queries),
%format(StreamPair, "***end_of_message***~w", [end_of_file]). % need to tell maude to stop receiving messages somehow
format(StreamPair, " .", []). % need to tell maude to stop receiving messages somehow
% writes reply back to client
% reply(StreamPair, Query).
%handle_service(StreamPair).
% shows all results for queries
handle_query(StreamPair, Query) :-
%writeln(Query).
%format("nooo~n"),
Query =.. [F|Args],
format("F = ~w~n", [F]),
format("Args = ~w~n", [Args]),
% if all args are terms, run query deterministically
% else run it non-deterministically
(maplist(atom, Args), handle_deterministic_query(StreamPair, Query);
flatten([F, Args], L), handle_non_deterministic_query(StreamPair, Query, L)).
%(maplist(atom, Args), handle_deterministic_query(StreamPair, Query);
%flatten([F, Args], L), handle_non_deterministic_query(StreamPair, Query, L)).
% FunctionList should be [process, var1, var2]
handle_non_deterministic_query(StreamPair, Query, FunctionList) :-
forall(Query, write_variable_sized_term(StreamPair, FunctionList)).
%forall(Query, format('~w(~w,~w)~n', [Functor|Arguments])),
% TODO: is something like this possible?
%forall(\+ Query, format('~w(~w,~w)~n', [Functor|Arguments])).
%forall(Query, format('~w(~w,~w)~n', List)).
% writes out a term with a functor where the amount of arguments can vary
write_variable_sized_term(StreamPair, [Functor|Arguments]) :-
format(StreamPair, '~w(', Functor),
write_arguments(StreamPair, Arguments),
format(StreamPair, ') # ', []).
/*
format('~w(', Functor),
write_arguments(Arguments),
format(')~n').
*/
% writes out a list of variable size: e1,e2,e3
write_arguments(StreamPair, [FirstArg|Rest]) :-
(length(Rest, 0), format(StreamPair, '~w', FirstArg)); % base case (last argument)
(format(StreamPair, '~w,', FirstArg), write_arguments(StreamPair, Rest)).
/*
write_arguments(StreamPair, [LastArg]) :-
format(StreamPair, '~w', LastArg).
*/
/*
(length(Rest, 0), format('~w', FirstArg)); % base case (last argument)
(format('~w,', FirstArg), write_arguments(Rest)).
*/
% writes the query if it's true and neg(query) if false.
handle_deterministic_query(StreamPair, Query) :-
(Query,
format(StreamPair, '~w~n', Query));
(\+ Query,
format(StreamPair, 'neg(~w)~n', Query)).
/*
(Query,
format('~w~n', Query));
(\+ Query,
format('neg(~w)~n', Query)).
*/
reply(StreamPair, Query) :-
(Query\=end_of_file,
(positive_reply(StreamPair, Query);
negative_reply(StreamPair, Query)));
eof_error_reply(StreamPair).
% TODO: hvorfor er end_of_file med?
% har noe med hvordan maude leser meldinger? eller bare tull å ha det der?
% reply with query if true
positive_reply(StreamPair, Query) :-
Query,
format(StreamPair, '~w~w', [Query, end_of_file]).
% reply with neg(query) if false
negative_reply(StreamPair, Query) :-
\+ Query,
format(StreamPair, 'neg(~w)~w', [Query, end_of_file]).
eof_error_reply(StreamPair) :-
format(StreamPair, 'eof_error~w', [end_of_file]).
maplist_const(_, _, []).
maplist_const(Pred, Const, [H|T]) :-
call(Pred, Const, H),
maplist_const(Pred, Const, T).