PreviousUpNext

15.4.389  src/lib/compiler/back/low/tools/adl-syntax/adl-raw-syntax-translation.pkg

## adl-raw-syntax-translation.pkg

# Compiled by:
#     src/lib/compiler/back/low/tools/sml-ast.lib

# Translation from one sort to another



###                "Above the cloud with its shadow
###                 is the star with its light.
###                 Above all things reverence thyself."
###
###                                -- Pythagoras



stipulate
    package htb =  hashtable;                                                           # hashtable                                     is from   src/lib/src/hashtable.pkg
    package lem =  lowhalf_error_message;                                               # lowhalf_error_message                         is from   src/lib/compiler/back/low/control/lowhalf-error-message.pkg
    package spp =  simple_prettyprinter;                                                # simple_prettyprinter                          is from   src/lib/prettyprint/simple/simple-prettyprinter.pkg
    package rrs =  adl_rewrite_raw_syntax_parsetree;                                    # adl_rewrite_raw_syntax_parsetree              is from   src/lib/compiler/back/low/tools/adl-syntax/adl-rewrite-raw-syntax-parsetree.pkg
    package raw =  adl_raw_syntax_form;                                                 # adl_raw_syntax_form                           is from   src/lib/compiler/back/low/tools/adl-syntax/adl-raw-syntax-form.pkg
    package rsu =  adl_raw_syntax_unparser;                                             # adl_raw_syntax_unparser                       is from   src/lib/compiler/back/low/tools/adl-syntax/adl-raw-syntax-unparser.pkg
