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 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.86",
5
+ "version": "1.5.88",
6
6
  "type": "module",
7
7
  "main": "index.js",
8
8
  "keywords": [
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
- PREDICATES_SET,
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 { hasApplyLambdaBlock, hasBlock, stringifyArgs } from './utils.js'
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
- PREDICATES_SET.has(first[VALUE]) &&
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 (isLeaf(rest[i].at(-1))) {
594
- const fnName = rest[i].at(-1)[VALUE]
595
- const fn = env[fnName]
596
- if (fn && fn[STATS][RETURNS][0] !== MAIN_TYPE) {
597
- errorStack.add(
598
- `Incorrect type of argument (${i}) for (${
599
- first[VALUE]
600
- }). Expected (${toTypeNames(
601
- MAIN_TYPE
602
- )}) but got an (${toTypeNames(
603
- fn[STATS][RETURNS][0]
604
- )}) (${stringifyArgs(exp)}) (check #26)`
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
- )}) (${stringifyArgs(exp)}) (check #27)`
701
+ )}) but got an (${toTypeNames(
702
+ fn[STATS][RETURNS][0]
703
+ )}) (${stringifyArgs(exp)}) (check #26)`
621
704
  )
622
705
  }
623
- } else if (env[returns[VALUE]]) {
624
- if (
625
- MAIN_TYPE !== env[returns[VALUE]][STATS][RETURNS][0]
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
- MAIN_TYPE
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
- for (let i = 0; i < rest.length; ++i) {
643
- const MAIN_TYPE = expectedArgs[i][STATS][TYPE_PROP][0]
644
- if (MAIN_TYPE === UNKNOWN && !isCast) continue
645
- if (!isLeaf(rest[i])) {
646
- const CAR = rest[i][0][VALUE]
647
- const isKnown =
648
- env[CAR] && env[CAR][STATS][RETURNS][0] !== UNKNOWN
649
- if (isKnown && !isCast) {
650
- if (env[CAR][STATS][RETURNS][0] !== MAIN_TYPE) {
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
- MAIN_TYPE
810
+ EXPECTED_TYPE
656
811
  )}) but got (${toTypeNames(
657
- env[CAR][STATS][RETURNS][0]
658
- )}) (${stringifyArgs(exp)}) (check #1)`
812
+ rest[i][TYPE]
813
+ )}) (${stringifyArgs(exp)}) (check #2)`
659
814
  )
660
815
  }
661
- // never reached because there is only 1 subtype at the moment
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 (isLeaf(rest[i])) {
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 PREDICATES_SET = new Set([
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 { getSuffix, hasBlock, stringifyArgs } from './utils.js'
18
+ import { hasBlock, stringifyArgs } from './utils.js'
21
19
  export const SUGGAR = {
22
20
  // Syntactic suggars
23
21
  PIPE: '|>',