fez-lisp 1.5.86 → 1.5.88
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 +1 -1
- package/src/check.js +204 -106
- package/src/keywords.js +13 -1
- package/src/macros.js +1 -3
package/package.json
CHANGED
package/src/check.js
CHANGED
@@ -1,12 +1,16 @@
|
|
1
1
|
import {
|
2
2
|
APPLY,
|
3
3
|
ATOM,
|
4
|
+
FALSE,
|
4
5
|
KEYWORDS,
|
5
6
|
PLACEHOLDER,
|
6
|
-
|
7
|
+
PREDICATE_SUFFIX,
|
8
|
+
PREDICATES_INPUT_SET,
|
9
|
+
PREDICATES_OUTPUT_SET,
|
7
10
|
SPECIAL_FORMS_SET,
|
8
11
|
STATIC_TYPES,
|
9
12
|
STATIC_TYPES_SET,
|
13
|
+
TRUE,
|
10
14
|
TYPE,
|
11
15
|
VALUE,
|
12
16
|
WORD
|
@@ -30,7 +34,12 @@ import {
|
|
30
34
|
VARIABLE_ORDER_INDEX,
|
31
35
|
COLLECTION
|
32
36
|
} from './types.js'
|
33
|
-
import {
|
37
|
+
import {
|
38
|
+
getSuffix,
|
39
|
+
hasApplyLambdaBlock,
|
40
|
+
hasBlock,
|
41
|
+
stringifyArgs
|
42
|
+
} from './utils.js'
|
34
43
|
|
35
44
|
export const identity = (name) => [
|
36
45
|
[0, 'let'],
|
@@ -54,6 +63,50 @@ const deepLambdaReturn = (rest, condition) => {
|
|
54
63
|
const rem = hasBlock(body) ? body.at(-1) : body
|
55
64
|
return condition(rem) ? rem : deepLambdaReturn(rem, condition)
|
56
65
|
}
|
66
|
+
const checkPredicateName = (exp, rest, warningStack) => {
|
67
|
+
if (getSuffix(rest[0][VALUE]) === PREDICATE_SUFFIX) {
|
68
|
+
const last = rest.at(-1)
|
69
|
+
if (isLeaf(last)) {
|
70
|
+
if (last[TYPE] === ATOM && last[VALUE] !== TRUE && last[VALUE] !== FALSE)
|
71
|
+
warningStack.add(
|
72
|
+
`Assigning predicate (ending in ?) variable (${
|
73
|
+
rest[0][VALUE]
|
74
|
+
}) to an (${
|
75
|
+
STATIC_TYPES.ATOM
|
76
|
+
}) that is not (or ${TRUE} ${FALSE}) (${stringifyArgs(exp)})`
|
77
|
+
)
|
78
|
+
else if (
|
79
|
+
last[TYPE] === WORD &&
|
80
|
+
getSuffix(last[VALUE]) !== PREDICATE_SUFFIX &&
|
81
|
+
!PREDICATES_OUTPUT_SET.has(last[VALUE])
|
82
|
+
)
|
83
|
+
warningStack.add(
|
84
|
+
`Assigning predicate (ending in ?) variable (${
|
85
|
+
rest[0][VALUE]
|
86
|
+
}) to another variable which is not a predicate (also ending in ?) (${stringifyArgs(
|
87
|
+
exp
|
88
|
+
)})`
|
89
|
+
)
|
90
|
+
} else if (last[0][0] === APPLY) {
|
91
|
+
const application = last[0]
|
92
|
+
switch (application[VALUE]) {
|
93
|
+
default:
|
94
|
+
if (
|
95
|
+
getSuffix(application[VALUE]) !== PREDICATE_SUFFIX &&
|
96
|
+
!PREDICATES_OUTPUT_SET.has(application[VALUE])
|
97
|
+
)
|
98
|
+
warningStack.add(
|
99
|
+
`Assigning predicate (ending in ?) variable (${
|
100
|
+
application[VALUE]
|
101
|
+
}) to another variable which is not a predicate (also ending in ?) (${stringifyArgs(
|
102
|
+
exp
|
103
|
+
)})`
|
104
|
+
)
|
105
|
+
break
|
106
|
+
}
|
107
|
+
}
|
108
|
+
}
|
109
|
+
}
|
57
110
|
// const assign = (a, b, i) => {
|
58
111
|
// a[i] = b[i]
|
59
112
|
// }
|
@@ -164,16 +217,32 @@ export const typeCheck = (ast) => {
|
|
164
217
|
)
|
165
218
|
} else {
|
166
219
|
const name = rest[0][VALUE]
|
220
|
+
// Predicate name consistency
|
167
221
|
const resolveRetunType = (returns, rem, prop) => {
|
168
222
|
if (returns[TYPE] === ATOM) {
|
169
223
|
// ATOM ASSIGMENT
|
170
224
|
env[name][STATS][prop][0] = ATOM
|
171
225
|
env[name][STATS][RETURNS][0] = ATOM
|
226
|
+
checkPredicateName(
|
227
|
+
exp,
|
228
|
+
[[WORD, name], returns],
|
229
|
+
warningStack
|
230
|
+
)
|
172
231
|
} else {
|
173
232
|
switch (returns[VALUE]) {
|
174
233
|
case KEYWORDS.IF:
|
175
234
|
{
|
176
235
|
const re = rem.slice(2)
|
236
|
+
checkPredicateName(
|
237
|
+
exp,
|
238
|
+
[[WORD, name], isLeaf(re[0]) ? re[0] : re[0][0]],
|
239
|
+
warningStack
|
240
|
+
)
|
241
|
+
checkPredicateName(
|
242
|
+
exp,
|
243
|
+
[[WORD, name], isLeaf(re[1]) ? re[1] : re[1][0]],
|
244
|
+
warningStack
|
245
|
+
)
|
177
246
|
if (re[0][TYPE] === ATOM || re[1][TYPE] === ATOM) {
|
178
247
|
// ATOM ASSIGMENT
|
179
248
|
env[name][STATS][prop][0] = ATOM
|
@@ -237,12 +306,34 @@ export const typeCheck = (ast) => {
|
|
237
306
|
}
|
238
307
|
break
|
239
308
|
default:
|
309
|
+
checkPredicateName(
|
310
|
+
exp,
|
311
|
+
[[WORD, name], returns],
|
312
|
+
warningStack
|
313
|
+
)
|
240
314
|
if (!env[returns[VALUE]])
|
241
315
|
env[name][STATS][RETURNS] = [UNKNOWN]
|
242
316
|
// env[name][STATS][RETURNS] = APPLY
|
243
317
|
else if (
|
244
318
|
env[returns[VALUE]][STATS][TYPE_PROP][0] === APPLY
|
245
319
|
) {
|
320
|
+
if (returns[VALUE] === KEYWORDS.CALL_FUNCTION) {
|
321
|
+
const fn = rest.at(-1).at(-1).at(-1)
|
322
|
+
checkPredicateName(
|
323
|
+
exp,
|
324
|
+
[
|
325
|
+
[WORD, name],
|
326
|
+
isLeaf(fn)
|
327
|
+
? fn // when apply is a word (let x? (lambda (apply [] array:empty!)))
|
328
|
+
: drillReturnType(
|
329
|
+
fn,
|
330
|
+
(r) => r[VALUE] === KEYWORDS.CALL_FUNCTION
|
331
|
+
) // when apply is an annonymous lambda // (let fn? (lambda x (apply x (lambda x (array:empty! [])))))
|
332
|
+
],
|
333
|
+
warningStack
|
334
|
+
)
|
335
|
+
}
|
336
|
+
|
246
337
|
// TODO This seems to be able to be deleted
|
247
338
|
// FOR NOT IT CAN BE
|
248
339
|
// if (returns[VALUE] === KEYWORDS.CALL_FUNCTION) {
|
@@ -324,6 +415,7 @@ export const typeCheck = (ast) => {
|
|
324
415
|
check(rightHand, env, exp)
|
325
416
|
}
|
326
417
|
} else {
|
418
|
+
checkPredicateName(exp, rest, warningStack)
|
327
419
|
const isL = isLeaf(rightHand)
|
328
420
|
if (isL && rightHand[TYPE] === WORD) {
|
329
421
|
// TODO make sure this prevents the assigment all together
|
@@ -574,10 +666,10 @@ export const typeCheck = (ast) => {
|
|
574
666
|
}
|
575
667
|
}
|
576
668
|
}
|
577
|
-
|
578
669
|
// also type of arg
|
579
670
|
const args = env[first[VALUE]][STATS][ARGUMENTS] ?? []
|
580
671
|
for (let i = 0; i < args.length; ++i) {
|
672
|
+
const isRestILeaf = isLeaf(rest[i])
|
581
673
|
// type check
|
582
674
|
// TODO get rof pred type
|
583
675
|
// const PRED_TYPE = args[i][STATS][TYPE_PROP][1]
|
@@ -585,50 +677,57 @@ export const typeCheck = (ast) => {
|
|
585
677
|
if (first[TYPE] === APPLY && isSpecial) {
|
586
678
|
if (
|
587
679
|
MAIN_TYPE === ATOM &&
|
588
|
-
|
589
|
-
!isLeaf(rest[i]) &&
|
590
|
-
rest[i][0][TYPE] === APPLY &&
|
591
|
-
rest[i][0][VALUE] === KEYWORDS.CALL_FUNCTION
|
680
|
+
PREDICATES_INPUT_SET.has(first[VALUE])
|
592
681
|
) {
|
593
|
-
if (
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
} else {
|
608
|
-
const body = rest[i].at(-1).at(-1)
|
609
|
-
const rem = hasBlock(body) ? body.at(-1) : body
|
610
|
-
const returns = isLeaf(rem) ? rem : rem[0]
|
611
|
-
if (returns[TYPE] === ATOM) {
|
612
|
-
if (MAIN_TYPE !== ATOM) {
|
682
|
+
// if (isRestILeaf && rest[i][TYPE] === ATOM && rest[i][VALUE] !== TRUE && rest[i][TYPE] !== FALSE) throw some rror
|
683
|
+
// else if (
|
684
|
+
// isRestILeaf && est[i][TYPE] === ATOM && (rest[i][VALUE] === TRUE || rest[i][VALUE] === FALSE)
|
685
|
+
// ) continue
|
686
|
+
// else
|
687
|
+
if (
|
688
|
+
!isRestILeaf &&
|
689
|
+
rest[i][0][TYPE] === APPLY &&
|
690
|
+
rest[i][0][VALUE] === KEYWORDS.CALL_FUNCTION
|
691
|
+
) {
|
692
|
+
if (isLeaf(rest[i].at(-1))) {
|
693
|
+
const fnName = rest[i].at(-1)[VALUE]
|
694
|
+
const fn = env[fnName]
|
695
|
+
if (fn && fn[STATS][RETURNS][0] !== ATOM) {
|
613
696
|
errorStack.add(
|
614
|
-
`Incorrect type of argument ${i} for (${
|
697
|
+
`Incorrect type of argument (${i}) for (${
|
615
698
|
first[VALUE]
|
616
699
|
}). Expected (${toTypeNames(
|
617
|
-
MAIN_TYPE
|
618
|
-
)}) but got an (${toTypeNames(
|
619
700
|
ATOM
|
620
|
-
)})
|
701
|
+
)}) but got an (${toTypeNames(
|
702
|
+
fn[STATS][RETURNS][0]
|
703
|
+
)}) (${stringifyArgs(exp)}) (check #26)`
|
621
704
|
)
|
622
705
|
}
|
623
|
-
} else
|
624
|
-
|
625
|
-
|
706
|
+
} else {
|
707
|
+
const body = rest[i].at(-1).at(-1)
|
708
|
+
const rem = hasBlock(body) ? body.at(-1) : body
|
709
|
+
const returns = isLeaf(rem) ? rem : rem[0]
|
710
|
+
if (returns[TYPE] === ATOM) {
|
711
|
+
if (MAIN_TYPE !== ATOM) {
|
712
|
+
errorStack.add(
|
713
|
+
`Incorrect type of argument ${i} for (${
|
714
|
+
first[VALUE]
|
715
|
+
}). Expected (${toTypeNames(
|
716
|
+
MAIN_TYPE
|
717
|
+
)}) but got an (${toTypeNames(
|
718
|
+
ATOM
|
719
|
+
)}) (${stringifyArgs(exp)}) (check #27)`
|
720
|
+
)
|
721
|
+
}
|
722
|
+
} else if (
|
723
|
+
env[returns[VALUE]] &&
|
724
|
+
env[returns[VALUE]][STATS][RETURNS][0] !== ATOM
|
626
725
|
) {
|
627
726
|
errorStack.add(
|
628
727
|
`Incorrect type of argument ${i} for (${
|
629
728
|
first[VALUE]
|
630
729
|
}). Expected (${toTypeNames(
|
631
|
-
|
730
|
+
ATOM
|
632
731
|
)}) but got (${toTypeNames(
|
633
732
|
env[returns[VALUE]][STATS][TYPE_PROP]
|
634
733
|
)}) (${stringifyArgs(exp)}) (check #29)`
|
@@ -639,89 +738,88 @@ export const typeCheck = (ast) => {
|
|
639
738
|
}
|
640
739
|
const isCast = STATIC_TYPES_SET.has(first[VALUE])
|
641
740
|
const expectedArgs = env[first[VALUE]][STATS][ARGUMENTS]
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
741
|
+
const EXPECTED_TYPE = expectedArgs[i][STATS][TYPE_PROP][0]
|
742
|
+
// IF UKNOWN andnot csted -we have nothing much to do
|
743
|
+
if (EXPECTED_TYPE === UNKNOWN && !isCast) continue
|
744
|
+
if (!isRestILeaf) {
|
745
|
+
const CAR = rest[i][0][VALUE]
|
746
|
+
const isKnown =
|
747
|
+
env[CAR] && env[CAR][STATS][RETURNS][0] !== UNKNOWN
|
748
|
+
if (isKnown && !isCast) {
|
749
|
+
if (env[CAR][STATS][RETURNS][0] !== EXPECTED_TYPE) {
|
750
|
+
errorStack.add(
|
751
|
+
`Incorrect type of argument (${i}) for special form (${
|
752
|
+
first[VALUE]
|
753
|
+
}). Expected (${toTypeNames(
|
754
|
+
EXPECTED_TYPE
|
755
|
+
)}) but got (${toTypeNames(
|
756
|
+
env[CAR][STATS][RETURNS][0]
|
757
|
+
)}) (${stringifyArgs(exp)}) (check #1)`
|
758
|
+
)
|
759
|
+
}
|
760
|
+
// never reached because there is only 1 subtype at the moment
|
761
|
+
// else if (
|
762
|
+
// PRED_TYPE &&
|
763
|
+
// env[CAR][STATS][RETURNS][1] !== PRED_TYPE
|
764
|
+
// ) {
|
765
|
+
// }
|
766
|
+
}
|
767
|
+
} else {
|
768
|
+
switch (rest[i][TYPE]) {
|
769
|
+
case WORD:
|
770
|
+
{
|
771
|
+
const CAR = rest[i][VALUE]
|
772
|
+
const isKnown =
|
773
|
+
env[CAR] &&
|
774
|
+
env[CAR][STATS][TYPE_PROP][0] !== UNKNOWN
|
775
|
+
if (isKnown && !isCast) {
|
776
|
+
if (
|
777
|
+
EXPECTED_TYPE !== env[CAR][STATS][TYPE_PROP][0]
|
778
|
+
) {
|
779
|
+
errorStack.add(
|
780
|
+
`Incorrect type of argument (${i}) for special form (${
|
781
|
+
first[VALUE]
|
782
|
+
}). Expected (${toTypeNames(
|
783
|
+
EXPECTED_TYPE
|
784
|
+
)}) but got (${toTypeNames(
|
785
|
+
env[CAR][STATS][TYPE_PROP][0]
|
786
|
+
)}) (${stringifyArgs(exp)}) (check #3)`
|
787
|
+
)
|
788
|
+
}
|
789
|
+
} else if (env[CAR]) {
|
790
|
+
if (isCast) {
|
791
|
+
// CAST assigment
|
792
|
+
env[rest[i][VALUE]][STATS][TYPE_PROP][0] =
|
793
|
+
root[first[VALUE]][STATS][RETURNS][0]
|
794
|
+
|
795
|
+
// root[first[VALUE]][STATS][RETURNS] =
|
796
|
+
// root[first[VALUE]][STATS][RETURNS]
|
797
|
+
} else {
|
798
|
+
// VALUE assigment
|
799
|
+
env[CAR][STATS][TYPE_PROP][0] = EXPECTED_TYPE
|
800
|
+
}
|
801
|
+
}
|
802
|
+
}
|
803
|
+
break
|
804
|
+
case ATOM: {
|
805
|
+
if (rest[i][TYPE] !== EXPECTED_TYPE) {
|
651
806
|
errorStack.add(
|
652
807
|
`Incorrect type of argument (${i}) for special form (${
|
653
808
|
first[VALUE]
|
654
809
|
}). Expected (${toTypeNames(
|
655
|
-
|
810
|
+
EXPECTED_TYPE
|
656
811
|
)}) but got (${toTypeNames(
|
657
|
-
|
658
|
-
)}) (${stringifyArgs(exp)}) (check #
|
812
|
+
rest[i][TYPE]
|
813
|
+
)}) (${stringifyArgs(exp)}) (check #2)`
|
659
814
|
)
|
660
815
|
}
|
661
|
-
|
662
|
-
// else if (
|
663
|
-
// PRED_TYPE &&
|
664
|
-
// env[CAR][STATS][RETURNS][1] !== PRED_TYPE
|
665
|
-
// ) {
|
666
|
-
// }
|
667
|
-
}
|
668
|
-
} else {
|
669
|
-
switch (rest[i][TYPE]) {
|
670
|
-
case WORD:
|
671
|
-
{
|
672
|
-
const CAR = rest[i][VALUE]
|
673
|
-
const isKnown =
|
674
|
-
env[CAR] &&
|
675
|
-
env[CAR][STATS][TYPE_PROP][0] !== UNKNOWN
|
676
|
-
if (isKnown && !isCast) {
|
677
|
-
if (
|
678
|
-
MAIN_TYPE !== env[CAR][STATS][TYPE_PROP][0]
|
679
|
-
) {
|
680
|
-
errorStack.add(
|
681
|
-
`Incorrect type of argument (${i}) for special form (${
|
682
|
-
first[VALUE]
|
683
|
-
}). Expected (${toTypeNames(
|
684
|
-
MAIN_TYPE
|
685
|
-
)}) but got (${toTypeNames(
|
686
|
-
env[CAR][STATS][TYPE_PROP][0]
|
687
|
-
)}) (${stringifyArgs(exp)}) (check #3)`
|
688
|
-
)
|
689
|
-
}
|
690
|
-
} else if (env[CAR]) {
|
691
|
-
if (isCast) {
|
692
|
-
// CAST assigment
|
693
|
-
env[rest[i][VALUE]][STATS][TYPE_PROP][0] =
|
694
|
-
root[first[VALUE]][STATS][RETURNS][0]
|
695
|
-
|
696
|
-
// root[first[VALUE]][STATS][RETURNS] =
|
697
|
-
// root[first[VALUE]][STATS][RETURNS]
|
698
|
-
} else {
|
699
|
-
// VALUE assigment
|
700
|
-
env[CAR][STATS][TYPE_PROP][0] = MAIN_TYPE
|
701
|
-
}
|
702
|
-
}
|
703
|
-
}
|
704
|
-
break
|
705
|
-
case ATOM: {
|
706
|
-
if (rest[i][TYPE] !== MAIN_TYPE) {
|
707
|
-
errorStack.add(
|
708
|
-
`Incorrect type of argument (${i}) for special form (${
|
709
|
-
first[VALUE]
|
710
|
-
}). Expected (${toTypeNames(
|
711
|
-
MAIN_TYPE
|
712
|
-
)}) but got (${toTypeNames(
|
713
|
-
rest[i][TYPE]
|
714
|
-
)}) (${stringifyArgs(exp)}) (check #2)`
|
715
|
-
)
|
716
|
-
}
|
717
|
-
break
|
718
|
-
}
|
816
|
+
break
|
719
817
|
}
|
720
818
|
}
|
721
819
|
}
|
722
820
|
}
|
723
821
|
// type checking
|
724
|
-
else if (
|
822
|
+
else if (isRestILeaf) {
|
725
823
|
const T =
|
726
824
|
rest[i][TYPE] === WORD && env[rest[i][VALUE]]
|
727
825
|
? env[rest[i][VALUE]][STATS][TYPE_PROP][0]
|
package/src/keywords.js
CHANGED
@@ -77,10 +77,22 @@ export const SPECIAL_FORMS_SET = new Set(
|
|
77
77
|
Object.values(KEYWORDS).concat(Object.values(STATIC_TYPES))
|
78
78
|
)
|
79
79
|
export const STATIC_TYPES_SET = new Set(Object.values(STATIC_TYPES))
|
80
|
-
export const
|
80
|
+
export const PREDICATES_INPUT_SET = new Set([
|
81
81
|
KEYWORDS.IF,
|
82
82
|
KEYWORDS.AND,
|
83
83
|
KEYWORDS.OR,
|
84
84
|
KEYWORDS.NOT,
|
85
85
|
KEYWORDS.LOOP
|
86
86
|
])
|
87
|
+
export const PREDICATES_OUTPUT_SET = new Set([
|
88
|
+
KEYWORDS.AND,
|
89
|
+
KEYWORDS.OR,
|
90
|
+
KEYWORDS.NOT,
|
91
|
+
KEYWORDS.EQUAL,
|
92
|
+
KEYWORDS.GREATHER_THAN,
|
93
|
+
KEYWORDS.LESS_THAN,
|
94
|
+
KEYWORDS.GREATHER_THAN_OR_EQUAL,
|
95
|
+
KEYWORDS.LESS_THAN_OR_EQUAL,
|
96
|
+
KEYWORDS.IS_ATOM,
|
97
|
+
KEYWORDS.IS_LAMBDA
|
98
|
+
])
|
package/src/macros.js
CHANGED
@@ -10,14 +10,12 @@ import {
|
|
10
10
|
FALSE,
|
11
11
|
KEYWORDS,
|
12
12
|
PLACEHOLDER,
|
13
|
-
PREDICATE_SUFFIX,
|
14
|
-
STATIC_TYPES,
|
15
13
|
TRUE,
|
16
14
|
TYPE,
|
17
15
|
VALUE,
|
18
16
|
WORD
|
19
17
|
} from './keywords.js'
|
20
|
-
import {
|
18
|
+
import { hasBlock, stringifyArgs } from './utils.js'
|
21
19
|
export const SUGGAR = {
|
22
20
|
// Syntactic suggars
|
23
21
|
PIPE: '|>',
|