implementation module LinkerMessages;

//1.3
from StdString import String, toString, +++;
//3.1
/*2.0
import StdEnv;
0.2*/
from StdBool import not;
from StdList import isEmpty, ++;

// Linker Messages; messages should added in reverse order
:: LinkerMessagesState = { 
		ok						:: !Bool
	,	messages				:: LinkerMessages
	};
	
:: LinkerMessages :== [LinkerMessage];

:: LinkerMessage 
	= LinkerError !String
	| LinkerWarning !String
	| Verbose !String
	;
	
instance toString LinkerMessage
where {
	toString (LinkerError error)
		= "Linker error: " +++ error;
	toString (LinkerWarning warning)
		= "Linker warning: " +++ warning;
	toString (Verbose msg)
		= "Linker message: " +++ msg;
};
	
// Operations on Linker Messages
DefaultLinkerMessages :: !LinkerMessagesState;
DefaultLinkerMessages 
	= { LinkerMessagesState |
		ok					= True
	,	messages			= []
	};
	

class LinkError .a
where {
	isLinkerErrorOccured :: !.a -> (!Bool,!.a);
	
	addLinkMessage :: !LinkerMessage !.a -> !.a
};

//1.3
instance LinkError !LinkerMessagesState
//3.1
/*2.0
instance LinkError LinkerMessagesState
0.2*/
where {
	isLinkerErrorOccured state=:{ok} = (ok,state);
	
	addLinkMessage message linker_message_state
		= addLinkerMessage message linker_message_state
};

isLinkerError (LinkerError _) = True;
isLinkerError _ = False;

strip_linker_message (LinkerError s)	= s;
strip_linker_message (LinkerWarning s)	= s;
strip_linker_message (Verbose s)		= s;
import RWSDebugChoice;
import StdList;

from StdMisc import abort;
setLinkerMessages :: !LinkerMessages !.LinkerMessagesState -> !.LinkerMessagesState;
setLinkerMessages linker_messages linker_messages_state=:{messages}
	| True <<- (map strip_linker_message linker_messages)

	#! linker_errors
		= [ m \\ m <- linker_messages | isLinkerError m];
	= { linker_messages_state &
		ok = isEmpty linker_errors
	,	messages = messages ++ linker_messages 
	};	
setLinkerMessages _ _
	= abort "setLinkerMessage: mismatch";
	
setLinkerError error :== setLinkerMessages [LinkerError error] DefaultLinkerMessages;

getLinkerMessages :: !LinkerMessagesState -> [String];
getLinkerMessages {messages}
	= [ toString m \\ m <- messages ];
	
get_LinkerMessages :: !LinkerMessagesState -> !LinkerMessages;
get_LinkerMessages {messages}
	= messages;
	
	
addLinkerMessage message linker_messages_state :== setLinkerMessages [message] linker_messages_state;

// ADDED
class AddMessage .a 
where {
	AddMessage :: !LinkerMessage !*a -> !*a;
	
	IsErrorOccured :: !*a -> !(!Bool,!*a);
	
	GetLinkerMessages :: !*a -> (!LinkerMessages,!*a);
	
	SetLinkerMessages :: !LinkerMessages !*a -> !*a
};