(function (__global__) { var Session = (function () { var __struct__ = Object.create (null); var SESSION_STEP = Type.synonym ([ 'Session.SESSION_STEP', Type.modelPlus (Rec.create ({ input : EcmaScript.CODE })) (Rec.create ({ id : EcmaScript.ID, output : ANYTHING, error : STRING, // only either `output` or `error` must occur __output__ : ANYTHING, __error__ : STRING, // only either `__output__` or `__error__` must occur __bug__ : Type.nullify(Data.Moral.type(STRING)) })) ]); var DOC_STEP = Type.synonym ([ 'Session.DOC_STEP', Type.modelPlus (Rec.create ({ doc : Type.MARKDOWN })) (Rec.create ({ __doc__ : Data.HTML })) ]); var SESSION = Type.synonym ([ 'Session.SESSION', Type.list (Type.or (SESSION_STEP) (DOC_STEP)) ]); var defaultId = '_'; var fromFlatCode = function (flatCode) { var result = FlatCode.parseStringRecordList (flatCode); // `result` is of type `Data.Moral.type(Type.list(Type.record(STRING)))` if (Data.Moral.isBad (result)) { return Data.Moral.bad ( "`Session.fromFlatCode(flatCode)` error, when trying to convert `flatCode` into a string record list:\n" + Data.Moral.badValue (result) ); } else { var recL = Data.Moral.goodValue (result); // `recL` is here of type `Type.list (Type.record (STRING))` // change all `output` and `__output__` properties from type `STRING` to type `ANYTHING` for (var i = 0; i < recL.length; i++) { if ('output' in recL[i]) { try { var x = Val.read (recL[i]['output']); recL[i]['output'] = x; } catch (e) { return Data.Moral.bad ( "`Session.fromFlatCode(flatCode)` error, the `output` value `" + recL[i]['output'] + "` in the step `" + i + "` does not parse to a value." ) } } if ('__output__' in recL[i]) { try { var x = Val.read (recL[i]['__output__']); recL[i]['__output__'] = x; } catch (e) { return Data.Moral.bad ( "`Session.fromFlatCode(flatCode)` error, the `__output__` value `" + recL[i]['__output__'] + "` in the step `" + i + "` does not parse to a value." ) } } } // verify that `recL` is a session var c = SESSION.complain (recL); if (c) { return Data.Moral.bad ( "`Session.fromFlatCode(flatCode)` error.\n" + "`flatCode` does convert into a string record list, which is not a proper `SESSION`, however:\n" + c ); } else { return Data.Moral.good (recL); } } }; var toFlatCode = function (session) { var recL = []; for (var i = 0; i < session.length; i++) { var rec = Val.clone (session [i]); if ('output' in rec) { rec.output = Literal.block (output); } recL.push (rec); } return FlatCode.fromStringRecordList (recL); }; var run = function (session) { session = Val.clone (session); for (var i = 0; i < session.length; i++) { if ('input' in session[i]) { var step = session[i]; var id = ('id' in step ? step.id : defaultId); try { eval ("var " + id + " = " + step.input + ";"); var __output__ = eval (id); step.__output__ = __output__; } catch (e) { step.__error__ = e.toString(); } } } return session; }; var runnerCode = function (session) { var code = "var __session__ =" + "\n" + Str.indent(2)(Literal.block (session)) + ";\n"; for (var i = 0; i < session.length; i++) { if ('input' in session[i]) { var step = session[i]; var id = ('id' in step ? step.id : defaultId); code += "try {" + "\n" + " var " + id + " =" + "\n" + Str.indent(4)(step.input) + ";" + "\n" + " __session__[" + i + "].__output__ = " + id + ";" + "\n" + "} catch (e) {" + "\n" + " __session__[" + i + "].__error__ = e.toString();" + "\n" + "}" + "\n"; } } return ( "(function () {\n" + Str.indent(2)(code) + " return __session__;\n" + "}())" ); }; var bugChecker = function (session) { var checkedSession = []; for (var i = 0; i < session.length; i++) { var step = Val.clone (session [i]); if ('input' in step) { if (('output' in step || '__output__' in step) && ('error' in step || '__error__' in step)) { step.__bug__ = Data.Moral.bad ("Output and error clash!"); } else if ('output' in step && '__output__' in step) // and no 'error' and no '__error__' { if (Val.eq (step.output) (step.__output__)) { step.__bug__ = null; delete step.__output__; } else { step.__bug__ = Data.Moral.bad ("Predicted and real output are different!"); } } else if ('error' in step && '__error__' in step) // and no 'output' and no '__output__' { if (step.error === step.__error__) { step.__bug__ = null; delete step.__error__; } else { step.__bug__ = Data.Moral.good ("Not sure if the predicted and real error are really equal."); } } else if ('output' in step) // and no '__output__', no 'error' and no '__error__' { step.__bug__ = Data.Moral.good ("The real output is still undetermined."); } else if ('__output__' in step) // and no 'output', no 'error' and no '__error__' { if (Val.literal (step.__output__) === step.input) { step.__bug__ = null; delete step.__output__; } else { step.__bug__ = Data.Moral.good ("Not sure if the real output is correct."); } } else if ('error' in step) // and no 'output', no '__output__' and no '__error__' { step.__bug__ = Data.Moral.good ("Not sure if the predicted error is really thrown."); } else if ('__error__' in step) // and no 'output', no '__output__' and no 'error' { step.__bug__ = Data.Moral.good ("Not sure if the thrown error should be expected."); } else // so no 'output', no '__output__', no 'error' and no '__error__' { step.__bug__ = Data.Moral.good ("No predicted or real behavior mentioned here."); } } checkedSession.push (step); } return checkedSession; }; var bugSummary = function (session) { var n = 0; // for the total number of errors var bugs = ""; for (var i = 0; i < session.length; i++) { if ('__bug__' in session[i]) { var bug = session[i]['__bug__']; if (bug !== null && Data.Moral.isBad(bug)) { n++; bugs += "* Step " + i + " **" + Data.Moral.badValue (session[i]['__bug__']) + "**" + "\n\n" + Str.indent (8) (Literal.block (session[i])) + "\n\n" ; } } } if (n === 0) { return null; } else { return ( "" + n + " bugs are found!" + "\n\n" + bugs ); } }; var allMarkdownToHtml = function (session) { var session = Val.clone (session); for (var i = 0; i < session.length; i++) { if (DOC_STEP.chi (session [i])) { session[i]['__doc__'] = Markdown.toHtml (session [i]['doc']); delete session[i]['doc']; } } return session; }; var Css = (function () { var __struct__ = Object.create (null); var defaultStyle = 'color:#444444;background-color:#DDDDDD'; var userStyle = 'color:#666666;background-color:#FFFFFF;font-family:monospace;padding:1px'; var machineStyle = 'color:#666666;background-color:#FFFFFF;font-family:monospace;'; Object.defineProperty (__struct__, "defaultStyle", { writable: false, configurable: false, enumerable: true, value: defaultStyle }); Object.defineProperty (__struct__, "userStyle", { writable: false, configurable: false, enumerable: true, value: userStyle }); Object.defineProperty (__struct__, "machineStyle", { writable: false, configurable: false, enumerable: true, value: machineStyle }); return __struct__; }) (); var Symbols = (function () { var __struct__ = Object.create (null); var inputSymbol = "◀"; var outputSymbol = "▶"; var errorSymbol = "❌"; Object.defineProperty (__struct__, "inputSymbol", { writable: false, configurable: false, enumerable: true, value: inputSymbol }); Object.defineProperty (__struct__, "outputSymbol", { writable: false, configurable: false, enumerable: true, value: outputSymbol }); Object.defineProperty (__struct__, "errorSymbol", { writable: false, configurable: false, enumerable: true, value: errorSymbol }); return __struct__; }) (); var toHtml = function (session) { var id = defaultId; // updated in each call of `oneStepToHtml(step)` function userCode (code) { return '' + Html.entityify (code) + ''; } function machineCode (code) { return '' + Html.entityify (code) + ''; } function bugSymbol (bug) { // `bug` is of type `Type.nullify(Data.Moral.type(STRING))` if (bug === null) { return '✔'; } else if (Data.Moral.isGood (bug)) { return '???'; } else if (Data.Moral.isBad (bug)) { return '!!!'; } } function threeCellRow (leftCell, middleCell, rightCell) { return ( '