(*
*) (********************************************************************** Ephram Requirements Specification Objects and Operations Jon Doyel Fall 1994 For more infomation, please see the See AppleScript syntax *) op Display(ew:EphramWorld, f:Form)->Form; op DisplaySummary(ew:EphramWorld, f:Form)->fs:FormSummary post: HasAllSignificantFeatures(ew, f, fs); end; function HasAllSignificantFeatures(ew: EphramWorld, f:Form, fs:FormSummary)->boolean = ( let prefs = ew.prefs; let formprefs = FindPrefsForFormType(ew, f.type); forall (fn in formprefs) FindChunkByName(f,fn) iff FindChunkByName(fs,fn) ); op FindPrefsForFormType(ew:EphramWorld,type:FormType)->FieldNameList = FindPrefsForFormTypeJr(ew.prefs.summaries,type); op FindPrefsForFormTypeJr(sums:Summaries,type:FormType)->FieldNameList = if sums[1].type = type then sums[1].fnl else FindPrefsForFormTypeJr(sums[2:#sums],type); obj FieldName = string; obj FieldNameList = FieldName*; (************************************************************ * The following are the main, top-level Ephram operations. ************************************************************) op RecordViaAppleScriptEditor(ew:EphramWorld, start:StartRecordingAppleEventAndFile)-> (ew':EphramWorld) description: (* Tell the AppleScript Editor to run, recording whatever the user * does. We'll tell it to stop when the user comes back to Ephram and * chooses 'Stop Recording'. *); pre: IsScriptable(ew.ase) (* Sorry, but this is now known to be false, * so we need a fall back position. No fooling * here, we need to figure out how to make this * happen. *) and ew ?. teach; post: (* Everything in the output world is the same, except for the * script ed component, which is simply whatever the input * AppleScriptEditor produces inside itself, the actions of which * are opaque to Ephram; and possibly the info base, which may have * been modified during the running of the editor. We should note * that the info base could also be modified by backgrounding * Ephram with the finder, but this is beyond the scope of this * spec. *) (ew'.ib = ew'.ase.ib) and (ew'.rb = ew.ib) and (ew'.ws = ew.ws) and (* NOTE: the workspace is frozen in teach mode.*) (ew'.prefs = ew.prefs) and (ew'.state = ew.state) and (ew'.ase = WhatItDo(ew.ase)); end; function WhatItDo(ase:AppleScriptEditor)->(ase':AppleScriptEditor); (* An apple script editor at play with the user. Genuinely opaque to * Ephram, until it's done playing. Despite the flipancy here, is is * actually a fundamentally important principle. Viz., Eprham is not a * recorder at the Mac World level. Rather, lets the AppleScript * editor do this, and then uses its output to work on. *) op TellAppleScriptEditorToQuitAndSaveItsWork(ew:EphramWorld, StopRecordingAndSaveAppleEvent)-> (ew':EphramWorld) description: (* After the users tells Ephram to stop, Ephram in turn tells AS Ed to * stop, after which Ephram snags the the AppleScript that the Ed * built from the file that Ephram originally told the Ed to record * to. *); pre: not (ew ?. teach); post: as = ew.ase.as (* This is the "snagging", given that the * recording file has been abstracted out. * Rather, we snag the script directly from the * editor object, which concretely will be * implemented as a file read. *) and ew'.ib = Inference(ew.ase.as, ew.rb, nil); (* ^^^ user assistance, which Ephram cant give to itself *) end; op Run(ew:EphramWorld, mw:MacWorld)-> (mw':MacWorld, hfur:HelpFromUserRequest) description: (* If the ew.rb finds a match for the situation in the ew.ws, then it * gens the AppleScript to do what it should and runs it. The user, * of course, does not know or care that it's AppleScript running, but * we include it here to reminda us what is going on. *); pre: not (ew ?. teach); (* Prevents recursive teaching! *) post: if FindSituationMatch(ew.rb, ew.ws) != nil then mw' = RunAppleScript(mw, ew.ase, FindSituationMatch(ew.rb, ew.ws)) and hfur = nil else (mw' = mw) and (hfur = TeachMeDialog); end; val TeachMeDialog = "I dont understand, please help ..."; (* Where Ephram asks for help, expecting the user to enter teach mode. *) obj x; function FindSituationMatch(rb:RuleBase, ws:WorkSpace)-> (as:AppleScript); (* This function is the rule-based expert system running in action rule * mode, where an action rule generates apple script, not more rules. * Cf. the Inference function just below. *) function Inference(AppleScript, (* Recorded by the AS Ed *) RuleBase, (* Pre-inference rule base *) UserAssistance)-> (* Asked for when help is needed *) (RuleBase, (* Post-inference rule base *) UserExplanations);(* As appropriate and/or asked for *) (* This function is the rule-based expert system running in meta rule * mode, where a meta rule generates more rules. Cf. the * FindSituationMatch function just above. * * It's honestly not clear if a formal logic spec would be useful here * or not, given that this function will be implemented in some expert * system, the logic of which is comparable to RSL. Hence, we might * consider the expert system to be the spec itself. *) function RunAppleScript(mw:MacWorld, ase:AppleScriptEditor, as:AppleScript)-> (mw':MacWorld); (* The ultimately opaque function -- it does in the Mac World what * Ephram figured out should be done. *) end Ephram; (**)