UNPKG

@readable-js/core

Version:

ReadableJS is a toolkit for teachers to craft small demos that can be explored interactively.

102 lines (101 loc) 5.28 kB
import { isPattern } from '../../../../../enode-type-check'; import * as escodegen from 'escodegen'; function helperLOC(loc) { return [loc.start.line, loc.end.line]; } const ge = generateReadableExpression; export function generateReadableExpression(e, options, evaluateVar) { const m2 = new Map([ ['CallExpression', (exp) => [...helperLOC(exp.loc), `Call function ${evaluateVar[0]}`]], ['UpdateExpression', (exp) => [ ...helperLOC(exp.loc), `Increment <span class="${options.classNames.variable}">${evaluateVar[0]}</span> by <span class="${options.classNames.value}">1</span>` ]], ['AssignmentExpression', (exp) => { const varValue = `<span class="${options.classNames.value}">` + "${" + evaluateVar[0] + "}" + "</span>"; const varName = `<span class="${options.classNames.variable}">${evaluateVar[0]}</span>`; const right = `<span class="${options.classNames.expression}">${escodegen.generate(exp.right)}</span>`; const mapAssignmentExp = new Map([ ['=', (a) => `Set ${varName} to ${varValue}`], ['+=', (a) => `Add ${right} to ${varName} and set ${varName} to ${varValue}`], ['-=', (a) => `Subtract ${right} from ${varName} and set ${varName} to ${varValue}`], ['*=', (a) => `Multiply ${varName} by ${right} and set ${varName} to ${varValue}`], ['/=', (a) => `Divide ${varName} by ${right} and set ${varName} to ${varValue}`], ['%=', (a) => `Divide ${varName} by ${right} and set ${varName} to the remainder: ${varValue}`], ['**=', (a) => ``], ['<<=', (a) => ``], ['>>=', (a) => ``], ['>>>=', (a) => ``], ['|=', (a) => ``], ['^=', (a) => ``], ['&=', (a) => ``], ]); const mapAssignmentExpGet = mapAssignmentExp.get(exp.operator); return [...helperLOC(exp.loc), mapAssignmentExpGet ? mapAssignmentExpGet(exp) : '']; }] ]); const m2Get = m2.get(e.type); return [m2Get ? m2Get(e) : [...helperLOC(e.loc), '']]; } export function generateReadable(eNode, options, evaluateVar, ifConditionTest) { const m = new Map([ // return multiple message, one for each variable declaration ["VariableDeclaration", (e) => { if (!evaluateVar) { throw new Error('Unexpected case: evaluateVar undefined in generateReadable VariableDeclaration parser.'); } const messages = e.declarations.map((dec, i) => { const varToName = new Map([ ['let', 'variable'], ['var', 'variable'], ['const', 'constant'], ]); let createMessage = ''; if (isPattern.Identifier(dec.id)) { createMessage = `Create the ${varToName.get(e.kind)} <span class="${options.classNames.variable}">${dec.id.name}</span>`; } let initMessage = ''; if (!!dec.init) { initMessage = ` and set it to <span class="${options.classNames.value}">${"${" + evaluateVar[i] + "}"}</span>`; } let message = createMessage + initMessage; return [...helperLOC(dec.loc), message]; }); return messages; }], ["IfStatement", (e) => { return [ [ e.loc.start.line, e.test.loc.end.line, `${ifConditionTest ? 'Because ... evaluate to true' : 'Skip because ... evaluate to false'}`, ], ]; }], ["ExpressionStatement", (e) => { const messages = generateReadableExpression(e.expression, options, evaluateVar); return messages; }], ['WhileStatement', (e) => { return [ [e.loc.start.line, e.test.loc.end.line, ifConditionTest ? 'Because ...' : 'Because ... is not'], [e.loc.end.line, e.loc.end.line, ifConditionTest ? '... and try again' : '... stop looping'] ]; }], ['ForStatement', (e) => { var _a, _b; return [ [e.loc.start.line, (_b = (_a = e.test) === null || _a === void 0 ? void 0 : _a.loc.end.line) !== null && _b !== void 0 ? _b : e.loc.start.line, ifConditionTest ? 'Because ...' : 'Because ... is not'], [e.loc.end.line, e.loc.end.line, ifConditionTest ? '... and try again' : '... stop looping'] ]; }], ]); const parser = m.get(eNode.type); if (parser) { return parser(eNode); } else { console.warn(`No readable generated for type ${eNode.type}.`); return []; } }