implementation module Request; ALLOW_LAZY_LIBRARY_REFERENCES yes no :== yes; // for apply USE_OLD_NAMESTABLE_STORAGE yes no :== no; from predef import UnderscoreSystemDynamicModule_String, T_ypeObjectTypeRepresentation_String; import StdEnv; //import StdDynamicError; import DLState; import CommonObjectToDisk; // mac import ReadState; import RWSDebugChoice; import type_io_read; import lib; import Directory; import shared_buffer; import ObjectToMem; import pdObjectToMem; import DynamicLink; from DLState import findLabel; import selectively_import_and_mark_labels; //2.0 from DynamicLinkerInterface import ::TypeReference(..), ::LazyDynamicReference(..), ::LibraryID(..), ::RunTimeIDW(..) , instance EnDecode RunTimeIDW, instance EnDecode LazyDynamicReference, instance EnDecode TypeReference , instance DefaultElem RunTimeIDW, instance DefaultElem LazyDynamicReference, instance DefaultElem TypeReference; //0.2 import EnDecode; // utilities import ExtInt; import ExtFile; from type_io_common import get_type_name_and_module_name_from_type_string, isPredefinedModuleName, LowLevelInterfaceModule; // utilities; power mac interface //from files import LaunchApplication; //, FSMakeFSSpec; //import ioState; //import files; //1.3 from deltaIOState import FileEnv; from ReadObject import ImportDynamicLibrarySymbols; //3.1 /*2.0 from ReadObject import class ImportDynamicLibrarySymbols(..), instance ImportDynamicLibrarySymbols LibraryList; from deltaIOState import class FileEnv, instance FileEnv (IOState s); // instance GetTypeTableIndex LibraryID 0.2*/ import deltaEventIO; import Redirections; from utilities import foldSt; import StdMaybe; import MemoryState; from type_io_common import PredefinedModuleName; import utilities; import CollectTypes; from predef import UnderscoreSystemDynamicModule_String, DynamicRepresentation_String; import predefined_types; from type_io_common import UnderscoreSystemModule; from ExtList import anySt, allSt; instance FileSystem (IOState s) where { fopen a0 a1 io #! ((r0,r1),io) = accFiles fopen2 io; = (r0,r1,io); where { fopen2 files # (r0,r1,files) = fopen a0 a1 files; = ((r0,r1),files); } // fopen fclose file io = accFiles (fclose file) io; stdio io = accFiles stdio io; sfopen a0 a1 io #! ((r0,r1),io) = accFiles fopen2 io; = (r0,r1,io); where { fopen2 files # (r0,r1,files) = sfopen a0 a1 files; = ((r0,r1),files); } // sfopen }; // IO 0.8.1 import deltaTimer; from deltaDialog import OpenNotice; import pdRequest; import DebugUtilities; import ProcessSerialNumber; import pdState; import dynamics; import DynamicID; // platform independent Quit :: !ProcessSerialNumber [String] !*DLServerState !(IOState !*DLServerState) -> !(!Bool,!ProcessSerialNumber,!*DLServerState, !(IOState !*DLServerState)); Quit client_id _ s io #! dl_client_state = { DefaultDLClientState & id = client_id , app_linker_state = EmptyState }; = (True,client_id,AddToDLServerState dl_client_state s,io); produce_verbose_output [] [] labels = labels; produce_verbose_output [ModuleUnknown module_name label_name:unknown_modules] [label_address:label_addresses] labels #! label = Verbose ("label " +++ label_name +++ " at " +++ (hex_int label_address)); = produce_verbose_output unknown_modules label_addresses [label:labels]; produce_verbose_output [SymbolUnknown module_name label_name:unknown_modules] [label_address:label_addresses] labels #! label = Verbose ("label " +++ label_name +++ " at " +++ (hex_int label_address)); = produce_verbose_output unknown_modules label_addresses [label:labels]; produce_verbose_output _ [] _ = abort "!produce_verbose_output; no addresses"; produce_verbose_output2 messages {dusl_label_name,dusl_library_instance_i,dusl_linked,dusl_label_kind} address #! linked = if dusl_linked "linked " ""; #! label_kind = case dusl_label_kind of { DSL_RUNTIME_SYSTEM_LABEL -> "RTS"; DSL_TYPE_EQUIVALENT_CLASS_WITH_IMPLEMENTATION -> "LINKED TYPE"; DSL_TYPE_EQUIVALENT_CLASS_IMPLEMENTATION -> "UNLINKED TYPE"; DSL_CLEAN_LABEL_BUT_NOT_A_TYPE -> "NON CLEAN TYPE"; DSL_EMPTY -> "EMPTY"; }; #! label = Verbose (linked +++ "label " +++ dusl_label_name +++ "<" +++ toString dusl_library_instance_i +++ "," +++ label_kind +++ "> at " +++ (hex_int address)); = [label:messages]; AddAndInit :: !ProcessSerialNumber [String] !*DLServerState !(IOState !*DLServerState) -> !(!Bool,!ProcessSerialNumber,!*DLServerState, !(IOState !*DLServerState)); AddAndInit client_id [eagerly_linked_client_name,do_add_project] s=:{/*targets,*/application_path} io // fill application linker state by reading the complement #! state = AddMessage (Verbose "AddAndInit") EmptyState; #! (name_without_extension,_) = ExtractPathFileAndExtension eagerly_linked_client_name; #! (state,io) = case do_add_project == "T" of { True -> (state,io); _ -> accFiles (ReadState eagerly_linked_client_name state) io; }; #! (ok,state) = IsErrorOccured state; | not ok #! dl_client_state = { DefaultDLClientState & id = client_id , app_linker_state = state }; #! s = AddToDLServerState dl_client_state s; #! (s,io) = openClientWindow eagerly_linked_client_name client_id s io; = (True,client_id,s,io); // windows specific #! state = sel_platform (RemoveStaticClientLibrary state) state; #! (dl_client_state,s,io) = InitDLClientState DefaultDLClientState client_id name_without_extension False state s io; #! (ok,dl_client_state) = IsErrorOccured dl_client_state; // openClientWindow #! s = AddToDLServerState dl_client_state s; #! (s,io) = openClientWindow eagerly_linked_client_name client_id s io; = (not ok,client_id,s,io); Close :: !ProcessSerialNumber [String] !*DLServerState !(IOState !*DLServerState) -> !(!Bool,!ProcessSerialNumber,!*DLServerState, !(IOState !*DLServerState)); Close client_id _ s=:{application_path} io #! (client_exists,dl_client_state=:{client_window},s) = RemoveFromDLServerState client_id s; | not client_exists = internal_error "Close (internal error): client not registered" client_id dl_client_state s io; // platform dependent #! (dl_client_state,io) = CloseClient dl_client_state io; = (True,client_id,AddToDLServerState dl_client_state s,io); show_msg l s io #! io = DisableTimer timer_id io; #! (i,s,io) = OpenNotice (Notice l (NoticeButton 0 "Ok") []) s io; #! io = EnableTimer timer_id io; = (s, io); internal_error :: !{#Char} !ProcessSerialNumber !*DLClientState !*DLServerState .a -> *(!Bool,!ProcessSerialNumber,!DLServerState,.a); internal_error message client_id dl_client_state=:{app_linker_state=state} s io #! dl_client_state = { dl_client_state & id = client_id , app_linker_state = AddMessage (LinkerError message) state }; = (True,client_id,AddToDLServerState dl_client_state s,io); InitDLClientState dl_client_state client_id name_without_extension project_required state s=:{application_path/*,targets*/} io #! dl_client_state = { dl_client_state & id = client_id}; = (dl_client_state,s,io); // lookup addresses of some already linked in labels GetLabelAddresses :: !ProcessSerialNumber [String] !*DLServerState !(IOState !*DLServerState) -> !(!Bool,!ProcessSerialNumber,!*DLServerState, !(IOState !*DLServerState)); GetLabelAddresses client_id [label_names_encoded_in_msg] s io #! (client_exists,dl_client_state,s) = RemoveFromDLServerState client_id s; | F "GetLabelAddresses" not client_exists = internal_error "GetLabelAddresses (internal error): client not registered" client_id dl_client_state s io; #! (dl_client_state) = AddMessage (Verbose "GetLabelAddresses") dl_client_state; #! symbols = ExtractArguments '\n' 0 label_names_encoded_in_msg []; #! (Just main_library_instance_i,dl_client_state) = dl_client_state!cs_main_library_instance_i; #! (labels_to_be_linked,_) = mapSt (convert_symbol_name_into_dus_label main_library_instance_i) symbols 0; #! (symbol_addresses,dl_client_state,io) = LoadLibraryInstance_new main_library_instance_i (Just labels_to_be_linked) dl_client_state io; // check for errors #! (ok,dl_client_state) = IsErrorOccured dl_client_state; | not ok = (not ok,client_id,AddToDLServerState dl_client_state s,io); // verbose #! messages = foldl2 produce_verbose_output2 [] labels_to_be_linked symbol_addresses; #! dl_client_state = SetLinkerMessages messages dl_client_state ; // end #! io = SendAddressToClient client_id symbol_addresses io; = (not ok,client_id,AddToDLServerState dl_client_state s,io); where { convert_symbol_name_into_dus_label library_instance_i label_name ith_address #! dus_label = { default_elem & dusl_label_name = label_name , dusl_library_instance_i = library_instance_i , dusl_linked = False , dusl_label_kind = DSL_EMPTY , dusl_ith_address = ith_address , dusl_address = -1 }; = (dus_label,inc ith_address); } ComputeDescAddressTable :: !ProcessSerialNumber [String] !*DLServerState !(IOState !*DLServerState) -> !(!Bool,!ProcessSerialNumber,!*DLServerState, !(IOState !*DLServerState)); ComputeDescAddressTable client_id [args] s io = abort "ComputeDescAddressTable; disabled"; /* #! (client_exists,dl_client_state,s) = RemoveFromDLServerState client_id s; | F "ComputeDescAddressTable" not client_exists = internal_error "ComputeDescAddressTable (internal error): client not registered" client_id dl_client_state s io; #! (dl_client_state) = AddMessage (Verbose "ComputeDescAddressTable") dl_client_state; #! args = ExtractArguments '\n' 0 args []; | length args <> 1 //2 = internal_error "ComputeDescAddressTable (internal error): didn't get expected arguments" client_id dl_client_state s io; #! file_name = hd args; // get stringtable and descriptor address table #! ((ok,version,stringtable,desc_address_table),io) = accFiles (read_stringtable_and_desc_address_table file_name /*header_fp*/) io; #! unknown_modules_or_symbols = generate_needed_label_names2 stringtable desc_address_table; #! (ok,latest_version,dl_client_state,s) = eager_read_version version dl_client_state s; #! (dlink_dir,s) = GetDynamicLinkerDirectory s; #! module_name = dlink_dir +++ "\\" +++ copy_string_to_graph +++ "_" +++ (toFileNameSubString latest_version) +++ ".obj"; #! symbol_name = "e____SystemDynamic__d" +++ copy__string__to__graph +++ "__" +++ toFileNameSubString latest_version; #! unknown_modules_or_symbols = [ModuleUnknown module_name symbol_name:unknown_modules_or_symbols]; // copy of AddDescriptors ... // search, link and load descriptors #! (linked,l,dl_client_state,s,io) = NewLinkerFunction2 unknown_modules_or_symbols dl_client_state s io; // check for errors #! (ok,dl_client_state) = IsErrorOccured dl_client_state; | not ok = (not ok,client_id,AddToDLServerState dl_client_state s,io); // verbose #! dl_client_state = SetLinkerMessages (produce_verbose_output unknown_modules_or_symbols l []) dl_client_state; = (not ok,client_id,AddToDLServerState dl_client_state s,io); // ... copy of AddDescriptors */ ComputeDescAddressTable2_n_args :== 4; ComputeDescAddressTable2_n_copy_request_args :== 6; import memory_mapped_files; RegisterLazyDynamic :: !ProcessSerialNumber [String] !*DLServerState !(IOState !*DLServerState) -> !(!Bool,!ProcessSerialNumber,!*DLServerState, !(IOState !*DLServerState)); RegisterLazyDynamic client_id [args] s io #! (client_exists,dl_client_state,s) = RemoveFromDLServerState client_id s; | /*F "ComputeDescAddressTable2"*/ not client_exists = internal_error "RegisterLazyDynamic (internal error): client not registered" client_id dl_client_state s io; #! (dl_client_state) = AddMessage (Verbose "RegisterLazyDynamic") dl_client_state; #! args = ExtractArguments '\n' 0 args []; #! l_args = length args; #! rt_lazy_dynamic_index = FromStringToInt (hd args) 0; // run-time ptr // Using the run-time lazy dynamic index (rt_lazy_dynamic_index), the id of the main dynamic i.e. the // top-level dynamic is determined. #! (result,dl_client_state) = get_dynamic_id rt_lazy_dynamic_index dl_client_state | isNothing result = abort "RegisterLazyDynamic; get_dynamic_id; lazy_dynamic_index cannot be found"; // dynamic found // 1. map file // 2. initialize dynamic (using code in ComputeDescAddressTable2) #! (disk_lazy_dynamic_index,id) = fromJust result; #! main_dynamic_id = id; // run-time pointer // extract file name from dynamic containing the lazy dynamic # (file_name,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_lazy_dynamics_a.[disk_lazy_dynamic_index]; // assign the lazy dynamic a run-time id #! (id,dl_client_state) = new_dynamic_id dl_client_state; #! lazy_dynamic_id = id; #! (has_lazy_dynamic_already_been_initialized,dl_client_state) = dl_client_state!cs_lazy_dynamic_index_to_dynamic_id.[rt_lazy_dynamic_index]; #! initialized_lazy_dynamic = isJust has_lazy_dynamic_already_been_initialized // the dynamic associated from which the build_lazy_block wants to build a block has already // been initialized. #! dl_client_state = case initialized_lazy_dynamic of { True -> dl_client_state; _ -> { dl_client_state & cs_lazy_dynamic_index_to_dynamic_id.[rt_lazy_dynamic_index] = Just id }; }; // map file into memory of client ... # client_process_id = GetOSProcessSerialNumber client_id; # (dynamic_rts_process_handle,st) = OpenProcess (STANDARD_RIGHTS_REQUIRED bitor PROCESS_ALL_ACCESS) FALSE client_process_id initialState; # (ok,file,exported_handle) = CreateSharedBufferFromFile2 dynamic_rts_process_handle file_name; | not ok = abort "could not create memory mapped file"; // body ... # (file,id,dl_client_state,io) = case initialized_lazy_dynamic of { False # (ok,dynamic_header,file) = read_dynamic_header file; | not ok -> abort "get_tables_from_dynamic: error reading dynamic header"; # (file,id,dl_client_state,io) = read_from_dynamic id file_name file dl_client_state io dynamic_header; -> (file,id,dl_client_state,io); True -> (file,fromJust has_lazy_dynamic_already_been_initialized,dl_client_state,io); }; | not (CloseExistingSharedBuffer file) || not (CloseST st) = abort "stop"; // ... map file into memory of client // initialize dynamic #! (dl_client_state,io) = case initialized_lazy_dynamic of { False #! (_,dl_client_state,io) = init_lazy_dynamic id dl_client_state io; // lazy dynamic at rt_lazy_dynamic_index is assigned dynamic id, now type references must be // converted. Promotion of lazy dynamic to a dynamic #! dl_client_state = update_type_implementation_table rt_lazy_dynamic_index id dl_client_state -> (dl_client_state,io); True -> (dl_client_state,io); }; # (di_string_table,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_string_table; // msg ... #! (library_instance_runtime_ids,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_disk_id_to_library_instance_i; #! (di_disk_to_rt_dynamic_indices,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_disk_to_rt_dynamic_indices; // due to 1.3 bug, a six tuple cannot be exported. Therefore I pack the file_name // with the exported handle. #! msg = ((exported_handle, file_name), library_instance_runtime_ids, // lazy dynamics... di_disk_to_rt_dynamic_indices, // ... lazy dynamics id); // ... msg #! io = SendAddressToClient client_id (encode msg) io; #! ok = True = (not ok,client_id,AddToDLServerState dl_client_state s,io); where { // Converts LibRefViaLazyDynamic into LibRef. This means that a lazy dynamic is promoted to a dynamic // because all its library instances have been assigned a run-time library instance number because the // evaluation needs some part of the lazy dynamic. update_type_implementation_table rt_lazy_dynamic_index rt_dynamic_index dl_client_state | True <<- ("update_type_implementation_table", id) #! (n_type_equivalent_classes,dl_client_state) = dl_client_state!cs_type_implementation_table.teit_n_type_implementations; #! dl_client_state = loopAst convert_type_equivalent_class dl_client_state n_type_equivalent_classes; = dl_client_state; where { convert_type_equivalent_class ith_type_equivalent_class dl_client_state #! (type_equivalent_class=:{tei_type_implementations},dl_client_state) = dl_client_state!cs_type_implementation_table.teit_type_implementations_a.[ith_type_equivalent_class]; #! (converted_type_references,(changed,dl_client_state)) = mapSt convert_type_reference tei_type_implementations (False,dl_client_state); | not changed = dl_client_state; #! dl_client_state = { dl_client_state & cs_type_implementation_table.teit_type_implementations_a.[ith_type_equivalent_class].tei_type_implementations = converted_type_references }; // inform user #! msg = "converted lazy dynamic index " +++ toString rt_lazy_dynamic_index +++ " to dynamic index " +++ toString rt_dynamic_index; #! dl_client_state = AddMessage (Verbose msg) dl_client_state; = dl_client_state; where { convert_type_reference type_reference=:(LIT_TypeReference (LibRefViaLazyDynamic disk_library_instance_i rt_offered_lazy_dynamic_index _) tio_type_ref) (changed,dl_client_state) | rt_lazy_dynamic_index == rt_offered_lazy_dynamic_index // promote lazy dynamic to a dynamic by converting the LibRefViaLazyDynamic to LibRef. The // library instances used by the lazy dynamic have been assigned an unique number by init_ // dynamic2. Now the type implementation table must be converted accordingly. Note that the // RunTimeIDs still contain references to the lazy dynamic index. #! (rt_library_instance,dl_client_state) = dl_client_state!cs_dynamic_info.[rt_dynamic_index].di_disk_id_to_library_instance_i.[disk_library_instance_i]; #! converted_type_reference = LIT_TypeReference (LibRef rt_library_instance) tio_type_ref; = (converted_type_reference,(True,dl_client_state)); = (type_reference,(changed,dl_client_state)); convert_type_reference type_reference s = (type_reference,s); } } // update_type_implementation_table }; get_dynamic_id searched_rt_lazy_dynamic_index dl_client_state #! (n_dynamics,dl_client_state) = dl_client_state!dynamic_ids.did_counter; #! (result,dl_client_state) = findAst is_searched_dynamic_index dl_client_state n_dynamics; = (result,dl_client_state); where { is_searched_dynamic_index dynamic_index dl_client_state // determine whether the dynamic id is valid # (is_valid_dynamic_index,dl_client_state) = is_valid_id2 dynamic_index dl_client_state; | not is_valid_dynamic_index = (Nothing,dl_client_state); // valid, extract array holding all run-time lazy dynamic indices # (di_disk_to_rt_dynamic_indices,dl_client_state) = dl_client_state!cs_dynamic_info.[dynamic_index].di_disk_to_rt_dynamic_indices; # result = findAi is_lazy_disk_dynamic di_disk_to_rt_dynamic_indices; = (result,dl_client_state); where { is_lazy_disk_dynamic disk_lazy_dynamic_index rt_lazy_dynamic_index | searched_rt_lazy_dynamic_index == rt_lazy_dynamic_index = Just (disk_lazy_dynamic_index,dynamic_index); = Nothing; }; // is_searched_dynamic }; // get_dynamic_id2 init_lazy_dynamic id dl_client_state io = init_dynamic2 "LAZY DYNAMIC" True id dl_client_state io; // physically reads in file and initializes the administration for the dynamic by init_dynamic2 init_dynamic file_name False id block_i args dl_client_state io = (id,dl_client_state,io); init_dynamic file_name first_time id block_i args dl_client_state io // create a new id #! (id,dl_client_state) = new_dynamic_id dl_client_state; #! msg = "** Encoded a dynamic (e.g. from disk): " +++ toString id; #! (dl_client_state) = AddMessage (Verbose msg) dl_client_state; # (id,dl_client_state,io) = get_tables_from_dynamic args file_name id dl_client_state io; #! msg = "dynamic: '" +++ file_name +++ "' id: " +++ toString id +++" block: " +++ toString block_i; #! (dl_client_state) = AddMessage (Verbose msg) dl_client_state; = init_dynamic2 file_name first_time id dl_client_state io; where { get_tables_from_dynamic args file_name id dl_client_state io #! dynamic_access = case (size args) of { ComputeDescAddressTable2_n_args -> "FILE"; // file containing dynamic is read by dynamic rts ComputeDescAddressTable2_n_copy_request_args -> "VIEW"; // view passed by the rts is read by dynamic rts }; #! dl_client_state = AddMessage (Verbose ("dynamic access: " +++ dynamic_access)) dl_client_state; | size args == ComputeDescAddressTable2_n_args // open dynamic #! (ok,dynamic_header,file,io) = open_dynamic_as_binary file_name io; | not ok #! (_,io) = close_dynamic_as_binary file io; #! msg = "could not open dynamic '" +++ file_name +++ "'"; #! dl_client_state = AddMessage (LinkerError msg) dl_client_state; = (0,dl_client_state,io); # (file,id,dl_client_state,io) = read_from_dynamic id file_name file dl_client_state io dynamic_header; # (_,io) = close_dynamic_as_binary file io; = (id,dl_client_state,io); | size args == ComputeDescAddressTable2_n_copy_request_args # file_mapping_handle = toInt args.[4]; # s_buffer = toInt args.[5]; # (ok,file) = OpenExistingSharedBuffer file_mapping_handle s_buffer | not ok = abort "get_tables_from_dynamic: OpenExistingSharedBuffer failed"; # (ok,dynamic_header,file) = read_dynamic_header file; | not ok = abort "get_tables_from_dynamic: error reading dynamic header"; # (file,id,dl_client_state,io) = read_from_dynamic id file_name file dl_client_state io dynamic_header; | CloseExistingSharedBuffer file = (id,dl_client_state,io); = abort "unreachable"; } // DynamicInfo init_dynamic2 file_name first_time id dl_client_state io #! (dl_client_state) = case first_time of { True -> AddMessage (Verbose ("init_dynamic2: dynamic id " +++ toString id)) dl_client_state; _ -> dl_client_state; }; #! ({di_disk_type_equivalent_classes,di_n_blocks},dl_client_state) = dl_client_state!cs_dynamic_info.[id]; | di_n_blocks <= 0 = abort "init_dynamic2; internal error; dynamic has no blocks"; #! (stringtable,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_string_table; #! (descriptor_usage_table,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_descriptor_usage_table; // lazy dynamics ... #! (di_lazy_dynamics_a,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_lazy_dynamics_a; #! (cs_n_lazy_dynamics,dl_client_state) = dl_client_state!cs_n_lazy_dynamics; #! n_lazy_disk_dynamics = size di_lazy_dynamics_a; #! di_disk_to_rt_dynamic_indices = createArray n_lazy_disk_dynamics 0; // allocate lazy dynamic ids for each lazy disk dynamic id #! dl_client_state = AddMessage (Verbose "Preallocation of its lazy dynamics") dl_client_state #! (di_disk_to_rt_dynamic_indices,cs_n_lazy_dynamics,dl_client_state) = loopAst ( \index (di_disk_to_rt_dynamic_indices,cs_n_lazy_dynamics,dl_client_state) -> let { cs_next_lazy_dynamic = inc cs_n_lazy_dynamics; msg = toString cs_n_lazy_dynamics +++ ": '" +++ di_lazy_dynamics_a.[index] } in ({di_disk_to_rt_dynamic_indices & [index] = cs_n_lazy_dynamics},cs_next_lazy_dynamic,AddMessage (Verbose msg) dl_client_state) ) (di_disk_to_rt_dynamic_indices,cs_n_lazy_dynamics,dl_client_state) n_lazy_disk_dynamics; // extend array to include new lazy dynamics #! (cs_lazy_dynamic_index_to_dynamic_id,dl_client_state) = get_lazy_dynamic_index_to_dynamic_id dl_client_state; #! (_,cs_lazy_dynamic_index_to_dynamic_id) = extend_array_nu n_lazy_disk_dynamics cs_lazy_dynamic_index_to_dynamic_id; #! dl_client_state = { dl_client_state & cs_lazy_dynamic_index_to_dynamic_id = cs_lazy_dynamic_index_to_dynamic_id }; #! dl_client_state = { dl_client_state & cs_n_lazy_dynamics = cs_n_lazy_dynamics }; # dl_client_state = { dl_client_state & cs_dynamic_info.[id].di_disk_to_rt_dynamic_indices = di_disk_to_rt_dynamic_indices }; // get info about the library instances used by the dynamic # (di_library_instance_to_library_index,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_library_instance_to_library_index; # (di_library_index_to_library_name,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_library_index_to_library_name; # library_instance_runtime_ids // indexed by RunTimeID(diskID) to obtain library instance id = force_unboxed_int_array (createArray (size di_library_instance_to_library_index) (-1)); # (library_instance_runtime_ids,_,dl_client_state,io) = mapAiSt convert_string_id_to_runtime_id_for_a_library_instance di_library_instance_to_library_index (library_instance_runtime_ids,di_library_index_to_library_name,dl_client_state,io); // ComputeDescAddress still contains diskIDs instead of real RunTimeIDs, so the conversion table // must be preserved. # dl_client_state = { dl_client_state & cs_dynamic_info.[id].di_disk_id_to_library_instance_i = library_instance_runtime_ids , cs_dynamic_info.[id].di_has_block_been_used = createArray di_n_blocks False }; // printing #! dl_client_state = AddMessage (Verbose "References to type-libraries i.e. type tables") dl_client_state; #! (type_tables,dl_client_state) = get_type_tables dl_client_state; #! (type_tables,dl_client_state) = loopAfill print_library_name type_tables dl_client_state; // updating #! dl_client_state = { dl_client_state & cs_type_tables = type_tables }; // Each dynamic has type equations which ensure that equivalent types have a single, unique representation // within a dynamic or even among several dynamics. It should be noted that by several does not imply all // dynamics: it depends upon the external types of dynamics which directly or indirectly could use the // dynamic being initialized here. // All lazy type equations are ignored here because the associated dynamics have not yet been initialized // let alone built which implies that the types implementations needed by these lazy dynamics can never // have been linked in already, so no type equations are needed to enforce this. Upon the first block built // of a lazy dynamic, the situation changes. // Hence only (eager) type equations will be stored in the type implementation table which is done below: // ... # (dl_client_state,io) = mapASt (enter_type_equations_in_type_implementation_table id) di_disk_type_equivalent_classes (dl_client_state,io); = (id,dl_client_state,io); where { enter_type_equations_in_type_implementation_table id type_equations (dl_client_state,io) # (di_disk_id_to_library_instance_i,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_disk_id_to_library_instance_i; #! (di_disk_to_rt_dynamic_indices,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_disk_to_rt_dynamic_indices; # type_equations = [ type \\ type <-: type_equations ]; # (types,(di_disk_id_to_library_instance_i,di_disk_to_rt_dynamic_indices,dl_client_state,io)) = mapSt convert_encoded_library_reference type_equations (di_disk_id_to_library_instance_i,di_disk_to_rt_dynamic_indices,dl_client_state,io); #! (Just (type_implementation_ref,created_new_type_equivalence_class),dl_client_state) = enter_type_equation (hd types) (hd (tl types)) dl_client_state; #! dl_client_state = add_lazy_type_equations type_implementation_ref (tl (tl types)) dl_client_state; = (dl_client_state,io); where { convert_encoded_library_reference type=:(LIT_TypeReference lib_ref tio_type_reference) (di_disk_id_to_library_instance_i,di_disk_to_rt_dynamic_indices,dl_client_state,io) # (lib_ref,dl_client_state,io) = case lib_ref of { LibRef disk_library_instance -> (LibRef (di_disk_id_to_library_instance_i.[disk_library_instance]),dl_client_state,io); LibRefViaLazyDynamic disk_library_instance disk_dynamic_index type_library_reference # (library_name,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_library_index_to_library_name.[type_library_reference]; // allocate & load required type table # (type_table_i,dl_client_state) = AddReferenceToTypeTable library_name dl_client_state; # (dl_client_state,io) = LoadTypeTable type_table_i dl_client_state io; # type_table_reference = type_table_i; -> (LibRefViaLazyDynamic disk_library_instance (di_disk_to_rt_dynamic_indices.[disk_dynamic_index]) type_table_reference,dl_client_state,io); }; # type = LIT_TypeReference lib_ref tio_type_reference; = (type,(di_disk_id_to_library_instance_i,di_disk_to_rt_dynamic_indices,dl_client_state,io)); }; force_unboxed_int_array :: !*{#Int} -> !*{#Int}; force_unboxed_int_array i = i; convert_string_id_to_runtime_id_for_a_library_instance library_instance_string_id (LIK_LazyLibraryInstance {lik_library_instance_i=lr_library_instance_i,lik_dynamic_index_i=lr_dynamic_index_i}) s=:(library_instance_runtime_ids,di_library_index_to_library_name,dl_client_state,io) // skip reserved elements | library_instance_string_id < RTID_DISKID_RENUMBER_START = s //<<- (library_instance_string_id, "not accepted"); // name of lazy dynamic # (lazy_dynamic_name,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_lazy_dynamics_a // convert *disk* lazy library to *run-time* lazy library # (rt_lazy_dynamic_index,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_disk_to_rt_dynamic_indices.[lr_dynamic_index_i]; // consistency check # (result,dl_client_state) = dl_client_state!cs_lazy_dynamic_index_to_dynamic_id.[rt_lazy_dynamic_index]; | isJust result // The lazy dynamics of the main dynamic being initialized here with identification id, are assigned numbers into // the cs_lazy_dynamic_index_to_dynamic_id-array which means that none of the code for the lazy dynamics has been // used yet and they therefore have not (yet) been initialized. = abort "encode_references_to_type_libraries; internal error; lazy dynamic has already been assigned a run-time id" # library_instance_runtime_ids = { library_instance_runtime_ids & [library_instance_string_id] = LLI_CREATE_LAZY_LIBRARY_INSTANCE lr_library_instance_i rt_lazy_dynamic_index }; = (library_instance_runtime_ids,di_library_index_to_library_name,dl_client_state,io); convert_string_id_to_runtime_id_for_a_library_instance library_instance_string_id (LIK_LibraryInstance {LIK_LibraryInstance | lik_index_in_di_library_index_to_library_name=library_name_i}) s=:(library_instance_runtime_ids,di_library_index_to_library_name,dl_client_state,io) // skip reserved elements | library_instance_string_id < RTID_DISKID_RENUMBER_START = s // convert string index for a library instance into a run-time index for that library instance # library_name = di_library_index_to_library_name.[library_name_i]; # (library_instance_i,_,dl_client_state,io) = RegisterLibrary (Just id) False library_name dl_client_state io; # library_instance_runtime_ids = { library_instance_runtime_ids & [library_instance_string_id] = library_instance_i }; = (library_instance_runtime_ids,di_library_index_to_library_name,dl_client_state,io); convert_string_id_to_runtime_id_for_a_library_instance library_instance_string_id (LIK_LibraryRedirection _) s = s; print_library_name i a dl_client_state // printing #! (tt_name,a) = a![i].tt_name; #! (tt_loaded,a) = a![i].tt_loaded; #! msg = toString i +++ (if tt_loaded " (Loaded)" " (Not loaded)") +++ ": " +++ tt_name; #! dl_client_state = AddMessage (Verbose msg) dl_client_state; = (a,dl_client_state); }; read_from_dynamic :: !Int !String !*f !*DLClientState !.a !.DynamicHeader -> *(!*f,!Int,!*DLClientState,!.a) | BinaryDynamicIO f; read_from_dynamic id file_name file dl_client_state io dynamic_header // read descriptor usage set table #! (ok,descriptor_usage_table,file) = read_descriptor_usage_table_from_dynamic dynamic_header file; | not ok #! msg = "could not read descriptor usage table '" +++ file_name +++ "'"; #! dl_client_state = AddMessage (LinkerError msg) dl_client_state; = (file,0,dl_client_state,io); // read string table #! (ok,stringtable,file) = read_string_table_from_dynamic dynamic_header file; #! dl_client_state = case ok of { True -> dl_client_state; False #! msg = "could not read string table from '" +++ file_name +++ "'"; -> AddMessage (LinkerError msg) dl_client_state; }; // read block table #! (ok,block_table,file) = read_block_table_from_dynamic dynamic_header file; #! dl_client_state = case ok of { True -> dl_client_state; False #! msg = "could not read block table from '" +++ file_name +++ "'"; -> AddMessage (LinkerError msg) dl_client_state; }; // read dynamic rts info #! (ok2,dynamic_info,file) = read_rts_info_from_dynamic dynamic_header file; #! dl_client_state = case ok2 of { True -> dl_client_state; False #! msg = "could not read dynamic rts info from '" +++ file_name +++ "'"; -> AddMessage (LinkerError msg) dl_client_state; }; # dynamic_info = { dynamic_info & di_string_table = stringtable , di_descriptor_usage_table = descriptor_usage_table , di_version = toVersion dynamic_header.version_number , di_file_name = file_name , di_n_blocks = size block_table }; # dl_client_state = UpdateDynamicInfo id dynamic_info dl_client_state = (file,id,dl_client_state,io); ComputeDescAddressTable2 :: !ProcessSerialNumber [String] !*DLServerState !(IOState !*DLServerState) -> !(!Bool,!ProcessSerialNumber,!*DLServerState, !(IOState !*DLServerState)); ComputeDescAddressTable2 client_id [args] s io #! (client_exists,dl_client_state,s) = RemoveFromDLServerState client_id s; | not client_exists = internal_error "ComputeDescAddressTable2 (internal error): client not registered" client_id dl_client_state s io; #! (dl_client_state) = AddMessage (Verbose "ComputeDescAddressTable2") dl_client_state; #! args = ExtractArguments '\n' 0 args []; #! l_args = length args #! is_non_copy_request = (l_args == ComputeDescAddressTable2_n_args); #! is_copy_request = (l_args == ComputeDescAddressTable2_n_copy_request_args); | not (is_non_copy_request || is_copy_request) = internal_error ("ComputeDescAddressTable2 (internal error): didn't get expected arguments " +++ toString l_args) client_id dl_client_state s io; // extract arguments #! args = h { arg \\ arg <- args }; #! file_name = args.[0]; #! first_time = args.[1] == "True"; #! id = toInt args.[2]; #! block_i = toInt args.[3]; #! (id,dl_client_state,io) = init_dynamic file_name first_time id block_i args dl_client_state io; // mark block as used ... #! (di_has_block_been_used,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_has_block_been_used; #! di_has_block_been_used = { x \\ x <-: di_has_block_been_used }; // make unique #! dl_client_state = { dl_client_state & cs_dynamic_info.[id].di_has_block_been_used = { di_has_block_been_used & [block_i] = True } }; // ... mark block as used # ({di_version,di_string_table,di_descriptor_usage_table,di_library_instance_to_library_index},dl_client_state) = dl_client_state!cs_dynamic_info.[id]; #! n_disk_libraries = size di_library_instance_to_library_index; #! used_disk_libraries = NewBitSet n_disk_libraries; #! (ok,latest_version,dl_client_state,s) = eager_read_version di_version dl_client_state s; // ... #! (dlink_dir,s) = GetDynamicLinkerDirectory s; #! module_name = dlink_dir +++ "\\" +++ copy_string_to_graph +++ "_" +++ (toFileNameSubString latest_version) +++ ".obj"; #! symbol_name = "e____SystemDynamic__d" +++ copy__string__to__graph +++ "__" +++ toFileNameSubString latest_version; #! (Just main_library_instance_i,dl_client_state) = dl_client_state!cs_main_library_instance_i; # conversion_dus_label = { default_elem & dusl_label_name = symbol_name , dusl_library_instance_i = main_library_instance_i , dusl_linked = False }; // ... # initial_labels = []; //conversion_dus_label]; # (do_dump_dynamic,dl_client_state) = dl_client_state!do_dump_dynamic; # (a,dl_client_state,s,io) = case do_dump_dynamic of { True -> (0,dl_client_state,s,io); _ # (maybe_to_graph_entry,dl_client_state) = get_to_graph_function_address2 (Just latest_version) dl_client_state; | isNothing maybe_to_graph_entry // Required conversion function not present -> abort ("ComputeDescAddressTable2: required conversion function not found >>" +++ toFileNameSubString latest_version); #! ({tafge_conversion},i) = fromJust maybe_to_graph_entry #! (a,dl_client_state,s,io) = case tafge_conversion of { Nothing # (dl_client_state,s,io) = add_object_module_to_library_instance module_name main_library_instance_i dl_client_state s io; # ([address:_],dl_client_state,io) = LoadLibraryInstance_new main_library_instance_i (Just [conversion_dus_label]) dl_client_state io; # dl_client_state = { dl_client_state & cs_to_and_from_graph.tafgt_to_graphs.[i].tafge_conversion = Just address }; -> (address,dl_client_state,s,io); Just address -> (address,dl_client_state,s,io); }; -> (a,dl_client_state,s,io); }; // address #! (n_addresses,used_disk_libraries) = mapAiSt (compute_used_libraries_in_current_block block_i) di_descriptor_usage_table (length initial_labels,used_disk_libraries); #! (used_disk_libraries,(dus_labels,dl_client_state,s,io)) = enum_setSt (link_library_instance di_string_table di_descriptor_usage_table block_i id n_addresses) used_disk_libraries (initial_labels,dl_client_state,s,io); // ----------------------------------------------- #! addresses = createArray n_addresses 0; #! dus_labels_a = createArray n_addresses default_elem; #! (addresses,dus_labels) = foldSt fill_addresses_and_dus_labels dus_labels (addresses,dus_labels_a); #! dus_labels = [conversion_dus_label : [ dus_label \\ dus_label <-: dus_labels ] ]; #! symbol_addresses = [ a : [ address \\ address <-: addresses ] ]; #! (dl_client_state,io) = case first_time of { False -> (dl_client_state,SendAddressToClient client_id (/* toString DYN_OK,*/ id,symbol_addresses) io); True #! (library_instance_runtime_ids,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_disk_id_to_library_instance_i; #! (di_disk_to_rt_dynamic_indices,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_disk_to_rt_dynamic_indices; | True <<- ("$$$",library_instance_runtime_ids) #! msg = (encode library_instance_runtime_ids, encode di_disk_to_rt_dynamic_indices, id,symbol_addresses); -> (dl_client_state,SendAddressToClient client_id msg io); }; // check for errors #! (ok,dl_client_state) = IsErrorOccured dl_client_state; | not ok = (not ok,client_id,AddToDLServerState dl_client_state s,io); // verbose #! messages = if do_dump_dynamic (foldl2 produce_verbose_output2 [] (tl dus_labels) (tl symbol_addresses)) (foldl2 produce_verbose_output2 [] dus_labels symbol_addresses); #! dl_client_state = SetLinkerMessages messages dl_client_state ; = (not ok,client_id,AddToDLServerState dl_client_state s,io); where { fill_addresses_and_dus_labels:: !u:DusLabel !*(!*{#Int},!*{#DusLabel}) -> (!*{#Int},!*{#DusLabel}); fill_addresses_and_dus_labels dus_label=:{dusl_linked,dusl_ith_address,dusl_address} (addresses,dus_labels_a) #! addresses = { addresses & [dusl_ith_address] = dusl_address }; #! dus_labels_a = { dus_labels_a & [dusl_ith_address] = dus_label }; = (addresses,dus_labels_a); // computes which disk libraries are needed to build the current block compute_used_libraries_in_current_block block_i _ {bitset,prefix_set_and_string_ptr,dus_library_instance_nr_on_disk} (ith_address,used_disk_libraries) #! (prefixes,_,_) = determine_prefixes3 prefix_set_and_string_ptr; #! ith_address = if (fst (isBitSetMember bitset block_i)) (ith_address + length prefixes) ith_address; #! used_disk_libraries = AddBitSet used_disk_libraries dus_library_instance_nr_on_disk; = (ith_address,used_disk_libraries); /* link_to_graph_conversion s1 dl_client_state s io #! (b,ad,dl_client_state,s,io) = NewLinkerFunction2a False s1 dl_client_state s io; | length ad <> 1 = abort "ComputeDescAddressTable2; internal error"; = ((b,ad),dl_client_state,s,io); */ lookup_library_id :: !Int (!*{#Int},!{#{String}},!*DLClientState) -> (!*{#Int},!{#{String}},!*DLClientState); lookup_library_id index (type_table_id_array,library_names,dl_client_state) # (type_table_id,dl_client_state) = AddReferenceToTypeTable library_names.[index] dl_client_state; # type_table_id_array = { type_table_id_array & [index] = type_table_id }; = (type_table_id_array,library_names,dl_client_state); Pl [] s = s; Pl [ModuleUnknown module_name symbol_name:xs] s = Pl xs ("(" +++ module_name +++ "," +++ symbol_name +++ ")\n " +++ s); }; compute_addresses_for_labels_belonging_to_an_implemented_type_equivalent_class3 :: !DusLabel !*DLClientState -> (!DusLabel,*DLClientState); compute_addresses_for_labels_belonging_to_an_implemented_type_equivalent_class3 dus_label/*=:{dusl_linked=True}*/ dl_client_state #! (label_address,dl_client_state) = compute_addresses_for_labels_belonging_to_an_implemented_type_equivalent_class2 dus_label /*(-89)*/ /*[]*/ dl_client_state; #! dus_label = { dus_label & dusl_address = label_address }; = (dus_label,dl_client_state); compute_addresses_for_labels_belonging_to_an_implemented_type_equivalent_class3 dus_label dl_client_state = (dus_label,dl_client_state); compute_addresses_for_labels_belonging_to_an_implemented_type_equivalent_class2 :: !DusLabel !*DLClientState -> *(Int,*DLClientState); compute_addresses_for_labels_belonging_to_an_implemented_type_equivalent_class2 {dusl_label_name,dusl_library_instance_i} dl_client_state #! (maybe_label,dl_client_state) = findLabel dusl_label_name dusl_library_instance_i dl_client_state; | isNothing maybe_label = abort ("compute_addresses_for_labels_belonging_to_an_implemented_type_equivalent_class; internal error; label should exist '" +++ dusl_label_name +++ "'"); #! (file_n,symbol_n) = fromJust maybe_label; #! (maybe_label_address,dl_client_state) = isLabelImplemented file_n symbol_n dl_client_state; | isNothing maybe_label_address = abort ("compute_addresses_for_labels_belonging_to_an_implemented_type_equivalent_class; internal error; label should exist (unmarked) '" +++ dusl_label_name +++ "'" +++ toString dusl_library_instance_i); = (fromJust maybe_label_address,dl_client_state); N_SECTIONS_IN_MEMORY :== 2; from SearchObject import load_object; add_object_module_to_library_instance :: !{#Char} !Int !*DLClientState !*DLServerState !*(IOState *a) -> *(!*DLClientState,*DLServerState,*IOState *a); add_object_module_to_library_instance object_name library_instance_i dl_client_state s io # (state,dl_client_state) = get_state dl_client_state; // extract namestable #! (names_table,dl_client_state) = acc_names_table library_instance_i dl_client_state; #! state = {state & namestable = names_table }; // add new object module # (ok,labels,state,dl_client_state,s,io) = load_object object_name 0 "" state dl_client_state s io; | not ok || (not (isEmpty labels)) = abort ("add_object_module_to_library_instance; internal error" +++ (fst3 (hd labels))); // restoring namestable #! (names_table,state) = get_names_table state; #! dl_client_state = { dl_client_state & cs_library_instances.lis_library_instances.[library_instance_i].li_names_table = names_table }; # dl_client_state = { dl_client_state & app_linker_state = state }; = (dl_client_state,s,io); where { get_names_table state=:{namestable} = (namestable,{state & namestable = {}}); }; // get address of the graph to string function GetGraphToStringFunction :: !ProcessSerialNumber [String] !*DLServerState !(IOState !*DLServerState) -> !(!Bool,!ProcessSerialNumber,!*DLServerState, !(IOState !*DLServerState)); GetGraphToStringFunction client_id [label_names_encoded_in_msg] s io #! (client_exists,dl_client_state,s) = RemoveFromDLServerState client_id s; | F "GetGraphToStringFunction" not client_exists = internal_error "GetGraphToStringFunction (internal error): client not registered" client_id dl_client_state s io; #! (dl_client_state) = AddMessage (Verbose "GetGraphToStringFunction") dl_client_state; #! (l,graph_to_string,dl_client_state,s,io) = case True of { True // The conversion-functions are shared among all library instances. The Clean-data structures used within // these functions may only have a single implementation. #! ({tafge_version=latest_version,tafge_conversion},tfge_index,dl_client_state) = get_from_graph_function_address2 Nothing dl_client_state; | isJust tafge_conversion <<- tafge_conversion // conversion-functions have already been linked. Re-use these functions #! (dlink_dir,s) = GetDynamicLinkerDirectory s; #! module_name = dlink_dir +++ "\\" +++ copy_graph_to_string +++ "_" +++ (toFileNameSubString latest_version) +++ ".obj"; #! symbol_name = "e____SystemDynamic__d" +++ copy__graph__to__string +++ "__" +++ toFileNameSubString latest_version; #! graph_to_string = [ModuleUnknown module_name symbol_name]; -> ([fromJust tafge_conversion],graph_to_string,dl_client_state,s,io); #! (dlink_dir,s) = GetDynamicLinkerDirectory s; #! module_name = dlink_dir +++ "\\" +++ copy_graph_to_string +++ "_" +++ (toFileNameSubString latest_version) +++ ".obj"; #! symbol_name = "e____SystemDynamic__d" +++ copy__graph__to__string +++ "__" +++ toFileNameSubString latest_version; #! graph_to_string = [ModuleUnknown module_name symbol_name]; #! (Just main_library_instance_i,dl_client_state) = dl_client_state!cs_main_library_instance_i; #! (dl_client_state,s,io) = add_object_module_to_library_instance module_name main_library_instance_i dl_client_state s io; #! label = { default_elem & dusl_label_name = symbol_name , dusl_linked = False , dusl_label_kind = DSL_RUNTIME_SYSTEM_LABEL }; #! (l,dl_client_state,io) = LoadLibraryInstance_new main_library_instance_i (Just [label]) dl_client_state io # dl_client_state = { dl_client_state & cs_to_and_from_graph.tafgt_from_graphs.[tfge_index].tafge_conversion = Just (hd l) }; -> (l,graph_to_string,dl_client_state,s,io); }; // check for errors #! (ok,dl_client_state) = IsErrorOccured dl_client_state; | not ok = (not ok,client_id,AddToDLServerState dl_client_state s,io); // DLClientState # (cs_n_lazy_dynamics,dl_client_state) = dl_client_state!cs_n_lazy_dynamics; # (msg,dl_client_state) = build_range_table dl_client_state; # encoded_l = EncodeClientMessage l +++ msg +++ FromIntToString cs_n_lazy_dynamics; # io = SendAddressToClient client_id encoded_l io; //abort "ok"; // verbose #! dl_client_state = SetLinkerMessages (produce_verbose_output graph_to_string l []) dl_client_state; = (not ok,client_id,AddToDLServerState dl_client_state s,io); // ... copy of AddDescriptors where { build_range_table dl_client_state=:{cs_library_instances={lis_n_library_instances}} # (range_entries,dl_client_state) = loopAst build_range_entry3 ([],dl_client_state) lis_n_library_instances; # range_entries = { range_entry \\ range_entry <- range_entries }; # n_sections = size range_entries; # range_id = { rid_n_range_id_entries = n_sections , rid_n_type_tables = /* RTID_LIBRARY_INSTANCE_ID_START + */ lis_n_library_instances , rid_range_entries = range_entries }; // rid_n_type_tables is indexed by run-time ids at run-time = (toString range_id,dl_client_state); where { build_range_entry3 library_instance_i (range_entries,dl_client_state) # (li_memory_areas,dl_client_state) = dl_client_state!cs_library_instances.lis_library_instances.[library_instance_i].li_memory_areas; # range_entries = foldSt add_range_entry li_memory_areas range_entries; = (range_entries,dl_client_state); where { add_range_entry {ma_begin,ma_end} range_entries # range_id_entry = { default_range_id_entry & ride_begin_address = ma_begin , ride_end_address = ma_end , ride_type_table_i = library_instance_i }; = [range_id_entry:range_entries]; }; }; }; app_state_with_proper_names_table f dl_client_state s io // extracting ... #! (main_library_instance_i,dl_client_state) = dl_client_state!cs_main_library_instance_i; #! main_library_instance_i = fromJust main_library_instance_i; #! (names_table,dl_client_state) = acc_names_table main_library_instance_i dl_client_state; #! dl_client_state = {dl_client_state & app_linker_state.namestable = names_table }; // ... extracting #! (x,dl_client_state,s,io) = f dl_client_state s io; // restoring... #! (names_table,dl_client_state) = acc_state (\s=:{namestable} -> (namestable,{s & namestable = {}})) dl_client_state; #! dl_client_state = { dl_client_state & cs_library_instances.lis_library_instances.[main_library_instance_i].li_names_table = names_table }; // ... restoring = (x,dl_client_state,s,io); // ****************************************************************************************************** generate_needed_label_names3 block_i stringtable descriptor_usage_table # s = mapAiSt collect_label descriptor_usage_table ([],[]); = s; where { collect_label _ {bitset,prefix_set_and_string_ptr} (ms,descriptor_module_table) // determine if descriptor is used | not (fst (isBitSetMember bitset block_i)) = (ms,descriptor_module_table); // get descriptor name #! (prefixes,string_offset,_) = determine_prefixes3 prefix_set_and_string_ptr; | length prefixes > 1 = abort "gen_label_names; more than one prefix should be tested"; #! (descriptor_and_module_name,descriptor_module_table) = get_descriptor_and_module_name string_offset stringtable descriptor_module_table; // generate label names with proper prefixes #! l = map (\prefix -> ModuleUnknown (snd descriptor_and_module_name) (gen_label_name True descriptor_and_module_name prefix)) prefixes; = (ms ++ l,descriptor_module_table); }; update_namestable_to_include_recent_type_implementations library_instance_i dl_client_state io // extend available array if necessary #! (teit_n_type_implementations,dl_client_state) = dl_client_state!cs_type_implementation_table.teit_n_type_implementations; #! (li_s_type_available,dl_client_state) = dl_client_state!cs_library_instances.lis_library_instances.[library_instance_i].li_s_type_available; #! dl_client_state = case (teit_n_type_implementations == li_s_type_available) of { True -> dl_client_state; False #! (dl_client_state,li_type_available) = loopAst copy_array_element (dl_client_state,createArray teit_n_type_implementations False) li_s_type_available; #! dl_client_state = { dl_client_state & cs_library_instances.lis_library_instances.[library_instance_i].li_s_type_available = teit_n_type_implementations , cs_library_instances.lis_library_instances.[library_instance_i].li_type_available = li_type_available }; -> dl_client_state; }; // teit_n_type_implementations is valid #! dl_client_state = loopAst enter_type_implementation_if_necessary dl_client_state teit_n_type_implementations; = (dl_client_state,io); where { copy_array_element i (dl_client_state,li_type_available) #! (ith_element,dl_client_state) = dl_client_state!cs_library_instances.lis_library_instances.[library_instance_i].li_type_available.[i]; | True <<- (ith_element) #! li_type_available = { li_type_available & [i] = ith_element }; = (dl_client_state,li_type_available); enter_type_implementation_if_necessary type_implementation_reference dl_client_state #! (type_equivalent_class_available,dl_client_state) = dl_client_state!cs_library_instances.lis_library_instances.[library_instance_i].li_type_available.[type_implementation_reference]; | type_equivalent_class_available // <<- ("daar",library_instance_i,type_implementation_reference,type_equivalent_class_available) // The NamesTable has already been modified for the current type equivalent class. = dl_client_state; #! ({tei_chosen_type_implementation,tei_type_implementations},dl_client_state) = get_type_implementation type_implementation_reference dl_client_state; | isNothing tei_chosen_type_implementation // Type equivalent class has not yet an implementation = dl_client_state; #! (chosen_library_instance_i,chosen_tio_type_reference) = extract_LIT_TypeReference (fromJust tei_chosen_type_implementation); | chosen_library_instance_i == library_instance_i || (isTypeWithoutDefinition chosen_tio_type_reference) // No implementation but current library implements the type = dl_client_state; #! type_implementations_to_redirect = filter (\type_ref -> case type_ref of { (LIT_TypeReference (LibRef library_instance_j) _) -> library_instance_i == library_instance_j; _ -> False; }) tei_type_implementations; | isEmpty type_implementations_to_redirect // A chosen implementation for the type equivalent class but the current library (library_instance_i) has no types // within the type equivalent class. So it can be ignored. = dl_client_state; // The type_implementations_to_redirect belong to type equivalent class having an implementation from another library instance. // If there are more than the library instance has also internal type equivalences. Now the namestable should be adapted to refer // to the type implementation in the other library. // mark type as available #! dl_client_state = { dl_client_state & cs_library_instances.lis_library_instances.[library_instance_i].li_type_available.[type_implementation_reference] = True }; // get label names which implementent the chosen type implementation #! (li_chosen_type_table_i,dl_client_state) = dl_client_state!cs_library_instances.lis_library_instances.[chosen_library_instance_i].li_type_table_i; #! (chosen_type_name,labels_implementing_chosen_type,dl_client_state) = get_type_label_names chosen_tio_type_reference li_chosen_type_table_i dl_client_state; #! (labels_implementing_chosen_type,dl_client_state) = mapSt (lookup_file_n_symbol_n_for_each_label chosen_library_instance_i) labels_implementing_chosen_type dl_client_state; // #! dl_client_state // = AddMessage (Verbose ("Patching NamesTable for '" +++ chosen_type_name +++ "'")) dl_client_state; // get labels for type_implementations_to_redirect #! (_,dl_client_state) = foldSt (redirect_type chosen_library_instance_i) type_implementations_to_redirect (labels_implementing_chosen_type,dl_client_state); = dl_client_state; where { redirect_type chosen_library_instance_i (LIT_TypeReference (LibRef library_instance_i) tio_type_reference) (labels_implementing_chosen_type,dl_client_state) #! (li_type_table_i,dl_client_state) = dl_client_state!cs_library_instances.lis_library_instances.[library_instance_i].li_type_table_i; #! (_,labels_implementing_type,dl_client_state) = get_type_label_names tio_type_reference li_type_table_i dl_client_state; #! dl_client_state = fold2St redirect_type_label labels_implementing_type labels_implementing_chosen_type dl_client_state; = (labels_implementing_chosen_type,dl_client_state); where { redirect_type_label refering_label chosen_label=:(file_n,symbol_n,chosen_label_name) dl_client_state // #! msg // = "> redirect '" +++ refering_label +++ "'<" +++ toString library_instance_i +++ "> to '" // +++ chosen_label_name +++ "'<" +++ toString chosen_library_instance_i +++ ">"; // #! dl_client_state // = AddMessage (Verbose msg) dl_client_state; #! dl_client_state = replaceLabel refering_label library_instance_i file_n symbol_n chosen_label_name dl_client_state; = dl_client_state; }; // redirect_type lookup_file_n_symbol_n_for_each_label chosen_library_instance_i type_label_name dl_client_state #! (maybe_file_n_symbol_n,dl_client_state) = findLabel type_label_name chosen_library_instance_i dl_client_state; | isNothing maybe_file_n_symbol_n = abort ("alal " +++ type_label_name); #! (file_n,symbol_n) = fromJust maybe_file_n_symbol_n; = ((file_n,symbol_n,type_label_name),dl_client_state); extract_LIT_TypeReference (LIT_TypeReference (LibRef library_instance_i) tio_type_reference) = (library_instance_i,tio_type_reference); } }; link_library_instance stringtable descriptor_usage_table block_i id n_addresses disk_library_i (dus_labels,dl_client_state,s,io) #! (stringtable,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_string_table; #! (descriptor_usage_table,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_descriptor_usage_table; #! (library_instance_i,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_disk_id_to_library_instance_i.[disk_library_i]; #! (labels_linked,n_addresses2,labels,dl_client_state) = mapAiSt dus_entry_of_proper_library_instance_and_block descriptor_usage_table (True,0,[],dl_client_state); | n_addresses <> n_addresses2 = abort "link_library_instance; internal error; number of addresses should be the same"; # (dl_client_state,s,io) = case labels_linked of { True // all current library instance labels have already been linked. -> (dl_client_state,s,io); False #! (_,dl_client_state/*,s*/,io) = LoadLibraryInstance_new library_instance_i (Just labels) dl_client_state /*s*/ io; // what types have been linked in under water? #! (li_type_table_i,dl_client_state) = dl_client_state!cs_library_instances.lis_library_instances.[library_instance_i].li_type_table_i; // If a type is eagerly linked i.e. all labels implementing the type have been linked, then // the LoadLibraryInstance_new-application is unnecessary because it is guaranteed that all // type labels have already been linked. // If lazy linking of type is to be supported, the unlinked_labels_of_types might become // handy. // // Note: // An efficiency improving technique might be to separate the actual link/relocation process // from the marking/module offset computation. Then all libraries required to satisfy a // request are linked at once. // #! (dl_client_state/*,s*/,io) // = LoadLibraryInstance_new library_instance_i (Just unlinked_labels_of_types) dl_client_state /*s*/ io; -> (dl_client_state,s,io); }; #! (new_dus_labels,dl_client_state) = mapSt compute_addresses_for_labels_belonging_to_an_implemented_type_equivalent_class3 labels dl_client_state; = (dus_labels ++ new_dus_labels,dl_client_state,s,io); where { dus_entry_of_proper_library_instance_and_block :: .a !.DescriptorUsageEntry !*(.Bool,.Int,u:[w:DusLabel],*DLClientState) -> *(Bool,Int,v:[x:DusLabel],*DLClientState), [w <= x, u <= v]; dus_entry_of_proper_library_instance_and_block _ dus_entry=:{bitset,prefix_set_and_string_ptr,dus_library_instance_nr_on_disk} (labels_linked,ith_address,labels,dl_client_state) #! is_entry_block_member = (fst (isBitSetMember bitset block_i)); | not is_entry_block_member = (labels_linked,ith_address,labels,dl_client_state); | disk_library_i == dus_library_instance_nr_on_disk // same library and in the same block = generate_label_name ith_address labels dl_client_state; #! (prefixes,_,_) = determine_prefixes3 prefix_set_and_string_ptr; = (labels_linked,ith_address + length prefixes,labels,dl_client_state); where { generate_label_name ith_address labels dl_client_state // get descriptor name #! (prefixes,string_offset,_) = determine_prefixes3 prefix_set_and_string_ptr; #! descriptor_module_table = []; // overbodig? #! (descriptor_and_module_name=:(descriptor_name,module_name),descriptor_module_table) = get_descriptor_and_module_name string_offset stringtable descriptor_module_table; #! used_library_instances = NewBitSet 0; // overbodig? #! (dus_implementation=:{dusi_linked},_,dl_client_state) = determine_implementation_for_dus_entry descriptor_name module_name dus_library_instance_nr_on_disk prefix_set_and_string_ptr id used_library_instances dl_client_state; // insert prefixes #! (l,(ith_address,_)) = mapSt generate_dus_label2 prefixes (ith_address,dus_implementation); = (labels_linked && dusi_linked,ith_address,labels ++ l,dl_client_state); where { generate_dus_label2 prefix (ith_address,dus_implementation) #! (dus_label,dus_implementation) = generate_dus_label prefix dus_implementation; #! dus_label = { dus_label & dusl_ith_address = ith_address }; = (dus_label,(inc ith_address,dus_implementation)); } // generate_label_name } // dus_entry_of_proper_library_instance_and_block } LoadLibraryInstance_new :: !.Int !(Maybe [.DusLabel]) !*DLClientState *(IOState *DLServerState) -> *([Int],*DLClientState,*IOState *DLServerState); LoadLibraryInstance_new library_instance_i (Just []) dl_client_state io = ([],dl_client_state,io); LoadLibraryInstance_new library_instance_i labels_to_be_linked dl_client_state io #! (state,dl_client_state) = get_state dl_client_state; #! (q,l,state,dl_client_state,io) = LoadLibraryInstance library_instance_i labels_to_be_linked state dl_client_state io; #! dl_client_state = { dl_client_state & app_linker_state = state }; #! (n_type_implementations,dl_client_state) = dl_client_state!cs_type_implementation_table.teit_n_type_implementations; #! (unlinked_labels_of_types,dl_client_state,_,io) = loopAst (enter_implicitly_linked_type_as_chosen_type_equivalent_class_implementation library_instance_i) ([],dl_client_state,1,io) n_type_implementations; | True <<- ("unlinked:",unlinked_labels_of_types) = (l,dl_client_state,io); enter_implicitly_linked_type_as_chosen_type_equivalent_class_implementation library_instance_i type_implementation_i (unlinked_labels_of_types,dl_client_state,s,io) #! ({tei_type_implementations,tei_chosen_type_implementation},dl_client_state) = dl_client_state!cs_type_implementation_table.teit_type_implementations_a.[type_implementation_i]; | isJust tei_chosen_type_implementation // a type has already been chosen and as a consequence also linked. = (unlinked_labels_of_types,dl_client_state,s,io); // determine whether the current library instance is member of the current type equivalent class (indicated by // library_instance_i) which has not yet an implementation. If the current library instance has multiple types // in the type equivalent class, then it should look also if one of these have already been linked. #! type_implementations = filter (\lit_type_ref -> case lit_type_ref of { (LIT_TypeReference (LibRef offered_library_instance_i) _) -> library_instance_i == offered_library_instance_i; _ -> False; } ) tei_type_implementations; | isEmpty type_implementations // the current library instance does not contain a type from the type equivalent class = (unlinked_labels_of_types,dl_client_state,s,io); // a linked in type equivalent class *without* the chosen type implementation being entered in the type // implementation table. Enter the implicitly chosen implementation type. #! type_implementation = hd type_implementations; #! (implementation_is_available,dl_client_state) = isTypeImplemented type_implementation dl_client_state; | isNothing implementation_is_available // the type has *not* been implicitly linked = (unlinked_labels_of_types,dl_client_state,s,io); #! (type_name,labels_implementing_type) = fromJust implementation_is_available; // ensure that the implementation of the type is loaded completely. #! remaining_unlinked_labels_implementing_type = [ {default_elem & dusl_label_name = label_name , dusl_library_instance_i = library_instance_i , dusl_label_kind = DSL_TYPE_EQUIVALENT_CLASS_IMPLEMENTATION } \\ label_name <- labels_implementing_type ]; #! unlinked_labels_of_types = remaining_unlinked_labels_implementing_type ++ unlinked_labels_of_types; // make the chosen type the implementation type of the current equivalent class. #! (type_found,Just type_implementation_reference,dl_client_state) = findImplementationType type_implementation dl_client_state; | not type_found = abort "enter_implicitly_linked_type_as_chosen_type_equivalent_class_implementation; internal error"; #! dl_client_state = enter_implementation_type_for_equivalence_class2 type_implementation_reference type_implementation dl_client_state; // print change #! msg = "type '" +++ type_name +++ "' has been implicitly linked from library instance #" +++ toString library_instance_i; #! dl_client_state = AddMessage (Verbose msg) dl_client_state; #! dl_client_state = foldSt print_type_labels labels_implementing_type dl_client_state; #! dl_client_state = print_type_implementation_table dl_client_state; = (unlinked_labels_of_types,dl_client_state,s,io); where { print_type_labels label_name dl_client_state #! (Just (file_n,symbol_n),dl_client_state) = findLabel label_name library_instance_i dl_client_state; // #! msg // = label_name +++ "<" +++ toString library_instance_i +++ "> (file_n,symbol_n)" +++ toString file_n +++ "," +++ toString symbol_n; // #! dl_client_state // = AddMessage (Verbose msg) dl_client_state; = dl_client_state; // predefined types without definitions (and DynamicTemp) all come from the main library instance. get_non_predefined_type (LIT_TypeReference _ tio_type_ref) //=:{tio_type_without_definition=Nothing}) = tio_type_ref; check_whether_implementation_is_available label_name dl_client_state #! (Just (file_n,symbol_n),dl_client_state) = findLabel label_name library_instance_i dl_client_state; #! (maybe_address,dl_client_state) = isLabelImplemented file_n symbol_n dl_client_state; = (isJust maybe_address,dl_client_state); }; generate_needed_label_names4 block_i stringtable descriptor_usage_table dl_client_state id # (n_Library_instances,dl_client_state) = dl_client_state!cs_library_instances.lis_n_library_instances; # used_library_instances = NewBitSet n_Library_instances; # s = mapAiSt collect_label descriptor_usage_table ([],[],used_library_instances,dl_client_state); = s; where { collect_label _ {bitset,prefix_set_and_string_ptr,dus_library_instance_nr_on_disk} (ms,descriptor_module_table,used_library_instances,dl_client_state) // each label is guaranteed to have a module and descriptor name because only the references to code from // the graph are collected in a dynamic. Internal code labels do not occur. // determine if descriptor is used | not (fst (isBitSetMember bitset block_i)) = (ms,descriptor_module_table,used_library_instances,dl_client_state); // get descriptor name #! (prefixes,string_offset,_) = determine_prefixes3 prefix_set_and_string_ptr; | length prefixes > 1 = abort "gen_label_names; more than one prefix should be tested"; #! (descriptor_and_module_name=:(descriptor_name,module_name),descriptor_module_table) = get_descriptor_and_module_name string_offset stringtable descriptor_module_table; #! (dus_implementation,used_library_instances,dl_client_state) = determine_implementation_for_dus_entry descriptor_name module_name dus_library_instance_nr_on_disk prefix_set_and_string_ptr id used_library_instances dl_client_state; // insert prefixes #! (l,_) = mapSt generate_dus_label prefixes dus_implementation; = (ms ++ l,descriptor_module_table,used_library_instances,dl_client_state); }; generate_dus_label prefix dusi=:{dusi_descriptor_name,dusi_module_name,dusi_library_instance_i,dusi_linked,dusi_label_kind} #! label_name = gen_label_name True (dusi_descriptor_name,dusi_module_name) prefix; #! dus_label = { default_elem & dusl_label_name = label_name , dusl_library_instance_i = dusi_library_instance_i , dusl_linked = dusi_linked , dusl_label_kind = dusi_label_kind }; = (dus_label,dusi); :: DusImplementation = { dusi_descriptor_name :: !String , dusi_module_name :: !String , dusi_library_instance_i :: !Int // if field below is False then library_instance_i contains/will contain the label_name, otherwise library_instance_i that contains actually contains the label. , dusi_linked :: !Bool // label representing a constructor of a type equivalence member *with* implementation for that class , dusi_label_kind :: !DusLabelKind }; :: DusLabel = { dusl_label_name :: !String // label name valid in dusl_library_instance_i , dusl_library_instance_i :: !Int // if field below is False then library_instance_i contains/will contain the label_name, otherwise library_instance_i that contains actually contains the label. , dusl_linked :: !Bool // label representing a constructor of a type equivalence member *with* implementation for that class , dusl_label_kind :: !DusLabelKind , dusl_ith_address :: !Int , dusl_address :: !Int }; :: DusLabelKind = DSL_EMPTY | DSL_RUNTIME_SYSTEM_LABEL | DSL_TYPE_EQUIVALENT_CLASS_WITH_IMPLEMENTATION | DSL_TYPE_EQUIVALENT_CLASS_IMPLEMENTATION | DSL_CLEAN_LABEL_BUT_NOT_A_TYPE ; instance DefaultElem DusLabel where { default_elem = { dusl_label_name = "" , dusl_library_instance_i = 0 , dusl_linked = False , dusl_label_kind = DSL_EMPTY , dusl_ith_address = -999 , dusl_address = -1 }; }; // convert_constructor_name_to_descriptor_label_name convert_descriptor_name_to_type_constructor_name True constructor_name = "_" +++ constructor_name; convert_descriptor_name_to_type_constructor_name is_record constructor_name = constructor_name; determine_implementation_for_dus_entry descriptor_name module_name dus_library_instance_nr_on_disk prefix_set_and_string_ptr id used_library_instances dl_client_state=:{cs_main_library_instance_i} #! (library_instance_i,dl_client_state) = dl_client_state!cs_dynamic_info.[id].di_disk_id_to_library_instance_i.[dus_library_instance_nr_on_disk]; #! (type_table_i,dl_client_state) = dl_client_state!cs_library_instances.lis_library_instances.[library_instance_i].li_type_table_i; /* ** :: Rec ** = { ... } ** :: Xyz ** = Rec ... ** ** At run-time both the Rec-record constructor and the equally named constructor of type Xyz have the same descriptor. ** The Clean-compiler internally distinguishes between both constructors by prefixing the record constructor with an ** underscore. */ #! descriptor_name_as_used_in_type_table = convert_descriptor_name_to_type_constructor_name (is_record (get_prefix_set prefix_set_and_string_ptr)) descriptor_name; #! (result,dl_client_state) = findTypeUsingConstructorName descriptor_name_as_used_in_type_table module_name type_table_i dl_client_state; | isNothing result <<- ("searching",descriptor_name_as_used_in_type_table, module_name,library_instance_i, result) // label is not a Clean type but e.g. a closure, a function. It *cannot* be a non-Clean label (rts) because they // cannot occur in the datagraph. The implementation // comes from the current library instance except for run-time system label which should always come from // the main-library instance. | module_name == UnderscoreSystemModule # dus_implementation = { dusi_descriptor_name = descriptor_name , dusi_module_name = module_name , dusi_library_instance_i = fromJust cs_main_library_instance_i , dusi_linked = False , dusi_label_kind = DSL_RUNTIME_SYSTEM_LABEL }; = (dus_implementation,used_library_instances,dl_client_state); # dus_implementation = { dusi_descriptor_name = descriptor_name , dusi_module_name = module_name , dusi_library_instance_i = library_instance_i , dusi_linked = False , dusi_label_kind = DSL_CLEAN_LABEL_BUT_NOT_A_TYPE }; = (dus_implementation,used_library_instances,dl_client_state); // Label belongs to a Clean-type # (is_type_equation,type_implementation_ref,dl_client_state) = findImplementationType (LIT_TypeReference (LibRef library_instance_i) (fromJust result)) dl_client_state; | not is_type_equation <<- (descriptor_name,module_name) // a Clean type without equation. The implementation of the type comes from the current library // instance. Possibilities: // (KAN NIET) - rts-label -> use rts-label from main library_instance_i // - otherwise -> use labels from library instance i # dus_implementation = { dusi_descriptor_name = descriptor_name , dusi_module_name = module_name , dusi_library_instance_i = library_instance_i , dusi_linked = False , dusi_label_kind = DSL_RUNTIME_SYSTEM_LABEL }; = (dus_implementation,used_library_instances,dl_client_state); // Get possible implementation type # type_implementation_ref = fromJust type_implementation_ref; # (chosen_implementation_type,dl_client_state) = getImplementationType type_implementation_ref dl_client_state; // Clean type in equivalence class | isNothing chosen_implementation_type // <<- ("^^^",type_implementation_ref) // A Clean type belong to some type equivalence class *without* implementation. The implementation // chosen is that of the current library instance. // # dus_implementation = { dusi_descriptor_name = descriptor_name , dusi_module_name = module_name , dusi_library_instance_i = library_instance_i , dusi_linked = False , dusi_label_kind = DSL_RUNTIME_SYSTEM_LABEL }; = (dus_implementation,used_library_instances,dl_client_state); // a Clean type, member of a type equivalence class and *with* implementation // # (new_module_name,new_library_instance_i,dl_client_state) = case (fromJust chosen_implementation_type) of { (LIT_TypeReference (LibRef library_instance_i) {tio_type_without_definition=Just _}) // an internal type -> (module_name,library_instance_i,dl_client_state); (LIT_TypeReference (LibRef library_instance_i) {tio_tr_module_n}) #! (li_type_table_i,dl_client_state) = dl_client_state!cs_library_instances.lis_library_instances.[library_instance_i].li_type_table_i; #! (tio_module,dl_client_state) = dl_client_state!cs_type_tables.[li_type_table_i].tt_tio_common_defs.[tio_tr_module_n].tio_module; #! (string_table_i,dl_client_state) = dl_client_state!cs_type_tables.[li_type_table_i].tt_type_io_state.tis_string_table; #! module_name = get_name_from_string_table tio_module string_table_i; -> (module_name,library_instance_i,dl_client_state) }; # dus_implementation = { dusi_descriptor_name = descriptor_name , dusi_module_name = new_module_name , dusi_library_instance_i = new_library_instance_i , dusi_linked = True // , dusi_label_kind = DSL_TYPE_EQUIVALENT_CLASS_WITH_IMPLEMENTATION }; = (dus_implementation,used_library_instances,dl_client_state); // send by second or later instance of dynamic rts to first instance of dynamic rts MessageFromSecondOrLaterLinker :: !ProcessSerialNumber [String] !*DLServerState !(IOState !*DLServerState) -> !(!Bool,!ProcessSerialNumber,!*DLServerState, !(IOState !*DLServerState)); MessageFromSecondOrLaterLinker client_id [cmd_line] s=:{application_path} io = AddClient3 client_id [s \\ s <-: (ParseCommandLine cmd_line)] s io; DumpDynamic :: !ProcessSerialNumber [String] !*DLServerState !(IOState !*DLServerState) -> !(!Bool,!ProcessSerialNumber,!*DLServerState, !(IOState !*DLServerState)); DumpDynamic client_id [cmd_line] s=:{application_path} io #! (client_exists,dl_client_state,s) = RemoveFromDLServerState client_id s; | not client_exists = abort "DumpDynamic: client doesnot exist"; # dl_client_state = AddMessage (Verbose "DumpDynamic") dl_client_state; #! dl_client_state = { dl_client_state & do_dump_dynamic = True }; // DLClientState # io = SendAddressToClient client_id "" io; //abort "ok"; # s = AddToDLServerState dl_client_state s; = (False,client_id,s,io); // commandline should look as follows: // libpath commandlineargs // libpath should be an absolute, full path name to an existing .lib file. // the commandlineargs are as is passed to the process h :: !{#{#Char}} -> !{#{#Char}}; h i = i; AddClient3 :: !ProcessSerialNumber [String] !*DLServerState !(IOState !*DLServerState) -> !(!Bool,!ProcessSerialNumber,!*DLServerState, !(IOState !*DLServerState)); AddClient3 client_id [cmd_line:xl] s=:{application_path} io // initialize dl_client_state # state = AddMessage (Verbose "AddClient3") EmptyState; # dl_client_state = { DefaultDLClientState & app_linker_state = state }; # parsed_cmd_line = h { arg \\ arg <- xl }; // console or gui application # (path_file,_) = ExtractPathFileAndExtension parsed_cmd_line.[0]; # open_console_window = path_file.[dec (size path_file)] == 'c'; # ((ok,path),io) = pd_StringToPath parsed_cmd_line.[0] io; # ((error,_),io) = getFileInfo path io; | error == DoesntExist #! msg = "file '" +++ parsed_cmd_line.[0] +++ "' does not exist!" +++ parsed_cmd_line.[0]; = (True,client_id,AddToDLServerState (AddMessage (LinkerError msg) dl_client_state) s,io); #! (current_directory,file_name) = ExtractPathAndFile parsed_cmd_line.[0]; #! new_cmd_line = foldSt (\arg s -> s +++ " " +++ arg) (tl xl) {}; #! (client_started,client_id,client_executable,dl_client_state,s,io) = StartClientApplication3 current_directory file_name open_console_window new_cmd_line dl_client_state s io; #! dl_client_state = { dl_client_state & id = client_id }; | not client_started #! msg = "file '" +++ client_executable +++ "' cannot be started"; = (True,client_id,AddToDLServerState (AddMessage (LinkerError msg) dl_client_state) s,io); # dl_client_state = { dl_client_state & cs_main_library_name = fst (ExtractPathFileAndExtension parsed_cmd_line.[0]) }; #! s = AddToDLServerState dl_client_state s; #! (s,io) = openClientWindow "" client_id s io; = (False,client_id,s,io); where { build_cmdline_in_addclient_format i limit cmd_line | i == limit = ""; = cmd_line.[i] +++ (if (i == (dec limit)) "" " ") +++ (build_cmdline_in_addclient_format (inc i) limit cmd_line); }; get_state dl_client_state=:{app_linker_state} = (app_linker_state,{dl_client_state & app_linker_state = EmptyState}); /* in ReadObject: globally: list of modules names with index init: module_contains_type_redirections := False if contains_type_redirections(module_to_be_read) then module_contains_type_redirections := True create_an_empty_hash_table for each redirected type {module,prefix,constructor} names are used # prefixes = 7, can be less if the redirected type is taken into account # labels = # constructors * # prefixes An hash entry looks as follows: name :: !String redirection_index :: !Int for fast filling of the hash table, the index of the module name is computed which is used in further searching. labelled definition: if hash_table_contains(labelled_definition_name) then isolate_prefix_in_labelled_definition_name select_the_appropriate_prefix_using_the_indirection_table_by_using_the_redirection_index if (isYes the_selected_prefix) then change_definition_into_a_reference_to_the_string_following_Yes else change_the_selected_prefix_in_the_redirection_table_to_labelled_definition_name enter_name_into_the_symbol_table end if end if If the condition is false, then the labelled_definition_name need not be redirected. */ create_module_name_table :: !{#TIO_CommonDefs} !*TypeIOState -> *(.ModuleNameTable,*TypeIOState); create_module_name_table tio_common_defs type_io_state=:{tis_string_table} # module_names = { get_name_from_string_table tio_module_index tis_string_table \\ {tio_module=tio_module_index} <-: tio_common_defs }; # module_name_table = { ModuleNameTable | module_names = module_names , contains_dynamics = NewBitSet (size module_names) }; = (module_name_table,type_io_state); build_redirection_table :: !{#TIO_CommonDefs} !*TypeIOState -> (!*RedirectionTable,ModuleNameTable,!*TypeIOState); build_redirection_table tio_common_defs type_io_state=:{tis_equivalent_type_definitions,tis_string_table} # (module_name_table,type_io_state) = create_module_name_table tio_common_defs type_io_state; # s_redirection_table = mapASt (\{partitions} n_partitions -> size partitions + n_partitions) tis_equivalent_type_definitions 0; # redirection_table = { default_redirection_info \\ _ <- [1..s_redirection_table] }; // TEST ... # (s_redirection_table,redirection_table) = usize redirection_table; # (_,redirection_table,module_name_table) = mapASt equally_named_types tis_equivalent_type_definitions (0,redirection_table,module_name_table); = (redirection_table,module_name_table,type_io_state); where { n_tio_common_defs = size tio_common_defs; equally_named_types {type_name=type_name_index,partitions=equivalent_type_definitions} s // equality on type definitions is defined by the class EqTypes = mapASt equally_considered_definitions equivalent_type_definitions s where { equally_considered_definitions type_definitions (ith_redirection,redirection_table,module_name_table) # (s_redirection_table,redirection_table) = usize redirection_table; # (redirection_info,redirection_table) = replace redirection_table ith_redirection default_redirection_info; # redirection_info = { redirection_info & ri_module_names = NewBitSet n_tio_common_defs }; # (redirection_info,module_name_table) = mapASt insert_indirection type_definitions (redirection_info,module_name_table); # x = collect_constructor_names type_definitions.[0] tio_common_defs # (s_x,x) = usize x; # redirection_info = { redirection_info & ri_constructor_infos = x , ri_s_constructor_infos = s_x }; # redirection_table = { redirection_table & [ith_redirection] = redirection_info }; = (inc ith_redirection,redirection_table,module_name_table); where { insert_indirection {tio_tr_module_n} (redirection_info,module_name_table) # redirection_info = AddBitSetE select_indirection_bitset update_indirection_bitset redirection_info tio_tr_module_n # module_name_table = AddBitSetE (\index module_name_table -> module_name_table!contains_dynamics.map.[index]) (\elem index module_name_table -> { module_name_table & contains_dynamics.map.[index] = elem}) module_name_table tio_tr_module_n = (redirection_info,module_name_table); where { select_indirection_bitset :: !Int !*RedirectionInfo -> (!Int,!*RedirectionInfo); select_indirection_bitset index redirection_info = redirection_info!ri_module_names.map.[index]; update_indirection_bitset :: !Int !Int !*RedirectionInfo -> !*RedirectionInfo; update_indirection_bitset elem index redirection_info = { redirection_info & ri_module_names.map.[index] = elem}; } // insert_indirection collect_constructor_names {tio_tr_module_n,tio_tr_type_def_n} tio_common_defs = case tio_common_defs.[tio_tr_module_n].tio_com_type_defs.[tio_tr_type_def_n].tio_td_rhs of { TIO_AlgType defined_constructors # constructor_infos = { collect_constructor_info tio_ds_index tio_ds_arity \\ {tio_ds_arity,tio_ds_index} <- defined_constructors }; -> constructor_infos; }; where { collect_constructor_info tio_ds_index tio_ds_arity # {tio_cons_symb,tio_cons_type={tio_st_args}} = tio_common_defs.[tio_tr_module_n].tio_com_cons_defs.[tio_ds_index]; #! tio_st_args_strictness = tio_common_defs.[tio_tr_module_n].tio_com_cons_defs.[tio_ds_index].tio_cons_type.tio_st_args_strictness; # is_strict_constructor = has_strict_field 0 tio_ds_arity False tio_st_args_strictness; # constructor_info = { default_constructor_info & ci_name = get_name_from_string_table tio_cons_symb tis_string_table , ci_prefix_set = if is_strict_constructor (StrictConstructor default_strict_constructor) (NonStrictConstructor default_non_strict_constructor) }; = constructor_info; }; // collect_constructor_names } // equally_considered_definitions } // equally_named_types } // build_redirection_table //1.3 //print_type_equivalence :: EquivalentTypeDef (!*State,*TypeIOState,!*{#TIO_CommonDefs}) -> *(!*State,*TypeIOState,!*{#TIO_CommonDefs}); //3.1 print_type_equivalence {type_name,partitions} (state,type_io_state=:{tis_string_table},tio_common_defs) # type_name = get_name_from_string_table type_name tis_string_table; # s = mapAiSt print_partitions partitions (createArray (size partitions) {}); # s = mapAiSt (\i string s -> if (i == 0) string (s +++ ", " +++ string)) s ""; # state = AddMessage (Verbose ("Type equivalence(s) for '" +++ type_name +++ "': {" +++ s +++ "}")) state; = (state,type_io_state,tio_common_defs); where { print_partitions :: !Int !{#TIO_TypeReference} !*{#{#Char}} -> !*{#{#Char}}; print_partitions ith_partition partition s # partition_string = mapAiSt print_partition partition ""; = { s & [ith_partition] = "{" +++ partition_string +++ "}" }; where { print_partition i {tio_tr_module_n} s # module_name_string_offset = tio_common_defs.[tio_tr_module_n].tio_module; # module_name = get_name_from_string_table module_name_string_offset tis_string_table; # s = if (i == 0) module_name (s +++ "," +++ module_name); = s; }; // print_partitions }; // print_type_equivalence read_type_library ls_main_code_type_lib files :== read_type_library_new True ls_main_code_type_lib files; // old behaviour = create_new_names_table set to True read_type_library_new :: !Bool !String *Files -> *(*(Bool,RTI,.{#TIO_CommonDefs},*TypeIOState,*{!NamesTableElement}),*Files); read_type_library_new create_new_names_table ls_main_code_type_lib files | create_new_names_table # (ok,rti,tio_common_defs,type_io_state,names_table,files) = read_type_information (build_type_lib_name ls_main_code_type_lib) create_names_table files; = ((ok,rti,tio_common_defs,type_io_state,names_table),files); // to prevent a names table being created and filled # (ok,rti,tio_common_defs,type_io_state,names_table,files) = read_type_information_new create_new_names_table (build_type_lib_name ls_main_code_type_lib) {} files; = ((ok,rti,tio_common_defs,type_io_state,names_table),files); // computes from the library instances which physical libraries are being used. A physical library occurs at most once // in the LIBRARY STRING TABLE. compute_amount_of_libraries_and_instance_used :: !Int !(Maybe !LibraryInstanceInfo) !*(!Int,*{#Bool},!Int,!*DLClientState) -> *(!Int,*{#Bool},!Int,!*DLClientState); compute_amount_of_libraries_and_instance_used library_instance_i (Just {lii_encoded_library_instance=library_instance_i_non_runtime_index}) s=:(library_instance_max_index,library_used,n_libraries_used,dl_client_state) // library_instance_i_non_runtime_index | library_instance_i < RTID_LIBRARY_INSTANCE_ID_START // || library_instance_i_non_runtime_index == TTUT_UNUSED = s; // compute maximum library *instance* index # library_instance_max_index = max library_instance_max_index library_instance_i_non_runtime_index; // WASlibrary_instance_i; // get type table for current library instance # (type_table_i,dl_client_state) = dl_client_state!cs_library_instances.lis_library_instances.[library_instance_i].li_type_table_i; | library_used.[type_table_i] = (library_instance_max_index,library_used,/* WAS inc*/ n_libraries_used,dl_client_state); # library_used = { library_used & [type_table_i] = True }; = (library_instance_max_index,library_used,inc n_libraries_used,dl_client_state); compute_amount_of_libraries_and_instance_used _ _ s = s; // Types :: LibraryInstance1 = UnusedLibraryInstance | UsedLibraryInstance !Int // disk_library_instance_i | LazyLibraryInstance !Int !Int // lazy_dynamic_index disk_library_instance_i ; :: LibraryInstanceInfo = { lii_used_by_code :: !Bool , lii_used_by_type :: !Bool , lii_encoded_library_instance :: !Int // assigned disk id for the run-time library instance }; instance DefaultElem LibraryInstanceInfo where { default_elem = { lii_used_by_code = False , lii_used_by_type = False , lii_encoded_library_instance = -1 }; }; q :: !*{Maybe LibraryInstanceInfo} -> !*{Maybe LibraryInstanceInfo}; q i = i; :: *EliminateLazyReferencesState = { elrs_predefined_library_instance :: !Int // diskID , elrs_library_instance_to_library_index_index :: !*{#LibraryInstanceToLibraryIndexInfo} , elrs_library_index_to_library_name :: !*{#{#Char}} }; :: LibraryInstanceToLibraryIndexInfo = { litlii_kind :: !LibraryInstanceKind , litlii_index_in_di_library_index_to_library_name :: !Int , litlii_used_by_code :: !Bool , litlii_used_by_type :: !Bool // Just _ = iff litlii_used_by_type == True and litlii_used_by_code == False // Nothing = otherwise , litlii_reference_to_library_instance_in_lazy_dynamic :: !Maybe !LibraryReference }; instance DefaultElem LibraryInstanceToLibraryIndexInfo where { default_elem = { litlii_kind = LIK_Empty , litlii_index_in_di_library_index_to_library_name = 0 , litlii_used_by_code = False , litlii_used_by_type = False , litlii_reference_to_library_instance_in_lazy_dynamic = Nothing }; }; isLazyLibraryInstanceIndex :: LibraryInstanceToLibraryIndexInfo -> !Bool; isLazyLibraryInstanceIndex {litlii_used_by_code=False,litlii_used_by_type=True,litlii_reference_to_library_instance_in_lazy_dynamic=Just _} = True; isLazyLibraryInstanceIndex _ //{litlii_used_by_code=True} = False; :: LibraryReference = { lr_library_instance_i :: !Int // disk library instance index w.r.t. lazy dynamic lr_dynamic_index_i , lr_dynamic_index_i :: !Int // w.r.t. main dynamic }; instance == LibraryReference where { (==) {lr_library_instance_i=lr_library_instance_i1,lr_dynamic_index_i=lr_dynamic_index_i1} {lr_library_instance_i,lr_dynamic_index_i} = lr_library_instance_i1 == lr_library_instance_i && lr_dynamic_index_i1 == lr_dynamic_index_i; }; instance DefaultElem LibraryReference where { default_elem = { lr_library_instance_i = 0 , lr_dynamic_index_i = 0 }; }; //find_code_library_instance :: !Int LibraryInstanceInfo -> (!Maybe !Int); find_code_library_instance i {litlii_used_by_code=True} | i < RTID_DISKID_RENUMBER_START = Nothing; = Just i; find_code_library_instance _ _ = Nothing; getQ dio=:{dio_library_instance_to_library_index} = (dio_library_instance_to_library_index,{dio & dio_library_instance_to_library_index = {}}); // only those references in types whose library instances have not yet been linked in. determine_references_to_type_implementation dii=:{dii_library_instances_a=library_instances_a,dii_lazy_dynamic_references=lazy_dynamic_references,dii_run_time_ids=run_time_ids} dio=:{dio_library_index_to_library_name,dio_convert_rt_type_equivalence_class,dio_type_equivalence_classes} dl_client_state io #! (dio_library_instance_to_library_index,dio) = getQ dio; // Find an arbitrary library instance whose code is used because each library instance can implement the // predefined types. This library instance exists always because there always some code needed to use a // dynamic (except for a data dynamic). # (r,dio_library_instance_to_library_index) = findAieu find_code_library_instance dio_library_instance_to_library_index; | isNothing r = abort "try_to_eliminate_lazy_references_in_types; internal error; the code of at least one library instance should be used by the dynamic being encoded"; // bezig met elrs toevoegen aan de map #! elrs = { elrs_predefined_library_instance = fromJust r , elrs_library_instance_to_library_index_index = dio_library_instance_to_library_index //{ x \\ x <-: dio_library_instance_to_library_index } , elrs_library_index_to_library_name = { x \\ x <-: dio_library_index_to_library_name } }; # (library_instances_a,elrs,dio,dl_client_state,io) = mapASt try_to_eliminate_lazy_reference run_time_ids (library_instances_a,elrs,dio,dl_client_state,io) # ({elrs_library_instance_to_library_index_index,elrs_library_index_to_library_name}) = elrs; # dio = { dio & dio_library_instance_to_library_index = elrs_library_instance_to_library_index_index , dio_library_index_to_library_name = elrs_library_index_to_library_name// { x \\ x <-: elrs_library_index_to_library_name } }; = (dio,dl_client_state,io); where { try_to_eliminate_lazy_reference x=:{rtid_runtime_id=library_instance_i,rtid_type_string,rtid_assigned_disk_id} (library_instances_a,elrs=:{elrs_predefined_library_instance},dio,dl_client_state,io) | ALLOW_LAZY_LIBRARY_REFERENCES False True = abort "try_to_eliminate_lazy_reference; lazy library references (lazy dynamic) unimplemented"; | LLI_IS_MAIN_LIBRARY_INSTANCE library_instance_i <<- ("@@@",rtid_type_string) = abort "process_lazy_type_references; internal error; type reference should be lazy"; #! (type_name,module_name) = get_type_name_and_module_name_from_type_string rtid_type_string; | isPredefinedModuleName module_name // predefined type are defined in the run-time system which is (of course) shared by the // library instances. # elrs = { elrs & elrs_library_instance_to_library_index_index.[rtid_assigned_disk_id].litlii_kind = LIK_LibraryRedirection elrs_predefined_library_instance , elrs_library_instance_to_library_index_index.[rtid_assigned_disk_id].litlii_used_by_type = True }; = (library_instances_a,elrs,dio,dl_client_state,io) // non-predefined type # lazy_dynamic_index = LLI_EXTRACT_LAZY_DYNAMIC_INDEX library_instance_i; # lazy_library_instance_index = LLI_EXTRACT_LAZY_LIBRARY_INSTANCE_INDEX library_instance_i; # (maybe_initialized_lazy_dynamic,dl_client_state) = dl_client_state!cs_lazy_dynamic_index_to_dynamic_id.[lazy_dynamic_index]; = try_to_eliminate_lazy_reference_to_a_nonpredefined_type maybe_initialized_lazy_dynamic type_name module_name lazy_dynamic_index lazy_library_instance_index x (library_instances_a,elrs,dio,dl_client_state,io); try_to_eliminate_lazy_reference_to_a_nonpredefined_type maybe_initialized_lazy_dynamic type_name module_name lazy_dynamic_index lazy_library_instance_index {rtid_runtime_id=library_instance_i,rtid_type_string,rtid_assigned_disk_id} (library_instances_a,elrs=:{elrs_predefined_library_instance},dio,dl_client_state,io) # (Just (disk_lazy_dynamic_index,main_dynamic_index),dl_client_state) = get_dynamic_id lazy_dynamic_index dl_client_state; // lazy(lazy_library_instance_index,disk_lazy_dynamic_index) // GOAL: type_table_i // get library instance of its main dynamic #! (di_library_instance_to_library_index,dl_client_state) = dl_client_state!cs_dynamic_info.[main_dynamic_index].di_library_instance_to_library_index; #! r = findAi (find_lazy_library_reference lazy_library_instance_index disk_lazy_dynamic_index) di_library_instance_to_library_index; | isNothing r // A library instance reference which refers to a library instance of a lazy dynamic (aka a // lazy library reference) when the dynamic was created, has been created as lazy. See also // isLazyLibraryInstanceIndex. Otherwise an internal error is reported. = abort "try_to_eliminate_lazy_reference; internal error; cannot find lazy (?,?)"; // get type table name #! library_index_to_library_name = case di_library_instance_to_library_index.[fromJust r] of { LIK_LazyLibraryInstance {LIK_LazyLibraryInstance | lik_index_in_di_library_index_to_library_name} -> lik_index_in_di_library_index_to_library_name; }; #! (library_name,dl_client_state) = dl_client_state!cs_dynamic_info.[main_dynamic_index].di_library_index_to_library_name.[library_index_to_library_name]; // allocate & load required type table # (type_table_i,dl_client_state) = AddReferenceToTypeTable library_name dl_client_state; # (dl_client_state,io) = LoadTypeTable type_table_i dl_client_state io; # (maybe_tio_type_reference,dl_client_state) = findTypeUsingTypeName type_name module_name type_table_i dl_client_state; | isNothing maybe_tio_type_reference // A type_name and module_name for the given type library must exist. Otherwise an internal // error is reported. = abort "try_to_eliminate_lazy_reference; internal error; cannot find required type"; # tio_type_reference = fromJust maybe_tio_type_reference; # (lit_type_reference,dl_client_state) = case maybe_initialized_lazy_dynamic of { Nothing # lib_ref = LibRefViaLazyDynamic lazy_library_instance_index lazy_dynamic_index type_table_i; # lit_type_reference = LIT_TypeReference lib_ref tio_type_reference; -> (lit_type_reference, dl_client_state); Just rt_dynamic_index #! (rt_library_instance,dl_client_state) = dl_client_state!cs_dynamic_info.[rt_dynamic_index].di_disk_id_to_library_instance_i.[lazy_library_instance_index]; #! lit_type_reference = LIT_TypeReference (LibRef rt_library_instance) tio_type_reference; -> (lit_type_reference,dl_client_state); }; # (found,type_ref,dl_client_state) = findImplementationType lit_type_reference dl_client_state; # maybe_disk_type_equivalent_classes_index = if (not found || isNothing type_ref) Nothing (dio_convert_rt_type_equivalence_class.[fromJust type_ref]); | isNothing maybe_disk_type_equivalent_classes_index // This alternative is taken iff // - the current type i.e. lit_type_reference is *not* a member of some type equivalent class. // - the current type is a member of some *stripped* type equivalent class. A stripped type // equivalent class is to be stored and only contains types which are relevant i.e. used by // the dynamic being created. // Create an new level of indirection by making it a LAZY-entry. #! maybe_disk_main_dynamic_index = findAi (\_ {ldr_id,ldr_lazy_dynamic_index} -> if (ldr_id == main_dynamic_index) (Just ldr_lazy_dynamic_index) Nothing) lazy_dynamic_references; | isNothing maybe_disk_main_dynamic_index // The dynamic being built does not have the required lazy dynamic which is being // referenced from its type. = abort "try_to_eliminate_lazy_reference; internal error; cannot find required lazy dynamic"; #! disk_main_dynamic_index = fromJust maybe_disk_main_dynamic_index #! (index,elrs) = get_library_index library_name elrs; # elrs = { elrs & elrs_library_instance_to_library_index_index.[rtid_assigned_disk_id].litlii_index_in_di_library_index_to_library_name = index , elrs_library_instance_to_library_index_index.[rtid_assigned_disk_id].litlii_used_by_type = True , elrs_library_instance_to_library_index_index.[rtid_assigned_disk_id].litlii_used_by_code = False , elrs_library_instance_to_library_index_index.[rtid_assigned_disk_id].litlii_reference_to_library_instance_in_lazy_dynamic = Just {lr_library_instance_i=fromJust r, lr_dynamic_index_i=disk_main_dynamic_index} }; = (library_instances_a,elrs,dio,dl_client_state,io); // There is a run-time type equivalent class with at least two types to be stored in it and the // current type is also in it. The current type can be replaced by another member of the same // (disk) type equivalent class. #! disk_type_equivalent_classes_index = fromJust maybe_disk_type_equivalent_classes_index; // select an arbitrarily type of the type equivalent class. There is no need for conversion from run-time indices to // disk indices and/or checking for the availability of library instances because it has already been done when the // type equations were collected. #! type = choose_type_from_equivalent_class dio_type_equivalence_classes.[disk_type_equivalent_classes_index]; #! (library_instances_a,elrs,dio,dl_client_state,io) = case type of { LIT_TypeReference (LibRef disk_library_instance) _ # elrs = { elrs & elrs_library_instance_to_library_index_index.[rtid_assigned_disk_id].litlii_kind = LIK_LibraryRedirection disk_library_instance , elrs_library_instance_to_library_index_index.[rtid_assigned_disk_id].litlii_used_by_type = True }; -> (library_instances_a,elrs,dio,dl_client_state,io); LIT_TypeReference (LibRefViaLazyDynamic disk_library_instance lazy_dynamic_index_in_main_dynamic type_library_reference) _ # elrs = { elrs & elrs_library_instance_to_library_index_index.[rtid_assigned_disk_id].litlii_index_in_di_library_index_to_library_name = type_library_reference , elrs_library_instance_to_library_index_index.[rtid_assigned_disk_id].litlii_used_by_type = True , elrs_library_instance_to_library_index_index.[rtid_assigned_disk_id].litlii_used_by_code = False , elrs_library_instance_to_library_index_index.[rtid_assigned_disk_id].litlii_reference_to_library_instance_in_lazy_dynamic = Just {lr_library_instance_i=disk_library_instance, lr_dynamic_index_i=lazy_dynamic_index_in_main_dynamic} }; -> (library_instances_a,elrs,dio,dl_client_state,io); }; = (library_instances_a,elrs,dio,dl_client_state,io); where { choose_type_from_equivalent_class type_equivalent_class // A reference to a non-lazy library instance i.e. a library instance that is *not* a library in instance of // lazy dynamic within the main_dynamic is prefered to a lazy library instance. The latter imposes run-time // overhead when the dynamic is used. #! maybe_type = findAi try_to_find_type_with_library_instance_in_main_dynamic type_equivalent_class; | isJust maybe_type = fromJust maybe_type; # random_member = 0; = type_equivalent_class.[random_member]; where { try_to_find_type_with_library_instance_in_main_dynamic _ type=:(LIT_TypeReference (LibRef _) _) = Just type; try_to_find_type_with_library_instance_in_main_dynamic _ _ = Nothing; }; get_library_index library_name elrs=:{elrs_library_index_to_library_name} # (found,elrs_library_index_to_library_name) = findAieu (\i library_name2 -> if (library_name == library_name2) (Just i) Nothing) elrs_library_index_to_library_name; | isJust found # elrs = { elrs & elrs_library_index_to_library_name = elrs_library_index_to_library_name }; = (fromJust found,elrs); // include the library in table because it has not been included. #! (new_index,new) = extend_array_nu 1 elrs_library_index_to_library_name; #! new = { new & [new_index] = library_name }; # elrs = { elrs & elrs_library_index_to_library_name = new }; = (new_index,elrs); find_lazy_library_reference lazy_library_instance_index disk_lazy_dynamic i (LIK_LazyLibraryInstance { LIK_LazyLibraryInstance | lik_library_instance_i,lik_dynamic_index_i}) | lik_dynamic_index_i == disk_lazy_dynamic && lik_library_instance_i == lazy_library_instance_index = Just i; = Nothing; find_lazy_library_reference lazy_library_instance_index disk_lazy_dynamic i _ = Nothing; } }; // The build_block rt_lazy_dynamic id (defined in _SystemDynamic) have been collected in the LazyDynamicReferences-array by the // conversion function. This functions puts them into a list. determine_used_lazy_dynamics :: !DynamicInfoInput !*DynamicInfoOutput !*DLClientState -> (!*DynamicInfoOutput,!*DLClientState); determine_used_lazy_dynamics dii=:{dii_lazy_dynamic_references=lazy_dynamic_references} dio dl_client_state // determine used lazy dynamics # max_lazy_dynamic_index = mapASt (\{ldr_lazy_dynamic_index} accu -> max ldr_lazy_dynamic_index accu) lazy_dynamic_references (-1); # n_lazy_dynamics = inc max_lazy_dynamic_index; # lazy_dynamics_a = createArray n_lazy_dynamics default_elem; # (lazy_dynamics_a,dl_client_state) = mapASt collect_lazy_dynamic_reference lazy_dynamic_references (lazy_dynamics_a,dl_client_state); # dio = { dio & dio_lazy_dynamics = lazy_dynamics_a }; = (dio,dl_client_state); where { collect_lazy_dynamic_reference {ldr_id,ldr_lazy_dynamic_index} (lazy_dynamics_a,dl_client_state) #! (di_file_name,dl_client_state) = dl_client_state!cs_dynamic_info.[ldr_id].di_file_name; #! lazy_dynamics_a = { lazy_dynamics_a & [ldr_lazy_dynamic_index] = { ldi_runtime_id = ldr_id, ldi_name = di_file_name } }; = (lazy_dynamics_a,dl_client_state); }; :: *DynamicInfoOutput = { // Libraries dio_n_library_instances :: !Int , dio_library_instance_to_library_index :: !*{#LibraryInstanceToLibraryIndexInfo} // indexed by a RunTimeID, index in di_library_index_to_library_name , dio_library_index_to_library_name :: !{#{#Char}} // indexed by index from above array, string reference to {code,type}-library , dio_used_library_instances :: !{LibraryInstance1} // Lazy dynamics , dio_lazy_dynamics :: !{#LazyDynamicInfo} // Type equations , dio_type_equivalence_classes :: !{#{LibraryInstanceTypeReference}} //!{DiskTypeEquivalentClass} , dio_convert_rt_type_equivalence_class :: !{Maybe !Int} // indexed by type_ref from type equivalent class and delivers index in dio_type_equivalence_classes }; :: LazyDynamicInfo = { ldi_runtime_id :: !Int , ldi_name :: !String }; instance DefaultElem LazyDynamicInfo where { default_elem = { ldi_runtime_id = default_elem , ldi_name = default_elem }; }; instance DefaultElemU DynamicInfoOutput where { default_elemU = { // Libraries dio_n_library_instances = 0 , dio_library_instance_to_library_index = {} , dio_library_index_to_library_name = {} , dio_used_library_instances = {} // Lazy dynamics , dio_lazy_dynamics = {} // Type equations , dio_type_equivalence_classes = {} , dio_convert_rt_type_equivalence_class = {} }; }; :: DynamicInfoInput = { dii_library_instances_a :: {Maybe !LibraryInstanceInfo} // used run-time library instances , dii_lazy_dynamic_references :: !{#LazyDynamicReference} // used lazy dynamic by main dynamic , dii_run_time_ids :: !{#RunTimeIDW} // references to types in type component }; // DynamicInfo determine_used_libraries :: !DynamicInfoInput !*DynamicInfoOutput !*DLClientState -> (!*DynamicInfoOutput,!*DLClientState); determine_used_libraries dii=:{dii_library_instances_a=library_instances_a,dii_lazy_dynamic_references=lazy_dynamic_references} dio dl_client_state // create library used # (n_type_tables,dl_client_state) = get_number_of_type_tables dl_client_state; # library_used = createArray n_type_tables False; // determine used type and code libraries # (library_instance_max_index,_,n_libraries_used,dl_client_state) = mapAiSt compute_amount_of_libraries_and_instance_used library_instances_a (0,library_used,0,dl_client_state); # n_library_instances = inc library_instance_max_index; // maps a type_table_i to its index in library_name_a (temp) # library_name_indices = createArray n_type_tables Nothing; // maps a library instance to its library name; LIBRARY INSTANCE TABLE # library_instance_to_library_index_a = createArray n_library_instances default_elem; // indexed by an element from library_instance_to_library_name_a to a library name; LIBRARY STRING TABLE # library_index_to_library_name_a = { "" \\ _ <- [1..n_libraries_used] }; // fill LIBRARY INSTANCE TABLE and LIBRARY STRING TABLE # (_,library_instance_to_library_index_a,library_index_to_library_name_a,_,dl_client_state) = mapAiSt (fill_library_arrays n_libraries_used) library_instances_a (library_name_indices,library_instance_to_library_index_a,library_index_to_library_name_a,0,dl_client_state); // ----------------------------------------------- // Store type equations for all library instances involved // library_instances_a contains the used library instances for the new dynamic being created. Type equations must // be inserted before the first block of the new dynamic will be demanded. These equations are called *eager* type // equations. // # (lis_n_library_instances,dl_client_state) = dl_client_state!cs_library_instances.lis_n_library_instances; // Auxillary array which maps *used* library instances used in the main dynamic i.e. the dynamic being created to encoded // library instances. There are two kinds of library instances: library instances in the main dynamic and library instances // relative to a lazy dynamic of the main dynamic. The algorithm reflects this fact by also creating the array in two steps. // step 1: collect the library instances directly used by the main dynamic #! used_library_instances = createArray lis_n_library_instances UnusedLibraryInstance; #! (used_library_instances,dl_client_state) = mapAiSt determine_the_used_library_instances_of_main_dynamic library_instances_a (used_library_instances,dl_client_state); // step 2: collect the used library instances of lazy dynamics which are used by the main dynamic #! (used_library_instances,dl_client_state) = mapASt determine_the_used_library_instances_within_the_lazy_dynamics_of_the_main_dynamic lazy_dynamic_references (used_library_instances,dl_client_state) # dio = { dio & dio_n_library_instances = n_library_instances , dio_library_instance_to_library_index = library_instance_to_library_index_a , dio_library_index_to_library_name = library_index_to_library_name_a , dio_used_library_instances = used_library_instances }; = (dio,dl_client_state); where { // computes the LIBRARY INSTANCE TABLE in library_instance_to_library_index_a and the LIBRARY STRING TABLE in // library_index_to_library_name_a. // library_instance_i_non_runtime_index fill_library_arrays :: !Int !Int !(Maybe !LibraryInstanceInfo) *(*{Maybe !Int},*{#LibraryInstanceToLibraryIndexInfo},*{#String},.Int,*DLClientState) -> *(*{Maybe Int},*{#LibraryInstanceToLibraryIndexInfo},*{#String},Int,*DLClientState); fill_library_arrays n_libraries_used library_instance_i (Just {lii_used_by_code,lii_used_by_type,lii_encoded_library_instance=library_instance_i_non_runtime_index}) s=:(library_name_indices,library_instance_to_library_index_a,library_index_to_library_name_a,free_library_index_to_library_name_index,dl_client_state) | library_instance_i < RTID_LIBRARY_INSTANCE_ID_START = s; // get type table for current library instance # (type_table_i,dl_client_state) = dl_client_state!cs_library_instances.lis_library_instances.[library_instance_i].li_type_table_i; | isNothing library_name_indices.[type_table_i] // fill library_instance_to_library_index_a with index in library_index_to_library_name_a # library_instance_to_library_index_a = { library_instance_to_library_index_a & [library_instance_i_non_runtime_index] = {default_elem & litlii_index_in_di_library_index_to_library_name = free_library_index_to_library_name_index , litlii_used_by_code = lii_used_by_code , litlii_used_by_type = lii_used_by_type } }; // fill library_index_to_library_name_a # (li_library_name,dl_client_state) = dl_client_state!cs_library_instances.lis_library_instances.[library_instance_i].li_library_name; # library_index_to_library_name_a = { library_index_to_library_name_a & [free_library_index_to_library_name_index] = fromJust li_library_name }; // # library_name_indices = { library_name_indices & [type_table_i] = Just free_library_index_to_library_name_index }; // # free_library_index_to_library_name_index = inc free_library_index_to_library_name_index; = (library_name_indices,library_instance_to_library_index_a,library_index_to_library_name_a,free_library_index_to_library_name_index,dl_client_state) # library_index_to_library_name = fromJust library_name_indices.[type_table_i]; // fill library_instance_to_library_index_a with index in library_index_to_library_name_a # library_instance_to_library_index_a = { library_instance_to_library_index_a & [library_instance_i_non_runtime_index] = {default_elem & litlii_index_in_di_library_index_to_library_name = free_library_index_to_library_name_index , litlii_used_by_code = lii_used_by_code , litlii_used_by_type = lii_used_by_type } }; = (library_name_indices,library_instance_to_library_index_a,library_index_to_library_name_a,free_library_index_to_library_name_index,dl_client_state); fill_library_arrays _ _ _ s = s; // collect used library *code* instances in a set // library_instance_i_non_runtime_index2 determine_the_used_library_instances_of_main_dynamic :: .Int !(Maybe .LibraryInstanceInfo) !*(*{LibraryInstance1},!*DLClientState) -> (*{LibraryInstance1},!*DLClientState); determine_the_used_library_instances_of_main_dynamic library_instance_i (Just {lii_used_by_code=True,lii_encoded_library_instance=library_instance_i_non_runtime_index}) (used_library_instances,dl_client_state) | library_instance_i < RTID_LIBRARY_INSTANCE_ID_START = (used_library_instances,dl_client_state); | False <<- ("$$$") = undef; #! used_library_instances = { used_library_instances & [library_instance_i] = UsedLibraryInstance library_instance_i_non_runtime_index }; = (used_library_instances,dl_client_state); determine_the_used_library_instances_of_main_dynamic _ _ s = s; determine_the_used_library_instances_within_the_lazy_dynamics_of_the_main_dynamic :: !.LazyDynamicReference !*(*{LibraryInstance1},!*DLClientState) -> *(*{LibraryInstance1},*DLClientState); determine_the_used_library_instances_within_the_lazy_dynamics_of_the_main_dynamic {ldr_id,ldr_lazy_dynamic_index} (used_library_instances,dl_client_state) #! (di_disk_id_to_library_instance_i,dl_client_state) = dl_client_state!cs_dynamic_info.[ldr_id].di_disk_id_to_library_instance_i; #! used_library_instances = mapAiSt determine_the_used_library_instances_within_a_lazy_dynamic di_disk_id_to_library_instance_i used_library_instances; = (used_library_instances,dl_client_state); where { determine_the_used_library_instances_within_a_lazy_dynamic disk_library_instance_i library_instance_i used_library_instances | disk_library_instance_i < RTID_DISKID_RENUMBER_START || library_instance_i == TTUT_UNUSED = used_library_instances; | LLI_IS_LAZY_LIBRARY_INSTANCE library_instance_i <<- ("****") = used_library_instances; //abort "determine_the_used_library_instances_within_a_lazy_dynamic: (unimplemented) lazy type reference detected which cannot yet be handled"; #! (kind,used_library_instances) = used_library_instances![library_instance_i]; #! used_library_instances = case kind of { UnusedLibraryInstance #! used_library_instances = { used_library_instances & [library_instance_i] = LazyLibraryInstance ldr_lazy_dynamic_index disk_library_instance_i }; -> used_library_instances; _ // Library instance has already been used. If it is used by an UsedLibraryInstance, // then the dynamic being constructed uses an already constructed block i.e. a block // without build_block of another dynamic and at least some build_blocks. Because at // least one block has been included in the new dynamic, all the disk library instances // have been converted to run-time library instances: there is no need for lazy type // equations. -> used_library_instances; }; = used_library_instances; }; }; determine_references_to_a_library_instance_of_a_lazy_dynamic dii=:{dii_library_instances_a=library_instances_a,dii_lazy_dynamic_references=lazy_dynamic_references} dio=:{dio_n_library_instances=n_library_instances,dio_library_instance_to_library_index=library_instance_to_library_index_a} dl_client_state // A type is represented at run-time by the T_ypeObjectType-type from _SystemDynamic. A type consists of a name, a module_name // and reference to a library instance represented by the RunTimeID-constructor. This constructor has a single argument: a // reference to a library instance. A library instance contains among other things: // - reference to type library i.e. type definition table // - reference to code library i.e. code // // If the library instance is going to be part of the dynamic being created, then that instance provides both the type definition // and its implementation. In this case the library instance is being used by code and by type. // // Otherwise the library instance is used only by type and it can be provided by a lazy dynamic later. This can be encoded by using // the following tuple: // - library instance within that lazy dynamic // - lazy dynamic index w.r.t. the main dynamic // #! lazy_type_references = createArray n_library_instances Nothing; #! (library_instance_to_library_index_a,dl_client_state) = mapAiSt (collect_references_to_a_library_instance_within_a_lazy_dynamic lazy_dynamic_references) library_instances_a (library_instance_to_library_index_a,dl_client_state); #! dio = { dio & dio_library_instance_to_library_index = library_instance_to_library_index_a }; = (dio,dl_client_state); where { // A library instance can be referenced as: // 1. a library instance number in the main dynamic // 2. a library instance number w.r.t. its lazy dynamic number (within the main dynamic) collect_references_to_a_library_instance_within_a_lazy_dynamic :: !{#LazyDynamicReference} !Int !(Maybe LibraryInstanceInfo) (*{#LibraryInstanceToLibraryIndexInfo},!*DLClientState) -> (*{#LibraryInstanceToLibraryIndexInfo},!*DLClientState); collect_references_to_a_library_instance_within_a_lazy_dynamic lazy_dynamic_references rt_library_instance_i (Just {lii_used_by_code=False,lii_used_by_type=True,lii_encoded_library_instance}) (library_instance_to_library_index_a,dl_client_state) // rt_library_instance_i = ith run-time library instance // lii_encoded_library_instance = ith disk library instance in main dynamic (assigned by conversion functions) // Determine to what dynamic, the rt_library_instance_i is associated. The pattern below must always succeed // because all library instances but the main library instance. The result is the run-time lazy dynamic id. #! (Just rt_lazy_dynamic_index,dl_client_state) = dl_client_state!cs_library_instances.lis_library_instances.[rt_library_instance_i].li_dynamic_index; // Determine the disk lazy dynamic id recorded in lazy_dynamic_references-array. If the run-time lazy dynamic index // (rt_lazy_dynamic_index) equals the ldr_id-field, then the ldr_lazy_dynamic_index-field gives the by the graph_to // _string-conversion function assigned disk lazy dynamic index. #! r = findAi (determine_disk_lazy_dynamic_index rt_lazy_dynamic_index) lazy_dynamic_references; | isNothing r // For the time being it is assumed that a lazy type reference always refers to some // type table in a lazy dynamic. This need probably not be so. = abort "!collect_references_to_a_library_instance_within_a_lazy_dynamic: internal error; lazy type references which does not reference to a type table in a lazy dynamic"; // determine library instance on disk #! (di_disk_id_to_library_instance_i,dl_client_state) = dl_client_state!cs_dynamic_info.[rt_lazy_dynamic_index].di_disk_id_to_library_instance_i; #! maybe_disk_library_instance_i = findAi determine_disk_library_instance_i di_disk_id_to_library_instance_i | isNothing maybe_disk_library_instance_i // For the time being it is assumed that each disk_library_instance is mapped onto a (valid) // run-time library instance. = abort "collect_references_to_a_library_instance_within_a_lazy_dynamic; internal error"; #! lr = { default_elem & lr_library_instance_i = fromJust maybe_disk_library_instance_i , lr_dynamic_index_i = fromJust r }; #! library_instance_to_library_index_a = { library_instance_to_library_index_a & [lii_encoded_library_instance].litlii_reference_to_library_instance_in_lazy_dynamic = Just lr }; = (library_instance_to_library_index_a,dl_client_state) where { determine_disk_lazy_dynamic_index rt_lazy_dynamic_index _ {ldr_id,ldr_lazy_dynamic_index} | ldr_id == rt_lazy_dynamic_index = Just ldr_lazy_dynamic_index; = Nothing; determine_disk_library_instance_i disk_library_instance_j rt_library_instance_j | rt_library_instance_i == rt_library_instance_j = Just disk_library_instance_j; = Nothing; }; collect_references_to_a_library_instance_within_a_lazy_dynamic _ rt_library_instance_i x s // The library instance is unused (x=:Nothing) by the main dynamic or at least used by code (x=:Just _) of the main // dynamic. The former is ignored because it doesn't reappear in the dynamic. The latter means that if there is a // reference from the type component of the main dynamic, then . = s; }; find_library_string_index library_name library_names # (found,library_names) = findAieu (\i library_name2 -> if (library_name == library_name2) (Just i) Nothing) library_names; | isJust found = (fromJust found,library_names); # (new_library_name_index,library_names) = extend_array_nu 1 library_names; # library_names = { library_names & [new_library_name_index] = library_name }; = (new_library_name_index,library_names); determine_used_type_equations :: !DynamicInfoInput !*DynamicInfoOutput !*DLClientState -> (!*DynamicInfoOutput,!*DLClientState); determine_used_type_equations dii=:{dii_lazy_dynamic_references} dio=:{dio_lazy_dynamics,dio_used_library_instances=used_library_instances,dio_library_index_to_library_name} dl_client_state // Compute the type equations to be stored in the dynamic. The fixed avalailable types are skipped because they // are automatically inserted each time a new library is added. #! ( n_fixed_available_types,dl_client_state) = dl_client_state!cs_n_fixed_available_types; #! (n_type_equivalent_classes,dl_client_state) = dl_client_state!cs_type_implementation_table.teit_n_type_implementations #! n_fixed_available_types = if (isNothing n_fixed_available_types) 0 (fromJust n_fixed_available_types); #! dio_convert_rt_type_equivalence_class = createArray n_type_equivalent_classes Nothing; #! dio_library_index_to_library_name = { name \\ name <-: dio_library_index_to_library_name }; #! (_,di_disk_type_equivalent_classes,dio_convert_rt_type_equivalence_class,dio_library_index_to_library_name,dl_client_state) = foldSt collect_type_equation [n_fixed_available_types..(dec n_type_equivalent_classes)] (0,[],dio_convert_rt_type_equivalence_class,dio_library_index_to_library_name,dl_client_state) # dio = { dio & dio_library_index_to_library_name = dio_library_index_to_library_name // type equations , dio_type_equivalence_classes = { { t \\ t <- reverse x } \\ x <- di_disk_type_equivalent_classes } , dio_convert_rt_type_equivalence_class = dio_convert_rt_type_equivalence_class }; = (dio,dl_client_state); where { collect_type_equation type_implementation_table_ref s=:(i,collected_type_equations,dio_convert_rt_type_equivalence_class,dio_library_index_to_library_name,dl_client_state) #! (tei_type_implementations,dl_client_state) = dl_client_state!cs_type_implementation_table.teit_type_implementations_a.[type_implementation_table_ref].tei_type_implementations; #! (converted,dio_library_index_to_library_name,dl_client_state) = foldSt convert_rt_id_to_disk_id tei_type_implementations ([],dio_library_index_to_library_name,dl_client_state); | length converted < 2 = (i,collected_type_equations,dio_convert_rt_type_equivalence_class,dio_library_index_to_library_name,dl_client_state); # dio_convert_rt_type_equivalence_class = { dio_convert_rt_type_equivalence_class & [type_implementation_table_ref] = Just i }; = (inc i,[converted:collected_type_equations],dio_convert_rt_type_equivalence_class,dio_library_index_to_library_name,dl_client_state); where { convert_rt_id_to_disk_id (LIT_TypeReference (LibRef library_instance_i) tio_type_ref) (list,dio_library_index_to_library_name,dl_client_state) # (list,dio_library_index_to_library_name,dl_client_state) = case used_library_instances.[library_instance_i] of { UnusedLibraryInstance -> (list,dio_library_index_to_library_name,dl_client_state); UsedLibraryInstance disk_library_instance_i -> ([LIT_TypeReference (LibRef disk_library_instance_i) tio_type_ref : list],dio_library_index_to_library_name,dl_client_state); LazyLibraryInstance lazy_dynamic_index disk_library_instance_i #! (Just library_name,dl_client_state) = dl_client_state!cs_library_instances.lis_library_instances.[library_instance_i].li_library_name; #! (library_index,dio_library_index_to_library_name) = find_library_string_index library_name dio_library_index_to_library_name; #! type_library_reference = library_index; -> ([LIT_TypeReference (LibRefViaLazyDynamic disk_library_instance_i lazy_dynamic_index type_library_reference) tio_type_ref : list],dio_library_index_to_library_name,dl_client_state); }; = (list,dio_library_index_to_library_name,dl_client_state); convert_rt_id_to_disk_id (LIT_TypeReference (LibRefViaLazyDynamic disk_library_instance rt_dynamic_index type_table_i) tio_type_ref) (list,dio_library_index_to_library_name,dl_client_state) | ALLOW_LAZY_LIBRARY_REFERENCES False True = abort "convert_rt_id_to_disk_id; lazy library references (lazy dynamic) unimplemented"; // determine the main dynamic of the lazy dynamic # (Just (disk_lazy_dynamic_index,rt_main_dynamic_index),dl_client_state) = get_dynamic_id rt_dynamic_index dl_client_state; // determine whether the lazy dynamic is included in the dynamic to be written # maybe_disk_dynamic_index_within_main_dynamic = findAi (\_ {ldr_id,ldr_lazy_dynamic_index} -> if (ldr_id == rt_main_dynamic_index) (Just ldr_lazy_dynamic_index) Nothing) dii_lazy_dynamic_references; | isNothing maybe_disk_dynamic_index_within_main_dynamic // type reference does not belong to a lazy dynamic of the main dynamic being created. Ignore it. = (list,dio_library_index_to_library_name,dl_client_state); // determine the lazy library instance within the main dynamic of the lazy dynamic. # lazy_id = {lr_library_instance_i=disk_library_instance,lr_dynamic_index_i=disk_lazy_dynamic_index}; # (di_library_instance_to_library_index,dl_client_state) = dl_client_state!cs_dynamic_info.[rt_main_dynamic_index].di_library_instance_to_library_index; # r = findAi (find_library_instance_i_for_lazy_reference lazy_id) di_library_instance_to_library_index; | isNothing r = (list,dio_library_index_to_library_name,dl_client_state); # (tt_name,dl_client_state) = dl_client_state!cs_type_tables.[type_table_i].tt_name; # (library_index,dio_library_index_to_library_name) = find_library_string_index tt_name dio_library_index_to_library_name; # type_library_reference = library_index; # converted_type = LIT_TypeReference (LibRefViaLazyDynamic (fromJust r) (fromJust maybe_disk_dynamic_index_within_main_dynamic) type_library_reference) tio_type_ref; = ([ converted_type : list],dio_library_index_to_library_name,dl_client_state); where { find_library_instance_i_for_lazy_reference searched_lazy_id disk_library_instance_i (LIK_LazyLibraryInstance {LIK_LazyLibraryInstance | lik_library_instance_i,lik_dynamic_index_i}) #! lazy_id = {lr_library_instance_i=lik_library_instance_i,lr_dynamic_index_i=lik_dynamic_index_i} = if (searched_lazy_id == lazy_id) (Just disk_library_instance_i) Nothing; find_library_instance_i_for_lazy_reference searched_lazy_id disk_library_instance_i _ = Nothing; }; }; }; // send to get extra dynamic rts information GetDynamicRTSInfo :: !ProcessSerialNumber [String] !*DLServerState !(IOState !*DLServerState) -> !(!Bool,!ProcessSerialNumber,!*DLServerState, !(IOState !*DLServerState)); GetDynamicRTSInfo client_id [arg] s io #! (client_exists,dl_client_state,s) = RemoveFromDLServerState client_id s; | F "GetDynamicRTSInfo" not client_exists = internal_error "GetDynamicRTSInfo (internal error): client not registered" client_id dl_client_state s io; #! (dl_client_state) = AddMessage (Verbose "GetDynamicRTSInfo") dl_client_state; # dii = decode_arg_block arg; # (dio,dl_client_state) = determine_used_lazy_dynamics dii default_elemU dl_client_state; # (dio,dl_client_state) = determine_used_libraries dii dio dl_client_state; # (dio,dl_client_state) = determine_used_type_equations dii dio dl_client_state; # (dio,dl_client_state) = determine_references_to_a_library_instance_of_a_lazy_dynamic dii dio dl_client_state; # (dio,dl_client_state,io) = determine_references_to_type_implementation dii dio dl_client_state io; // ----------------------------------------------- // UITPAKKEN #! (lazy_dynamics_a,dio) = dio!dio_lazy_dynamics; #! (di_disk_type_equivalent_classes,dio) = dio!dio_type_equivalence_classes; #! (library_instance_to_library_index_a,dio) = get dio; #! (library_index_to_library_name_a,dio) = dio!dio_library_index_to_library_name; #! di = { default_dynamic_info & di_library_instance_to_library_index = { convert_litlii_to_library_instance_kind library_instance \\ library_instance <-: library_instance_to_library_index_a } // LIBRARY INSTANCE TABLE , di_library_index_to_library_name = library_index_to_library_name_a // LIBRARY STRING TABLE , di_disk_type_equivalent_classes = di_disk_type_equivalent_classes , di_lazy_dynamics_a = { ldi_name \\ {ldi_name} <-: lazy_dynamics_a } }; #! io = SendAddressToClient client_id (encode di) io; # ok = True = (not ok,client_id,AddToDLServerState dl_client_state s,/*KillClient3 client_id ok*/ io); where { get dio=:{dio_library_instance_to_library_index} = (dio_library_instance_to_library_index,{dio & dio_library_instance_to_library_index = {} }); convert_litlii_to_library_instance_kind {litlii_kind=LIK_LibraryRedirection disk_library_instance_i} = LIK_LibraryRedirection disk_library_instance_i; convert_litlii_to_library_instance_kind litlii=:{litlii_index_in_di_library_index_to_library_name,litlii_reference_to_library_instance_in_lazy_dynamic} | isLazyLibraryInstanceIndex litlii # {lr_library_instance_i,lr_dynamic_index_i} = fromJust litlii_reference_to_library_instance_in_lazy_dynamic; # lik_lazy_library_instance = { LIK_LazyLibraryInstance | lik_index_in_di_library_index_to_library_name = litlii_index_in_di_library_index_to_library_name , lik_library_instance_i = lr_library_instance_i , lik_dynamic_index_i = lr_dynamic_index_i }; = LIK_LazyLibraryInstance lik_lazy_library_instance; # lik_library_instance = { LIK_LibraryInstance | lik_index_in_di_library_index_to_library_name = litlii_index_in_di_library_index_to_library_name}; = LIK_LibraryInstance lik_library_instance; decode_arg_block :: !String -> !DynamicInfoInput; decode_arg_block arg_block # (library_instances_a,j) = help_type_checker2 (from_string 0 arg_block); /// maps diskids to library_instances # library_instances_a = q { if (x == ~1) Nothing (Just { default_elem & lii_used_by_code = IS_CODE_LIBRARY_INSTANCE x , lii_used_by_type = IS_TYPE_LIBRARY_INSTANCE x , lii_encoded_library_instance = GET_LIBRARY_INSTANCE_I x }) \\ x <-: library_instances_a }; # (lazy_dynamic_references,k) = (from_string j arg_block); # (run_time_ids,l) = (from_string k arg_block); # dii = { dii_library_instances_a = library_instances_a , dii_lazy_dynamic_references = lazy_dynamic_references , dii_run_time_ids = run_time_ids }; = dii; where { help_type_checker2 :: (!{#Int},!Int) -> (!{#Int},!Int); help_type_checker2 i = i; }; } // HEADER // - version // - offset/size of tables e.g. string table, DiskID (or MediaID) table // // STRING TABLE // each string is zero-terminated. // // DISK ID TABLE (or MEDIA ID TABLE) // array of offsets in the string table. An offset refers to a complete path // name. In the future this may also be network addresses. The table is indexed // by the parameter of the DiskID-constructor // // For data dynamics (external) type information is stored here. // // TODO (for writing a dynamic): // - The encoded DISK ID-table is returned to the application by the GetDynamicRTSInfo // function and stored in the dynamic. // - RunTimeID ---> DiskID which is similar to the ModuleID-case. // - dumpDynamic should be able to display the extended format // TODO (reading a dynamic): // - DiskID ---> RunTimeID by generating a table which is indexed by a DiskID and then // delivers the RunTimeID. So DiskID occur only in encoded dynamics. The RunTimeID // is the index in type_table (cs_type_tables-field of DLClientState-record). // TODO (type checking) // - if type names match i.e. type names are equal, the following information is used // to identify the proper type definition: // * type name // * referencing module name (not *defining* module name due to separate compilation) // * ModuleID/RunTimeID. A ModuleID is converted to a RunTimeID. The RunTimeID is then // used to identify the proper type table. The dynamic rts has to check the types. resolve_overloading :: !{#Char} -> !{#Char}; resolve_overloading i = i; resolve_overloading2 :: [TypeReference] -> [TypeReference]; resolve_overloading2 i = i; //import StdDynamicLowLevelInterface; instance GetTypeTableIndex LibraryID where { get_type_table_index (Address address) ms = get_type_table_index address ms; get_type_table_index (Number type_table_i) _ = Just type_table_i }; convert_to_library_instance_type_reference /*(LibRef library_instance_i)*/ lib_ref (TypeTableTypeReference type_table_i tio_type_ref) = LIT_TypeReference lib_ref tio_type_ref; // Task: // 1. checks type definitions in the 1st-arg list // 2. if all type defs checks succeed, then these type (and the types they depend upon) are entered into the type implementation table CheckAndEnterType :: [.TypeReference] (!Maybe !Int) !*DLClientState *(IOState DLServerState) -> *(Bool,*DLClientState,*IOState DLServerState); CheckAndEnterType l library_instance_i_implements_type_equivalence_class dl_client_state io /* for each pair of types: - replace Address by Number if necessary - apply equal_types to both types if type definitions are equivalent then continue with next pair else quit changes to equal_types: - two self-contained tio_common_defs; may require extracting info from type_io_state - a general type check state */ // pass 1: establish equivalences # (type_defs_are_equivalent,equivalent_type_defs,dl_client_state,io) = foldSt check_type_pair l (True,[],dl_client_state,io); # dl_client_state = case (type_defs_are_equivalent && not (isEmpty equivalent_type_defs)) of { True // pass 2: generate type equations # dl_client_state = foldSt generate_type_equations equivalent_type_defs dl_client_state; // print results # dl_client_state = print_type_implementation_table dl_client_state; -> dl_client_state; _ -> dl_client_state; }; = (type_defs_are_equivalent,dl_client_state,io); where { check_type_pair {tr_type_name,tr_module_name1,tr_module_name2,tr_library1,tr_library2} (True,equivalent_types,dl_client_state,io) // build type references # (library_instance_i1,rt_type_reference1,dl_client_state,io) = create_type_reference tr_type_name tr_module_name1 tr_library1 dl_client_state io; # (library_instance_i2,rt_type_reference2,dl_client_state,io) = create_type_reference tr_type_name tr_module_name2 tr_library2 dl_client_state io; // check type definitions # (type_tables,dl_client_state) = get_type_tables dl_client_state; # (ets,dl_client_state) = get_ets dl_client_state; # (equivalent_type_defs,type_tables,ets) = equal_type_defs rt_type_reference1 rt_type_reference2 type_tables ets; # (ets_proven_type_equivalences,ets) = ets!ets_proven_type_equivalences; # dl_client_state = { dl_client_state & cs_type_tables = type_tables , cs_intra_type_equalities = ets }; | library_instance_i1 == library_instance_i2 = (equivalent_type_defs,equivalent_types,dl_client_state,io); // print result #! type1 = tr_module_name1 +++ toString rt_type_reference1; #! type2 = tr_module_name2 +++ toString rt_type_reference2; #! (dl_client_state) = AddMessage (Verbose (tr_type_name +++ ": " +++ type1 +++ (if equivalent_type_defs " == " " <> ") +++ type2 )) dl_client_state; # equivalent_type = (convert_to_library_instance_type_reference library_instance_i1 rt_type_reference1, convert_to_library_instance_type_reference library_instance_i2 rt_type_reference2); = (equivalent_type_defs,[equivalent_type:equivalent_types],dl_client_state,io); check_type_pair _ s = s; generate_type_equations (LIT_TypeReference lr_left tio_type_ref_left,LIT_TypeReference lr_right tio_type_ref_right) dl_client_state // get types table for left and right types of the above tuple # (type_table_left_i,dl_client_state) = case lr_left of { (LibRef library_instance_left_i) -> dl_client_state!cs_library_instances.lis_library_instances.[library_instance_left_i].li_type_table_i; (LibRefViaLazyDynamic _ _ type_table_left_i) -> (type_table_left_i,dl_client_state); }; # (type_table_right_i,dl_client_state) = case lr_right of { (LibRef library_instance_right_i) -> dl_client_state!cs_library_instances.lis_library_instances.[library_instance_right_i].li_type_table_i; (LibRefViaLazyDynamic _ _ type_table_right_i) -> (type_table_right_i,dl_client_state); }; // collect types # type_left = TypeTableTypeReference type_table_left_i tio_type_ref_left; # type_right = TypeTableTypeReference type_table_right_i tio_type_ref_right; # (type_tables,dl_client_state) = get_type_tables dl_client_state; # (cts=:{cts_type_dependencies,cts_type_tables=type_tables}) = collect_types type_left type_right {default_collect_types_state & cts_type_tables = type_tables}; | True <<- ("cts_type_dependencies",length cts_type_dependencies) # dl_client_state = { dl_client_state & cs_type_tables = type_tables }; # dl_client_state = foldSt add_type_implementation cts_type_dependencies dl_client_state; = dl_client_state; where { // TIO_TypeReference add_type_implementation (tio_type_ref_left,tio_type_ref_right) dl_client_state # left_library_instance_type_ref = LIT_TypeReference lr_left tio_type_ref_left; # right_library_instance_type_ref = LIT_TypeReference lr_right tio_type_ref_right; # (_,dl_client_state) = enter_type_equation left_library_instance_type_ref right_library_instance_type_ref dl_client_state; = dl_client_state; }; //isTypeWithoutDefinition }; CheckTypeDefinitions :: !ProcessSerialNumber [String] !*DLServerState !(IOState !*DLServerState) -> !(!Bool,!ProcessSerialNumber,!*DLServerState, !(IOState !*DLServerState)); CheckTypeDefinitions client_id [arg] s io #! (client_exists,dl_client_state,s) = RemoveFromDLServerState client_id s; | F "CheckTypeDefinitions" not client_exists = internal_error "CheckTypeDefinitions (internal error): client not registered" client_id dl_client_state s io; # l = resolve_overloading2 (decode (resolve_overloading arg /* { c \\ c <-: arg}*/ )); #! (dl_client_state) = AddMessage (Verbose ("CheckTypeDefinitions" +++ toString (length l))) dl_client_state; /* for each pair of types: - replace Address by Number if necessary - apply equal_types to both types if type definitions are equivalent then continue with next pair else quit changes to equal_types: - two self-contained tio_common_defs; may require extracting info from type_io_state - a general type check state */ #! (type_defs_are_equivalent,dl_client_state,io) = CheckAndEnterType l Nothing dl_client_state io; #! io = SendAddressToClient client_id (encode type_defs_are_equivalent) io; # ok = True = (not ok,client_id,AddToDLServerState dl_client_state s,/*KillClient3 client_id ok*/ io); instance toString TypeTableTypeReference where { toString (TypeTableTypeReference type_table_i _) = " <" +++ toString type_table_i +++ ">"; }; import type_io_equal_types; class GetLibraryInstanceIndex a :: a !*DLClientState -> (!Int,!*DLClientState); instance GetLibraryInstanceIndex LibraryID where { GetLibraryInstanceIndex (Address address) dl_client_state = GetLibraryInstanceIndex address dl_client_state; GetLibraryInstanceIndex (Number library_instance_i) dl_client_state = (library_instance_i,dl_client_state); }; instance GetLibraryInstanceIndex Int where { GetLibraryInstanceIndex address dl_client_state # (lis_n_library_instances,dl_client_state) = dl_client_state!cs_library_instances.lis_n_library_instances # (result,dl_client_state) = findAst find_library_instance dl_client_state lis_n_library_instances; | isJust result = (fromJust result,dl_client_state); = abort ("GetLibraryInstanceIndex Int; unknown address: " +++ toString address); where { find_library_instance library_instance_i dl_client_state #! (li_memory_areas,dl_client_state) = dl_client_state!cs_library_instances.lis_library_instances.[library_instance_i].li_memory_areas; #! li_memory_areas = filter (\{ma_begin,ma_end} -> between ma_begin address ma_end) li_memory_areas; | isEmpty li_memory_areas = (Nothing,dl_client_state); = (Just library_instance_i,dl_client_state); } }; // predefined are treated specially. but there should be distinguished between version numbers // create_type_reference (IOState(DLServerState),LibraryID) :: .{#Char} !{#.Char} LibraryID *DLClientState *(IOState DLServerState) -> *(.RTTypeReference,*DLClientState,*IOState DLServerState); create_type_reference tr_type_name tr_module_name tr_library dl_client_state io # (library_instance_i,dl_client_state) = GetLibraryInstanceIndex tr_library dl_client_state # (type_table_i,library_instance_i,dl_client_state,io) = case (LLI_IS_MAIN_LIBRARY_INSTANCE library_instance_i) of { True # (type_table_i,dl_client_state) = dl_client_state!cs_library_instances.lis_library_instances.[library_instance_i].li_type_table_i; -> (type_table_i,LibRef library_instance_i,dl_client_state,io); _ // A lazy reference has been detected. Such a reference consists of: // - lazy dynamic index // - lazy library instance index # lazy_dynamic_index = LLI_EXTRACT_LAZY_DYNAMIC_INDEX library_instance_i; # lazy_library_instance_index = LLI_EXTRACT_LAZY_LIBRARY_INSTANCE_INDEX library_instance_i; # (maybe_initialized_lazy_dynamic,dl_client_state) = dl_client_state!cs_lazy_dynamic_index_to_dynamic_id.[lazy_dynamic_index]; | isJust maybe_initialized_lazy_dynamic // the dynamic refered to by the lazy reference has been initialized, so the // lazy reference can be dereferenced. # lazy_dynamic_i = fromJust maybe_initialized_lazy_dynamic; # (library_instance_i,dl_client_state) = dl_client_state!cs_dynamic_info.[lazy_dynamic_i].di_disk_id_to_library_instance_i.[lazy_library_instance_index]; # (type_table_i,dl_client_state) = dl_client_state!cs_library_instances.lis_library_instances.[library_instance_i].li_type_table_i; -> (type_table_i,LibRef library_instance_i,dl_client_state,io); // Using the index of the main dynamic which contains the lazy dynamic, the library // The main dynamic index is the index of the dynamic containing the // lazy dynamic. # (Just (disk_lazy_dynamic_index,main_dynamic_index),dl_client_state) = get_dynamic_id lazy_dynamic_index dl_client_state; # (library_instance_kind,dl_client_state) = dl_client_state!cs_dynamic_info.[main_dynamic_index].di_library_instance_to_library_index.[lazy_library_instance_index]; # (library_name,dl_client_state) = case library_instance_kind of { LIK_LazyLibraryInstance {LIK_LazyLibraryInstance | lik_index_in_di_library_index_to_library_name=library_name_index} # (library_name,dl_client_state) = dl_client_state!cs_dynamic_info.[main_dynamic_index].di_library_index_to_library_name.[library_name_index]; -> (library_name,dl_client_state); _ // The current *lazy* type reference should refer to entry in the // library instance table reflecting this fact. -> abort "create_type_reference: internal error"; }; // allocate & load required type table # (type_table_i,dl_client_state) = AddReferenceToTypeTable library_name dl_client_state; # (dl_client_state,io) = LoadTypeTable type_table_i dl_client_state io; # lib_ref_via_lazy_dynamic = LibRefViaLazyDynamic lazy_library_instance_index lazy_dynamic_index type_table_i -> (type_table_i,lib_ref_via_lazy_dynamic,dl_client_state,io); }; // ensure required type table is loaded # (dl_client_state,io) = case library_instance_i of { (LibRef library_instance_i) -> LoadLibraryInstanceTypeTable library_instance_i type_table_i dl_client_state io; _ -> (dl_client_state,io); }; # (type_tables,dl_client_state) = get_type_tables dl_client_state; # (maybe_tio_type_reference,type_tables) = findTypeUsingTypeName tr_type_name tr_module_name type_table_i type_tables; # dl_client_state = { dl_client_state & cs_type_tables = type_tables }; # q = TypeTableTypeReference type_table_i (fromJust maybe_tio_type_reference); = (library_instance_i,q,dl_client_state,io); where { lookup_defining_module type_table_i tis_string_table tio_common_def_i dl_client_state # (module_name_index,dl_client_state) = dl_client_state!cs_type_tables.[type_table_i].tt_tio_common_defs.[tio_common_def_i].tio_module; # module_name = get_name_from_string_table module_name_index tis_string_table; | module_name <> tr_module_name = (Nothing,dl_client_state); # (tio_com_type_defs,dl_client_state) = dl_client_state!cs_type_tables.[type_table_i].tt_tio_common_defs.[tio_common_def_i].tio_com_type_defs; # maybe_type_name = findAi lookup_type_name tio_com_type_defs; | isNothing maybe_type_name = abort "create_type_reference: interal error; defining module not found"; = (maybe_type_name,dl_client_state) where { lookup_type_name tio_com_type_def_i {tio_td_name} # type_name = get_name_from_string_table tio_td_name tis_string_table; | type_name <> tr_type_name = Nothing; # rt_type_reference = { default_elem & tio_tr_module_n = tio_common_def_i , tio_tr_type_def_n = tio_com_type_def_i } | F ("****************" +++ type_name +++ " - " +++ toString type_table_i +++ " - " +++ toString tio_common_def_i +++ " - " +++ toString tio_com_type_def_i ) True = Just rt_type_reference; }; }; LoadLibraryInstanceTypeTable library_instance_i given_type_table_i dl_client_state=:{cs_main_library_instance_i=xx,do_dump_dynamic} io // first call with library_instance_i; load type table for current instance, if necessary. The if can be omitted // after it turns out, the if-holds always. #! (li_type_table_i,dl_client_state) = dl_client_state!cs_library_instances.lis_library_instances.[library_instance_i].li_type_table_i; #! (dl_client_state,io) = LoadTypeTable (if (li_type_table_i == given_type_table_i) li_type_table_i (abort "aanname mis")) dl_client_state io; #! (li_initial_types_equivalences_entered,dl_client_state) = dl_client_state!cs_library_instances.lis_library_instances.[library_instance_i].li_initial_types_equivalences_entered; | li_initial_types_equivalences_entered // The type table has already been loaded and the initial type equivalences have already // been established at the first call with the current library_instance_i. = (dl_client_state,io); // mark it #! dl_client_state = { dl_client_state & cs_library_instances.lis_library_instances.[library_instance_i].li_initial_types_equivalences_entered = True }; // type available ... #! (tt_n_tio_common_defs,dl_client_state) = dl_client_state!cs_type_tables.[li_type_table_i].tt_n_tio_common_defs; # (n_library_instances,dl_client_state) = dl_client_state!cs_library_instances.lis_n_library_instances; # (dl_client_state,io) = case ((n_library_instances - RTID_LIBRARY_INSTANCE_ID_START) < 2) of { True -> (dl_client_state,io); False #! cs_main_library_instance_i = RTID_LIBRARY_INSTANCE_ID_START; // all other dynamics must communicate with the application, so they all need to agree on // at least a single representation for Dynamics and the types of dynamics. There is only // one choice, taking the implementation of the application because it is loaded and linked // first. # dynamicje = { tr_type_name = DynamicRepresentation_String , tr_module_name1 = UnderscoreSystemDynamicModule_String , tr_module_name2 = UnderscoreSystemDynamicModule_String , tr_library2 = Number cs_main_library_instance_i // will be 2nd arg of enter_type_equation , tr_library1 = Number library_instance_i // RunTimeID (not diskID) }; // graph_to_string-instances must share a single LazyDynamicReference # lazy_dynamic_reference = { tr_type_name = LazyDynamicReference_String , tr_module_name1 = StdDynamicLowLevelInterfaceModule_String , tr_module_name2 = StdDynamicLowLevelInterfaceModule_String , tr_library2 = Number cs_main_library_instance_i // will be 2nd arg of enter_type_equation , tr_library1 = Number library_instance_i // RunTimeID (not diskID) }; # global_dynamic_info_dummy = { tr_type_name = GlobalDynamicInfoDummy_String , tr_module_name1 = UnderscoreSystemDynamicModule_String , tr_module_name2 = UnderscoreSystemDynamicModule_String , tr_library2 = Number cs_main_library_instance_i // will be 2nd arg of enter_type_equation , tr_library1 = Number library_instance_i // RunTimeID (not diskID) }; // The predefined types defined in the run-time system are shared among all library instances because it // is/will be used by all library instances, if necessary. // main library instance provides the implementation #! (ok,dl_client_state,io) = CheckAndEnterType [dynamicje/*,realtje*/,lazy_dynamic_reference,global_dynamic_info_dummy] (Just cs_main_library_instance_i) dl_client_state io; | not ok -> abort "internal/external error; representation of dynamics has changed"; #! (cs_n_fixed_available_types,dl_client_state) = dl_client_state!cs_n_fixed_available_types; #! (dl_client_state,io) = case cs_n_fixed_available_types of { Nothing // it is assumed that a type equivalent class which already has an implementation i.e. // the type implementation has been linked, is marked as such in the available array // below. #! (teit_n_type_implementations,dl_client_state) = dl_client_state!cs_type_implementation_table.teit_n_type_implementations; #! li_type_available = createArray teit_n_type_implementations True; #! dl_client_state = { dl_client_state & cs_library_instances.lis_library_instances.[cs_main_library_instance_i].li_s_type_available = teit_n_type_implementations , cs_library_instances.lis_library_instances.[cs_main_library_instance_i].li_type_available = li_type_available }; #! dl_client_state = { dl_client_state & cs_n_fixed_available_types = Just teit_n_type_implementations }; // a type implementation for a particular type equivalent class has been implemented if // *all* of the labels implementing the type have been linked. #! dl_client_state = print_type_implementation_table dl_client_state; -> (dl_client_state,io); Just _ -> (dl_client_state,io); }; // internal types moeten ook nog and basic types -> (dl_client_state,io); }; = (dl_client_state,io); where { // communication is done by dynamics. So the DynamicTemp and its type (and further types it depends upon) // must at the very least be constructible e.i. there exists a correctly typed Clean graph. The value may // not be (this depends on the type which describes the value). Here it is ensure that *all* labels which // implement the DynamicTemp-type are linked in. // Furthermore predefined types e.g. ints, reals, lists, etc. are also shared by all library instances. } LoadTypeTable :: .Int *DLClientState *a -> *(*DLClientState,*a) | FileEnv a; LoadTypeTable type_table_i dl_client_state io # (tt_loaded,dl_client_state) = dl_client_state!cs_type_tables.[type_table_i].tt_loaded; | tt_loaded = (dl_client_state,io); // load type table # (tt_name,dl_client_state) = dl_client_state!cs_type_tables.[type_table_i].tt_name; # ((ok,rti,tio_common_defs,type_io_state,_),io) = accFiles (read_type_library_new False tt_name) io; | not ok #! msg = "Loaded type table " +++ toString type_table_i +++ ": " +++ tt_name; #! dl_client_state = AddMessage (LinkerError msg) dl_client_state; = (dl_client_state,io); // create new type table # new_type_table = { default_type_table & tt_type_io_state = type_io_state , tt_tio_common_defs = { x \\ x <-: tio_common_defs } , tt_n_tio_common_defs = size tio_common_defs , tt_rti = rti }; # dl_client_state = AddTypeTable type_table_i new_type_table dl_client_state; // print that type library has been loaded #! dl_client_state = AddMessage (Verbose ("Loaded type table " +++ toString type_table_i +++ ": " +++ tt_name)) dl_client_state; = (dl_client_state,io); // Loads an application from a library // // Output: // - for each set of type equivalence with at least two types, a single implementation has been linked in. LoadApplication :: !ProcessSerialNumber [String] !*DLServerState !(IOState !*DLServerState) -> !(!Bool,!ProcessSerialNumber,!*DLServerState, !(IOState !*DLServerState)); LoadApplication client_id _ s io // copy from Init #! (client_exists,dl_client_state,s) = RemoveFromDLServerState client_id s; | not client_exists = internal_error "LoadApplication (internal error): client not registered" client_id dl_client_state s io; # (main_code_type_lib,dl_client_state) = dl_client_state!cs_main_library_name; #! dl_client_state = AddMessage (Verbose ("LoadApplication: " +++ main_code_type_lib)) dl_client_state; #! args = []; // check args-argument of Init-request #! dl_client_state = case (sel_platform True False) of { True // winOS | not (isEmpty args) #! dl_client_state = AddMessage (LinkerError "args argument of Init in Request.icl cannot have arguments") dl_client_state; -> dl_client_state; -> dl_client_state; False // macOS /* | length args <> 1 //isEmpty args #! dl_client_state = AddMessage (LinkerError "args argument of Init in Request.icl should have exactly one parameter") dl_client_state; -> dl_client_state; #! dl_client_state = app_pd_state (\pd_state -> {pd_state & qd_address = FromStringToInt (hd args) 0}) dl_client_state; -> dl_client_state; */ -> abort "LoadApplication; Init (line 131) uncomment!!!"; } #! (dlink_dir,s) = GetDynamicLinkerDirectory s; #! (to_and_from_graph_table,io) = init_to_and_from_graph_table dlink_dir io; #! (library_instance_i,_,dl_client_state=:{cs_main_library_instance_i},io) = RegisterLibrary Nothing True main_code_type_lib dl_client_state io; # dl_client_state = { dl_client_state & cs_to_and_from_graph = to_and_from_graph_table }; #! (state,dl_client_state) = get_state dl_client_state; #! dl_server_state = s; #! (start_addr,_,state,dl_client_state,io) = LoadLibraryInstance library_instance_i Nothing state dl_client_state io; # io = SendAddressToClient client_id (FromIntToString start_addr) io; # dl_client_state = { dl_client_state & app_linker_state = state }; # dl_client_state = AddMessage (Verbose ("###start:" +++ (hex_int start_addr))) dl_client_state; // check for errors #! (ok,dl_client_state) = IsErrorOccured {dl_client_state & initial_link = False}; = (not ok,client_id,AddToDLServerState dl_client_state dl_server_state,/*KillClient3 client_id ok*/ io); where { get_state dl_client_state=:{app_linker_state} = (app_linker_state,{dl_client_state & app_linker_state = EmptyState}); } LoadLibraryInstance library_instance_i non_main_library state dl_client_state=:{cs_main_library_instance_i} /*dl_server_state*/ io # (type_table_i,dl_client_state) = dl_client_state!cs_library_instances.lis_library_instances.[library_instance_i].li_type_table_i; # (dl_client_state,io) = LoadLibraryInstanceTypeTable library_instance_i type_table_i dl_client_state io = LoadCodeLibraryInstance non_main_library library_instance_i type_table_i state dl_client_state /*dl_server_state*/ io; RegisterLibrary dynamic_index is_main_library library_name s io # (type_table_i,s) = AddReferenceToTypeTable library_name s; # (library_instance_i,s) = AddLibraryInstance dynamic_index library_name type_table_i s; // print #! msg = "Register library as library instance #" +++ toString library_instance_i +++ " and name '" +++ library_name +++ "'"; #! (s) = AddMessage (Verbose msg) s; # (s,io) = LoadLibraryInstanceTypeTable library_instance_i type_table_i s io; = (library_instance_i,type_table_i,s,io); from SearchObject import add_module2, add_library2; collect_type_labels types type_table_i dl_client_state # (type_tables,dl_client_state) = get_type_tables dl_client_state; // collect types # (types,type_tables) = foldSt convert_type_name_into_tio_type_ref types ([],type_tables); | False <<- ("types", types) = undef; # dl_client_state = { dl_client_state & cs_type_tables = type_tables }; // collect labels # (labels,dl_client_state) = foldSt (collect_labels_implementing_a_type type_table_i) types ([],dl_client_state) = (labels,dl_client_state); where { convert_type_name_into_tio_type_ref (type_name,module_name) (types,type_tables) # (maybe_tio_type_reference,type_tables) = findTypeUsingTypeName type_name module_name type_table_i type_tables; | isNothing maybe_tio_type_reference = abort ("convert_type_name_into_tio_type_ref: internal error; unknown type " +++ type_name); # type = TypeTableTypeReference type_table_i (fromJust maybe_tio_type_reference); # (cts=:{cts_type_dependencies,cts_type_tables=type_tables}) = collect_types type type {default_collect_types_state & cts_type_tables = type_tables}; = (cts_type_dependencies ++ types,type_tables); collect_labels_implementing_a_type type_table_i (tio_type_ref,_) (labels,dl_client_state) #! (type_name,labels_implementing_type,dl_client_state) = get_type_label_names tio_type_ref type_table_i dl_client_state; | False <<- ("<>", type_name,labels_implementing_type) = abort type_name; = (labels_implementing_type ++ labels,dl_client_state); } // loads both the code library assumes type table has already been loaded. The redirections to be made are derived from the // type table and imposed on the code. LoadCodeLibraryInstance :: (Maybe [.DusLabel]) !.Int !Int !*State !*DLClientState !(IOState !*DLServerState) -> (!Int,[Int],!*State,!*DLClientState /*,!*DLServerState*/ ,!(IOState !*DLServerState)); LoadCodeLibraryInstance non_main_library library_instance_i type_table_i state dl_client_state io # (li_library_name,dl_client_state) = dl_client_state!cs_library_instances.lis_library_instances.[library_instance_i].li_library_name; # li_library_name = fromJust li_library_name; // get names table #! (li_library_initialized,dl_client_state) = dl_client_state!cs_library_instances.lis_library_instances.[library_instance_i].li_library_initialized; #! (share_runtime_system,state,dl_client_state,io) = case li_library_initialized of { True // library list zetten in state #! (li_library_list,dl_client_state) = dl_client_state!cs_library_instances.lis_library_instances.[library_instance_i].li_library_list; #! (names_table,dl_client_state) = acc_names_table library_instance_i dl_client_state; #! state = { state & namestable = names_table , library_list = li_library_list }; -> (False,state,dl_client_state,io); False #! (Just main_library_instance_i,dl_client_state) = dl_client_state!cs_main_library_instance_i; #! (do_dump_dynamic,dl_client_state) = dl_client_state!do_dump_dynamic; #! is_dump_dynamic_main_library = library_instance_i == main_library_instance_i && do_dump_dynamic; #! is_main_library_instance = library_instance_i == main_library_instance_i; #! (share_runtime_system,dl_client_state) = dl_client_state!cs_share_runtime_system; #! dl_client_state = { dl_client_state & cs_share_runtime_system = True }; # dl_client_state = case share_runtime_system of { False -> { dl_client_state & cs_main_library_instance_i = Just library_instance_i }; _ -> dl_client_state; }; // load library # ({rti_n_libraries=n_libraries,rti_n_library_symbols=n_library_symbols,rti_library_list=library_list},dl_client_state) = dl_client_state!cs_type_tables.[type_table_i].tt_rti; // mark library instance i as initialized #! dl_client_state = { dl_client_state & cs_library_instances.lis_library_instances.[library_instance_i].li_library_initialized = True }; #! (n_old_libraries,state) = state!n_libraries; // import DLL symbols #! (symbol_n,library_n,names_table) = ImportDynamicLibrarySymbols library_list 0 (~(n_libraries + n_old_libraries)) create_names_table; | symbol_n <> n_library_symbols || library_n <> (~n_old_libraries) -> abort "LoadCodeLibraryInstance: internal error; .typ-file corrupt"; // LibraryList #! state = case non_main_library of { _ -> add_library2 n_libraries n_library_symbols library_list state; _ -> state; }; // load code library *without* run-time system which is shared with the main library // instance. # (do_dump_dynamic,dl_client_state) = dl_client_state!do_dump_dynamic; # (rs,dl_client_state) = case share_runtime_system of { False -> (default_redirection_state,dl_client_state); _ # (cs_main_library_instance_i,dl_client_state) = dl_client_state!cs_main_library_instance_i; # main_library_instance_i = fromJust cs_main_library_instance_i; # library_name = (snd (ExtractPathAndFile li_library_name)); # library_name = "_" +++ (library_name % (0,size library_name - 2)) +++ "_options.o"; # rts_objects = ["_startup0.o",library_name,"_startup1.o","_startup2.o","_startup1Profile.o","_startup1Trace.o","_system.o"]; #! (names_table,dl_client_state) = acc_names_table main_library_instance_i dl_client_state; # rs = { default_redirection_state & rs_main_names_table = names_table , rs_rts_modules = rts_objects }; -> (rs,dl_client_state); }; # (n_xcoff_files,state) = state!n_xcoff_files; # code_lib_name = build_code_lib_name li_library_name; # (s_names_table,names_table) = usize names_table; # ((errors, xcoff_l, names_table, _,rs),io) = accFiles (read_code_library2 (n_xcoff_files) [] code_lib_name names_table rs) io; // restore name table # dl_client_state = case share_runtime_system of { False -> dl_client_state; _ # (cs_main_library_instance_i,dl_client_state) = dl_client_state!cs_main_library_instance_i; # main_library_instance_i = fromJust cs_main_library_instance_i; # dl_client_state = { dl_client_state & cs_library_instances.lis_library_instances.[main_library_instance_i].li_names_table = rs.rs_main_names_table }; -> dl_client_state; }; #! state = { state & namestable = names_table , library_list = library_list }; // add_module #! state = foldSt add_module2 xcoff_l state; // ------------------------ // A lazy dynamic is marked by a BUILD_BLOCK_LABEL or a BUILD_LAZY_BLOCK_LABEL. Each library also defines these // two labels. Without precautions, these copies would also be put in the image, making the conversion routines // much more complex. Therefore the copy of the main library instance is taken and references of other library // instance are redirected to those of the main library instance. // backup namestable from state #! (names_table,state) = select_namestable state; #! dl_client_state = { dl_client_state & cs_library_instances.lis_library_instances.[library_instance_i].li_names_table = names_table }; // body ... #! (state,dl_client_state) = case share_runtime_system of { False -> (state,dl_client_state); True // backup state #! dl_client_state = { dl_client_state & app_linker_state = state }; // replace BUILD_BLOCK_LABEL #! (Just main_library_instance_i,dl_client_state) = dl_client_state!cs_main_library_instance_i; #! (Just (build_block_file_n,build_block_symbol_n),dl_client_state) = findLabel BUILD_BLOCK_LABEL main_library_instance_i dl_client_state; #! dl_client_state = replaceLabel BUILD_BLOCK_LABEL library_instance_i build_block_file_n build_block_symbol_n BUILD_BLOCK_LABEL dl_client_state; // replace BUILD_LAZY_BLOCK_LABEL #! (Just (build_lazy_block_file_n,build_lazy_block_symbol_n),dl_client_state) = findLabel BUILD_LAZY_BLOCK_LABEL main_library_instance_i dl_client_state; #! dl_client_state = replaceLabel BUILD_LAZY_BLOCK_LABEL library_instance_i build_lazy_block_file_n build_lazy_block_symbol_n BUILD_LAZY_BLOCK_LABEL dl_client_state; // extract state #! (state,dl_client_state) = acc_state (\state -> (state,EmptyState)) dl_client_state; -> (state,dl_client_state); }; // ... body // restore namestable in state #! (names_table,dl_client_state) = acc_names_table library_instance_i dl_client_state; #! state = { state & namestable = names_table }; -> (share_runtime_system,state,dl_client_state,io); }; #! (names_table,state) = select_namestable state; #! (library_list,state) = state!library_list #! dl_client_state = { dl_client_state & cs_library_instances.lis_library_instances.[library_instance_i].li_names_table = names_table , app_linker_state = state }; #! (dl_client_state,io) = update_namestable_to_include_recent_type_implementations library_instance_i dl_client_state io; #! (names_table,dl_client_state) = acc_names_table library_instance_i dl_client_state; #! (state,dl_client_state) = acc_state (\s -> (s,EmptyState)) dl_client_state; #! state = { state & namestable = names_table , library_list = library_list }; #! (main_symbols,dl_client_state) = case non_main_library of { Nothing // # (type_table_i,dl_client_state) = dl_client_state!cs_library_instances.lis_library_instances.[library_instance_i].li_type_table_i; # types = [ // , (T_ypeObjectTypeRepresentation_String,UnderscoreSystemDynamicModule_String) ] # (labels,dl_client_state) = collect_type_labels types type_table_i dl_client_state; #! main_symbol = sel_platform "_mainCRTStartup" "main"; #! main_symbols = [ SymbolUnknown "" main_symbol , SymbolUnknown "" BUILD_BLOCK_LABEL , SymbolUnknown "" BUILD_LAZY_BLOCK_LABEL ] ++ [ SymbolUnknown UnderscoreSystemDynamicModule_String label_name \\ label_name <- labels ]; #! (teit_n_type_implementations,dl_client_state) = dl_client_state!cs_type_implementation_table.teit_n_type_implementations; -> (main_symbols,dl_client_state); (Just dus_labels) // exclude label which already have been linked by other library instances #! labels = [ SymbolUnknown "" dusl_label_name \\ {dusl_label_name,dusl_linked} <- dus_labels | not dusl_linked]; -> (labels,dl_client_state); }; /* ** The preliminary temp solution above ensures that the RunTimeID-constructor is allocated into ** library space and not lazily allocated in space for the graph_to_string-conversion function ** which is not a library instance and therefore not included in the table which is sent to the ** application and contains start/end addresses for each library instance. ** In the future the RunTimeID constructor of the context library should be used. */ #! ((wii,p=:[start_addr:_],state,dl_client_state),io) = LinkUnknownSymbols main_symbols state library_instance_i dl_client_state io; // LibraryList #! (library_list,names_table,state) = case (USE_OLD_NAMESTABLE_STORAGE True False) of { True -> (EmptyLibraryList,create_names_table,state); False #! (names_table,state) = select_namestable state; #! (library_list,state) = state!library_list; -> (library_list,names_table,state); }; #! dl_client_state = case wii of { Nothing -> dl_client_state; Just {wii_code_start,wii_code_end,wii_data_start,wii_data_end} #! (li_memory_areas,dl_client_state) = dl_client_state!cs_library_instances.lis_library_instances.[library_instance_i].li_memory_areas; #! li_memory_areas = [{ma_begin=wii_data_start,ma_end=wii_data_end},{ma_begin=wii_code_start,ma_end=wii_code_end}:li_memory_areas]; #! dl_client_state = { dl_client_state & cs_library_instances.lis_library_instances.[library_instance_i].li_memory_areas = li_memory_areas }; -> dl_client_state; }; // update #! dl_client_state = { dl_client_state & cs_library_instances.lis_library_instances.[library_instance_i].li_library_initialized = True , cs_library_instances.lis_library_instances.[library_instance_i].li_library_list = library_list , cs_library_instances.lis_library_instances.[library_instance_i].li_names_table = names_table } = (start_addr,p,state,dl_client_state,io); where { check_label dl_client_state=:{cs_main_library_instance_i=Just main_library_instance_i} #! (Just (file_n,symbol_n),dl_client_state) = findLabel BUILD_BLOCK_LABEL main_library_instance_i dl_client_state = dl_client_state; where { check_a_label label dl_client_state = undef } f :: !*DLClientState -> !*DLClientState; f i = i; read_code_library2 file_n module_to_be_removed code_lib_name names_table rs files # (errors, xcoff_l, _, names_table, file_n, files,_,rs) = read_static_lib_files_new module_to_be_removed [code_lib_name] [] names_table file_n [] files default_rsl_state rs; = ((errors, xcoff_l, names_table, file_n,rs), files); }; // SHOULD BE MORE SPECIALIZED TO ENFORCE MORE EFFICIENT CODE instance findTypeUsingTypeName DLClientState where { findTypeUsingTypeName type_name module_name type_table_i dl_client_state # (type_tables,dl_client_state) = get_type_tables dl_client_state; # (result,type_tables) = findTypeUsingTypeName type_name module_name type_table_i type_tables; # dl_client_state = { dl_client_state & cs_type_tables = type_tables }; = (result,dl_client_state); }; instance findTypeUsingConstructorName DLClientState where { findTypeUsingConstructorName type_name module_name type_table_i dl_client_state # (type_tables,dl_client_state) = get_type_tables dl_client_state; # (result,type_tables) = findTypeUsingConstructorName type_name module_name type_table_i type_tables; # dl_client_state = { dl_client_state & cs_type_tables = type_tables }; = (result,dl_client_state); }; instance findModuleName DLClientState where { findModuleName module_name type_table_i dl_client_state # (type_tables,dl_client_state) = get_type_tables dl_client_state; # (result,type_tables) = findModuleName module_name type_table_i type_tables; # dl_client_state = { dl_client_state & cs_type_tables = type_tables }; = (result,dl_client_state); }; instance getImplementationType DLClientState where { getImplementationType index_of_type_equivalence_class dl_client_state # (type_implementation_table,dl_client_state) = get_type_implementation_table dl_client_state; # (implementation_type,type_implementation_table) = getImplementationType index_of_type_equivalence_class type_implementation_table; # dl_client_state = { dl_client_state & cs_type_implementation_table = type_implementation_table }; = (implementation_type,dl_client_state); }; instance enter_implementation_type_for_equivalence_class2 DLClientState where { enter_implementation_type_for_equivalence_class2 index_of_type_equivalence_class type_implementing_type_equivalence_class dl_client_state # (type_implementation_table,dl_client_state) = get_type_implementation_table dl_client_state; # type_implementation_table = enter_implementation_type_for_equivalence_class2 index_of_type_equivalence_class type_implementing_type_equivalence_class type_implementation_table; # dl_client_state = { dl_client_state & cs_type_implementation_table = type_implementation_table }; = dl_client_state; }; instance enter_implementation_type_for_equivalence_class DLClientState where { enter_implementation_type_for_equivalence_class index_of_type_equivalence_class library_instance_i_implements_type_equivalence_class dl_client_state # (type_implementation_table,dl_client_state) = get_type_implementation_table dl_client_state; # type_implementation_table = enter_implementation_type_for_equivalence_class index_of_type_equivalence_class library_instance_i_implements_type_equivalence_class type_implementation_table; # dl_client_state = { dl_client_state & cs_type_implementation_table = type_implementation_table }; = dl_client_state; }; instance enter_type_equation DLClientState where { enter_type_equation type1 type2 dl_client_state | isTypeWithoutDefinition type1 && isTypeWithoutDefinition type2 // types without definitions are implemented in the rts and are shared by default = (Nothing,dl_client_state); # (type_implementation_table,dl_client_state) = get_type_implementation_table dl_client_state; // body... // pattern below only fails when type equation without definition (in a icl-module) have been entered // in the type implementation table. The type implementation table is then invalid. # (Just (index_of_type_equivalence_class,created_new_type_equivalence_class),type_implementation_table) = enter_type_equation type1 type2 type_implementation_table; # ({tei_chosen_type_implementation},type_implementation_table) = get_type_implementation index_of_type_equivalence_class type_implementation_table; # dl_client_state = { dl_client_state & cs_type_implementation_table = type_implementation_table }; | isJust tei_chosen_type_implementation // an type implementation from the type equivalent class has already been chosen i.e. linked = (Just (index_of_type_equivalence_class,created_new_type_equivalence_class),dl_client_state); /* // examine type equivalent class if it already has been implemented. | isTypeWithoutDefinition type1 <<- "implementation" | True <<- ("kraai",type1) // a type without definition e.g. _List, Int. // #! (cs_main_library_instance_i,dl_client_state) // = dl_client_state!cs_main_library_instance_i; // #! dl_client_state // = enter_implementation_type_for_equivalence_class index_of_type_equivalence_class (fromJust cs_main_library_instance_i) dl_client_state; = (index_of_type_equivalence_class,created_new_type_equivalence_class,dl_client_state); = abort "stoip"; // The following is assumed for each type equivalent class: // - without a chosen type definition, each member of the class must be unimplemented i.e. unlinked. // - with a chosen type definition, each member but the chosen must be unimplemented. The chosen // type definition must be implemented i.e. linked. // */ | created_new_type_equivalence_class // <<- ("%%%",index_of_type_equivalence_class,type1,type2) #! (maybe_type1_implemented,dl_client_state) = isTypeImplemented type1 dl_client_state; | isJust maybe_type1_implemented #! dl_client_state = dl_client_state //<<- ("type 1 implemented") #! dl_client_state = enter_implementation_type_for_equivalence_class2 index_of_type_equivalence_class type1 dl_client_state; = (Just (index_of_type_equivalence_class,created_new_type_equivalence_class),dl_client_state); #! (maybe_type2_implemented,dl_client_state) = isTypeImplemented type2 dl_client_state; | isJust maybe_type2_implemented #! dl_client_state = dl_client_state //<<- ("type 2 implemented") #! dl_client_state = enter_implementation_type_for_equivalence_class2 index_of_type_equivalence_class type2 dl_client_state; = (Just (index_of_type_equivalence_class,created_new_type_equivalence_class),dl_client_state); // new type equivalent class has not been implemented #! dl_client_state = dl_client_state //<<- ("new equiv but only with type equations",type1,type2); = (Just (index_of_type_equivalence_class,created_new_type_equivalence_class),dl_client_state); // type2 is unlinked member of the type equivalent class. #! (maybe_type1_implemented,dl_client_state) = isTypeImplemented type1 dl_client_state; | isNothing maybe_type1_implemented //<<- ("enter",type1) = (Just (index_of_type_equivalence_class,created_new_type_equivalence_class),dl_client_state); = abort "dkkd"; /* | isNothing library_instance_i_implements_type_equivalence_class // generate only type equations = dl_client_state; # (implementation_type_for_equivalence_class,dl_client_state) = getImplementationType ti_reference dl_client_state; | isNothing implementation_type_for_equivalence_class // given library instance provides the implementation of the type equivalence class = enter_implementation_type_for_equivalence_class ti_reference (fromJust library_instance_i_implements_type_equivalence_class) dl_client_state; = dl_client_state; */ /* = (index_of_type_equivalence_class,created_new_type_equivalence_class,dl_client_state); //abort "stop"; */ }; debug name library_instance_i dl_client_state #! (li_library_initialized,dl_client_state) = dl_client_state!cs_library_instances.lis_library_instances.[library_instance_i].li_library_initialized; #! (names_table,dl_client_state) = acc_names_table library_instance_i dl_client_state; #! (s_names_table,names_table) = usize names_table; | (s_names_table < 10) <<- ("names_table: " +++ toString (size names_table) +++ " for library instance #" +++ toString library_instance_i +++ (if (li_library_initialized) "initialized" "not initialzied")) = abort ("debug " +++ name); #! dl_client_state = { dl_client_state & cs_library_instances.lis_library_instances.[library_instance_i].li_names_table = names_table}; = dl_client_state; replaceLabel refering_label library_instance_i file_n symbol_n chosen_label_name dl_client_state #! ((symbol_hash,ref_file_n,ref_symbol_n,names_table_element_list),dl_client_state) = split_symbol_list_in_symbol_table refering_label (\index dl_client_state -> dl_client_state!cs_library_instances.lis_library_instances.[library_instance_i].li_names_table.[index]) dl_client_state; #! new_names_table_element = NamesTableElement refering_label symbol_n file_n names_table_element_list; #! dl_client_state = { dl_client_state & cs_library_instances.lis_library_instances.[library_instance_i].li_names_table.[symbol_hash] = new_names_table_element }; // debug ... #! msg = "replace " +++ refering_label +++ "<" +++ toString ref_file_n +++ "," +++ toString ref_symbol_n +++ "> by " +++ chosen_label_name +++ "<" +++ toString file_n +++ "," +++ toString symbol_n +++ ">"; | True <<- msg // ... debug // The chosen_label_name which implements a type can be referenced within the defining object module or // from some other object module. The latter references are resolved by name using the names table. The // former reference by symbol index. These references are accounted for by marking the symbol itself and // its defining section (module) as linked and by copying the address of the defining module of the chosen // symbol to that referencing module. // find module containing referencing symbol #! (ref_module_n,dl_client_state) = acc_state (replace_section_label_by_label2 ref_file_n ref_symbol_n) dl_client_state; // find module containing chosen symbol #! (chosen_symbol,dl_client_state) = dl_client_state!app_linker_state.xcoff_a.[file_n].symbol_table.symbols.[symbol_n]; #! chosen_module_n = case chosen_symbol of { Label _ _ module_n -> module_n; s | True <<- ("***",s) -> abort ("unimported label " +++ refering_label ); }; // compute address of chosen module_n #! (chosen_module_n_index,dl_client_state) = symbol_n_to_offset file_n chosen_module_n dl_client_state; #! (chosen_module_n_address,dl_client_state) = dl_client_state!app_linker_state.module_offset_a.[chosen_module_n_index]; // mark referencing module as marked by settings its address to that of the chosen module #! (ref_module_n_index,dl_client_state) = symbol_n_to_offset ref_file_n ref_module_n dl_client_state; #! dl_client_state = { dl_client_state & app_linker_state.module_offset_a.[ref_module_n_index] = chosen_module_n_address , app_linker_state.marked_bool_a.[ref_module_n_index] = True }; #! (ref_symbol_n_index,dl_client_state) = symbol_n_to_offset ref_file_n ref_symbol_n dl_client_state; #! dl_client_state = { dl_client_state & app_linker_state.marked_bool_a.[ref_symbol_n_index] = True }; = dl_client_state; instance get_type_implementation DLClientState where { get_type_implementation index_of_type_equivalence_class dl_client_state # (type_implementation_table,dl_client_state) = get_type_implementation_table dl_client_state; # (implementation_type,type_implementation_table) = get_type_implementation index_of_type_equivalence_class type_implementation_table; # dl_client_state = { dl_client_state & cs_type_implementation_table = type_implementation_table }; = (implementation_type,dl_client_state); }; instance add_lazy_type_equations DLClientState where { add_lazy_type_equations index library_instance_type_references dl_client_state # (type_implementation_table,dl_client_state) = get_type_implementation_table dl_client_state; # type_implementation_table = add_lazy_type_equations index library_instance_type_references type_implementation_table; # dl_client_state = { dl_client_state & cs_type_implementation_table = type_implementation_table }; = dl_client_state; };