fez-lisp 1.5.201 → 1.6.0

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.5.201",
5
+ "version": "1.6.0",
6
6
  "type": "module",
7
7
  "main": "index.js",
8
8
  "keywords": [
@@ -25,7 +25,7 @@
25
25
  "build": "node ./lib/builder.js",
26
26
  "fez": "node main.js",
27
27
  "test": "mocha",
28
- "examples": "node ./examples/2015/test.spec.js && node ./examples/2019/test.spec.js && node ./examples/2020/test.spec.js && node ./examples/2021/test.spec.js && node ./examples/2023/test.spec.js && node ./examples/2024/test.spec.js"
28
+ "examples": "node ./examples/leetcode/test.spec.js && node ./examples/2015/test.spec.js && node ./examples/2019/test.spec.js && node ./examples/2020/test.spec.js && node ./examples/2021/test.spec.js && node ./examples/2023/test.spec.js && node ./examples/2024/test.spec.js"
29
29
  },
30
30
  "license": "MIT",
31
31
  "devDependencies": {
package/src/check.js CHANGED
@@ -215,7 +215,7 @@ export const setTypeToCollection = (stats) =>
215
215
  (stats[TYPE_PROP][0] = COLLECTION)
216
216
  export const setTypeToAbstraction = (stats) =>
217
217
  (isUnknownType(stats) || isAnyType(stats)) && (stats[TYPE_PROP][0] = APPLY)
218
- export const setReturnToAbbstraction = (stats) =>
218
+ export const setReturnToAbstraction = (stats) =>
219
219
  isUnknownReturn(stats) && (stats[RETURNS][0] = APPLY)
220
220
  export const setTypeRef = (stats, value) =>
221
221
  (isUnknownType(stats) || isAnyType(stats)) &&
@@ -238,8 +238,8 @@ export const setTypeToReturnRef = (stats, value) => {
238
238
  // Change main type if unknown
239
239
  if (isUnknownType(stats) || isAnyType(stats))
240
240
  if (!isUnknownReturn(value)) stats[TYPE_PROP][0] = value[RETURNS][0]
241
- // TODO: Figure out what we do if generic thigns get infered
242
- // cange sub type if it doesn't have
241
+ // TODO: Figure out what we do if generic things get inferred
242
+ // change sub type if it doesn't have
243
243
  if (!hasSubType(stats) || getSubType(stats).has(UNKNOWN))
244
244
  if (hasSubReturn(value)) stats[TYPE_PROP][1] = value[RETURNS][1]
245
245
  }
@@ -263,13 +263,13 @@ export const setType = (stats, value) =>
263
263
  ((stats[TYPE_PROP][0] = value[TYPE_PROP][0]),
264
264
  value[TYPE_PROP][1] && (stats[TYPE_PROP][1] = value[TYPE_PROP][1]))
265
265
  export const setSubType = (stats, value) =>
266
- // makes no senseto protect this for now
266
+ // makes no sense to protect this for now
267
267
  hasSubType(value) && (stats[TYPE_PROP][1] = value[TYPE_PROP][1])
268
268
  export const setPropToSubType = (stats, prop, value) =>
269
- // makes no senseto protect this for now
269
+ // makes no sense to protect this for now
270
270
  hasSubType(value) && (stats[prop][1] = value[TYPE_PROP][1])
271
271
  export const setPropToSubReturn = (stats, prop, value) =>
272
- // makes no senseto protect this for now
272
+ // makes no sense to protect this for now
273
273
  hasSubReturn(value) && (stats[prop][1] = value[RETURNS][1])
274
274
  export const setTypeToReturn = (stats, value) =>
275
275
  (isUnknownType(stats) || isAnyType(stats)) &&
@@ -297,11 +297,18 @@ export const getSubType = (stats) => stats && stats[TYPE_PROP][1]
297
297
  export const hasSubType = (stats) => stats && stats[TYPE_PROP][1] instanceof Set
298
298
  export const getSubReturn = (stats) => stats && stats[RETURNS][1]
299
299
  export const hasSubReturn = (stats) => stats && stats[RETURNS][1] instanceof Set
300
- export const isUknownSubReturn = (stats) =>
300
+ export const isUnknownSubReturn = (stats) =>
301
301
  !hasSubReturn(stats) ||
302
- (stats[RETURNS][1].size === 1 && stats[RETURNS][1].has(UNKNOWN))
303
- export const isUknownSubType = (stats) =>
302
+ (stats &&
303
+ stats[RETURNS] &&
304
+ stats[RETURNS][1] &&
305
+ stats[RETURNS][1].size === 1 &&
306
+ stats[RETURNS][1].has(UNKNOWN))
307
+ export const isUnknownSubType = (stats) =>
304
308
  hasSubType(stats) &&
309
+ stats &&
310
+ stats[TYPE_PROP] &&
311
+ stats[TYPE_PROP][1] &&
305
312
  stats[TYPE_PROP][1].size === 1 &&
306
313
  stats[TYPE_PROP][1].has(UNKNOWN)
307
314
  export const isAtomType = (stats) =>
@@ -315,7 +322,7 @@ export const equalTypes = (a, b) => {
315
322
  if (!isSameType) return false
316
323
  return true
317
324
  }
318
- const isRedifinedInLambda = (env, name, exp) => {
325
+ const isRedefinedInLambda = (env, name, exp) => {
319
326
  if (exp.slice(1, -1).some((x) => x[VALUE] === name)) return true
320
327
  else if (
321
328
  exp
@@ -424,12 +431,12 @@ const checkPredicateNameDeep = (name, exp, rest, returns) => {
424
431
  [WORD, name],
425
432
  isLeaf(fn)
426
433
  ? fn // when apply is a word (let x? (lambda (apply [] array:empty!)))
427
- : drillReturnType(fn, (r) => r[VALUE] === KEYWORDS.CALL_FUNCTION) // when apply is an annonymous lambda // (let fn? (lambda x (apply x (lambda x (array:empty! [])))))
434
+ : drillReturnType(fn, (r) => r[VALUE] === KEYWORDS.CALL_FUNCTION) // when apply is an anonymous lambda // (let fn? (lambda x (apply x (lambda x (array:empty! [])))))
428
435
  ])
429
436
  }
430
437
  return checkPredicateName(exp, [[WORD, name], returns])
431
438
  }
432
- const fillUknownArgs = (n) =>
439
+ const fillUnknownArgs = (n) =>
433
440
  Array.from({ length: n })
434
441
  .fill(null)
435
442
  .map(() => ({
@@ -510,7 +517,7 @@ const IfApplyBranch = ({
510
517
  setPropToAbstraction(ref[STATS], prop)
511
518
  ref[STATS][RETURNS] = [UNKNOWN]
512
519
  ref[STATS][ARG_COUNT] = re.length - 2
513
- ref[STATS][ARGUMENTS] = fillUknownArgs(re.length - 2)
520
+ ref[STATS][ARGUMENTS] = fillUnknownArgs(re.length - 2)
514
521
  break
515
522
  case KEYWORDS.CALL_FUNCTION:
516
523
  if (re.at(-1)[TYPE] === WORD) {
@@ -538,14 +545,14 @@ const IfApplyBranch = ({
538
545
  const ifExpression = ({ re, env, ref, prop, stack, exp, check }) => {
539
546
  if (re[0][TYPE] === ATOM || re[1][TYPE] === ATOM)
540
547
  return setPropToAtom(ref[STATS], prop)
541
- // TODO check that both brancehs are predicates if one is
548
+ // TODO check that both branches are predicates if one is
542
549
  else {
543
550
  const conc = isLeaf(re[0]) ? re[0] : re[0][0]
544
551
  const alt = isLeaf(re[1]) ? re[1] : re[1][0]
545
552
  const concequent = env[conc[VALUE]]
546
553
  const alternative = env[alt[VALUE]]
547
554
  // TODO make this more simple - it's so many different things just because types are functions or not
548
- // WHY not consiter making return types for everything
555
+ // WHY not consider making return types for everything
549
556
  if (concequent)
550
557
  if (conc[TYPE] === WORD) {
551
558
  return setPropToTypeRef(ref[STATS], prop, concequent[STATS])
@@ -869,8 +876,7 @@ const resolveReturnType = ({
869
876
  return true
870
877
  } else if (!env[returns[VALUE]]) return false
871
878
  else if (getType(env[returns[VALUE]][STATS]) === APPLY) {
872
- if (returns[TYPE] === WORD)
873
- setReturnToAbbstraction(env[name][STATS])
879
+ if (returns[TYPE] === WORD) setReturnToAbstraction(env[name][STATS])
874
880
  else {
875
881
  // ALWAYS APPLY
876
882
  // rest.at(-1)[0][TYPE] === APPLY
@@ -897,9 +903,9 @@ const resolveReturnType = ({
897
903
  case KEYWORDS.ANONYMOUS_FUNCTION:
898
904
  {
899
905
  // TODO figure out a better way to do this
900
- // This is insitialisation of identity or any other
906
+ // This is initialization of identity or any other
901
907
  // function that returns it's argument
902
- // Redifine the variable but since it's an error doing that
908
+ // Redefine the variable but since it's an error doing that
903
909
  // Delete it first
904
910
  delete env[name]
905
911
  check(
@@ -914,7 +920,7 @@ const resolveReturnType = ({
914
920
  // const n = genericReturn.length
915
921
  // setTypeToAbstraction(env[name][STATS])
916
922
  // env[name][STATS][ARG_COUNT] = n - 2
917
- // env[name][STATS][ARGUMENTS] = fillUknownArgs(
923
+ // env[name][STATS][ARGUMENTS] = fillUnknownArgs(
918
924
  // n - 2
919
925
  // )
920
926
  // checkReturnType({
@@ -1055,7 +1061,7 @@ export const typeCheck = (ast, ctx = SPECIAL_FORM_TYPES) => {
1055
1061
  )
1056
1062
  // TODO delete this maybe
1057
1063
  // #C2
1058
- // It will not be possilbe to know return type
1064
+ // It will not be possible to know return type
1059
1065
  const match1 = () => {
1060
1066
  const actual = local[lambdaName]
1061
1067
  const expected = args[i]
@@ -1165,7 +1171,7 @@ export const typeCheck = (ast, ctx = SPECIAL_FORM_TYPES) => {
1165
1171
  case WORD:
1166
1172
  if (!isSpecial)
1167
1173
  stagger(stack, 'append', [first, env], () => {
1168
- // Figure out how to determine if varible is define after it's used
1174
+ // Figure out how to determine if variable is define after it's used
1169
1175
  if (env[first[VALUE]] === undefined) {
1170
1176
  throw new TypeError(
1171
1177
  `Trying to access undefined variable ${first[VALUE]} (check #11)`
@@ -1188,11 +1194,11 @@ export const typeCheck = (ast, ctx = SPECIAL_FORM_TYPES) => {
1188
1194
  exp
1189
1195
  )})`
1190
1196
  )
1191
- // TODO check leT define types
1197
+ // TODO check let define types
1192
1198
  const name = rest[0][VALUE]
1193
1199
  if (env.hasOwnProperty(name))
1194
1200
  throw new ReferenceError(
1195
- `Attempting to rediclare (${name}) which was previously declared in this scope (${stringifyArgs(
1201
+ `Attempting to redeclare (${name}) which was previously declared in this scope (${stringifyArgs(
1196
1202
  exp
1197
1203
  )})`
1198
1204
  )
@@ -1247,7 +1253,7 @@ export const typeCheck = (ast, ctx = SPECIAL_FORM_TYPES) => {
1247
1253
  retried: 0,
1248
1254
  counter: 0,
1249
1255
  [ARG_COUNT]: n - 2,
1250
- [ARGUMENTS]: fillUknownArgs(n - 2),
1256
+ [ARGUMENTS]: fillUnknownArgs(n - 2),
1251
1257
  [RETURNS]: [UNKNOWN]
1252
1258
  }
1253
1259
  }
@@ -1287,7 +1293,7 @@ export const typeCheck = (ast, ctx = SPECIAL_FORM_TYPES) => {
1287
1293
  })
1288
1294
  }
1289
1295
  resolve()
1290
- if (isUknownSubType(env[name][STATS]))
1296
+ if (isUnknownSubType(env[name][STATS]))
1291
1297
  stagger(stack, 'prepend', exp, () => {
1292
1298
  once(env[name][STATS], exp, stack, () => {
1293
1299
  setPropToCollection(env[name][STATS], TYPE_PROP)
@@ -1303,12 +1309,12 @@ export const typeCheck = (ast, ctx = SPECIAL_FORM_TYPES) => {
1303
1309
  checkPredicateName(exp, rest)
1304
1310
  const isLeafNode = isLeaf(rightHand)
1305
1311
  if (isLeafNode && rightHand[TYPE] === WORD) {
1306
- // TODO make sure this prevents the assigment all together
1312
+ // TODO make sure this prevents the assignment all together
1307
1313
  if (env[rest[1][VALUE]] === undefined)
1308
1314
  throw new TypeError(
1309
1315
  `Trying to access undefined variable ${rest[1][VALUE]} (check #22)`
1310
1316
  )
1311
- // Used to be checkin if it's an assigment to a special form
1317
+ // Used to be checking if it's an assignment to a special form
1312
1318
  // but this should not cause problems
1313
1319
  // env[name] = SPECIAL_FORMS_SET.has(rest[1][VALUE])
1314
1320
  // ? structuredClone(env[rest[1][VALUE]])
@@ -1412,7 +1418,7 @@ export const typeCheck = (ast, ctx = SPECIAL_FORM_TYPES) => {
1412
1418
  if (isLeaf(returns)) {
1413
1419
  // TODO figure out what we do here
1414
1420
  // this here is a variable WORD
1415
- // so return type of that function is that varible type
1421
+ // so return type of that function is that variable type
1416
1422
  switch (returns[TYPE]) {
1417
1423
  case ATOM:
1418
1424
  setReturnToAtom(ref[STATS])
@@ -1469,9 +1475,7 @@ export const typeCheck = (ast, ctx = SPECIAL_FORM_TYPES) => {
1469
1475
  // default:
1470
1476
  // if (copy[ret[VALUE]]) {
1471
1477
  // if (isUnknownReturn(copy[ret[VALUE]][STATS])) {
1472
- // once(ref[STATS], [returns, copy], stack, () => {
1473
- // setReturnRef(ref[STATS], copy[ret[VALUE]][STATS])
1474
- // })
1478
+ // once(ref[STATS], copy[ret[VALUE]][STATS])
1475
1479
  // } else setReturnRef(ref[STATS], copy[ret[VALUE]][STATS])
1476
1480
  // } else
1477
1481
  // stagger(stack, 'append', [ret, copy], () => {
@@ -1541,13 +1545,13 @@ export const typeCheck = (ast, ctx = SPECIAL_FORM_TYPES) => {
1541
1545
  }) (${stringifyArgs(exp)}) (check #12)`
1542
1546
  )
1543
1547
  else if (!env[first[VALUE]][STATS][ARG_COUNT]) {
1544
- // TODO recursively take return type of applicaion
1548
+ // TODO recursively take return type of application
1545
1549
  // FN ASSIGMENT
1546
- // ASSIGMENT of paramaters of lambda that are a lambda
1550
+ // ASSIGMENT of parameters of lambda that are a lambda
1547
1551
  // minus one to remove the body
1548
1552
  env[first[VALUE]][STATS][TYPE_PROP] = [APPLY]
1549
1553
  env[first[VALUE]][STATS][ARG_COUNT] = rest.length
1550
- env[first[VALUE]][STATS][ARGUMENTS] = fillUknownArgs(
1554
+ env[first[VALUE]][STATS][ARGUMENTS] = fillUnknownArgs(
1551
1555
  rest.length
1552
1556
  )
1553
1557
  for (let i = 0; i < rest.length; ++i) {
@@ -1569,7 +1573,7 @@ export const typeCheck = (ast, ctx = SPECIAL_FORM_TYPES) => {
1569
1573
  // case ATOM:
1570
1574
  // break
1571
1575
  case APPLY:
1572
- // passing arg asA APPLICATION
1576
+ // passing arg as a APPLICATION
1573
1577
  if (isUnknownType(arg[i][STATS]))
1574
1578
  setTypeToReturnRef(
1575
1579
  arg[i][STATS],
@@ -1577,7 +1581,7 @@ export const typeCheck = (ast, ctx = SPECIAL_FORM_TYPES) => {
1577
1581
  )
1578
1582
  break
1579
1583
  case WORD:
1580
- // if param is a word we assosiate them by referanc
1584
+ // if param is a word we associate them by reference
1581
1585
  // if (isUnknownType(arg[i][STATS]))
1582
1586
  setStatsRef(arg[i], env[ARG[VALUE]])
1583
1587
  break
@@ -1611,7 +1615,7 @@ export const typeCheck = (ast, ctx = SPECIAL_FORM_TYPES) => {
1611
1615
  env[name][STATS][ARG_COUNT] !==
1612
1616
  args[i][STATS][ARG_COUNT]
1613
1617
  ) {
1614
- // TODO: Investigate why there used to be and error called #111 with this condition if (args[i][STATS][ARG_COUNT] === undefined)
1618
+ // TODO: Investigate why there used to be an error called #111 with this condition if (args[i][STATS][ARG_COUNT] === undefined)
1615
1619
  if (getType(args[i][STATS]) === APPLY)
1616
1620
  throw new TypeError(
1617
1621
  `Incorrect number of arguments for (${
@@ -1749,7 +1753,7 @@ export const typeCheck = (ast, ctx = SPECIAL_FORM_TYPES) => {
1749
1753
  setType(env[name][STATS], args[i][STATS])
1750
1754
  else if (isUnknownType(env[name][STATS])) {
1751
1755
  // REFF ASSIGMENT
1752
- // EXPLAIN: Not asigning ref fixes this overwritting
1756
+ // EXPLAIN: Not assigning ref fixes this overwriting
1753
1757
  // (let sum (lambda testxs (+ (get testxs 0) (get testxs 1))))
1754
1758
  // (let range (math:range 1 10))
1755
1759
  // (sum range)
@@ -1795,10 +1799,10 @@ export const typeCheck = (ast, ctx = SPECIAL_FORM_TYPES) => {
1795
1799
  setReturnRef(env[name][STATS], args[i][STATS])
1796
1800
  break
1797
1801
  default:
1798
- // TODO fix this assigment
1802
+ // TODO fix this assignment
1799
1803
  // It turns out it's not possible to determine return type of function here
1800
1804
  // what if it's a global function used elsewhere where the return type mwould be different
1801
- // THIS willgive lambda return types but refactor is needed still
1805
+ // THIS will give lambda return types but refactor is needed still
1802
1806
  setReturnRef(env[name][STATS], args[i][STATS])
1803
1807
  break
1804
1808
  }
package/src/enhance.js CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  import { getPrefix, shake, wrapInBlock } from './utils.js'
12
12
  import std from '../lib/baked/std.js'
13
13
  export const OPTIMIZATIONS = {
14
- RECURSION: 'recursive',
14
+ TAILCALL: 'tail-call',
15
15
  CACHE: 'memoized'
16
16
  }
17
17
  export const OPTIMIZED_PREFIX = 'optimized-lambda::'
@@ -53,7 +53,7 @@ const opt = (ast) => {
53
53
  ) {
54
54
  const name = exp[1][VALUE]
55
55
  const prefix = getPrefix(name)
56
- if (prefix === OPTIMIZATIONS.RECURSION) {
56
+ if (prefix === OPTIMIZATIONS.TAILCALL) {
57
57
  const args = last.slice(1, -1)
58
58
  const newName = `${OPTIMIZED_PREFIX}${name}::*${performance
59
59
  .now()
package/src/utils.js CHANGED
@@ -119,7 +119,7 @@ const KEYWORDS_SET = Object.values(KEYWORDS).reduce((a, b) => {
119
119
  export const isForbiddenVariableName = (name) => {
120
120
  switch (name) {
121
121
  case '_':
122
- case OPTIMIZATIONS.RECURSION:
122
+ case OPTIMIZATIONS.TAILCALL:
123
123
  case OPTIMIZATIONS.CACHE:
124
124
  return true
125
125
  default: