implementation module Sections;

import StdArray, StdClass, StdInt;

//1.3
from StdString import String;
//3.1
from StdMisc import undef, abort;

//import macState;
import State;
import PlatformLinkOptions;
import pdSections;

:: ComputeSectionType
	:== !Int -> !Int -> !Int -> !SectionHeader -> *(!*State -> *(!*PlatformLinkOptions -> *(!*Files -> *(!Int,!SectionHeader,!*State,!*PlatformLinkOptions,!*Files))));

:: GenerateSectionType
	:== !SectionHeader -> (!*File -> *(!*PlatformLinkOptions -> *(!*State -> *(!*Files -> *(!*File,!*PlatformLinkOptions,!*State,!*Files)))));
			
:: SectionHeader = {
	// fields should be initialized 
		kind				:: !SectionHeadKind
	,	index				:: !Int							// obsolete
	,	alignment			:: !Int
	,	compute_section 	:: ComputeSectionType
	,	generate_section	:: GenerateSectionType
	, 	is_virtual_section 	:: !Bool
	,	s_virtual_data		:: !Int

	// automatically initialized
	,	s_raw_data			:: !Int							// only if s_raw_data == 0
	,	fp_section			:: !Int
	
	// platform dependent part of section header
	,	pd_header			:: PDSectionHeader
};

sh_get_kind :: !SectionHeader -> !SectionHeadKind;
sh_get_kind {kind}
	= kind;
	
sh_get_alignment :: !SectionHeader -> !Int;
sh_get_alignment {alignment} 
	= alignment;
	
sh_get_is_virtual_section :: !SectionHeader -> !Bool;
sh_get_is_virtual_section {is_virtual_section}
	= is_virtual_section;

sh_get_s_virtual_data :: !SectionHeader -> !Int;
sh_get_s_virtual_data section_header=:{s_virtual_data}
	= s_virtual_data;
	
sh_get_compute_section :: !SectionHeader -> ComputeSectionType;
sh_get_compute_section {compute_section}
	= compute_section;
	
sh_get_generate_section :: !SectionHeader -> GenerateSectionType;
sh_get_generate_section {generate_section}
	= generate_section;
	
sh_get_s_raw_data :: !SectionHeader -> !Int;
sh_get_s_raw_data section_header=:{s_raw_data}
	= s_raw_data;
	
sh_get_fp_section :: !SectionHeader -> !Int;
sh_get_fp_section section_header=:{fp_section}
	= fp_section;
	
sh_get_pd_section_header :: !SectionHeader -> !PDSectionHeader;
sh_get_pd_section_header {pd_header}
	= pd_header;
	

/*
sh_set_pd_section_header :: !PDSectionHeader !SectionHeader -> !SectionHeader;
sh_set_pd_section_header pd_section_header section_header
	= { section_header &
		pd_header			= pd_section_header
	};
*/
	
DefaultSectionHeader :: !SectionHeader;
DefaultSectionHeader 
	= { SectionHeader |
		kind				= NoSectionHeader
	,	index				= 0
	,	alignment			= 512
	,	compute_section		= undef //compute_start_prefix //(\i s -> s) //.compute_start_prefix
	,	generate_section	= undef
	, 	is_virtual_section	= False
	,	s_virtual_data		= 0
	
	// automatically initialized
	,	s_raw_data			= 0
	,	fp_section			= 0
	
	// platform dependent part of section header
	,	pd_header			= DefaultPDSectionHeader
};		

(DSH) infixl;
(DSH) dsh f :== f dsh;
 

// Accessors; set
sh_set_kind :: !SectionHeadKind !SectionHeader -> !SectionHeader;
sh_set_kind kind section_header
	= { section_header & kind = kind};

sh_set_index :: !Int !SectionHeader -> !SectionHeader;
sh_set_index index section_header
	= { section_header & index = index };
	
sh_set_alignment :: !Int !SectionHeader -> !SectionHeader;
sh_set_alignment alignment section_header
	= { section_header & alignment = alignment };
	
sh_set_is_virtual_section :: !Bool !SectionHeader -> !SectionHeader;
sh_set_is_virtual_section is_virtual_section section_header
	= { section_header & is_virtual_section = is_virtual_section};
	
sh_set_virtual_data :: !Int !SectionHeader -> !SectionHeader;
sh_set_virtual_data s_virtual_data section_header
	= { section_header &
		s_virtual_data		= s_virtual_data
	};
	
sh_set_s_raw_data :: !Int !SectionHeader -> !SectionHeader;
sh_set_s_raw_data s_raw_data section_header
	= { section_header & s_raw_data = s_raw_data };
	
sh_set_fp_section :: !Int !SectionHeader -> !SectionHeader;
sh_set_fp_section fp_section section_header
	= { section_header & fp_section = fp_section };
	
sh_set_compute_section :: ComputeSectionType !SectionHeader -> !SectionHeader;
sh_set_compute_section compute_section section_header
	= { section_header & compute_section = compute_section };
	
sh_set_generate_section :: GenerateSectionType !SectionHeader -> !SectionHeader;
sh_set_generate_section generate_section section_header
	= { section_header & generate_section = generate_section };

sh_set_pd_section_header :: !PDSectionHeader !SectionHeader -> !SectionHeader;
sh_set_pd_section_header pd_section_header section_header
	= { section_header &
		pd_header			= pd_section_header
	};
	
