PreviousUpNext

15.4.428  src/lib/compiler/back/low/tools/match-compiler/match-gen-g.pkg

# match-gen-g.pkg
# Interface with the match compiler to generate Mythryl code.

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



###                        "Do not eat your heart."
###
###                                   -- Pythagoras



# 2008-01-29 CrT:   So far as I can tell, this generic is not invoked
#                   by the compiler mainline.  It -is- invoked by:
#
#                       src/lib/c-glue/ml-grinder/ml-grinder.pkg
#                       src/lib/compiler/back/low/tools/nowhere/nowhere.pkg
#                       src/lib/compiler/back/low/tools/match-compiler/test-match-g.pkg
#
#                   Compiler mainline pattern-match compilation is handled by
#
#                       src/lib/compiler/back/top/translate/translate-deep-syntax-pattern-to-lambdacode.pkg 
#

stipulate
    package ils =  int_list_set;                                                        # int_list_set                                  is from   src/lib/src/int-list-set.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
herein

    # This generic is invoked in:
    #
    #     src/lib/compiler/back/low/tools/nowhere/nowhere.pkg
    #
    #     src/lib/c-glue/ml-grinder/ml-grinder.pkg (broken)
    #     src/lib/compiler/back/low/tools/match-compiler/test-match-g.pkg (broken)
    #
    generic package   match_gen_g   (
        #             ===========
        #
        package rsu:    Adl_Raw_Syntax_Unparser;                                        # Adl_Raw_Syntax_Unparser                       is from   src/lib/compiler/back/low/tools/adl-syntax/adl-raw-syntax-unparser.api
        package rsj:    Adl_Raw_Syntax_Junk;                                            # Adl_Raw_Syntax_Junk                           is from   src/lib/compiler/back/low/tools/adl-syntax/adl-raw-syntax-junk.api
    )
    : (weak) Match_G                                                                    # Match_G                                       is from   src/lib/compiler/back/low/tools/match-compiler/match-g.api
    {
        # Exported to clients:
        #     mc
        #     lit_map
        #     dictionary
        #

        stipulate
            package rsu =  rsu;                                                         # "rsu" == "raw_syntax_unparser".
        herein

            ++ = spp::CONS;

            infix my ++ ;

            i2s =  int::to_string;

            package guard {
                #
                Guard = (Int, raw::Expression);

                fun to_string (_, e)
                    =
                    spp::prettyprint_expression_to_string (rsu::expression e);

                fun compare ((i, _), (j, _))
                    =
                    int::compare (i, j); 

                counter = REF 0;

                fun guard e
                    =
                    (*counter, e)
                    then
                        counter := *counter + 1;

                fun logical_and ((_, x), (_, y))
                    =
                    guard
                        (rsj::and_fn (x, y));
            };

            package expression {
                #
                Expression =  raw::Expression;
                to_string  =  spp::prettyprint_expression_to_string o rsu::expression;
            };

            package literal {
                #
                Literal   =  raw::Literal;
                to_string =  spp::prettyprint_expression_to_string o rsu::literal;
                compare   =  rsj::compare_literal;
                bools     =  THE { others => FALSE,
                                   known  => [raw::BOOL_LIT FALSE, raw::BOOL_LIT TRUE]
                                 };

                fun variants (raw::BOOL_LIT _) =>  bools;
                    variants _              =>  NULL;
                end; 

                package map
                    =
                    red_black_map_g (                                                   # red_black_map_g               is from   src/lib/src/red-black-map-g.pkg
                        Key =  Literal;
                        compare =  compare;
                    );
            };

            package lit_map                                                             # Exported to client packages.
                =
                literal::map;

            Valcon_Form
                =
                VALCON_FORM  (List( raw::Id ), raw::Constructor, raw::Sumtype) 
                |
                EXCEPTION  (List( raw::Id ), raw::Id, Null_Or( raw::Type ));

            package con {
                #
                Con =  Valcon_Form; 


                fun to_string (VALCON_FORM (path, raw::CONSTRUCTOR { name, ... }, _))
                        => 
                        spp::prettyprint_expression_to_string (rsu::uppercase_ident (raw::IDENT (path, name)));

                    to_string (EXCEPTION (path, id, type))
                        =>
                        spp::prettyprint_expression_to_string (rsu::uppercase_ident (raw::IDENT (path, id)));
                end;


                fun compare (VALCON_FORM(_, raw::CONSTRUCTOR { name=>x, ... }, _),
                             VALCON_FORM(_, raw::CONSTRUCTOR { name=>y, ... }, _))
                        =>
                        string::compare (x, y);

                    compare (EXCEPTION(_, x, _), EXCEPTION(_, y, _))
                        =>
                        string::compare (x, y);

                    compare (VALCON_FORM _, EXCEPTION _) =>  LESS;
                    compare (EXCEPTION _, VALCON_FORM _) =>  GREATER;
                end;


                fun variants (VALCON_FORM (path, _, dt as raw::SUMTYPE { cbs, ... } ))
                        =>
                        { others =>  FALSE,
                          known  =>  map
                                         (\\ c =  VALCON_FORM (path, c, dt))
                                         cbs
                        };

                    variants (EXCEPTION _)
                        =>
                        { known => [],   others => TRUE };

                    variants _ =>   raise exception DIE "Bug: Unsupported case in 'variants'.";
                end;


                fun arity (VALCON_FORM (_, raw::CONSTRUCTOR { type => NULL,     ... }, _)) =>  0;
                    arity (VALCON_FORM (_, raw::CONSTRUCTOR { type => THE type, ... }, _)) =>  1;
                    #
                    arity (EXCEPTION(_, _, NULL))  =>  0;
                    arity (EXCEPTION(_, _, THE _)) =>  1;
                end;
            };

            package variable {
                #
                Var = raw::Id;

                compare =  string::compare; 

                fun to_string x
                    =
                    x;

                package map
                    =
                    red_black_map_g (                                           # red_black_map_g               is from   src/lib/src/red-black-map-g.pkg
                        Key = Var; 
                        compare = compare;
                    );

                package set
                    =
                    red_black_set_g (
                        Key = Var; 
                        compare = compare;
                    );
            };

            package action {
                #
                Action = raw::Expression;

                to_string
                    =
                    spp::prettyprint_expression_to_string o rsu::expression;

                fun free_vars e
                    =
                    {   fvs =  REF  variable::set::empty;

                        fun expression _ (e as raw::ID_IN_EXPRESSION (raw::IDENT([], x)))
                                => 
                                {   fvs := variable::set::add(*fvs, x);
                                    e;
                                };

                            expression _ e
                                =>
                                e;
                        end;


                        (rrs::make_raw_syntax_parsetree_rewriters [ rrs::REWRITE_EXPRESSION_NODE expression ]).rewrite_expression_parsetree
                            e;

                        variable::set::vals_list  *fvs;
                    }; 
            };

            package mc                                                  # Exported to client packages.
                =
                match_compiler_g (                                      # match_compile_g       is from   src/lib/compiler/back/low/tools/match-compiler/match-compiler-g.pkg
                    #
                    package gua =  guard;
                    package exp =  expression;
                    package lit =  literal;
                    package con =  con;
                    package var =  variable;
                    package act =  action;
                );

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

            fun state_fn x
                =
                "state_" + (i2s x);

            exception MATCH_COMPILER = mc::MATCH_COMPILER;

            package dictionary {
                #
                Dictionary
                    =
                    DICTIONARY
                      { cons: variable::map::Map( Valcon_Form ),
                        sigs: variable::map::Map( Dictionary )
                      };

                fun insert_cons (DICTIONARY { cons, sigs }, id, pick_valcon_form)
                    =
                    DICTIONARY {
                      cons => variable::map::set (cons, id, pick_valcon_form),
                      sigs
                    };

                fun bind_api_identifier (DICTIONARY { cons, sigs }, id, dictionary)
                    =
                    DICTIONARY {
                      cons,
                      sigs => variable::map::set (sigs, id, dictionary)
                    };

                fun lookup_sig  (DICTIONARY { sigs, ... }, id) =  variable::map::get (sigs, id);
                fun lookup_cons (DICTIONARY { cons, ... }, id) =  variable::map::get (cons, id);

                empty = DICTIONARY
                          {
                            cons => variable::map::empty,
                            sigs => variable::map::empty
                          };
            };

            Compiled_Type_Info
                =
                dictionary::Dictionary; 

            # Enter all sumtypes
            # definitions into a list:
            #
            fun compile_types ds
                =
                decls (ds, dictionary::empty)
                where
                    fun decl (raw::SUMTYPE_DECL (dbs, _),                    dictionary) =>  dbinds (dbs, dictionary);
                        decl (raw::EXCEPTION_DECL ebs,                        dictionary) =>  ebinds (ebs, dictionary);
                        decl (raw::SOURCE_CODE_REGION_FOR_DECLARATION(_, d),  dictionary) =>  decl (d, dictionary);

                        decl (raw::API_DECL (id, raw::DECLARATIONS_API ds),            dictionary) =>  decls (ds, dictionary);
                        decl (raw::PACKAGE_DECL (id, _, _, raw::DECLSEXP ds),  dictionary) =>  nested (id, ds, dictionary);

                        decl (raw::SEQ_DECL ds,                                dictionary) =>  decls (ds, dictionary);
                        decl (_,                                              dictionary) =>  dictionary;
                    end 

                    also
                    fun decls (ds, dictionary)
                        =
                        list::fold_backward decl dictionary ds 

                    also
                    fun dbind (t as raw::SUMTYPE { cbs, ... }, dictionary)
                            => 
                            list::fold_backward
                                (\\ (c as raw::CONSTRUCTOR { name, ... }, dictionary)
                                    =
                                    dictionary::insert_cons (dictionary, name, VALCON_FORM([], c, t))
                                )
                                dictionary
                                cbs;

                        dbind(_, dictionary)
                            =>
                            dictionary;
                    end 

                    also
                    fun dbinds (dbs, dictionary)
                        =
                        list::fold_backward dbind dictionary dbs

                    also
                    fun ebind (raw::EXCEPTION (id, type), dictionary)
                            =>
                            dictionary::insert_cons (dictionary, id, EXCEPTION([], id, type));

                        ebind(_, dictionary)
                            =>
                            dictionary;
                     end 

                    also
                    fun ebinds (ebs, dictionary)
                        =
                        list::fold_backward ebind dictionary ebs

                    also
                    fun nested (id, ds, dictionary)
                        = 
                        {   dictionary' = decls (ds, dictionary::empty); 
                            dictionary::bind_api_identifier (dictionary, id, dictionary');
                        };
                end;

            fun pr_clause (p, g)
                = 
                spp::prettyprint_expression_to_string
                    (   rsu::pattern p ++ spp::MAYBE_BLANK
                         ++ 
                         case g    NULL  =>  spp::ALPHABETIC  "=> ...";
                                   THE e =>  spp::ALPHABETIC  "where ... => ...";
                         esac
                    );

            fun compile dictionary clauses
                =
                {   # Rename all rules 

                    fun has_con x
                        =
                        not_null (dictionary::lookup_cons (dictionary, x));

                    fun lookup (dictionary, path,[], x)
                            => 
                            case (dictionary::lookup_cons (dictionary, x))
                                #
                                THE (VALCON_FORM(_, c, t))
                                    =>
                                    VALCON_FORM (path, c, t);

                                THE (EXCEPTION(_, id, t))
                                    =>
                                    EXCEPTION (path, id, t);

                                NULL =>   raise exception MATCH_COMPILER ("undefined constructor " + x);
                            esac;

                        lookup (dictionary, path, p ! ps, x)
                            => 
                            case (dictionary::lookup_sig (dictionary, p))
                                #
                                THE dictionary
                                    =>
                                    lookup (dictionary, path, ps, x);

                                NULL =>
                                    raise exception MATCH_COMPILER("undefined package " + p + " in " +
                                                      spp::prettyprint_expression_to_string (rsu::lowercase_ident (raw::IDENT (path, x))));
                            esac;

                    end;

                    fun lookup_con (raw::IDENT (p, x))
                        =
                        lookup (dictionary, p, p, x);

                    # Rewrite list patterns 
                    #
                    fun trans_list_pattern p
                        = 
                        {   fun cons (x, y)
                                =
                                raw::CONSPAT (raw::IDENT([], "::"), THE (raw::TUPLEPAT [x, y]));

                            nil = raw::CONSPAT (raw::IDENT([], "NIL"), NULL);

                            fun listify ([], THE p) =>  p;
                                listify ([], NULL)  =>  nil;
                                listify (p ! ps, t) =>  cons (p, listify (ps, t));
                            end;

                            fun pattern _ (raw::LISTPAT (ps, t)) => listify (ps, t);
                                pattern _ p => p;
                            end;

                            fns =  rrs::make_raw_syntax_parsetree_rewriters [ rrs::REWRITE_PATTERN_NODE pattern ];

                            fns.rewrite_pattern_parsetree  p;
                        }; 

                    rule_no =  REF 0;

                    fun rename_rule (c as raw::CLAUSE ([pattern], guard, e))
                            =>
                            {   my (e, match_fail_exception)
                                    =
                                    case e
                                         raw::MATCH_FAIL_EXCEPTION_IN_EXPRESSION (e, x)  =>  (e, THE x);  # Some odd extension -- 'x' names an exception 'FOO', from surface syntax   <pattern> <guard> exception FOO => <expression>; 
                                        _                                                =>  (e, NULL);
                                    esac;

                                mc::rename
                                    (\\ { id_pattern, as_pattern, cons_pattern, wild_pattern, 
                                         tuple_pattern, record_pattern, lit_pattern, 
                                         or_pattern, and_pattern, not_pattern, where_pattern, nested_pattern, ...
                                        }
                                        =
                                        \\  raw::ASPAT (id, p)            =>  as_pattern (id, p);
                                            raw::WILDCARD_PATTERN         =>  wild_pattern();
                                            raw::CONSPAT (c, NULL)        =>  cons_pattern (lookup_con c,[]);
                                            raw::CONSPAT (c, THE (p))     =>  cons_pattern (lookup_con c,[p]);
                                            raw::TUPLEPAT ps              =>  tuple_pattern ps;
                                            raw::RECORD_PATTERN (lps, _)  =>  record_pattern lps;
                                            raw::LITPAT lit               =>  lit_pattern lit;
                                            raw::OR_PATTERN ps            =>  or_pattern ps;
                                            raw::ANDPAT ps                =>  and_pattern ps;
                                            raw::NOTPAT p                 =>  not_pattern p;
                                            raw::WHEREPAT (p, e)          =>  where_pattern  (p, guard::guard e);
                                            raw::NESTEDPAT (p, e, p')     =>  nested_pattern (p, guard::guard e, p');

                                            raw::IDPAT id
                                                => 
                                                if (has_con  id)
                                                    #
                                                    cons_pattern (lookup_con (raw::IDENT([], id)),[]);
                                                else
                                                    id_pattern id;
                                                fi;


                                            p =>    raise exception mc::MATCH_COMPILER (   "illegal pattern "
                                                                                       +   spp::prettyprint_expression_to_string (rsu::pattern p)
                                                                                       );
                                        end
                                    )

                                    # (I think) our return record will be processed by   fun rename   in
                                    #     src/lib/compiler/back/low/tools/match-compiler/match-compiler-g.pkg
                                    #
                                    { number       => *rule_no, 
                                      patterns     => [trans_list_pattern  pattern],
                                      guard        => null_or::map guard::guard guard,
                                      action       => e,
                                      match_fail_exception      # Currently ignored. I think intended to allow end-user selection of exception generated on match failure. -- 2011-04-23 CrT
                                    }
                                    then
                                        rule_no :=  *rule_no + 1;
                            }
                            except
                                mc::MATCH_COMPILER msg
                                    =
                                    raise exception mc::MATCH_COMPILER (msg + " in " + pr_clause (pattern, guard));

                        rename_rule _ =>   raise exception DIE "Bug: Unsupported case in rename_rule";
                    end;                                                                                                        # fun rename_rule

                    rules =   map  rename_rule  clauses;

                    # Compile the rules into a dfa:
                    #
                    dfa = mc::compile
                            {
                              compiled_rules =>  rules,
                              compress       =>  TRUE
                            };

                    dfa;
                };              # fun compile



            # Report errors:
            #
            fun report { warning, error, log, dfa, rules }
                =  
                {   red =  mc::redundant  dfa;
                    ex  =  mc::exhaustive dfa;

                    bad =   ils::vals_count red   >   0;

                    error =   bad  ??  error
                                   ::  warning;

                    message
                        =
                        if ex
                            bad ?? "redundant matches"
                                :: "";
                        else 
                            bad ?? "non-exhaustive and redundant matches"
                                :: "non-exhaustive matches";
                        fi;

                    fun dump_rules (i, [])
                            =>
                            ();

                        dump_rules (i, r ! rules)
                            =>
                            {   tab =   if (ils::member (red, i))  "---> ";
                                        else                       "     ";
                                        fi;

                                my (p, g)
                                    =
                                    case r     raw::CLAUSE ([p], g, _)  =>   (p, g);
                                        /* */  _                        =>   raise exception DIE "Bug: Unsupported case in dump_rules.";
                                    esac;

                                text =  pr_clause (p, g);

                                log  (tab + text);

                                dump_rules (i+1, rules);
                            };
                    end;

                    if (not ex or bad)
                        #                 
                        error message;
                        dump_rules (0, rules);
                    fi;
                };

            exception GEN_REAL also GEN_INTEGER; 

            stipulate
                integer_compare =  raw::ID_IN_EXPRESSION (raw::IDENT (["integer"], "compare"));
                real_eq         =  raw::ID_IN_EXPRESSION (raw::IDENT (["Float"], "=="));        # XXX BUGGO FIXME does this need to change to "===="?
                eq              =  raw::ID_IN_EXPRESSION (raw::IDENT ([], "="));                # XXX BUGGO FIXME does this need to change to "=="?
                equal           =  raw::ID_IN_EXPRESSION (raw::IDENT ([], "EQUAL"));
            herein

                fun make_integer_eq (x, y)
                    =
                    raw::APPLY_EXPRESSION (
                        eq,
                        raw::TUPLE_IN_EXPRESSION [
                            raw::APPLY_EXPRESSION (
                                integer_compare,
                                raw::TUPLE_IN_EXPRESSION [x, y]
                            ),
                            equal
                        ]
                    );

                fun make_real_eq (x, y)
                    =
                    raw::APPLY_EXPRESSION (real_eq, raw::TUPLE_IN_EXPRESSION [x, y]);
            end;

            name_counter
                =
                REF 0;

            fun new_name ()
                =
                *name_counter
                then
                    name_counter :=  *name_counter + 1;

            fun init ()
                =
                name_counter := 0;


            # Generate Mythryl code:
            #
            fun code_gen { root, dfa, fail=>gen_fail, literals }
                =
                {   # Make unique name for path variables:

                    name_table
                        =
                        REF  mc::path::map::empty;

                    fun gen_lit (l as raw::INTEGER_LIT _)
                            => 
                            case (literal::map::get (*literals, l))
                                #                      
                                THE v =>   rsj::id v;  

                                NULL =>
                                    {   v =  "lit_" + i2s (new_name());

                                        literals :=   literal::map::set  (*literals, l, v);

                                        rsj::id  v;
                                    };
                            esac;

                        gen_lit l
                            =>
                            raw::LITERAL_IN_EXPRESSION l;
                    end;

                    fun get_name path
                        =
                        case (mc::path::map::get   (*name_table,  path))
                            #
                            THE name =>   name;
                            #
                            NULL =>
                                {   v =  "v_" + i2s (new_name());

                                    name_table
                                        :=
                                        mc::path::map::set  (*name_table, path, v);

                                    v;
                                };
                        esac;



                    # Now generate the code; we just
                    # have to hook things up with the MC 
                    #   
                    fun gen_variable path
                        =
                        get_name path;


                    fun gen_path path
                        =
                        id_fn (gen_variable path);


                    fun gen_bind []
                            =>
                            [];

                        gen_bind namings
                            =>
                            [   raw::VAL_DECL (
                                    map
                                        (\\ (v, e)
                                            =
                                            raw::NAMED_VARIABLE (raw::IDPAT v, e)
                                        )
                                        namings
                                )
                            ];
                    end;


                    fun gen_ok (e)
                        =
                        e;

                    fun path_to_pattern (path)
                        =
                        raw::IDPAT (get_name path);

                    fun arg  NULL   =>  raw::WILDCARD_PATTERN;
                        arg (THE p) =>  raw::IDPAT (get_name p);
                    end;


                    fun from_rep (VALCON_FORM (path, raw::CONSTRUCTOR c, _))
                            =>
                            raw::IDENT (path, c.name);

                        from_rep (EXCEPTION (path, id, _))
                            =>
                            raw::IDENT (path, id);
                    end;


                    fun gen_con_pattern (mc::CON con, [])
                            =>
                            raw::CONSPAT (from_rep con, NULL);

                        gen_con_pattern (mc::CON con, paths)
                            => 
                            raw::CONSPAT (from_rep con, THE (raw::TUPLEPAT (map arg paths)));

                        gen_con_pattern (mc::LIT (raw::FLOAT_LIT _), _)
                            =>
                            raise exception GEN_REAL;

                        gen_con_pattern (mc::LIT (raw::INTEGER_LIT _), _)
                            =>
                            raise exception GEN_INTEGER;

                        gen_con_pattern (mc::LIT lit, _)
                            =>
                            raw::LITPAT lit;
                    end;


                    fun gen_case (v, cases, default)
                        = 
                        raw::CASE_EXPRESSION
                          (
                            id_fn v,

                            map (\\ (con, paths, e)
                                    =
                                    raw::CLAUSE(  [gen_con_pattern (con, paths)],  NULL,  e)
                                )

                                cases
                                @
                                case default
                                    #
                                    NULL        =>  [];
                                    THE default =>  [raw::CLAUSE([raw::WILDCARD_PATTERN], NULL, default)];
                                esac
                          )
                        except
                            GEN_REAL    =>  gen_lit_cmp (make_real_eq,    v, cases, default);
                            GEN_INTEGER =>  gen_lit_cmp (make_integer_eq, v, cases, default);
                        end 

                    also
                    fun gen_lit_cmp (eq, v, cases, THE default)
                            =>
                            {   x =  id_fn v; 
                                #
                                fun equal lit
                                    =
                                    eq (x, gen_lit lit);

                                list::fold_backward  f  default  cases
                                where
                                    fun f ((mc::LIT lit, _, e), rest)
                                            =>
                                            raw::IF_EXPRESSION (equal lit, e, rest);

                                        f _ =>   raise exception DIE "Bug: Unsupported case in gen_lit_cmp.";
                                    end;
                                end;
                            };

                        gen_lit_cmp (_, _, _, NULL) =>   raise exception DIE "Bug: Unsupported case in gen_lit_cmp.";
                    end;


                    fun gen_if ((_, e), y, n)
                        =
                        raw::IF_EXPRESSION (e, y, n);


                    fun gen_goto (f, args)
                        =
                        raw::APPLY_EXPRESSION (id_fn (state_fn f), raw::TUPLE_IN_EXPRESSION (map id_fn args)); 


                    fun gen_fun (f, args, body)
                        = 
                        raw::FUN_DECL [
                            raw::FUN (
                                state_fn f,
                                [   raw::CLAUSE (
                                        [ raw::TUPLEPAT (map raw::IDPAT args) ],
                                        NULL,
                                        body
                                    )
                                ]
                            )
                        ];


                    fun gen_let ([], e) =>  e;
                        gen_let ( d, e) =>  raw::LET_EXPRESSION (d,[e]);
                    end;


                    fun gen_val (v, e)
                        =
                        raw::VAL_DECL [ raw::NAMED_VARIABLE (raw::IDPAT v, e) ];


                    fun gen_proj (path, namings)
                        =
                        {   pattern
                                =
                                case namings
                                    #
                                    []  =>
                                        raw::WILDCARD_PATTERN;

                                    (p, mc::INT _) ! ps
                                        => 
                                        raw::TUPLEPAT
                                            (map
                                                (\\ (p, _) =  arg p)
                                                namings
                                            );

                                    (p, mc::LABEL _) ! ps
                                        =>
                                        raw::RECORD_PATTERN  (map f namings,  TRUE)
                                        where
                                            fun f (p, mc::LABEL l) =>  (l, arg p);
                                                f (p, _          ) =>  raise exception DIE "Bug: Unsupported case in gen_proj";
                                            end;
                                        end;
                                esac;

                            raw::VAL_DECL [raw::NAMED_VARIABLE (pattern, id_fn (get_name path)) ];
                        };

                    fun gen_cont (k, f, vars)
                        = 
                        raw::FUN_DECL [
                            raw::FUN (
                                k,
                                [   raw::CLAUSE (
                                        [ raw::TUPLEPAT [] ],
                                        NULL,
                                        raw::APPLY_EXPRESSION (
                                            id_fn (state_fn f),
                                            raw::TUPLE_IN_EXPRESSION (map  id_fn  vars)
                                        )
                                    )
                                ]
                            )
                        ];

                  mc::code_gen 
                      { gen_fail,
                        gen_ok,
                        gen_path,
                        gen_bind,
                        gen_case,
                        gen_if,
                        gen_goto,
                        gen_cont,
                        gen_fun,
                        gen_let,
                        gen_variable,
                        gen_val,
                        gen_proj
                      }
                      (root, dfa);
                };                                      # fun code_gen

            fun complex_pattern p
                =
                *complex
                where
                    complex = REF FALSE;

                    fun rewrite_pattern_node _ (p as raw::WHEREPAT                  _) =>  { complex := TRUE;   p; };
                        rewrite_pattern_node _ (p as raw::NESTEDPAT                 _) =>  { complex := TRUE;   p; };
                        rewrite_pattern_node _ (p as raw::ANDPAT                    _) =>  { complex := TRUE;   p; };
                        rewrite_pattern_node _ (p as raw::NOTPAT                    _) =>  { complex := TRUE;   p; };
                        rewrite_pattern_node _ (p as raw::OR_PATTERN                _) =>  { complex := TRUE;   p; };
                        rewrite_pattern_node _ (p as raw::LITPAT (raw::FLOAT_LIT   _)) =>  { complex := TRUE;   p; };
                        rewrite_pattern_node _ (p as raw::LITPAT (raw::INTEGER_LIT _)) =>  { complex := TRUE;   p; };
                        rewrite_pattern_node _ p => p;
                    end;


                    fns.rewrite_pattern_parsetree   p
                    where
                        fns =  rrs::make_raw_syntax_parsetree_rewriters [ rrs::REWRITE_PATTERN_NODE rewrite_pattern_node ];
                    end;
                end;

            # Are clauses conditional?
            #
            is_complex
                =
                list::exists
                    (\\ raw::CLAUSE (p, g, _)
                        =
                        not_null g   or   list::exists complex_pattern p
                    );
        end;                                                                                            # stipulate
    };                                                                                                  # generic package   match_gen_g
end;                                                                                                    # stipulate


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext