fez-lisp 1.5.102 → 1.5.103

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 +11 -10
  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.103",
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)`
@@ -1130,7 +1131,7 @@ export const typeCheck = (ast, error = true) => {
1130
1131
  }
1131
1132
  const copy = JSON.parse(JSON.stringify(ast))
1132
1133
  check(copy, root, copy)
1133
- while (stack.length) stack.pop()()
1134
+ while (stack.length) stack.cut()()
1134
1135
  return [ast, Types]
1135
1136
  }
1136
1137
  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
+ }