implementation module PmTypes

// The types for the Project Manager

import StdBool, StdInt
import UtilStrictLists, UtilDate
from UtilNewlinesFile import :: NewlineConvention(..)
import PmCompilerOptions
from StdPathname import :: Pathname
import StdFile


::	Modulename			:== String

// Unexpected :: .a {#Char} -> .a
Unexpected message defaultValue
	:== UnexpectedEvalBefore defaultValue (UnexpectedReport message)

UnexpectedEvalBefore :: !.a !.b -> .a
UnexpectedEvalBefore defaultValue _
	=	defaultValue

Don`tCareValue :== 0

UnexpectedReport :: !{#Char} -> Int
UnexpectedReport message
	=	UnexpectedEvalBefore Don`tCareValue (fwrites message stderr)

UnexpectedConstructor :: !{#Char} !{#Char} !.a -> .a
UnexpectedConstructor typeName string defaultValue
	=	Unexpected ( "fromString (" +++ typeName +++ "): unknown value (" +++ string +++ ")\n") defaultValue

//--

::	Processor = CurrentProcessor | MC68000 | MC68020 | MC68020_and_68881

instance == Processor
where
	(==) :: Processor Processor -> Bool
	(==) CurrentProcessor CurrentProcessor
		=	True
	(==) MC68000 MC68000
		=	True
	(==) MC68020 MC68020
		=	True
	(==) MC68020_and_68881 MC68020_and_68881
		=	True
	(==) _ _
		=	False

instance fromString Processor
where
	fromString :: {#Char} -> Processor
	fromString "CurrentProcessor"
		=	CurrentProcessor
	fromString "MC68000"
		=	MC68000
	fromString "MC68020"
		=	MC68020
	fromString "MC68020_and_68881"
		=	MC68020_and_68881
	fromString string
		=	UnexpectedConstructor "Processor" string CurrentProcessor

instance toString Processor
where
	toString :: Processor -> {#Char}
	toString MC68000
		=	"MC68000"
	toString MC68020
		=	"MC68020"
	toString MC68020_and_68881
		=	"MC68020_and_68881"
	toString CurrentProcessor
		=	"CurrentProcessor"

:: ModInfoAndName =
	{
		info	:: ModInfo,
		name	:: {#Char}
	}

::	ModInfo	=
	{ dir				:: !String				// !Pathname			// directory
	, compilerOptions	:: !CompilerOptions		// compiler options
	, defeo 			:: !EditWdOptions		// edit options def module
	, impeo				:: !EditWdOptions		// edit options imp module
	, defopen 			:: !Bool				// dcl open?
	, impopen			:: !Bool				// icl open?
	, date				:: !DATE				// last scan date of file???
	, abcLinkInfo		:: !ABCLinkInfo
	}

:: ABCLinkInfo = {linkObjFileNames :: !List LinkObjFileName, linkLibraryNames :: !List LinkLibraryName}

:: LinkObjFileName	:== String
:: LinkLibraryName	:== String

//-- Link Options

::	LinkOptions =
	{ extraObjectModules	:: !List {#Char}
	, libraries				:: !List {#Char}
	, method				:: !LinkMethod
	, generate_relocations	:: !Bool			// Win only option
	, generate_link_map		:: !Bool
	, link_resources		:: !Bool
	, resource_source		:: !String

	, generate_dll						:: !Bool
	, dll_export_list_name				:: !String
	}

instance == LinkOptions		// do we need to check resource linking flags???
where
	(==) :: !LinkOptions !LinkOptions -> Bool
	(==) lo1 lo2 =

		lo1.method == lo2.method &&
		lo1.generate_relocations == lo2.generate_relocations &&
		lo1.generate_link_map == lo2.generate_link_map &&
		lo1.link_resources == lo2.link_resources &&
		(if lo1.link_resources (lo1.resource_source == lo2.resource_source) True) &&
		EQStrings (SortStrings lo1.extraObjectModules) (SortStrings lo2.extraObjectModules) &&
		EQStrings (SortStrings lo1.libraries) (SortStrings lo2.libraries)

DefaultLinkOptions :: LinkOptions;
DefaultLinkOptions =
	{ extraObjectModules		= Nil
	, libraries					= Nil
	, method					= LM_Static
	, generate_relocations		= False
	, generate_link_map			= False
	, link_resources			= False
	, resource_source			= ""

	, generate_dll						= False
	, dll_export_list_name				= ""
	}

:: LinkMethod
	= LM_Static
//	| LM_Eager
	| LM_Dynamic
	| LM_StaticLibrary		// produce static library
	| LM_DynamicLibrary		// produce shared library

instance toString LinkMethod
where
	toString LM_Static	= "Static"
//	toString LM_Eager	= "Eager"
	toString LM_Dynamic	= "Dynamic"
	toString LM_StaticLibrary	= "StaticLibrary"
	toString LM_DynamicLibrary	= "DynamicLibrary"
	
instance fromString LinkMethod
where
	fromString "Static"			= LM_Static
	fromString "Eager"			= LM_Dynamic
	fromString "Dynamic"		= LM_Dynamic
	fromString "StaticLibrary"	= LM_StaticLibrary
	fromString "DynamicLibrary"	= LM_DynamicLibrary
/*
	fromString "Eager"			= LM_Eager
	fromString "Dynamic"		= LM_Dynamic
*/
	fromString _				= LM_Static

instance == LinkMethod
where
	(==) :: !LinkMethod !LinkMethod -> Bool
	(==) LM_Static			LM_Static			= True
//	(==) LM_Eager			LM_Eager			= True
	(==) LM_Dynamic			LM_Dynamic			= True
	(==) LM_StaticLibrary	LM_StaticLibrary	= True
	(==) LM_DynamicLibrary	LM_DynamicLibrary	= True
	(==) _					_					= False

//	Window position and size

::	WindowPos_and_Size	=
	{	posx	:: !Int
	,	posy	:: !Int
	,	sizex	:: !Int
	,	sizey	:: !Int
	}

instance == WindowPos_and_Size
where
	(==) :: !WindowPos_and_Size !WindowPos_and_Size -> Bool
	(==) pos1 pos2
		=	pos1.posx == pos2.posx &&
			pos1.posy == pos2.posy &&
			pos1.sizex == pos2.sizex &&
			pos1.sizey == pos2.sizey

DefWindowPos_and_Size :: WindowPos_and_Size
DefWindowPos_and_Size =
	{ posx=0
	, posy=0
	, sizex=500
	, sizey=300
	}


//	The Editor Options: default settings for the EditWindows.

::	EditOptions	=
	{/*	tabs		:: !Int
	,	fontname	:: !String				// !FontName
	,	fontsize	:: !Int					// !FontSize
	,	autoi		:: !Bool
	,*/	newlines	:: !NewlineConvention
/*	,	showtabs	:: !Bool
	,	showlins	:: !Bool
	,	showsync	:: !Bool
*/	}
	// (tabs,font&size,auto indent)

instance == EditOptions
where
	(==) :: !EditOptions !EditOptions -> Bool
	(==) eo1 eo2
		= True
/*		=	eo1.tabs == eo2.tabs &&
			eo1.EditOptions.fontname == eo2.EditOptions.fontname &&
			eo1.EditOptions.fontsize == eo2.EditOptions.fontsize &&
			eo1.EditOptions.autoi == eo2.EditOptions.autoi
*/

//	The Window parameters: edit options and window position and size
::	EditWdOptions	=
	{	eo			:: !EditOptions
	,	pos_size	:: !WindowPos_and_Size 
	}
	// edit options, window pos&size
	
//	The Code Generator Options: default settings for the code generator
::	CodeGenOptions =
	{ cs	:: !Bool
	, ci	:: !Bool
//	, kaf	:: !Bool
	, tp	:: !Processor
	}

instance == CodeGenOptions
where
	(==) :: !CodeGenOptions !CodeGenOptions -> Bool
	(==) cg1 cg2
		=	cg1.cs == cg2.cs &&
			cg1.ci == cg2.ci &&
			cg1.tp == cg2.tp

DefCodeGenOptions :: CodeGenOptions;
DefCodeGenOptions =
	{	cs		= False
	,	ci		= True
	,	tp		= CurrentProcessor
	}

//	The Application Options: default settings for the application.
::	ApplicationOptions	=
	{	hs								:: !Int
	,	ss								:: !Int
	,	em								:: !Int
	,	heap_size_multiple				:: !Int
	,	initial_heap_size				:: !Int
	,	set								:: !Bool
	,	sgc								:: !Bool
	,	pss								:: !Bool
	,	marking_collection				:: !Bool
	,	o								:: !Output
	,	fn								:: !String		// !FontName
	,	fs								:: !Int			// !FontSize
	,	write_stderr_to_file			:: !Bool
	,	memoryProfiling 				:: !Bool
	,	memoryProfilingMinimumHeapSize	:: !Int
	,	profiling 						:: !Bool
	,	stack_traces					:: !Bool
	,	standard_rte					:: !Bool		// DvA: use standard RTE (only in IDE)
	}

DefApplicationOptions :: ApplicationOptions;
DefApplicationOptions =
	{	hs	= 409600
	,	ss	= 102400
	,	em	= 81920
	,	heap_size_multiple = 4096/*16*256*/
	,	initial_heap_size = 204800
	,	set	= False
	,	sgc	= False
	,	pss	= False
	,	marking_collection = False
	,	o	= ShowConstructors
	,	fn	= "Courier"				//=> platform dependant?
	,	fs	= 9						//=> platform dependant?
	,	write_stderr_to_file
						= False
	,	memoryProfiling = False
	,	memoryProfilingMinimumHeapSize = 0
	,	profiling = False
	,	stack_traces = False
	,	standard_rte = True
	}
	
::	Output = BasicValuesOnly | ShowConstructors | NoConsole

instance == Output
where
	(==) :: Output Output -> Bool
	(==) BasicValuesOnly BasicValuesOnly
		=	True
	(==) ShowConstructors ShowConstructors
		=	True
	(==) NoConsole NoConsole
		=	True
	(==) _ _
		=	False;

instance fromString Output
where
	fromString :: {#Char} -> Output
	fromString "BasicValuesOnly"
		=	BasicValuesOnly
	fromString "ShowConstructors"
		=	ShowConstructors
	fromString "NoConsole"
		=	NoConsole
	fromString string
		=	UnexpectedConstructor "Output" string BasicValuesOnly

instance toString Output
where
	toString :: Output -> {#Char}
	toString BasicValuesOnly
		=	"BasicValuesOnly"
	toString ShowConstructors
		=	"ShowConstructors"
	toString NoConsole
		=	"NoConsole"

:: StaticLibInfo =
	{ sLibs :: !List Pathname
	, sDcls :: !List Modulename
	, sDeps :: !List Modulename
	}

isProjLibraryModule :: !.String !StaticLibInfo -> Bool
isProjLibraryModule mod info=:{sDcls}
	= StringOccurs mod sDcls

