fez-lisp 1.5.83 → 1.5.85

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/src/compiler.js CHANGED
@@ -8,7 +8,6 @@ import {
8
8
  WORD,
9
9
  STATIC_TYPES
10
10
  } from './keywords.js'
11
- import { OPTIMIZATIONS } from './macros.js'
12
11
  import { leaf, isLeaf, AST } from './parser.js'
13
12
  const deepRename = (name, newName, tree) => {
14
13
  if (!isLeaf(tree))
@@ -0,0 +1,231 @@
1
+ import { AST, isLeaf } from './parser.js'
2
+ import {
3
+ APPLY,
4
+ ATOM,
5
+ KEYWORDS,
6
+ PREDICATE_SUFFIX,
7
+ TYPE,
8
+ VALUE,
9
+ WORD
10
+ } from './keywords.js'
11
+ import { getSuffix, shake, wrapInBlock } from './utils.js'
12
+ import std from '../lib/baked/std.js'
13
+ export const OPTIMIZATIONS = {
14
+ RECURSION: 'recursive',
15
+ CACHE: 'memoized'
16
+ }
17
+ export const OPTIMIZED_PREFIX = 'optimized-lambda::'
18
+ const deepTransform = (predicate, transform, tree) => {
19
+ if (!isLeaf(tree))
20
+ for (const leaf of tree) {
21
+ // Figure out a non mutable solution so
22
+ // I can get rid of deep clone AST.parse(AST.stringify(ast))
23
+ if (predicate(leaf)) transform(leaf)
24
+ else deepTransform(predicate, transform, leaf)
25
+ }
26
+ }
27
+ export const enhance = (ast) => {
28
+ const evaluate = (exp) => {
29
+ const [first, ...rest] = isLeaf(exp) ? [exp] : exp
30
+ if (first != undefined) {
31
+ switch (first[TYPE]) {
32
+ case WORD:
33
+ break
34
+ case ATOM:
35
+ break
36
+ case APPLY:
37
+ {
38
+ switch (first[VALUE]) {
39
+ case KEYWORDS.DEFINE_VARIABLE:
40
+ {
41
+ const last = exp.at(-1)
42
+ if (
43
+ !isLeaf(last) &&
44
+ Array.isArray(last) &&
45
+ last[0] &&
46
+ last[0][TYPE] === APPLY &&
47
+ last[0][VALUE] === KEYWORDS.ANONYMOUS_FUNCTION
48
+ ) {
49
+ const name = exp[1][VALUE]
50
+ const prefix = name.split(':')[0]
51
+ if (prefix === OPTIMIZATIONS.RECURSION) {
52
+ const args = last.slice(1, -1)
53
+ const newName = `${OPTIMIZED_PREFIX}${name}::*${performance
54
+ .now()
55
+ .toString()
56
+ .replace('.', 0)}*`
57
+ deepTransform(
58
+ (leaf) =>
59
+ Array.isArray(leaf) &&
60
+ leaf[0] &&
61
+ leaf[0][TYPE] === APPLY &&
62
+ leaf[0][VALUE] === name,
63
+ (leaf) => {
64
+ const copy = [...leaf]
65
+ leaf.length = 0
66
+ copy[0][VALUE] = newName
67
+ leaf.push([APPLY, KEYWORDS.ANONYMOUS_FUNCTION], copy)
68
+ },
69
+ last
70
+ )
71
+
72
+ exp[exp.length - 1] = [
73
+ [APPLY, KEYWORDS.CALL_FUNCTION],
74
+ [
75
+ [APPLY, KEYWORDS.ANONYMOUS_FUNCTION],
76
+ [
77
+ [APPLY, KEYWORDS.BLOCK],
78
+ [
79
+ [APPLY, KEYWORDS.DEFINE_VARIABLE],
80
+ [WORD, newName],
81
+ last
82
+ ],
83
+ [
84
+ [APPLY, KEYWORDS.CALL_FUNCTION],
85
+ [WORD, newName],
86
+ [
87
+ [APPLY, KEYWORDS.ANONYMOUS_FUNCTION],
88
+ [WORD, '*fn*'],
89
+ [
90
+ [APPLY, KEYWORDS.ANONYMOUS_FUNCTION],
91
+ ...args,
92
+ [
93
+ [APPLY, KEYWORDS.BLOCK],
94
+ [
95
+ [APPLY, KEYWORDS.DEFINE_VARIABLE],
96
+ [WORD, '*res*'],
97
+ [
98
+ [APPLY, KEYWORDS.CREATE_ARRAY],
99
+ [[APPLY, '*fn*'], ...args]
100
+ ]
101
+ ],
102
+ [
103
+ [APPLY, KEYWORDS.LOOP],
104
+ [
105
+ [APPLY, KEYWORDS.IS_LAMBDA],
106
+ [
107
+ [APPLY, KEYWORDS.GET_ARRAY],
108
+ [WORD, '*res*'],
109
+ [ATOM, 0]
110
+ ]
111
+ ],
112
+ [
113
+ [APPLY, KEYWORDS.SET_ARRAY],
114
+ [WORD, '*res*'],
115
+ [ATOM, 0],
116
+ [
117
+ [APPLY, KEYWORDS.CALL_FUNCTION],
118
+ [
119
+ [APPLY, KEYWORDS.GET_ARRAY],
120
+ [WORD, '*res*'],
121
+ [ATOM, 0]
122
+ ]
123
+ ]
124
+ ]
125
+ ],
126
+ [
127
+ [APPLY, KEYWORDS.GET_ARRAY],
128
+ [WORD, '*res*'],
129
+ [ATOM, 0]
130
+ ]
131
+ ]
132
+ ]
133
+ ]
134
+ ]
135
+ ]
136
+ ]
137
+ ]
138
+
139
+ evaluate(exp[exp.length - 1])
140
+ } else if (prefix === OPTIMIZATIONS.CACHE) {
141
+ const args = last.slice(1, -1)
142
+ const newName = `${OPTIMIZED_PREFIX}${name}::*${performance
143
+ .now()
144
+ .toString()
145
+ .replace('.', 0)}*`
146
+ deepTransform(
147
+ (leaf) =>
148
+ Array.isArray(leaf) &&
149
+ leaf[0] &&
150
+ leaf[0][TYPE] === APPLY &&
151
+ leaf[0][VALUE] === name,
152
+ (leaf) => (leaf[0][VALUE] = newName),
153
+ last
154
+ )
155
+ const memoName = newName + ':memo'
156
+ const keyName = newName + ':key'
157
+
158
+ exp[exp.length - 1] = [
159
+ [APPLY, KEYWORDS.CALL_FUNCTION],
160
+ [
161
+ [APPLY, KEYWORDS.ANONYMOUS_FUNCTION],
162
+ [
163
+ [APPLY, KEYWORDS.BLOCK],
164
+ [
165
+ [APPLY, KEYWORDS.DEFINE_VARIABLE],
166
+ [WORD, memoName],
167
+ [[APPLY, 'new:map64']]
168
+ ],
169
+ [
170
+ [APPLY, KEYWORDS.DEFINE_VARIABLE],
171
+ [WORD, newName],
172
+ [
173
+ [APPLY, KEYWORDS.ANONYMOUS_FUNCTION],
174
+ ...args,
175
+ [
176
+ [APPLY, KEYWORDS.BLOCK],
177
+ [
178
+ [APPLY, KEYWORDS.DEFINE_VARIABLE],
179
+ [WORD, keyName],
180
+ [
181
+ [APPLY, 'from:string-or-number->key'],
182
+ [[APPLY, KEYWORDS.CREATE_ARRAY], ...args]
183
+ ]
184
+ ],
185
+ [
186
+ [APPLY, KEYWORDS.IF],
187
+ [
188
+ [APPLY, 'map:exists?'],
189
+ [WORD, memoName],
190
+ [WORD, keyName]
191
+ ],
192
+ [
193
+ [APPLY, 'map:get'],
194
+ [WORD, memoName],
195
+ [WORD, keyName]
196
+ ],
197
+ [
198
+ [APPLY, 'map:set-and-get!'],
199
+ [WORD, memoName],
200
+ [WORD, keyName],
201
+ last.at(-1)
202
+ ]
203
+ ]
204
+ ]
205
+ ]
206
+ ],
207
+ [WORD, newName]
208
+ ]
209
+ ]
210
+ ]
211
+ evaluate(exp[exp.length - 1])
212
+ }
213
+ }
214
+ }
215
+ break
216
+ default:
217
+ break
218
+ }
219
+ }
220
+ break
221
+ default:
222
+ break
223
+ }
224
+
225
+ for (const r of rest) evaluate(r)
226
+ }
227
+ }
228
+ evaluate(AST.parse(AST.stringify(ast)))
229
+ const shaked = shake(ast[1][1].slice(1), std)
230
+ return wrapInBlock(shaked)
231
+ }
package/src/macros.js CHANGED
@@ -30,20 +30,6 @@ export const SUGGAR = {
30
30
  INTEGER_DEVISION: '//',
31
31
  CONDITION: 'cond'
32
32
  }
33
- export const OPTIMIZATIONS = {
34
- RECURSION: 'recursive',
35
- CACHE: 'memoized'
36
- }
37
- export const OPTIMIZED_PREFIX = 'optimized-lambda::'
38
- const deepTransform = (predicate, transform, tree) => {
39
- if (!isLeaf(tree))
40
- for (const leaf of tree) {
41
- // Figure out a non mutable solution so
42
- // I can get rid of deep clone AST.parse(AST.stringify(ast))
43
- if (predicate(leaf)) transform(leaf)
44
- else deepTransform(predicate, transform, leaf)
45
- }
46
- }
47
33
  export const deSuggarAst = (ast, scope) => {
48
34
  if (scope === undefined) scope = ast
49
35
  if (ast.length === 0) throw new SyntaxError(`No expressions...`)
@@ -514,194 +500,6 @@ export const deSuggarAst = (ast, scope) => {
514
500
  exp.iron = true
515
501
  exp.push(newScope)
516
502
  deSuggarAst(scope)
517
- } else if (
518
- !isLeaf(last) &&
519
- Array.isArray(last) &&
520
- last[0] &&
521
- last[0][TYPE] === APPLY &&
522
- last[0][VALUE] === KEYWORDS.ANONYMOUS_FUNCTION
523
- ) {
524
- const name = exp[1][VALUE]
525
- const prefix = name.split(':')[0]
526
- if (prefix === OPTIMIZATIONS.RECURSION) {
527
- if (getSuffix(name) === PREDICATE_SUFFIX) {
528
- throw new TypeError(
529
- `Optimized (lambda) ${name} can't be a (Predicate) as it will return a (lambda). Remove the (${PREDICATE_SUFFIX}) from the name`
530
- )
531
- }
532
- const args = last.slice(1, -1)
533
- const newName = `${OPTIMIZED_PREFIX}${name}::*${performance
534
- .now()
535
- .toString()
536
- .replace('.', 0)}*`
537
- deepTransform(
538
- (leaf) =>
539
- Array.isArray(leaf) &&
540
- leaf[0] &&
541
- leaf[0][TYPE] === APPLY &&
542
- leaf[0][VALUE] === name,
543
- (leaf) => {
544
- const copy = [...leaf]
545
- leaf.length = 0
546
- copy[0][VALUE] = newName
547
- leaf.push([APPLY, KEYWORDS.ANONYMOUS_FUNCTION], copy)
548
- },
549
- last
550
- )
551
-
552
- exp[exp.length - 1] = [
553
- [APPLY, KEYWORDS.CALL_FUNCTION],
554
- [
555
- [APPLY, KEYWORDS.ANONYMOUS_FUNCTION],
556
- [
557
- [APPLY, KEYWORDS.BLOCK],
558
- [
559
- [APPLY, KEYWORDS.DEFINE_VARIABLE],
560
- [WORD, newName],
561
- last
562
- ],
563
- args.length < 5
564
- ? [
565
- [
566
- APPLY,
567
- `optimization:tail-calls-${args.length}`
568
- ],
569
- [WORD, newName]
570
- ]
571
- : [
572
- [APPLY, KEYWORDS.CALL_FUNCTION],
573
- [WORD, newName],
574
- [
575
- [APPLY, KEYWORDS.ANONYMOUS_FUNCTION],
576
- [WORD, '*fn*'],
577
- [
578
- [APPLY, KEYWORDS.ANONYMOUS_FUNCTION],
579
- ...args,
580
- [
581
- [APPLY, KEYWORDS.BLOCK],
582
- [
583
- [APPLY, KEYWORDS.DEFINE_VARIABLE],
584
- [WORD, '*res*'],
585
- [
586
- [APPLY, KEYWORDS.CREATE_ARRAY],
587
- [[APPLY, '*fn*'], ...args]
588
- ]
589
- ],
590
- [
591
- [APPLY, KEYWORDS.LOOP],
592
- [
593
- [APPLY, KEYWORDS.IS_LAMBDA],
594
- [
595
- [APPLY, KEYWORDS.GET_ARRAY],
596
- [WORD, '*res*'],
597
- [ATOM, 0]
598
- ]
599
- ],
600
- [
601
- [APPLY, KEYWORDS.SET_ARRAY],
602
- [WORD, '*res*'],
603
- [ATOM, 0],
604
- [
605
- [APPLY, KEYWORDS.CALL_FUNCTION],
606
- [
607
- [APPLY, KEYWORDS.GET_ARRAY],
608
- [WORD, '*res*'],
609
- [ATOM, 0]
610
- ]
611
- ]
612
- ]
613
- ],
614
- [
615
- [APPLY, KEYWORDS.GET_ARRAY],
616
- [WORD, '*res*'],
617
- [ATOM, 0]
618
- ]
619
- ]
620
- ]
621
- ]
622
- ]
623
- ]
624
- ]
625
- ]
626
- deSuggarAst(exp[exp.length - 1])
627
- } else if (prefix === OPTIMIZATIONS.CACHE) {
628
- if (getSuffix(name) === PREDICATE_SUFFIX) {
629
- throw new TypeError(
630
- `Optimized (lambda) ${name} can't be a (Predicate) as it will return a (lambda). Remove the (${PREDICATE_SUFFIX}) from the name`
631
- )
632
- }
633
- const args = last.slice(1, -1)
634
- const newName = `${OPTIMIZED_PREFIX}${name}::*${performance
635
- .now()
636
- .toString()
637
- .replace('.', 0)}*`
638
- deepTransform(
639
- (leaf) =>
640
- Array.isArray(leaf) &&
641
- leaf[0] &&
642
- leaf[0][TYPE] === APPLY &&
643
- leaf[0][VALUE] === name,
644
- (leaf) => (leaf[0][VALUE] = newName),
645
- last
646
- )
647
- const memoName = newName + ':memo'
648
- const keyName = newName + ':key'
649
-
650
- exp[exp.length - 1] = [
651
- [APPLY, KEYWORDS.CALL_FUNCTION],
652
- [
653
- [APPLY, KEYWORDS.ANONYMOUS_FUNCTION],
654
- [
655
- [APPLY, KEYWORDS.BLOCK],
656
- [
657
- [APPLY, KEYWORDS.DEFINE_VARIABLE],
658
- [WORD, memoName],
659
- [[APPLY, 'new:map64']]
660
- ],
661
- [
662
- [APPLY, KEYWORDS.DEFINE_VARIABLE],
663
- [WORD, newName],
664
- [
665
- [APPLY, KEYWORDS.ANONYMOUS_FUNCTION],
666
- ...args,
667
- [
668
- [APPLY, KEYWORDS.BLOCK],
669
- [
670
- [APPLY, KEYWORDS.DEFINE_VARIABLE],
671
- [WORD, keyName],
672
- [
673
- [APPLY, 'from:string-or-number->key'],
674
- [[APPLY, KEYWORDS.CREATE_ARRAY], ...args]
675
- ]
676
- ],
677
- [
678
- [APPLY, KEYWORDS.IF],
679
- [
680
- [APPLY, 'map:exists?'],
681
- [WORD, memoName],
682
- [WORD, keyName]
683
- ],
684
- [
685
- [APPLY, 'map:get'],
686
- [WORD, memoName],
687
- [WORD, keyName]
688
- ],
689
- [
690
- [APPLY, 'map:set-and-get!'],
691
- [WORD, memoName],
692
- [WORD, keyName],
693
- last.at(-1)
694
- ]
695
- ]
696
- ]
697
- ]
698
- ],
699
- [WORD, newName]
700
- ]
701
- ]
702
- ]
703
- deSuggarAst(exp[exp.length - 1])
704
- }
705
503
  }
706
504
  }
707
505
  break
package/src/utils.js CHANGED
@@ -13,9 +13,9 @@ import { isLeaf, LISP } from './parser.js'
13
13
  import {
14
14
  deSuggarAst,
15
15
  deSuggarSource,
16
- handleUnbalancedQuotes,
17
- OPTIMIZATIONS
16
+ handleUnbalancedQuotes
18
17
  } from './macros.js'
18
+ import { OPTIMIZATIONS } from './enchance.js'
19
19
  export const logError = (error) =>
20
20
  console.log('\x1b[31m', `\n${error}\n`, '\x1b[0m')
21
21
  export const logSuccess = (output) => console.log('\x1b[32m', output, '\x1b[0m')