From e8794a78d568aa8769af598ad9d6d5e553123431 Mon Sep 17 00:00:00 2001 From: logicmoo Date: Mon, 20 Jan 2025 23:36:34 -0800 Subject: [PATCH] passes fish_riddle again 3 --- prolog/metta_lang/metta_types.pl | 232 ++++++++++++++++--------------- 1 file changed, 121 insertions(+), 111 deletions(-) diff --git a/prolog/metta_lang/metta_types.pl b/prolog/metta_lang/metta_types.pl index 7e9b477c70..c6f2cb4387 100755 --- a/prolog/metta_lang/metta_types.pl +++ b/prolog/metta_lang/metta_types.pl @@ -217,27 +217,30 @@ % % @arg Type The type being checked. % -is_decl_utype('%Undefined%'). -is_decl_utype('Number'). -is_decl_utype('Symbol'). -is_decl_utype('Expression'). -is_decl_utype('String'). -is_decl_utype('Bool'). -is_decl_utype('Type'). -is_decl_utype('Any'). -is_decl_utype('Atom'). +is_decl_utype(U):- is_decl_utype(U,_). +is_decl_utype('Atom',1). +is_decl_utype('Expression',5). +is_decl_utype('Any',3). +is_decl_utype('%Undefined%',3). +is_decl_utype('AnyRet',3). +is_decl_utype('Type',5). +is_decl_utype('Number',5). +is_decl_utype('Symbol',5). +is_decl_utype('String',5). +is_decl_utype('Bool',5). % is_decl_utype(Type) :- is_decl_type_l(Type). %! is_decl_mtype(+Type) is nondet. % % @arg Type The type being checked. % -is_decl_mtype('Variable'). -is_decl_mtype('Number'). -is_decl_mtype('Symbol'). -is_decl_mtype('Expression'). -is_decl_mtype('Grounded'). -is_decl_mtype('PyObject'). +is_decl_mtype(U):- is_decl_mtype(U,_). +is_decl_mtype('Variable',5). +is_decl_mtype('Number',5). +is_decl_mtype('Symbol',5). +is_decl_mtype('Expression',5). +is_decl_mtype('Grounded',4). +is_decl_mtype('PyObject',4). % is_decl_type([ST|_]) :- !, atom(ST), is_decl_type_l(ST). % is_decl_type(ST) :- \+ atom(ST), !, fail. @@ -444,7 +447,7 @@ call_nth(get_type_each(Depth, Self, Val, Type),Nth), Type\=='', ((Nth > 1) -> Type\== 'Atom' ; true), % Ensure the type matches the expected no-repeat type. - NoRepeatType = Type, + \+ \+ (NoRepeatType = Type), Type = TypeO, % If only the first type should be returned, cut; otherwise, proceed. (return_only_first_type -> !; true). @@ -540,29 +543,6 @@ is_PyObject(S) :- % Succeeds if S is recognized as a Python object. py_is_py(S). -is_PyObject(S) :- - % Fail if S is an unbound variable. - var(S), !, fail. -is_PyObject('@'(S)) :- - % Succeeds if S is a non-variable and recognized as a Python constant. - !, nonvar(S), is_py_const(S). - -%! is_py_const(+Const) is nondet. -% -% Succeeds if the given Const is a recognized Python constant. -% -% @arg Const The constant to be evaluated. -% -% @example -% ?- is_py_const('True'). -% true. -% -% ?- is_py_const('Unknown'). -% false. -% -is_py_const('None'). -is_py_const('False'). -is_py_const('True'). %! get_type_each(+Depth, +Self, +Val, -Type) is nondet. % @@ -594,6 +574,8 @@ % get_type(Depth, Self, Val, Type) :- is_debugging(eval), % ftrace(get_type_each(Depth, Self, Val, Type)), % fail. +get_type_each(Depth, Self, Var, Type) :- var(Var), get_attr(Var,cns, _ = Set),member(Type,Set). + get_type_each(Depth, Self, Expr, ['StateMonad', Type]) :- % Handle state monad expressions. notrace(is_valid_nb_state(Expr)), !, @@ -603,7 +585,7 @@ get_type_each(_Dpth, Self, Var, Type) :- % Retrieve type from variable attributes. var(Var), !, - get_attr(Var, metta_type, Self = TypeList), + get_attr(Var, cns, Self = TypeList), member(Type, TypeList). get_type_each(_Dpth, _Slf, Expr, 'hyperon::space::DynSpace') :- % Check if the expression is a dynamic space. @@ -685,7 +667,7 @@ % Get the length of arguments or determine if unbound. len_or_unbound(Args, Len), % Retrieve the operator type definition. - get_operator_typedef1(Self, Op, Len, ArgTypes, RType). + get_operator_typedef_R(Self, Op, Len, ArgTypes, RType). %! badly_typed_expression(+Depth, +Self, +Expr) is nondet. % @@ -840,10 +822,10 @@ get_dict_type(Val, _, Type) :- % Retrieve the type from the dictionary 'type' field. get_dict(Val, type, Type). -get_dict_type(Val, _, TypeO) :- +get_dict_type(Val, _, Type) :- % Retrieve the type from the dictionary 'class' field. get_dict(Val, class, Type). -get_dict_type(Val, _, TypeO) :- +get_dict_type(Val, _, Type) :- % Retrieve the type from the dictionary 'types' field if it is a list. get_dict(Val, types, TypeL), is_list(TypeL), @@ -878,13 +860,16 @@ last(Type1,Type). get_type_cmpd(Depth,Self,[Op|Args],Type,ac(Op,[P|Arams],RetType)):- symbol(Op), len_or_unbound(Args,Len), - get_operator_typedef1(Self,Op,Len,[P|Arams],RetType), + get_operator_typedef(Self,Op,Len,[P|Arams],RetType), % Fills in type variables when possible args_conform(Depth,Self,Args,[P|Arams]), % \+ maplist(var,Arams), % unitests: arg violations should return () (\+ args_violation(Depth,Self,Args,[P|Arams])), Type=RetType. + +get_type_cmpd(Depth,Self,ArTypeDecl,Type,arrow_type(ParamTypes,RetType)):- arrow_type(ArTypeDecl,ParamTypes,RetType), Type='%Undefined%',!. + get_type_cmpd(_Dpth,_Slf,Cmpd,Type,typed_list):- typed_list(Cmpd,Type,_List). % commenting this fails two tests @@ -936,7 +921,7 @@ maplist(get_type(Depth2, Self), List, Type), % Ensure the expression is not badly typed. \+ badly_typed_expression(Depth, Self, Type). -get_type_cmpd_eval(Depth2, Self, EvalMe, Val, Type, eval_first) :- +get_type_cmpd_eval(Depth2, Self, _EvalMe, Val, Type, eval_first) :- % Handle first-evaluation strategy. !, \+ needs_eval(Val), @@ -966,7 +951,6 @@ % ?- get_value_type(_, _, X, Type). % Type = '%Undefined%'. % -get_value_type(_Dpth,_Slf,Var,'%Undefined%'):- var(Var),!. get_value_type(_Dpth,_Slf,Val,'Number'):- number(Val),!. get_value_type(_Dpth,_Slf,Val,'String'):- string(Val),!. get_value_type(Depth,Self,Val,T):- get_type(Depth,Self,Val,T), T\==[], T\=='%Undefined%',!. @@ -1018,7 +1002,7 @@ % as_prolog(I, O) :- % Use default recursion depth of 10 and '&self' as context. - as_prolog(10, '&self', I, O). + as_prolog(0, '&self', I, O). %! as_prolog(+Depth, +Self, +I, -O) is det. % @@ -1037,32 +1021,48 @@ % ?- as_prolog(_, _, ['@', foo, a, b], O). % O = foo(a, b). % -as_prolog(_Dpth, _Slf, I, O) :- - % If I is not a 'conz' structure, unify it directly with O. - \+ iz_conz(I), !, I = O. -as_prolog(Depth, Self, [Cons, H, T], [HH | TT]) :- + +:- dynamic(dont_de_Cons/0). +dont_de_Cons. + +as_prolog(0, _Slf, S, P):- S=='Nil', \+ dont_de_Cons, !,P=[]. +as_prolog(_Dpth, _Slf, I, O) :- \+ compound(I), !, O = I. +as_prolog(0, Self, [Cons, H, T | Nil], [HH | TT]) :- % Handle 'Cons' structures as lists. Cons=='Cons', - !, - as_prolog(Depth, Self, H, HH), - as_prolog(Depth, Self, T, TT). -as_prolog(Depth, Self, [List, H | T], O) :- + Nil == [], \+ dont_de_Cons, !, + as_prolog(0, Self, H, HH), + as_prolog(0, Self, T, TT). +as_prolog(0, Self, [CC | List], O) :- % Handle '::' operator by mapping elements to Prolog terms. - List=='::', - !, - maplist(as_prolog(Depth, Self), [H | T], L), + CC =='::', + is_list(List), \+ dont_de_Cons, !, + maplist(as_prolog(0, Self), List, L), !, O = L. -as_prolog(Depth, Self, [At, H | T], O) :- + +as_prolog(_, Self, exec(Eval), O) :- !, eval_args(30, Self, Eval, O). +as_prolog(_, Self, quote(O), O) :- !. +as_prolog(_Dpth, _Slf, I, O) :- + % If I is not a 'conz' structure, unify it directly with O. + \+ iz_conz(I), !, I = O. + +as_prolog(N, Self, [At| List], O) :- % Handle '@' symbol by constructing compound terms. - At=='@', - !, - maplist(as_prolog(Depth, Self), [H | T], [HH | L]), - atom(H), !, - O =.. [HH | L]. + At=='@', \+ dont_de_Cons, + is_list(List), \+ dont_de_Cons, + maplist(as_prolog(N, Self), List, [HH | L]), + atom(HH), !, + compound_name_arguments(O, HH, L). + + as_prolog(Depth, Self, I, O) :- % If I is a list, map each element to Prolog terms. is_list(I), !, maplist(as_prolog(Depth, Self), I, O). +as_prolog(Depth, Self, [H|T], [HH|TT]) :- + % If is a list, map each element to Prolog terms. + as_prolog(Depth, Self, H, HH), + as_prolog(1, Self, T, TT), !. as_prolog(_Dpth, _Slf, I, I). %! try_adjust_arg_types(+Eq, +RetType, +Depth, +Self, +Params, +X, -Y) is nondet. @@ -1156,11 +1156,24 @@ % @arg X The input arguments. % @arg Y The final adjusted arguments. % -adjust_argsA(Else, Eq, RetType, Res, NewRes, Depth, Self, Op, X, Y) :- +adjust_argsA(Else, Eq, RetType, Res, NewRes, Depth, Self, Op, X, Y):- + if_or_else(adjust_argsA1(Else, Eq, RetType, Res, NewRes, Depth, Self, Op, X, Y), + adjust_argsA2(Else, Eq, RetType, Res, NewRes, Depth, Self, Op, X, Y)). + +adjust_argsA1(Else, Eq, RetType, Res, NewRes, Depth, Self, Op, X, Y) :- + len_or_unbound(X, Len), + get_operator_typedef(Self, Op, Len, ParamTypes, RRetType), + (nonvar(NewRes) -> CRes = NewRes ; CRes = Res), + RRetType = RetType, + args_conform(Depth, Self, [CRes | X], [RRetType | ParamTypes]), + trace_if_debug(Op,Len), + into_typed_args(Depth, Self, [RRetType | ParamTypes], [Res | X], [NewRes | Y]). +adjust_argsA2(Else, Eq, RetType, Res, NewRes, Depth, Self, Op, X, Y) :- len_or_unbound(X, Len), get_operator_typedef(Self, Op, Len, ParamTypes, RRetType), (nonvar(NewRes) -> CRes = NewRes ; CRes = Res), RRetType = RetType, + trace_if_debug(Op,Len), args_conform(Depth, Self, [CRes | X], [RRetType | ParamTypes]), into_typed_args(Depth, Self, [RRetType | ParamTypes], [Res | X], [NewRes | Y]). @@ -1200,7 +1213,7 @@ % @arg Adjusted The result after evaluation. % eval_1_arg(Else, Eq, ReturnType, Depth, Self, Arg, Adjusted) :- - must_det_ll( + ( if_or_else( eval(Eq, ReturnType, Depth, Self, Arg, Adjusted), call(Else, Arg, Adjusted))). @@ -1258,13 +1271,12 @@ % Try to retrieve the type definition from cache, or fallback to other strategies. if_or_else( get_operator_typedef0(Self, Op, Len, ParamTypes, RetType), - if_or_else( get_operator_typedef1(Self, Op, Len, ParamTypes, RetType), - get_operator_typedef2(Self, Op, Len, ParamTypes, RetType))). + get_operator_typedef2(Self, Op, Len, ParamTypes, RetType)). -%! get_operator_typedef1(+Self, +Op, +Len, -ParamTypes, -RetType) is nondet. +%! get_operator_typedef_R(+Self, +Op, +Len, -ParamTypes, -RetType) is nondet. % -% Retrieves the operator type definition based on the `'->'` type structure +% _REALLY_ Retrieves the operator type definition based on the `'->'` type structure % and caches the result in `get_operator_typedef0/5`. % % @arg Self The context or structure being evaluated. @@ -1273,7 +1285,7 @@ % @arg ParamTypes The list of parameter types. % @arg RetType The return type of the operator. % -get_operator_typedef1(Self, Op, Len, ParamTypes, RetType) :- +get_operator_typedef_R(Self, Op, Len, ParamTypes, RetType) :- % Ensure the length matches the parameter types or is unbound. len_or_unbound(ParamTypes, Len), % Build the type list for metta_type lookup. @@ -1281,7 +1293,22 @@ % Check the type definition in metta_type/3. metta_type(Self, Op, ['->' | List]), % Cache the result for future lookups. - if_t(var(ParamTypes), append(ParamTypes, [RetType], List)), + if_t(var(ParamTypes), append(ParamTypes, [RetType], List)). + +%! get_operator_typedef1(+Self, +Op, +Len, -ParamTypes, -RetType) is nondet. +% +% Retrieves the operator type definition based on the `'->'` type structure +% and caches the result in `get_operator_typedef0/5`. +% +% @arg Self The context or structure being evaluated. +% @arg Op The operator whose type is being retrieved. +% @arg Len The arity of the operator. +% @arg ParamTypes The list of parameter types. +% @arg RetType The return type of the operator. +% + +get_operator_typedef1(Self, Op, Len, ParamTypes, RetType) :- + get_operator_typedef_R(Self, Op, Len, ParamTypes, RetType), assert(get_operator_typedef0(Self, Op, Len, ParamTypes, RetType)). %! get_operator_typedef2(+Self, +Op, +Len, -ParamTypes, -RetType) is nondet. @@ -1338,7 +1365,7 @@ ignored_arg_conform(Depth, Self, A, L) :- % Check the argument type and verify it conforms to the expected type. get_type(Depth, Self, A, T), - type_conform(T, L), !. + can_assign(T, L), !. ignored_arg_conform(Depth, Self, _, _) :- !. %! args_conform(+Depth, +Self, +Args, +List) is det. @@ -1367,33 +1394,10 @@ % @arg Arg The argument to be checked. % @arg Expected The expected type or value. % -arg_conform(_Dpth, _Slf, _A, L) :- - % Succeed if the expected type is a non-specific type. - nonvar(L), is_nonspecific_type(L), !. -arg_conform(Depth, Self, A, L) :- - % Check the argument type and verify it conforms to the expected type. - get_type_each(Depth, Self, A, T), T \== 'Var', - type_conform(T, L), !. +arg_conform(_Depth, Self, A, ParamType):- non_arg_violation_each(Self,ParamType, A). % arg_conform(_Dpth, _Slf, _, _). % arg_conform(Depth, Self, A, _) :- get_type(Depth, Self, A, _), !. -%! type_conform(+Type, +Expected) is nondet. -% -% Checks if a type (Type) conforms to the expected type (Expected). -% -% @arg Type The type to be checked. -% @arg Expected The expected type. -% -type_conform(T, L) :- - % Succeed if the types are equal. - T = L, !. -type_conform(T, L) :- \+ is_nonspecific_type(T), \+ is_nonspecific_type(L), !, can_assign(T, L). -type_conform(T, L) :- fail, - % Succeed if either type is non-specific. - \+ \+ (is_nonspecific_type(T); is_nonspecific_type(L)), !. -type_conform(T, L) :- - % Succeed if the type can be assigned. - can_assign(T, L). % Declare `thrown_metta_return/1` as dynamic to allow runtime modifications. :- dynamic(thrown_metta_return/1). @@ -1446,7 +1450,7 @@ % into_typed_arg(_Dpth, Self, T, M, Y) :- % If the value is a variable, assign the type attribute and unify it. - var(M), !, Y = M, nop(put_attr(M, metta_type, Self = T)). + var(M), !, Y = M, nop(put_attr(M, cns, Self = T)). into_typed_arg(Depth, Self, T, M, Y) :- % Use into_typed_arg0 for further evaluation or fallback to direct unification. into_typed_arg0(Depth, Self, T, M, Y) *-> true ; M = Y. @@ -1464,7 +1468,7 @@ into_typed_arg0(Depth, Self, T, M, Y) :- % If the type is a variable, determine the value type and evaluate if needed. var(T), !, - must_det_ll(( + (( get_type(Depth, Self, M, T), (wants_eval_kind(T) -> eval_args(Depth, Self, M, Y) ; Y = M))). into_typed_arg0(Depth, Self, T, M, Y) :- @@ -1491,17 +1495,20 @@ nonvar(T), is_pro_eval_kind(T), !. wants_eval_kind(_) :- true. -%! metta_type:attr_unify_hook(+Input, +NewValue) is det. +%! cns:attr_unify_hook(+Input, +NewValue) is det. % -% Handles the unification of a value with a `metta_type` attribute. +% Handles the unification of a value with a `cns` attribute. % % @arg Input The context or structure being evaluated. % @arg NewValue The value being unified with the attribute. % -metta_type:attr_unify_hook(Self = TypeList, NewValue) :- +prevent_type_violations(BecomingValue,RequireType):- non_arg_violation(_Self, RequireType, BecomingValue). +% TODO make sure it is inclusive rather than exclusive +cns:attr_unify_hook(_=TypeRequirements,BecomingValue):- \+ maplist(prevent_type_violations(BecomingValue),TypeRequirements), !, fail. +cns:attr_unify_hook(Self = TypeList, NewValue) :- % If the new value is an attributed variable, assign the same attribute. - attvar(NewValue), !, put_attr(NewValue, metta_type, Self = TypeList). -metta_type:attr_unify_hook(Self = TypeList, NewValue) :- + attvar(NewValue), !, put_attr(NewValue, cns, Self = TypeList). +cns:attr_unify_hook(Self = TypeList, NewValue) :- % Retrieve the type of the new value and check if it can be assigned. get_type(20, Self, NewValue, Was), can_assign(Was, Type). @@ -1546,7 +1553,7 @@ add_type(_Depth, Self, Var, TypeL, Type) :- var(Var), !, % Add the new type to the list and set it as an attribute. append([Type], TypeL, TypeList), - put_attr(Var, metta_type, Self = TypeList). + put_attr(Var, cns, Self = TypeList). add_type(_Depth, _Self, Var, TypeL, Type) :- ignore(append(_,[Type|_], TypeL)),!. % If the variable is not bound, do nothing. @@ -1565,10 +1572,14 @@ % ?- can_assign('Number', 'Number'). % true. % - +can_assign(T, L) :- + % Succeed if the types are equal. + T == L, !. +can_assign(T, L) :- fail, + % Succeed if either type is non-specific. + \+ \+ (is_nonspecific_type(T); is_nonspecific_type(L)), !. % If the types are identical, assignment is allowed. -can_assign(Was, Type) :- nonvar(Was),nonvar(Type), - formated_data_type(Was),formated_data_type(Type),!,Type==Was. +can_assign(Was, Type) :- nonvar(Was),nonvar(Type), formated_data_type(Was),formated_data_type(Type),!,Type==Was. % If the types are identical, assignment is allowed. can_assign(Was, Type) :- Was = Type, !. % If either type is non-specific, assignment is allowed. @@ -1599,6 +1610,7 @@ % If the type is non-variable, not 'Any', and non-specific, succeed. nonvar(Type), Type \== 'Any', is_nonspecific_type(Type), !. is_non_eval_kind('Atom'). +is_non_eval_kind('Expression'). %! is_nonspecific_type(+Type) is nondet. % @@ -2231,6 +2243,4 @@ % :- load_pfc_file('metta_ontology.pl.pfc'). - - - +:- ensure_loaded(metta_typed_functions).