UNPKG

js-slang

Version:

Javascript-based implementations of Source, written in Typescript

178 lines 7.04 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.draw_data = exports.list = exports.is_null = exports.tail = exports.head = exports.is_pair = exports.pair = exports.evaluateModuleFunction = exports.evaluateMath = exports.parse_int = exports.is_undefined = exports.is_boolean = exports.is_function = exports.is_string = exports.is_number = exports.prompt = exports.error = exports.stringify = exports.display = exports.get_time = void 0; const misc = require("../stdlib/misc"); const ast = require("../utils/ast/astCreator"); const errors_1 = require("../errors/errors"); const converter_1 = require("./converter"); const stepper_1 = require("./stepper"); const util_1 = require("./util"); // define builtins that takes in AST, and return AST // // if (context.chapter >= 1) { // defineBuiltin(context, 'get_time()', misc.get_time) function get_time() { return ast.literal(misc.get_time()); } exports.get_time = get_time; // defineBuiltin(context, 'display(val)', display) // ignore the "display" capability function display(val) { return val; } exports.display = display; // defineBuiltin(context, 'raw_display(str)', rawDisplay) // defineBuiltin(context, 'stringify(val)', stringify) function stringify(val) { return ast.literal((0, stepper_1.codify)(val)); } exports.stringify = stringify; // defineBuiltin(context, 'error(str)', misc.error_message) function error(val, str) { const output = (str === undefined ? '' : str + ' ') + stringify(val); throw new errors_1.BuiltInFunctionError(output); } exports.error = error; // defineBuiltin(context, 'prompt(str)', prompt) function prompt(str) { if (str.type !== 'Literal' || typeof str.value !== 'string') { throw new errors_1.BuiltInFunctionError('Argument to error must be a string.'); } const result = window.prompt(str.value); return ast.literal((result ? result : null)); } exports.prompt = prompt; // defineBuiltin(context, 'is_number(val)', misc.is_number) function is_number(val) { return ast.literal((0, util_1.isNumber)(val)); } exports.is_number = is_number; // defineBuiltin(context, 'is_string(val)', misc.is_string) function is_string(val) { return ast.literal(val.type === 'Literal' && misc.is_string(val.value)); } exports.is_string = is_string; // defineBuiltin(context, 'is_function(val)', misc.is_function) function is_function(val) { return ast.literal(val.type.includes('Function') || (0, util_1.isBuiltinFunction)(val)); } exports.is_function = is_function; // defineBuiltin(context, 'is_boolean(val)', misc.is_boolean) function is_boolean(val) { return ast.literal(val.type === 'Literal' && misc.is_boolean(val.value)); } exports.is_boolean = is_boolean; // defineBuiltin(context, 'is_undefined(val)', misc.is_undefined) function is_undefined(val) { return ast.literal(val.type === 'Identifier' && val.name === 'undefined'); } exports.is_undefined = is_undefined; // defineBuiltin(context, 'parse_int(str, radix)', misc.parse_int) function parse_int(str, radix) { if (str.type === 'Literal' && typeof str.value === 'string' && radix.type === 'Literal' && typeof radix.value === 'number' && Number.isInteger(radix.value) && 2 <= radix.value && radix.value <= 36) { return (0, converter_1.valueToExpression)(parseInt(str.value, radix.value)); } else { throw new Error('parse_int expects two arguments a string s, and a positive integer i between 2 and 36, inclusive.'); } } exports.parse_int = parse_int; // defineBuiltin(context, 'undefined', undefined) // defineBuiltin(context, 'NaN', NaN) // defineBuiltin(context, 'Infinity', Infinity) // // Define all Math libraries // const props = Object.getOwnPropertyNames(Math) // for (const prop of props) { // defineBuiltin(context, 'math_' + prop, Math[prop]) // } // } // evaluateMath(mathFn: string, ...args: substituterNodes): substituterNodes function evaluateMath(mathFn, ...args) { const fn = Math[mathFn.split('_')[1]]; if (!fn) { throw new errors_1.BuiltInFunctionError(`Math function ${mathFn} not found.`); } else if (args.some(arg => !(0, util_1.isNumber)(arg))) { throw new errors_1.BuiltInFunctionError(`Math functions must be called with number arguments`); } const jsArgs = args.map(converter_1.nodeToValue); return (0, converter_1.valueToExpression)(fn(...jsArgs)); } exports.evaluateMath = evaluateMath; // evaluateModuleFunction(mathFn: string, context: Context, ...args: substituterNodes): substituterNodes function evaluateModuleFunction(moduleFn, context, ...args) { const fn = context.runtime.environments[0].head[moduleFn]; if (!fn) { throw new errors_1.BuiltInFunctionError(`Module function ${moduleFn} not found.`); } const jsArgs = args.map(arg => (0, converter_1.nodeToValueWithContext)(arg, context)); return (0, converter_1.valueToExpression)(fn(...jsArgs), context); } exports.evaluateModuleFunction = evaluateModuleFunction; // if (context.chapter >= 2) { // // List library // defineBuiltin(context, 'pair(left, right)', list.pair) function pair(left, right) { if (left == null || right == null) { throw new errors_1.BuiltInFunctionError( //Count the number of arguments that are not undefined `Expected 2 arguments, but got ${[left, right].filter(x => x != undefined).length}`); } return ast.arrayExpression([left, right]); } exports.pair = pair; // defineBuiltin(context, 'is_pair(val)', list.is_pair) function is_pair(val) { if (val == null) { throw new errors_1.BuiltInFunctionError('Expected 1 argument, but got 0'); } return ast.literal(val.type === 'ArrayExpression' && val.elements.length === 2); } exports.is_pair = is_pair; // defineBuiltin(context, 'head(xs)', list.head) function head(xs) { if (is_pair(xs).value === false) { throw new errors_1.BuiltInFunctionError(`${(0, stepper_1.codify)(xs)} is not a pair`); } return xs.elements[0]; } exports.head = head; // defineBuiltin(context, 'tail(xs)', list.tail) function tail(xs) { if (is_pair(xs).value === false) { throw new errors_1.BuiltInFunctionError(`${(0, stepper_1.codify)(xs)} is not a pair`); } return xs.elements[1]; } exports.tail = tail; // defineBuiltin(context, 'is_null(val)', list.is_null) function is_null(val) { return ast.literal(val.type === 'Literal' && val.value === null); } exports.is_null = is_null; // defineBuiltin(context, 'list(...values)', list.list) function list(...values) { let ret = ast.primitive(null); for (const v of values.reverse()) { ret = pair(v, ret); } return ret; } exports.list = list; // defineBuiltin(context, 'draw_data(xs)', visualiseList) function draw_data(...xs) { if (xs.length === 0) { return ast.primitive(undefined); } else { return xs[0]; } } exports.draw_data = draw_data; //# sourceMappingURL=lib.js.map