// get


/*
	misschien kunnen de pd_* opgeheven worden. Als ik een functie maak die een PDSectionHeader
	teruggeeft als resultaat.
	
// section_name
instance pd_get_section_name !SectionHeader
where {
	pd_get_section_name section_header=:{pd_header} 
		= pd_get_section_name pd_header;
};

instance pd_get_section_rva !SectionHeader
where {
	pd_get_section_rva section_header=:{pd_header}
		= pd_get_section_rva pd_header;
};


instance pd_get_section_flags !SectionHeader
where {
	pd_get_section_flags section_header=:{pd_header}
		= pd_get_section_flags pd_header;
};
*/
/*
class FileEnv env where
	accFiles :: !.(*Files -> (.x,*Files)) !*env -> (!.x,!*env)
	appFiles :: !.(*Files -> *Files) !*env -> *env
*/
appSectionHeader_a f section_header_a
	# (x,section_header_a)
		= f section_header_a;
	= (x,section_header_a);
	

get_section_index :: !Int SectionHeadKind !*{!SectionHeader} -> (!Bool,!Int,!SectionHeader,!*{!SectionHeader});
get_section_index start_i demanded_section_head_kind section_header_a 
	= get_section_index2 (==) start_i demanded_section_head_kind section_header_a;
	
// {!SectionHeader}
get_section_index2 :: (SectionHeadKind SectionHeadKind -> !Bool) !Int SectionHeadKind !*{!SectionHeader} -> (!Bool,!Int,!SectionHeader,!*{!SectionHeader});
get_section_index2 p start_i demanded_section_head_kind section_header_a 
	# (s_section_header_a,section_header_a)
		= usize section_header_a;
	= loop_get_section_index start_i s_section_header_a section_header_a
where {
	loop_get_section_index i limit section_header_a
		| i >= limit
			= (False,0,DefaultSectionHeader,section_header_a);
			
			# (section_header,section_header_a)
				= section_header_a![i];
			| p section_header.kind demanded_section_head_kind
				= (True,i,section_header,section_header_a);
				= loop_get_section_index (inc i) limit section_header_a;
}

/*
:: SectionHeader = {
	section_name				:: !String,	// offset 0
	s_virtual_data				:: !Int,	// offset 8
	section_rva					:: !Int,	// offset 12
	s_raw_data					:: !Int,	// offset 16
	fp_section					:: !Int, 	// offset 20
	section_flags				:: !Int
};

EmptySectionHeader :: !SectionHeader;
EmptySectionHeader = {
	section_name				= "",
	s_virtual_data				= 0,
	section_rva					= 0,
	s_raw_data					= 0,
	fp_section					= 0,
	section_flags				= 0
	};

:: SectionHeaderKind
	= 
	  StartPrefix			!Int 
	| TextSectionHeader 	!Int
	| DataSectionHeader 	!Int
	| BssSectionHeader		!Int
	| IDataSectionHeader	!Int
	| EDataSectionHeader	!Int
	| RelocSectionHeader	!Int
	| EndSuffix				!Int
	;
	
:: SectionHeaderKinds :== ![!SectionHeaderKind];

is_start_prefix :: !SectionHeaderKind -> !(!Bool,Int);
is_start_prefix (StartPrefix i ) 		= (True,i);
is_start_prefix _						= (False,undef);

is_text_section :: !SectionHeaderKind -> !(!Bool,Int);
is_text_section (TextSectionHeader i )	= (True,i);
is_text_section _						= (False,undef);

is_data_section :: !SectionHeaderKind -> !(!Bool,Int);
is_data_section (DataSectionHeader i )	= (True,i);
is_data_section _						= (False,undef);

is_bss_section :: !SectionHeaderKind -> !(!Bool,Int);
is_bss_section (BssSectionHeader i )		= (True,i);
is_bss_section _						= (False,undef);

is_idata_section :: !SectionHeaderKind -> !(!Bool,Int);
is_idata_section (IDataSectionHeader i )	= (True,i);
is_idata_section _						= (False,undef);

is_edata_section :: !SectionHeaderKind -> !(!Bool,Int);
is_edata_section (EDataSectionHeader i ) = (True,i);
is_edata_section _						= (False,undef);

is_reloc_section :: !SectionHeaderKind -> !(!Bool,Int);
is_reloc_section (RelocSectionHeader i )	= (True,i);
is_reloc_section _						= (False,undef);

get_section_index :: (SectionHeaderKind -> (!Bool,Int)) SectionHeaderKinds -> !Int; 
get_section_index _ []
	= abort "get_section_index";
get_section_index is_required_section [section_header_kind:section_header_kinds]
	# (found,index)
		= is_required_section section_header_kind;
	| found
		= index;
		= get_section_index is_required_section section_header_kinds;
		
get_section_header_index section_header_kind :== get_section_header_index section_header_kind
where {
	get_section_header_index (StartPrefix i )		= i;
	get_section_header_index (TextSectionHeader i )	= i;
	get_section_header_index (DataSectionHeader i)	= i;
	get_section_header_index (BssSectionHeader i )	= i;
	get_section_header_index (IDataSectionHeader i ) = i;
	get_section_header_index (EDataSectionHeader i ) = i;
	get_section_header_index (RelocSectionHeader i ) = i;
	get_section_header_index (EndSuffix i ) 			= i;
}
*/
