fez-lisp 1.5.102 → 1.5.104

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.
Files changed (3) hide show
  1. package/package.json +1 -1
  2. package/src/check.js +29 -16
  3. package/src/utils.js +113 -0
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.102",
5
+ "version": "1.5.104",
6
6
  "type": "module",
7
7
  "main": "index.js",
8
8
  "keywords": [
package/src/check.js CHANGED
@@ -37,6 +37,7 @@ import {
37
37
  validateLambda
38
38
  } from './types.js'
39
39
  import {
40
+ Brr,
40
41
  getSuffix,
41
42
  hasApplyLambdaBlock,
42
43
  hasBlock,
@@ -240,13 +241,13 @@ const retry = (stats, stack, cb) => {
240
241
  stats.retried < MAX_RETRY_DEFINITION
241
242
  ) {
242
243
  stats.retried += 1
243
- stack.unshift(() => cb())
244
+ stack.prepend(() => cb())
244
245
  }
245
246
  }
246
247
  const retryArgs = (stats, stack, cb) => {
247
248
  if (stats.counter < MAX_ARGUMENT_RETRY) {
248
249
  stats.counter++
249
- stack.unshift(cb)
250
+ stack.prepend(cb)
250
251
  }
251
252
  }
252
253
  const ifExpression = ({ re, env, ref }) => {
@@ -329,7 +330,7 @@ const resolveCondition = ({ rem, name, env, exp }) => {
329
330
  default:
330
331
  if (env[ret[VALUE]]) setReturnRef(ref[STATS], env[ret[VALUE]][STATS])
331
332
  else
332
- stack.push(() => {
333
+ stack.append(() => {
333
334
  if (env[ret[VALUE]]) setReturnRef(ref[STATS], env[ret[VALUE]][STATS])
334
335
  })
335
336
  break
@@ -355,7 +356,7 @@ const resolveRetunType = ({ returns, rem, stack, prop, exp, name, env }) => {
355
356
  // rest.at(-1)[0][TYPE] === APPLY
356
357
  // Here is upon application to store the result in the variable
357
358
  if (isUnknownType(env[name][STATS]))
358
- stack.unshift(() => {
359
+ stack.prepend(() => {
359
360
  setTypeToReturn(env[name][STATS], env[returns[VALUE]][STATS])
360
361
  // env[name][STATS][TYPE_PROP][0] =
361
362
  // env[returns[VALUE]][STATS][RETURNS][0]
@@ -390,7 +391,7 @@ export const typeCheck = (ast, error = true) => {
390
391
  let scopeIndex = 0
391
392
  const root = structuredClone(SPECIAL_FORM_TYPES)
392
393
  const Types = new Map()
393
- const stack = []
394
+ const stack = new Brr()
394
395
  const check = (exp, env, scope) => {
395
396
  const [first, ...rest] = isLeaf(exp) ? [exp] : exp
396
397
  if (first === undefined)
@@ -402,7 +403,7 @@ export const typeCheck = (ast, error = true) => {
402
403
  switch (first[TYPE]) {
403
404
  case WORD:
404
405
  if (!isSpecial)
405
- stack.push(() => {
406
+ stack.append(() => {
406
407
  // Figure out how to determine if varible is define after it's used
407
408
  if (env[first[VALUE]] === undefined) {
408
409
  throw new TypeError(
@@ -567,7 +568,7 @@ export const typeCheck = (ast, error = true) => {
567
568
  // TODO figure out what we do here
568
569
  // this here is a variable WORD
569
570
  // so return type of that function is that varible type
570
- stack.push(
571
+ stack.append(
571
572
  () =>
572
573
  copy[returns[VALUE]] &&
573
574
  setReturnToType(ref[STATS], copy[returns[VALUE]][STATS])
@@ -589,7 +590,7 @@ export const typeCheck = (ast, error = true) => {
589
590
  if (copy[ret[VALUE]])
590
591
  setReturnRef(ref[STATS], copy[ret[VALUE]][STATS])
591
592
  else
592
- stack.push(() => {
593
+ stack.append(() => {
593
594
  if (copy[ret[VALUE]])
594
595
  setReturnRef(ref[STATS], copy[ret[VALUE]][STATS])
595
596
  })
@@ -619,7 +620,7 @@ export const typeCheck = (ast, error = true) => {
619
620
  }
620
621
  break
621
622
  default:
622
- stack.push(() => {
623
+ stack.append(() => {
623
624
  if (!isSpecial && env[first[VALUE]] === undefined)
624
625
  throw new TypeError(
625
626
  `Trying to call undefined (lambda) ${first[VALUE]} (check #9)`
@@ -848,7 +849,7 @@ export const typeCheck = (ast, error = true) => {
848
849
  getType(args[i][STATS]) !== ATOM
849
850
  ) {
850
851
  throw new TypeError(
851
- `Incorrect type of arguments ${i} for (${
852
+ `Incorrect type of argument (${i}) for (${
852
853
  first[VALUE]
853
854
  }). Expected (${toTypeNames(
854
855
  getType(args[i][STATS])
@@ -862,8 +863,19 @@ export const typeCheck = (ast, error = true) => {
862
863
  !isUnknownType(env[rest[i][VALUE]][STATS]) &&
863
864
  env[rest[i][VALUE]][STATS][ARG_COUNT] !== VARIADIC
864
865
  ) {
866
+ if (getType(args[i][STATS]) !== APPLY)
867
+ // TODO this should really happen in 10 or 16
868
+ throw new TypeError(
869
+ `Incorrect type for argument of (${
870
+ first[VALUE]
871
+ }) at position (${i}). Expected (${
872
+ STATIC_TYPES.ABSTRACTION
873
+ }) but got (${toTypeNames(
874
+ getType(args[i][STATS])
875
+ )}) (${stringifyArgs(exp)}) (check #111)`
876
+ )
865
877
  // Handles words that are Lambdas
866
- if (
878
+ else if (
867
879
  env[rest[i][VALUE]][STATS][ARG_COUNT] !==
868
880
  args[i][STATS][ARG_COUNT]
869
881
  ) {
@@ -936,6 +948,7 @@ export const typeCheck = (ast, error = true) => {
936
948
  }
937
949
  }
938
950
  }
951
+
939
952
  if (
940
953
  T === COLLECTION &&
941
954
  env[rest[i][VALUE]] &&
@@ -944,7 +957,7 @@ export const typeCheck = (ast, error = true) => {
944
957
  !compareTypes(env[rest[i][VALUE]][STATS], args[i][STATS])
945
958
  ) {
946
959
  throw new TypeError(
947
- `Incorrect type of arguments ${i} for (${
960
+ `Incorrect type of argument (${i}) for (${
948
961
  first[VALUE]
949
962
  }). Expected (${toTypeNames(
950
963
  getType(args[i][STATS])
@@ -952,9 +965,9 @@ export const typeCheck = (ast, error = true) => {
952
965
  exp
953
966
  )}) (check #30)`
954
967
  )
955
- } else if (isUnknownType(args[i][STATS]))
968
+ } else if (isUnknownType(args[i][STATS])) {
956
969
  retry(args[i][STATS], stack, () => check(exp, env, scope))
957
- else if (
970
+ } else if (
958
971
  env[rest[i][VALUE]] &&
959
972
  !isUnknownType(args[i][STATS]) &&
960
973
  isUnknownType(env[rest[i][VALUE]][STATS]) &&
@@ -974,7 +987,7 @@ export const typeCheck = (ast, error = true) => {
974
987
  if (!isUnknownType(expected) && !isUnknownReturn(actual))
975
988
  if (!compareTypeWithReturn(expected, actual))
976
989
  throw new TypeError(
977
- `Incorrect type of arguments ${i} for (${
990
+ `Incorrect type of argument (${i}) for (${
978
991
  first[VALUE]
979
992
  }). Expected (${toTypeNames(
980
993
  getType(expected)
@@ -1130,7 +1143,7 @@ export const typeCheck = (ast, error = true) => {
1130
1143
  }
1131
1144
  const copy = JSON.parse(JSON.stringify(ast))
1132
1145
  check(copy, root, copy)
1133
- while (stack.length) stack.pop()()
1146
+ while (stack.length) stack.cut()()
1134
1147
  return [ast, Types]
1135
1148
  }
1136
1149
  export const type = (ast) => typeCheck(ast)[0]
package/src/utils.js CHANGED
@@ -347,3 +347,116 @@ export const UTILS = {
347
347
  stringifyArgs,
348
348
  shake
349
349
  }
350
+ export class Brr {
351
+ constructor(...items) {
352
+ this._left = [Brr._negativeZeroSymbol]
353
+ this._right = []
354
+ if (items.length === 0) return this
355
+ const half = (items.length / 2) | 0.5
356
+ for (let i = half - 1; i >= 0; --i) this._left.push(items[i])
357
+ for (let i = half; i < items.length; ++i) this._right.push(items[i])
358
+ return this
359
+ }
360
+ _addToLeft(item) {
361
+ this._left.push(item)
362
+ }
363
+ _addToRight(item) {
364
+ this._right.push(item)
365
+ }
366
+ _removeFromLeft() {
367
+ const len = this.length
368
+ if (len) {
369
+ if (len === 1) this.clear()
370
+ else if (this._left.length > 0) this._left.pop()
371
+ }
372
+ }
373
+ _removeFromRight() {
374
+ const len = this.length
375
+ if (len) {
376
+ if (len === 1) this.clear()
377
+ else if (this._right.length > 0) this._right.pop()
378
+ }
379
+ }
380
+ static _negativeZeroSymbol = Symbol('-0')
381
+ static isBrr(entity) {
382
+ return entity instanceof Brr
383
+ }
384
+ _offsetLeft() {
385
+ return (this._left.length - 1) * -1
386
+ }
387
+ _offsetRight() {
388
+ return this._right.length
389
+ }
390
+ get length() {
391
+ return this._left.length + this._right.length - 1
392
+ }
393
+ get first() {
394
+ return this.get(0)
395
+ }
396
+ get last() {
397
+ return this.get(-1)
398
+ }
399
+ get(offset) {
400
+ if (offset < 0) offset = this.length + offset
401
+ const offsetIndex = offset + this._offsetLeft()
402
+ const index = offsetIndex < 0 ? offsetIndex * -1 : offsetIndex
403
+ return offsetIndex >= 0 ? this._right[index] : this._left[index]
404
+ }
405
+ set(index, value) {
406
+ index = index < 0 ? this.length + index : index
407
+ const offset = index + this._offsetLeft()
408
+ if (offset >= 0) this._right[offset] = value
409
+ else this._left[offset * -1] = value
410
+ return this
411
+ }
412
+ append(item) {
413
+ this._addToRight(item)
414
+ return this
415
+ }
416
+ prepend(item) {
417
+ this._addToLeft(item)
418
+ return this
419
+ }
420
+ cut() {
421
+ if (this._offsetRight() === 0) this.balance()
422
+ const last = this.last
423
+ this._removeFromRight()
424
+ return last
425
+ }
426
+ chop() {
427
+ if (this._offsetLeft() === 0) this.balance()
428
+ const first = this.first
429
+ this._removeFromLeft()
430
+ return first
431
+ }
432
+ head() {
433
+ if (this._offsetRight() === 0) this.balance()
434
+ this._removeFromRight()
435
+ return this
436
+ }
437
+ tail() {
438
+ if (this._offsetLeft() === 0) this.balance()
439
+ this._removeFromLeft()
440
+ return this
441
+ }
442
+ clear() {
443
+ this._left.length = 1
444
+ this._right.length = 0
445
+ return this
446
+ }
447
+ isBalanced() {
448
+ return this._offsetRight() + this._offsetLeft() === 0
449
+ }
450
+ balance() {
451
+ if (this.isBalanced()) return this
452
+ const initial = [...this]
453
+ this.clear()
454
+ const half = (initial.length / 2) | 0.5
455
+ for (let i = half - 1; i >= 0; --i) this._addToLeft(initial[i])
456
+ for (let i = half; i < initial.length; ++i) this._addToRight(initial[i])
457
+ return this
458
+ }
459
+ *[Symbol.iterator]() {
460
+ for (let i = 0, len = this.length; i < len; ++i) yield this.get(i)
461
+ }
462
+ }