fez-lisp 1.5.86 → 1.5.87
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 +167 -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(rest)})`
|
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,6 +217,7 @@ 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
|
@@ -324,6 +378,7 @@ export const typeCheck = (ast) => {
|
|
324
378
|
check(rightHand, env, exp)
|
325
379
|
}
|
326
380
|
} else {
|
381
|
+
checkPredicateName(exp, rest, warningStack)
|
327
382
|
const isL = isLeaf(rightHand)
|
328
383
|
if (isL && rightHand[TYPE] === WORD) {
|
329
384
|
// TODO make sure this prevents the assigment all together
|
@@ -574,10 +629,10 @@ export const typeCheck = (ast) => {
|
|
574
629
|
}
|
575
630
|
}
|
576
631
|
}
|
577
|
-
|
578
632
|
// also type of arg
|
579
633
|
const args = env[first[VALUE]][STATS][ARGUMENTS] ?? []
|
580
634
|
for (let i = 0; i < args.length; ++i) {
|
635
|
+
const isRestILeaf = isLeaf(rest[i])
|
581
636
|
// type check
|
582
637
|
// TODO get rof pred type
|
583
638
|
// const PRED_TYPE = args[i][STATS][TYPE_PROP][1]
|
@@ -585,50 +640,57 @@ export const typeCheck = (ast) => {
|
|
585
640
|
if (first[TYPE] === APPLY && isSpecial) {
|
586
641
|
if (
|
587
642
|
MAIN_TYPE === ATOM &&
|
588
|
-
|
589
|
-
!isLeaf(rest[i]) &&
|
590
|
-
rest[i][0][TYPE] === APPLY &&
|
591
|
-
rest[i][0][VALUE] === KEYWORDS.CALL_FUNCTION
|
643
|
+
PREDICATES_INPUT_SET.has(first[VALUE])
|
592
644
|
) {
|
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) {
|
645
|
+
// if (isRestILeaf && rest[i][TYPE] === ATOM && rest[i][VALUE] !== TRUE && rest[i][TYPE] !== FALSE) throw some rror
|
646
|
+
// else if (
|
647
|
+
// isRestILeaf && est[i][TYPE] === ATOM && (rest[i][VALUE] === TRUE || rest[i][VALUE] === FALSE)
|
648
|
+
// ) continue
|
649
|
+
// else
|
650
|
+
if (
|
651
|
+
!isRestILeaf &&
|
652
|
+
rest[i][0][TYPE] === APPLY &&
|
653
|
+
rest[i][0][VALUE] === KEYWORDS.CALL_FUNCTION
|
654
|
+
) {
|
655
|
+
if (isLeaf(rest[i].at(-1))) {
|
656
|
+
const fnName = rest[i].at(-1)[VALUE]
|
657
|
+
const fn = env[fnName]
|
658
|
+
if (fn && fn[STATS][RETURNS][0] !== ATOM) {
|
613
659
|
errorStack.add(
|
614
|
-
`Incorrect type of argument ${i} for (${
|
660
|
+
`Incorrect type of argument (${i}) for (${
|
615
661
|
first[VALUE]
|
616
662
|
}). Expected (${toTypeNames(
|
617
|
-
MAIN_TYPE
|
618
|
-
)}) but got an (${toTypeNames(
|
619
663
|
ATOM
|
620
|
-
)})
|
664
|
+
)}) but got an (${toTypeNames(
|
665
|
+
fn[STATS][RETURNS][0]
|
666
|
+
)}) (${stringifyArgs(exp)}) (check #26)`
|
621
667
|
)
|
622
668
|
}
|
623
|
-
} else
|
624
|
-
|
625
|
-
|
669
|
+
} else {
|
670
|
+
const body = rest[i].at(-1).at(-1)
|
671
|
+
const rem = hasBlock(body) ? body.at(-1) : body
|
672
|
+
const returns = isLeaf(rem) ? rem : rem[0]
|
673
|
+
if (returns[TYPE] === ATOM) {
|
674
|
+
if (MAIN_TYPE !== ATOM) {
|
675
|
+
errorStack.add(
|
676
|
+
`Incorrect type of argument ${i} for (${
|
677
|
+
first[VALUE]
|
678
|
+
}). Expected (${toTypeNames(
|
679
|
+
MAIN_TYPE
|
680
|
+
)}) but got an (${toTypeNames(
|
681
|
+
ATOM
|
682
|
+
)}) (${stringifyArgs(exp)}) (check #27)`
|
683
|
+
)
|
684
|
+
}
|
685
|
+
} else if (
|
686
|
+
env[returns[VALUE]] &&
|
687
|
+
env[returns[VALUE]][STATS][RETURNS][0] !== ATOM
|
626
688
|
) {
|
627
689
|
errorStack.add(
|
628
690
|
`Incorrect type of argument ${i} for (${
|
629
691
|
first[VALUE]
|
630
692
|
}). Expected (${toTypeNames(
|
631
|
-
|
693
|
+
ATOM
|
632
694
|
)}) but got (${toTypeNames(
|
633
695
|
env[returns[VALUE]][STATS][TYPE_PROP]
|
634
696
|
)}) (${stringifyArgs(exp)}) (check #29)`
|
@@ -639,89 +701,88 @@ export const typeCheck = (ast) => {
|
|
639
701
|
}
|
640
702
|
const isCast = STATIC_TYPES_SET.has(first[VALUE])
|
641
703
|
const expectedArgs = env[first[VALUE]][STATS][ARGUMENTS]
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
704
|
+
const EXPECTED_TYPE = expectedArgs[i][STATS][TYPE_PROP][0]
|
705
|
+
// IF UKNOWN andnot csted -we have nothing much to do
|
706
|
+
if (EXPECTED_TYPE === UNKNOWN && !isCast) continue
|
707
|
+
if (!isRestILeaf) {
|
708
|
+
const CAR = rest[i][0][VALUE]
|
709
|
+
const isKnown =
|
710
|
+
env[CAR] && env[CAR][STATS][RETURNS][0] !== UNKNOWN
|
711
|
+
if (isKnown && !isCast) {
|
712
|
+
if (env[CAR][STATS][RETURNS][0] !== EXPECTED_TYPE) {
|
713
|
+
errorStack.add(
|
714
|
+
`Incorrect type of argument (${i}) for special form (${
|
715
|
+
first[VALUE]
|
716
|
+
}). Expected (${toTypeNames(
|
717
|
+
EXPECTED_TYPE
|
718
|
+
)}) but got (${toTypeNames(
|
719
|
+
env[CAR][STATS][RETURNS][0]
|
720
|
+
)}) (${stringifyArgs(exp)}) (check #1)`
|
721
|
+
)
|
722
|
+
}
|
723
|
+
// never reached because there is only 1 subtype at the moment
|
724
|
+
// else if (
|
725
|
+
// PRED_TYPE &&
|
726
|
+
// env[CAR][STATS][RETURNS][1] !== PRED_TYPE
|
727
|
+
// ) {
|
728
|
+
// }
|
729
|
+
}
|
730
|
+
} else {
|
731
|
+
switch (rest[i][TYPE]) {
|
732
|
+
case WORD:
|
733
|
+
{
|
734
|
+
const CAR = rest[i][VALUE]
|
735
|
+
const isKnown =
|
736
|
+
env[CAR] &&
|
737
|
+
env[CAR][STATS][TYPE_PROP][0] !== UNKNOWN
|
738
|
+
if (isKnown && !isCast) {
|
739
|
+
if (
|
740
|
+
EXPECTED_TYPE !== env[CAR][STATS][TYPE_PROP][0]
|
741
|
+
) {
|
742
|
+
errorStack.add(
|
743
|
+
`Incorrect type of argument (${i}) for special form (${
|
744
|
+
first[VALUE]
|
745
|
+
}). Expected (${toTypeNames(
|
746
|
+
EXPECTED_TYPE
|
747
|
+
)}) but got (${toTypeNames(
|
748
|
+
env[CAR][STATS][TYPE_PROP][0]
|
749
|
+
)}) (${stringifyArgs(exp)}) (check #3)`
|
750
|
+
)
|
751
|
+
}
|
752
|
+
} else if (env[CAR]) {
|
753
|
+
if (isCast) {
|
754
|
+
// CAST assigment
|
755
|
+
env[rest[i][VALUE]][STATS][TYPE_PROP][0] =
|
756
|
+
root[first[VALUE]][STATS][RETURNS][0]
|
757
|
+
|
758
|
+
// root[first[VALUE]][STATS][RETURNS] =
|
759
|
+
// root[first[VALUE]][STATS][RETURNS]
|
760
|
+
} else {
|
761
|
+
// VALUE assigment
|
762
|
+
env[CAR][STATS][TYPE_PROP][0] = EXPECTED_TYPE
|
763
|
+
}
|
764
|
+
}
|
765
|
+
}
|
766
|
+
break
|
767
|
+
case ATOM: {
|
768
|
+
if (rest[i][TYPE] !== EXPECTED_TYPE) {
|
651
769
|
errorStack.add(
|
652
770
|
`Incorrect type of argument (${i}) for special form (${
|
653
771
|
first[VALUE]
|
654
772
|
}). Expected (${toTypeNames(
|
655
|
-
|
773
|
+
EXPECTED_TYPE
|
656
774
|
)}) but got (${toTypeNames(
|
657
|
-
|
658
|
-
)}) (${stringifyArgs(exp)}) (check #
|
775
|
+
rest[i][TYPE]
|
776
|
+
)}) (${stringifyArgs(exp)}) (check #2)`
|
659
777
|
)
|
660
778
|
}
|
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
|
-
}
|
779
|
+
break
|
719
780
|
}
|
720
781
|
}
|
721
782
|
}
|
722
783
|
}
|
723
784
|
// type checking
|
724
|
-
else if (
|
785
|
+
else if (isRestILeaf) {
|
725
786
|
const T =
|
726
787
|
rest[i][TYPE] === WORD && env[rest[i][VALUE]]
|
727
788
|
? 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: '|>',
|