fez-lisp 1.5.40 → 1.5.41
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/lib/baked/std.js +1 -1
- package/package.json +1 -1
- package/src/check.js +472 -126
- package/src/macros.js +3 -3
- package/src/utils.js +1 -0
package/src/check.js
CHANGED
@@ -4,6 +4,7 @@ import {
|
|
4
4
|
DEBUG,
|
5
5
|
FALSE,
|
6
6
|
KEYWORDS,
|
7
|
+
MUTATION_SUFFIX,
|
7
8
|
PLACEHOLDER,
|
8
9
|
PREDICATE_SUFFIX,
|
9
10
|
SPECIAL_FORMS_SET,
|
@@ -13,7 +14,12 @@ import {
|
|
13
14
|
WORD
|
14
15
|
} from './keywords.js'
|
15
16
|
import { isLeaf } from './parser.js'
|
16
|
-
import {
|
17
|
+
import {
|
18
|
+
getSuffix,
|
19
|
+
hasApplyLambdaBlock,
|
20
|
+
hasBlock,
|
21
|
+
stringifyArgs
|
22
|
+
} from './utils.js'
|
17
23
|
const ARGS_COUNT = 'n'
|
18
24
|
const VARIADIC = '...'
|
19
25
|
const STATS = '__stats__'
|
@@ -21,7 +27,8 @@ const ARGS = 'args'
|
|
21
27
|
const UNKNOWN = -1
|
22
28
|
const RETURNS = 'returns'
|
23
29
|
const SCOPE_NAME = '__scope__'
|
24
|
-
const
|
30
|
+
const SUB_TYPE = 'subType'
|
31
|
+
const TYPE_PROP = 'type'
|
25
32
|
const PREDICATE = 3
|
26
33
|
const RETRY_COUNT = 1
|
27
34
|
const DEFINITON_RETRY_COUNT = 1
|
@@ -328,7 +335,7 @@ export const typeCheck = (ast) => {
|
|
328
335
|
[ARGS_COUNT]: 1,
|
329
336
|
[ARGS]: [[ATOM, PLACEHOLDER, PREDICATE]],
|
330
337
|
[RETURNS]: ATOM,
|
331
|
-
[
|
338
|
+
[SUB_TYPE]: PREDICATE
|
332
339
|
}
|
333
340
|
},
|
334
341
|
[KEYWORDS.EQUAL]: {
|
@@ -341,7 +348,7 @@ export const typeCheck = (ast) => {
|
|
341
348
|
[ATOM, PLACEHOLDER]
|
342
349
|
],
|
343
350
|
[RETURNS]: ATOM,
|
344
|
-
[
|
351
|
+
[SUB_TYPE]: PREDICATE
|
345
352
|
}
|
346
353
|
},
|
347
354
|
[KEYWORDS.LESS_THAN]: {
|
@@ -354,7 +361,7 @@ export const typeCheck = (ast) => {
|
|
354
361
|
[ATOM, PLACEHOLDER]
|
355
362
|
],
|
356
363
|
[RETURNS]: ATOM,
|
357
|
-
[
|
364
|
+
[SUB_TYPE]: PREDICATE
|
358
365
|
}
|
359
366
|
},
|
360
367
|
[KEYWORDS.GREATHER_THAN]: {
|
@@ -367,7 +374,7 @@ export const typeCheck = (ast) => {
|
|
367
374
|
[ATOM, PLACEHOLDER]
|
368
375
|
],
|
369
376
|
[RETURNS]: ATOM,
|
370
|
-
[
|
377
|
+
[SUB_TYPE]: PREDICATE
|
371
378
|
}
|
372
379
|
},
|
373
380
|
[KEYWORDS.GREATHER_THAN_OR_EQUAL]: {
|
@@ -380,7 +387,7 @@ export const typeCheck = (ast) => {
|
|
380
387
|
[ATOM, PLACEHOLDER]
|
381
388
|
],
|
382
389
|
[RETURNS]: ATOM,
|
383
|
-
[
|
390
|
+
[SUB_TYPE]: PREDICATE
|
384
391
|
}
|
385
392
|
},
|
386
393
|
[KEYWORDS.LESS_THAN_OR_EQUAL]: {
|
@@ -393,7 +400,7 @@ export const typeCheck = (ast) => {
|
|
393
400
|
[ATOM, PLACEHOLDER]
|
394
401
|
],
|
395
402
|
[RETURNS]: ATOM,
|
396
|
-
[
|
403
|
+
[SUB_TYPE]: PREDICATE
|
397
404
|
}
|
398
405
|
},
|
399
406
|
[KEYWORDS.AND]: {
|
@@ -406,7 +413,7 @@ export const typeCheck = (ast) => {
|
|
406
413
|
[ATOM, PLACEHOLDER, PREDICATE]
|
407
414
|
],
|
408
415
|
[RETURNS]: ATOM,
|
409
|
-
[
|
416
|
+
[SUB_TYPE]: PREDICATE
|
410
417
|
}
|
411
418
|
},
|
412
419
|
[KEYWORDS.OR]: {
|
@@ -419,7 +426,7 @@ export const typeCheck = (ast) => {
|
|
419
426
|
[ATOM, PLACEHOLDER, PREDICATE]
|
420
427
|
],
|
421
428
|
[RETURNS]: ATOM,
|
422
|
-
[
|
429
|
+
[SUB_TYPE]: PREDICATE
|
423
430
|
}
|
424
431
|
},
|
425
432
|
[KEYWORDS.IS_ATOM]: {
|
@@ -429,7 +436,7 @@ export const typeCheck = (ast) => {
|
|
429
436
|
[ARGS_COUNT]: 1,
|
430
437
|
[ARGS]: [[UNKNOWN, PLACEHOLDER]],
|
431
438
|
[RETURNS]: ATOM,
|
432
|
-
[
|
439
|
+
[SUB_TYPE]: PREDICATE
|
433
440
|
}
|
434
441
|
},
|
435
442
|
[KEYWORDS.IS_LAMBDA]: {
|
@@ -439,7 +446,7 @@ export const typeCheck = (ast) => {
|
|
439
446
|
[ARGS_COUNT]: 1,
|
440
447
|
[ARGS]: [[UNKNOWN, PLACEHOLDER]],
|
441
448
|
[RETURNS]: ATOM,
|
442
|
-
[
|
449
|
+
[SUB_TYPE]: PREDICATE
|
443
450
|
}
|
444
451
|
},
|
445
452
|
[KEYWORDS.ERROR]: {
|
@@ -463,7 +470,6 @@ export const typeCheck = (ast) => {
|
|
463
470
|
const getScopeNames = (scope) => {
|
464
471
|
const scopeNames = []
|
465
472
|
let current = scope
|
466
|
-
|
467
473
|
while (current) {
|
468
474
|
if (current[SCOPE_NAME]) {
|
469
475
|
scopeNames.push(current[SCOPE_NAME])
|
@@ -518,6 +524,150 @@ export const typeCheck = (ast) => {
|
|
518
524
|
)
|
519
525
|
} else {
|
520
526
|
const name = rest[0][VALUE]
|
527
|
+
const resolveRetunType = (
|
528
|
+
returns,
|
529
|
+
rem,
|
530
|
+
prop,
|
531
|
+
isPredicate
|
532
|
+
) => {
|
533
|
+
if (returns[TYPE] === ATOM) {
|
534
|
+
env[name][STATS][prop] = ATOM
|
535
|
+
} else {
|
536
|
+
switch (returns[VALUE]) {
|
537
|
+
case KEYWORDS.IF:
|
538
|
+
const re = rem.slice(2)
|
539
|
+
if (re[0][TYPE] === ATOM || re[1][TYPE] === ATOM) {
|
540
|
+
env[name][STATS][RETURNS] = ATOM
|
541
|
+
// if (
|
542
|
+
// re[0][VALUE] === FALSE ||
|
543
|
+
// re[0][VALUE] === TRUE ||
|
544
|
+
// re[1][VALUE] === FALSE ||
|
545
|
+
// re[1][VALUE] === TRUE
|
546
|
+
// ) {
|
547
|
+
// env[name][STATS][SUB_TYPE] = PREDICATE
|
548
|
+
// }
|
549
|
+
} else if (!isLeaf(re[0]) && env[re[0][0][VALUE]]) {
|
550
|
+
env[name][STATS][RETURNS] =
|
551
|
+
env[re[0][0][VALUE]][STATS][RETURNS]
|
552
|
+
env[name][STATS][SUB_TYPE] =
|
553
|
+
env[re[0][0][VALUE]][STATS][SUB_TYPE]
|
554
|
+
} else {
|
555
|
+
if (env[re[0][VALUE]]) {
|
556
|
+
env[name][STATS][RETURNS] =
|
557
|
+
env[re[0][VALUE]][STATS].type
|
558
|
+
env[name][STATS][SUB_TYPE] =
|
559
|
+
env[re[0][VALUE]][STATS][SUB_TYPE]
|
560
|
+
} else {
|
561
|
+
env[name][STATS][RETURNS] = UNKNOWN
|
562
|
+
// env[name][STATS][RETURNS] = APPLY
|
563
|
+
}
|
564
|
+
}
|
565
|
+
break
|
566
|
+
default:
|
567
|
+
if (env[returns[VALUE]]) {
|
568
|
+
if (env[returns[VALUE]][STATS].type === APPLY) {
|
569
|
+
if (returns[VALUE] === KEYWORDS.CALL_FUNCTION) {
|
570
|
+
if (isLeaf(rest.at(-1).at(-1).at(-1))) {
|
571
|
+
const fnName = rest.at(-1).at(-1).at(-1)[
|
572
|
+
VALUE
|
573
|
+
]
|
574
|
+
const fn = env[fnName]
|
575
|
+
if (
|
576
|
+
!isPredicate &&
|
577
|
+
fn[STATS][SUB_TYPE] === PREDICATE
|
578
|
+
) {
|
579
|
+
warningStack.add(
|
580
|
+
`${name} is assigned to ${fnName} which ends in (${PREDICATE_SUFFIX}) so ${name} must also end in (${PREDICATE_SUFFIX}) (check #24)`
|
581
|
+
)
|
582
|
+
} else if (
|
583
|
+
isPredicate &&
|
584
|
+
fn[STATS][SUB_TYPE] !== PREDICATE
|
585
|
+
) {
|
586
|
+
warningStack.add(
|
587
|
+
`${name} ends in (${PREDICATE_SUFFIX}) and is expected to return (Predicate) but it doesn't (try wrapping it in a (true?) or (false?)) (check #25)`
|
588
|
+
)
|
589
|
+
}
|
590
|
+
env[name][STATS].type = fn[STATS][RETURNS]
|
591
|
+
env[name][STATS][SUB_TYPE] =
|
592
|
+
fn[STATS][SUB_TYPE]
|
593
|
+
} else {
|
594
|
+
const body = rest.at(-1).at(-1).at(-1).at(-1)
|
595
|
+
const rem = hasBlock(body)
|
596
|
+
? body.at(-1)
|
597
|
+
: body
|
598
|
+
const returns = isLeaf(rem) ? rem : rem[0]
|
599
|
+
resolveRetunType(
|
600
|
+
returns,
|
601
|
+
rem,
|
602
|
+
TYPE_PROP,
|
603
|
+
isPredicate
|
604
|
+
)
|
605
|
+
}
|
606
|
+
}
|
607
|
+
env[name][STATS][RETURNS] =
|
608
|
+
env[returns[VALUE]][STATS][RETURNS]
|
609
|
+
env[name][STATS][SUB_TYPE] =
|
610
|
+
env[returns[VALUE]][STATS][SUB_TYPE]
|
611
|
+
} else {
|
612
|
+
env[name][STATS][RETURNS] =
|
613
|
+
env[returns[VALUE]][STATS].type
|
614
|
+
env[name][STATS][SUB_TYPE] =
|
615
|
+
env[returns[VALUE]][SUB_TYPE]
|
616
|
+
}
|
617
|
+
} else {
|
618
|
+
env[name][STATS][RETURNS] = UNKNOWN
|
619
|
+
// env[name][STATS][RETURNS] = APPLY
|
620
|
+
}
|
621
|
+
break
|
622
|
+
}
|
623
|
+
}
|
624
|
+
if (
|
625
|
+
isPredicate &&
|
626
|
+
env[name][STATS][prop] !== UNKNOWN &&
|
627
|
+
env[name][STATS][SUB_TYPE] !== PREDICATE
|
628
|
+
) {
|
629
|
+
warningStack.add(
|
630
|
+
`${name} ends in (${PREDICATE_SUFFIX}) and is expected to return (Predicate) but it doesn't (try wrapping it in a (true?) or (false?)) (check #7)`
|
631
|
+
)
|
632
|
+
} else if (
|
633
|
+
!isPredicate &&
|
634
|
+
env[name][STATS][SUB_TYPE] === PREDICATE
|
635
|
+
) {
|
636
|
+
warningStack.add(
|
637
|
+
`${name} should end in (${PREDICATE_SUFFIX}) because it return (Predicate) (try adding ? at the end of the lambda name) (check #8)`
|
638
|
+
)
|
639
|
+
}
|
640
|
+
if (isPredicate) {
|
641
|
+
env[name][STATS][prop] = ATOM
|
642
|
+
env[name][STATS][SUB_TYPE] = PREDICATE
|
643
|
+
}
|
644
|
+
}
|
645
|
+
const checkReturnType = () => {
|
646
|
+
// if (name[name.length - 1] === PREDICATE_SUFFIX) {
|
647
|
+
// env[name][STATS][RETURNS] = ATOM
|
648
|
+
// env[name][STATS][SUB_TYPE] = PREDICATE
|
649
|
+
// } else {
|
650
|
+
const last = rest.at(-1).at(-1)
|
651
|
+
// const isApplyLambdaDoBlock = hasApplyLambdaBlock(
|
652
|
+
// rest.at(-1)
|
653
|
+
// )
|
654
|
+
const body = hasApplyLambdaBlock(last)
|
655
|
+
? last.at(-1).at(-1)
|
656
|
+
: last
|
657
|
+
const rem = hasBlock(body) ? body.at(-1) : body
|
658
|
+
const returns = isLeaf(rem) ? rem : rem[0]
|
659
|
+
const isPredicate = getSuffix(name) === PREDICATE_SUFFIX
|
660
|
+
resolveRetunType(returns, rem, RETURNS, isPredicate)
|
661
|
+
// }
|
662
|
+
// if (
|
663
|
+
// env[name][STATS][RETURNS] === UNKNOWN &&
|
664
|
+
// env[name][STATS].retried < RETRY_COUNT
|
665
|
+
// ) {
|
666
|
+
// env[name][STATS].retried += 1
|
667
|
+
// console.log(name, env[name][STATS])
|
668
|
+
// checkReturnType()
|
669
|
+
// }
|
670
|
+
}
|
521
671
|
if (
|
522
672
|
rest.at(-1)[0][TYPE] === APPLY &&
|
523
673
|
rest.at(-1)[0][VALUE] === KEYWORDS.ANONYMOUS_FUNCTION
|
@@ -531,102 +681,7 @@ export const typeCheck = (ast) => {
|
|
531
681
|
[ARGS]: []
|
532
682
|
}
|
533
683
|
}
|
534
|
-
|
535
|
-
// if (name[name.length - 1] === PREDICATE_SUFFIX) {
|
536
|
-
// env[name][STATS][RETURNS] = ATOM
|
537
|
-
// env[name][STATS][SUB_RETURN_TYPE] = PREDICATE
|
538
|
-
// } else {
|
539
|
-
const isPredicate =
|
540
|
-
name[name.length - 1] === PREDICATE_SUFFIX
|
541
|
-
const last = rest.at(-1).at(-1)
|
542
|
-
const body = hasApplyLambdaBlock(last)
|
543
|
-
? last.at(-1).at(-1)
|
544
|
-
: last
|
545
|
-
const rem = hasBlock(body) ? body.at(-1) : body
|
546
|
-
const returns = isLeaf(rem) ? rem : rem[0]
|
547
|
-
if (returns[TYPE] === ATOM) {
|
548
|
-
env[name][STATS][RETURNS] = ATOM
|
549
|
-
} else {
|
550
|
-
switch (returns[VALUE]) {
|
551
|
-
case KEYWORDS.IF:
|
552
|
-
const re = rem.slice(2)
|
553
|
-
if (re[0][TYPE] === ATOM || re[1][TYPE] === ATOM) {
|
554
|
-
env[name][STATS][RETURNS] = ATOM
|
555
|
-
// if (
|
556
|
-
// re[0][VALUE] === FALSE ||
|
557
|
-
// re[0][VALUE] === TRUE ||
|
558
|
-
// re[1][VALUE] === FALSE ||
|
559
|
-
// re[1][VALUE] === TRUE
|
560
|
-
// ) {
|
561
|
-
// env[name][STATS][SUB_RETURN_TYPE] = PREDICATE
|
562
|
-
// }
|
563
|
-
} else if (!isLeaf(re[0]) && env[re[0][0][VALUE]]) {
|
564
|
-
env[name][STATS][RETURNS] =
|
565
|
-
env[re[0][0][VALUE]][STATS][RETURNS]
|
566
|
-
env[name][STATS][SUB_RETURN_TYPE] =
|
567
|
-
env[re[0][0][VALUE]][STATS][SUB_RETURN_TYPE]
|
568
|
-
} else {
|
569
|
-
if (env[re[0][VALUE]]) {
|
570
|
-
env[name][STATS][RETURNS] =
|
571
|
-
env[re[0][VALUE]][STATS].type
|
572
|
-
env[name][STATS][SUB_RETURN_TYPE] =
|
573
|
-
env[re[0][VALUE]][STATS][SUB_RETURN_TYPE]
|
574
|
-
} else {
|
575
|
-
env[name][STATS][RETURNS] = UNKNOWN
|
576
|
-
// env[name][STATS][RETURNS] = APPLY
|
577
|
-
}
|
578
|
-
}
|
579
|
-
break
|
580
|
-
default:
|
581
|
-
if (env[returns[VALUE]]) {
|
582
|
-
if (env[returns[VALUE]][STATS].type === APPLY) {
|
583
|
-
env[name][STATS][RETURNS] =
|
584
|
-
env[returns[VALUE]][STATS][RETURNS]
|
585
|
-
env[name][STATS][SUB_RETURN_TYPE] =
|
586
|
-
env[returns[VALUE]][STATS][SUB_RETURN_TYPE]
|
587
|
-
} else {
|
588
|
-
env[name][STATS][RETURNS] =
|
589
|
-
env[returns[VALUE]][STATS].type
|
590
|
-
env[name][STATS][SUB_RETURN_TYPE] =
|
591
|
-
env[returns[VALUE]][SUB_RETURN_TYPE]
|
592
|
-
}
|
593
|
-
} else {
|
594
|
-
env[name][STATS][RETURNS] = UNKNOWN
|
595
|
-
// env[name][STATS][RETURNS] = APPLY
|
596
|
-
}
|
597
|
-
break
|
598
|
-
}
|
599
|
-
}
|
600
|
-
if (
|
601
|
-
isPredicate &&
|
602
|
-
env[name][STATS][RETURNS] !== UNKNOWN &&
|
603
|
-
env[name][STATS][SUB_RETURN_TYPE] !== PREDICATE
|
604
|
-
) {
|
605
|
-
warningStack.add(
|
606
|
-
`${name} ends in (${PREDICATE_SUFFIX}) and is expected to return (Predicate) but it doesn't (try wrapping it in a (true?) or (false?)) (check #7)`
|
607
|
-
)
|
608
|
-
} else if (
|
609
|
-
!isPredicate &&
|
610
|
-
env[name][STATS][SUB_RETURN_TYPE] === PREDICATE
|
611
|
-
) {
|
612
|
-
warningStack.add(
|
613
|
-
`${name} should end in (${PREDICATE_SUFFIX}) because it return (Predicate) (try adding ? at the end of the lambda name) (check #8)`
|
614
|
-
)
|
615
|
-
}
|
616
|
-
if (isPredicate) {
|
617
|
-
env[name][STATS][RETURNS] = ATOM
|
618
|
-
env[name][STATS][SUB_RETURN_TYPE] = PREDICATE
|
619
|
-
}
|
620
|
-
// }
|
621
|
-
// if (
|
622
|
-
// env[name][STATS][RETURNS] === UNKNOWN &&
|
623
|
-
// env[name][STATS].retried < RETRY_COUNT
|
624
|
-
// ) {
|
625
|
-
// env[name][STATS].retried += 1
|
626
|
-
// console.log(name, env[name][STATS])
|
627
|
-
// checkReturnType()
|
628
|
-
// }
|
629
|
-
}
|
684
|
+
|
630
685
|
checkReturnType()
|
631
686
|
if (
|
632
687
|
env[name][STATS][RETURNS] === UNKNOWN &&
|
@@ -642,21 +697,119 @@ export const typeCheck = (ast) => {
|
|
642
697
|
check(rest.at(-1), env, exp)
|
643
698
|
}
|
644
699
|
} else {
|
645
|
-
if (!(name in env)) {
|
646
|
-
|
647
|
-
|
648
|
-
|
700
|
+
// if (!(name in env)) {
|
701
|
+
if (rest[1][TYPE] === WORD) {
|
702
|
+
env[name] = env[rest[1][VALUE]]
|
703
|
+
if (
|
704
|
+
getSuffix(rest[1][VALUE]) === PREDICATE_SUFFIX &&
|
705
|
+
getSuffix(name) !== PREDICATE_SUFFIX
|
706
|
+
)
|
707
|
+
warningStack.add(
|
708
|
+
`${name} is assigned to ${rest[1][VALUE]} which ends in (${PREDICATE_SUFFIX}) so ${name} must also end in (${PREDICATE_SUFFIX}) (check #17)`
|
709
|
+
)
|
710
|
+
else if (
|
711
|
+
getSuffix(rest[1][VALUE]) === MUTATION_SUFFIX &&
|
712
|
+
getSuffix(name) !== MUTATION_SUFFIX
|
713
|
+
)
|
714
|
+
warningStack.add(
|
715
|
+
`${name} is assigned to ${rest[1][VALUE]} which ends in (${MUTATION_SUFFIX}) so ${name} must also end in (${MUTATION_SUFFIX}) (check #18)`
|
716
|
+
)
|
717
|
+
} else {
|
718
|
+
const isL = isLeaf(rest.at(-1))
|
719
|
+
const right = isL ? rest.at(-1) : rest.at(-1)[0]
|
720
|
+
if (isL && right[TYPE] === ATOM) {
|
721
|
+
const isPredicate = getSuffix(name) === PREDICATE_SUFFIX
|
722
|
+
if (
|
723
|
+
isPredicate &&
|
724
|
+
right[VALUE] !== TRUE &&
|
725
|
+
right[VALUE] !== FALSE
|
726
|
+
) {
|
727
|
+
warningStack.add(
|
728
|
+
`${name} ends in (${PREDICATE_SUFFIX}) but is assigned to ${
|
729
|
+
right[VALUE]
|
730
|
+
} which is not a (${toTypeNames(
|
731
|
+
PREDICATE
|
732
|
+
)}). Either remove (${PREDICATE_SUFFIX}) or change the value to ${TRUE} or ${FALSE} (check #20)`
|
733
|
+
)
|
734
|
+
}
|
649
735
|
env[name] = {
|
650
736
|
[STATS]: {
|
651
737
|
retried: 0,
|
652
|
-
type:
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
738
|
+
type: ATOM
|
739
|
+
}
|
740
|
+
}
|
741
|
+
if (isPredicate) env[name][STATS][SUB_TYPE] = PREDICATE
|
742
|
+
} else {
|
743
|
+
const isPredicate = getSuffix(name) === PREDICATE_SUFFIX
|
744
|
+
if (
|
745
|
+
getSuffix(right[VALUE]) === PREDICATE_SUFFIX &&
|
746
|
+
!isPredicate
|
747
|
+
)
|
748
|
+
warningStack.add(
|
749
|
+
`${name} is assigned to ${right[VALUE]} which ends in (${PREDICATE_SUFFIX}) so ${name} must also end in (${PREDICATE_SUFFIX}) (check #19)`
|
750
|
+
)
|
751
|
+
env[name] = {
|
752
|
+
[STATS]: {
|
753
|
+
retried: 0,
|
754
|
+
type: isL
|
755
|
+
? right[TYPE]
|
756
|
+
: env[right[VALUE]]?.[STATS]?.[RETURNS] ?? UNKNOWN
|
757
|
+
}
|
758
|
+
}
|
759
|
+
if (right[VALUE] === KEYWORDS.CALL_FUNCTION) {
|
760
|
+
if (isLeaf(rest.at(-1).at(-1))) {
|
761
|
+
const fnName = rest.at(-1).at(-1)[VALUE]
|
762
|
+
const fn = env[fnName]
|
763
|
+
if (
|
764
|
+
!isPredicate &&
|
765
|
+
fn[STATS][SUB_TYPE] === PREDICATE
|
766
|
+
) {
|
767
|
+
warningStack.add(
|
768
|
+
`${name} is assigned to ${fnName} which ends in (${PREDICATE_SUFFIX}) so ${name} must also end in (${PREDICATE_SUFFIX}) (check #24)`
|
769
|
+
)
|
770
|
+
} else if (
|
771
|
+
isPredicate &&
|
772
|
+
fn[STATS][SUB_TYPE] !== PREDICATE
|
773
|
+
) {
|
774
|
+
warningStack.add(
|
775
|
+
`${name} ends in (${PREDICATE_SUFFIX}) and is expected to return (Predicate) but it doesn't (try wrapping it in a (true?) or (false?)) (check #25)`
|
776
|
+
)
|
777
|
+
}
|
778
|
+
env[name][STATS].type = fn[STATS][RETURNS]
|
779
|
+
env[name][STATS][SUB_TYPE] = fn[STATS][SUB_TYPE]
|
780
|
+
} else {
|
781
|
+
const body = rest.at(-1).at(-1).at(-1)
|
782
|
+
const rem = hasBlock(body) ? body.at(-1) : body
|
783
|
+
const returns = isLeaf(rem) ? rem : rem[0]
|
784
|
+
// console.log({ returns })
|
785
|
+
resolveRetunType(
|
786
|
+
returns,
|
787
|
+
rem,
|
788
|
+
TYPE_PROP,
|
789
|
+
isPredicate
|
790
|
+
)
|
791
|
+
}
|
792
|
+
}
|
793
|
+
if (isPredicate) env[name][STATS][SUB_TYPE] = PREDICATE
|
794
|
+
if (env[right[VALUE]]?.[STATS]?.[SUB_TYPE]) {
|
795
|
+
if (
|
796
|
+
env[right[VALUE]][STATS][SUB_TYPE] === PREDICATE &&
|
797
|
+
!isPredicate
|
798
|
+
) {
|
799
|
+
warningStack.add(
|
800
|
+
`${name} is assigned to the result of a (${toTypeNames(
|
801
|
+
PREDICATE
|
802
|
+
)}) so ${name} must end in (${PREDICATE_SUFFIX}) (check #23)`
|
803
|
+
)
|
657
804
|
}
|
805
|
+
env[name][STATS][SUB_TYPE] =
|
806
|
+
env[right[VALUE]][STATS][SUB_TYPE]
|
658
807
|
}
|
808
|
+
}
|
809
|
+
|
810
|
+
// console.log(name, env[name])
|
659
811
|
}
|
812
|
+
// }
|
660
813
|
check(rest.at(-1), env, scope)
|
661
814
|
}
|
662
815
|
}
|
@@ -690,11 +843,9 @@ export const typeCheck = (ast) => {
|
|
690
843
|
}
|
691
844
|
if (env[copy[SCOPE_NAME]]) {
|
692
845
|
env[copy[SCOPE_NAME]][STATS][ARGS][i] = copy[param[VALUE]]
|
693
|
-
if (
|
694
|
-
param[VALUE][param[VALUE].length - 1] === PREDICATE_SUFFIX
|
695
|
-
) {
|
846
|
+
if (getSuffix(param[VALUE]) === PREDICATE_SUFFIX) {
|
696
847
|
copy[param[VALUE]][STATS][RETURNS] = ATOM
|
697
|
-
copy[param[VALUE]][STATS][
|
848
|
+
copy[param[VALUE]][STATS][SUB_TYPE] = PREDICATE
|
698
849
|
}
|
699
850
|
}
|
700
851
|
}
|
@@ -742,15 +893,210 @@ export const typeCheck = (ast) => {
|
|
742
893
|
env[first[VALUE]][STATS][ARGS_COUNT] = rest.length
|
743
894
|
}
|
744
895
|
}
|
896
|
+
|
745
897
|
// also type of arg
|
746
898
|
const args = env[first[VALUE]][STATS][ARGS]
|
747
899
|
if (args) {
|
748
900
|
for (let i = 0; i < args.length; ++i) {
|
749
901
|
// type check
|
902
|
+
// todo finish this
|
903
|
+
|
904
|
+
if (args[i][SUB] != undefined) {
|
905
|
+
// first[TYPE] === APPLY &&
|
906
|
+
// env[first[VALUE]][STATS][SUB_TYPE] === PREDICATE
|
907
|
+
// args[i][SUB] = env[rest[i][VALUE]][SUB_TYPE]
|
908
|
+
if (isLeaf(rest[i])) {
|
909
|
+
if (rest[i][TYPE] === WORD) {
|
910
|
+
// TODO finish this
|
911
|
+
if (
|
912
|
+
env[rest[i][VALUE]] &&
|
913
|
+
args[i][SUB] !==
|
914
|
+
env[rest[i][VALUE]][STATS][SUB_TYPE]
|
915
|
+
) {
|
916
|
+
errorStack.set(
|
917
|
+
key.str,
|
918
|
+
`Incorrect type of arguments for (${
|
919
|
+
first[VALUE]
|
920
|
+
}). Expected (${toTypeNames(
|
921
|
+
args[i][SUB]
|
922
|
+
)}) but got (${toTypeNames(
|
923
|
+
env[rest[i][VALUE]][STATS][SUB_TYPE] ??
|
924
|
+
env[rest[i][VALUE]][STATS].type
|
925
|
+
)}) (${stringifyArgs(exp)}) (check #16)`
|
926
|
+
)
|
927
|
+
}
|
928
|
+
} else if (rest[i][TYPE] === ATOM) {
|
929
|
+
if (
|
930
|
+
args[i][SUB] === PREDICATE &&
|
931
|
+
rest[i][VALUE] !== TRUE &&
|
932
|
+
rest[i][VALUE] !== FALSE
|
933
|
+
) {
|
934
|
+
errorStack.set(
|
935
|
+
key.str,
|
936
|
+
`Incorrect type of arguments for (${
|
937
|
+
first[VALUE]
|
938
|
+
}). Expected (${toTypeNames(
|
939
|
+
args[i][SUB]
|
940
|
+
)}) but got an (${toTypeNames(
|
941
|
+
rest[i][TYPE]
|
942
|
+
)}) which is neither ${TRUE} or ${FALSE} (${stringifyArgs(
|
943
|
+
exp
|
944
|
+
)}) (check #22)`
|
945
|
+
)
|
946
|
+
}
|
947
|
+
}
|
948
|
+
} else {
|
949
|
+
const current = rest[i][0]
|
950
|
+
if (current[TYPE] === APPLY) {
|
951
|
+
if (current[VALUE] == KEYWORDS.CALL_FUNCTION) {
|
952
|
+
if (isLeaf(rest[i].at(-1))) {
|
953
|
+
const fnName = rest[i].at(-1)[VALUE]
|
954
|
+
const fn = env[fnName]
|
955
|
+
if (
|
956
|
+
fn &&
|
957
|
+
fn[STATS][RETURNS] !== args[i][TYPE]
|
958
|
+
) {
|
959
|
+
errorStack.set(
|
960
|
+
key.str,
|
961
|
+
`Incorrect type of arguments for (${
|
962
|
+
first[VALUE]
|
963
|
+
}). Expected (${toTypeNames(
|
964
|
+
args[i][TYPE]
|
965
|
+
)}) but got an (${toTypeNames(
|
966
|
+
fn[STATS][RETURNS]
|
967
|
+
)}) (${stringifyArgs(exp)}) (check #26)`
|
968
|
+
)
|
969
|
+
}
|
970
|
+
if (
|
971
|
+
fn &&
|
972
|
+
fn[STATS][SUB_TYPE] !== args[i][SUB]
|
973
|
+
) {
|
974
|
+
errorStack.set(
|
975
|
+
key.str,
|
976
|
+
`Incorrect type of arguments for (${
|
977
|
+
first[VALUE]
|
978
|
+
}). Expected (${toTypeNames(
|
979
|
+
args[i][SUB]
|
980
|
+
)}) but got an (${toTypeNames(
|
981
|
+
fn[STATS][SUB_TYPE]
|
982
|
+
)}) which is neither ${TRUE} or ${FALSE} (${stringifyArgs(
|
983
|
+
exp
|
984
|
+
)}) (check #27)`
|
985
|
+
)
|
986
|
+
}
|
987
|
+
// env[name][STATS].type = fn[STATS][RETURNS]
|
988
|
+
// env[name][STATS][SUB_TYPE] = fn[STATS][SUB_TYPE]
|
989
|
+
} else {
|
990
|
+
const body = rest[i].at(-1).at(-1)
|
991
|
+
const rem = hasBlock(body)
|
992
|
+
? body.at(-1)
|
993
|
+
: body
|
994
|
+
const returns = isLeaf(rem) ? rem : rem[0]
|
995
|
+
if (returns[TYPE] === ATOM) {
|
996
|
+
if (args[i][TYPE] !== ATOM) {
|
997
|
+
errorStack.set(
|
998
|
+
key.str,
|
999
|
+
`Incorrect type of argument ${i} for (${
|
1000
|
+
first[VALUE]
|
1001
|
+
}). Expected (${toTypeNames(
|
1002
|
+
args[i][TYPE]
|
1003
|
+
)}) but got an (${toTypeNames(
|
1004
|
+
ATOM
|
1005
|
+
)}) (${stringifyArgs(
|
1006
|
+
exp
|
1007
|
+
)}) (check #27)`
|
1008
|
+
)
|
1009
|
+
}
|
1010
|
+
if (
|
1011
|
+
args[i][SUB] &&
|
1012
|
+
args[i][SUB] === PREDICATE &&
|
1013
|
+
returns[VALUE] !== TRUE &&
|
1014
|
+
returns[VALUE] !== FALSE
|
1015
|
+
) {
|
1016
|
+
errorStack.set(
|
1017
|
+
key.str,
|
1018
|
+
`Incorrect type of argument ${i} for (${
|
1019
|
+
first[VALUE]
|
1020
|
+
}). Expected (${toTypeNames(
|
1021
|
+
args[i][SUB]
|
1022
|
+
)}) but got an (${toTypeNames(
|
1023
|
+
ATOM
|
1024
|
+
)}) which is neither ${TRUE} or ${FALSE} (${stringifyArgs(
|
1025
|
+
exp
|
1026
|
+
)}) (check #27)`
|
1027
|
+
)
|
1028
|
+
}
|
1029
|
+
} else if (env[returns[VALUE]]) {
|
1030
|
+
if (
|
1031
|
+
args[i][TYPE] !==
|
1032
|
+
env[returns[VALUE]][STATS][RETURNS]
|
1033
|
+
) {
|
1034
|
+
errorStack.set(
|
1035
|
+
key.str,
|
1036
|
+
`Incorrect type of argument ${i} for (${
|
1037
|
+
first[VALUE]
|
1038
|
+
}). Expected (${toTypeNames(
|
1039
|
+
args[i][TYPE]
|
1040
|
+
)}) but got (${toTypeNames(
|
1041
|
+
env[returns[VALUE]][STATS][TYPE_PROP]
|
1042
|
+
)}) (${stringifyArgs(
|
1043
|
+
exp
|
1044
|
+
)}) (check #29)`
|
1045
|
+
)
|
1046
|
+
}
|
1047
|
+
if (
|
1048
|
+
args[i][SUB] &&
|
1049
|
+
args[i][SUB] !==
|
1050
|
+
env[returns[VALUE]][STATS][SUB_TYPE]
|
1051
|
+
) {
|
1052
|
+
errorStack.set(
|
1053
|
+
key.str,
|
1054
|
+
`Incorrect type of argument ${i} for (${
|
1055
|
+
first[VALUE]
|
1056
|
+
}). Expected (${toTypeNames(
|
1057
|
+
args[i][SUB]
|
1058
|
+
)}) but got (${toTypeNames(
|
1059
|
+
env[returns[VALUE]][STATS][SUB_TYPE]
|
1060
|
+
)}) (${stringifyArgs(exp)}) (check #28)`
|
1061
|
+
)
|
1062
|
+
}
|
1063
|
+
}
|
1064
|
+
|
1065
|
+
// // console.log({ returns })
|
1066
|
+
// resolveRetunType(
|
1067
|
+
// returns,
|
1068
|
+
// rem,
|
1069
|
+
// TYPE_PROP,
|
1070
|
+
// isPredicate
|
1071
|
+
// )
|
1072
|
+
}
|
1073
|
+
|
1074
|
+
// console.log(args[i], env[current[VALUE]][STATS])
|
1075
|
+
} else if (
|
1076
|
+
env[current[VALUE]][STATS][SUB_TYPE] !==
|
1077
|
+
args[i][SUB]
|
1078
|
+
) {
|
1079
|
+
errorStack.set(
|
1080
|
+
key.str,
|
1081
|
+
`Incorrect type of arguments (${i}) for (${
|
1082
|
+
first[VALUE]
|
1083
|
+
}). Expected (${toTypeNames(
|
1084
|
+
args[i][SUB]
|
1085
|
+
)}) but got (${toTypeNames(
|
1086
|
+
env[current[VALUE]][STATS][SUB_TYPE] ??
|
1087
|
+
env[current[VALUE]][STATS][RETURNS]
|
1088
|
+
)}) (${stringifyArgs(exp)}) (check #21)`
|
1089
|
+
)
|
1090
|
+
}
|
1091
|
+
}
|
1092
|
+
}
|
1093
|
+
}
|
1094
|
+
|
750
1095
|
if (
|
751
1096
|
first[TYPE] === APPLY &&
|
752
|
-
isSpecial
|
753
|
-
|
1097
|
+
isSpecial
|
1098
|
+
// &&
|
1099
|
+
// env[first[VALUE]][STATS][ARGS_COUNT] !== VARIADIC
|
754
1100
|
) {
|
755
1101
|
const expectedArgs = env[first[VALUE]][STATS][ARGS]
|
756
1102
|
for (let i = 0; i < rest.length; ++i) {
|
@@ -780,7 +1126,7 @@ export const typeCheck = (ast) => {
|
|
780
1126
|
} else if (
|
781
1127
|
isKnown &&
|
782
1128
|
expectedArgs[i][SUB] &&
|
783
|
-
env[CAR][STATS][
|
1129
|
+
env[CAR][STATS][SUB_TYPE] !==
|
784
1130
|
expectedArgs[i][SUB]
|
785
1131
|
) {
|
786
1132
|
errorStack.set(
|
@@ -790,7 +1136,7 @@ export const typeCheck = (ast) => {
|
|
790
1136
|
}). Expected (${toTypeNames(
|
791
1137
|
expectedArgs[i][SUB]
|
792
1138
|
)}) but got (${toTypeNames(
|
793
|
-
env[CAR][STATS][
|
1139
|
+
env[CAR][STATS][SUB_TYPE] ??
|
794
1140
|
env[CAR][STATS][RETURNS]
|
795
1141
|
)}) (${stringifyArgs(exp)}) (check #13)`
|
796
1142
|
)
|