implementation module EdCommandsMenu;

/*	The commands of the Command menu */

import StdBool;
import 	EdProgramState, EdProject, EdProjectUtils, EdPath, EdDialogs, EdWindows,
		EdSupport, EdCleanSystem, EdWindowsMenu;

(THEN2) infixl;
(THEN2) s f :== f e1 e2; { (e1,e2) = s };

::	CompileFun
	:==	Pathname -> Project -> SetMadeProjectFun -> ProgState -> * (IO -> ProgIO);
		
::	SetMadeProjectFun`
	:== Pathname -> Bool -> Bool -> ProgState -> *(IO -> ProgIO);

// Device function for the Compile Command

Compiler :: !ProgState !IO -> ProgIO;
Compiler prog io
	= Process "compiling" (CompileProjectModule Compilation) prog io;

CheckSyntax :: !ProgState !IO -> ProgIO;
CheckSyntax prog io
	= Process "checking" (CompileProjectModule SyntaxCheck) prog io;


// Device function for the Generate Assembly Command
	
GenerateAssembly :: !ProgState !IO -> ProgIO;
GenerateAssembly prog io
	= Process "generating code" (CompileAndGenCodeProjectModule AsmGeneration) prog io;

// Device function for the BringUpToDate Command

BringUpToDate :: !ProgState !IO -> ProgIO;
BringUpToDate prog io
	# (prio1,ok)	= SaveTheWindows True "bringing the project up to date" prog io;
	| ok
		= prio1 THEN2 BringProjectUpToDate uptodatemsg
		= prio1;
	where {
		uptodatemsg :: Pathname Bool Bool ProgState IO -> ProgIO;
		uptodatemsg path linked ok prog io
			| linked || not ok
				= (prog, CloseInfo io);
				= ShowInfo True True ["Project Is Up To Date"] prog io;
	};

// Device function for the Execute Command

Run	:: !ProgState !IO -> ProgIO;
Run prog io
	| ok
		=	prio1 THEN2 BringProjectUpToDate run;
		=	prio1;
	where {
		(prio1,ok)	= SaveTheWindows True "running" prog io;

		run :: Pathname Bool Bool ProgState IO -> ProgIO;
		run path linked ok prog io
			| ok
				= RunProgram path prog io1;
				= (prog, io1);
			where {
				io1	= CloseInfo io;
			};
	};

/*	Auxilary function used by Run to actuallly run the program */
	
RunProgram :: !Pathname !ProgState !IO -> ProgIO;
RunProgram path prog=:{ editor ={project}} io
	=	prio0;
	where {
	ao          = PR_GetApplicationOptions project;
	(prio0,_)	= Execute (UpdateInfoWindow ErrorWdID) path ao prog io;
	};

/*	Auxilary function used by Compile and GenerateAssembly to compile / generate code for the
	module in the front window */
	
Process :: !String !CompileFun !ProgState !IO -> ProgIO;
Process msg compile prog=:{editor={editwindows,project,defaults={edit,cgo,ao,po,linkOptions}}} io
	| not ok
		= (prog1,io1);
		= CloseWindow "" ErrorWdID prog1 io1			
			 THEN2 CloseWindow "" TypeWdID
			 THEN2 compile winpath project` setproject;
	where {
	(prog1,io1,ok)		= savewindows msg prog io;
	project` | prj_mod	= project;
						= PR_NewProject winpath edit wco cgo ao po Nil linkOptions;
	modname				= GetModuleName winpath;
	(prj_mod,_)			= PR_GetModuleInfo modname project;
	winpath				= front.wstate.pathname;
	wco					= front.wstate.WinState.co;
	(_,front)			= GetFrontWindow editwindows;
	
	savewindows :: !String !ProgState !IO -> (!ProgState, !IO, !Bool);
	savewindows msg prog io
		| not ok
			= (prog1,io1,False);
		 	= (prog2,io1,True);
		where {
			prog2		= {prog1 & editor={Editor | prog1.editor & project=PR_InitProject}};
			(prio0,ok)	= SaveTheWindows True msg prog io;
			(prog1,io1)	= prio0;
		};
	
	setproject :: Bool Bool Project ProgState IO -> ProgIO;
	setproject	ok newpaths newproject prog=:{editor} io
		| prj_mod
			= UpdateProjectWindowAndSaveProjectFile newproject prog io1;
			= ({prog & editor={Editor | editor & project=project}}, io1);
		where {
			io1	= CloseInfo io;
		};
	};

/*	Auxilary function used by Run and BringUpToDate to generate an up to date executable for the
	current project / .icl module in the front window */

BringProjectUpToDate :: !SetMadeProjectFun` !ProgState !IO -> ProgIO;
BringProjectUpToDate uptodate
		prog=:{editor=ed=:{editwindows,project,execwdid,defaults={edit,cgo,ao,po,linkOptions}}} io
	=	CloseWindow "" ErrorWdID prog0 io
		THEN2 CloseWindow "" TypeWdID 
		THEN2 MakeProject project` uptodate`;
	where {
	prog0					= {prog & editor={Editor | ed & project=PR_InitProject}};
	project` | projectset	= project;
							= PR_NewProject winpath weo wco cgo ao po Nil linkOptions;
	path | projectset 		= MakeExecPathname root;
							= MakeExecPathname winpath;
	winpath					= mainwd.wstate.pathname;
	root					= PR_GetRootPathName project;
	wco						= mainwd.wstate.WinState.co;
	weo						= {edit & eo = EW_GetEditOptions mainwd};
	projectset				= PR_ProjectSet project;
	mainwd					= GetWindow execwdid editwindows;
		
	uptodate` :: Bool Bool Project ProgState IO -> ProgIO;
	uptodate` compiled ok project prog io
		| projectset	= UpdateProjectWindowAndSaveProjectFile project prog io THEN2 uptodate path compiled ok
						= uptodate path compiled ok prog io;
	};
	
