|
2230 | 2230 |
|
2231 | 2231 | % :- load_pfc_file('metta_ontology.pl.pfc').
|
2232 | 2232 |
|
2233 |
| - |
2234 |
| - |
2235 |
| -% Enums for Guarded Type Handling in Prolog |
2236 |
| - |
2237 |
| -% GuardMatchResult: Describes the result of evaluating several type guards against the function arguments. |
2238 |
| -mo_match_behavior(return_original_on_no_match). |
2239 |
| -mo_match_behavior(fail_on_no_match). |
2240 |
| -mo_match_behavior(throw_type_error_on_no_match). |
2241 |
| -% EvaluationOrder: Describes how the type guards are prioritized during evaluation. |
2242 |
| -evaluation_order(clause_order_priority). |
2243 |
| -evaluation_order(fittest_first_priority). |
2244 |
| -% ExecutionResult: Describes the outcome of executing the guarded expression. |
2245 |
| -execution_result_behavior(continue_on_success). |
2246 |
| -execution_result_behavior(cut_on_first_success). |
2247 |
| -% ExecutionResult: Describes the outcome of executing the guarded expression. |
2248 |
| -execution_failed_behavior(continue_on_failure). |
2249 |
| -execution_failed_behavior(cut_on_first_failure). |
2250 |
| -% What do when there are no successfull bodies |
2251 |
| -out_of_clauses_behavior(fail_on_final_failure). |
2252 |
| -out_of_clauses_behavior(return_original_on_final_failure). |
2253 |
| - |
2254 |
| - |
2255 |
| - |
2256 |
| - |
2257 |
| -%predicate_behavior(Predicate, Len, NoMatchBehavior, EvaluationOrder, SuccessBehavior, FailureBehavior, OutOfClausesBehavior) |
2258 |
| -predicate_behavior_impl('get-type', 1, fail_on_no_match, clause_order_priority, continue_on_success, continue_on_failure, fail_on_final_failure). |
2259 |
| - |
2260 |
| -predicate_behavior_impl('foo', 2, return_original_on_no_match, fittest_first_priority, continue_on_success, continue_on_failure, return_original_on_final_failure). |
2261 |
| - |
2262 |
| -predicate_behavior_impl('match', 4, fail_on_no_match, clause_order_priority, continue_on_success, continue_on_failure, fail_on_final_failure). |
2263 |
| -% default |
2264 |
| -predicate_behavior_fallback(_, _, return_original_on_no_match, clause_order_priority, continue_on_success, continue_on_failure, return_original_on_final_failure). |
2265 |
| - |
2266 |
| -predicate_behavior(Predicate, Len, NoMatchBehavior, EvaluationOrder, SuccessBehavior, FailureBehavior, OutOfClausesBehavior):- |
2267 |
| - predicate_behavior_impl(Predicate, Len, NoMatchBehavior, EvaluationOrder, SuccessBehavior, FailureBehavior, OutOfClausesBehavior) |
2268 |
| - *->true; predicate_behavior_fallback(Predicate, Len, NoMatchBehavior, EvaluationOrder, SuccessBehavior, FailureBehavior, OutOfClausesBehavior). |
2269 |
| - |
2270 |
| -function_declaration(Predicate, Len, Parameters, ParamTypes, RetType, [let,ReturnVal,Body,ReturnVal], ReturnVal):- |
2271 |
| - Self='&self', |
2272 |
| - len_or_unbound(Parameters, Len), |
2273 |
| - NR = ([Predicate|Parameters]+Body), |
2274 |
| - copy_term(NR,NRR), |
2275 |
| - no_repeats_var(NRR), |
2276 |
| - metta_defn(Self,[Predicate|Parameters],Body), |
2277 |
| - get_operator_typedef(Self, Predicate, Len, ParamTypes, RetType), |
2278 |
| - NR=NRR, |
2279 |
| - write_src_nl(metta_defn(Self,[Predicate|Parameters],Body)). |
2280 |
| - |
2281 |
| -clause_match_level(Predicate, Len, Parameters, Score, Body, ReturnVal):- |
2282 |
| - function_declaration(Predicate, Len, Parameters, Types, RetType, Body, ReturnVal), |
2283 |
| - maplist(nc_weight,[RetType|Types],XXL),sumlist(XXL,Score). |
2284 |
| - |
2285 |
| -info_about(Predicate, Len):- |
2286 |
| - predicate_behavior(Predicate, Len, NoMatchBehavior, EvaluationOrder, SuccessBehavior, FailureBehavior, OutOfClausesBehavior), |
2287 |
| - write_src_nl(predicate_behavior(Predicate, Len, NoMatchBehavior, EvaluationOrder, SuccessBehavior, FailureBehavior, OutOfClausesBehavior)),!, |
2288 |
| - findall(Score- Body, clause_match_level(Predicate, Len, Parameters, Score, Body, ReturnVal), ScoredBodies), |
2289 |
| - maplist(write_src_nl,ScoredBodies),!. |
2290 |
| - |
2291 |
| -implement_predicate([Predicate|Parameters], ReturnVal):- |
2292 |
| - catch(implement_predicate_nr([Predicate|Parameters], ReturnVal),metta_notreducable(ReturnVal),true). |
2293 |
| - |
2294 |
| -implement_predicate_nr([Predicate|Parameters], ReturnVal) :- |
2295 |
| - len_or_unbound(Parameters, Len), |
2296 |
| - |
2297 |
| - predicate_behavior(Predicate, Len, NoMatchBehavior, EvaluationOrder, SuccessBehavior, FailureBehavior, OutOfClausesBehavior), |
2298 |
| - |
2299 |
| - % Generate Score-Body pairs |
2300 |
| - findall(Score- Body, clause_match_level(Predicate, Len, Parameters, Score, Body, ReturnVal), ScoredBodies), |
2301 |
| - |
2302 |
| - % Handle no matches |
2303 |
| - (ScoredBodies \== [] -> |
2304 |
| - true ; |
2305 |
| - (NoMatchBehavior == fail_on_no_match -> fail ; throw(metta_notreducable([Predicate | Parameters])))), % vs return_original_on_no_match |
2306 |
| - |
2307 |
| - % Sort based on evaluation order |
2308 |
| - (EvaluationOrder == clause_order_priority -> |
2309 |
| - OrderedBodies = ScoredBodies ; |
2310 |
| - sort(ScoredBodies, OrderedBodies)), % fittest_first_priority |
2311 |
| - |
2312 |
| - % Extract bodies from sorted or original pairs |
2313 |
| - maplist(arg(2), OrderedBodies, Bodies), |
2314 |
| - |
2315 |
| - % Iterate over bodies and handle success/failure policies |
2316 |
| - (((member(Body, Bodies), call(Body)) *-> |
2317 |
| - (SuccessBehavior == cut_on_first_success -> ! ; true) % vs continue_on_success |
2318 |
| - ; |
2319 |
| - (FailureBehavior == cut_on_first_failure -> (!, fail) ; fail)) % vs continue_on_failure |
2320 |
| - *-> |
2321 |
| - true ; |
2322 |
| - (OutOfClausesBehavior == fail_on_final_failure -> fail ; throw(metta_notreducable([Predicate | Parameters])))). % vs return_original_on_final_failure |
2323 |
| - |
2324 |
| - |
2325 |
| - |
2326 |
| -% ------------------------------------------------------------------------------ |
2327 |
| -% Core Logic with Type Guards |
2328 |
| -% ------------------------------------------------------------------------------ |
2329 |
| - |
2330 |
| -% Helper to check type guards. |
2331 |
| -guard_match(X, number) :- number(X). |
2332 |
| -guard_match(X, atom) :- atom(X). |
2333 |
| -guard_match(X, list) :- is_list(X). |
2334 |
| -guard_match(X, complex) :- is_list(X), length(X, N), N > 5. |
2335 |
| -guard_match(X, simple) :- is_list(X), length(X, N), N =< 5. |
2336 |
| -guard_match(_, generic). |
2337 |
| - |
2338 |
| -% Define what happens inside the guarded body. |
2339 |
| -guarded_body(X, Result, success) :- |
2340 |
| - writeln(successful_guard(X)), |
2341 |
| - Result = processed(X). |
2342 |
| - |
2343 |
| -guarded_body(X, Result, failure) :- |
2344 |
| - writeln(failed_guard(X)), |
2345 |
| - Result = return_original(X). |
2346 |
| - |
2347 |
| -% Fallback logic if no guards match. |
2348 |
| -fallback_logic(X, Result) :- |
2349 |
| - writeln('No type guard matched. Executing fallback.'), |
2350 |
| - Result = default_value(X). |
2351 |
| - |
2352 |
| -% Nested guard logic. |
2353 |
| -nested_guard(X, Result) :- |
2354 |
| - ( X = hello -> |
2355 |
| - Result = special_case_handled |
2356 |
| - ; Result = default_atom_result |
2357 |
| - ). |
2358 |
| - |
2359 |
| -% ------------------------------------------------------------------------------ |
2360 |
| -% Tests |
2361 |
| -% ------------------------------------------------------------------------------ |
2362 |
| - |
2363 |
| -% Test 1: Simple Type Guard Matching |
2364 |
| -test_simple_guard :- |
2365 |
| - function(42, Result1), writeln(Result1), |
2366 |
| - function(hello, Result2), writeln(Result2), |
2367 |
| - function([], Result3), writeln(Result3), |
2368 |
| - function(foo, Result4), writeln(Result4). |
2369 |
| - |
2370 |
| -% Test 2: Fallback Behavior |
2371 |
| -test_fallback :- |
2372 |
| - function_with_fallback([], Result), writeln(Result). |
2373 |
| - |
2374 |
| -% Test 3: Prioritized Type Guard Evaluation |
2375 |
| -test_prioritized :- |
2376 |
| - prioritized_function([1,2,3], Result1), writeln(Result1), |
2377 |
| - prioritized_function([1,2,3,4,5,6], Result2), writeln(Result2), |
2378 |
| - prioritized_function(hello, Result3), writeln(Result3). |
2379 |
| - |
2380 |
| -% Test 4: Nested Guarded Logic with Errors |
2381 |
| -test_nested :- |
2382 |
| - nested_function(42, Result1), writeln(Result1), |
2383 |
| - nested_function(hello, Result2), writeln(Result2), |
2384 |
| - nested_function(world, Result3), writeln(Result3), |
2385 |
| - nested_function([], Result4), writeln(Result4). |
2386 |
| - |
2387 |
| -% ------------------------------------------------------------------------------ |
2388 |
| -% Function Definitions |
2389 |
| -% ------------------------------------------------------------------------------ |
2390 |
| - |
2391 |
| -% Function with basic guards. |
2392 |
| -function(X, Result) :- |
2393 |
| - ( guard_match(X, number) -> |
2394 |
| - guarded_body(X, Result, success) |
2395 |
| - ; guard_match(X, atom) -> |
2396 |
| - guarded_body(X, Result, success) |
2397 |
| - ; guard_match(X, list) -> |
2398 |
| - guarded_body(X, Result, success) |
2399 |
| - ; guarded_body(X, Result, failure) |
2400 |
| - ). |
2401 |
| - |
2402 |
| -% Function with a fallback mechanism. |
2403 |
| -function_with_fallback(X, Result) :- |
2404 |
| - ( guard_match(X, number) -> |
2405 |
| - guarded_body(X, Result, success) |
2406 |
| - ; guard_match(X, atom) -> |
2407 |
| - guarded_body(X, Result, success) |
2408 |
| - ; fallback_logic(X, Result) |
2409 |
| - ). |
2410 |
| - |
2411 |
| -% Function with prioritized guards. |
2412 |
| -prioritized_function(X, Result) :- |
2413 |
| - evaluation_order(fittest_first), % Assume we process most specific guards first. |
2414 |
| - ( guard_match(X, complex) -> |
2415 |
| - guarded_body(X, Result, success) |
2416 |
| - ; guard_match(X, simple) -> |
2417 |
| - guarded_body(X, Result, success) |
2418 |
| - ; guard_match(X, generic) -> |
2419 |
| - guarded_body(X, Result, success) |
2420 |
| - ; guarded_body(X, Result, failure) |
2421 |
| - ). |
2422 |
| - |
2423 |
| -% Function with nested guards and error handling. |
2424 |
| -nested_function(X, Result) :- |
2425 |
| - ( guard_match(X, number) -> |
2426 |
| - guarded_body(X, Result, success) |
2427 |
| - ; guard_match(X, atom) -> |
2428 |
| - nested_guard(X, Result) |
2429 |
| - ; fallback_logic(X, Result) |
2430 |
| - ). |
2431 |
| - |
2432 |
| -ffffff:- writeln(' |
2433 |
| - ?- test_simple_guard. |
2434 |
| - ?- test_fallback. |
2435 |
| - ?- test_prioritized. |
2436 |
| - ?- test_nested. |
2437 |
| -'). |
2438 |
| - |
2439 |
| - |
2440 |
| -%! freeist(+X, +Y, -Result) is det. |
2441 |
| -% |
2442 |
| -% A comparison predicate for `predsort/3` that sorts terms by freeness. |
2443 |
| -% |
2444 |
| -% Terms are sorted based on the following criteria: |
2445 |
| -% - Variables are considered the "most free" and are sorted first. |
2446 |
| -% - Partially instantiated terms come next. |
2447 |
| -% - Fully ground terms are sorted last. Among them, they are further sorted by |
2448 |
| -% their complexity (the total number of functors and arguments in the term). |
2449 |
| -% |
2450 |
| -% If two terms have the same degree of freeness and complexity, a lexicographic comparison |
2451 |
| -% is used as a final fallback. |
2452 |
| -% |
2453 |
| -% Example usage with `predsort/3`: |
2454 |
| -% == |
2455 |
| -% ?- predsort(freeist, [X, f(Y), g(a), Z, b, h(1,2,3)], Sorted). |
2456 |
| -% % Sorted = [X, Z, f(Y), b, g(a), h(1, 2, 3)]. |
2457 |
| -% |
2458 |
| -% ?- predsort(freeist, [a, f(a), h(a, b, c), g(a), b], Sorted). |
2459 |
| -% % Sorted = [a, b, g(a), f(a), h(a, b, c)]. |
2460 |
| -% |
2461 |
| -% ?- predsort(freeist, [X, Z, f(X, Y), b, h(a), g(a)], Sorted). |
2462 |
| -% % Sorted = [X, Z, f(X, Y), b, g(a), h(a)]. |
2463 |
| -% |
2464 |
| -% ?- predsort(freeist, [g(a), g(b), f(a, b), a, h(a, b, c), X, Z], Sorted). |
2465 |
| -% % Sorted = [X, Z, a, g(a), g(b), f(a, b), h(a, b, c)]. |
2466 |
| -% == |
2467 |
| -% |
2468 |
| -% @param Result Comparison result: `<`, `=`, or `>`. |
2469 |
| -% @param Y Second term to compare. |
2470 |
| -% @param X First term to compare. |
2471 |
| - |
2472 |
| -%freeist(Result, X, Y):- X == Y, !, Result = (=). |
2473 |
| -freeist(Result, X, Y):- X =@= Y, !, compare(Result, Y, X). |
2474 |
| -freeist(Result, Y, X) :- compound(Y),Y=(YY-_),!,freeist(Result, YY, X). |
2475 |
| -freeist(Result, Y, X) :- compound(X),X=(XX-_),!,freeist(Result, Y, XX). |
2476 |
| -freeist(Result, Y, X) :- |
2477 |
| - term_freeness(Y, FX), |
2478 |
| - term_freeness(X, FY), |
2479 |
| - ( FX = FY -> |
2480 |
| - ( FX = 2 -> % If both terms are ground |
2481 |
| - term_arity(Y, AX), |
2482 |
| - term_arity(X, AY), |
2483 |
| - ( AX = AY -> |
2484 |
| - term_complexity(Y, CX), |
2485 |
| - term_complexity(X, CY), |
2486 |
| - ( CX = CY -> |
2487 |
| - (compound_term_compare(ResultNE, X, Y), (ResultNE \= (=) -> ResultNE=Result ; compare(Result, Y, X))) % Compare compound terms argument by argument |
2488 |
| - ; compare(Result, CX, CY) ) |
2489 |
| - ; compare(Result, AX, AY) ) |
2490 |
| - ; compare(Result, Y, X) ) % Fallback for other types if freeness is the same |
2491 |
| - ; compare(Result, FX, FY) % Compare by freeness |
2492 |
| - ), !. |
2493 |
| - |
2494 |
| -% Calculate term freeness |
2495 |
| -term_freeness(Term, 1) :- attvar(Term), !. |
2496 |
| -term_freeness(Term, 0) :- var(Term), !. |
2497 |
| -%term_freeness(Term, 1) :- term_variables(Term, Vars), Vars \= [], !. |
2498 |
| -term_freeness(_, 2). |
2499 |
| - |
2500 |
| -% Calculate term arity (number of arguments) |
2501 |
| -term_arity(Term, Arity) :- |
2502 |
| - %ground(Term), % Only applies to ground terms |
2503 |
| - Term =.. [_|Args], |
2504 |
| - length(Args, Arity). |
2505 |
| -term_arity([_|Args], Arity):-length(Args, Arity). |
2506 |
| - |
2507 |
| -% Calculate term complexity (total number of functors and arguments in the term) |
2508 |
| -term_complexity(Term, Complexity) :- fail, |
2509 |
| - ground(Term), % Only applies to ground terms |
2510 |
| - term_complexity_acc(Term, 0, Complexity). |
2511 |
| -term_complexity(_,1). |
2512 |
| - |
2513 |
| -term_complexity_acc(Term, Acc, Complexity) :- |
2514 |
| - Term =.. [_|Args], |
2515 |
| - length(Args, ArgCount), |
2516 |
| - NewAcc is Acc + 1 + ArgCount, |
2517 |
| - foldl(term_complexity_acc, Args, NewAcc, Complexity). |
2518 |
| - |
2519 |
| -term_to_list(L, [L]):- \+ compound(L),!. |
2520 |
| -term_to_list(L,L):- is_list(L),!. |
2521 |
| -term_to_list(C, [F|Args]):- C \=[_|_],!, compound_name_arguments(C,F,Args). |
2522 |
| -term_to_list(L, [L]). |
2523 |
| - |
2524 |
| -% Compare compound terms argument by argument |
2525 |
| -compound_term_compare(Result, X, Y) :- |
2526 |
| - term_to_list(X,XX), |
2527 |
| - term_to_list(Y,YY), |
2528 |
| - maplist(nc_weight,XX,XXL),sumlist(XXL,SX), |
2529 |
| - maplist(nc_weight,YY,YYL),sumlist(YYL,SY), |
2530 |
| - compare(FunctorResult, SY, SX), % Compare functors lexicographically |
2531 |
| - ( FunctorResult = (=) -> |
2532 |
| - compare_args(Result, XX, YY) % Compare arguments recursively |
2533 |
| - ; Result = FunctorResult ). |
2534 |
| - |
2535 |
| -% Recursively compare lists of arguments |
2536 |
| -compare_args(Result, [A1|Rest1], [A2|Rest2]) :- !, |
2537 |
| - non_compound_compare(ArgResult, A1, A2), % Compare individual arguments using the custom predicate |
2538 |
| - ( ArgResult = (=) -> |
2539 |
| - compare_args(Result, Rest1, Rest2) % Continue with the remaining arguments |
2540 |
| - ; Result = ArgResult ). |
2541 |
| -compare_args(Result, A, B) :- A==B, Result = (=). % Both lists are empty |
2542 |
| -compare_args(Result, A, _) :- A==[], Result = (<). % First list is shorter |
2543 |
| -compare_args(Result, _, B) :- B==[], Result = (>). % Second list is shorter |
2544 |
| - |
2545 |
| -% Example custom comparison for individual atoms or non-compound terms |
2546 |
| -non_compound_compare(Result, A, B) :- |
2547 |
| - % Example: Comparing atoms by custom weights |
2548 |
| - nc_weight(A, WA), |
2549 |
| - nc_weight(B, WB), |
2550 |
| - (WA==WB-> compare(Result, WB, WA); compare(Result, A, B)). |
2551 |
| - |
2552 |
| -% Example weight mapping for atomics |
2553 |
| -nc_weight(Attvar, 7):- attvar(Attvar),!. |
2554 |
| -nc_weight(Var, 8):- var(Var),!. |
2555 |
| -nc_weight(T, N):- is_decl_mtype(T,N),!. |
2556 |
| -nc_weight(T, N):- is_decl_utype(T,N),!. |
2557 |
| -nc_weight(T, 6):- atomic(T),!. |
2558 |
| - |
2559 |
| - |
2560 |
| - |
| 2233 | +:- ensure_loaded(metta_typed_functions). |
0 commit comments