PreviousUpNext

15.4.500  src/lib/compiler/back/top/lambdacode/check-lambdacode-expression.pkg

## check-lambdacode-expression.pkg

# Compiled by:
#     src/lib/compiler/core.sublib



###              "All scientific knowledge to which man
###               owes his role as master of the world
###               arose from playful activities."
###
###                              -- Konrad Lorenz



api Check_Lambdacode_Expression {
    #
   check_lty:  (lambdacode::Lambda_Expression, Int) -> Bool;
   newlam_ref:  Ref(  lambdacode::Lambda_Expression );
   fname_ref:  Ref(  String );

};



stipulate
    package hcf =  highcode_form;                       # highcode_form                         is from   src/lib/compiler/back/top/highcode/highcode-form.pkg
    package lv  =  highcode_codetemp;                   # highcode_codetemp                             is from   src/lib/compiler/back/top/highcode/highcode-codetemp.pkg
    package di  =  debruijn_index;                      # debruijn_index                        is from   src/lib/compiler/front/typer/basics/debruijn-index.pkg
    #
    include package   lambdacode; 
herein


    package   check_lambdacode_expression
    : (weak)  Check_Lambdacode_Expression               # Check_Lambdacode_Expression           is from   src/lib/compiler/back/top/lambdacode/check-lambdacode-expression.pkg
    {

        /*** a hack of printing diagnostic output into a separate file ***/ 
        my newlam_ref:  Ref( lambdacode::Lambda_Expression ) = REF (RECORD []);
        my fname_ref:  Ref( String ) = REF "yyy";

        fun bug s = error_message::impossible ("CheckLty: " $ s);
        say = controls::print::say;

        anyerror = REF FALSE;
        clickerror = \\ () => (anyerror := TRUE); end ;

        /****************************************************************************
         *                         BASIC UTILITY FUNCTIONS                          *
         ****************************************************************************/
        fun app2 (f, [], []) => ();
            app2 (f, a . r, b . z) => { f (a, b); app2 (f, r, z);};
            app2 (f, _, _) => bug "unexpected list arguments in function app2";
        end;

        fun simplify (le, 0)
                =>
                STRING "<dummy>";

            simplify (le, n)
                => 
                {   fun h le = simplify (le, n - 1);

                    case le 
                        FN (v, t, e) => FN (v, t, h e);
                        APPLY (e1, e2) => APPLY (h e1, h e2);
                        LET (v, e1, e2) => LET (v, h e1, h e2);
                        TYPEFUN (ks, e) => TYPEFUN (ks, h e);
                        APPLY_TYPEFUN (e, ts) => APPLY_TYPEFUN (h e, ts);
                        PACK (lt, ts, nts, e) => PACK (lt, ts, nts, h e);
                        CON (l, x, e) => CON (l, x, h e);
           #            DECON (l, x, e) => DECON (l, x, h e) 
                        FIX (lv, lt, le, b) => FIX (lv, lt, map h le, h b);

                        SWITCH (e, l, dc, opp)
                            => 
                            {   fun g (c, x)
                                    =
                                    (c, h x);

                                fun f x
                                    =
                                    case x
                                        THE y => THE (h y);
                                        NULL  => NULL;
                                    esac;

                                SWITCH (h e, l, map g dc, f opp);
                            };

                        RECORD e => RECORD (map h e);
                        PACKAGE_RECORD e => PACKAGE_RECORD (map h e);
                        VECTOR (e, x) => VECTOR (map h e, x);
                        SELECT (i, e) => SELECT (i, h e);
                        EXCEPT (e1, e2) => EXCEPT (h e1, h e2);
                        WRAP (t, b, e) => WRAP (t, b, h e);
                        UNWRAP (t, b, e) => UNWRAP (t, b, h e);
                        _ => le;
                    esac;
              };
        end;

        # Utility functions for printing:
        #
        say_uniqkind   = say o hcf::uniqkind_to_string;
        say_uniqtype = say o hcf::uniqtype_to_string;
        say_uniqtypoid   = say o hcf::uniqtypoid_to_string;
        #
        fun le_print le
            =
            prettyprint_lambdacode_expression::print_lexp (simplify (le, 3));


        # A hack for type checking:
        #
        fun later_phase i
            =
            i > 20;


        /****************************************************************************
         *           MAIN FUNCTION --- my check_lty:  lambdacode::Lambda_Expression -> Bool          *
         ****************************************************************************/
        fun check_lty (lambda_expression, phase)
            = 
            {   lt_equiv  = hcf::same_uniqtypoid;

                lt_string = if (later_phase (phase))  hcf::void_uniqtypoid; else hcf::string_uniqtypoid; fi;
                lt_exn    = if (later_phase (phase))  hcf::void_uniqtypoid; else hcf::exception_uniqtypoid;    fi;

                fun lt_etag lt
                    =
                    if (later_phase phase)  hcf::void_uniqtypoid; 
                    else                    hcf::make_exception_tag_uniqtypoid lt;
                    fi;

                fun lt_vector t
                    =
                    if (later_phase phase)   hcf::void_uniqtypoid;
                    else                     hcf::make_type_uniqtypoid (hcf::make_ro_vector_uniqtype t);
                    fi;

                # Lazily select a field from
                # a record/package type:
                #
                exception LTY_SELECT;

                fun lt_sel (lt, i)
                    = 
                    (hcf::lt_select (lt, i))
                    except
                        _ = raise exception LTY_SELECT;

                # Build a function or generic package type
                # from a pair of arbitrary ltys 
                #
                fun lt_fun (x, y)
                    = 
                    if (hcf::uniqtypoid_is_type x
                    and hcf::uniqtypoid_is_type y)   hcf::make_lambdacode_arrow_uniqtypoid            (x, y);
                    else                             hcf::make_lambdacode_generic_package_uniqtypoid  (x, y);
                    fi;

                fun lt_tup ts
                    =
                    hcf::make_type_uniqtypoid (hcf::make_tuple_uniqtype (map hcf::unpack_type_uniqtypoid ts));

                # Lazily keyed_find out the arg and
                # result of an Uniqtypoid:
                #
                exception LTY_ARROW; 
                #
                fun lt_arrow lt
                    = 
                    if (hcf::uniqtypoid_is_type  lt)   hcf::unpack_lambdacode_arrow_uniqtypoid           lt;
                    else                               hcf::unpack_lambdacode_generic_package_uniqtypoid lt;
                    fi
                    except
                      _ =  raise exception LTY_ARROW;

                apply_typeagnostic_type_to_arglist_with_checking =   hcf::apply_typeagnostic_type_to_arglist_with_checking_thunk ();                                                    # Evaluating the thunk allocates a new memo dictionary.

                fun lt_app_check (lt, ts, kenv)
                    = 
                    case (apply_typeagnostic_type_to_arglist_with_checking (lt, ts, kenv))
                         [b] => b; 
                        _ => bug "unexpected ase in ltAppChk";
                    esac;

                # Utility functions for type checking:
                #
                fun lt_ty_app le s (lt, ts, kenv)
                    = 
                    (lt_app_check (lt, ts, kenv))
                    except
                        zz = {   clickerror ();
                                 say (s + "  **** Kind conflicting in lambda_expression =====> \n    ");
                                 case zz    hcf::APPLY_TYPEFUN_CHECK_FAILED => say "      exception APPLY_TYPEFUN_CHECK_FAILED raised! \n";
                                           hcf::KIND_TYPE_CHECK_FAILED =>  say "      exception KIND_TYPE_CHECK_FAILED raised! \n";
                                           _ => say "   other weird exception raised! \n";
                                 esac;
                                 say "\n \n"; le_print le; say "\n For Types: \n";  
                                 say_uniqtypoid lt; say "\n and   \n    "; 
                                 apply (\\ x => { say_uniqtype x; say "\n";}; end ) ts;   say "\n \n";  
                                 say "***************************************************** \n"; 
                                 bug "fatal typing error in lt_ty_app";
                             };

                fun lt_match le s (t1, t2)
                    = 
                    if (not (lt_equiv (t1, t2)))
                        clickerror();
                        say (s + "  **** Lty conflicting in Lambda_Expression =====> \n    ");
                        say_uniqtypoid t1; say "\n and   \n    ";
                        say_uniqtypoid t2;
                        say "\n \n";  prettyprint_lambdacode_expression::print_lexp le;
                        say "***************************************************** \n";
                    fi
                    except
                        zz = {   clickerror();
                                 say (s + "  **** Lty conflicting in Lambda_Expression =====> \n    ");
                                 say "uncaught exception found ";
                                 say "\n \n";
                                 prettyprint_lambdacode_expression::print_lexp le;
                                 say "\n";  
                                 say_uniqtypoid t1;
                                 say "\n and   \n    ";
                                 say_uniqtypoid t2;
                                 say "\n";  
                                 say "***************************************************** \n";
                             };

                fun lt_fn_app le s (t1, t2)
                    = 
                    b1
                    where
                        my (a1, b1)
                            = 
                            (lt_arrow t1)
                            except
                                zz = {   clickerror ();
                                         say (s + "  **** Applying Non-Arrow Type in Lambda_Expression =====> \n    ");
                                         case zz    LTY_ARROW => say "exception LTY_ARROW raised. \n";
                                                   hcf::UNBOUND_TYPE => say "exception UNBOUND_TYPE raised. \n";
                                                   _ => say "other weird exceptions raised\n"; esac;
                                         say "\n \n";  le_print le; say "\n For Types \n";
                                         say_uniqtypoid t1; say "\n and   \n    "; say_uniqtypoid t2; say "\n \n";  
                                         say "***************************************************** \n"; 
                                         bug "fatal typing error in ltFnApp";
                                     };

                       lt_match le s (a1, t2);
                    end;

                fun lt_fn_app_r le s (t1, t2)                   # Used for DECON lexps.
                    =
                    a1
                    where
                        my (a1, b1)
                            = 
                            (lt_arrow t1)
                            except
                                zz = {   clickerror ();
                                         say (s + "  **** Rev-Apply Non-Arrow Type in Lambda_Expression =====> \n    ");
                                         case zz    LTY_ARROW => say "exception LTY_ARROW raised. \n";
                                                   hcf::UNBOUND_TYPE => say "exception UNBOUND_TYPE raised. \n";
                                                   _ => say "other weird exceptions raised\n"; esac;
                                         say "\n \n";  le_print le; say "\n For Types \n";
                                         say_uniqtypoid t1; say "\n and   \n    "; say_uniqtypoid t2; say "\n \n"; 
                                         say "***************************************************** \n"; 
                                         bug "fatal typing error in ltFnApp";
                                     };

                        lt_match le s (b1, t2);
                    end;

                fun lt_select le s (lt, i)
                    = 
                    (lt_sel (lt, i))
                    except
                        zz = {
                                  clickerror ();
                                  say (s + "  **** Select from a wrong-type Lambda_Expression  =====> \n    ");

                                  case zz    LTY_SELECT        => say "exception LTY_SELECT raised. \n";
                                            hcf::UNBOUND_TYPE => say "exception UNBOUND_TYPE raised. \n";
                                            _                  => say "other weird exceptions raised\n";
                                  esac;

                                  say "\n \n";  le_print le; say "\n \n";
                                  say "Selecting "; say (int::to_string i); 
                                  say "-th component from the type: \n     "; say_uniqtypoid lt; say "\n \n "; 
                                  say "***************************************************** \n"; 
                                  bug "fatal typing error in ltSelect";
                             };

                # ltConChk currently does not check the case for Valcon 
                # Of course, we could easily check for typelocked Valcons 
                #
                fun lt_con_check le s (valcon ((_, representation, lt), ts, v), root, kenv, venv, d)
                        => 
                        {   t1 = lt_ty_app le "DECON" (lt, ts, kenv);
                            t = lt_fn_app_r le "DECON" (t1, root);
                            hcf::set_uniqtypoid_for_var (venv, v, t, d);
                        };

                    lt_con_check le s (c, root, kenv, venv, d)
                        => 
                        {   nt = case c
                                     int1con  _ => hcf::int1_uniqtypoid;
                                     word32con _ => hcf::int1_uniqtypoid;
                                     realcon   _ => hcf::float64_uniqtypoid;
                                     stringcon _ => lt_string;
                                     integercon _ => bug "INTEGERcon";
                                      _ => hcf::int_uniqtypoid;
                                 esac;

                            lt_match le s (nt, root);

                            venv;
                        };
                end;


                # check:  tkindDict * ltyDict * di::depth -> Lambda_Expression -> Uniqtypoid 
                #
                fun check (kenv, venv, d)
                    = 
                    loop
                    where
                        fun loop le
                            =
                            case le

                                VAR v
                                    => 
                                    hcf::get_uniqtypoid_for_var (venv, v, d) 
                                    except
                                        hcf::HIGHCODE_VARIABLE_NOT_FOUND
                                            =
                                            {   say ( "** lambda_variable ** "
                                                    + (lv::name_of_lambda_variable (v))
                                                    + " is unbound *** \n"
                                                    );
                                                bug "unexpected lambda code in checkLty";
                                            };

                                (INT   _ | WORD   _) =>  hcf::int_uniqtypoid;
                                (INT1 _ | WORD32 _) =>  hcf::int1_uniqtypoid;

                                REAL   _ =>  hcf::float64_uniqtypoid;
                                STRING _ =>  lt_string;

                                PRIM (p, t, ts)
                                    =>
                                    lt_ty_app le "PRIM" (t, ts, kenv); 

                                FN (v, t, e1)
                                    => 
                                    {   venv' = hcf::set_uniqtypoid_for_var (venv, v, t, d);
                                        result = check (kenv, venv', d) e1;
                                        lt_fun (t, result);                     # Handle both functions and generics.
                                    };

                                FIX (vs, ts, es, eb)
                                    => 
                                    {   fun h (dictionary, v . r, x . z) => h (hcf::set_uniqtypoid_for_var (dictionary, v, x, d), r, z);
                                            h (dictionary, [], []) => dictionary;
                                            h _ => bug "unexpected FIX namings in checkLty.";
                                        end;

                                        venv' = h (venv, vs, ts);

                                        nts = map (check (kenv, venv', d)) es;
                                        app2 (lt_match le "FIX1", ts, nts);

                                        check (kenv, venv', d) eb;
                                    };

                                APPLY (e1, e2)
                                    =>
                                    lt_fn_app le "APPLY" (loop e1, loop e2);

                                LET (v, e1, e2)
                                    => 
                                    {   venv' = hcf::set_uniqtypoid_for_var (venv, v, loop e1, d);
                                        check (kenv, venv', d) e2;
                                    };

                                TYPEFUN (ks, e)
                                    => 
                                    {   kenv' = hcf::set_in_kind_dictionary (kenv, ks);
                                        lt = check (kenv', venv, di::next d) e;
                                        hcf::make_typeagnostic_uniqtypoid (ks, [lt]);
                                    };

                                APPLY_TYPEFUN (e, ts)
                                    =>
                                    lt_ty_app le "APPLY_TYPEFUN" (loop e, ts, kenv);

                                GENOP (dictionary, p, t, ts)
                                    => 
                                    (   # Should type check dictionary also     XXX BUGGO FIXME
                                        lt_ty_app le "GENOP" (t, ts, kenv)
                                    );

                                PACK (lt, ts, nts, e)
                                    => 
                                    {   arg_type = lt_ty_app le "PACK-A" (lt, ts, kenv);
                                        lt_match le "PACK-M" (arg_type, loop e);
                                        lt_ty_app le "PACK-R" (lt, nts, kenv);
                                    };

                                CON ((_, representation, lt), ts, e)
                                    =>   
                                    {   t1 = lt_ty_app le "CON" (lt, ts, kenv);
                                        t2 = loop e;
                                        lt_fn_app le "CON-A" (t1, t2);
                                    };

#                               DECON((_, representation, lt), ts, e) =>   
#                                  let t1 = ltTyApp le "DECON" (lt, ts, kenv)
#                                      t2 = loop e
#                                   in ltFnAppR le "DECON" (t1, t2)
#                                  end

                                RECORD el
                                    =>
                                    lt_tup (map loop el);

                                PACKAGE_RECORD el
                                    =>
                                    hcf::make_package_uniqtypoid (map loop el);

                                VECTOR (el, t)
                                    => 
                                    {   ts = map loop el;

                                        apply
                                            (\\ x = lt_match le "VECTOR" (x, hcf::make_type_uniqtypoid t))
                                            ts; 

                                        lt_vector t;
                                    };

                                SELECT (i, e)
                                    =>
                                    lt_select le "SEL" (loop e, i);

                                SWITCH (e, _, cl, opp)
                                    => 
                                    {   root = loop e;

                                        fun h (c, x)
                                            = 
                                            {   venv' = lt_con_check le "SWT1" (c, root, kenv, venv, d);
                                                check (kenv, venv', d) x; 
                                            };

                                        ts = map h cl;

                                        case ts

                                            [] => bug "empty switch in checkLty";

                                            a . r
                                                => 
                                                {   apply
                                                        (\\ x = lt_match le "SWT2" (x, a))
                                                        r;

                                                    case opp

                                                        NULL => a;

                                                        THE be
                                                            =>
                                                            {   lt_match le "SWT3" (loop be, a);
                                                                a;
                                                            };
                                                    esac;
                                                };
                                        esac;
                                   };

                                EXCEPTION_TAG (e, t)
                                    => 
                                    {   z = loop e;                     # What do we check on e ? 
                                        lt_match le "ETAG1" (z, hcf::string_uniqtypoid); 
                                        lt_etag t;
                                    };

                                RAISE (e, t)
                                    => 
                                    {   lt_match le "RAISE" (loop e, lt_exn);
                                        t;
                                    };

                                EXCEPT (e1, e2)
                                    => 
                                    {   t1 = loop e1;
                                        arg = lt_fn_app_r le "EXCEPT" (loop e2, t1);
                                        t1;
                                    };

                                # These two cases should never
                                # happen before wrapping:
                                #
                                WRAP (t, b, e)
                                    => 
                                    {   lt_match le "WRAP" (loop e, hcf::make_type_uniqtypoid t); 

                                        if (later_phase (phase))

                                            hcf::void_uniqtypoid;
                                        else
                                            hcf::make_type_uniqtypoid
                                              (b   ??   hcf::make_boxed_uniqtype t
                                                   ::   hcf::make_abstract_uniqtype t
                                              );
                                        fi;
                                    };

                                UNWRAP (t, b, e)
                                    => 
                                    {   ntc =   if   (later_phase phase)   hcf::void_uniqtype;
                                                elif b                     hcf::make_boxed_uniqtype t;
                                                else                       hcf::make_abstract_uniqtype t;
                                                fi;

                                        nt = hcf::make_type_uniqtypoid ntc;

                                        lt_match le "UNWRAP" (loop e, nt);

                                        hcf::make_type_uniqtypoid t;
                                    };
                            esac;
                 end;                           # fun check 


                anyerror := FALSE;

                check
                    ( hcf::empty_debruijn_to_uniqkind_listlist,
                      hcf::empty_highcode_variable_to_uniqtypoid_map,
                      di::top
                    )
                    lambda_expression;

                *anyerror;
            };                                  # fun check_lty 

    };                                          # package check_lty 
end;                                            # toplevel stipulate 



Comments and suggestions to: bugs@mythryl.org

PreviousUpNext