fez-lisp 1.2.42 → 1.2.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "fez-lisp",
3
3
  "description": "Lisp interpreted & compiled to JavaScript",
4
4
  "author": "AT290690",
5
- "version": "1.2.42",
5
+ "version": "1.2.44",
6
6
  "type": "module",
7
7
  "main": "index.js",
8
8
  "keywords": [
package/src/compiler.js CHANGED
@@ -8,13 +8,22 @@ import {
8
8
  WORD
9
9
  } from './keywords.js'
10
10
  import { leaf, isLeaf } from './parser.js'
11
- const deepRename = (name, newName, tree) => {
11
+ const deepRenameTco = (name, newName, tree) => {
12
12
  if (!isLeaf(tree))
13
13
  for (const leaf of tree) {
14
14
  // Figure out a non mutable solution so
15
15
  // I can get rid of deep copy
16
16
  if (leaf[VALUE] === name) leaf[VALUE] = `()=>${newName}`
17
- deepRename(name, newName, leaf)
17
+ deepRenameTco(name, newName, leaf)
18
+ }
19
+ }
20
+ const deepRenameCache = (name, newName, tree) => {
21
+ if (!isLeaf(tree))
22
+ for (const leaf of tree) {
23
+ // Figure out a non mutable solution so
24
+ // I can get rid of deep copy
25
+ if (leaf[VALUE] === name) leaf[VALUE] = newName
26
+ deepRenameCache(name, newName, leaf)
18
27
  }
19
28
  }
20
29
  const earMuffsToLodashes = (name) => name.replace(new RegExp(/\*/g), '_')
@@ -166,16 +175,20 @@ const compile = (tree, Drill) => {
166
175
  }
167
176
  case KEYWORDS.DEFINE_VARIABLE: {
168
177
  const n = Arguments[0][VALUE]
169
- if (n.split(':')[0] === KEYWORDS.RECURSION) {
178
+ const prefix = n.split(':')[0]
179
+ if (prefix === KEYWORDS.RECURSION) {
170
180
  const name = lispToJavaScriptVariableName(n)
171
- const newName = `rec_${performance.now().toString().replace('.', 7)}`
181
+ const newName = `recursive_${performance
182
+ .now()
183
+ .toString()
184
+ .replace('.', 7)}`
172
185
  Drill.Variables.add(name)
173
186
  Drill.Variables.add(newName)
174
187
  Drill.Helpers.add('__tco')
175
188
  const functionArgs = Arguments.at(-1).slice(1)
176
189
  const body = functionArgs.pop()
177
190
  const FunctionDrill = { Variables: new Set(), Helpers: Drill.Helpers }
178
- deepRename(n, newName, body)
191
+ deepRenameTco(n, newName, body)
179
192
  const evaluatedBody = compile(body, FunctionDrill)
180
193
  const vars = FunctionDrill.Variables.size
181
194
  ? `var ${[...FunctionDrill.Variables].join(',')};`
@@ -186,6 +199,31 @@ const compile = (tree, Drill) => {
186
199
  )})=>{${vars}return ${evaluatedBody
187
200
  .toString()
188
201
  .trim()}}, ${newName})));`
202
+ } else if (prefix === KEYWORDS.CACHE) {
203
+ // memoization here
204
+ const name = lispToJavaScriptVariableName(n)
205
+ const newName = name.substring(2)
206
+ Drill.Variables.add(name)
207
+ Drill.Variables.add(newName)
208
+ const functionArgs = Arguments.at(-1).slice(1)
209
+ const body = functionArgs.pop()
210
+ deepRenameCache(n, newName, body)
211
+ const FunctionDrill = { Variables: new Set(), Helpers: Drill.Helpers }
212
+ const evaluatedBody = compile(body, FunctionDrill)
213
+ const vars = FunctionDrill.Variables.size
214
+ ? `var ${[...FunctionDrill.Variables].join(',')};`
215
+ : ''
216
+ return `(${name}=function(){const __${newName}_map = new Map();
217
+ var ${newName} = (function(${parseArgs(functionArgs, Drill)}){${vars};
218
+ var __key = [...arguments].join(',')
219
+ if (__${newName}_map.has(__key)) return __${newName}_map.get(__key)
220
+ else {
221
+ const __res = ${evaluatedBody.toString().trim()}
222
+ __${newName}_map.set(__key, __res)
223
+ return __res
224
+ }})
225
+ return ${newName}(...arguments)
226
+ });`
189
227
  } else {
190
228
  const name = lispToJavaScriptVariableName(n)
191
229
  Drill.Variables.add(name)
@@ -1,7 +1,7 @@
1
1
  import { TYPE, VALUE, WORD, KEYWORDS, FALSE, TRUE, TYPES } from './keywords.js'
2
2
  import { evaluate } from './evaluator.js'
3
3
  import { isForbiddenVariableName, stringifyArgs } from './utils.js'
4
- const keywords = {
4
+ export const keywords = {
5
5
  [KEYWORDS.REMAINDER_OF_DIVISION]: (args, env) => {
6
6
  if (args.length < 2)
7
7
  throw new RangeError(
@@ -820,5 +820,3 @@ const keywords = {
820
820
  throw new Error(expression.map((x) => String.fromCharCode(x)).join(''))
821
821
  }
822
822
  }
823
-
824
- export { keywords }
package/src/keywords.js CHANGED
@@ -57,7 +57,9 @@ export const KEYWORDS = {
57
57
  NOT_EQUAL_2: '<>',
58
58
  UNLESS: 'unless',
59
59
  LIST_TYPE: 'list',
60
- RECURSION: 'rec'
60
+
61
+ RECURSION: 'recursive',
62
+ CACHE: 'memoized'
61
63
  }
62
64
 
63
65
  export const TYPES = {
package/src/utils.js CHANGED
@@ -102,6 +102,8 @@ export const isForbiddenVariableName = (name) => {
102
102
  switch (name) {
103
103
  case '_':
104
104
  case KEYWORDS.DEFINE_VARIABLE:
105
+ case KEYWORDS.RECURSION:
106
+ case KEYWORDS.CACHE:
105
107
  return true
106
108
  default:
107
109
  return !isNaN(name[0])
@@ -262,9 +264,8 @@ export const fez = (source, options = {}) => {
262
264
  }
263
265
  } catch (error) {
264
266
  // console.log(error)
265
- const err = error.message
266
- .replace("'[object Array]'", '(array)')
267
- .replace('object', '(array)')
267
+ const err = error.message.replace("'[object Array]'", '(array)')
268
+ // .replace('object', '(array)')
268
269
  logError(err)
269
270
  if (options.throw) throw err
270
271
  return err
@@ -315,7 +316,7 @@ export const minify = (source) =>
315
316
  deSuggar(LISP.parse(replaceQuotes(replaceStrings(removeNoCode(source)))))
316
317
  )
317
318
  export const prep = (source) =>
318
- deSuggar(LISP.parse(replaceQuotes(replaceStrings(removeNoCode(source)))))
319
+ deSuggar(LISP.parse(removeNoCode(replaceQuotes(replaceStrings(source)))))
319
320
  export const src = (source, deps) => {
320
321
  source = prep(source)
321
322
  return LISP.source([
@@ -336,6 +337,10 @@ export const ast = (source, deps) => {
336
337
  ...source
337
338
  ]
338
339
  }
340
+ export const astWithStd = (source) => {
341
+ const parsed = prep(source)
342
+ return [...treeShake(parsed, std), ...parsed]
343
+ }
339
344
  export const dependencies = (source, deps) => {
340
345
  source = prep(source)
341
346
  return shakedList(