diff options
Diffstat (limited to 'frontend/generics1.icl')
-rw-r--r-- | frontend/generics1.icl | 3062 |
1 files changed, 3062 insertions, 0 deletions
diff --git a/frontend/generics1.icl b/frontend/generics1.icl new file mode 100644 index 0000000..9c28918 --- /dev/null +++ b/frontend/generics1.icl @@ -0,0 +1,3062 @@ +//************************************************************************************** +// Generic programming features +//************************************************************************************** + +implementation module generics1 + +import StdEnv +import check +from checktypes import createClassDictionaries +/*2.0 +from transform import ::Group +0.2*/ +//1.3 +from transform import Group +//3.1 + +import genericsupport + +//************************************************************************************** +// Data types +//************************************************************************************** + +:: FunDefs :== {#FunDef} +:: Modules :== {#CommonDefs} +:: DclModules :== {#DclModule} +:: Groups :== {!Group} +:: FunsAndGroups :== (!Index, !Index, ![FunDef], ![Group]) + +//************************************************************************************** +// Exported functions +//************************************************************************************** + +convertGenerics :: + !Int // index of the main dcl module + !NumberSet // set of used modules + !{#CommonDefs} // common definitions of all modules + !{!Group} // groups of functions + !*{# FunDef} // functions + !*TypeDefInfos // type definition information of all modules + !*Heaps // all heaps + !*HashTable // needed for what creating class dictionaries + !*PredefinedSymbols // predefined symbols + !u:{# DclModule} // dcl modules + !*ErrorAdmin // to report errors + -> ( !{#CommonDefs} // common definitions of all modules + , !{!Group} // groups of functions + , !*{# FunDef} // function definitions + , ![IndexRange] // index ranges of generated functions + , !*TypeDefInfos // type definition infos + , !*Heaps // all heaps + , !*HashTable // needed for creating class dictinaries + , !*PredefinedSymbols // predefined symbols + , !u:{# DclModule} // dcl modules + , !*ErrorAdmin // to report errors + ) +convertGenerics + main_dcl_module_n + used_module_numbers + modules + groups + funs + td_infos + heaps + hash_table + u_predefs + dcl_modules + error + + //#! td_infos = td_infos ---> "************************* generic phase started ******************** " + //#! funs = dump_funs 0 funs + //#! dcl_modules = dump_dcl_modules 0 dcl_modules + + #! modules = {x \\ x <-: modules} // unique copy + #! dcl_modules = { x \\ x <-: dcl_modules } // unique copy + #! size_predefs = size u_predefs + #! (predefs, u_predefs) = arrayCopyBegin u_predefs size_predefs // non-unique copy + + #! td_infos = clearTypeDefInfos td_infos + //---> ("used module numbers ", main_dcl_module_n, numberSetToList used_module_numbers) + #! (modules, heaps) = clearGenericDefs modules heaps + + #! (iso_range, funs, groups, td_infos, modules, heaps, error) + = buildGenericRepresentations + (main_dcl_module_n /*---> "====================== call buildGenericRepresentations"*/) + predefs + funs groups td_infos modules heaps error + | not error.ea_ok + = (modules, groups, funs, [], td_infos, heaps, hash_table, u_predefs, dcl_modules, error) + + // build classes for each kind of each generic function + #! (modules, dcl_modules, heaps, symbol_table, td_infos, error) + = buildClasses + main_dcl_module_n used_module_numbers + modules dcl_modules heaps hash_table.hte_symbol_heap td_infos error + //---> ("====================== call buildClasses") + #! hash_table = { hash_table & hte_symbol_heap = symbol_table } + | not error.ea_ok + = (modules, groups, funs, [], td_infos, heaps, hash_table, u_predefs, dcl_modules, error) + + #! (instance_range, funs, groups, modules, dcl_modules, td_infos, heaps, error) + = convertGenericCases main_dcl_module_n used_module_numbers predefs funs groups modules dcl_modules td_infos heaps error + //---> ("====================== call convertGenericCases") + + | not error.ea_ok + = (modules, groups, funs, [], td_infos, heaps, hash_table, u_predefs, dcl_modules, error) + + //#! funs = dump_funs 0 funs + //#! dcl_modules = dump_dcl_modules 0 dcl_modules + //#! error = error ---> "************************* generic phase completed ******************** " + //| True = abort "generic phase aborted for testing\n" + = (modules, groups, funs, [iso_range, instance_range], td_infos, heaps, hash_table, u_predefs, dcl_modules, error) +where + + dump_funs n funs + | n == size funs + = funs + #! ({fun_symb, fun_type, fun_body}, funs) = funs ! [n] + #! funs = funs + //---> ("icl function ", fun_symb, n, fun_type, fun_body) + = dump_funs (inc n) funs + dump_dcl_modules n dcl_modules + | n == size dcl_modules + = dcl_modules + # ({dcl_functions}, dcl_modules) = dcl_modules ! [n] + = dump_dcl_modules (inc n) (dump_dcl_funs 0 dcl_functions dcl_modules) + //---> ("dcl module", n) + dump_dcl_funs n dcl_funs dcl_modules + | n == size dcl_funs + = dcl_modules + # {ft_symb, ft_type} = dcl_funs.[n] + = dump_dcl_funs (inc n) dcl_funs dcl_modules + //---> ("dcl function", ft_symb, n, ft_type) + + +//**************************************************************************************** +// clear stuff that might have been left over +// from compilation of other icl modules +//**************************************************************************************** + +clearTypeDefInfos td_infos + = clear_modules 0 td_infos +where + clear_modules n td_infos + | n == size td_infos + = td_infos + #! (td_infos1, td_infos) = replace td_infos n {} + #! td_infos1 = clear_td_infos 0 td_infos1 + #! (_, td_infos) = replace td_infos n td_infos1 + = clear_modules (inc n) td_infos + + clear_td_infos n td_infos + | n == size td_infos + = td_infos + #! (td_info, td_infos) = td_infos![n] + #! td_infos = {td_infos & [n] = {td_info & tdi_gen_rep = No}} + = clear_td_infos (inc n) td_infos + +clearGenericDefs modules heaps + = clear_module 0 modules heaps +where + clear_module n modules heaps + | n == size modules + = (modules, heaps) + #! ({com_generic_defs}, modules) = modules![n] + #! (com_generic_defs, heaps) = updateArraySt clear_generic_def {x\\x<-:com_generic_defs} heaps + #! modules = {modules & [n].com_generic_defs = com_generic_defs} + = clear_module (inc n) modules heaps + + clear_generic_def _ generic_def=:{gen_name,gen_info_ptr} heaps=:{hp_generic_heap} + #! (gen_info, hp_generic_heap) = readPtr gen_info_ptr hp_generic_heap + #! gen_info = + { gen_info + & gen_cases = [] + , gen_classes = createArray 32 [] + } + #! hp_generic_heap = writePtr gen_info_ptr gen_info hp_generic_heap + = (generic_def, {heaps & hp_generic_heap = hp_generic_heap}) + +//**************************************************************************************** +// generic type representation +//**************************************************************************************** + +// generic representation is built for each type argument of +// generic cases of the current module +buildGenericRepresentations :: + !Index + !PredefinedSymbols + !*FunDefs + !Groups + !*TypeDefInfos + !*Modules + !*Heaps + !*ErrorAdmin + -> ( !IndexRange + , !*FunDefs + , !Groups + , !*TypeDefInfos + , !*Modules + , !*Heaps + , !*ErrorAdmin + ) +buildGenericRepresentations main_module_index predefs funs groups td_infos modules heaps error + + #! size_funs = size funs + #! size_groups = size groups + #! ({com_gencase_defs}, modules) = modules ! [main_module_index] + + #! ((new_fun_index, new_group_index, new_funs, new_groups), td_infos, modules, heaps, error) + = foldArraySt on_gencase com_gencase_defs ((size_funs, size_groups, [], []), td_infos, modules, heaps, error) + + #! funs = arrayPlusRevList funs new_funs + #! groups = arrayPlusRevList groups new_groups + + #! range = {ir_from = size_funs, ir_to = new_fun_index} + + = (range, funs, groups, td_infos, modules, heaps, error) +where + + on_gencase index case_def=:{gc_type_cons,gc_name} st + = build_generic_rep_if_needed gc_type_cons st + + build_generic_rep_if_needed :: + !TypeCons !((!Index,!Index,![FunDef],![Group]), !*TypeDefInfos, !*{#CommonDefs}, !*Heaps, !*ErrorAdmin) + -> (!(!Index, !Index, ![FunDef], ![Group]), !*TypeDefInfos, !*{#CommonDefs}, !*Heaps, !*ErrorAdmin) + build_generic_rep_if_needed (TypeConsSymb {type_index={glob_module,glob_object}, type_name}) (funs_and_groups, td_infos, modules, heaps, error) + #! (type_def, modules) = modules![glob_module].com_type_defs.[glob_object] + #! (td_info, td_infos) = td_infos![glob_module, glob_object] + #! type_def_gi = {gi_module=glob_module,gi_index=glob_object} + = case td_info.tdi_gen_rep of + Yes _ + -> (funs_and_groups, td_infos, modules, heaps, error) + //---> ("generic representation is already built", type_name) + No + #! (gen_type_rep, funs_and_groups, modules, heaps, error) + = buildGenericTypeRep type_def_gi main_module_index predefs funs_and_groups modules heaps error + + #! td_info = {td_info & tdi_gen_rep = Yes gen_type_rep} + #! td_infos = {td_infos & [glob_module, glob_object] = td_info} + -> (funs_and_groups, td_infos, modules, heaps, error) + //---> ("build generic representation", type_name) + build_generic_rep_if_needed _ st = st + +buildGenericTypeRep :: + !GlobalIndex // type def index + !Index // main module index + !PredefinedSymbols + !(!Index,!Index,![FunDef],![Group]) + !*{#CommonDefs} + !*Heaps + !*ErrorAdmin + -> ( !GenericTypeRep + , !(!Index, !Index, ![FunDef], ![Group]) + , !*{#CommonDefs} + , !*Heaps + , !*ErrorAdmin + ) +buildGenericTypeRep type_index main_module_index predefs funs_and_groups modules heaps error + # (type_def, modules) = modules![type_index.gi_module].com_type_defs.[type_index.gi_index] + # (atype, modules,error) = buildStructureType type_index predefs modules error + + # (from_fun_ds, funs_and_groups, heaps, error) + = buildConversionFrom type_index.gi_module type_def main_module_index predefs funs_and_groups heaps error + + # (to_fun_ds, funs_and_groups, heaps, error) + = buildConversionTo type_index.gi_module type_def main_module_index predefs funs_and_groups heaps error + + # (iso_fun_ds, funs_and_groups, heaps, error) + = buildConversionIso type_def from_fun_ds to_fun_ds main_module_index predefs funs_and_groups heaps error + + = ({gtr_type=atype,gtr_iso=iso_fun_ds}, funs_and_groups, modules, heaps, error) + //---> ("buildGenericTypeRep", type_def.td_name, atype) + +//======================================================================================== +// the structure type +//======================================================================================== + +buildStructureType :: + !GlobalIndex // type definition module + !PredefinedSymbols + !*{#CommonDefs} + !*ErrorAdmin + -> ( !AType // the structure type + , !*{#CommonDefs} + , !*ErrorAdmin + ) +buildStructureType {gi_module,gi_index} predefs modules error + # (type_def=:{td_name}, modules) = modules![gi_module].com_type_defs.[gi_index] + # (common_defs, modules) = modules ! [gi_module] + # (atype, error) = build_type type_def common_defs error + = (atype, modules, error) + //---> ("buildStructureType", td_name, atype) +where + build_type {td_rhs=(AlgType alts)} common_defs error + # cons_defs = [common_defs.com_cons_defs.[ds_index] \\ {ds_index} <- alts] + # cons_args = [buildProductType cons_def.cons_type.st_args predefs \\ cons_def <- cons_defs] + = (buildSumType cons_args predefs, error) + build_type {td_rhs=(RecordType {rt_constructor={ds_index}})} common_defs error + # cons_def = common_defs.com_cons_defs.[ds_index] + = (buildProductType cons_def.cons_type.st_args predefs, error) + build_type {td_rhs=(SynType type)} common_defs error + = (type /* is that correct ???*/, error) + build_type td=:{td_rhs=(AbstractType _),td_name, td_arity, td_args, td_pos} common_defs error + = (makeAType TE TA_Multi, + reportError td_name td_pos "cannot build a generic representation of an abstract type" error) + +// build a product of types +buildProductType :: ![AType] !PredefinedSymbols -> !AType +buildProductType types predefs + = listToBin build_pair build_unit types +where + build_pair x y = buildPredefTypeApp PD_TypePAIR [x, y] predefs + build_unit = buildPredefTypeApp PD_TypeUNIT [] predefs + +// build a sum of types +buildSumType :: ![AType] !PredefinedSymbols -> !AType +buildSumType types predefs + = listToBin build_either build_void types +where + build_either x y = buildPredefTypeApp PD_TypeEITHER [x, y] predefs + build_void = abort "sum of zero types\n" + +// build a binary representation of a list +listToBin :: (a a -> a) a [a] -> a +listToBin bin tip [] = tip +listToBin bin tip [x] = x +listToBin bin tip xs + # (l,r) = splitAt ((length xs) / 2) xs + = bin (listToBin bin tip l) (listToBin bin tip r) + +// build application of a predefined type constructor +buildPredefTypeApp :: !Int [AType] !PredefinedSymbols -> !AType +buildPredefTypeApp predef_index args predefs + # {pds_module, pds_def} = predefs.[predef_index] + # pds_ident = predefined_idents.[predef_index] + # global_index = {glob_module = pds_module, glob_object = pds_def} + # type_symb = MakeTypeSymbIdent global_index pds_ident (length args) + = makeAType (TA type_symb args) TA_Multi + +//======================================================================================== +// conversions functions +//======================================================================================== + +// buildConversionIso +buildConversionIso :: + !CheckedTypeDef // the type definition + !DefinedSymbol // from fun + !DefinedSymbol // to fun + !Index // main module + !PredefinedSymbols + (!Index, !Index, ![FunDef], ![Group]) + !*Heaps + !*ErrorAdmin + -> ( !DefinedSymbol + , (!Index, !Index, ![FunDef], ![Group]) + , !*Heaps + , !*ErrorAdmin + ) +buildConversionIso + type_def=:{td_name, td_pos} + from_fun + to_fun + main_dcl_module_n + predefs + funs_and_groups + heaps + error + #! (from_expr, heaps) = buildFunApp main_dcl_module_n from_fun [] heaps + #! (to_expr, heaps) = buildFunApp main_dcl_module_n to_fun [] heaps + #! (iso_expr, heaps) = build_iso to_expr from_expr heaps + + #! ident = makeIdent ("iso" +++ td_name.id_name) + #! (def_sym, funs_and_groups) = buildFunAndGroup ident [] iso_expr No main_dcl_module_n td_pos funs_and_groups + = (def_sym, funs_and_groups, heaps, error) + //---> ("buildConversionIso", td_name, let (_,_,fs,_) = funs_and_groups in hd fs) +where + build_iso to_expr from_expr heaps + = buildPredefConsApp PD_ConsBimap [to_expr, from_expr] predefs heaps + +// conversion from type to generic +buildConversionTo :: + !Index // type def module + !CheckedTypeDef // the type def + !Index // main module + !PredefinedSymbols + !(!Index, !Index, ![FunDef], ![Group]) + !*Heaps + !*ErrorAdmin + -> ( !DefinedSymbol + , (!Index, !Index, ![FunDef], ![Group]) + , !*Heaps + , !*ErrorAdmin + ) +buildConversionTo + type_def_mod + type_def=:{td_rhs, td_name, td_index, td_pos} + main_module_index + predefs + funs_and_groups + heaps + error + # (arg_expr, arg_var, heaps) = buildVarExpr "x" heaps + # (body_expr, heaps, error) = + build_expr_for_type_rhs type_def_mod td_index td_rhs arg_expr heaps error + # fun_name = makeIdent ("fromGenericTo" +++ td_name.id_name) + | not error.ea_ok + # (def_sym, funs_and_groups) + = (buildFunAndGroup fun_name [] EE No main_module_index td_pos funs_and_groups) + = (def_sym, funs_and_groups, heaps, error) + //---> ("buildConversionTo failed", td_name) + # (def_sym, funs_and_groups) + = (buildFunAndGroup fun_name [arg_var] body_expr No main_module_index td_pos funs_and_groups) + = (def_sym, funs_and_groups, heaps, error) + //---> ("buildConversionTo", td_name, let (_,_,fs,_) = funs_and_groups in hd fs) +where + // build conversion for type rhs + build_expr_for_type_rhs :: + !Int // type def module + !Int // type def index + !TypeRhs // type def rhs + !Expression // expression of the function argument variable + !*Heaps + !*ErrorAdmin + -> ( !Expression // generated expression + , !*Heaps // state + , !*ErrorAdmin + ) + build_expr_for_type_rhs type_def_mod type_def_index (AlgType def_symbols) arg_expr heaps error + = build_expr_for_conses type_def_mod type_def_index def_symbols arg_expr heaps error + build_expr_for_type_rhs type_def_mod type_def_index (RecordType {rt_constructor}) arg_expr heaps error + = build_expr_for_conses type_def_mod type_def_index [rt_constructor] arg_expr heaps error + build_expr_for_type_rhs type_def_mod type_def_index (AbstractType _) arg_expr heaps error + #! error = checkErrorWithIdentPos (newPosition td_name td_pos) "cannot build isomorphisms for an abstract type" error + = (EE, heaps, error) + build_expr_for_type_rhs type_def_mod type_def_index (SynType _) arg_expr heaps error + #! error = checkErrorWithIdentPos (newPosition td_name td_pos) "cannot build isomorphisms for a synonym type" error + = (EE, heaps, error) + + // build conversion for constructors of a type def + build_expr_for_conses type_def_mod type_def_index cons_def_syms arg_expr heaps error + # (case_alts, heaps, error) = + build_exprs_for_conses 0 (length cons_def_syms) type_def_mod cons_def_syms heaps error + # case_patterns = AlgebraicPatterns {glob_module = type_def_mod, glob_object = type_def_index} case_alts + # (case_expr, heaps) = buildCaseExpr arg_expr case_patterns heaps + = (case_expr, heaps, error) + //---> (free_vars, case_expr) + + // build conversions for a constructor + build_exprs_for_conses :: !Int !Int !Int ![DefinedSymbol] !*Heaps !*ErrorAdmin + -> ([AlgebraicPattern], !*Heaps, !*ErrorAdmin) + build_exprs_for_conses i n type_def_mod [] heaps error = ([], heaps, error) + build_exprs_for_conses i n type_def_mod [cons_def_sym:cons_def_syms] heaps error + #! (alt, heaps, error) = build_expr_for_cons i n type_def_mod cons_def_sym heaps error + #! (alts, heaps, error) = build_exprs_for_conses (i+1) n type_def_mod cons_def_syms heaps error + = ([alt:alts], heaps, error) + + // build conversion for a constructor + build_expr_for_cons :: !Int !Int !Int !DefinedSymbol !*Heaps !*ErrorAdmin + -> (AlgebraicPattern, !*Heaps, !*ErrorAdmin) + build_expr_for_cons + i n type_def_mod def_symbol=:{ds_ident, ds_arity} + heaps error + + #! names = ["x" +++ toString (i+1) +++ toString k \\ k <- [1..ds_arity]] + #! (var_exprs, vars, heaps) = buildVarExprs names heaps + #! (expr, heaps) = build_prod var_exprs predefs heaps + #! (expr, heaps) = build_sum i n expr predefs heaps + + #! alg_pattern = { + ap_symbol = {glob_module = type_def_mod, glob_object = def_symbol}, + ap_vars = vars, + ap_expr = expr, + ap_position = NoPos + } + = (alg_pattern, heaps, error) + + build_sum :: !Int !Int !Expression !PredefinedSymbols !*Heaps -> (!Expression, !*Heaps) + build_sum i n expr predefs heaps + | n == 0 = abort "build sum of zero elements\n" + | i >= n = abort "error building sum" + | n == 1 = (expr, heaps) + | i < (n/2) + # (expr, heaps) = build_sum i (n/2) expr predefs heaps + = build_left expr heaps + | otherwise + # (expr, heaps) = build_sum (i - (n/2)) (n - (n/2)) expr predefs heaps + = build_right expr heaps + where + build_left x heaps = buildPredefConsApp PD_ConsLEFT [x] predefs heaps + build_right x heaps = buildPredefConsApp PD_ConsRIGHT [x] predefs heaps + + build_prod :: ![Expression] !PredefinedSymbols !*Heaps -> (!Expression, !*Heaps) + build_prod [] predefs heaps = build_unit heaps + where + build_unit heaps = buildPredefConsApp PD_ConsUNIT [] predefs heaps + build_prod [expr] predefs heaps = (expr, heaps) + build_prod exprs predefs heaps + # (lexprs, rexprs) = splitAt ((length exprs)/2) exprs + # (lexpr, heaps) = build_prod lexprs predefs heaps + # (rexpr, heaps) = build_prod rexprs predefs heaps + = build_pair lexpr rexpr heaps + where + build_pair x y heaps = buildPredefConsApp PD_ConsPAIR [x, y] predefs heaps + +buildConversionFrom :: + !Index // type def module + !CheckedTypeDef // the type def + !Index // main module + !PredefinedSymbols + !(!Index, !Index, ![FunDef], ![Group]) + !*Heaps + !*ErrorAdmin + -> ( !DefinedSymbol + , (!Index, !Index, ![FunDef], ![Group]) + , !*Heaps + , !*ErrorAdmin + ) +buildConversionFrom + type_def_mod + type_def=:{td_rhs, td_name, td_index, td_pos} + main_module_index + predefs + funs_and_groups + heaps + error + # (body_expr, arg_var, heaps, error) = + build_expr_for_type_rhs type_def_mod td_rhs heaps error + # fun_name = makeIdent ("toGenericFrom" +++ td_name.id_name) + | not error.ea_ok + # (def_sym, funs_and_groups) + = (buildFunAndGroup fun_name [] EE No main_module_index td_pos funs_and_groups) + = (def_sym, funs_and_groups, heaps, error) + //---> ("buildConversionFrom failed", td_name) + # (def_sym, funs_and_groups) + = (buildFunAndGroup fun_name [arg_var] body_expr No main_module_index td_pos funs_and_groups) + = (def_sym, funs_and_groups, heaps, error) + //---> ("buildConversionFrom", td_name, let (_,_,fs,_) = funs_and_groups in hd fs) +where + // build expression for type def rhs + build_expr_for_type_rhs :: + !Index // type def module + !TypeRhs // type rhs + !*Heaps + !*ErrorAdmin + -> ( !Expression // body expresssion + , !FreeVar + , !*Heaps + , !*ErrorAdmin + ) + build_expr_for_type_rhs type_def_mod (AlgType def_symbols) heaps error + = build_sum type_def_mod def_symbols heaps error + build_expr_for_type_rhs type_def_mod (RecordType {rt_constructor}) heaps error + = build_sum type_def_mod [rt_constructor] heaps error + build_expr_for_type_rhs type_def_mod (AbstractType _) heaps error + #! error = reportError td_name td_pos "cannot build isomorphisms for an abstract type" error + = (EE, undef, heaps, error) + build_expr_for_type_rhs type_def_mod (SynType _) heaps error + #! error = reportError td_name td_pos "cannot build isomorphisms for a synonym type" error + = (EE, undef, heaps, error) + + // build expression for sums + build_sum :: + !Index + ![DefinedSymbol] + !*Heaps + !*ErrorAdmin + -> ( !Expression + , !FreeVar // top variable + , !*Heaps + , !*ErrorAdmin + ) + build_sum type_def_mod [] heaps error + = abort "algebraic type with no constructors!\n" + build_sum type_def_mod [def_symbol] heaps error + #! (cons_app_expr, cons_arg_vars, heaps) = build_cons_app type_def_mod def_symbol heaps + #! (alt_expr, var, heaps) = build_prod cons_app_expr cons_arg_vars heaps + = (alt_expr, var, heaps, error) + build_sum type_def_mod def_symbols heaps error + #! (left_def_syms, right_def_syms) = splitAt ((length def_symbols) /2) def_symbols + + #! (left_expr, left_var, heaps, error) + = build_sum type_def_mod left_def_syms heaps error + + #! (right_expr, right_var, heaps, error) + = build_sum type_def_mod right_def_syms heaps error + + #! (case_expr, var, heaps) = + build_case_either left_var left_expr right_var right_expr heaps + = (case_expr, var, heaps, error) + + // build expression for products + build_prod :: + !Expression // result of the case on product + ![FreeVar] // list of variables of the constructor pattern + !*Heaps + -> ( !Expression // generated product + , !FreeVar // top variable + , !*Heaps + ) + build_prod expr [] heaps + = build_case_unit expr heaps + build_prod expr [cons_arg_var] heaps + = (expr, cons_arg_var, heaps) + build_prod expr cons_arg_vars heaps + #! (left_vars, right_vars) = splitAt ((length cons_arg_vars) /2) cons_arg_vars + #! (expr, left_var, heaps) = build_prod expr left_vars heaps + #! (expr, right_var, heaps) = build_prod expr right_vars heaps + #! (case_expr, var, heaps) = build_case_pair left_var right_var expr heaps + = (case_expr, var, heaps) + + // build constructor applicarion expression + build_cons_app :: !Index !DefinedSymbol !*Heaps + -> (!Expression, ![FreeVar], !*Heaps) + build_cons_app cons_mod def_symbol=:{ds_arity} heaps + #! names = ["x" +++ toString k \\ k <- [1..ds_arity]] + #! (var_exprs, vars, heaps) = buildVarExprs names heaps + #! (expr, heaps) = buildConsApp cons_mod def_symbol var_exprs heaps + = (expr, vars, heaps) + + // build case expressions for PAIR, EITHER and UNIT + build_case_unit body_expr heaps + # unit_pat = buildPredefConsPattern PD_ConsUNIT [] body_expr predefs + # {pds_module, pds_def} = predefs.[PD_TypeUNIT] + # case_patterns = AlgebraicPatterns {glob_module = pds_module, glob_object = pds_def} [unit_pat] + = build_case_expr case_patterns heaps + + build_case_pair var1 var2 body_expr heaps + # pair_pat = buildPredefConsPattern PD_ConsPAIR [var1, var2] body_expr predefs + # {pds_module, pds_def} = predefs.[PD_TypePAIR] + # case_patterns = AlgebraicPatterns {glob_module = pds_module, glob_object = pds_def} [pair_pat] + = build_case_expr case_patterns heaps + + build_case_either left_var left_expr right_var right_expr heaps + # left_pat = buildPredefConsPattern PD_ConsLEFT [left_var] left_expr predefs + # right_pat = buildPredefConsPattern PD_ConsRIGHT [right_var] right_expr predefs + # {pds_module, pds_def} = predefs.[PD_TypeEITHER] + # case_patterns = AlgebraicPatterns {glob_module = pds_module, glob_object = pds_def} [left_pat, right_pat] + = build_case_expr case_patterns heaps + + // case with a variable as the selector expression + build_case_expr case_patterns heaps + # (var_expr, var, heaps) = buildVarExpr "c" heaps + # (case_expr, heaps) = buildCaseExpr var_expr case_patterns heaps + = (case_expr, var, heaps) + + +//**************************************************************************************** +// build kind indexed classes +//**************************************************************************************** + +buildClasses :: + !Int + !NumberSet + !*{#CommonDefs} + !*{#.DclModule} + !*Heaps + !*SymbolTable + !*TypeDefInfos + !*ErrorAdmin + -> (.{#CommonDefs} + ,.{#DclModule} + ,.Heaps + ,.SymbolTable + ,.TypeDefInfos + ,.ErrorAdmin + ) +buildClasses main_module_index used_module_numbers modules dcl_modules heaps symbol_table td_infos error + #! (common_defs=:{com_class_defs, com_member_defs}, modules) = modules ! [main_module_index] + #! num_classes = size com_class_defs + #! num_members = size com_member_defs + +/* + #! (modules, (classes, members, new_num_classes, new_num_members, heaps, td_infos, error)) + = mapGenericCaseDefs on_gencase modules ([], [], num_classes, num_members, heaps, td_infos, error) +*/ + #! (modules, (classes, members, new_num_classes, new_num_members, heaps, td_infos, error)) + = build_modules 0 modules ([], [], num_classes, num_members, heaps, td_infos, error) + + // obtain common definitions again because com_gencase_defs are updated + #! (common_defs, modules) = modules ! [main_module_index] + # common_defs = + { common_defs + & com_class_defs = arrayPlusRevList com_class_defs classes + , com_member_defs = arrayPlusRevList com_member_defs members + } + + #! (common_defs, dcl_modules, heaps, symbol_table) + = build_class_dictionaries common_defs dcl_modules heaps symbol_table + + #! modules = {modules & [main_module_index] = common_defs} + = (modules, dcl_modules, heaps, symbol_table, td_infos, error) +where + build_modules module_index modules st + | module_index == size modules + = (modules, st) + #! (common_defs=:{com_gencase_defs}, modules) = modules![module_index] + #! (com_gencase_defs, modules, st) + = build_module module_index com_gencase_defs modules st + #! modules = + { modules + & [module_index] = {common_defs & com_gencase_defs = com_gencase_defs } + } + = build_modules (inc module_index) modules st + + build_module module_index com_gencase_defs modules st + | inNumberSet module_index used_module_numbers + #! com_gencase_defs = {x\\x<-:com_gencase_defs} + = build_module1 module_index 0 com_gencase_defs modules st + = (com_gencase_defs, modules, st) + + build_module1 module_index index com_gencase_defs modules st + | index == size com_gencase_defs + = (com_gencase_defs, modules, st) + #! (gencase, com_gencase_defs) = com_gencase_defs ! [index] + #! (gencase, modules, st) = on_gencase module_index index gencase modules st + #! com_gencase_defs = {com_gencase_defs & [index] = gencase} + = build_module1 module_index (inc index) com_gencase_defs modules st + + on_gencase :: + !Index + !Index + !GenericCaseDef + !*Modules + (![ClassDef], ![MemberDef], !Index, Index, !*Heaps, !*TypeDefInfos, !*ErrorAdmin) + -> ( !GenericCaseDef + , !*Modules + , (![ClassDef], ![MemberDef], !Index, Index, !*Heaps, !*TypeDefInfos, !*ErrorAdmin) + ) + on_gencase + module_index index + gencase=:{gc_name,gc_generic, gc_type_cons} + modules + (classes, members, class_index, member_index, heaps, td_infos, error) + + #! (gen_def, modules) = modules ! [gc_generic.gi_module].com_generic_defs.[gc_generic.gi_index] + #! (kind, td_infos) = get_kind_of_type_cons gc_type_cons td_infos + + //#! kinds = partially_applied_kinds kind + #! st = build_class_if_needed gen_def kind (classes, members, class_index, member_index, modules, heaps, error) + + // build classes needed for shorthand instances + #! (classes, members, class_index, member_index, modules, heaps, error) + = case kind of + KindConst -> st + KindArrow ks + -> foldSt (build_class_if_needed gen_def) [KindConst:ks] st + + #! gencase = { gencase & gc_kind = kind } + = (gencase, modules, (classes, members, class_index, member_index, heaps, td_infos, error)) + + build_class_if_needed gen_def kind (classes, members, class_index, member_index, modules, heaps, error) + #! (opt_class_info, heaps) = lookup_generic_class_info gen_def kind heaps + = case opt_class_info of + No + #! (class_def, member_def, modules, heaps, error) + = buildClassAndMember main_module_index class_index member_index kind gen_def modules heaps error + #! class_info = + { gci_kind = kind + , gci_module = main_module_index + , gci_class = class_index + , gci_member = member_index + } + #! heaps = add_generic_class_info gen_def class_info heaps + -> ([class_def:classes], [member_def:members], inc class_index, inc member_index, modules, heaps, error) + Yes class_info + -> (classes, members, class_index, member_index, modules, heaps, error) + + partially_applied_kinds KindConst + = [KindConst] + partially_applied_kinds (KindArrow kinds) + = do_it kinds + where + do_it [] = [KindConst] + do_it all_ks=:[k:ks] = [(KindArrow all_ks) : do_it ks] + + get_kind_of_type_cons :: !TypeCons !*TypeDefInfos -> (!TypeKind, !*TypeDefInfos) + get_kind_of_type_cons (TypeConsBasic _) td_infos + = (KindConst, td_infos) + get_kind_of_type_cons TypeConsArrow td_infos + = (KindArrow [KindConst,KindConst], td_infos) + get_kind_of_type_cons (TypeConsSymb {type_name, type_index}) td_infos + #! ({tdi_kinds}, td_infos) = td_infos ! [type_index.glob_module,type_index.glob_object] + = (if (isEmpty tdi_kinds) KindConst (KindArrow tdi_kinds), td_infos) + get_kind_of_type_cons (TypeConsVar tv) td_infos + = (KindConst, td_infos) + + lookup_generic_class_info {gen_info_ptr} kind heaps=:{hp_generic_heap} + #! ({gen_classes}, hp_generic_heap) = readPtr gen_info_ptr hp_generic_heap + = (lookupGenericClassInfo kind gen_classes + , {heaps & hp_generic_heap = hp_generic_heap}) + + add_generic_class_info {gen_info_ptr} class_info heaps=:{hp_generic_heap} + #! (gen_info=:{gen_classes}, hp_generic_heap) = readPtr gen_info_ptr hp_generic_heap + #! gen_classes = addGenericClassInfo class_info gen_classes + #! hp_generic_heap = writePtr gen_info_ptr {gen_info&gen_classes=gen_classes} hp_generic_heap + = {heaps & hp_generic_heap = hp_generic_heap} + + build_class_dictionaries + common_defs dcl_modules + heaps=:{hp_type_heaps=hp_type_heaps=:{th_vars}, hp_var_heap} + symbol_table + #! class_defs = { x \\ x <-: common_defs.com_class_defs } // make unique copy + # type_defs = { x \\ x <-: common_defs.com_type_defs } // make unique copy + # cons_defs = { x \\ x <-: common_defs.com_cons_defs } // make unique copy + # selector_defs = { x \\ x <-: common_defs.com_selector_defs } // make unique copy + # (size_type_defs,type_defs) = usize type_defs + #! (new_type_defs, new_selector_defs, new_cons_defs,_,type_defs,selector_defs,cons_defs,class_defs, dcl_modules, th_vars, hp_var_heap, symbol_table) = + createClassDictionaries + False + main_module_index + size_type_defs + (size common_defs.com_selector_defs) + (size common_defs.com_cons_defs) + type_defs selector_defs cons_defs class_defs dcl_modules th_vars hp_var_heap symbol_table + + #! common_defs = { common_defs & + com_class_defs = class_defs, + com_type_defs = arrayPlusList type_defs new_type_defs, + com_selector_defs = arrayPlusList selector_defs new_selector_defs, + com_cons_defs = arrayPlusList cons_defs new_cons_defs} + + #! heaps = {heaps & hp_var_heap = hp_var_heap, hp_type_heaps = {hp_type_heaps & th_vars = th_vars}} + #! modules = { modules & [module_index] = common_defs } + = (common_defs, dcl_modules, heaps, symbol_table) + + +// limitations: +// - context restrictions on generic variables are not allowed +buildMemberType :: + !GenericDef + !TypeKind + !TypeVar + !*Modules + !*TypeHeaps + !*GenericHeap + !*ErrorAdmin + -> ( !SymbolType + , !*Modules + , !*TypeHeaps + , !*GenericHeap + , !*ErrorAdmin + ) +buildMemberType {gen_name,gen_pos,gen_type,gen_vars} kind class_var modules th gh error + #! (kind_indexed_st, gatvs, th, error) + = buildKindIndexedType gen_type gen_vars kind gen_name gen_pos th error + //---> ("buildMemberType called for", gen_name, kind, gen_type) + #! (member_st, th, error) + = replace_generic_vars_with_class_var kind_indexed_st gatvs kind th error + + #! th = assertSymbolType member_st th + #! th = assertSymbolType gen_type th + + = (member_st, modules, th, gh, error) + //---> ("buildMemberType returns", gen_name, kind, member_st) +where + + replace_generic_vars_with_class_var st atvs kind th error + #! th = subst_gvs atvs th + //---> ("replace_generic_vars_with_class_var called for", atvs, st) + #! (new_st, th) = applySubstInSymbolType st th + = (new_st, th, error) + //---> ("replace_generic_vars_with_class_var returns", new_st) + where + subst_gvs atvs th=:{th_vars, th_attrs} + #! tvs = [atv_variable \\ {atv_variable} <- atvs ] + #! avs = [av \\ {atv_attribute=TA_Var av} <- atvs ] + + # th_vars = foldSt subst_tv tvs th_vars + +/* + # th_attrs = case kind of + KindConst -> case avs of + [av:avs] -> foldSt (subst_av av) avs th_attrs + [] -> th_attrs + _ -> th_attrs +*/ + # th_attrs = case avs of + [av:avs] -> foldSt (subst_av av) avs th_attrs + [] -> th_attrs + + = { th & th_vars = th_vars, th_attrs = th_attrs } + + subst_tv {tv_info_ptr} th_vars + = writePtr tv_info_ptr (TVI_Type (TV class_var)) th_vars + + subst_av av {av_info_ptr} th_attrs + = writePtr av_info_ptr (AVI_Attr (TA_Var av)) th_attrs + //---> ("(1) writePtr av_info_ptr", ptrToInt av_info_ptr, av) + +buildClassAndMember + module_index class_index member_index kind + gen_def=:{gen_name, gen_pos} modules heaps error + #! (class_var, heaps) = fresh_class_var heaps + #! (member_def, modules, heaps, error) + = build_class_member class_var modules heaps error + #! class_def = build_class class_var member_def + = (class_def, member_def, modules, heaps, error) + //---> ("buildClassAndMember", gen_def.gen_name, kind) +where + fresh_class_var heaps=:{hp_type_heaps=th=:{th_vars}} + # (tv, th_vars) = freshTypeVar (makeIdent "class_var") th_vars + = (tv, {heaps & hp_type_heaps = { th & th_vars = th_vars }}) + + class_ident = genericIdentToClassIdent gen_def.gen_name kind + member_ident = genericIdentToMemberIdent gen_def.gen_name kind + class_ds = {ds_index = class_index, ds_ident = class_ident, ds_arity = 1} + + build_class_member class_var modules heaps=:{hp_var_heap, hp_type_heaps, hp_generic_heap} error + #! (type_ptr, hp_var_heap) = newPtr VI_Empty hp_var_heap + #! (tc_var_ptr, hp_var_heap) = newPtr VI_Empty hp_var_heap + #! type_context = + { tc_class = {glob_module = module_index, glob_object=class_ds} + , tc_types = [ TV class_var ] + , tc_var = tc_var_ptr + } + #! (member_type, modules, hp_type_heaps, hp_generic_heap, error) + = buildMemberType gen_def kind class_var modules hp_type_heaps hp_generic_heap error + #! member_type = { member_type & st_context = [type_context : member_type.st_context] } + #! member_def = { + me_symb = member_ident, + me_class = {glob_module = module_index, glob_object = class_index}, + me_offset = 0, + me_type = member_type, + me_type_ptr = type_ptr, // empty + me_class_vars = [class_var], // the same variable as in the class + me_pos = gen_pos, + me_priority = NoPrio + } + //---> ("member_type", member_type) + = (member_def, modules, {heaps & hp_type_heaps = hp_type_heaps, hp_var_heap = hp_var_heap, hp_generic_heap = hp_generic_heap}, error) + build_class class_var member_def=:{me_type} + #! class_member = + { ds_ident = member_ident + , ds_index = member_index + , ds_arity = me_type.st_arity + } + #! class_dictionary = + { ds_ident = class_ident + , ds_arity = 0 + , ds_index = NoIndex/*index in the type def table, filled in later*/ + } + #! class_def = { + class_name = class_ident, + class_arity = 1, + class_args = [class_var], + class_context = [], + class_pos = gen_pos, + class_members = createArray 1 class_member, + class_cons_vars = 0, // dotted class variables + class_dictionary = class_dictionary, + class_arg_kinds = [kind] + } + + = class_def + + +//**************************************************************************************** +// Convert generic cases +//**************************************************************************************** +convertGenericCases :: + !Index // current module + !NumberSet // used module numbers + !PredefinedSymbols + !*{#FunDef} + !{!Group} + !*{#CommonDefs} + !*{#DclModule} + !*TypeDefInfos + !*Heaps + !*ErrorAdmin + -> ( !IndexRange // created instance functions + , !*{#FunDef} // added instance functions + , !{!Group} // added instance groups + , !*{#CommonDefs} // added instances + , !*{#DclModule} // updated function types + , !*TypeDefInfos + , !*Heaps + , !*ErrorAdmin + ) +convertGenericCases + main_module_index used_module_numbers + predefs funs groups modules dcl_modules td_infos heaps error + + #! (first_fun_index, funs) = usize funs + #! first_group_index = size groups + #! fun_info = (first_fun_index, first_group_index, [], []) + + #! first_instance_index = size main_module_instances + #! instance_info = (first_instance_index, []) + + #! (modules1, dcl_modules, (fun_info, instance_info, funs, td_infos, heaps, error)) + = convert_modules 0 modules1 dcl_modules (fun_info, instance_info, funs, td_infos, heaps, error) + + #! (fun_index, group_index, new_funs, new_groups) = fun_info + #! funs = arrayPlusRevList funs new_funs + #! groups = arrayPlusRevList groups new_groups + + #! (instance_index, new_instances) = instance_info + #! com_instance_defs = arrayPlusRevList main_module_instances new_instances + + #! main_common_defs = {main_common_defs & com_instance_defs = com_instance_defs} + #! modules1 = {modules1 & [main_module_index] = main_common_defs} + + #! instance_fun_range = {ir_from=first_fun_index, ir_to=fun_index} + = (instance_fun_range, funs, groups, modules1, dcl_modules, td_infos, heaps, error) +where + + (main_common_defs, modules1) = modules ! [main_module_index] + main_module_classes = main_common_defs.com_class_defs + main_module_members = main_common_defs.com_member_defs + main_module_instances = main_common_defs.com_instance_defs + + convert_modules :: + !Index + !*{#CommonDefs} + !*{#DclModule} + ( FunsAndGroups + , (!Index, ![ClassInstance]) + , !*{#FunDef} + , !*TypeDefInfos + , !*Heaps + , !*ErrorAdmin + ) + -> (!*{#CommonDefs} + ,*{#DclModule} + , ( FunsAndGroups + , (!Index, ![ClassInstance]) + , !*{#FunDef} + , !*TypeDefInfos + , !*Heaps + , !*ErrorAdmin + ) + ) + convert_modules module_index modules dcl_modules st + | module_index == size modules + = (modules, dcl_modules, st) + #! (common_defs=:{com_gencase_defs}, modules) = modules ! [module_index] + #! (dcl_module=:{dcl_functions}, dcl_modules) = dcl_modules ! [module_index] + #! (dcl_functions, modules, st) + = convert_module module_index com_gencase_defs {x\\x<-:dcl_functions} modules st + #! dcl_modules = {dcl_modules & [module_index] = {dcl_module & dcl_functions = dcl_functions}} + = convert_modules (inc module_index) modules dcl_modules st + + convert_module module_index com_gencase_defs dcl_functions modules st + | inNumberSet module_index used_module_numbers + #! dcl_functions = {x\\x<-:dcl_functions} + = foldArraySt (convert_gencase module_index) + com_gencase_defs (dcl_functions, modules, st) + = (dcl_functions, modules, st) + + convert_gencase :: + !Index + !Index + !GenericCaseDef + (!*{#FunType} + ,!*Modules + , ( FunsAndGroups + , (!Index, ![ClassInstance]) + , !*{#FunDef} + , !*TypeDefInfos + , !*Heaps + , !*ErrorAdmin + ) + ) + -> (!*{#FunType} + ,!*Modules + , ( FunsAndGroups + , (!Index, ![ClassInstance]) + , !*{#FunDef} + , !*TypeDefInfos + , !*Heaps + , !*ErrorAdmin + ) + ) + convert_gencase module_index gc_index gencase=:{gc_name, gc_type} st + #! st = build_main_instance module_index gc_index gencase st + #! st = build_shorthand_instance_if_needed module_index gc_index gencase st + = st + //---> ("convert gencase", gc_name, gc_type) + + build_main_instance module_index gc_index + gencase=:{gc_name, gc_kind, gc_generic, gc_pos, gc_type, gc_type_cons, gc_body = GCB_FunIndex fun_index} + (dcl_functions, modules, (fun_info, ins_info, fun_defs, td_infos, heaps, error)) + #! ({gen_classes}, modules, heaps) + = get_generic_info gc_generic modules heaps + # (Yes class_info) + = lookupGenericClassInfo gc_kind gen_classes + + #! {class_members} + = main_module_classes . [class_info.gci_class] + #! member_def + = main_module_members . [class_members.[0].ds_index] + + #! ins_type = + { it_vars = case gc_type_cons of + TypeConsVar tv -> [tv] + _ -> [] + , it_types = [gc_type] + , it_attr_vars = [] + , it_context = [] + } + + #! (fun_type, heaps, error) + = determine_type_of_member_instance member_def ins_type heaps error + + #! (dcl_functions, heaps) + = update_dcl_function fun_index gencase fun_type dcl_functions heaps + + #! (fun_info, fun_defs, td_infos, modules, heaps, error) + = update_icl_function_if_needed + module_index + fun_index gencase fun_type + fun_info fun_defs td_infos modules heaps error + + #! (fun_info, ins_info, heaps) + = build_instance_and_member module_index class_info.gci_class gencase fun_type ins_type fun_info ins_info heaps + + = (dcl_functions, modules, (fun_info, ins_info, fun_defs, td_infos, heaps, error)) + + build_shorthand_instance_if_needed module_index gc_index gencase=:{gc_kind=KindConst} st + = st + build_shorthand_instance_if_needed + module_index gc_index + gencase=:{gc_name, gc_generic, gc_kind=KindArrow arg_kinds, gc_type} + (dcl_functions, modules, (fun_info, ins_info, fun_defs, td_infos, heaps, error)) + + #! (star_class_info, (modules, heaps)) + = get_class_for_kind gc_generic KindConst (modules, heaps) + + #! (arg_class_infos, (modules, heaps)) + = mapSt (get_class_for_kind gc_generic) arg_kinds (modules, heaps) + + #! {class_members} + = main_module_classes . [star_class_info.gci_class] + #! member_def + = main_module_members . [class_members.[0].ds_index] + + #! (ins_type, heaps) + = build_instance_type gc_type arg_class_infos heaps + + #! (fun_type, heaps, error) + = determine_type_of_member_instance member_def ins_type heaps error + + #! (memfun_ds, fun_info, heaps) + = build_shorthand_instance_member module_index gencase fun_type arg_class_infos fun_info heaps + + #! ins_info + = build_class_instance star_class_info.gci_class gencase memfun_ds ins_type ins_info + + = (dcl_functions, modules, (fun_info, ins_info, fun_defs, td_infos, heaps, error)) + where + build_instance_type type class_infos heaps=:{hp_type_heaps=th=:{th_vars},hp_var_heap} + #! arity = length class_infos + #! type_var_names = [makeIdent ("a" +++ toString i) \\ i <- [1 .. arity]] + #! (type_vars, th_vars) = mapSt freshTypeVar type_var_names th_vars + #! type_var_types = [TV tv \\ tv <- type_vars] + #! new_type_args = [makeAType t TA_Multi \\ t <- type_var_types] + + #! type = fill_type_args type new_type_args + + #! (contexts, hp_var_heap) + = zipWithSt build_context class_infos type_vars hp_var_heap + + #! ins_type = + { it_vars = type_vars + , it_types = [type] + , it_attr_vars = [] + , it_context = contexts + } + + = (ins_type, {heaps & hp_type_heaps = {th & th_vars = th_vars}, hp_var_heap = hp_var_heap}) + //---> ("instance type for shorthand instance", gc_name, gc_type, ins_type) + where + fill_type_args (TA type_symb_ident=:{type_arity} type_args) new_type_args + #! type_arity = type_arity + length new_type_args + #! type_args = type_args ++ new_type_args + = TA {type_symb_ident & type_arity = type_arity} type_args + fill_type_args TArrow [arg_type, res_type] + = arg_type --> res_type + fill_type_args (TArrow1 arg_type) [res_type] + = arg_type --> res_type + fill_type_args type args + = abort ("fill_type_args\n"---> ("fill_type_args", type, args)) + + build_context {gci_class, gci_module, gci_kind} tv hp_var_heap + # (var_info_ptr, hp_var_heap) = newPtr VI_Empty hp_var_heap + # type_context = + { tc_class = + { glob_module=gci_module // the same as icl module + , glob_object = + { ds_ident = genericIdentToClassIdent gc_name gci_kind + , ds_index = gci_class + , ds_arity = 1 + } + } + , tc_types = [TV tv] + , tc_var = var_info_ptr + } + = (type_context, hp_var_heap) + + get_generic_info {gi_module, gi_index} modules heaps=:{hp_generic_heap} + #! ({gen_info_ptr}, modules) + = modules ! [gi_module] . com_generic_defs . [gi_index] + #! (gen_info, hp_generic_heap) = readPtr gen_info_ptr hp_generic_heap + = (gen_info, modules, {heaps & hp_generic_heap = hp_generic_heap}) + + get_class_for_kind generic_gi kind (modules, heaps) + #! ({gen_classes}, modules, heaps) = get_generic_info generic_gi modules heaps + # (Yes class_info) = lookupGenericClassInfo kind gen_classes + = (class_info, (modules, heaps)) + + + determine_type_of_member_instance :: !MemberDef !InstanceType !*Heaps !*ErrorAdmin + -> (!SymbolType, !*Heaps, !*ErrorAdmin) + determine_type_of_member_instance {me_type, me_class_vars} ins_type heaps=:{hp_type_heaps, hp_var_heap} error + #! (symbol_type, _, hp_type_heaps, _, error) + = determineTypeOfMemberInstance me_type me_class_vars ins_type SP_None hp_type_heaps No error + #! (st_context, hp_var_heap) = initializeContextVariables symbol_type.st_context hp_var_heap + #! hp_type_heaps = clearSymbolType me_type hp_type_heaps + #! symbol_type = {symbol_type & st_context = st_context} + #! heaps = {heaps & hp_type_heaps = hp_type_heaps, hp_var_heap = hp_var_heap} + = (symbol_type, heaps, error) + //---> ("determine_type_of_member_instance", ins_type, symbol_type) + + update_dcl_function :: !Index !GenericCaseDef !SymbolType !*{#FunType} !*Heaps + -> (!*{#FunType}, !*Heaps) + update_dcl_function fun_index {gc_name, gc_type_cons} symbol_type dcl_functions heaps + | fun_index < size dcl_functions + #! (symbol_type, heaps) = fresh_symbol_type symbol_type heaps + #! (fun, dcl_functions) = dcl_functions ! [fun_index] + #! fun = + { fun + & ft_symb = genericIdentToFunIdent gc_name gc_type_cons + , ft_type = symbol_type + } + #! dcl_functions = { dcl_functions & [fun_index] = fun} + = (dcl_functions, heaps) + //---> ("update dcl function", fun.ft_symb, fun_index, symbol_type) + = (dcl_functions, heaps) + //---> ("update dcl function: not in the dcl module", fun_index) + + update_icl_function_if_needed module_index fun_index gencase fun_type fun_info fun_defs td_infos modules heaps error + | module_index == main_module_index // current module + #! (fi, gi, fs, gs) = fun_info + #! (gi, gs, fun_defs, td_infos, modules, heaps, error) + = update_icl_function fun_index gencase fun_type gi gs fun_defs td_infos modules heaps error + = ((fi, gi, fs, gs), fun_defs, td_infos, modules, heaps, error) + = (fun_info, fun_defs, td_infos, modules, heaps, error) + + update_icl_function :: + !Index !GenericCaseDef !SymbolType + !Index ![Group] !*{#FunDef} !*TypeDefInfos !*{#CommonDefs} !*Heaps !*ErrorAdmin + -> (!Index, ![Group], !*{#FunDef}, !*TypeDefInfos, !*{#CommonDefs}, !*Heaps, !*ErrorAdmin) + update_icl_function fun_index gencase=:{gc_name, gc_type_cons, gc_pos} st group_index groups fun_defs td_infos modules heaps error + #! (st, heaps) = fresh_symbol_type st heaps + #! (fun=:{fun_body, fun_arity}, fun_defs) = fun_defs ! [fun_index] + #! fun_ident = genericIdentToFunIdent gc_name gc_type_cons + = case fun_body of + TransformedBody tb // user defined case + | fun_arity <> st.st_arity + # error = reportError gc_name gc_pos + ("incorrect arity: " +++ toString st.st_arity +++ " expected") error + -> (group_index, groups, fun_defs, td_infos, modules, heaps, error) + #! fun = + { fun + & fun_symb = fun_ident + , fun_type = Yes st + , fun_body = fun_body + } + #! fun_defs = { fun_defs & [fun_index] = fun } + -> (group_index, groups, fun_defs, td_infos, modules, heaps, error) + //---> ("update_icl_function, TransformedBody", fun.fun_symb, fun_index, st) + + GeneratedBody // derived case + #! (TransformedBody {tb_args, tb_rhs}, td_infos, modules, heaps, error) + = buildGenericCaseBody main_module_index gencase st predefs td_infos modules heaps error + //---> ("call buildGenericCaseBody\n") + #! fun = makeFunction fun_ident fun_index group_index tb_args tb_rhs (Yes st) main_module_index gc_pos + #! fun_defs = { fun_defs & [fun_index] = fun } + + # group = {group_members=[fun_index]} + + -> (inc group_index, [group:groups], fun_defs, td_infos, modules, heaps, error) + //---> ("update_icl_function, GeneratedBody", fun.fun_symb, fun_index, st) + _ -> abort "update_icl_function: generic case body\n" + + // build wrapping instance for the generic case function + build_instance_and_member :: !Index !Index !GenericCaseDef !SymbolType !InstanceType !FunsAndGroups (!Index, ![ClassInstance]) !*Heaps + -> (!FunsAndGroups, (!Index, ![ClassInstance]), !*Heaps) + build_instance_and_member module_index class_index gencase symbol_type ins_type fun_info ins_info heaps + #! (memfun_ds, fun_info, heaps) + = build_instance_member module_index gencase symbol_type fun_info heaps +/* + #! ins_type = + { it_vars = [] + , it_types = [gencase.gc_type] + , it_attr_vars = [] + , it_context = [] + } +*/ + #! ins_info = build_class_instance class_index gencase memfun_ds ins_type ins_info + = (fun_info, ins_info, heaps) + + // Creates a function that just calls the generic case function + // It is needed because the instance member must be in the same + // module as the instance itself + build_instance_member module_index gencase st fun_info heaps + + # {gc_name, gc_pos, gc_type_cons, gc_kind, gc_body=GCB_FunIndex fun_index} = gencase + #! arg_var_names = ["x" +++ toString i \\ i <- [1..st.st_arity]] + #! (arg_var_exprs, arg_vars, heaps) = buildVarExprs arg_var_names heaps + + #! (expr_info_ptr, hp_expression_heap) = newPtr EI_Empty heaps.hp_expression_heap + #! heaps = {heaps & hp_expression_heap = hp_expression_heap} + #! fun_name = genericIdentToFunIdent gc_name gc_type_cons + #! expr = App + { app_symb = + { symb_name=fun_name + , symb_kind=SK_Function {glob_module=module_index, glob_object=fun_index} + } + , app_args = arg_var_exprs + , app_info_ptr = expr_info_ptr + } + + #! (st, heaps) = fresh_symbol_type st heaps + + #! memfun_name = genericIdentToMemberIdent gc_name gc_kind + #! (fun_ds, fun_info) + = buildFunAndGroup memfun_name arg_vars expr (Yes st) main_module_index gc_pos fun_info + = (fun_ds, fun_info, heaps) + + build_shorthand_instance_member module_index gencase=:{gc_generic, gc_name, gc_kind, gc_pos} st class_infos fun_info heaps + #! arg_var_names = ["x" +++ toString i \\ i <- [1..st.st_arity]] + #! (arg_var_exprs, arg_vars, heaps) = buildVarExprs arg_var_names heaps + + #! (expr_info_ptr, hp_expression_heap) = newPtr EI_Empty heaps.hp_expression_heap + #! heaps = {heaps & hp_expression_heap = hp_expression_heap} + #! fun_name = genericIdentToMemberIdent gc_name KindConst + + # (gen_exprs, heaps) = mapSt (build_generic_app gc_generic gc_name) class_infos heaps + + # (body_expr, heaps) + = buildGenericApp gc_generic.gi_module gc_generic.gi_index + gc_name gc_kind (gen_exprs ++ arg_var_exprs) heaps + + #! (st, heaps) = fresh_symbol_type st heaps + + #! (fun_ds, fun_info) + = buildFunAndGroup fun_name arg_vars body_expr (Yes st) main_module_index gc_pos fun_info + + = (fun_ds, fun_info, heaps) + //---> ("shorthand instance body", body_expr) + where + build_generic_app {gi_module, gi_index} gc_name {gci_kind} heaps + = buildGenericApp gi_module gi_index gc_name gci_kind [] heaps + + build_class_instance class_index gencase member_fun_ds ins_type (ins_index, instances) + + # {gc_pos, gc_name, gc_kind} = gencase + + #! class_name = genericIdentToClassIdent gc_name gc_kind + #! class_ds = {ds_index = class_index, ds_arity=1, ds_ident=class_name} + #! ins = + { ins_class = {glob_module=main_module_index, glob_object=class_ds} + , ins_ident = class_name + , ins_type = ins_type + , ins_members = {member_fun_ds} + , ins_specials = SP_None + , ins_pos = gc_pos + , ins_generated = True + } + + = (inc ins_index, [ins:instances]) + + fresh_symbol_type :: !SymbolType !*Heaps -> (!SymbolType, !*Heaps) + fresh_symbol_type st heaps=:{hp_type_heaps} + # (fresh_st, hp_type_heaps) = freshSymbolType st hp_type_heaps + = (fresh_st, {heaps & hp_type_heaps = hp_type_heaps}) + //---> ("fresh_symbol_type") + +buildGenericCaseBody :: + !Index + !GenericCaseDef + !SymbolType + !PredefinedSymbols + !*TypeDefInfos + !*{#CommonDefs} + !*Heaps + !*ErrorAdmin + -> ( !FunctionBody + , !*TypeDefInfos + , !*{#CommonDefs} + , !*Heaps + , !*ErrorAdmin + ) +buildGenericCaseBody main_module_index {gc_name,gc_pos, gc_generic, gc_type_cons=TypeConsSymb {type_index}} st predefs td_infos modules heaps error + + // get all the data we need + #! (gen_def=:{gen_vars, gen_type, gen_bimap}, modules) + = modules ! [gc_generic.gi_module].com_generic_defs.[gc_generic.gi_index] + #! (td_info=:{tdi_gen_rep}, td_infos) + = td_infos ! [type_index.glob_module, type_index.glob_object] + # ({gtr_iso, gtr_type}) = case tdi_gen_rep of + Yes x -> x + No -> abort "no generic representation\n" + + #! (type_def=:{td_args}, modules) + = modules ! [type_index.glob_module].com_type_defs.[type_index.glob_object] + + #! original_arity = gen_type.st_arity // arity of generic type + #! generated_arity = st.st_arity - original_arity // number of added arguments (arity of the kind) + + // generate variable names and exprs + #! generated_arg_names = [ "f" +++ toString n \\ n <- [1 .. generated_arity]] + #! (generated_arg_exprs, generated_arg_vars, heaps) = buildVarExprs generated_arg_names heaps + #! original_arg_names = [ "x" +++ toString n \\ n <- [1 .. original_arity]] + #! (original_arg_exprs, original_arg_vars, heaps) = buildVarExprs original_arg_names heaps + #! arg_vars = generated_arg_vars ++ original_arg_vars + + // create adaptor + #! (iso_exprs, heaps) + = unfoldnSt (buildFunApp main_module_index gtr_iso []) (length gen_vars) heaps + #! (bimap_id_exprs, heaps) + = unfoldnSt (buildPredefFunApp PD_bimapId [] predefs) (length (gen_type.st_vars -- gen_vars)) heaps + + //#! (bimap_expr, heaps) + // = buildFunApp main_module_index gen_bimap iso_exprs heaps + #! spec_env = + [(tv,expr)\\tv <- gen_vars & expr <- iso_exprs] + ++ + [(tv,expr)\\tv <- gen_type.st_vars -- gen_vars & expr <- bimap_id_exprs] + #! curried_gen_type = curry_symbol_type gen_type + #! {pds_module = bimap_module, pds_def=bimap_index} = predefs.[PD_GenericBimap] + + #! (bimap_expr, (td_infos, heaps, error)) + = buildSpecializedExpr1 + bimap_module bimap_index + curried_gen_type spec_env + gc_name gc_pos + (td_infos, heaps, error) + + #! adaptor_expr = buildRecordSelectionExpr bimap_expr PD_map_from predefs + + // create expression for the generic representation + #! spec_env = [(atv_variable, expr) \\ {atv_variable} <- td_args & expr <- generated_arg_exprs] + #! (specialized_expr, (td_infos, heaps, error)) + = buildSpecializedExpr1 + gc_generic.gi_module gc_generic.gi_index + gtr_type spec_env + gc_name gc_pos + (td_infos, heaps, error) + + // create the body expr + #! body_expr = if (isEmpty original_arg_exprs) + (adaptor_expr @ [specialized_expr]) + ((adaptor_expr @ [specialized_expr]) @ original_arg_exprs) + + = (TransformedBody {tb_args=arg_vars, tb_rhs=body_expr}, td_infos, modules, heaps, error) + //---> (" buildGenericCaseBody", body_expr) +where + curry_symbol_type {st_args, st_result} + = foldr (\x y -> makeAType (x --> y) TA_Multi) st_result st_args + +//buildGenericCaseBody main_module_index {gc_name,gc_pos, gc_generic, gc_type_cons=TypeConsSymb {type_index}} st predefs td_infos modules heaps error +buildGenericCaseBody main_module_index {gc_name,gc_pos} st predefs td_infos modules heaps error + # error = reportError gc_name gc_pos "cannot specialize to this type" error + = (TransformedBody {tb_args=[], tb_rhs=EE}, td_infos, modules, heaps, error) + +//**************************************************************************************** +// specialization +//**************************************************************************************** + +buildSpecializedExpr1 :: + !Index // generic module + !Index // generic index + !AType // type to specialize to + ![(TypeVar, Expression)] // specialization environment + !Ident // generic/generic case + !Position // of generic case + (!*TypeDefInfos, !*Heaps, !*ErrorAdmin) + -> ( !Expression + , !(!*TypeDefInfos, !*Heaps, !*ErrorAdmin) + ) +buildSpecializedExpr1 gen_module gen_index atype spec_env ident pos (td_infos, heaps, error) + + #! heaps = set_tvs spec_env heaps + #! (expr, (td_infos, heaps, error)) + = buildSpecializedExpr gen_module gen_index atype ident pos (td_infos, heaps, error) + + #! heaps = clear_tvs spec_env heaps + = (expr, (td_infos, heaps, error)) +where + set_tvs spec_env heaps=:{hp_type_heaps=hp_type_heaps=:{th_vars}} + #! th_vars = foldSt write_tv spec_env th_vars + with write_tv ({tv_info_ptr}, expr) th_vars + = writePtr tv_info_ptr (TVI_Expr expr) th_vars + = {heaps & hp_type_heaps = {hp_type_heaps & th_vars = th_vars }} + + clear_tvs spec_env heaps=:{hp_type_heaps=hp_type_heaps=:{th_vars}} + #! th_vars = foldSt write_tv spec_env th_vars + with write_tv ({tv_info_ptr}, _) th_vars + = writePtr tv_info_ptr TVI_Empty th_vars + = {heaps & hp_type_heaps = {hp_type_heaps & th_vars = th_vars }} + +// generates an expression that corresponds to a type +buildSpecializedExpr :: + !Index // generic module index + !Index // generic index + !AType // type to specialize to + // tv_info_ptr of type variables must contain expressions + // corresponding to the type variables + !Ident // for error reporting + !Position // for error reporting + !(!*TypeDefInfos, !*Heaps, !*ErrorAdmin) + -> ( !Expression // generated expression + , !(!*TypeDefInfos, !*Heaps, !*ErrorAdmin) + ) +buildSpecializedExpr gen_module gen_index type gen_name pos gs + = spec_atype type gs +where + spec_atype {at_type} gs = spec_type at_type gs + + spec_atypes [] gs = ([], gs) + spec_atypes [type:types] gs + # (expr, gs) = spec_atype type gs + # (exprs, gs) = spec_atypes types gs + = ([expr:exprs], gs) + + spec_type :: !Type !(!*TypeDefInfos, !*Heaps, !*ErrorAdmin) + -> !(Expression, !(!*TypeDefInfos, !*Heaps, !*ErrorAdmin)) + spec_type (TA {type_index, type_name} args) st + # (arg_exprs, st) = spec_atypes args st + # (kind, st) = get_kind type_index st + = build_generic_app kind arg_exprs st + spec_type (TAS {type_index, type_name} args _) st + # (arg_exprs, st) = spec_atypes args st + # (kind, st) = get_kind type_index st + = build_generic_app kind arg_exprs st + spec_type (arg_type --> res_type) st + #! (arg_expr, st) = spec_atype arg_type st + #! (res_expr, st) = spec_atype res_type st + = build_generic_app (KindArrow [KindConst, KindConst]) [arg_expr, res_expr] st + spec_type ((CV type_var) :@: args) gs + #! (expr, gs) = spec_type_var type_var gs + #! (exprs, gs) = spec_atypes args gs + = (expr @ exprs, gs) + spec_type (TB basic_type) st + = build_generic_app KindConst [] st + spec_type (TFA atvs type) (td_infos, heaps, error) + #! error = reportError gen_name pos "cannot specialize to forall types" error + = (EE, (td_infos, heaps, error)) + spec_type (TV type_var) gs = spec_type_var type_var gs + //spec_type (GTV type_var) gs = spec_type_var type_var gs + //spec_type (TQV type_var) gs = spec_type_var type_var gs + //spec_type (TLifted type_var) gs = spec_type_var type_var gs + spec_type _ (td_infos, heaps, error) + #! error = reportError gen_name pos "cannot specialize to this type" error + = (EE, (td_infos, heaps, error)) + + spec_type_var tv=:{tv_info_ptr} (td_infos, heaps=:{hp_type_heaps=th=:{th_vars}}, error) + #! (TVI_Expr expr, th_vars) = readPtr tv_info_ptr th_vars + = (expr, (td_infos, {heaps & hp_type_heaps = {th & th_vars = th_vars}}, error)) + + build_generic_app kind arg_exprs (td_infos, heaps, error) + # (expr, heaps) + = buildGenericApp gen_module gen_index gen_name kind arg_exprs heaps + = (expr, (td_infos, heaps, error)) + + get_kind {glob_module, glob_object} (td_infos, heaps, error) + # (td_info, td_infos) = td_infos ! [glob_module, glob_object] + = (make_kind td_info.tdi_kinds, (td_infos, heaps, error)) + where + make_kind [] = KindConst + make_kind ks = KindArrow ks + +//**************************************************************************************** +// kind indexing of generic types +//**************************************************************************************** + +// kind indexing: +// t_* a1 ... an = t a1 ... an +// t_{k->l} a1 ... an = forall b1...bn.(t_k b1 ... bn) -> (t_l (a1 b1) ... (an bn)) +buildKindIndexedType :: + !SymbolType // symbol type to kind-index + ![TypeVar] // generic type variables + !TypeKind // kind index + !Ident // name for debugging + !Position // position for debugging + !*TypeHeaps // type heaps + !*ErrorAdmin + -> ( !SymbolType // instantiated type + , ![ATypeVar] // fresh generic type variables + , !*TypeHeaps // type heaps + , !*ErrorAdmin + ) +buildKindIndexedType st gtvs kind ident pos th error + + #! th = clearSymbolType st th + //---> ("buildKindIndexedType called for", kind, gtvs, st) + #! (fresh_st, fresh_gtvs, th) = fresh_generic_type st gtvs th + + #! (gatvs, th) = collectAttrsOfTypeVarsInSymbolType fresh_gtvs fresh_st th + + #! (kind_indexed_st, _, th, error) = build_symbol_type fresh_st gatvs kind 1 th error + + #! th = clearSymbolType kind_indexed_st th + #! th = clearSymbolType st th // paranoja + = (kind_indexed_st, gatvs, th, error) + //---> ("buildKindIndexedType returns", kind_indexed_st) +where + + fresh_generic_type st gtvs th + # (fresh_st, th) = freshSymbolType st th + # fresh_gtvs = take (length gtvs) fresh_st.st_vars + = (fresh_st, fresh_gtvs, th) + //---> ("fresh_generic_type", fresh_gtvs, fresh_st) + + build_symbol_type :: + !SymbolType // generic type, + ![ATypeVar] // attributed generic variables + !TypeKind // kind to specialize to + !Int // current order (in the sense of the order of the kind) + !*TypeHeaps + !*ErrorAdmin + -> ( !SymbolType // new generic type + , ![ATypeVar] // fresh copies of generic variables created for the + // generic arguments + , !*TypeHeaps + , !*ErrorAdmin + ) + build_symbol_type st gatvs KindConst order th error + = (st, [], th, error) + build_symbol_type st gatvs (KindArrow kinds) order th error + | order > 2 + //---> ("build_symbol_type called for", (KindArrow kinds), gatvs, st) + # error = reportError ident pos "kinds of order higher then 2 are not supported" error + = (st, [], th, error) + + # (arg_sts, arg_gatvss, th, error) + = build_args st gatvs order kinds th error + + # (body_st, th) + = build_body st gatvs (transpose arg_gatvss) th + + # num_added_args = length kinds + # new_st = + { st_vars = removeDup ( + foldr (++) body_st.st_vars [st_vars \\ {st_vars}<-arg_sts]) + , st_attr_vars = removeDup ( + foldr (++) body_st.st_attr_vars [st_attr_vars \\ {st_attr_vars}<-arg_sts]) + , st_args = [st_result \\ {st_result}<-arg_sts] ++ body_st.st_args + , st_result = body_st.st_result + , st_arity = body_st.st_arity + num_added_args + , st_context = removeDup( + foldr (++) body_st.st_context [st_context \\ {st_context} <- arg_sts]) + , st_attr_env = removeDup( + foldr (++) body_st.st_attr_env [st_attr_env \\ {st_attr_env} <- arg_sts]) + , st_args_strictness = insert_n_lazy_values_at_beginning num_added_args body_st.st_args_strictness + } + + = (new_st, flatten arg_gatvss, th, error) + //---> ("build_symbol_type returns", arg_gatvss, st) + + build_args st gatvs order kinds th error + # (arg_sts_and_gatvss, (_,th,error)) + = mapSt (build_arg st gatvs order) kinds (1,th,error) + # (arg_sts, arg_gatvss) = unzip arg_sts_and_gatvss + = (arg_sts, arg_gatvss, th, error) + + build_arg :: + !SymbolType // current part of the generic type + ![ATypeVar] // generic type variables with their attrs + !Int // order + !TypeKind // kind corrseponding to the arg + ( !Int // the argument number + , !*TypeHeaps + , !*ErrorAdmin + ) + -> ( (!SymbolType, [ATypeVar]) // fresh symbol type and generic variables + , ( !Int // incremented argument number + , !*TypeHeaps + , !*ErrorAdmin + ) + ) + build_arg st gatvs order kind (arg_num, th, error) + #! th = clearSymbolType st th + //---> ("build_arg called for", arg_num, kind, gatvs, st) + #! (fresh_gatvs, th) = mapSt subst_gatv gatvs th + #! (new_st, th) = applySubstInSymbolType st th + + #! (new_st, forall_atvs, th, error) + = build_symbol_type new_st fresh_gatvs kind (inc order) th error + #! (curry_st, th) + = curryGenericArgType1 new_st ("cur" +++ toString order +++ postfix) th + + #! curry_st = adjust_forall curry_st forall_atvs + + = ((curry_st, fresh_gatvs), (inc arg_num, th, error)) + //---> ("build_arg returns", fresh_gatvs, curry_st) + where + postfix = toString arg_num + + subst_gatv atv=:{atv_attribute, atv_variable} th=:{th_attrs, th_vars} + # (tv, th_vars) = subst_gtv atv_variable th_vars + # (attr, th_attrs) = subst_attr atv_attribute th_attrs + = ( {atv & atv_variable = tv, atv_attribute = attr} + , {th & th_vars = th_vars, th_attrs = th_attrs} + ) + + // generic type var is replaced with a fresh one + subst_gtv {tv_info_ptr, tv_name} th_vars + # (tv, th_vars) = freshTypeVar (postfixIdent tv_name postfix) th_vars + = (tv, writePtr tv_info_ptr (TVI_Type (TV tv)) th_vars) + + subst_attr (TA_Var {av_name, av_info_ptr}) th_attrs + # (av, th_attrs) = freshAttrVar (postfixIdent av_name postfix) th_attrs + = (TA_Var av, writePtr av_info_ptr (AVI_Attr (TA_Var av)) th_attrs) + //---> ("(2) writePtr av_info_ptr", ptrToInt av_info_ptr, av) + subst_attr TA_Multi th = (TA_Multi, th) + subst_attr TA_Unique th = (TA_Unique, th) + + adjust_forall curry_st [] = curry_st + adjust_forall curry_st=:{st_result} forall_atvs + #! st_result = {st_result & at_type = TFA forall_atvs st_result.at_type} + = { curry_st + & st_result = st_result + , st_attr_vars + = curry_st.st_attr_vars -- [av \\ {atv_attribute=TA_Var av} <- forall_atvs] + , st_vars + = curry_st.st_vars -- [atv_variable \\ {atv_variable} <- forall_atvs] + } + //---> ("adjust forall", curry_st.st_vars, forall_atvs, curry_st.st_vars -- [atv_variable \\ {atv_variable} <- forall_atvs]) + + build_body :: + !SymbolType + ![ATypeVar] + ![[ATypeVar]] + !*TypeHeaps + -> (!SymbolType + , !*TypeHeaps + ) + build_body st gatvs arg_gatvss th + # th = clearSymbolType st th + # th = fold2St subst_gatv gatvs arg_gatvss th + = applySubstInSymbolType st th + where + subst_gatv gatv=:{atv_variable} arg_gatvs th=:{th_vars} + #! type_args = [ makeAType (TV atv_variable) atv_attribute + \\ {atv_variable, atv_attribute} <- arg_gatvs] + #! type = (CV atv_variable) :@: type_args + #! th_vars = writePtr atv_variable.tv_info_ptr (TVI_Type type) th_vars + = {th & th_vars = th_vars} + +reportError name pos msg error=:{ea_file} + //= checkErrorWithIdentPos (newPosition name pos) msg error + # ea_file = ea_file <<< "Error " <<< (newPosition name pos) <<< ":" <<< msg <<< '\n' + = { error & ea_file = ea_file , ea_ok = False } + +reportWarning name pos msg error=:{ea_file} + # ea_file = ea_file <<< "Warning " <<< (newPosition name pos) <<< ":" <<< msg <<< '\n' + = { error & ea_file = ea_file } + +//**************************************************************************************** +// Type Helpers +//**************************************************************************************** +makeAType :: !Type !TypeAttribute -> !AType +makeAType type attr = { at_attribute = attr, at_type = type } + +makeATypeVar :: !TypeVar !TypeAttribute -> !ATypeVar +makeATypeVar tv attr = {atv_variable = tv, atv_attribute = attr} + +//---------------------------------------------------------------------------------------- +// folding of a AType, depth first +//---------------------------------------------------------------------------------------- + +class foldType t :: (Type .st -> .st) (AType .st -> .st) t .st -> .st + +instance foldType [a] | foldType a where + foldType on_type on_atype types st + = foldSt (foldType on_type on_atype) types st + +instance foldType (a,b) | foldType a & foldType b where + foldType on_type on_atype (x,y) st + = foldType on_type on_atype y (foldType on_type on_atype x st) + +instance foldType Type where + foldType on_type on_atype type st + # st = fold_type type st + = on_type type st + where + fold_type (TA type_symb args) st = foldType on_type on_atype args st + fold_type (TAS type_symb args _) st = foldType on_type on_atype args st + fold_type (l --> r) st = foldType on_type on_atype (l,r) st + fold_type (TArrow) st = st + fold_type (TArrow1 t) st = foldType on_type on_atype t st + fold_type (_ :@: args) st = foldType on_type on_atype args st + fold_type (TB _) st = st + fold_type (TFA tvs type) st = foldType on_type on_atype type st + fold_type (GTV _) st = st + fold_type (TV _) st = st + fold_type t st = abort "foldType: does not match\n" ---> ("type", t) + +instance foldType AType where + foldType on_type on_atype atype=:{at_type} st + # st = foldType on_type on_atype at_type st + = on_atype atype st + +instance foldType TypeContext where + foldType on_type on_atype {tc_types} st + = foldType on_type on_atype tc_types st + +//---------------------------------------------------------------------------------------- +// mapping of a AType, depth first +//---------------------------------------------------------------------------------------- +class mapTypeSt type :: + (Type .st -> (Type, .st)) // called on each type before recursion + (AType .st -> (AType, .st)) // called on each attributed type before recursion + (Type .st -> (Type, .st)) // called on each type after recursion + (AType .st -> (AType, .st)) // called on each attributed type after recursion + type .st -> (type, .st) + +mapTypeBeforeSt :: + (Type .st -> (Type, .st)) // called on each type before recursion + (AType .st -> (AType, .st)) // called on each attributed type before recursion + type .st -> (type, .st) | mapTypeSt type +mapTypeBeforeSt on_type_before on_atype_before type st + = mapTypeSt on_type_before on_atype_before idSt idSt type st + +mapTypeAfterSt :: + (Type .st -> (Type, .st)) // called on each type after recursion + (AType .st -> (AType, .st)) // called on each attributed type after recursion + type .st -> (type, .st) | mapTypeSt type +mapTypeAfterSt on_type_after on_atype_after type st + = mapTypeSt idSt idSt on_type_after on_atype_after type st + +instance mapTypeSt [a] | mapTypeSt a where + mapTypeSt on_type_before on_atype_before on_type_after on_atype_after type st + = mapSt (mapTypeSt on_type_before on_atype_before on_type_after on_atype_after) type st + +instance mapTypeSt (a, b) | mapTypeSt a & mapTypeSt b where + mapTypeSt on_type_before on_atype_before on_type_after on_atype_after (x, y) st + #! (x1, st) = mapTypeSt on_type_before on_atype_before on_type_after on_atype_after x st + #! (y1, st) = mapTypeSt on_type_before on_atype_before on_type_after on_atype_after y st + = ((x1,y1), st) + +instance mapTypeSt Type where + mapTypeSt on_type_before on_atype_before on_type_after on_atype_after type st + #! (type1, st) = on_type_before type st + #! (type2, st) = map_type type1 st + #! (type3, st) = on_type_after type2 st + = (type3, st) + //---> ("mapTypeSt Type", type, type1, type2, type3) + where + + map_type (TA type_symb_ident args) st + #! (args, st) = mapTypeSt on_type_before on_atype_before on_type_after on_atype_after args st + = (TA type_symb_ident args, st) + map_type (TAS type_symb_ident args strictness) st + #! (args, st) = mapTypeSt on_type_before on_atype_before on_type_after on_atype_after args st + = (TAS type_symb_ident args strictness, st) + map_type (l --> r) st + #! ((l,r), st) = mapTypeSt on_type_before on_atype_before on_type_after on_atype_after (l,r) st + = (l --> r, st) + map_type TArrow st = (TArrow, st) + map_type (TArrow1 t) st + #! (t, st) = mapTypeSt on_type_before on_atype_before on_type_after on_atype_after t st + = (TArrow1 t, st) + map_type (cv :@: args) st + #! (args, st) = mapTypeSt on_type_before on_atype_before on_type_after on_atype_after args st + = (cv :@: args, st) + map_type t=:(TB _) st = (t, st) + map_type (TFA tvs type) st + #! (type, st) = mapTypeSt on_type_before on_atype_before on_type_after on_atype_after type st + = (TFA tvs type, st) + map_type t=:(GTV _) st = (t, st) + map_type t=:(TV _) st = (t, st) + map_type t st + = abort "mapTypeSt: type does not match\n" ---> ("type", t) + +instance mapTypeSt AType where + mapTypeSt on_type_before on_atype_before on_type_after on_atype_after atype st + #! (atype, st) = on_atype_before atype st + #! (at_type, st) = mapTypeSt on_type_before on_atype_before on_type_after on_atype_after atype.at_type st + = on_atype_after {atype & at_type = at_type} st + +instance mapTypeSt TypeContext where + mapTypeSt on_type_before on_atype_before on_type_after on_atype_after tc=:{tc_types} st + #! (tc_types, st) = mapTypeSt on_type_before on_atype_before on_type_after on_atype_after tc_types st + = ({tc&tc_types=tc_types}, st) + + +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- + +// allocate fresh type variable +freshTypeVar :: !Ident !*TypeVarHeap -> (!TypeVar, !*TypeVarHeap) +freshTypeVar name th_vars + # (info_ptr, th_vars) = newPtr TVI_Empty th_vars + = ({tv_name = name, tv_info_ptr = info_ptr}, th_vars) + +// allocate fresh attribute variable +freshAttrVar :: !Ident !*AttrVarHeap -> (!AttributeVar, !*AttrVarHeap) +freshAttrVar name th_attrs + # (info_ptr, th_attrs) = newPtr AVI_Empty th_attrs + = ({av_name = name, av_info_ptr = info_ptr}, th_attrs) + + +// take a fresh copy of a SymbolType +freshSymbolType :: + !SymbolType // symbol type to take fresh + !*TypeHeaps // variable storage + -> ( !SymbolType // fresh symbol type + , !*TypeHeaps // variable storage + ) +freshSymbolType st th=:{th_vars, th_attrs} + #! (fresh_st_vars, th_vars) = mapSt subst_type_var st.st_vars th_vars + //---> ("freshSymbolType called for", st) + #! (fresh_st_attr_vars, th_attrs) = mapSt subst_attr_var st.st_attr_vars th_attrs + #! th = {th & th_vars = th_vars, th_attrs = th_attrs} + + #! (fresh_st_args, th) = fresh_type st.st_args th + #! (fresh_st_result, th) = fresh_type st.st_result th + #! (fresh_st_context, th) = fresh_type st.st_context th + #! (fresh_st_attr_env, th) = mapSt fresh_ineq st.st_attr_env th + + #! fresh_st = + { st + & st_args = fresh_st_args + , st_result = fresh_st_result + , st_context = fresh_st_context + , st_attr_env = fresh_st_attr_env + , st_vars = fresh_st_vars + , st_attr_vars = fresh_st_attr_vars + } + + #! th = clearSymbolType fresh_st th + #! th = clearSymbolType st th + + #! th = assertSymbolType fresh_st th + #! th = assertSymbolType st th + + = (fresh_st, th) + //---> ("freshSymbolType returns", fresh_st) +where + subst_type_var :: !TypeVar !*TypeVarHeap -> (!TypeVar, !*TypeVarHeap) + subst_type_var tv=:{tv_info_ptr} th_vars + # (new_ptr, th_vars) = newPtr TVI_Empty th_vars + = ({tv & tv_info_ptr=new_ptr}, writePtr tv_info_ptr (TVI_TypeVar new_ptr) th_vars) + subst_attr_var :: !AttributeVar !*AttrVarHeap -> (!AttributeVar, !*AttrVarHeap) + subst_attr_var av=:{av_info_ptr} th_attrs + # (new_ptr, th_attrs) = newPtr AVI_Empty th_attrs + = ({av & av_info_ptr = new_ptr}, writePtr av_info_ptr (AVI_AttrVar new_ptr) th_attrs) + + fresh_type :: type !*TypeHeaps -> (type, !*TypeHeaps) | mapTypeSt type + fresh_type t st = mapTypeBeforeSt on_type on_atype t st + + on_type (TV tv) th + #! (tv, th) = on_type_var tv th + = (TV tv, th) + on_type (GTV tv) th + #! (tv, th) = on_type_var tv th + = (GTV tv, th) + on_type (CV tv=:{tv_info_ptr} :@: args) th=:{th_vars} + #! (tv, th) = on_type_var tv th + = (CV tv :@: args, th) + on_type (TFA atvs type) th + #! (fresh_atvs, th) = mapSt subst_atv atvs th + // the variables in the type will be substituted by + // the recursive call of mapType + = (TFA fresh_atvs type, th) + where + subst_atv atv=:{atv_variable, atv_attribute} th=:{th_vars, th_attrs} + #! (atv_variable, th_vars) = subst_type_var atv_variable th_vars + # (atv_attribute, th_attrs) = subst_attr atv_attribute th_attrs + = ( {atv & atv_variable = atv_variable, atv_attribute = atv_attribute} + , {th & th_vars = th_vars, th_attrs = th_attrs}) + subst_attr (TA_Var av=:{av_info_ptr}) th_attrs + # (av_info, th_attrs) = readPtr av_info_ptr th_attrs + = case av_info of + AVI_Empty + # (av, th_attrs) = subst_attr_var av th_attrs + -> (TA_Var av, th_attrs) + AVI_AttrVar av_info_ptr + -> (TA_Var {av & av_info_ptr = av_info_ptr}, th_attrs) + subst_attr TA_Unique th_attrs + = (TA_Unique, th_attrs) + subst_attr TA_Multi th_attrs + = (TA_Multi, th_attrs) + on_type type th + = (type, th) + + on_atype atype=:{at_attribute=TA_Var av} th + #! (fresh_av, th) = on_attr_var av th + = ({atype & at_attribute=TA_Var fresh_av}, th) + //---> ("on_atype av", av, fresh_av) + on_atype atype th + = (atype, th) + + fresh_ineq :: !AttrInequality !*TypeHeaps -> (!AttrInequality, !*TypeHeaps) + fresh_ineq ai=:{ai_demanded,ai_offered} th + #! (ai_demanded, th) = on_attr_var ai_demanded th + #! (ai_offered, th) = on_attr_var ai_offered th + = ({ai & ai_demanded = ai_demanded, ai_offered = ai_offered}, th) + + on_type_var tv=:{tv_info_ptr} th=:{th_vars} + #! (tv_info, th_vars) = readPtr tv_info_ptr th_vars + #! tv = case tv_info of + TVI_TypeVar new_ptr -> {tv & tv_info_ptr = new_ptr} + _ -> abort ("freshSymbolType, invalid tv_info\n" ---> tv_info) + = (tv, {th & th_vars = th_vars}) + + on_attr_var av=:{av_info_ptr} th=:{th_attrs} + #! (av_info, th_attrs) = readPtr av_info_ptr th_attrs + #! av = case av_info of + AVI_AttrVar new_ptr -> {av & av_info_ptr = new_ptr} + //---> ("fresh attr var", av.av_name, ptrToInt av_info_ptr, ptrToInt new_ptr) + _ -> abort ("freshSymbolType, invalid av_info\n" ---> av_info) + = ( av, {th & th_attrs = th_attrs}) + +assertSymbolType :: !SymbolType !*TypeHeaps -> !*TypeHeaps +assertSymbolType {st_args, st_result, st_context} th + = foldType on_type on_atype ((st_args, st_result), st_context) th +where + on_type :: !Type !*TypeHeaps -> !*TypeHeaps + on_type (TV tv) th=:{th_vars} + #! (tv_info, th_vars) = readPtr tv.tv_info_ptr th_vars + #! th = {th & th_vars = th_vars} + = case tv_info of + TVI_Empty -> th + _ -> (abort "TV tv_info not empty\n") --->(tv, tv_info) + on_type (CV tv :@: _) th=:{th_vars} + #! (tv_info, th_vars) = readPtr tv.tv_info_ptr th_vars + #! th = {th & th_vars = th_vars} + = case tv_info of + TVI_Empty -> th + _ -> (abort "CV tv_info not empty\n") --->(tv, tv_info) + on_type (TFA atvs type) th=:{th_attrs, th_vars} + #! th_attrs = foldSt on_av [av \\ {atv_attribute=TA_Var av} <- atvs] th_attrs + #! th_vars = foldSt on_tv [atv_variable\\{atv_variable} <- atvs] th_vars + = {th & th_attrs = th_attrs, th_vars = th_vars } + where + on_av av th_attrs + #! (av_info, th_attrs) = readPtr av.av_info_ptr th_attrs + = case av_info of + AVI_Empty -> th_attrs + _ -> (abort "TFA av_info not empty\n") --->(av, av_info) + on_tv tv th_vars + #! (tv_info, th_vars) = readPtr tv.tv_info_ptr th_vars + = case tv_info of + TVI_Empty -> th_vars + _ -> (abort "TFA tv_info not empty\n") --->(tv, tv_info) + on_type _ th = th + + on_atype :: !AType !*TypeHeaps -> !*TypeHeaps + on_atype {at_attribute=TA_Var av} th=:{th_attrs} + #! (av_info, th_attrs) = readPtr av.av_info_ptr th_attrs + #! th = {th & th_attrs = th_attrs} + = case av_info of + AVI_Empty -> th + _ -> (abort "av_info not empty\n") --->(av, av_info) + on_atype _ th = th + + +// build curried type out of SymbolType +buildCurriedType :: ![AType] !AType !TypeAttribute ![AttrInequality] ![AttributeVar] !String !Int !*AttrVarHeap + -> (!AType, ![AttrInequality], ![AttributeVar], !Int, !*AttrVarHeap) +buildCurriedType [] type cum_attr attr_env attr_vars attr_var_name attr_store th_attrs + = (type, attr_env, attr_vars, attr_store, th_attrs) +buildCurriedType [at=:{at_attribute}] type cum_attr attr_env attr_vars attr_var_name attr_store th_attrs + # atype = makeAType (at --> type) cum_attr + = (atype, attr_env, attr_vars, attr_store, th_attrs) +buildCurriedType [at=:{at_attribute}:ats] type cum_attr attr_env attr_vars attr_var_name attr_store th_attrs + # (next_cum_attr, new_attr_env, attr_vars, attr_store, th_attrs) = combine_attributes at_attribute cum_attr attr_env attr_vars attr_store th_attrs + (res_type, attr_env, attr_vars, attr_store, th_attrs) = buildCurriedType ats type next_cum_attr attr_env attr_vars attr_var_name attr_store th_attrs + # atype = makeAType (at --> res_type) cum_attr + = (atype, attr_env, attr_vars, attr_store, th_attrs) +where + combine_attributes TA_Unique cum_attr attr_env attr_vars attr_store th_attrs + = (TA_Unique, attr_env, attr_vars, attr_store, th_attrs) + combine_attributes (TA_Var attr_var) (TA_Var cum_attr_var) attr_env attr_vars attr_store th_attrs + #! (new_attr_var, th_attrs) + = freshAttrVar (makeIdent (attr_var_name +++ toString attr_store)) th_attrs + # attr_env = + [ { ai_demanded = cum_attr_var,ai_offered = new_attr_var } + , { ai_demanded = attr_var, ai_offered = new_attr_var } + : attr_env + ] + = ( TA_Var new_attr_var, attr_env, [new_attr_var:attr_vars], inc attr_store, th_attrs) + combine_attributes (TA_Var _) cum_attr attr_env attr_vars attr_store th_attrs + = (cum_attr, attr_env, attr_vars, attr_store, th_attrs) + combine_attributes _ (TA_Var cum_attr_var) attr_env attr_vars attr_store th_attrs + #! (new_attr_var, th_attrs) + = freshAttrVar (makeIdent (attr_var_name +++ toString attr_store)) th_attrs + # attr_env = [ { ai_demanded = cum_attr_var,ai_offered = new_attr_var }: attr_env] + = ( TA_Var new_attr_var, attr_env, [new_attr_var:attr_vars], inc attr_store, th_attrs) + combine_attributes _ cum_attr attr_env attr_vars attr_store th_attrs + = (cum_attr, attr_env, attr_vars, attr_store, th_attrs) + +// Build curried type out of symbol type. +// Starts with TA_Multi cumulative attribute. +// This is the weakest requirement, +// since we do not know how the generic argument will be used +// in the instance functions. It depends on the instance type. +curryGenericArgType :: !SymbolType !String !*TypeHeaps + -> (!SymbolType, !*TypeHeaps) +curryGenericArgType st=:{st_args, st_result, st_attr_env, st_attr_vars} attr_var_name th=:{th_attrs} + + #! (atype, attr_env, attr_vars, attr_store, th_attrs) + = buildCurriedType st_args st_result TA_Multi st_attr_env st_attr_vars attr_var_name 1 th_attrs + + # curried_st = + { st + & st_args = [] + , st_arity = 0 + , st_result = atype + , st_attr_env = attr_env + , st_attr_vars = attr_vars + } + = (curried_st, {th & th_attrs = th_attrs}) + //---> ("curryGenericArgType", st, curried_st) + + +curryGenericArgType1 :: !SymbolType !String !*TypeHeaps + -> (!SymbolType, !*TypeHeaps) +curryGenericArgType1 st=:{st_args, st_result, st_attr_env, st_attr_vars} attr_var_name th=:{th_attrs} + + # (atype, attr_vars, av_num, th_attrs) = curry st_args st_result 1 th_attrs + + # curried_st = + { st + & st_args = [] + , st_arity = 0 + , st_result = atype + , st_attr_vars = attr_vars + } + = (curried_st, {th & th_attrs = th_attrs}) + //---> ("curryGenericArgType", st, curried_st) +where + // outermost closure gets TA_Multi attribute + curry [] res av_num th_attrs + = (res, [], av_num, th_attrs) + curry [arg:args] res av_num th_attrs + #! (res, avs, av_num, th_attrs) = curry1 args res av_num th_attrs + #! atype = makeAType (arg --> res) TA_Multi + = (atype, avs, av_num, th_attrs) + + // inner closures get TA_Var attributes + curry1 [] res av_num th_attrs + = (res, [], av_num, th_attrs) + curry1 [arg:args] res av_num th_attrs + #! (res, avs, av_num, th_attrs) = curry1 args res av_num th_attrs + #! (av, th_attrs) = freshAttrVar (makeIdent (attr_var_name +++ toString av_num)) th_attrs + #! atype = makeAType (arg --> res) (TA_Var av) + = (atype, [av:avs], inc av_num, th_attrs) + +//---------------------------------------------------------------------------------------- +// write empty value in the variable heaps +//---------------------------------------------------------------------------------------- + +clearType t th + = foldType clear_type clear_atype t th +where + + clear_type (TV tv) th = clear_type_var tv th + clear_type (GTV tv) th = clear_type_var tv th + clear_type (CV tv :@: _) th = clear_type_var tv th + clear_type (TFA atvs type) th + #! th = foldSt clear_attr [atv_attribute \\ {atv_attribute} <- atvs] th + #! th = foldSt clear_type_var [atv_variable \\ {atv_variable} <- atvs] th + = th + + clear_type _ th = th + + clear_atype {at_attribute} th + = clear_attr at_attribute th + + clear_attr (TA_Var av) th = clear_attr_var av th + clear_attr (TA_RootVar av) th = clear_attr_var av th + clear_attr _ th = th + + clear_type_var {tv_info_ptr} th=:{th_vars} + = {th & th_vars = writePtr tv_info_ptr TVI_Empty th_vars} + clear_attr_var {av_info_ptr} th=:{th_attrs} + = {th & th_attrs = writePtr av_info_ptr AVI_Empty th_attrs} + +clearSymbolType st th + // clears not only st_vars and st_attrs, but also TFA variables + = clearType ((st.st_result, st.st_args), st.st_context) th + +//---------------------------------------------------------------------------------------- +// collect variables +//---------------------------------------------------------------------------------------- + +collectTypeVarsAndAttrVars :: + !type + !*TypeHeaps + -> (![TypeVar] + ,![AttributeVar] + ,!*TypeHeaps + ) + | foldType type +collectTypeVarsAndAttrVars type th + #! th = clearType type th + #! (tvs, avs, th) = foldType collect_type_var collect_attr type ([], [], th) + #! th = clearType type th + = (tvs, avs, th) +where + collect_type_var (TV tv) st = add_type_var tv st + collect_type_var (GTV tv) st = add_type_var tv st + collect_type_var (CV tv :@: _) st = add_type_var tv st + collect_type_var (TFA forall_atvs type) (tvs, avs, th_vars) + #! forall_tvs = [atv_variable\\{atv_variable}<-forall_atvs] + #! forall_avs = [av \\ {atv_attribute=TA_Var av}<-forall_atvs] + = (tvs -- forall_tvs, avs -- forall_avs, th_vars) + //---> ("collectTypeVarsAndAttrVars TFA", tvs, forall_tvs, tvs -- forall_tvs) + collect_type_var t st = st + + add_type_var tv (tvs, avs, th=:{th_vars}) + # (was_used, th_vars) = markTypeVarUsed tv th_vars + # th = {th & th_vars = th_vars} + | was_used + = (tvs, avs, th) + //---> ("collectTypeVarsAndAttrVars: TV was used", tv) + = ([tv:tvs], avs, th) + //---> ("collectTypeVarsAndAttrVars: TV was not used", tv) + + collect_attr {at_attribute} st = collect_attr_var at_attribute st + + collect_attr_var (TA_Var av) st = add_attr_var av st + collect_attr_var (TA_RootVar av) st = add_attr_var av st + collect_attr_var _ st = st + + add_attr_var av (atvs, avs, th=:{th_attrs}) + # (was_used, th_attrs) = markAttrVarUsed av th_attrs + # th = {th & th_attrs = th_attrs} + | was_used + = (atvs, avs, th) + = (atvs, [av:avs], th) + +collectTypeVars type th + # (tvs, _, th) = collectTypeVarsAndAttrVars type th + = (tvs, th) +collectAttrVars type th + # (_, avs, th) = collectTypeVarsAndAttrVars type th + = (avs, th) + +collectAttrsOfTypeVars :: ![TypeVar] type !*TypeHeaps -> (![ATypeVar], !*TypeHeaps) | foldType type +collectAttrsOfTypeVars tvs type th + #! (th=:{th_vars}) = clearType type th + //---> ("collectAttrsOfTypeVars called for", tvs) + + # th_vars = foldSt (\{tv_info_ptr} h->writePtr tv_info_ptr TVI_Used h) tvs th_vars + + #! (atvs, th_vars) = foldType on_type on_atype type ([], th_vars) + + # th_vars = foldSt (\{tv_info_ptr} h->writePtr tv_info_ptr TVI_Empty h) tvs th_vars + + #! th = clearType type {th & th_vars= th_vars} + = (atvs, th) + //---> ("collectAttrsOfTypeVars returns", atvs) +where + on_type type st = st + + on_atype {at_type=TV tv, at_attribute} st = on_type_var tv at_attribute st + on_atype {at_type=GTV tv, at_attribute} st = on_type_var tv at_attribute st + on_atype {at_type=(CV tv :@: _), at_attribute} st = on_type_var tv at_attribute st + //??? TFA -- seems that it is not needed + on_atype _ st = st + + on_type_var tv=:{tv_info_ptr} attr (atvs, th_vars) + #! (tvi, th_vars) = readPtr tv_info_ptr th_vars + = case tvi of + TVI_Used + # th_vars = writePtr tv_info_ptr TVI_Empty th_vars + -> ([makeATypeVar tv attr : atvs], th_vars) + TVI_Empty + -> (atvs, th_vars) + +collectAttrsOfTypeVarsInSymbolType tvs {st_args, st_result} th + = collectAttrsOfTypeVars tvs [st_result:st_args] th + +// marks empty type vars used, +// returns whether the type var was already used +markTypeVarUsed tv=:{tv_info_ptr} th_vars + # (tv_info, th_vars) = readPtr tv_info_ptr th_vars + = case tv_info of + TVI_Empty -> (False, writePtr tv_info_ptr TVI_Used th_vars) + TVI_Used -> (True, th_vars) + _ -> (abort "markTypeVarUsed: wrong tv_info ") ---> (tv, tv_info) + +// marks empty attr vars used +// returns whether the attr var was already used +markAttrVarUsed {av_info_ptr} th_attrs + # (av_info, th_attrs) = readPtr av_info_ptr th_attrs + = case av_info of + AVI_Empty -> (False, writePtr av_info_ptr AVI_Used th_attrs) + AVI_Used -> (True, th_attrs) + + +simplifyTypeApp :: !Type ![AType] -> !Type +simplifyTypeApp (TA type_cons=:{type_arity} cons_args) type_args + = TA { type_cons & type_arity = type_arity + length type_args } (cons_args ++ type_args) +simplifyTypeApp (TAS type_cons=:{type_arity} cons_args strictness) type_args + = TAS { type_cons & type_arity = type_arity + length type_args } (cons_args ++ type_args) strictness +simplifyTypeApp (CV tv :@: type_args1) type_args2 = CV tv :@: (type_args1 ++ type_args2) +simplifyTypeApp TArrow [type1, type2] = type1 --> type2 +simplifyTypeApp TArrow [type] = TArrow1 type +simplifyTypeApp (TArrow1 type1) [type2] = type1 --> type2 +simplifyTypeApp (TV tv) type_args = CV tv :@: type_args +simplifyTypeApp (TB _) type_args = TE +simplifyTypeApp (TArrow1 _) type_args = TE + +//---------------------------------------------------------------------------------------- +// substitutions +//---------------------------------------------------------------------------------------- + +// +// Uninitialized variables are not substituted, but left intact +// +// This behaviour is needed for kind indexing generic types, +// where generic variables are substituted and non-generic variables +// are not +// +applySubst :: !type !*TypeHeaps -> (!type, !*TypeHeaps) | mapTypeSt type +applySubst type th + = mapTypeAfterSt on_type on_atype type th +where + on_type type=:(TV {tv_info_ptr}) th=:{th_vars} + # (tv_info, th_vars) = readPtr tv_info_ptr th_vars + # th = {th & th_vars = th_vars} + = case tv_info of + TVI_Type t -> (t, th) + TVI_Empty -> (type, th) + on_type (GTV _) th + = abort "GTV" + on_type type=:(CV {tv_info_ptr} :@: args) th=:{th_vars} + # (tv_info, th_vars) = readPtr tv_info_ptr th_vars + # th = {th & th_vars = th_vars} + = case tv_info of + TVI_Type t -> (simplifyTypeApp t args, th) + TVI_Empty -> (type, th) + + //on_type type=:(TFA atvs t) th=:{th_vars} + // = abort "applySubst TFA" + + on_type type th + = (type, th) + + on_atype atype=:{at_attribute} th=:{th_attrs} + # (at_attribute, th_attrs) = subst_attr at_attribute th_attrs + = ({atype & at_attribute = at_attribute}, {th & th_attrs = th_attrs}) + + subst_attr attr=:(TA_Var {av_info_ptr}) th_attrs + # (av_info, th_attrs) = readPtr av_info_ptr th_attrs + = case av_info of + AVI_Attr a -> (a, th_attrs) + AVI_Empty -> (attr, th_attrs) + subst_attr TA_Multi th = (TA_Multi, th) + subst_attr TA_Unique th = (TA_Unique, th) + +applySubstInSymbolType st=:{st_args, st_result, st_attr_env, st_context} th + #! (new_st_args, th) = applySubst st.st_args th + #! (new_st_result, th) = applySubst st.st_result th + #! (new_st_context, th) = applySubst st.st_context th + #! (new_st_attr_env, th) = mapSt subst_ineq st.st_attr_env th + + #! th = clear_type_vars st.st_vars th + #! th = clear_attr_vars st.st_attr_vars th + + #! (new_st_vars, new_st_attr_vars, th) + = collectTypeVarsAndAttrVars ((new_st_args,new_st_result), new_st_context) th + + #! new_st = + { st + & st_args = new_st_args + , st_result = new_st_result + , st_context = new_st_context + , st_attr_env = new_st_attr_env + , st_vars = new_st_vars + , st_attr_vars = new_st_attr_vars + } + + #! th = clearSymbolType st th + + #! th = assertSymbolType new_st th + #! th = assertSymbolType st th + + = (new_st, th) + //---> ("applySubstInSymbolType", new_st) +where + subst_ineq ai=:{ai_demanded,ai_offered} th + # (ai_demanded, th) = subst_attr_var ai_demanded th + # (ai_offered, th) = subst_attr_var ai_offered th + = ({ai & ai_demanded = ai_demanded, ai_offered = ai_offered}, th) + subst_attr_var av=:{av_info_ptr} th=:{th_attrs} + # (av_info, th_attrs) = readPtr av_info_ptr th_attrs + # th = {th & th_attrs = th_attrs} + = case av_info of + AVI_Attr (TA_Var av1) -> (av1, th) + AVI_Attr _ -> (av, th) + AVI_Empty -> (av, th) + clear_type_vars tvs th=:{th_vars} + #! th_vars = foldSt (\{tv_info_ptr} h->writePtr tv_info_ptr TVI_Empty h) tvs th_vars + = {th & th_vars = th_vars} + clear_attr_vars avs th=:{th_attrs} + #! th_attrs = foldSt (\{av_info_ptr} h->writePtr av_info_ptr AVI_Empty h) avs th_attrs + = {th & th_attrs = th_attrs} + +//**************************************************************************************** +// Function Helpers +//**************************************************************************************** + +makeFunction :: !Ident !Index !Index ![FreeVar] !Expression !(Optional SymbolType) !Index !Position + -> FunDef +makeFunction ident fun_index group_index arg_vars body_expr opt_sym_type main_dcl_module_n fun_pos + + #! (arg_vars, local_vars, free_vars) = collectVars body_expr arg_vars + | not (isEmpty free_vars) + = abort "makeFunction: free_vars is not empty\n" + + = { fun_symb = ident + , fun_arity = length arg_vars + , fun_priority = NoPrio + , fun_body = TransformedBody {tb_args = arg_vars, tb_rhs = body_expr } + , fun_type = opt_sym_type + , fun_pos = fun_pos + , fun_kind = FK_Function cNameNotLocationDependent + , fun_lifted = 0 + , fun_info = + { fi_calls = collectCalls main_dcl_module_n body_expr + , fi_group_index = group_index + , fi_def_level = NotALevel + , fi_free_vars = [] + , fi_local_vars = local_vars + , fi_dynamics = [] + , fi_properties = 0 + } + } + //---> ("makeFunction", ident, fun_index) + +// build function and +buildFunAndGroup :: + !Ident ![FreeVar] !Expression !(Optional SymbolType) !Index !Position + !FunsAndGroups + -> + (!DefinedSymbol, FunsAndGroups) +buildFunAndGroup + ident arg_vars body_expr opt_sym_type main_dcl_module_n fun_pos + (fun_index, group_index, funs, groups) + # fun = makeFunction ident fun_index group_index arg_vars body_expr opt_sym_type main_dcl_module_n fun_pos + # group = {group_members = [fun_index]} + # def_sym = {ds_ident=ident, ds_arity=fun.fun_arity, ds_index=fun_index} + = (def_sym, (inc fun_index, inc group_index, [fun:funs], [group:groups])) + +buildUndefFunAndGroup ident st main_dcl_module_n fun_pos fun_info predefs heaps + #! arg_var_names = [ "x" +++ toString i \\ i <- [1 .. st.st_arity]] + #! (arg_vars,heaps) = mapSt build_free_var arg_var_names heaps + #! (expr, heaps) = buildPredefFunApp PD_undef [] predefs heaps + = buildFunAndGroup ident arg_vars expr (Yes st) main_dcl_module_n fun_pos fun_info +where + build_free_var :: !String !*Heaps -> (!FreeVar, !*Heaps) + build_free_var name heaps=:{hp_var_heap} + # (var_info_ptr, hp_var_heap) = newPtr VI_Empty hp_var_heap + # var_name = { id_name = name, id_info = nilPtr } + # free_var = { fv_def_level = NotALevel, fv_count = 0, fv_info_ptr = var_info_ptr, fv_name = var_name} + = (free_var, {heaps & hp_var_heap = hp_var_heap}) + +/* +buildIdFunction :: + !DefinedSymbol // the desired function name and index + Int // group index + !Index // current module number + !*Heaps // heaps + -> ( !FunDef // created function definition + , !*Heaps // heaps + ) +buildIdFunction def_sym group_index gs_main_dcl_module_n heaps + # (arg_expr, arg_var, heaps) = buildVarExpr "x" heaps + # fun_def = makeFunction def_sym group_index [arg_var] arg_expr No [] gs_main_dcl_module_n NoPos + = (fun_def, heaps) +*/ + +/* +buildUndefFunction :: + !DefinedSymbol // the desired function name and index + !Int // group index + !PredefinedSymbols // predefined symbols + !Index // current module number + !*Heaps // heaps + -> ( !FunDef // created function definition + , !*Heaps // heaps + ) +buildUndefFunction def_sym group_index predefs gs_main_dcl_module_n heaps + # names = [ "x" +++ toString i \\ i <- [1 .. def_sym.ds_arity]] + # (arg_vars, heaps) = mapSt build_free_var names heaps + # (body_expr, heaps) = buildUndefFunApp [] predefs heaps + //# (body_expr, heaps) = buildUNIT predefs heaps + # fun_def = makeFunction def_sym group_index arg_vars body_expr No [] gs_main_dcl_module_n NoPos + = (fun_def, heaps) +where + build_free_var :: !String !*Heaps -> (!FreeVar, !*Heaps) + build_free_var name heaps=:{hp_var_heap} + # (var_info_ptr, hp_var_heap) = newPtr VI_Empty hp_var_heap + # var_name = { id_name = name, id_info = nilPtr } + # free_var = { fv_def_level = NotALevel, fv_count = 0, fv_info_ptr = var_info_ptr, fv_name = var_name} + = (free_var, {heaps & hp_var_heap = hp_var_heap}) +*/ + +//**************************************************************************************** +// Expr Helpers +//**************************************************************************************** + +//======================================================================================== +// Primitive expressions +//======================================================================================== + +makeIntExpr :: Int -> Expression +makeIntExpr value = BasicExpr (BVI (toString value)) + +makeStringExpr :: String !PredefinedSymbols -> Expression +makeStringExpr str predefs + #! {pds_module, pds_def} = predefs.[PD_StringType] + #! pds_ident = predefined_idents.[PD_StringType] + #! type_symb = MakeTypeSymbIdent { glob_module = pds_module, glob_object = pds_def } pds_ident 0 + = BasicExpr (BVS str) + +/* +makeListExpr :: [Expression] !PredefinedSymbols !*Heaps -> (Expression, !*Heaps) +makeListExpr [] predefs heaps + = buildPredefConsApp PD_NilSymbol [] predefs heaps +makeListExpr [expr:exprs] predefs heaps + # (list_expr, heaps) = makeListExpr exprs predefs heaps + = buildPredefConsApp PD_ConsSymbol [expr, list_expr] predefs heaps +*/ + +buildConsApp :: !Index DefinedSymbol ![Expression] !*Heaps + -> (!Expression, !*Heaps) +buildConsApp cons_mod {ds_ident, ds_index, ds_arity} arg_exprs heaps=:{hp_expression_heap} + # (expr_info_ptr, hp_expression_heap) = newPtr EI_Empty hp_expression_heap + # cons_glob = {glob_module = cons_mod, glob_object = ds_index} + # expr = App { + app_symb = { + symb_name = ds_ident, + symb_kind = SK_Constructor cons_glob + }, + app_args = arg_exprs, + app_info_ptr = expr_info_ptr} + # heaps = { heaps & hp_expression_heap = hp_expression_heap } + = (expr, heaps) + +buildFunApp :: !Index !DefinedSymbol ![Expression] !*Heaps + -> (!Expression, !*Heaps) +buildFunApp fun_mod {ds_ident, ds_index} arg_exprs heaps=:{hp_expression_heap} + # (expr_info_ptr, hp_expression_heap) = newPtr EI_Empty hp_expression_heap + # fun_glob = {glob_module = fun_mod, glob_object = ds_index} + # expr = App { + app_symb = { + symb_name = ds_ident, + symb_kind = SK_Function fun_glob + }, + app_args = arg_exprs, + app_info_ptr = expr_info_ptr} + # heaps = { heaps & hp_expression_heap = hp_expression_heap } + = (expr, heaps) + +buildPredefFunApp :: !Int [Expression] !PredefinedSymbols !*Heaps + -> (!Expression, !*Heaps) +buildPredefFunApp predef_index args predefs heaps + # {pds_module, pds_def} = predefs.[predef_index] + # fun_ds = + { ds_index = pds_def + , ds_ident = predefined_idents.[predef_index] + , ds_arity = 0 // not used + } + = buildFunApp pds_module fun_ds args heaps + +buildGenericApp :: !Index !Index !Ident !TypeKind ![Expression] !*Heaps + -> (!Expression, !*Heaps) +buildGenericApp gen_module gen_index gen_name kind arg_exprs heaps=:{hp_expression_heap} + # (expr_info_ptr, hp_expression_heap) = newPtr EI_Empty hp_expression_heap + # glob_index = {glob_module = gen_module, glob_object = gen_index} + # expr = App { + app_symb = { + symb_name = gen_name, + symb_kind = SK_Generic glob_index kind + }, + app_args = arg_exprs, + app_info_ptr = expr_info_ptr} + # heaps = { heaps & hp_expression_heap = hp_expression_heap } + = (expr, heaps) + +buildPredefConsApp :: !Int [Expression] !PredefinedSymbols !*Heaps + -> (!Expression, !*Heaps) +buildPredefConsApp predef_index args predefs heaps=:{hp_expression_heap} + # {pds_module, pds_def} = predefs.[predef_index] + # pds_ident = predefined_idents.[predef_index] + # global_index = {glob_module = pds_module, glob_object = pds_def} + # symb_ident = + { symb_name = pds_ident + , symb_kind = SK_Constructor global_index + } + # (expr_info_ptr, hp_expression_heap) = newPtr EI_Empty hp_expression_heap + # app = App {app_symb = symb_ident, app_args = args, app_info_ptr = expr_info_ptr} + = (app, {heaps & hp_expression_heap = hp_expression_heap}) + +buildPredefConsPattern :: !Int ![FreeVar] !Expression !PredefinedSymbols + -> AlgebraicPattern +buildPredefConsPattern predef_index vars expr predefs + # {pds_module, pds_def} = predefs.[predef_index] + # pds_ident = predefined_idents.[predef_index] + # cons_def_symbol = { + ds_ident = pds_ident, + ds_arity = length vars, + ds_index = pds_def + } + # pattern = { + ap_symbol = {glob_module = pds_module, glob_object = cons_def_symbol}, + ap_vars = vars, + ap_expr = expr, + ap_position = NoPos + } + = pattern + +buildCaseExpr :: Expression CasePatterns !*Heaps + -> (!Expression, !*Heaps) +buildCaseExpr case_arg case_alts heaps=:{hp_expression_heap} + # (expr_info_ptr, hp_expression_heap) = newPtr EI_Empty hp_expression_heap + # expr = Case + { case_expr = case_arg + , case_guards = case_alts + , case_default = No + , case_ident = No + , case_info_ptr = expr_info_ptr + , case_explicit = False + , case_default_pos = NoPos + } + # heaps = { heaps & hp_expression_heap = hp_expression_heap} + = (expr, heaps) + +buildRecordSelectionExpr :: !Expression !Index !PredefinedSymbols -> Expression +buildRecordSelectionExpr record_expr predef_field predefs + # {pds_module, pds_def} = predefs . [predef_field] + # pds_ident = predefined_idents . [predef_field] + # selector = { + glob_module = pds_module, + glob_object = {ds_ident = pds_ident, ds_index = pds_def, ds_arity = 1}} + = Selection NormalSelector record_expr [RecordSelection selector 1] + +//============================================================================= +// variables +//============================================================================= + +// build a new variable and an expression associated with it +buildVarExpr :: + !String // variable name + !*Heaps + -> (!Expression // variable expression + , !FreeVar // variable + , !*Heaps + ) +buildVarExpr name heaps=:{hp_var_heap, hp_expression_heap} + # (expr_info_ptr, hp_expression_heap) = newPtr EI_Empty hp_expression_heap + # (var_info_ptr, hp_var_heap) = newPtr VI_Empty hp_var_heap + # var_name = makeIdent name + # var = Var {var_name = var_name, var_expr_ptr = expr_info_ptr, var_info_ptr = var_info_ptr } + # hp_var_heap = writePtr var_info_ptr (VI_Expression var) hp_var_heap + # heaps = { heaps & hp_var_heap = hp_var_heap, hp_expression_heap = hp_expression_heap } + # fv = {fv_count = 1/* if 0, trans crashes*/, fv_name = var_name, fv_info_ptr = var_info_ptr, fv_def_level = NotALevel} + = (var, fv, heaps) + +buildVarExprs [] heaps = ([], [], heaps) +buildVarExprs [x:xs] heaps + # (y, z, heaps) = buildVarExpr x heaps + # (ys, zs, heaps) = buildVarExprs xs heaps + = ([y:ys], [z:zs], heaps) + +//============================================================================= +// recursion over expressions +//============================================================================= + +//----------------------------------------------------------------------------- +// fold expression applies a function to each node of an expression +// recursively: +// first apply the function, then recurse +//----------------------------------------------------------------------------- +foldExpr :: + (Expression -> .st -> .st) // function to apply at each node + Expression // expression to run throuh + .st // state + -> + .st // updated state +foldExpr f expr=:(App {app_args}) st + # st = f expr st + = foldSt (foldExpr f) app_args st +foldExpr f expr1=:(expr@exprs) st + # st = f expr st + = foldSt (foldExpr f) [expr:exprs] st +foldExpr f expr=:(Let {let_lazy_binds, let_strict_binds, let_expr}) st + # st = f expr st + # st = foldSt (fold_let_binds f) let_strict_binds st + # st = foldSt (fold_let_binds f) let_lazy_binds st + = foldExpr f let_expr st +where + fold_let_binds f {lb_src} st = foldExpr f lb_src st +foldExpr f expr=:(Case {case_expr,case_guards,case_default}) st + # st = f expr st + # st = foldExpr f case_expr st + # st = fold_guards f case_guards st + # st = foldOptional (foldExpr f) case_default st + = st +where + fold_guards f (AlgebraicPatterns gi aps) st = foldSt (foldExpr f) [ap_expr\\{ap_expr}<-aps] st + fold_guards f (BasicPatterns gi bps) st = foldSt (foldExpr f) [bp_expr\\{bp_expr}<-bps] st + fold_guards f (DynamicPatterns dps) st = foldSt (foldExpr f) [dp_rhs\\{dp_rhs}<-dps] st + fold_guards f NoPattern st = st +foldExpr f expr=:(Update expr1 sels expr2) st + # st = f expr st + # st = foldExpr f expr1 st + # st = foldSt (fold_sel f) sels st + # st = foldExpr f expr2 st + = st +where + fold_sel f (RecordSelection _ _) st = st + fold_sel f (ArraySelection _ _ expr) st = foldExpr f expr st + fold_sel f (DictionarySelection _ _ _ expr) st = foldExpr f expr st +foldExpr f expr=:(RecordUpdate _ expr1 binds) st + # st = f expr st + # st = foldExpr f expr1 st + # st = foldSt (foldExpr f) [bind_src\\{bind_src}<-binds] st + = st +foldExpr f expr=:(TupleSelect _ _ expr1) st + # st = f expr st + = foldExpr f expr1 st +foldExpr f expr=:(Conditional {if_cond,if_then,if_else}) st + # st = f expr st + # st = foldExpr f if_cond st + # st = foldExpr f if_then st + # st = foldOptional (foldExpr f) if_else st + = st +foldExpr f expr=:(MatchExpr _ expr1) st + # st = f expr st + = foldExpr f expr1 st +foldExpr f expr=:(DynamicExpr {dyn_expr}) st + # st = f expr st + = foldExpr f dyn_expr st +foldExpr f expr st + = f expr st + +//----------------------------------------------------------------------------- +// map expression applies a function to each node of an expression +// recursively: +// first recurse, then apply the function +//----------------------------------------------------------------------------- +mapExprSt :: + !(Expression -> w:st -> u:(Expression, w:st)) + !Expression + w:st + -> + v: ( Expression + , w:st + ) + , [v<=w,u<=v] +mapExprSt f (App app=:{app_args}) st + # (app_args, st) = mapSt (mapExprSt f) app_args st + = f (App { app & app_args = app_args }) st + +mapExprSt f (Let lad=:{let_lazy_binds, let_strict_binds, let_expr}) st + # (let_lazy_binds, st) = mapSt map_bind let_lazy_binds st + # (let_strict_binds, st) = mapSt map_bind let_strict_binds st + # (let_expr, st) = mapExprSt f let_expr st + # lad = + { lad + & let_expr = let_expr + , let_lazy_binds = let_lazy_binds + , let_strict_binds = let_strict_binds + } + = f (Let lad) st +where + map_bind b=:{lb_src} st + # (lb_src, st) = mapExprSt f lb_src st + = ({b & lb_src = lb_src}, st) + +mapExprSt f (Selection a expr b) st + # (expr, st) = mapExprSt f expr st + = f (Selection a expr b) st + +mapExprSt f (Update e1 x e2) st + # (e1, st) = mapExprSt f e1 st + # (e2, st) = mapExprSt f e2 st + = f (Update e1 x e2) st + +mapExprSt f (RecordUpdate x expr binds) st + # (expr, st) = mapExprSt f expr st + # (binds, st) = mapSt map_bind binds st + = f (RecordUpdate x expr binds) st +where + map_bind b=:{bind_src} st + # (bind_dst, st) = mapExprSt f bind_src st + = ({b & bind_src = bind_src}, st) + +mapExprSt f (TupleSelect x y expr) st + # (expr, st) = mapExprSt f expr st + = f (TupleSelect x y expr) st + +mapExprSt f (Conditional cond=:{if_cond, if_then, if_else}) st + # (if_cond, st) = mapExprSt f if_cond st + # (if_then, st) = mapExprSt f if_then st + # (if_else, st) = mapOptionalSt (mapExprSt f) if_else st +/* + # (if_else, st) = case if_else of + (Yes x) + # (x, st) = mapExprSt f x st + -> (Yes x, st) + No -> (No, st) +*/ + = f (Conditional {cond & if_cond = if_cond, if_then = if_then, if_else = if_else}) st + +mapExprSt f (MatchExpr y expr) st + # (expr, st) = mapExprSt f expr st + = f (MatchExpr y expr) st + +mapExprSt f (DynamicExpr dyn=:{dyn_expr}) st + # (dyn_expr, st) = mapExprSt f dyn_expr st + = f (DynamicExpr {dyn& dyn_expr = dyn_expr}) st + +mapExprSt f (Case c=:{case_expr, case_guards, case_default=case_default}) st + # (case_expr, st) = mapExprSt f case_expr st + # (case_guards, st) = map_patterns case_guards st + # (case_default, st) = case case_default of + (Yes x) + # (x, st) = mapExprSt f x st + -> (Yes x, st) + No -> (No, st) + # new_case = {c & case_expr=case_expr, case_guards=case_guards, case_default=case_default} + = f (Case new_case) st +where + map_patterns (AlgebraicPatterns index pats) st + # (pats, st) = mapSt map_alg_pattern pats st + = (AlgebraicPatterns index pats, st) + map_patterns (BasicPatterns bt pats) st + # (pats, st) = mapSt map_basic_pattern pats st + = (BasicPatterns bt pats, st) + map_patterns (DynamicPatterns pats) st + # (pats, st) = mapSt map_dyn_pattern pats st + = (DynamicPatterns pats, st) + + map_alg_pattern pat=:{ap_expr} st + # (ap_expr, st) = mapExprSt f ap_expr st + = ({pat & ap_expr = ap_expr}, st) + map_basic_pattern pat=:{bp_expr} st + # (bp_expr, st) = mapExprSt f bp_expr st + = ({pat & bp_expr = bp_expr}, st) + map_dyn_pattern pat=:{dp_rhs} st + # (dp_rhs, st) = mapExprSt f dp_rhs st + = ({pat & dp_rhs = dp_rhs}, st) + +mapExprSt f expr st = f expr st + +// needed for collectCalls +instance == FunCall where (==) (FunCall x _) (FunCall y _) = x == y + +// collect function calls made in the expression +collectCalls :: !Index !Expression -> [FunCall] +collectCalls current_module expr = removeDup (foldExpr get_call expr []) +where + get_call (App {app_symb={symb_kind=SK_Function {glob_module,glob_object}}}) indexes + | glob_module == current_module + = [FunCall glob_object NotALevel : indexes] + = indexes + get_call _ indexes = indexes + +// collects variables and computes the refernce counts +collectVars :: + !Expression // expression to collect variables in + ![FreeVar] // function argument variables + -> ( ![FreeVar] // argument variables (with updated ref count) + , ![FreeVar] // local variables + , ![FreeVar] // free_variables + ) +collectVars expr arg_vars + # arg_vars = [ {v & fv_count = 0} \\ v <- arg_vars] + = foldExpr collect_vars expr (arg_vars, [], []) +where + collect_vars (Var {var_name, var_info_ptr}) (arg_vars, local_vars, free_vars) + # var = {fv_name = var_name, fv_count = 1, fv_info_ptr = var_info_ptr, fv_def_level = NotALevel} + # (added, arg_vars) = add_var var arg_vars + | added + = (arg_vars, local_vars, free_vars) + # (added, local_vars) = add_var var local_vars + | added + = (arg_vars, local_vars, free_vars) + # (added, free_vars) = add_var var free_vars + | added + = (arg_vars, local_vars, free_vars) + = (arg_vars, local_vars, [var:free_vars]) + where + add_var var [] = (False, []) + add_var var [v=:{fv_count,fv_info_ptr}:vs] + | var.fv_info_ptr == fv_info_ptr + = (True, [{v&fv_count = inc fv_count}:vs]) + # (added, vs) = add_var var vs + = (added, [v:vs]) + collect_vars (Let {let_lazy_binds, let_strict_binds}) (arg_vars, local_vars, free_vars) + # vars = [{lb_dst&fv_count=0} \\ {lb_dst} <- (let_lazy_binds ++ let_strict_binds)] + # (local_vars, free_vars) = foldSt add_local_var vars (local_vars, free_vars) + = (arg_vars, local_vars, free_vars) + collect_vars (Case {case_guards}) (arg_vars, local_vars, free_vars) + # vars = [{v&fv_count=0} \\ v <- collect case_guards] + # (local_vars, free_vars) = foldSt add_local_var vars (local_vars, free_vars) + = (arg_vars, local_vars, free_vars) + where + collect (AlgebraicPatterns _ aps) = flatten [ap_vars\\{ap_vars}<-aps] + collect (BasicPatterns _ bps) = [] + collect (DynamicPatterns dps) = [dp_var \\ {dp_var}<-dps] + collect NoPattern = [] + collect_vars expr st = st + + add_local_var var (local_vars, []) = ([var:local_vars], []) + add_local_var var (local_vars, free_vars=:[fv:fvs]) + | var.fv_info_ptr == fv.fv_info_ptr + = ([fv:local_vars], fvs) + # (local_vars, fvs1) = add_local_var var (local_vars, fvs) + = (local_vars, [fv:fvs1]) + +//**************************************************************************************** +// Array helpers +//**************************************************************************************** + +//updateArray :: (Int a -> a) *{a} -> *{a} +updateArray f xs + = map_array 0 xs +where + map_array n xs + #! (s, xs) = usize xs + | n == s + = xs + # (x, xs) = xs ! [n] + = map_array (inc n) {xs & [n] = f n x} + +//updateArray1 :: (Int .a -> .a) *{.a} .a -> *{.a} +updateArray1 f xs dummy + # (xs, _) = map_array 0 xs dummy + = xs +where + map_array n xs d + #! (s, xs) = usize xs + | n == s + = (xs, d) + # (x, xs) = replace xs n d + # x = f n x + # (d, xs) = replace xs n x + = map_array (inc n) xs d + +update2dArray f xss + = updateArray1 (\n xs -> updateArray (f n) xs) xss {} + + +//updateArraySt :: (Int a .st -> (a, .st)) *{a} .st -> (*{a}, .st) +updateArraySt f xs st + = map_array 0 xs st +where + map_array n xs st + #! (s, xs) = usize xs + | n == s + = (xs, st) + # (x, xs) = xs![n] + # (x, st) = f n x st + = map_array (inc n) {xs&[n]=x} st + + +//updateArraySt :: (Int .a .st -> (.a, .st)) *{a} .a .st -> (*{a}, .st) +updateArray1St f xs dummy st + # (xs, _, st) = map_array 0 xs dummy st + = (xs, st) +where + map_array n xs d st + #! (s, xs) = usize xs + | n == s + = (xs, d, st) + # (x, xs) = replace xs n d + # (x, st) = f n x st + # (d, xs) = replace xs n x + = map_array (inc n) xs d st + +update2dArraySt f xss st + = updateArray1St (\n xs st -> updateArraySt (f n) xs st) xss {} st + +//foldArraySt :: (Int a .st -> .st) {a} .st -> .st +foldArraySt f xs st + = fold_array 0 xs st +where + fold_array n xs st + #! (s, xs) = usize xs + | n == s + = st + # st = f n xs.[n] st + = fold_array (inc n) xs st + +//foldUArraySt :: (Int a .st -> .st) u:{a} .st -> (u:{a}, .st) +foldUArraySt f array st + = map_array 0 array st +where + map_array n array st + # (s, array) = usize array + | n == s + = (array, st) + # (x, array) = array ! [n] + # st = f x st + = map_array (inc n) array st + +//**************************************************************************************** +// General Helpers +//**************************************************************************************** + +idSt x st = (x, st) + +(--) infixl 5 :: u:[a] .[a] -> u:[a] | Eq a +(--) x y = removeMembers x y + +// should actually be in the standard library +transpose [] = [] +transpose [[] : xss] = transpose xss +transpose [[x:xs] : xss] = + [[x : [hd l \\ l <- xss]] : transpose [xs : [ tl l \\ l <- xss]]] + +unzip3 [] = ([], [], []) +unzip3 [(x1,x2,x3):xs] + # (x1s, x2s, x3s) = unzip3 xs + = ([x1:x1s], [x2:x2s], [x3:x3s]) + +foldOptional f No st = st +foldOptional f (Yes x) st = f x st + +mapOptional f No = No +mapOptional f (Yes x) = Yes (f x) + +mapOptionalSt f No st = (No, st) +mapOptionalSt f (Yes x) st + # (y, st) = f x st + = (Yes y, st) + +mapSt2 f [] st1 st2 = ([], st1, st2) +mapSt2 f [x:xs] st1 st2 + # (y, st1, st2) = f x st1 st2 + # (ys, st1, st2) = mapSt2 f xs st1 st2 + = ([y:ys], st1, st2) + +zipWith f [] [] = [] +zipWith f [x:xs] [y:ys] = [f x y : zipWith f xs ys] + +zipWithSt f [] [] st + = ([], st) +zipWithSt f [x:xs] [y:ys] st + # (z, st) = f x y st + # (zs, st) = zipWithSt f xs ys st + = ([z:zs], st) + +unfoldnSt :: (.st -> (a, .st)) !Int .st -> ([a], .st) +unfoldnSt f 0 st = ([], st) +unfoldnSt f n st + #! (x, st) = f st + #! (xs, st) = unfoldnSt f (dec n) st + = ([x:xs], st) |