34
35:- module(yall,
36 [ (>>)/2, (>>)/3, (>>)/4, (>>)/5, (>>)/6, (>>)/7, (>>)/8, (>>)/9,
37 (/)/2, (/)/3, (/)/4, (/)/5, (/)/6, (/)/7, (/)/8, (/)/9,
38
39 lambda_calls/2, 40 lambda_calls/3, 41 is_lambda/1 42 ]). 43:- use_module(library(error)). 44:- use_module(library(lists)). 45
46:- meta_predicate
47 '>>'(?, 0),
48 '>>'(?, :, ?),
49 '>>'(?, :, ?, ?),
50 '>>'(?, :, ?, ?, ?),
51 '>>'(?, :, ?, ?, ?, ?),
52 '>>'(?, :, ?, ?, ?, ?, ?),
53 '>>'(?, :, ?, ?, ?, ?, ?, ?),
54 '>>'(?, :, ?, ?, ?, ?, ?, ?, ?). 55
56:- meta_predicate
57 '/'(?, 0),
58 '/'(?, 1, ?),
59 '/'(?, 2, ?, ?),
60 '/'(?, 3, ?, ?, ?),
61 '/'(?, 4, ?, ?, ?, ?),
62 '/'(?, 5, ?, ?, ?, ?, ?),
63 '/'(?, 6, ?, ?, ?, ?, ?, ?),
64 '/'(?, 7, ?, ?, ?, ?, ?, ?, ?). 65
138
160
161'>>'(Parms, Lambda) :-
162 unify_lambda_parameters(Parms, [],
163 ExtraArgs, Lambda, LambdaCopy),
164 Goal =.. [call, LambdaCopy| ExtraArgs],
165 call(Goal).
166
167'>>'(Parms, Lambda, A1) :-
168 unify_lambda_parameters(Parms, [A1],
169 ExtraArgs, Lambda, LambdaCopy),
170 Goal =.. [call, LambdaCopy| ExtraArgs],
171 call(Goal).
172
173'>>'(Parms, Lambda, A1, A2) :-
174 unify_lambda_parameters(Parms, [A1,A2],
175 ExtraArgs, Lambda, LambdaCopy),
176 Goal =.. [call, LambdaCopy| ExtraArgs],
177 call(Goal).
178
179'>>'(Parms, Lambda, A1, A2, A3) :-
180 unify_lambda_parameters(Parms, [A1,A2,A3],
181 ExtraArgs, Lambda, LambdaCopy),
182 Goal =.. [call, LambdaCopy| ExtraArgs],
183 call(Goal).
184
185'>>'(Parms, Lambda, A1, A2, A3, A4) :-
186 unify_lambda_parameters(Parms, [A1,A2,A3,A4],
187 ExtraArgs, Lambda, LambdaCopy),
188 Goal =.. [call, LambdaCopy| ExtraArgs],
189 call(Goal).
190
191'>>'(Parms, Lambda, A1, A2, A3, A4, A5) :-
192 unify_lambda_parameters(Parms, [A1,A2,A3,A4,A5],
193 ExtraArgs, Lambda, LambdaCopy),
194 Goal =.. [call, LambdaCopy| ExtraArgs],
195 call(Goal).
196
197'>>'(Parms, Lambda, A1, A2, A3, A4, A5, A6) :-
198 unify_lambda_parameters(Parms, [A1,A2,A3,A4,A5,A6],
199 ExtraArgs, Lambda, LambdaCopy),
200 Goal =.. [call, LambdaCopy| ExtraArgs],
201 call(Goal).
202
203'>>'(Parms, Lambda, A1, A2, A3, A4, A5, A6, A7) :-
204 unify_lambda_parameters(Parms, [A1,A2,A3,A4,A5,A6,A7],
205 ExtraArgs, Lambda, LambdaCopy),
206 Goal =.. [call, LambdaCopy| ExtraArgs],
207 call(Goal).
208
240
241
242'/'(Free, Lambda) :-
243 lambda_free(Free),
244 copy_term_nat(Free+Lambda, Free+LambdaCopy),
245 call(LambdaCopy).
246
247'/'(Free, Lambda, A1) :-
248 lambda_free(Free),
249 copy_term_nat(Free+Lambda, Free+LambdaCopy),
250 call(LambdaCopy, A1).
251
252'/'(Free, Lambda, A1, A2) :-
253 lambda_free(Free),
254 copy_term_nat(Free+Lambda, Free+LambdaCopy),
255 call(LambdaCopy, A1, A2).
256
257'/'(Free, Lambda, A1, A2, A3) :-
258 lambda_free(Free),
259 copy_term_nat(Free+Lambda, Free+LambdaCopy),
260 call(LambdaCopy, A1, A2, A3).
261
262'/'(Free, Lambda, A1, A2, A3, A4) :-
263 lambda_free(Free),
264 copy_term_nat(Free+Lambda, Free+LambdaCopy),
265 call(LambdaCopy, A1, A2, A3, A4).
266
267'/'(Free, Lambda, A1, A2, A3, A4, A5) :-
268 lambda_free(Free),
269 copy_term_nat(Free+Lambda, Free+LambdaCopy),
270 call(LambdaCopy, A1, A2, A3, A4, A5).
271
272'/'(Free, Lambda, A1, A2, A3, A4, A5, A6) :-
273 lambda_free(Free),
274 copy_term_nat(Free+Lambda, Free+LambdaCopy),
275 call(LambdaCopy, A1, A2, A3, A4, A5, A6).
276
277'/'(Free, Lambda, A1, A2, A3, A4, A5, A6, A7) :-
278 lambda_free(Free),
279 copy_term_nat(Free+Lambda, Free+LambdaCopy),
280 call(LambdaCopy, A1, A2, A3, A4, A5, A6, A7).
281
282
291
292unify_lambda_parameters(Parms, _Args, _ExtraArgs, _Lambda, _LambdaCopy) :-
293 var(Parms),
294 !,
295 instantiation_error(Parms).
296unify_lambda_parameters(Free/Parms, Args, ExtraArgs, Lambda, LambdaCopy) :-
297 !,
298 lambda_free(Free),
299 must_be(list, Parms),
300 copy_term_nat(Free/Parms>>Lambda, Free/ParmsCopy>>LambdaCopy),
301 unify_lambda_parameters_(ParmsCopy, Args, ExtraArgs,
302 Free/Parms>>Lambda).
303unify_lambda_parameters(Parms, Args, ExtraArgs, Lambda, LambdaCopy) :-
304 must_be(list, Parms),
305 copy_term_nat(Parms>>Lambda, ParmsCopy>>LambdaCopy),
306 unify_lambda_parameters_(ParmsCopy, Args, ExtraArgs,
307 Parms>>Lambda).
308
309unify_lambda_parameters_([], ExtraArgs, ExtraArgs, _) :- !.
310unify_lambda_parameters_([Parm|Parms], [Arg|Args], ExtraArgs, Culprit) :-
311 !,
312 Parm = Arg,
313 unify_lambda_parameters_(Parms, Args, ExtraArgs, Culprit).
314unify_lambda_parameters_(_,_,_,Culprit) :-
315 domain_error(lambda_parameters, Culprit).
316
317lambda_free(Free) :-
318 var(Free),
319 !,
320 instantiation_error(Free).
321lambda_free({_}) :- !.
322lambda_free({}) :- !.
323lambda_free(Free) :-
324 type_error(lambda_free, Free).
325
332
333expand_lambda(Goal, Head) :-
334 Goal =.. ['>>', Parms, Lambda| ExtraArgs],
335 is_callable(Lambda),
336 nonvar(Parms),
337 lambda_functor(Parms>>Lambda, Functor),
338 ( Parms = Free/ExtraArgs
339 -> is_lambda_free(Free),
340 free_to_list(Free, FreeList)
341 ; Parms = ExtraArgs,
342 FreeList = []
343 ),
344 append(FreeList, ExtraArgs, Args),
345 Head =.. [Functor|Args],
346 compile_aux_clause_if_new(Head, Lambda).
347expand_lambda(Goal, Head) :-
348 Goal =.. ['/', Free, Closure|ExtraArgs],
349 is_lambda_free(Free),
350 is_callable(Closure),
351 free_to_list(Free, FreeList),
352 lambda_functor(Free/Closure, Functor),
353 append(FreeList, ExtraArgs, Args),
354 Head =.. [Functor|Args],
355 Closure =.. [ClosureFunctor|ClosureArgs],
356 append(ClosureArgs, ExtraArgs, LambdaArgs),
357 Lambda =.. [ClosureFunctor|LambdaArgs],
358 compile_aux_clause_if_new(Head, Lambda).
359
360lambda_functor(Term, Functor) :-
361 copy_term_nat(Term, Copy),
362 variant_sha1(Copy, Functor0),
363 atom_concat('__aux_yall_', Functor0, Functor).
364
365free_to_list({}, []).
366free_to_list({VarsConj}, Vars) :-
367 conjunction_to_list(VarsConj, Vars).
368
369conjunction_to_list(Term, [Term]) :-
370 var(Term),
371 !.
372conjunction_to_list((Term, Conjunction), [Term|Terms]) :-
373 !,
374 conjunction_to_list(Conjunction, Terms).
375conjunction_to_list(Term, [Term]).
376
377compile_aux_clause_if_new(Head, Lambda) :-
378 prolog_load_context(module, Context),
379 ( predicate_property(Context:Head, defined)
380 -> true
381 ; expand_goal(Lambda, LambdaExpanded),
382 compile_aux_clauses([(Head :- LambdaExpanded)])
383 ).
384
385lambda_like(Goal) :-
386 compound(Goal),
387 compound_name_arity(Goal, Name, Arity),
388 lambda_functor(Name),
389 Arity >= 2.
390
391lambda_functor(>>).
392lambda_functor(/).
393
394:- dynamic system:goal_expansion/2. 395:- multifile system:goal_expansion/2. 396
397system:goal_expansion(Goal, Head) :-
398 lambda_like(Goal),
399 prolog_load_context(source, _),
400 \+ current_prolog_flag(xref, true),
401 expand_lambda(Goal, Head).
402
406
407is_lambda(Term) :-
408 compound(Term),
409 compound_name_arguments(Term, Name, Args),
410 is_lambda(Name, Args).
411
412is_lambda(>>, [Params,Lambda|_]) :-
413 is_lamdba_params(Params),
414 is_callable(Lambda).
415is_lambda(/, [Free,Lambda|_]) :-
416 is_lambda_free(Free),
417 is_callable(Lambda).
418
419is_lamdba_params(Var) :-
420 var(Var), !, fail.
421is_lamdba_params(Free/Params) :-
422 !,
423 is_lambda_free(Free),
424 is_list(Params).
425
426is_lambda_free(Free) :-
427 nonvar(Free), !, (Free = {_} -> true ; Free == {}).
428
429is_callable(Term) :-
430 strip_module(Term, _, Goal),
431 callable(Goal).
432
433
442
443lambda_calls(LambdaExtended, Goal) :-
444 compound(LambdaExtended),
445 compound_name_arguments(LambdaExtended, Name, [A1,A2|Extra]),
446 lambda_functor(Name),
447 compound_name_arguments(Lambda, Name, [A1,A2]),
448 lambda_calls(Lambda, Extra, Goal).
449
450lambda_calls(Lambda, Extra, Goal) :-
451 integer(Extra),
452 !,
453 length(ExtraVars, Extra),
454 lambda_calls_(Lambda, ExtraVars, Goal).
455lambda_calls(Lambda, Extra, Goal) :-
456 must_be(list, Extra),
457 lambda_calls_(Lambda, Extra, Goal).
458
459lambda_calls_(Params>>Lambda, Args, Goal) :-
460 unify_lambda_parameters(Params, Args, ExtraArgs, Lambda, LambdaCopy),
461 extend(LambdaCopy, ExtraArgs, Goal).
462lambda_calls_(Free/Lambda, ExtraArgs, Goal) :-
463 copy_term_nat(Free+Lambda, Free+LambdaCopy),
464 extend(LambdaCopy, ExtraArgs, Goal).
465
466extend(Var, _, _) :-
467 var(Var),
468 !,
469 instantiation_error(Var).
470extend(Cyclic, _, _) :-
471 cyclic_term(Cyclic),
472 !,
473 type_error(acyclic_term, Cyclic).
474extend(M:Goal0, Extra, M:Goal) :-
475 !,
476 extend(Goal0, Extra, Goal).
477extend(Goal0, Extra, Goal) :-
478 atom(Goal0),
479 !,
480 Goal =.. [Goal0|Extra].
481extend(Goal0, Extra, Goal) :-
482 compound(Goal0),
483 !,
484 compound_name_arguments(Goal0, Name, Args0),
485 append(Args0, Extra, Args),
486 compound_name_arguments(Goal, Name, Args).
487
488
489 492
493:- multifile prolog_colour:goal_colours/2. 494
495yall_colours(Lambda, built_in-[classify,body(Goal)|ArgSpecs]) :-
496 catch(lambda_calls(Lambda, Goal), _, fail),
497 Lambda =.. [>>,_,_|Args],
498 classify_extra(Args, ArgSpecs).
499
([], []).
501classify_extra([_|T0], [classify|T]) :-
502 classify_extra(T0, T).
503
504prolog_colour:goal_colours(Goal, Spec) :-
505 lambda_like(Goal),
506 yall_colours(Goal, Spec).
507
508
509 512
513:- multifile prolog:called_by/4. 514
515prolog:called_by(Lambda, yall, _, [Goal]) :-
516 lambda_like(Lambda),
517 catch(lambda_calls(Lambda, Goal), _, fail).
518
519
520 523
524:- multifile
525 sandbox:safe_meta_predicate/1,
526 sandbox:safe_meta/2. 527
528sandbox:safe_meta_predicate(yall:(/)/2).
529sandbox:safe_meta_predicate(yall:(/)/3).
530sandbox:safe_meta_predicate(yall:(/)/4).
531sandbox:safe_meta_predicate(yall:(/)/5).
532sandbox:safe_meta_predicate(yall:(/)/6).
533sandbox:safe_meta_predicate(yall:(/)/7).
534
535sandbox:safe_meta(yall:Lambda, [Goal]) :-
536 compound(Lambda),
537 compound_name_arity(Lambda, >>, Arity),
538 Arity >= 2,
539 lambda_calls(Lambda, Goal)