(* view.sig *) (* Copyright (C) 2008 Alley Stoughton This file is part of crypto, a cryptogram encoder/decoder. See the file COPYING.txt for copying and usage restrictions *) (* view - abstract user *) signature VIEW = sig (* basic symbol-based data *) include DATA (* primary commands - commands for primary command loop *) datatype primary_command = QuitPC | LexiconPC of sym_lexicon | EncodePC of msg | DecodePC of msg (* responses to primary commands *) datatype primary_response = (* responses from encode *) EncodeWordsNotInLexiconPR of (int * word)list (* wordes are labeled *) (* with line numbers, *) (* beginning with 1 *) | EncodeMultipleDecodingsPR | EncodeEncodingPR of msg (* responses from decode *) | DecodeNoDecodingsPR | DecodeMultipleDecodingsPR (* secondary commands - commands for secondary command loop *) datatype secondary_command = QuitSC | AbortSC | CheckSC | HintSC | ReplaceSC of sym * sym (* if ReplaceSC(a, b) is returned by *) (* secondaryInput(vd, pdm, olds, news), *) (* then a must be in olds, and b must *) (* be a symbol not in news *) | UndoSC (* responses to secondard commands *) datatype secondary_response = (* reponses from check *) CheckNotDecodableSR | CheckDecodedSR | CheckDecodableButNotDecodedSR (* responses from hint *) | HintNotDecodableSR | HintDecodedSR | HintReplaceSR of sym * sym (* HintReplaceSR(a, b) means *) (* old symbol a is being replaced *) (* by new symbol b *) (* data associated with the view *) type vd (* see the functions primary and secondary of ControllerFunc (controller-func.sml) to see the sequence in which the following functions will be called *) (* uses view data to get a primary command and new view data from user *) val primaryInput : vd -> vd * primary_command (* in a call secondaryInput(vd, pdm, olds, news), we require that olds be the old symbols of pdm, and that news be the new symbols of pdm secondaryInput uses the view data to inform user of current pdm, and then get a secondary command and new view data from user *) val secondaryInput : vd * pdm * sym_set * sym_set -> vd * secondary_command (* uses view data to inform user of response to a primary command, and to produce new view data *) val primaryOutput : vd * primary_response -> vd (* uses view data to inform user of response to a secondary command, and to produce new view data *) val secondaryOutput : vd * secondary_response -> vd (* abortable computation data: view data, plus the number of steps already completed *) type abort (* in a call abortable(vd, n, f), n must be >= 1 abortable(vd, n, f) uses the view data vd to tell the user that an abortable computation is being begun abortable then calls f with initial abortable computation data, consisting of vd plus the indication that 0 computation steps have been completed, and a function ca (check abort) of type abort -> abort * bool that f calls with the current abortable computation data whenever it begins a step of its computation the function f shouldn't communicate with the view or do any input/output operations directly; it should terminate normally; it should use the abortable computation data in a linear (single-use) manner when the number of computation steps recorded in the abortable computation data ab passed to ca is non-zero and divisible by n, then ca communicates this number of steps to the user, and finds out whether the user wants to abort the computation; if the user does wish to abort it, then it returns true, along with abortable computation data consisting of possibly new view data, as well as the number of steps in ab (no more computation steps will be completed); if the user does not wish to abort it, then it returns false, along with abortable computation data consisting of possibly new view data, as well as the number of steps in ab + 1 (one more computation step will have been completed by the next time ab is consulted) when the number of computation steps recorded in the abortable computation data ab passed to ca is zero or not divisible by n, then ca returns false, along with abortable computation data whose view data is as in ab, but whose number of steps is the number of steps in ab + 1 (one more computation step will have been completed by the next time ab is consulted) if f returns (ab, u, NONE), meaning it aborted with abortable computation data ab and secondary value u (but no primary value), then abortable returns (the view data of ab, u, NONE), after telling the user that the computation was aborted after completing the number of steps recorded in ab; if f returns (ab, u, SOME v), meaning that it terminated normally with abortable computation data ab, secondary value u and primary value v, then abortable returns (the view data of ab, u, SOME v), after telling the user that the computation terminated normally after the number of steps recorded in ab *) val abortable : vd * int * (abort * (abort -> abort * bool) -> abort * 'a * 'b option) -> vd * 'a * 'b option (* run(cmd, args, f) processes the command line arguments, initializes the view, producing view data vd, evaluates f vd, producing new view data, finalizes the view, and then returns a value of type OS.Process.status if the command line arguments are inappropriate, or if initializing the view fails, then it outputs an error message and returns OS.Process.failure, without first running f vd *) val run : string * string list * (vd -> vd) -> OS.Process.status end;