fez-lisp 1.5.91 → 1.5.92
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 +667 -539
- package/src/compiler.js +1 -0
- package/src/interpreter.js +2 -1
- package/src/keywords.js +2 -1
- package/src/types.js +23 -18
- package/src/utils.js +6 -0
package/src/check.js
CHANGED
@@ -32,12 +32,14 @@ import {
|
|
32
32
|
MAX_ARGUMENT_RETRY,
|
33
33
|
ORDER,
|
34
34
|
VARIABLE_ORDER_INDEX,
|
35
|
-
COLLECTION
|
35
|
+
COLLECTION,
|
36
|
+
ANY
|
36
37
|
} from './types.js'
|
37
38
|
import {
|
38
39
|
getSuffix,
|
39
40
|
hasApplyLambdaBlock,
|
40
41
|
hasBlock,
|
42
|
+
logExp,
|
41
43
|
stringifyArgs
|
42
44
|
} from './utils.js'
|
43
45
|
|
@@ -63,6 +65,84 @@ const deepLambdaReturn = (rest, condition) => {
|
|
63
65
|
const rem = hasBlock(body) ? body.at(-1) : body
|
64
66
|
return condition(rem) ? rem : deepLambdaReturn(rem, condition)
|
65
67
|
}
|
68
|
+
export const isTypeAbstraction = (stats) => {
|
69
|
+
return stats[TYPE_PROP] === APPLY
|
70
|
+
}
|
71
|
+
export const setTypeRef = (stats, value) => {
|
72
|
+
// if (!isAnyReturn(stats) && !isAnyReturn(value))
|
73
|
+
if (isUnknownType(stats)) stats[TYPE_PROP] = value[TYPE_PROP]
|
74
|
+
}
|
75
|
+
export const setReturnRef = (stats, value) => {
|
76
|
+
// if (!isAnyReturn(stats) && !isAnyReturn(value))
|
77
|
+
if (isUnknownReturn(stats)) stats[RETURNS] = value[RETURNS]
|
78
|
+
}
|
79
|
+
export const setReturnToTypeRef = (stats, value) => {
|
80
|
+
// if (!isAnyReturn(stats) && !isAnyReturn(value))
|
81
|
+
if (isUnknownReturn(stats)) stats[RETURNS] = value[TYPE_PROP]
|
82
|
+
}
|
83
|
+
export const setPropRef = (stats, prop, value) => {
|
84
|
+
// if (stats[prop][0] !== ANY && value[prop][0] !== ANY)
|
85
|
+
if (stats[prop][0] === UNKNOWN) stats[prop] = value[prop]
|
86
|
+
}
|
87
|
+
export const setReturn = (stats, value) => {
|
88
|
+
// if (!isAnyReturn(stats) && !isAnyReturn(value))
|
89
|
+
if (isUnknownReturn(stats) && !isUnknownReturn(value))
|
90
|
+
stats[RETURNS][0] = value[RETURNS][0]
|
91
|
+
}
|
92
|
+
export const setType = (stats, value) => {
|
93
|
+
// if (!isAnyType(stats) && !isAnyType(value))
|
94
|
+
|
95
|
+
if (isUnknownType(stats) && !isUnknownType(value))
|
96
|
+
stats[TYPE_PROP][0] = value[TYPE_PROP][0]
|
97
|
+
}
|
98
|
+
export const setTypeToReturn = (stats, value) => {
|
99
|
+
// if (!isAnyType(stats) && !isAnyReturn(value))
|
100
|
+
if (isUnknownType(stats) && !isUnknownReturn(value))
|
101
|
+
stats[TYPE_PROP][0] = value[RETURNS][0]
|
102
|
+
}
|
103
|
+
export const setReturnToType = (stats, value) => {
|
104
|
+
// if (!isAnyType(stats) && !isAnyReturn(value))
|
105
|
+
if (isUnknownReturn(stats) && !isUnknownType(value))
|
106
|
+
stats[RETURNS][0] = value[TYPE_PROP][0]
|
107
|
+
}
|
108
|
+
export const setProp = (stats, prop, value) => {
|
109
|
+
// if (stats[prop][0] !== ANY && value[prop][0] !== ANY)
|
110
|
+
if (stats[prop][0] === UNKNOWN && value[prop][0] !== UNKNOWN)
|
111
|
+
stats[prop][0] = value[prop][0]
|
112
|
+
}
|
113
|
+
export const isAnyReturn = (stats) => {
|
114
|
+
return stats && stats[RETURNS][0] === ANY
|
115
|
+
}
|
116
|
+
export const isAnyType = (stats) => {
|
117
|
+
return stats && stats[TYPE_PROP][0] === ANY
|
118
|
+
}
|
119
|
+
export const isUnknownType = (stats) => {
|
120
|
+
return stats && stats[TYPE_PROP][0] === UNKNOWN
|
121
|
+
}
|
122
|
+
export const isUnknownReturn = (stats) => {
|
123
|
+
return stats[RETURNS][0] === UNKNOWN
|
124
|
+
}
|
125
|
+
export const getType = (stats) => {
|
126
|
+
return stats && stats[TYPE_PROP][0]
|
127
|
+
}
|
128
|
+
export const getReturn = (stats) => {
|
129
|
+
return stats && stats[RETURNS][0]
|
130
|
+
}
|
131
|
+
export const isAtomType = (stats) => {
|
132
|
+
return isAnyType(stats) || stats[TYPE_PROP][0] === ATOM
|
133
|
+
}
|
134
|
+
export const isAtomReturn = (stats) => {
|
135
|
+
return isAnyType(stats) || stats[RETURNS][0] === ATOM
|
136
|
+
}
|
137
|
+
export const compareTypes = (a, b) => {
|
138
|
+
return isAnyType(a) || isAnyType(b) || a[TYPE_PROP][0] === b[TYPE_PROP][0]
|
139
|
+
}
|
140
|
+
export const compareReturns = (a, b) => {
|
141
|
+
return isAnyReturn(a) || isAnyReturn(b) || a[RETURNS][0] === b[RETURNS][0]
|
142
|
+
}
|
143
|
+
export const compareTypeWithReturn = (a, b) => {
|
144
|
+
return isAnyType(a) || isAnyReturn(b) || a[TYPE_PROP][0] === b[RETURNS][0]
|
145
|
+
}
|
66
146
|
const checkPredicateName = (exp, rest, warningStack) => {
|
67
147
|
if (getSuffix(rest[0][VALUE]) === PREDICATE_SUFFIX) {
|
68
148
|
const last = rest.at(-1)
|
@@ -147,7 +227,7 @@ export const formatType = (name, env) => {
|
|
147
227
|
const stats = env[name][STATS]
|
148
228
|
const isAnonymous = typeof name === 'number'
|
149
229
|
return stats
|
150
|
-
? stats
|
230
|
+
? getType(stats) === APPLY
|
151
231
|
? `${isAnonymous ? '' : `(let ${name} `}(lambda ${
|
152
232
|
stats[ARG_COUNT] === VARIADIC
|
153
233
|
? '... ' + STATIC_TYPES.UNKNOWN
|
@@ -155,17 +235,17 @@ export const formatType = (name, env) => {
|
|
155
235
|
.map(
|
156
236
|
(x, i) =>
|
157
237
|
`${
|
158
|
-
x[STATS]
|
238
|
+
getType(x[STATS]) === APPLY
|
159
239
|
? `${formatType(i, stats[ARGUMENTS])}`
|
160
|
-
: `${toTypeNames(x[STATS]
|
240
|
+
: `${toTypeNames(getType(x[STATS]))}`
|
161
241
|
}`
|
162
242
|
)
|
163
243
|
.join(' ')
|
164
244
|
// TODO format returned functions when type support is added
|
165
|
-
} (${KEYWORDS.BLOCK} ${toTypeNames(stats
|
245
|
+
} (${KEYWORDS.BLOCK} ${toTypeNames(getReturn(stats))})${
|
166
246
|
isAnonymous ? '' : ')'
|
167
247
|
})`
|
168
|
-
: `(let ${name} ${toTypeNames(stats
|
248
|
+
: `(let ${name} ${toTypeNames(getType(stats))})`
|
169
249
|
: name
|
170
250
|
}
|
171
251
|
const formatTypes = (env) => {
|
@@ -192,9 +272,9 @@ const withScope = (name, scope) => {
|
|
192
272
|
.map((x) => (Number.isInteger(+x) ? '::' : x))
|
193
273
|
.join(' ')} ${name}`
|
194
274
|
}
|
195
|
-
export const typeCheck = (ast) => {
|
275
|
+
export const typeCheck = (ast, error = true) => {
|
196
276
|
const root = structuredClone(SPECIAL_FORM_TYPES)
|
197
|
-
root[ORDER] = 0
|
277
|
+
// root[ORDER] = 0
|
198
278
|
const errorStack = new Set()
|
199
279
|
const warningStack = new Set()
|
200
280
|
// TODO delete this
|
@@ -273,7 +353,7 @@ export const typeCheck = (ast) => {
|
|
273
353
|
} else if (
|
274
354
|
!isLeaf(re[0]) &&
|
275
355
|
env[re[0][0][VALUE]] &&
|
276
|
-
env[re[0][0][VALUE]][STATS]
|
356
|
+
!isUnknownReturn(env[re[0][0][VALUE]][STATS])
|
277
357
|
) {
|
278
358
|
env[name][STATS][prop] =
|
279
359
|
env[re[0][0][VALUE]][STATS][RETURNS]
|
@@ -293,10 +373,13 @@ export const typeCheck = (ast) => {
|
|
293
373
|
} else if (
|
294
374
|
!isLeaf(re[1]) &&
|
295
375
|
env[re[1][0][VALUE]] &&
|
296
|
-
env[re[1][0][VALUE]][STATS]
|
376
|
+
!isUnknownReturn(env[re[1][0][VALUE]][STATS])
|
297
377
|
) {
|
298
|
-
|
299
|
-
env[
|
378
|
+
setProp(
|
379
|
+
env[name][STATS],
|
380
|
+
prop,
|
381
|
+
env[re[1][0][VALUE]][STATS]
|
382
|
+
)
|
300
383
|
env[name][STATS][prop] =
|
301
384
|
env[re[1][0][VALUE]][STATS][RETURNS]
|
302
385
|
if (re[1][0][TYPE] === APPLY) {
|
@@ -320,11 +403,24 @@ export const typeCheck = (ast) => {
|
|
320
403
|
env[re[0][VALUE]][STATS][RETURNS]
|
321
404
|
} else if (env[re[1][VALUE]]) {
|
322
405
|
// ASSIGMENT
|
323
|
-
|
324
|
-
env[
|
325
|
-
|
326
|
-
env[re[1][VALUE]][STATS]
|
327
|
-
|
406
|
+
setProp(
|
407
|
+
env[name][STATS],
|
408
|
+
prop,
|
409
|
+
env[re[1][VALUE]][STATS]
|
410
|
+
)
|
411
|
+
// env[name][STATS][prop] =
|
412
|
+
// env[re[1][VALUE]][STATS][prop]
|
413
|
+
setReturnRef(
|
414
|
+
env[name][STATS],
|
415
|
+
env[re[1][VALUE]][STATS]
|
416
|
+
)
|
417
|
+
}
|
418
|
+
// else {
|
419
|
+
// // setProp(env[name][STATS], prop, {
|
420
|
+
// // [prop]: [UNKNOWN]
|
421
|
+
// // })
|
422
|
+
// // env[name][STATS][prop] = [UNKNOWN]
|
423
|
+
// }
|
328
424
|
}
|
329
425
|
break
|
330
426
|
default:
|
@@ -335,29 +431,38 @@ export const typeCheck = (ast) => {
|
|
335
431
|
returns,
|
336
432
|
warningStack
|
337
433
|
)
|
338
|
-
if (!env[returns[VALUE]])
|
339
|
-
|
434
|
+
if (!env[returns[VALUE]]) {
|
435
|
+
return false
|
436
|
+
// env[name][STATS][RETURNS] = [ANY]
|
437
|
+
}
|
340
438
|
// env[name][STATS][RETURNS] = APPLY
|
341
439
|
else if (
|
342
|
-
env[returns[VALUE]][STATS]
|
440
|
+
getType(env[returns[VALUE]][STATS]) === APPLY
|
343
441
|
) {
|
344
442
|
// ALWAYS APPLY
|
345
443
|
// rest.at(-1)[0][TYPE] === APPLY
|
346
444
|
// Here is upon application to store the result in the variable
|
347
|
-
if (env[name][STATS]
|
445
|
+
if (isUnknownType(env[name][STATS]))
|
348
446
|
stack.unshift(() => {
|
349
|
-
|
350
|
-
env[
|
447
|
+
setTypeToReturn(
|
448
|
+
env[name][STATS],
|
449
|
+
env[returns[VALUE]][STATS]
|
450
|
+
)
|
451
|
+
// env[name][STATS][TYPE_PROP][0] =
|
452
|
+
// env[returns[VALUE]][STATS][RETURNS][0]
|
351
453
|
// this seems to be able to be deleted
|
352
454
|
// env[name][STATS][TYPE_PROP][1] =
|
353
455
|
// env[returns[VALUE]][STATS][RETURNS][1]
|
354
456
|
})
|
355
|
-
|
356
|
-
env[
|
457
|
+
setReturnRef(
|
458
|
+
env[name][STATS],
|
459
|
+
env[returns[VALUE]][STATS]
|
460
|
+
)
|
357
461
|
}
|
358
462
|
break
|
359
463
|
}
|
360
464
|
}
|
465
|
+
return true
|
361
466
|
}
|
362
467
|
const checkReturnType = () => {
|
363
468
|
const last = rest.at(-1).at(-1)
|
@@ -366,7 +471,7 @@ export const typeCheck = (ast) => {
|
|
366
471
|
: last
|
367
472
|
const rem = hasBlock(body) ? body.at(-1) : body
|
368
473
|
const returns = isLeaf(rem) ? rem : rem[0]
|
369
|
-
resolveRetunType(returns, rem, RETURNS)
|
474
|
+
return resolveRetunType(returns, rem, RETURNS)
|
370
475
|
}
|
371
476
|
const rightHand = rest.at(-1)
|
372
477
|
if (
|
@@ -382,17 +487,16 @@ export const typeCheck = (ast) => {
|
|
382
487
|
[SIGNATURE]: name,
|
383
488
|
retried: 0,
|
384
489
|
counter: 0,
|
385
|
-
[VARIABLE_ORDER_INDEX]: env[ORDER],
|
490
|
+
// [VARIABLE_ORDER_INDEX]: env[ORDER],
|
386
491
|
[ARG_COUNT]: n - 2,
|
387
492
|
[ARGUMENTS]: fillUknownArgs(n - 2),
|
388
493
|
[RETURNS]: [UNKNOWN]
|
389
494
|
}
|
390
495
|
}
|
391
|
-
|
392
|
-
checkReturnType()
|
393
496
|
if (
|
394
|
-
|
395
|
-
env[name][STATS]
|
497
|
+
!checkReturnType() ||
|
498
|
+
(isUnknownReturn(env[name][STATS]) &&
|
499
|
+
env[name][STATS].retried < MAX_RETRY_DEFINITION)
|
396
500
|
) {
|
397
501
|
env[name][STATS].retried += 1
|
398
502
|
stack.unshift(() => {
|
@@ -424,7 +528,7 @@ export const typeCheck = (ast) => {
|
|
424
528
|
[SIGNATURE]: name,
|
425
529
|
retried: 0,
|
426
530
|
counter: 0,
|
427
|
-
[VARIABLE_ORDER_INDEX]: env[ORDER],
|
531
|
+
// [VARIABLE_ORDER_INDEX]: env[ORDER],
|
428
532
|
[TYPE_PROP]: [ATOM],
|
429
533
|
[RETURNS]: [ATOM]
|
430
534
|
}
|
@@ -437,7 +541,7 @@ export const typeCheck = (ast) => {
|
|
437
541
|
retried: 0,
|
438
542
|
counter: 0,
|
439
543
|
[SIGNATURE]: name,
|
440
|
-
[VARIABLE_ORDER_INDEX]: env[ORDER],
|
544
|
+
// [VARIABLE_ORDER_INDEX]: env[ORDER],
|
441
545
|
[TYPE_PROP]: [
|
442
546
|
isL
|
443
547
|
? right[TYPE]
|
@@ -466,7 +570,7 @@ export const typeCheck = (ast) => {
|
|
466
570
|
}
|
467
571
|
Types.set(withScope(name, env), () => formatType(name, env))
|
468
572
|
}
|
469
|
-
root[ORDER]++
|
573
|
+
// root[ORDER]++
|
470
574
|
}
|
471
575
|
break
|
472
576
|
case KEYWORDS.ANONYMOUS_FUNCTION:
|
@@ -521,13 +625,17 @@ export const typeCheck = (ast) => {
|
|
521
625
|
// this here is a variable WORD
|
522
626
|
// so return type of that function is that varible type
|
523
627
|
if (copy[returns[VALUE]])
|
524
|
-
|
525
|
-
|
628
|
+
setReturnToTypeRef(
|
629
|
+
ref[STATS],
|
630
|
+
copy[returns[VALUE]][STATS]
|
631
|
+
)
|
526
632
|
else
|
527
633
|
stack.push(() => {
|
528
634
|
if (copy[returns[VALUE]])
|
529
|
-
|
530
|
-
|
635
|
+
setReturnToTypeRef(
|
636
|
+
ref[STATS],
|
637
|
+
copy[returns[VALUE]][STATS]
|
638
|
+
)
|
531
639
|
})
|
532
640
|
} else {
|
533
641
|
const ret = returns[0]
|
@@ -551,37 +659,35 @@ export const typeCheck = (ast) => {
|
|
551
659
|
// WHY not consiter making return types for everything
|
552
660
|
if (
|
553
661
|
concequent &&
|
554
|
-
concequent[STATS]
|
662
|
+
getType(concequent[STATS]) !== UNKNOWN
|
555
663
|
) {
|
556
|
-
if (concequent[STATS]
|
557
|
-
ref[STATS]
|
664
|
+
if (getType(concequent[STATS]) === APPLY)
|
665
|
+
setReturnRef(ref[STATS], concequent[STATS])
|
558
666
|
else
|
559
667
|
ref[STATS][RETURNS] = concequent[STATS][TYPE_PROP]
|
560
668
|
} else if (
|
561
669
|
alternative &&
|
562
|
-
alternative[STATS]
|
670
|
+
isUnknownType(alternative[STATS])
|
563
671
|
) {
|
564
|
-
if (alternative[STATS]
|
565
|
-
ref[STATS]
|
672
|
+
if (getType(alternative[STATS]) === APPLY)
|
673
|
+
setReturnRef(ref[STATS], alternative[STATS])
|
566
674
|
else
|
567
|
-
ref[STATS][
|
568
|
-
alternative[STATS][TYPE_PROP]
|
675
|
+
setReturnToTypeRef(ref[STATS], alternative[STATS])
|
569
676
|
} else if (concequent) {
|
570
|
-
if (concequent[STATS]
|
571
|
-
ref[STATS]
|
677
|
+
if (getType(concequent[STATS]) === APPLY)
|
678
|
+
setReturnRef(ref[STATS], concequent[STATS])
|
572
679
|
else
|
573
|
-
ref[STATS]
|
680
|
+
setReturnToTypeRef(ref[STATS], concequent[STATS])
|
574
681
|
}
|
575
682
|
}
|
576
683
|
break
|
577
684
|
default:
|
578
685
|
if (copy[ret[VALUE]])
|
579
|
-
ref[STATS]
|
686
|
+
setReturnRef(ref[STATS], copy[ret[VALUE]][STATS])
|
580
687
|
else
|
581
688
|
stack.push(() => {
|
582
689
|
if (copy[ret[VALUE]])
|
583
|
-
ref[STATS][
|
584
|
-
copy[ret[VALUE]][STATS][RETURNS]
|
690
|
+
setReturnRef(ref[STATS], copy[ret[VALUE]][STATS])
|
585
691
|
})
|
586
692
|
|
587
693
|
break
|
@@ -594,565 +700,585 @@ export const typeCheck = (ast) => {
|
|
594
700
|
}
|
595
701
|
break
|
596
702
|
default:
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
703
|
+
if (!STATIC_TYPES_SET.has(first[VALUE]))
|
704
|
+
stack.push(() => {
|
705
|
+
if (env[first[VALUE]] === undefined)
|
706
|
+
errorStack.add(
|
707
|
+
`Trying to call undefined (lambda) ${first[VALUE]} (check #9)`
|
708
|
+
)
|
709
|
+
else if (
|
710
|
+
env[first[VALUE]][STATS][TYPE_PROP][0] === APPLY &&
|
711
|
+
env[first[VALUE]][STATS][ARG_COUNT] !== VARIADIC &&
|
712
|
+
env[first[VALUE]][STATS][ARG_COUNT] !== rest.length
|
713
|
+
) {
|
714
|
+
errorStack.add(
|
715
|
+
`Incorrect number of arguments for (${
|
716
|
+
first[VALUE]
|
717
|
+
}). Expected (= ${
|
718
|
+
env[first[VALUE]][STATS][ARG_COUNT]
|
719
|
+
}) but got ${rest.length} (${stringifyArgs(
|
720
|
+
exp
|
721
|
+
)}) (check #15)`
|
722
|
+
)
|
723
|
+
} else {
|
724
|
+
if (first[TYPE] === APPLY && !isSpecial) {
|
725
|
+
if (getType(env[first[VALUE]][STATS]) === ATOM) {
|
726
|
+
errorStack.add(
|
727
|
+
`(${first[VALUE]}) is not a (lambda) (${stringifyArgs(
|
728
|
+
exp
|
729
|
+
)}) (check #12)`
|
730
|
+
)
|
731
|
+
} else if (!env[first[VALUE]][STATS][ARG_COUNT]) {
|
732
|
+
// TODO recursively take return type of applicaion
|
733
|
+
// if (env[first[VALUE]][STATS][RETURNS][0] === APPLY) {
|
734
|
+
// env[first[VALUE]][STATS][RETURNS] = [UNKNOWN]
|
735
|
+
// }
|
736
|
+
// FN ASSIGMENT
|
628
737
|
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
738
|
+
// ASSIGMENT of paramaters of lambda that are a lambda
|
739
|
+
// minus one to remove the body
|
740
|
+
env[first[VALUE]][STATS][TYPE_PROP] = [APPLY]
|
741
|
+
env[first[VALUE]][STATS][ARG_COUNT] = rest.length
|
742
|
+
env[first[VALUE]][STATS][ARGUMENTS] = fillUknownArgs(
|
743
|
+
rest.length
|
744
|
+
)
|
745
|
+
for (let i = 0; i < rest.length; ++i) {
|
746
|
+
const arg = env[first[VALUE]][STATS][ARGUMENTS]
|
747
|
+
arg[i] = {
|
748
|
+
[STATS]: {
|
749
|
+
retried: 0,
|
750
|
+
[SIGNATURE]: PLACEHOLDER,
|
751
|
+
[TYPE_PROP]: [UNKNOWN],
|
752
|
+
[RETURNS]: [UNKNOWN],
|
753
|
+
[ARGUMENTS]: [],
|
754
|
+
[ARG_COUNT]: 0
|
755
|
+
}
|
756
|
+
}
|
757
|
+
const ARG = isLeaf(rest[i]) ? rest[i] : rest[i][0]
|
758
|
+
if (!env[ARG[VALUE]]) continue
|
759
|
+
// console.log(stringifyArgs(exp), ARG)
|
760
|
+
switch (ARG[TYPE]) {
|
761
|
+
// THERE ARE NO ATOM ARGUMENTS
|
762
|
+
// case ATOM:
|
763
|
+
// break
|
764
|
+
case APPLY:
|
765
|
+
// passing arg asA APPLICATION
|
766
|
+
if (isUnknownType(arg[i][STATS]))
|
767
|
+
arg[i][STATS][TYPE_PROP] =
|
768
|
+
env[ARG[VALUE]][STATS][RETURNS]
|
769
|
+
break
|
770
|
+
case WORD:
|
771
|
+
// if param is a word we assosiate them by referanc
|
772
|
+
if (isUnknownType(arg[i][STATS]))
|
773
|
+
arg[i][STATS] = env[ARG[VALUE]][STATS]
|
774
|
+
break
|
646
775
|
}
|
647
|
-
}
|
648
|
-
const ARG = isLeaf(rest[i]) ? rest[i] : rest[i][0]
|
649
|
-
if (!env[ARG[VALUE]]) continue
|
650
|
-
// console.log(stringifyArgs(exp), ARG)
|
651
|
-
switch (ARG[TYPE]) {
|
652
|
-
// THERE ARE NO ATOM ARGUMENTS
|
653
|
-
// case ATOM:
|
654
|
-
// break
|
655
|
-
case APPLY:
|
656
|
-
// passing arg asA APPLICATION
|
657
|
-
if (arg[i][STATS][TYPE_PROP][0] === UNKNOWN)
|
658
|
-
arg[i][STATS][TYPE_PROP] =
|
659
|
-
env[ARG[VALUE]][STATS][RETURNS]
|
660
|
-
break
|
661
|
-
case WORD:
|
662
|
-
// if param is a word we assosiate them by referanc
|
663
|
-
if (arg[i][STATS][TYPE_PROP][0] === UNKNOWN)
|
664
|
-
arg[i][STATS] = env[ARG[VALUE]][STATS]
|
665
|
-
break
|
666
776
|
}
|
667
777
|
}
|
668
778
|
}
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
if (first[TYPE] === APPLY && isSpecial) {
|
680
|
-
if (
|
681
|
-
MAIN_TYPE === ATOM &&
|
682
|
-
PREDICATES_INPUT_SET.has(first[VALUE])
|
683
|
-
) {
|
779
|
+
// also type of arg
|
780
|
+
const args = env[first[VALUE]][STATS][ARGUMENTS] ?? []
|
781
|
+
for (let i = 0; i < args.length; ++i) {
|
782
|
+
const isRestILeaf = isLeaf(rest[i])
|
783
|
+
// type check
|
784
|
+
// TODO get rof pred type
|
785
|
+
// const PRED_TYPE = args[i][STATS][TYPE_PROP][1]
|
786
|
+
const MAIN_TYPE = getType(args[i][STATS])
|
787
|
+
if (MAIN_TYPE === ANY) continue
|
788
|
+
if (first[TYPE] === APPLY && isSpecial) {
|
684
789
|
if (
|
685
|
-
|
686
|
-
|
687
|
-
rest[i][0][VALUE] === KEYWORDS.CALL_FUNCTION
|
790
|
+
MAIN_TYPE === ATOM &&
|
791
|
+
PREDICATES_INPUT_SET.has(first[VALUE])
|
688
792
|
) {
|
689
|
-
if (
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
)}) but got an (${toTypeNames(
|
699
|
-
fn[STATS][RETURNS][0]
|
700
|
-
)}) (${stringifyArgs(exp)}) (check #26)`
|
701
|
-
)
|
702
|
-
}
|
703
|
-
} else {
|
704
|
-
const body = rest[i].at(-1).at(-1)
|
705
|
-
const rem = hasBlock(body) ? body.at(-1) : body
|
706
|
-
const returns = isLeaf(rem) ? rem : rem[0]
|
707
|
-
if (returns[TYPE] === ATOM) {
|
708
|
-
if (MAIN_TYPE !== ATOM) {
|
793
|
+
if (
|
794
|
+
!isRestILeaf &&
|
795
|
+
rest[i][0][TYPE] === APPLY &&
|
796
|
+
rest[i][0][VALUE] === KEYWORDS.CALL_FUNCTION
|
797
|
+
) {
|
798
|
+
if (isLeaf(rest[i].at(-1))) {
|
799
|
+
const fnName = rest[i].at(-1)[VALUE]
|
800
|
+
const fn = env[fnName]
|
801
|
+
if (fn && getReturn(fn[STATS]) !== ATOM) {
|
709
802
|
errorStack.add(
|
710
|
-
`Incorrect type of argument ${i} for (${
|
803
|
+
`Incorrect type of argument (${i}) for (${
|
711
804
|
first[VALUE]
|
712
805
|
}). Expected (${toTypeNames(
|
713
|
-
MAIN_TYPE
|
714
|
-
)}) but got an (${toTypeNames(
|
715
806
|
ATOM
|
716
|
-
)})
|
807
|
+
)}) but got an (${toTypeNames(
|
808
|
+
getReturn(fn[STATS])
|
809
|
+
)}) (${stringifyArgs(exp)}) (check #26)`
|
717
810
|
)
|
718
811
|
}
|
719
|
-
} else
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
first[VALUE]
|
726
|
-
}). Expected (${toTypeNames(
|
727
|
-
ATOM
|
728
|
-
)}) but got (${toTypeNames(
|
729
|
-
env[returns[VALUE]][STATS][TYPE_PROP]
|
730
|
-
)}) (${stringifyArgs(exp)}) (check #29)`
|
731
|
-
)
|
732
|
-
}
|
733
|
-
}
|
734
|
-
}
|
735
|
-
}
|
736
|
-
const isCast = STATIC_TYPES_SET.has(first[VALUE])
|
737
|
-
const expectedArgs = env[first[VALUE]][STATS][ARGUMENTS]
|
738
|
-
const EXPECTED_TYPE = expectedArgs[i][STATS][TYPE_PROP][0]
|
739
|
-
// IF UKNOWN andnot csted -we have nothing much to do
|
740
|
-
if (EXPECTED_TYPE === UNKNOWN && !isCast) continue
|
741
|
-
if (!isRestILeaf) {
|
742
|
-
const CAR = rest[i][0][VALUE]
|
743
|
-
const isKnown =
|
744
|
-
env[CAR] && env[CAR][STATS][RETURNS][0] !== UNKNOWN
|
745
|
-
if (isKnown && !isCast) {
|
746
|
-
if (env[CAR][STATS][RETURNS][0] !== EXPECTED_TYPE) {
|
747
|
-
errorStack.add(
|
748
|
-
`Incorrect type of argument (${i}) for special form (${
|
749
|
-
first[VALUE]
|
750
|
-
}). Expected (${toTypeNames(
|
751
|
-
EXPECTED_TYPE
|
752
|
-
)}) but got (${toTypeNames(
|
753
|
-
env[CAR][STATS][RETURNS][0]
|
754
|
-
)}) (${stringifyArgs(exp)}) (check #1)`
|
755
|
-
)
|
756
|
-
}
|
757
|
-
// never reached because there is only 1 subtype at the moment
|
758
|
-
// else if (
|
759
|
-
// PRED_TYPE &&
|
760
|
-
// env[CAR][STATS][RETURNS][1] !== PRED_TYPE
|
761
|
-
// ) {
|
762
|
-
// }
|
763
|
-
} else if (!isKnown && !isCast && env[CAR]) {
|
764
|
-
if (
|
765
|
-
env[CAR][STATS][TYPE_PROP][0] === APPLY &&
|
766
|
-
env[CAR][STATS][RETURNS][0] !== UNKNOWN
|
767
|
-
) {
|
768
|
-
switch (first[VALUE]) {
|
769
|
-
case KEYWORDS.IF:
|
770
|
-
break
|
771
|
-
case KEYWORDS.CALL_FUNCTION:
|
772
|
-
break
|
773
|
-
default:
|
774
|
-
// console.log(stringifyArgs(exp))
|
775
|
-
// TODO fix this assigment
|
776
|
-
// It turns out it's not possible to determine return type of function here
|
777
|
-
// what if it's a global function used elsewhere where the return type mwould be different/
|
778
|
-
// env[CAR][STATS][RETURNS][0] =
|
779
|
-
// root[first[VALUE]][STATS][RETURNS][0]
|
780
|
-
break
|
781
|
-
}
|
782
|
-
}
|
783
|
-
|
784
|
-
// TODO also handle casting
|
785
|
-
}
|
786
|
-
} else {
|
787
|
-
switch (rest[i][TYPE]) {
|
788
|
-
case WORD:
|
789
|
-
{
|
790
|
-
const CAR = rest[i][VALUE]
|
791
|
-
const isKnown =
|
792
|
-
env[CAR] &&
|
793
|
-
env[CAR][STATS][TYPE_PROP][0] !== UNKNOWN
|
794
|
-
if (isKnown && !isCast) {
|
795
|
-
if (
|
796
|
-
EXPECTED_TYPE !== env[CAR][STATS][TYPE_PROP][0]
|
797
|
-
) {
|
812
|
+
} else {
|
813
|
+
const body = rest[i].at(-1).at(-1)
|
814
|
+
const rem = hasBlock(body) ? body.at(-1) : body
|
815
|
+
const returns = isLeaf(rem) ? rem : rem[0]
|
816
|
+
if (returns[TYPE] === ATOM) {
|
817
|
+
if (MAIN_TYPE !== ATOM) {
|
798
818
|
errorStack.add(
|
799
|
-
`Incorrect type of argument
|
819
|
+
`Incorrect type of argument ${i} for (${
|
800
820
|
first[VALUE]
|
801
821
|
}). Expected (${toTypeNames(
|
802
|
-
|
803
|
-
)}) but got (${toTypeNames(
|
804
|
-
|
805
|
-
)})
|
822
|
+
MAIN_TYPE
|
823
|
+
)}) but got an (${toTypeNames(
|
824
|
+
ATOM
|
825
|
+
)}) (${stringifyArgs(exp)}) (check #27)`
|
806
826
|
)
|
807
827
|
}
|
808
|
-
} else if (
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
828
|
+
} else if (
|
829
|
+
env[returns[VALUE]] &&
|
830
|
+
!isUnknownReturn(env[returns[VALUE]][STATS]) &&
|
831
|
+
getReturn(env[returns[VALUE]][STATS]) !== ATOM
|
832
|
+
) {
|
833
|
+
errorStack.add(
|
834
|
+
`Incorrect type of argument ${i} for (${
|
835
|
+
first[VALUE]
|
836
|
+
}). Expected (${toTypeNames(
|
837
|
+
ATOM
|
838
|
+
)}) but got (${toTypeNames(
|
839
|
+
getReturn(env[returns[VALUE]][STATS])
|
840
|
+
)}) (${stringifyArgs(exp)}) (check #29)`
|
841
|
+
)
|
820
842
|
}
|
821
843
|
}
|
822
|
-
|
823
|
-
|
824
|
-
|
844
|
+
}
|
845
|
+
}
|
846
|
+
const isCast = STATIC_TYPES_SET.has(first[VALUE])
|
847
|
+
const expectedArgs = env[first[VALUE]][STATS][ARGUMENTS]
|
848
|
+
// IF UKNOWN andnot csted -we have nothing much to do
|
849
|
+
if (isUnknownType(expectedArgs[i][STATS]) && !isCast)
|
850
|
+
continue
|
851
|
+
if (!isRestILeaf) {
|
852
|
+
const CAR = rest[i][0][VALUE]
|
853
|
+
if (!env[CAR]) continue
|
854
|
+
const isKnown = !isUnknownReturn(env[CAR][STATS])
|
855
|
+
if (isKnown && !isCast) {
|
856
|
+
if (
|
857
|
+
!compareTypeWithReturn(
|
858
|
+
expectedArgs[i][STATS],
|
859
|
+
env[CAR][STATS]
|
860
|
+
)
|
861
|
+
) {
|
825
862
|
errorStack.add(
|
826
863
|
`Incorrect type of argument (${i}) for special form (${
|
827
864
|
first[VALUE]
|
828
865
|
}). Expected (${toTypeNames(
|
829
|
-
|
866
|
+
getType(expectedArgs[i][STATS])
|
830
867
|
)}) but got (${toTypeNames(
|
831
|
-
|
832
|
-
)}) (${stringifyArgs(exp)}) (check #
|
868
|
+
getReturn(env[CAR][STATS])
|
869
|
+
)}) (${stringifyArgs(exp)}) (check #1)`
|
833
870
|
)
|
834
871
|
}
|
835
|
-
|
872
|
+
// never reached because there is only 1 subtype at the moment
|
873
|
+
// else if (
|
874
|
+
// PRED_TYPE &&
|
875
|
+
// env[CAR][STATS][RETURNS][1] !== PRED_TYPE
|
876
|
+
// ) {
|
877
|
+
// }
|
878
|
+
} else if (!isKnown && !isCast) {
|
879
|
+
if (env[CAR] && getType(env[CAR][STATS]) === APPLY) {
|
880
|
+
switch (first[VALUE]) {
|
881
|
+
case KEYWORDS.IF:
|
882
|
+
break
|
883
|
+
case KEYWORDS.CALL_FUNCTION:
|
884
|
+
break
|
885
|
+
default:
|
886
|
+
// console.log(stringifyArgs(exp))
|
887
|
+
// TODO fix this assigment
|
888
|
+
// It turns out it's not possible to determine return type of function here
|
889
|
+
// what if it's a global function used elsewhere where the return type mwould be different
|
890
|
+
// THIS willgive lambda return types but refactor is needed still
|
891
|
+
setReturn(
|
892
|
+
env[CAR][STATS],
|
893
|
+
expectedArgs[i][STATS]
|
894
|
+
)
|
895
|
+
break
|
896
|
+
}
|
897
|
+
}
|
898
|
+
|
899
|
+
// TODO also handle casting
|
900
|
+
}
|
901
|
+
} else {
|
902
|
+
switch (rest[i][TYPE]) {
|
903
|
+
case WORD:
|
904
|
+
{
|
905
|
+
const CAR = rest[i][VALUE]
|
906
|
+
if (!env[CAR]) continue
|
907
|
+
const isKnown = !isUnknownType(env[CAR][STATS])
|
908
|
+
if (isKnown && !isCast) {
|
909
|
+
if (
|
910
|
+
!compareTypes(
|
911
|
+
expectedArgs[i][STATS],
|
912
|
+
env[CAR][STATS]
|
913
|
+
)
|
914
|
+
) {
|
915
|
+
errorStack.add(
|
916
|
+
`Incorrect type of argument (${i}) for special form (${
|
917
|
+
first[VALUE]
|
918
|
+
}). Expected (${toTypeNames(
|
919
|
+
getType(expectedArgs[i][STATS])
|
920
|
+
)}) but got (${toTypeNames(
|
921
|
+
getType(env[CAR][STATS])
|
922
|
+
)}) (${stringifyArgs(exp)}) (check #3)`
|
923
|
+
)
|
924
|
+
}
|
925
|
+
} else if (env[CAR]) {
|
926
|
+
if (isCast) {
|
927
|
+
// CAST assigment
|
928
|
+
setTypeToReturn(
|
929
|
+
env[rest[i][VALUE]][STATS],
|
930
|
+
root[first[VALUE]][STATS]
|
931
|
+
)
|
932
|
+
// root[first[VALUE]][STATS][RETURNS] =
|
933
|
+
// root[first[VALUE]][STATS][RETURNS]
|
934
|
+
} else {
|
935
|
+
// VALUE assigment
|
936
|
+
setType(
|
937
|
+
env[CAR][STATS],
|
938
|
+
expectedArgs[i][STATS]
|
939
|
+
)
|
940
|
+
// env[CAR][STATS][TYPE_PROP][0] =
|
941
|
+
// expectedArgs[i][STATS][TYPE_PROP][0]
|
942
|
+
}
|
943
|
+
}
|
944
|
+
}
|
945
|
+
break
|
946
|
+
case ATOM: {
|
947
|
+
if (
|
948
|
+
rest[i][TYPE] !==
|
949
|
+
expectedArgs[i][STATS][TYPE_PROP][0]
|
950
|
+
) {
|
951
|
+
errorStack.add(
|
952
|
+
`Incorrect type of argument (${i}) for special form (${
|
953
|
+
first[VALUE]
|
954
|
+
}). Expected (${toTypeNames(
|
955
|
+
expectedArgs[i][STATS][TYPE_PROP][0]
|
956
|
+
)}) but got (${toTypeNames(
|
957
|
+
rest[i][TYPE]
|
958
|
+
)}) (${stringifyArgs(exp)}) (check #2)`
|
959
|
+
)
|
960
|
+
}
|
961
|
+
break
|
962
|
+
}
|
836
963
|
}
|
837
964
|
}
|
838
965
|
}
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
T === ATOM &&
|
848
|
-
args[i][STATS][TYPE_PROP][0] !== UNKNOWN &&
|
849
|
-
args[i][STATS][TYPE_PROP][0] !== ATOM
|
850
|
-
) {
|
851
|
-
errorStack.add(
|
852
|
-
`Incorrect type of arguments ${i} for (${
|
853
|
-
first[VALUE]
|
854
|
-
}). Expected (${toTypeNames(
|
855
|
-
args[i][STATS][TYPE_PROP][0]
|
856
|
-
)}) but got (${toTypeNames(T)}) (${stringifyArgs(
|
857
|
-
exp
|
858
|
-
)}) (check #10)`
|
859
|
-
)
|
860
|
-
} else if (
|
861
|
-
T === APPLY &&
|
862
|
-
args[i][STATS][TYPE_PROP][0] !== UNKNOWN &&
|
863
|
-
env[rest[i][VALUE]][STATS][TYPE_PROP][0] !== UNKNOWN &&
|
864
|
-
env[rest[i][VALUE]][STATS][ARG_COUNT] !== VARIADIC
|
865
|
-
) {
|
866
|
-
// Handles words that are Lambdas
|
966
|
+
// type checking
|
967
|
+
else if (isRestILeaf) {
|
968
|
+
const T =
|
969
|
+
rest[i][TYPE] === WORD
|
970
|
+
? env[rest[i][VALUE]]
|
971
|
+
? getType(env[rest[i][VALUE]][STATS])
|
972
|
+
: UNKNOWN
|
973
|
+
: rest[i][TYPE]
|
867
974
|
if (
|
868
|
-
|
869
|
-
args[i][STATS]
|
975
|
+
T === ATOM &&
|
976
|
+
!isUnknownType(args[i][STATS]) &&
|
977
|
+
getType(args[i][STATS]) !== ATOM
|
870
978
|
) {
|
871
979
|
errorStack.add(
|
872
|
-
`Incorrect
|
873
|
-
args[i][STATS][SIGNATURE]
|
874
|
-
}) the (lambda) argument of (${
|
980
|
+
`Incorrect type of arguments ${i} for (${
|
875
981
|
first[VALUE]
|
876
|
-
})
|
877
|
-
args[i][STATS]
|
878
|
-
}) but got ${
|
879
|
-
|
880
|
-
|
982
|
+
}). Expected (${toTypeNames(
|
983
|
+
getType(args[i][STATS])
|
984
|
+
)}) but got (${toTypeNames(T)}) (${stringifyArgs(
|
985
|
+
exp
|
986
|
+
)}) (check #10)`
|
881
987
|
)
|
882
|
-
} else
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
//
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
// expected[STATS][RETURNS][0] !==
|
893
|
-
// actual[STATS][RETURNS][0]
|
894
|
-
// ) {
|
895
|
-
// errorStack.add(
|
896
|
-
// `Incorrect return type for (${
|
897
|
-
// expected[STATS][SIGNATURE]
|
898
|
-
// }) the (lambda) argument of (${
|
899
|
-
// first[VALUE]
|
900
|
-
// }) at position (${i}). Expected (${toTypeNames(
|
901
|
-
// expected[STATS][RETURNS][0]
|
902
|
-
// )}) but got (${toTypeNames(
|
903
|
-
// actual[STATS][RETURNS][0]
|
904
|
-
// )}) (${stringifyArgs(exp)}) (check #782)`
|
905
|
-
// )
|
906
|
-
// } else if (
|
907
|
-
// actual[STATS].retried < MAX_RETRY_DEFINITION
|
908
|
-
// ) {
|
909
|
-
// actual[STATS].retried += 1
|
910
|
-
// stack.unshift(() => match1())
|
911
|
-
// }
|
912
|
-
// }
|
913
|
-
// match1()
|
914
|
-
for (
|
915
|
-
let j = 0;
|
916
|
-
j < args[i][STATS][ARGUMENTS].length;
|
917
|
-
++j
|
988
|
+
} else if (
|
989
|
+
T === APPLY &&
|
990
|
+
!isUnknownType(args[i][STATS]) &&
|
991
|
+
!isUnknownType(env[rest[i][VALUE]][STATS]) &&
|
992
|
+
env[rest[i][VALUE]][STATS][ARG_COUNT] !== VARIADIC
|
993
|
+
) {
|
994
|
+
// Handles words that are Lambdas
|
995
|
+
if (
|
996
|
+
env[rest[i][VALUE]][STATS][ARG_COUNT] !==
|
997
|
+
args[i][STATS][ARG_COUNT]
|
918
998
|
) {
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
999
|
+
errorStack.add(
|
1000
|
+
`Incorrect number of arguments for (${
|
1001
|
+
args[i][STATS][SIGNATURE]
|
1002
|
+
}) the (lambda) argument of (${
|
1003
|
+
first[VALUE]
|
1004
|
+
}) at position (${i}). Expected (= ${
|
1005
|
+
args[i][STATS][ARG_COUNT]
|
1006
|
+
}) but got ${
|
1007
|
+
env[rest[i][VALUE]][STATS][ARG_COUNT]
|
1008
|
+
} (${stringifyArgs(exp)}) (check #778)`
|
1009
|
+
)
|
1010
|
+
} else {
|
1011
|
+
// DEFINED LAMBDAS TYPE CHECKING
|
1012
|
+
// #C1
|
1013
|
+
// TODO delete this maybe
|
1014
|
+
// It will not be possilbe to know return type
|
1015
|
+
const match1 = () => {
|
1016
|
+
const actual = env[rest[i][VALUE]]
|
1017
|
+
const expected = args[i]
|
923
1018
|
if (
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
)
|
1019
|
+
!isUnknownReturn(expected[STATS]) &&
|
1020
|
+
!isUnknownReturn(actual[STATS]) &&
|
1021
|
+
!compareReturns(expected[STATS], actual[STATS])
|
1022
|
+
) {
|
929
1023
|
errorStack.add(
|
930
|
-
`Incorrect type for (
|
931
|
-
|
932
|
-
})
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
}). Expected (${toTypeNames(
|
937
|
-
args[i][STATS][ARGUMENTS][j][STATS][
|
938
|
-
TYPE_PROP
|
939
|
-
][0]
|
1024
|
+
`Incorrect return type for (${
|
1025
|
+
expected[STATS][SIGNATURE]
|
1026
|
+
}) the (lambda) argument of (${
|
1027
|
+
first[VALUE]
|
1028
|
+
}) at position (${i}). Expected (${toTypeNames(
|
1029
|
+
getReturn(expected[STATS])
|
940
1030
|
)}) but got (${toTypeNames(
|
941
|
-
|
942
|
-
|
943
|
-
][TYPE_PROP][0]
|
944
|
-
)}) (${stringifyArgs(exp)}) (check #781)`
|
1031
|
+
getReturn(actual[STATS])
|
1032
|
+
)}) (${stringifyArgs(exp)}) (check #782)`
|
945
1033
|
)
|
946
|
-
else if (
|
1034
|
+
} else if (
|
947
1035
|
actual[STATS].retried < MAX_RETRY_DEFINITION
|
948
1036
|
) {
|
949
1037
|
actual[STATS].retried += 1
|
950
|
-
stack.unshift(() =>
|
1038
|
+
stack.unshift(() => match1())
|
951
1039
|
}
|
952
1040
|
}
|
953
|
-
|
1041
|
+
match1()
|
1042
|
+
for (
|
1043
|
+
let j = 0;
|
1044
|
+
j < args[i][STATS][ARGUMENTS].length;
|
1045
|
+
++j
|
1046
|
+
) {
|
1047
|
+
const match2 = () => {
|
1048
|
+
const actual =
|
1049
|
+
env[rest[i][VALUE]][STATS][ARGUMENTS][j]
|
1050
|
+
const expected = args[i][STATS][ARGUMENTS][j]
|
1051
|
+
if (
|
1052
|
+
!isUnknownType(actual[STATS]) &&
|
1053
|
+
!isUnknownType(expected[STATS]) &&
|
1054
|
+
!compareTypes(actual[STATS], expected[STATS])
|
1055
|
+
)
|
1056
|
+
errorStack.add(
|
1057
|
+
`Incorrect type for (lambda) (${
|
1058
|
+
args[i][STATS][SIGNATURE]
|
1059
|
+
}) argument at position (${j}) named as (${
|
1060
|
+
actual[STATS][SIGNATURE]
|
1061
|
+
}). Expected (${toTypeNames(
|
1062
|
+
getType(expected[STATS])
|
1063
|
+
)}) but got (${toTypeNames(
|
1064
|
+
getType(actual[STATS])
|
1065
|
+
)}) (${stringifyArgs(exp)}) (check #781)`
|
1066
|
+
)
|
1067
|
+
else if (
|
1068
|
+
actual[STATS].retried < MAX_RETRY_DEFINITION
|
1069
|
+
) {
|
1070
|
+
actual[STATS].retried += 1
|
1071
|
+
stack.unshift(() => match2())
|
1072
|
+
}
|
1073
|
+
}
|
1074
|
+
match2()
|
1075
|
+
}
|
954
1076
|
}
|
955
1077
|
}
|
956
|
-
}
|
957
|
-
if (
|
958
|
-
T === COLLECTION &&
|
959
|
-
env[rest[i][VALUE]] &&
|
960
|
-
env[rest[i][VALUE]][STATS][TYPE_PROP][0] !== UNKNOWN &&
|
961
|
-
args[i][STATS][TYPE_PROP][0] !== UNKNOWN &&
|
962
|
-
env[rest[i][VALUE]][STATS][TYPE_PROP][0] !==
|
963
|
-
args[i][STATS][TYPE_PROP][0]
|
964
|
-
) {
|
965
|
-
errorStack.add(
|
966
|
-
`Incorrect type of arguments ${i} for (${
|
967
|
-
first[VALUE]
|
968
|
-
}). Expected (${toTypeNames(
|
969
|
-
args[i][STATS][TYPE_PROP][0]
|
970
|
-
)}) but got (${toTypeNames(T)}) (${stringifyArgs(
|
971
|
-
exp
|
972
|
-
)}) (check #30)`
|
973
|
-
)
|
974
|
-
} else if (
|
975
|
-
args[i][STATS][TYPE_PROP][0] === UNKNOWN &&
|
976
|
-
args[i][STATS].retried < MAX_RETRY_DEFINITION
|
977
|
-
) {
|
978
|
-
args[i][STATS].retried += 1
|
979
|
-
stack.unshift(() => check(exp, env, scope))
|
980
|
-
} else {
|
981
1078
|
if (
|
1079
|
+
T === COLLECTION &&
|
982
1080
|
env[rest[i][VALUE]] &&
|
983
|
-
|
984
|
-
|
985
|
-
|
1081
|
+
!isUnknownType(env[rest[i][VALUE]][STATS]) &&
|
1082
|
+
!isUnknownType(args[i][STATS]) &&
|
1083
|
+
!compareTypes(
|
1084
|
+
env[rest[i][VALUE]][STATS],
|
1085
|
+
args[i][STATS]
|
1086
|
+
)
|
986
1087
|
) {
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
|
992
|
-
|
993
|
-
|
994
|
-
|
995
|
-
|
996
|
-
|
997
|
-
|
998
|
-
|
999
|
-
|
1000
|
-
|
1088
|
+
errorStack.add(
|
1089
|
+
`Incorrect type of arguments ${i} for (${
|
1090
|
+
first[VALUE]
|
1091
|
+
}). Expected (${toTypeNames(
|
1092
|
+
getType(args[i][STATS])
|
1093
|
+
)}) but got (${toTypeNames(T)}) (${stringifyArgs(
|
1094
|
+
exp
|
1095
|
+
)}) (check #30)`
|
1096
|
+
)
|
1097
|
+
} else if (
|
1098
|
+
isUnknownType(args[i][STATS]) &&
|
1099
|
+
args[i][STATS].retried < MAX_RETRY_DEFINITION
|
1100
|
+
) {
|
1101
|
+
args[i][STATS].retried += 1
|
1102
|
+
stack.unshift(() => check(exp, env, scope))
|
1103
|
+
} else {
|
1104
|
+
if (
|
1105
|
+
env[rest[i][VALUE]] &&
|
1106
|
+
!isUnknownType(args[i][STATS]) &&
|
1107
|
+
isUnknownType(env[rest[i][VALUE]][STATS]) &&
|
1108
|
+
getType(args[i][STATS]) !== APPLY
|
1109
|
+
) {
|
1110
|
+
// REFF ASSIGMENT
|
1111
|
+
env[rest[i][VALUE]][STATS][TYPE_PROP] =
|
1112
|
+
args[i][STATS][TYPE_PROP]
|
1113
|
+
env[rest[i][VALUE]][STATS][RETURNS] =
|
1114
|
+
args[i][STATS][RETURNS]
|
1115
|
+
}
|
1001
1116
|
}
|
1002
|
-
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
1012
|
-
)
|
1013
|
-
|
1014
|
-
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1029
|
-
|
1030
|
-
|
1031
|
-
|
1032
|
-
|
1033
|
-
|
1034
|
-
)
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
local
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
// }) at position (${i}). Expected (${toTypeNames(
|
1069
|
-
// expected[STATS][RETURNS][0]
|
1070
|
-
// )}) but got (${toTypeNames(
|
1071
|
-
// actual[STATS][RETURNS][0]
|
1072
|
-
// )}) (${stringifyArgs(
|
1073
|
-
// exp
|
1074
|
-
// )}) (check #779)`
|
1075
|
-
// )
|
1076
|
-
// } else if (
|
1077
|
-
// actual[STATS].retried <
|
1078
|
-
// MAX_RETRY_DEFINITION
|
1079
|
-
// ) {
|
1080
|
-
// actual[STATS].retried += 1
|
1081
|
-
// stack.unshift(() => match1())
|
1082
|
-
// }
|
1083
|
-
// }
|
1084
|
-
// match1()
|
1085
|
-
for (
|
1086
|
-
let j = 0;
|
1087
|
-
j < args[i][STATS][ARGUMENTS].length;
|
1088
|
-
++j
|
1089
|
-
) {
|
1090
|
-
const match2 = () => {
|
1091
|
-
const actual =
|
1092
|
-
local[lambdaName][STATS][ARGUMENTS][j]
|
1093
|
-
const expected =
|
1094
|
-
args[i][STATS][ARGUMENTS][j]
|
1117
|
+
} else if (env[rest[i][0][VALUE]]) {
|
1118
|
+
const match = () => {
|
1119
|
+
const actual = env[rest[i][0][VALUE]][STATS]
|
1120
|
+
const expected = args[i][STATS]
|
1121
|
+
if (args[i][STATS].counter < MAX_ARGUMENT_RETRY) {
|
1122
|
+
args[i][STATS].counter++
|
1123
|
+
stack.unshift(() => match())
|
1124
|
+
}
|
1125
|
+
if (
|
1126
|
+
!isUnknownType(expected) &&
|
1127
|
+
!isUnknownReturn(actual)
|
1128
|
+
) {
|
1129
|
+
if (!compareTypeWithReturn(expected, actual)) {
|
1130
|
+
errorStack.add(
|
1131
|
+
`Incorrect type of arguments ${i} for (${
|
1132
|
+
first[VALUE]
|
1133
|
+
}). Expected (${toTypeNames(
|
1134
|
+
getType(expected)
|
1135
|
+
)}) but got (${toTypeNames(
|
1136
|
+
getReturn(actual)
|
1137
|
+
)}) (${stringifyArgs(exp)}) (check #16)`
|
1138
|
+
)
|
1139
|
+
} else {
|
1140
|
+
switch (getType(expected)) {
|
1141
|
+
// almost exclusively for anonymous lambdas
|
1142
|
+
case APPLY:
|
1143
|
+
{
|
1144
|
+
const argsN = rest[i].length - 2
|
1145
|
+
if (
|
1146
|
+
env[rest[i][0][VALUE]][STATS][SIGNATURE] ===
|
1147
|
+
KEYWORDS.ANONYMOUS_FUNCTION
|
1148
|
+
) {
|
1149
|
+
if (argsN !== args[i][STATS][ARG_COUNT]) {
|
1150
|
+
errorStack.add(
|
1151
|
+
`Incorrect number of arguments for (${
|
1152
|
+
args[i][STATS][SIGNATURE]
|
1153
|
+
}) the (lambda) argument of (${
|
1154
|
+
first[VALUE]
|
1155
|
+
}) at position (${i}). Expected (= ${
|
1156
|
+
args[i][STATS][ARG_COUNT]
|
1157
|
+
}) but got ${argsN} (${stringifyArgs(
|
1158
|
+
exp
|
1159
|
+
)}) (check #777)`
|
1160
|
+
)
|
1161
|
+
} else {
|
1162
|
+
// ANONYMOUS LAMBDAS TYPE CHECKING
|
1163
|
+
const local = Object.create(env)
|
1164
|
+
const lambdaName = `lambda::annonymous::${i}::${performance
|
1165
|
+
.now()
|
1166
|
+
.toString()
|
1167
|
+
.replace('.', 0)}*`
|
1168
|
+
check(
|
1169
|
+
[
|
1170
|
+
[APPLY, KEYWORDS.DEFINE_VARIABLE],
|
1171
|
+
[WORD, lambdaName],
|
1172
|
+
rest[i]
|
1173
|
+
],
|
1174
|
+
local,
|
1175
|
+
scope
|
1176
|
+
)
|
1177
|
+
// TODO delete this maybe
|
1178
|
+
// #C2
|
1179
|
+
// It will not be possilbe to know return type
|
1180
|
+
const match1 = () => {
|
1181
|
+
const actual = local[lambdaName]
|
1182
|
+
const expected = args[i]
|
1095
1183
|
if (
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1101
|
-
|
1184
|
+
!isUnknownReturn(expected[STATS]) &&
|
1185
|
+
!isUnknownReturn(actual[STATS]) &&
|
1186
|
+
!compareReturns(
|
1187
|
+
expected[STATS],
|
1188
|
+
actual[STATS]
|
1189
|
+
)
|
1102
1190
|
) {
|
1103
1191
|
errorStack.add(
|
1104
|
-
`Incorrect type for (
|
1105
|
-
|
1106
|
-
})
|
1107
|
-
|
1108
|
-
|
1109
|
-
|
1110
|
-
}). Expected (${toTypeNames(
|
1111
|
-
args[i][STATS][ARGUMENTS][j][
|
1112
|
-
STATS
|
1113
|
-
][TYPE_PROP][0]
|
1192
|
+
`Incorrect return type for (${
|
1193
|
+
expected[STATS][SIGNATURE]
|
1194
|
+
}) the (lambda) argument of (${
|
1195
|
+
first[VALUE]
|
1196
|
+
}) at position (${i}). Expected (${toTypeNames(
|
1197
|
+
getReturn(expected[STATS])
|
1114
1198
|
)}) but got (${toTypeNames(
|
1115
|
-
|
1116
|
-
ARGUMENTS
|
1117
|
-
][j][STATS][TYPE_PROP][0]
|
1199
|
+
getReturn(actual[STATS])
|
1118
1200
|
)}) (${stringifyArgs(
|
1119
1201
|
exp
|
1120
|
-
)}) (check #
|
1202
|
+
)}) (check #779)`
|
1121
1203
|
)
|
1122
1204
|
} else if (
|
1123
1205
|
actual[STATS].retried <
|
1124
1206
|
MAX_RETRY_DEFINITION
|
1125
1207
|
) {
|
1126
1208
|
actual[STATS].retried += 1
|
1127
|
-
stack.unshift(() =>
|
1209
|
+
stack.unshift(() => match1())
|
1210
|
+
}
|
1211
|
+
}
|
1212
|
+
match1()
|
1213
|
+
for (
|
1214
|
+
let j = 0;
|
1215
|
+
j < args[i][STATS][ARGUMENTS].length;
|
1216
|
+
++j
|
1217
|
+
) {
|
1218
|
+
const match2 = () => {
|
1219
|
+
const actual =
|
1220
|
+
local[lambdaName][STATS][ARGUMENTS][
|
1221
|
+
j
|
1222
|
+
]
|
1223
|
+
const expected =
|
1224
|
+
args[i][STATS][ARGUMENTS][j]
|
1225
|
+
if (
|
1226
|
+
!isUnknownType(actual[STATS]) &&
|
1227
|
+
!isUnknownType(expected[STATS]) &&
|
1228
|
+
!compareTypes(
|
1229
|
+
actual[STATS],
|
1230
|
+
expected[STATS]
|
1231
|
+
)
|
1232
|
+
) {
|
1233
|
+
errorStack.add(
|
1234
|
+
`Incorrect type for (lambda) (${
|
1235
|
+
args[i][STATS][SIGNATURE]
|
1236
|
+
}) argument at position (${j}) named as (${
|
1237
|
+
local[lambdaName][STATS][
|
1238
|
+
ARGUMENTS
|
1239
|
+
][j][STATS][SIGNATURE]
|
1240
|
+
}). Expected (${toTypeNames(
|
1241
|
+
getType(expected[STATS])
|
1242
|
+
)}) but got (${toTypeNames(
|
1243
|
+
getType(actual[STATS])
|
1244
|
+
)}) (${stringifyArgs(
|
1245
|
+
exp
|
1246
|
+
)}) (check #780)`
|
1247
|
+
)
|
1248
|
+
} else if (
|
1249
|
+
actual[STATS].retried <
|
1250
|
+
MAX_RETRY_DEFINITION
|
1251
|
+
) {
|
1252
|
+
actual[STATS].retried += 1
|
1253
|
+
stack.unshift(() => match2())
|
1254
|
+
}
|
1128
1255
|
}
|
1256
|
+
match2()
|
1129
1257
|
}
|
1130
|
-
match2()
|
1131
1258
|
}
|
1259
|
+
} else {
|
1260
|
+
// TODO fix curry: lambdas enter here as undefined
|
1132
1261
|
}
|
1133
|
-
} else {
|
1134
|
-
// TODO fix curry: lambdas enter here as undefined
|
1135
1262
|
}
|
1136
|
-
|
1137
|
-
|
1138
|
-
|
1139
|
-
|
1140
|
-
|
1263
|
+
break
|
1264
|
+
// case ATOM:
|
1265
|
+
// case COLLECTION:
|
1266
|
+
// break
|
1267
|
+
}
|
1141
1268
|
}
|
1269
|
+
} else if (
|
1270
|
+
isUnknownType(expected) &&
|
1271
|
+
args[i][STATS].retried < MAX_RETRY_DEFINITION
|
1272
|
+
) {
|
1273
|
+
args[i][STATS].retried += 1
|
1274
|
+
stack.unshift(() => match())
|
1142
1275
|
}
|
1143
|
-
} else if (
|
1144
|
-
expected[0] === UNKNOWN &&
|
1145
|
-
args[i][STATS].retried < MAX_RETRY_DEFINITION
|
1146
|
-
) {
|
1147
|
-
args[i][STATS].retried += 1
|
1148
|
-
stack.unshift(() => match())
|
1149
1276
|
}
|
1277
|
+
match()
|
1150
1278
|
}
|
1151
|
-
match()
|
1152
1279
|
}
|
1153
1280
|
}
|
1154
|
-
}
|
1155
|
-
})
|
1281
|
+
})
|
1156
1282
|
for (let i = 0; i < rest.length; ++i) {
|
1157
1283
|
const r = rest[i]
|
1158
1284
|
if (isLeaf(r) && r[TYPE] !== ATOM) {
|
@@ -1176,8 +1302,10 @@ export const typeCheck = (ast) => {
|
|
1176
1302
|
const copy = JSON.parse(JSON.stringify(ast))
|
1177
1303
|
check(copy, root, copy)
|
1178
1304
|
while (stack.length) stack.pop()()
|
1179
|
-
|
1180
|
-
|
1305
|
+
if (error) {
|
1306
|
+
const issues = [...errorStack, ...warningStack]
|
1307
|
+
if (issues.length) throw new TypeError(issues.join('\n'))
|
1308
|
+
}
|
1181
1309
|
return [ast, Types]
|
1182
1310
|
}
|
1183
1311
|
export const type = (ast) => typeCheck(ast)[0]
|