UNPKG

glisp

Version:

A simple lisp interpreter in JS.

1,206 lines (918 loc) 32.1 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('ramda'), require('immutable'), require('mathjs'), require('iterall')) : typeof define === 'function' && define.amd ? define(['exports', 'ramda', 'immutable', 'mathjs', 'iterall'], factory) : (factory((global.GLISP = global.GLISP || {}),global.R,global.Immutable,global.math,global.iterall)); }(this, function (exports,R,I,M,iterall) { 'use strict'; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; var defineProperty = function (obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); var toArray$1 = function (arr) { return Array.isArray(arr) ? arr : Array.from(arr); }; var toConsumableArray = function (arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } }; function isNumberString(string) { return !Number.isNaN(parseFloat(string)) && !Number.isNaN(Number(string)); } function isBignumberString(string) { return string.endsWith('M') && isNumberString(string.slice(0, -1)); } function createBignumber(string) { return M.bignumber(string.replace(/M$/, '')); } function stripQuotes(string) { return string.replace(/(^"|"$)/g, ''); } function isFractionString(x) { var _String$split = String(x).split('/'); var _String$split2 = toArray$1(_String$split); var numerator = _String$split2[0]; var denominator = _String$split2[1]; var rest = _String$split2.slice(2); return rest.length === 0 && isNumberString(numerator) && isNumberString(denominator); } function getMatchingStartingParens(x) { return { ')': ['('], '}': ['#{', '{'], ']': ['['] }[x] || []; } function isEndingParen(x) { return ['}', ')', ']'].includes(x); } function isStartingParen(x) { return ['#{', '{', '(', '['].includes(x); } function serializeArray(x) { return '[' + x.join(', ') + ']'; } function conj(collection, item) { if (I.List.isList(collection)) { return collection.push(item); } if (I.Set.isSet(collection)) { return collection.add(item); } if (I.OrderedSet.isOrderedSet(collection)) { return collection.add(item); } if (I.Map.isMap(collection)) { var _item = slicedToArray(item, 2); var key = _item[0]; var value = _item[1]; return collection.set(key, value); } if (I.OrderedMap.isOrderedMap(collection)) { var _item2 = slicedToArray(item, 2); var _key = _item2[0]; var _value = _item2[1]; return collection.set(_key, _value); } if (I.Stack.isStack(collection)) { return collection.push(item); } throw new Error('Collection is not an Immutable object'); } function create(prototype) { for (var _len = arguments.length, props = Array(_len > 1 ? _len - 1 : 0), _key2 = 1; _key2 < _len; _key2++) { props[_key2 - 1] = arguments[_key2]; } return Object.assign.apply(Object, [Object.create(prototype)].concat(props)); } function isEven(x) { return x % 2 === 0; } function isOdd(x) { return x % 2 === 1; } function transformFnToMacro(fn) { Object.defineProperty(fn, 'isMacro', { value: true }); return fn; } function isMacro(fn) { return fn.isMacro; } function canExecuteForm(form) { return I.Stack.isStack(form) && form.size > 0; } var reduce = R.curry(function (reducer, initial, collection) { var reduced = initial; iterall.forEach(collection, function (item) { reduced = reducer(reduced, item); }); return reduced; }); var conjunct = R.curry(function (fn, args) { var _args = toArray$1(args); var first = _args[0]; var rest = _args.slice(1); return reduce(function (_ref, current) { var _ref2 = slicedToArray(_ref, 2); var result = _ref2[0]; var old = _ref2[1]; return [result && fn(old, current), current]; }, [true, first], rest)[0]; }); var disjunct = R.curry(function (fn, args) { var _args2 = toArray$1(args); var first = _args2[0]; var rest = _args2.slice(1); return reduce(function (_ref3, current) { var _ref4 = slicedToArray(_ref3, 2); var result = _ref4[0]; var old = _ref4[1]; return [result || fn(old, current), current]; }, [false, first], rest)[0]; }); function toArray(collection) { return reduce(function (array, element) { return [].concat(toConsumableArray(array), [element]); }, [], collection); } function error() { for (var _len2 = arguments.length, message = Array(_len2), _key3 = 0; _key3 < _len2; _key3++) { message[_key3] = arguments[_key3]; } return new Error(message.join(' ')); } var mergeKvp = R.curry(function (next, keys, values) { var kvPairs = zip(toArray(keys), toArray(values), function () { return void 0; }); return R.reduce(merge, {}, kvPairs); function merge(running, _ref5) { var _ref6 = slicedToArray(_ref5, 2); var k = _ref6[0]; var v = _ref6[1]; return _extends({}, running, next(running, [k, v])); } }); function executableForm(name) { var _I$Stack; for (var _len3 = arguments.length, body = Array(_len3 > 1 ? _len3 - 1 : 0), _key4 = 1; _key4 < _len3; _key4++) { body[_key4 - 1] = arguments[_key4]; } return (_I$Stack = I.Stack).of.apply(_I$Stack, [Symbol.for(name)].concat(body)); } function zip(keys, values, factory) { return keys.map(function (key, i) { return [key, i >= values.length ? factory() : values[i]]; }); } function isGlobalRef(symbol) { return String(symbol).startsWith('Symbol(js/'); } function isMethodCall(form) { var fnName = form.first(); return (typeof fnName === 'undefined' ? 'undefined' : _typeof(fnName)) === 'symbol' && String(fnName).startsWith('Symbol(.'); } function getGlobal() { if (typeof window !== 'undefined') { return window; } if (typeof global !== 'undefined') { return global; } throw new Error('Could not find global object.'); } function getSymbolName(symbol) { return (/Symbol\(([^)]*)\)/.exec(String(symbol))[1] ); } function getMethodName(symbol) { return getSymbolName(symbol).replace(/^\./, ''); } function getGlobalRefName(symbol) { return getSymbolName(symbol).replace(/^js\//, ''); } function is(one, two) { if ([one, two].every(isGLISPNumber)) { return M.equal(one, two); } return I.is(one, two); } function isGLISPNumber(x) { if (R.is(Number, x)) { return true; } if (x) { return ['Fraction', 'BigNumber'].includes(x.type); } return false; } var Util = Object.freeze({ isNumberString: isNumberString, isBignumberString: isBignumberString, createBignumber: createBignumber, stripQuotes: stripQuotes, isFractionString: isFractionString, getMatchingStartingParens: getMatchingStartingParens, isEndingParen: isEndingParen, isStartingParen: isStartingParen, serializeArray: serializeArray, conj: conj, create: create, isEven: isEven, isOdd: isOdd, transformFnToMacro: transformFnToMacro, isMacro: isMacro, canExecuteForm: canExecuteForm, reduce: reduce, conjunct: conjunct, disjunct: disjunct, toArray: toArray, error: error, mergeKvp: mergeKvp, executableForm: executableForm, zip: zip, isGlobalRef: isGlobalRef, isMethodCall: isMethodCall, getGlobal: getGlobal, getSymbolName: getSymbolName, getMethodName: getMethodName, getGlobalRefName: getGlobalRefName, is: is }); function tokenize(program) { var _R$reduce = R.reduce(buildTokens, [I.List(), ''], program); var _R$reduce2 = slicedToArray(_R$reduce, 2); var tokens = _R$reduce2[0]; var buffer = _R$reduce2[1]; return tokens.push(buffer).filter(R.complement(isComment)).filter(Boolean).toJS(); } function buildTokens(_ref, token) { var _ref2 = slicedToArray(_ref, 2); var tokens = _ref2[0]; var buffer = _ref2[1]; if (isString(buffer)) { if (token === '"' && R.last(buffer) !== '\\') { return [tokens.push(buffer + token), '']; } if (token === '"' && R.last(buffer) === '\\') { return [tokens, buffer.substring(0, buffer.length - 1) + token]; } return [tokens, buffer + token]; } if (isComment(buffer)) { if (token === '\n') { return [tokens.push(buffer), '']; } return [tokens, buffer + token]; } if (token === '~') { return [tokens.push(buffer), token]; } if (buffer === '~') { if (token === '@') { return [tokens.push('~@'), '']; } return [tokens.push('~'), token]; } if (token === '#') { return [tokens.push(buffer), token]; } if (buffer === '#' && token === '{') { return [tokens.push('#{'), '']; } if (['{', '}', '[', ']', '(', ')', '\'', '`'].includes(token)) { return [tokens.push(buffer, token), '']; } if (isWhitespace(token)) { return [tokens.push(buffer), '']; } return [tokens, buffer + token]; } function isWhitespace(string) { return (/(\s|,)+/.test(string) ); } function isComment(string) { return string.startsWith(';'); } function isString(string) { return string.startsWith('"'); } var ErrorFactories = { DetectedUnendedParens: function DetectedUnendedParens(stack) { return new Error('Detected unclosed starting parens ' + serializeStack(stack)); }, DetectedIllegalEndingParen: function DetectedIllegalEndingParen(start, end) { return new Error('Starting paren ' + start + ' is followed by an illegal instance of ' + end); }, DetectedNoStartingParens: function DetectedNoStartingParens(end, expectedParens) { return new Error('Detected ending paren ' + end + ' but no matching ' + serializeArray(expectedParens)); } }; function createParenMap(tokens) { var stack = []; var map = {}; var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = tokens.entries()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var _step$value = slicedToArray(_step.value, 2); var index = _step$value[0]; var token = _step$value[1]; if (isStartingParen(token)) { stack.push({ index: index, paren: token }); } else if (isEndingParen(token)) { var endingParen = token; var matchingStartingParens = getMatchingStartingParens(endingParen); if (stack.length === 0) { throw ErrorFactories.DetectedNoStartingParens(endingParen, matchingStartingParens); } var top = stack.pop(); if (!matchingStartingParens.includes(top.paren)) { throw ErrorFactories.DetectedIllegalEndingParen(top.paren, endingParen); } map[top.index] = index; } } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } if (stack.length !== 0) { throw ErrorFactories.DetectedUnendedParens(stack); } return map; } function serializeStack(stack) { return serializeArray(stack.map(serializeArray)); } function createAtom(x) { if (x === 'true') { return true; } if (x === 'false') { return false; } if (isFractionString(x)) { return M.fraction(x); } if (isBignumberString(x)) { return createBignumber(x); } if (isNumberString(x)) { return Number(x); } if (isActualString(x)) { return stripQuotes(x); } return Symbol.for(x); } function isActualString(string) { return string.startsWith('"') && string.endsWith('"'); } function createAst(tokens) { var endingParen = createParenMap(tokens); return build(0)[0]; // TODO: Re-implement so JavaScript can do tail call optimization function build(i) { var token = tokens[i]; var end = endingParen[i]; if (token === '(') { return [buildSeq(I.Stack(), i, end, i + 1).reverse(), end + 1]; } if (token === '[') { return [buildSeq(I.List(), i, end, i + 1), end + 1]; } if (token === '#{') { return [buildSeq(I.Set(), i, end, i + 1), end + 1]; } if (token === '{') { return [buildMap(I.Map(), i, end, i + 1), end + 1]; } // TODO: Re-implement so reader macros aren't inlined if (['\'', '`', '~'].includes(token)) { if (i + 1 === tokens.length) { throw new Error(token + ' must be followed by a form, found none.'); } } if (token === '\'' || token === '`') { var _build = build(i + 1); var _build2 = slicedToArray(_build, 2); var form = _build2[0]; var next = _build2[1]; return [I.Stack.of(createAtom('quote'), form), next]; } if (token === '~') { var _build3 = build(i + 1); var _build4 = slicedToArray(_build3, 2); var _form = _build4[0]; var _next = _build4[1]; return [I.Stack.of(createAtom('unquote'), _form), _next]; } return [createAtom(token), i + 1]; } function buildSeq(seq, start, end, i) { if (end === i) { return seq; } var _build5 = build(i); var _build6 = slicedToArray(_build5, 2); var object = _build6[0]; var next = _build6[1]; return buildSeq(conj(seq, object), start, end, next); } function buildMap(map, start, end, i) { if (end === i) { return map; } var _build7 = build(i); var _build8 = slicedToArray(_build7, 2); var key = _build8[0]; var valueIndex = _build8[1]; if (valueIndex >= end) { throw new Error('Map expects an even number of arguments'); } var _build9 = build(valueIndex); var _build10 = slicedToArray(_build9, 2); var value = _build10[0]; var next = _build10[1]; return buildMap(conj(map, [key, value]), start, end, next); } } function parse(program) { return createAst(tokenize(program)); } function def(env, args) { var _args = slicedToArray(args, 2); var name = _args[0]; var value = _args[1]; if (args.size !== 2) { throw new Error('expected def to be called with 2 args, but called with ' + args.size); } env[name] = evaluate(env, value); return env[name]; } function $do(env, args) { /** * Immutable.Stack.prototype.map's iterates over the stack from bottom to top. * To evaluate the expressions top to bottom, we reverse the stack. * To return the result of the last expression, we return .first(). */ return args.reverse().map(evaluate(env)).first(); } var destructureIterables = mergeKvp(function (env, _ref) { var _ref2 = slicedToArray(_ref, 2); var k = _ref2[0]; var v = _ref2[1]; return destructure(k, v); }); function destructure(bindingKey, bindingValue) { if ((typeof bindingKey === 'undefined' ? 'undefined' : _typeof(bindingKey)) === 'symbol') { return defineProperty({}, bindingKey, bindingValue); } if (I.List.isList(bindingKey)) { if (!iterall.isCollection(bindingValue)) { throw error('Expected binding to support an iteration protocol, but got ' + bindingValue); } if (isVariadic$1(bindingKey)) { var argKeys = bindingKey.butLast().butLast(); var restKey = bindingKey.last(); var bindingValueSeq = I.Seq(bindingValue); var argValues = bindingValueSeq.slice(0, argKeys.size); var restValue = bindingValueSeq.slice(argKeys.size); return _extends({}, destructureIterables(argKeys, argValues), destructure(restKey, restValue)); } return destructureIterables(bindingKey, bindingValue); } throw error('Failed to destructure (' + bindingKey + ', ' + bindingValue + ')'); } function isVariadic$1(iterable) { var bindingKey = I.List(iterable); var variadicSymbol = Symbol.for('&'); if (bindingKey.size >= 1 && bindingKey.last() === variadicSymbol) { throw error('Unexpected \'&\' as last item in binding key', bindingKey); } if (bindingKey.size >= 2 && bindingKey.get(bindingKey.size - 2) === variadicSymbol) { if (bindingKey.butLast().butLast().contains(variadicSymbol)) { throw error('Detected two \'&\' in binding key', bindingKey); } return true; } return false; } function fn(env, args) { if (args.size === 0) { throw new Error('Expected function declaration to have an arguments list, but found none.'); } var _args = toArray$1(args); var argNames = _args[0]; var body = _args.slice(1); if (!I.List.isList(argNames)) { throw error('Expected function arguments to be a List, but got ' + argNames); } return function func() { for (var _len = arguments.length, argValues = Array(_len), _key = 0; _key < _len; _key++) { argValues[_key] = arguments[_key]; } var actualArgs = I.List(argValues); validateArguments(argNames, actualArgs); var fnEnv = create(env, destructure(argNames, actualArgs)); var result = evaluate(fnEnv, executableForm.apply(Util, ['do'].concat(toConsumableArray(body)))); return result; }; } function validateArguments(argNames, argValues) { var argCount = getArgumentCount(argNames); if (isVariadic(argNames)) { if (argValues.size < argCount) { throw error('Variadic function was declared with ' + argCount + ' arguments,', 'but only called with ' + argValues.size + ' arguments'); } } else { if (argValues.size !== argCount) { throw error('fn declared with ' + argCount + ' arguments was called with ' + argValues.size + ' arguments'); } } } function getArgumentCount(args) { var index = args.indexOf(Symbol.for('&')); return index === -1 ? args.size : index; } function isVariadic(args) { return args.indexOf(Symbol.for('&')) !== -1; } function $if(env, args) { var _args = slicedToArray(args, 3); var test = _args[0]; var conseq = _args[1]; var alt = _args[2]; return evaluate(env, test) ? evaluate(env, conseq) : evaluate(env, alt); } function $let(env, args) { var _args = toArray$1(args); var bindings = _args[0]; var body = _args.slice(1); if (bindings.size % 2 !== 0) { throw new Error('let bindings should be of even length'); } var bindingKeys = bindings.filter(function (_, i) { return isEven(i); }); var bindingValues = bindings.filter(function (_, i) { return isOdd(i); }); // console.log({ bindingKeys, bindingValues }); var bindingEnv = buildLetBindingEnv(env, bindingKeys, bindingValues); var letEnvironment = create(env, bindingEnv); return evaluate(letEnvironment, executableForm.apply(Util, ['do'].concat(toConsumableArray(body)))); } function buildLetBindingEnv(outerEnv) { for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } return mergeKvp.apply(Util, [function (env, _ref) { var _ref2 = slicedToArray(_ref, 2); var key = _ref2[0]; var value = _ref2[1]; var innerEnv = create(outerEnv, env); var evaluatedValue = evaluate(innerEnv, value); // console.log({ key, evaluatedValue }); return destructure(key, evaluatedValue); }].concat(args)); } function $macro(env, args) { var fn$$ = fn(env, args); return transformFnToMacro(fn$$); } function quote(env, args) { if (args.size !== 1) { throw new Error('quote expects 1 arg, but was called with ' + args.size + ' args'); } var _args = slicedToArray(args, 1); var item = _args[0]; return unquote(env, item); } function unquote(env, form) { if (!I.Iterable.isIterable(form)) { return form; } if (isUnquoteForm(form)) { if (form.size !== 2) { throw new Error('unquote expects 1 arg, but was called with ' + (form.size - 1) + ' args'); } var argToUnquote = form.get(1); return evaluate(env, argToUnquote); } if (I.Map.isMap(form) || I.OrderedMap.isOrderedMap(form)) { return form.mapEntries(function (_ref) { var _ref2 = slicedToArray(_ref, 2); var key = _ref2[0]; var value = _ref2[1]; return [unquote(env, key), unquote(env, value)]; }); } return form.map(function (item) { return unquote(env, item); }); } function isUnquoteForm(form) { return canExecuteForm(form) && form.first() === Symbol.for('unquote'); } function method(env, form) { if (form.size < 2) { throw new Error('Method calls must be made with an object as the first argument, found none.'); } var _form$rest$map = form.rest().map(evaluate(env)); var _form$rest$map2 = toArray$1(_form$rest$map); var object = _form$rest$map2[0]; var args = _form$rest$map2.slice(1); if (R.isNil(object)) { throw new Error('Unexpected method call on ' + object); } var prop = getMethodName(form.first()); if (!R.is(Function, object[prop])) { throw new Error('Expected "' + prop + '" in object ' + object + ' to be a function, instead found ' + object[prop]); } return object[prop].apply(object, toConsumableArray(args)); } function $throw(env, forms) { if (forms.size !== 1) { throw new Error('(throw ,,,) expects exactly one argument'); } var error = evaluate(env, forms.first()); if (!(error instanceof Error)) { throw new Error('(throw ...) expects the throw object to be an Error instance'); } throw error; } function executeForm(env, form) { if (form.first() === Symbol.for('let')) { return $let(env, form.rest()); } if (form.first() === Symbol.for('do')) { return $do(env, form.rest()); } if (form.first() === Symbol.for('def')) { return def(env, form.rest()); } if (form.first() === Symbol.for('if')) { return $if(env, form.rest()); } if (form.first() === Symbol.for('fn')) { return fn(env, form.rest()); } if (form.first() === Symbol.for('quote')) { return quote(env, form.rest()); } if (form.first() === Symbol.for('throw')) { return $throw(env, form.rest()); } if (form.first() === Symbol.for('unquote')) { throw new Error('\'unquote\' call must be inside a \'quote\' call'); } if (form.first() === Symbol.for('macro')) { return $macro(env, form.rest()); } if (isMethodCall(form)) { return method(env, form); } /** Procedure call */ var _form = toArray$1(form); var fnForm = _form[0]; var args = _form.slice(1); var fn$$ = evaluate(env, fnForm); if (typeof fn$$ !== 'function') { throw new Error('Tried to call ' + String(fn$$) + ' as a function.'); } if (isMacro(fn$$)) { return evaluate(env, fn$$.apply(undefined, toConsumableArray(args))); } return fn$$.apply(undefined, toConsumableArray(args.map(evaluate(env)))); } var evaluate = R.curry(function (env, form) { if ((typeof form === 'undefined' ? 'undefined' : _typeof(form)) === 'symbol') { return getSymbolValue(env, form); } if (canExecuteForm(form)) { return executeForm(env, form); } return evaluateColl(env, form); }); function evaluateColl(env, form) { if (shouldMap(form)) { return form.map(evaluate(env)); } if (shouldMapEntries(form)) { return form.mapEntries(function (_ref) { var _ref2 = slicedToArray(_ref, 2); var k = _ref2[0]; var v = _ref2[1]; return [evaluate(env, k), evaluate(env, v)]; }); } return form; } function getSymbolValue(env, symbol) { if (isGlobalRef(symbol)) { var Global = getGlobal(); var propName = getGlobalRefName(symbol); if (!(propName in Global)) { throw new Error('Could not locate ' + propName + ' on global object.'); } return Global[propName]; } if (!(symbol in env)) { throw new Error('Trying to access ' + String(symbol) + ' but none found in scope.'); } return env[symbol]; } var shouldMap = or(I.List.isList, I.Set.isSet, I.OrderedSet.isOrderedSet, I.Seq.isSeq, I.Stack.isStack); var shouldMapEntries = or(I.OrderedMap.isOrderedMap, I.Map.isMap); function or() { for (var _len = arguments.length, fns = Array(_len), _key = 0; _key < _len; _key++) { fns[_key] = arguments[_key]; } return function (x) { return reduce(function (old, fn) { return old || fn(x); }, false, fns); }; } var _ROOT_ENV; var ROOT_ENV = (_ROOT_ENV = {}, defineProperty(_ROOT_ENV, Symbol.for('+'), function () { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return args.reduce(function (x, y) { return M.add(x, y); }); }), defineProperty(_ROOT_ENV, Symbol.for('-'), function () { for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } return args.reduce(function (x, y) { return M.subtract(x, y); }); }), defineProperty(_ROOT_ENV, Symbol.for('*'), function () { for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { args[_key3] = arguments[_key3]; } return args.reduce(function (x, y) { return M.multiply(x, y); }); }), defineProperty(_ROOT_ENV, Symbol.for('/'), function () { for (var _len4 = arguments.length, args = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { args[_key4] = arguments[_key4]; } return args.reduce(function (x, y) { return M.divide(x, y); }); }), defineProperty(_ROOT_ENV, Symbol.for('!'), function (x) { return !x; }), defineProperty(_ROOT_ENV, Symbol.for('='), function () { for (var _len5 = arguments.length, args = Array(_len5), _key5 = 0; _key5 < _len5; _key5++) { args[_key5] = arguments[_key5]; } return conjunct(function (x, y) { return is(x, y); }, args); }), defineProperty(_ROOT_ENV, Symbol.for('<'), function () { for (var _len6 = arguments.length, args = Array(_len6), _key6 = 0; _key6 < _len6; _key6++) { args[_key6] = arguments[_key6]; } return conjunct(function (x, y) { return M.smaller(x, y); }, args); }), defineProperty(_ROOT_ENV, Symbol.for('>'), function () { for (var _len7 = arguments.length, args = Array(_len7), _key7 = 0; _key7 < _len7; _key7++) { args[_key7] = arguments[_key7]; } return conjunct(function (x, y) { return M.larger(x, y); }, args); }), defineProperty(_ROOT_ENV, Symbol.for('and'), function () { for (var _len8 = arguments.length, args = Array(_len8), _key8 = 0; _key8 < _len8; _key8++) { args[_key8] = arguments[_key8]; } return conjunct(function (x, y) { return x && y; }, args); }), defineProperty(_ROOT_ENV, Symbol.for('or'), function () { for (var _len9 = arguments.length, args = Array(_len9), _key9 = 0; _key9 < _len9; _key9++) { args[_key9] = arguments[_key9]; } return disjunct(function (x, y) { return x || y; }, args); }), defineProperty(_ROOT_ENV, Symbol.for('mod'), M.mod), defineProperty(_ROOT_ENV, Symbol.for('abs'), M.abs), defineProperty(_ROOT_ENV, Symbol.for('floor'), M.floor), defineProperty(_ROOT_ENV, Symbol.for('ceil'), M.ceil), defineProperty(_ROOT_ENV, Symbol.for('gcd'), M.gcd), defineProperty(_ROOT_ENV, Symbol.for('round'), M.round), defineProperty(_ROOT_ENV, Symbol.for('pow'), M.pow), defineProperty(_ROOT_ENV, Symbol.for('conj'), conj), defineProperty(_ROOT_ENV, Symbol.for('List'), function () { var _I$List; return (_I$List = I.List).of.apply(_I$List, arguments); }), defineProperty(_ROOT_ENV, Symbol.for('List?'), function (x) { return I.List.isList(x); }), defineProperty(_ROOT_ENV, Symbol.for('Set'), function () { var _I$Set; return (_I$Set = I.Set).of.apply(_I$Set, arguments); }), defineProperty(_ROOT_ENV, Symbol.for('Set?'), function (x) { return I.Set.isSet(x); }), defineProperty(_ROOT_ENV, Symbol.for('Stack'), function () { var _I$Stack; return (_I$Stack = I.Stack).of.apply(_I$Stack, arguments); }), defineProperty(_ROOT_ENV, Symbol.for('Stack?'), function (x) { return I.Stack.isStack(x); }), defineProperty(_ROOT_ENV, Symbol.for('Map'), function () { var _I$Map; return (_I$Map = I.Map).of.apply(_I$Map, arguments); }), defineProperty(_ROOT_ENV, Symbol.for('Map?'), function (x) { return I.Map.isMap(x); }), defineProperty(_ROOT_ENV, Symbol.for('Seq'), function () { var _I$Seq; return (_I$Seq = I.Seq).of.apply(_I$Seq, arguments); }), defineProperty(_ROOT_ENV, Symbol.for('Seq?'), function (x) { return I.Seq.isSeq(x); }), defineProperty(_ROOT_ENV, Symbol.for('aset'), function (object, key, value) { object[key] = value;return object; }), defineProperty(_ROOT_ENV, Symbol.for('aget'), function (object, key) { return object[key]; }), defineProperty(_ROOT_ENV, Symbol.for('fromJS'), I.fromJS), _ROOT_ENV); function run(code) { return evaluate(create(ROOT_ENV), parse(code)); } exports.run = run; exports.RootEnv = ROOT_ENV; exports.evaluate = evaluate; exports.parse = parse; exports.tokenize = tokenize; Object.defineProperty(exports, '__esModule', { value: true }); }));