herein

    # This package is referenced in:
    #     src/lib/compiler/back/low/tools/arch/make-sourcecode-for-backend-packages.pkg
    #     src/lib/c-glue/ml-grinder/ml-grinder.pkg
    #     src/lib/compiler/back/low/tools/rewrite-generator/glue.pkg

    package  adl_raw_syntax_translation
    : (weak) Adl_Raw_Syntax_Translation                                                 # Adl_Raw_Syntax_Translation                    is from   src/lib/compiler/back/low/tools/adl-syntax/adl-raw-syntax-translation.api
    {
        fun error msg
            =
            lem::error("adl_raw_syntax_translation", msg);

        Map(X) =  { orig_name:  raw::Id,
                    new_name:   raw::Id,
                    type:       raw::Type
                   }
                   -> X;

        Folder(X)
            =
            ( { orig_name:  raw::Id,
                new_name:   raw::Id,
                type:       raw::Type
              },
              X
            )
            -> X;

        fun id x =   raw::ID_IN_EXPRESSION (raw::IDENT ([], x));

        exception NO_NAME;

        # Treat a type expression as a pattern
        # and compute its set of  variable namings.
        # Duplicates are given unique suffixes.  

        fun namings_in_type  type
            = 
            {   names_hashtable
                    =
                    htb::make_hashtable
                        (hash_string::hash_string, (==))
                        { size_hint => 32,  not_found_exception => NO_NAME };

                variables = REF 0;

                fun enter_name id
                    = 
                    {   variables := *variables + 1;
                        #
                        (htb::look_up  names_hashtable  id)
                            ->
                            (_, total_count);

                        total_count := *total_count + 1;
                    }
                    except
                        _ =  htb::set names_hashtable (id, (REF 0, REF 1));

                fun enter (raw::IDTY    (raw::IDENT(_, id))) => enter_name id;
                    enter (raw::TYVARTY (raw::VARTV id)) => enter_name id;
                    enter (raw::APPTY   (raw::IDENT(_, id), _)) => enter_name id;
                    enter (raw::REGISTER_TYPE id) => enter_name id;                                             # This (with id=="bar") came from a   foo: $bar   declaration -- the '$' distinguishes these from regular type declarations.
                    enter (raw::TUPLETY tys) => apply enter tys;
                    enter (raw::RECORDTY ltys) => apply (\\ (id, _) = enter_name id) ltys;
                    enter t => error("namingsInType: " + spp::prettyprint_expression_to_string (rsu::type t));
                end;

                strip_ticks =   string::map  \\ '\'' => 't';
                                                  c  => c;
                                             end; 

                fun get_name id 
                    = 
                    {   (htb::look_up  names_hashtable  id)
                            ->
                            (current_count, total_count);

                        strip_ticks(
                            if   (*total_count == 1)

                                 id; #  use the same name 
                            else 
                                 current_count := *current_count + 1;
                                 id + int::to_string *current_count;
                            fi
                        );
                    };
              enter type;
                (*variables, get_name);
            };


        # Translate a type into a pattern expression

        fun map_ty_to_pattern f' type
            =
            {   my (_, get_name) = namings_in_type type;

                fun f (id, type)
                    =
                    f'{ orig_name=>id, new_name=>get_name id, type };

                fun g (raw::IDTY (raw::IDENT(_, id)), type) => f (id, type);
                    g (raw::TYVARTY (raw::VARTV id), type) => f (id, type);
                    g (raw::APPTY (raw::IDENT(_, id), _), type) => f (id, type);
                    g (raw::REGISTER_TYPE id, type) => f (id, type);                            # This (with id=="bar") came from a   foo: $bar   declaration -- the '$' distinguishes these from regular type declarations.
                    g (raw::TUPLETY tys, _) => raw::TUPLEPAT (map g' tys);
                    g (raw::RECORDTY ltys, _) => raw::RECORD_PATTERN (map h ltys, FALSE);
                    g (t, _) => error("tyToPattern: " + spp::prettyprint_expression_to_string (rsu::type t));
                end 

                also
                fun g' t = g (t, t)

                also
                fun h (lab, type) = (lab, f (lab, type));

                g' type;
            };

        fun fold_type f' x type
            =
            {   my (_, get_name) = namings_in_type type;

                fun f (id, type, x)
                    =
                    f'( { orig_name=>id, new_name=>get_name id, type }, x);

                fun g (raw::IDTY (raw::IDENT(_, id)), type, x) => f (id, type, x);
                    g (raw::TYVARTY (raw::VARTV id), type, x) => f (id, type, x);
                    g (raw::APPTY (raw::IDENT(_, id), _), type, x) => f (id, type, x);
                    g (raw::REGISTER_TYPE id, type, x) => f (id, type, x);
                    g (raw::TUPLETY tys, type, x) => fold_backward g' x (reverse tys);
                    g (raw::RECORDTY ltys, type, x) => fold_backward h x (reverse ltys);
                    g (t, type, x) => error("foldTyNamings: " + spp::prettyprint_expression_to_string (rsu::type t));
                end 

                also
                fun g'(t, x) = g (t, t, x)

                also
                fun h ((lab, type), x) = f (lab, type, x);

                g'(type, x);
            };

        fun fold_cons f x (raw::CONSTRUCTOR { type => NULL,     ... } ) =>  x;
            fold_cons f x (raw::CONSTRUCTOR { type => THE type, ... } ) =>  fold_type f x type;
        end;


        # Translate a type into an expression
        #
        fun map_ty_to_expression f' type
            =
            {   my (_, get_name) = namings_in_type type;

                fun f (id, type)
                    =
                    f'{ orig_name=>id, new_name=>get_name id, type };

                fun g (raw::IDTY (raw::IDENT(_, id)), type) => f (id, type);
                    g (raw::TYVARTY (raw::VARTV id), type) => f (id, type);
                    g (raw::APPTY (raw::IDENT(_, id), _), type) => f (id, type);
                    g (raw::REGISTER_TYPE id, type) => f (id, type);                                            # This (with id=="bar") came from a   foo: $bar   declaration -- the '$' distinguishes these from regular type declarations.
                    g (raw::TUPLETY tys, type) => raw::TUPLE_IN_EXPRESSION (map g' tys);
                    g (raw::RECORDTY ltys, type) => raw::RECORD_IN_EXPRESSION (map h ltys);
                    g (t, _) => error("tyToPattern: " + spp::prettyprint_expression_to_string (rsu::type t));
                end 

                also
                fun g' t = g (t, t)

                also
                fun h (lab, type) = (lab, f (lab, type));

                g' type; 
            };


        # Translate a constructor into a pattern:
        #
        fun map_cons_to_pattern { prefix, id } (raw::CONSTRUCTOR { name, type, ... } )
            =
            raw::CONSPAT (raw::IDENT (prefix, name), null_or::map (map_ty_to_pattern id) type);


        # Translate a constructor into an expression:
        #
        fun map_cons_to_expression { prefix, id } (raw::CONSTRUCTOR { name, type, ... } )
            =
            raw::CONSTRUCTOR_IN_EXPRESSION (raw::IDENT (prefix, name), null_or::map (map_ty_to_expression id) type);


        fun map_cons_arg_to_expression id (raw::CONSTRUCTOR { type => NULL,     ... } ) =>   raw::TUPLE_IN_EXPRESSION [];
            map_cons_arg_to_expression id (raw::CONSTRUCTOR { type => THE type, ... } ) =>   map_ty_to_expression id type;
        end;


        fun map_cons_to_clause { prefix, pattern, expression } cons
            = 
            raw::CLAUSE
              (
                [ pattern (map_cons_to_pattern 
                              { prefix,
                                id => \\ { new_name, ... } = raw::IDPAT new_name
                              }
                              cons
                          )
                ],
                NULL,
                expression
              );

        fun cons_namings cons
            =
            {   fun enter ( { new_name, orig_name, type }, namings)
                    =
                    (new_name, type) ! namings;

                namings = fold_cons enter [] cons; 

                fun look_up (the_id:  raw::Id)
                    =
                    find namings
                    where
                        fun find ((b as (x, t)) ! bs) => if (x == the_id ) (id x, t); else find bs;fi; 
                            find [] => raise exception NO_NAME;
                        end;
                    end;

                look_up;
            };

        #  Simplification:
        #
        stipulate

            fun has_namings ps
                = 
                {   namings = REF FALSE;

                    fun rewrite_pattern_node _ (p as raw::IDPAT x) => { namings := TRUE; p;}; 
                        rewrite_pattern_node _ p => p;
                    end;

                    apply
                        (\\ p
                            =
                            {   
                                fns.rewrite_pattern_parsetree   p
                                where
                                    fns =  rrs::make_raw_syntax_parsetree_rewriters [ rrs::REWRITE_PATTERN_NODE rewrite_pattern_node ];
                                end;

                                ();
                            }
                        )
                        ps;

                    *namings;
                };

            fun all_the_same []
                    =>
                    TRUE;

                all_the_same (x ! xs)
                    =>
                    list::all
                        (\\ x' =  x == x')
                        xs;
            end;

            exception DO_NOT_APPLY;

            fun reduce_expression ===> (expression as raw::CASE_EXPRESSION (e,[]))
                    =>
                    expression;

                reduce_expression ===> (raw::SEQUENTIAL_EXPRESSIONS es)
                    =>
                    (raw::SEQUENTIAL_EXPRESSIONS
                        (fold_backward
                            \\ (raw::TUPLE_IN_EXPRESSION [], es)                =>   es;
                                (raw::SEQUENTIAL_EXPRESSIONS [], es) =>   es;
                                (e, es)                            =>   e ! es;
                            end 
                             [] es)
                    );

                reduce_expression ===> (expression as raw::CASE_EXPRESSION (e, all_cs as (c as raw::CLAUSE (p1, NULL, e1)) ! cs))
                    => 
                    {   ps' =   fold_backward  collect  []  (c ! cs)
                                where
                                    fun collect (raw::CLAUSE ([p], NULL, e), ps')
                                            =>
                                            ins ps'
                                            where
                                                fun ins ((ps, e') ! ps')
                                                        => 
                                                        if (e == e' )   (p ! ps, e )  !      ps';
                                                        else            (    ps, e')  !  ins ps';
                                                        fi;

                                                    ins [] =>   [ ([p], e) ];
                                                end;
                                            end;

                                        collect _ =>   error "Unsupported case in reduce_expression/collect.";
                                    end;
                                end;


                        fun or_pattern [p]
                                =>
                                p;

                            or_pattern ps
                                =>
                                if  (list::all
                                        #
                                        \\  raw::WILDCARD_PATTERN => TRUE;
                                            _                     => FALSE;
                                        end
                                        #
                                        ps
                                    )
                                    #
                                    raw::WILDCARD_PATTERN;
                                else
                                    raw::OR_PATTERN ps;
                                fi;
                        end;  

                        fun tuplepat [p] =>  p;
                            tuplepat ps  =>  raw::TUPLEPAT  ps;
                        end;


                        fun join ([p], e)
                                =>
                                raw::CLAUSE([p], NULL, e);

                            join (ps, e)
                                => 
                                {   xs = map   \\ raw::TUPLEPAT (p ! ps) =>  (p, ps);
                                                  _                    =>  raise exception DO_NOT_APPLY;
                                               end

                                               ps;

                                    first_pats = map #1 xs;
                                    rest_pats  = map #2 xs;

                                    if (all_the_same (map tuplepat rest_pats))
                                        # 
                                        raw::CLAUSE([tuplepat (or_pattern first_pats ! head rest_pats)], NULL, e);
                                    else
                                        raise exception DO_NOT_APPLY;
                                    fi;
                                }
                                except
                                    DO_NOT_APPLY =   raw::CLAUSE ([or_pattern ps], NULL, e);
                        end;

                        cs = map join (reverse ps');

                        case cs
                            #
                            [raw::CLAUSE([raw::TUPLEPAT []], NULL, body)]            =>  body;
                            [raw::CLAUSE([_], NULL, body as raw::LIST_IN_EXPRESSION([], NULL))] =>  body;
                            #
                            [raw::CLAUSE([raw::TUPLEPAT ps], NULL, body)]
                                => 
                                if (not (has_namings ps))
                                    #
                                    body;
                                else
                                    fun elim_or  (pattern as raw::OR_PATTERN p)
                                            =>
                                            if (has_namings p)   pattern;
                                            else                 raw::WILDCARD_PATTERN;
                                            fi;

                                         elim_or  pattern
                                            =>
                                            pattern;
                                    end;

                                    raw::CASE_EXPRESSION (e,
                                        [raw::CLAUSE([raw::TUPLEPAT (map elim_or ps)], NULL, body)]);
                                fi;

                            [raw::CLAUSE (ps, NULL, body)]
                                => 
                                if (has_namings ps)   raw::CASE_EXPRESSION (e, cs);
                                else                  body;
                                fi;

                            _ => raw::CASE_EXPRESSION (e, cs);
                        esac; 
                    };

                reduce_expression ===> (expression as raw::IF_EXPRESSION (a, b, c))
                    =>
                    if (b == c)   b;
                    else          expression;
                    fi;

                reduce_expression ===> e
                    =>
                    e;
            end;

            simplifier
                = 
                rrs::make_raw_syntax_parsetree_rewriters [ rrs::REWRITE_EXPRESSION_NODE reduce_expression ];
        herein

            simplify_expression  =  simplifier.rewrite_expression_parsetree;
            simplify_declaration =  simplifier.rewrite_declaration_parsetree;
            simplify_pattern     =  simplifier.rewrite_pattern_parsetree;
            simplify_sexp        =  simplifier.rewrite_statement_parsetree;
            simplify_type        =  simplifier.rewrite_type_parsetree;

            fun strip_marks  d                                                                          # Drop line number information from a declaration.
                =
                {   fun rewrite_declaration_node ===> (raw::SOURCE_CODE_REGION_FOR_DECLARATION (_, d))
                            =>
                            d;

                        rewrite_declaration_node ===> d
                            =>
                            d;
                    end;


                    fns.rewrite_declaration_parsetree  d
                    where       
                        fns =  rrs::make_raw_syntax_parsetree_rewriters [ rrs::REWRITE_DECLARATION_NODE rewrite_declaration_node ];
                    end;
                };
        end;                                                                                            # stipulate
    };                                                                                                  # package   adl_raw_syntax_translation
end;                                                                                                    # stipulate


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext