implementation module LibraryInstance;

import StdEnv;
import StdMaybe;
import StdDynamicLowLevelInterface;
import NamesTable;
import BitSet;

//1.3
from pdSymbolTable import LibraryList, EmptyLibraryList;
//3.1
/*2.0
from pdSymbolTable import ::LibraryList, EmptyLibraryList;
0.2*/
:: *LibraryInstance 
	= {
		li_library_name		:: !Maybe !String				// file name of library
	,	li_type_table_i		:: !Int							// index in cs_type_tables

	,	li_s_type_available	:: !Int							// size of array below
	,	li_type_available	:: !*{#Bool}					// index in type implementation table True = made available, False = not available valid for chosen types from current library instance

	,	li_names_table		:: !*NamesTable					// names table
	,	li_library_list		:: !LibraryList

	,	li_initial_types_equivalences_entered 	:: !Bool	// internal type equivalences i.e. within library instance and types which implement type-component of dynamic
	
	,	li_library_initialized	:: !Bool					// names table is non-empty, marked_bool_a, marked_offset_a, etc. are adapted which is reflected in app_linker_state (DLClientState)

	,	li_dynamic_index	:: !Maybe !Int					// index in cs_dynamic_info
	
/*
	,	li_code_begin		:: !Int
	,	li_code_end			:: !Int
	,	li_data_begin		:: !Int
	,	li_data_end			:: !Int	
*/
	
	,	li_memory_areas		:: [MemoryArea]
	};
	
:: MemoryArea
	= {
		ma_begin			:: !Int
	,	ma_end				:: !Int
	};
	
default_library_instance :: *LibraryInstance;
default_library_instance
	= { 
		li_library_name		= (Just "reserved")
	,	li_type_table_i		= 0
	
	,	li_s_type_available	= 0
	,	li_type_available	= {}
	
	,	li_names_table		= {}
	,	li_library_list		= EmptyLibraryList
	
	,	li_initial_types_equivalences_entered	= False
	
	,	li_library_initialized	= False
	
	
	,	li_dynamic_index	= Nothing

/*
	,	li_code_begin		= 0
	,	li_code_end			= 0
	,	li_data_begin		= 0
	,	li_data_end			= 0
*/
	
	,	li_memory_areas		= []
	};
		
:: *LibraryInstances
	= { 
		lis_n_library_instances		:: !Int
	,	lis_library_instances		:: !*{#*LibraryInstance}
	};

default_library_instances :: *LibraryInstances;
default_library_instances 
	= { 
		lis_n_library_instances		= RTID_LIBRARY_INSTANCE_ID_START
	,	lis_library_instances		= { default_library_instance \\ _ <- [0..dec RTID_LIBRARY_INSTANCE_ID_START]}
	};
	
class Library_Instances a
where {
	AddLibraryInstance :: (!Maybe !Int) !String !Int !*a -> (!Int,!*a)
};
	
instance Library_Instances LibraryInstances
where {
	AddLibraryInstance dynamic_index library_name type_table_i library_instances=:{lis_n_library_instances,lis_library_instances}
		# new_library_instance
			= { default_library_instance & 		
				li_library_name		= Just library_name
			,	li_type_table_i		= type_table_i
			,	li_dynamic_index	= dynamic_index
			};
			
		// enlarge library instance array & add new element
		# lis_library_instances
			= { extend_array 1 lis_library_instances & [lis_n_library_instances] = new_library_instance };
		
		# library_instances
			= { library_instances &
				lis_n_library_instances		= inc lis_n_library_instances
			,	lis_library_instances		= lis_library_instances
			};
		= (lis_n_library_instances,library_instances);
};


// -------------------------------------------------------------------------------------------------------------

instance DefaultElemU LibraryInstance
where {
	default_elemU = default_library_instance
};

//1.3
extend_array :: !Int {#*a} -> {#*a} | ArrayElem, DefaultElemU a;
//3.1
/*2.0
extend_array :: .Int *(a *b) -> *(c *b) | Array c b & Array a b & DefaultElemU b;
0.2*/
extend_array n_new_elements a 
	# (s_a,a)
		= usize a;
	# new_a
		= copy_array 0 s_a a { default_elemU \\ i <- [1..(s_a + n_new_elements)] };
	= new_a;
where {
	copy_array i limit old_array new_array 
		| i == limit
			= new_array;

			# (elem,old_array)
				= replace old_array i default_elemU;	
			= copy_array (inc i) limit old_array {new_array & [i] = elem};
};