fez-lisp 1.5.90 → 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 +676 -466
- 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,483 +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
|
-
|
806
|
+
ATOM
|
714
807
|
)}) but got an (${toTypeNames(
|
808
|
+
getReturn(fn[STATS])
|
809
|
+
)}) (${stringifyArgs(exp)}) (check #26)`
|
810
|
+
)
|
811
|
+
}
|
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) {
|
818
|
+
errorStack.add(
|
819
|
+
`Incorrect type of argument ${i} for (${
|
820
|
+
first[VALUE]
|
821
|
+
}). Expected (${toTypeNames(
|
822
|
+
MAIN_TYPE
|
823
|
+
)}) but got an (${toTypeNames(
|
824
|
+
ATOM
|
825
|
+
)}) (${stringifyArgs(exp)}) (check #27)`
|
826
|
+
)
|
827
|
+
}
|
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(
|
715
837
|
ATOM
|
716
|
-
)})
|
838
|
+
)}) but got (${toTypeNames(
|
839
|
+
getReturn(env[returns[VALUE]][STATS])
|
840
|
+
)}) (${stringifyArgs(exp)}) (check #29)`
|
717
841
|
)
|
718
842
|
}
|
719
|
-
}
|
720
|
-
|
721
|
-
|
843
|
+
}
|
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
|
+
)
|
722
861
|
) {
|
723
862
|
errorStack.add(
|
724
|
-
`Incorrect type of argument ${i} for (${
|
863
|
+
`Incorrect type of argument (${i}) for special form (${
|
725
864
|
first[VALUE]
|
726
865
|
}). Expected (${toTypeNames(
|
727
|
-
|
866
|
+
getType(expectedArgs[i][STATS])
|
728
867
|
)}) but got (${toTypeNames(
|
729
|
-
env[
|
730
|
-
)})
|
868
|
+
getReturn(env[CAR][STATS])
|
869
|
+
)}) (${stringifyArgs(exp)}) (check #1)`
|
731
870
|
)
|
732
871
|
}
|
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
|
+
}
|
733
963
|
}
|
734
964
|
}
|
735
965
|
}
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
745
|
-
|
746
|
-
|
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]
|
974
|
+
if (
|
975
|
+
T === ATOM &&
|
976
|
+
!isUnknownType(args[i][STATS]) &&
|
977
|
+
getType(args[i][STATS]) !== ATOM
|
978
|
+
) {
|
979
|
+
errorStack.add(
|
980
|
+
`Incorrect type of arguments ${i} for (${
|
981
|
+
first[VALUE]
|
982
|
+
}). Expected (${toTypeNames(
|
983
|
+
getType(args[i][STATS])
|
984
|
+
)}) but got (${toTypeNames(T)}) (${stringifyArgs(
|
985
|
+
exp
|
986
|
+
)}) (check #10)`
|
987
|
+
)
|
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]
|
998
|
+
) {
|
747
999
|
errorStack.add(
|
748
|
-
`Incorrect
|
1000
|
+
`Incorrect number of arguments for (${
|
1001
|
+
args[i][STATS][SIGNATURE]
|
1002
|
+
}) the (lambda) argument of (${
|
749
1003
|
first[VALUE]
|
750
|
-
}). Expected (${
|
751
|
-
|
752
|
-
|
753
|
-
env[
|
754
|
-
|
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)`
|
755
1009
|
)
|
756
|
-
}
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
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]
|
1018
|
+
if (
|
1019
|
+
!isUnknownReturn(expected[STATS]) &&
|
1020
|
+
!isUnknownReturn(actual[STATS]) &&
|
1021
|
+
!compareReturns(expected[STATS], actual[STATS])
|
1022
|
+
) {
|
1023
|
+
errorStack.add(
|
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])
|
1030
|
+
)}) but got (${toTypeNames(
|
1031
|
+
getReturn(actual[STATS])
|
1032
|
+
)}) (${stringifyArgs(exp)}) (check #782)`
|
1033
|
+
)
|
1034
|
+
} else if (
|
1035
|
+
actual[STATS].retried < MAX_RETRY_DEFINITION
|
1036
|
+
) {
|
1037
|
+
actual[STATS].retried += 1
|
1038
|
+
stack.unshift(() => match1())
|
1039
|
+
}
|
1040
|
+
}
|
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]
|
782
1051
|
if (
|
783
|
-
|
784
|
-
|
1052
|
+
!isUnknownType(actual[STATS]) &&
|
1053
|
+
!isUnknownType(expected[STATS]) &&
|
1054
|
+
!compareTypes(actual[STATS], expected[STATS])
|
1055
|
+
)
|
785
1056
|
errorStack.add(
|
786
|
-
`Incorrect type
|
787
|
-
|
1057
|
+
`Incorrect type for (lambda) (${
|
1058
|
+
args[i][STATS][SIGNATURE]
|
1059
|
+
}) argument at position (${j}) named as (${
|
1060
|
+
actual[STATS][SIGNATURE]
|
788
1061
|
}). Expected (${toTypeNames(
|
789
|
-
|
1062
|
+
getType(expected[STATS])
|
790
1063
|
)}) but got (${toTypeNames(
|
791
|
-
|
792
|
-
)}) (${stringifyArgs(exp)}) (check #
|
1064
|
+
getType(actual[STATS])
|
1065
|
+
)}) (${stringifyArgs(exp)}) (check #781)`
|
793
1066
|
)
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
root[first[VALUE]][STATS][RETURNS][0]
|
800
|
-
|
801
|
-
// root[first[VALUE]][STATS][RETURNS] =
|
802
|
-
// root[first[VALUE]][STATS][RETURNS]
|
803
|
-
} else {
|
804
|
-
// VALUE assigment
|
805
|
-
env[CAR][STATS][TYPE_PROP][0] = EXPECTED_TYPE
|
1067
|
+
else if (
|
1068
|
+
actual[STATS].retried < MAX_RETRY_DEFINITION
|
1069
|
+
) {
|
1070
|
+
actual[STATS].retried += 1
|
1071
|
+
stack.unshift(() => match2())
|
806
1072
|
}
|
807
1073
|
}
|
1074
|
+
match2()
|
808
1075
|
}
|
809
|
-
break
|
810
|
-
case ATOM: {
|
811
|
-
if (rest[i][TYPE] !== EXPECTED_TYPE) {
|
812
|
-
errorStack.add(
|
813
|
-
`Incorrect type of argument (${i}) for special form (${
|
814
|
-
first[VALUE]
|
815
|
-
}). Expected (${toTypeNames(
|
816
|
-
EXPECTED_TYPE
|
817
|
-
)}) but got (${toTypeNames(
|
818
|
-
rest[i][TYPE]
|
819
|
-
)}) (${stringifyArgs(exp)}) (check #2)`
|
820
|
-
)
|
821
|
-
}
|
822
|
-
break
|
823
1076
|
}
|
824
1077
|
}
|
825
|
-
}
|
826
|
-
}
|
827
|
-
// type checking
|
828
|
-
else if (isRestILeaf) {
|
829
|
-
const T =
|
830
|
-
rest[i][TYPE] === WORD && env[rest[i][VALUE]]
|
831
|
-
? env[rest[i][VALUE]][STATS][TYPE_PROP][0]
|
832
|
-
: rest[i][TYPE]
|
833
|
-
if (
|
834
|
-
T === ATOM &&
|
835
|
-
args[i][STATS][TYPE_PROP][0] !== UNKNOWN &&
|
836
|
-
args[i][STATS][TYPE_PROP][0] !== ATOM
|
837
|
-
) {
|
838
|
-
errorStack.add(
|
839
|
-
`Incorrect type of arguments ${i} for (${
|
840
|
-
first[VALUE]
|
841
|
-
}). Expected (${toTypeNames(
|
842
|
-
args[i][STATS][TYPE_PROP][0]
|
843
|
-
)}) but got (${toTypeNames(T)}) (${stringifyArgs(
|
844
|
-
exp
|
845
|
-
)}) (check #10)`
|
846
|
-
)
|
847
|
-
} else if (
|
848
|
-
T === APPLY &&
|
849
|
-
args[i][STATS][TYPE_PROP][0] !== UNKNOWN &&
|
850
|
-
env[rest[i][VALUE]][STATS][TYPE_PROP][0] !== UNKNOWN &&
|
851
|
-
env[rest[i][VALUE]][STATS][ARG_COUNT] !== VARIADIC
|
852
|
-
) {
|
853
|
-
// Handles words that are Lambdas
|
854
1078
|
if (
|
855
|
-
|
856
|
-
|
1079
|
+
T === COLLECTION &&
|
1080
|
+
env[rest[i][VALUE]] &&
|
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
|
+
)
|
857
1087
|
) {
|
858
1088
|
errorStack.add(
|
859
|
-
`Incorrect
|
860
|
-
args[i][STATS][SIGNATURE]
|
861
|
-
}) the (lambda) argument of (${
|
1089
|
+
`Incorrect type of arguments ${i} for (${
|
862
1090
|
first[VALUE]
|
863
|
-
})
|
864
|
-
args[i][STATS]
|
865
|
-
}) but got ${
|
866
|
-
|
867
|
-
|
1091
|
+
}). Expected (${toTypeNames(
|
1092
|
+
getType(args[i][STATS])
|
1093
|
+
)}) but got (${toTypeNames(T)}) (${stringifyArgs(
|
1094
|
+
exp
|
1095
|
+
)}) (check #30)`
|
868
1096
|
)
|
869
|
-
}
|
870
|
-
|
871
|
-
|
872
|
-
T === COLLECTION &&
|
873
|
-
env[rest[i][VALUE]] &&
|
874
|
-
env[rest[i][VALUE]][STATS][TYPE_PROP][0] !== UNKNOWN &&
|
875
|
-
args[i][STATS][TYPE_PROP][0] !== UNKNOWN &&
|
876
|
-
env[rest[i][VALUE]][STATS][TYPE_PROP][0] !==
|
877
|
-
args[i][STATS][TYPE_PROP][0]
|
878
|
-
) {
|
879
|
-
errorStack.add(
|
880
|
-
`Incorrect type of arguments ${i} for (${
|
881
|
-
first[VALUE]
|
882
|
-
}). Expected (${toTypeNames(
|
883
|
-
args[i][STATS][TYPE_PROP][0]
|
884
|
-
)}) but got (${toTypeNames(T)}) (${stringifyArgs(
|
885
|
-
exp
|
886
|
-
)}) (check #30)`
|
887
|
-
)
|
888
|
-
} else if (
|
889
|
-
args[i][STATS][TYPE_PROP][0] === UNKNOWN &&
|
890
|
-
args[i][STATS].retried < MAX_RETRY_DEFINITION
|
891
|
-
) {
|
892
|
-
args[i][STATS].retried += 1
|
893
|
-
stack.unshift(() => check(exp, env, scope))
|
894
|
-
} else {
|
895
|
-
if (
|
896
|
-
env[rest[i][VALUE]] &&
|
897
|
-
args[i][STATS][TYPE_PROP][0] !== UNKNOWN &&
|
898
|
-
env[rest[i][VALUE]][STATS][TYPE_PROP][0] === UNKNOWN &&
|
899
|
-
args[i][STATS][TYPE_PROP][0] !== APPLY
|
1097
|
+
} else if (
|
1098
|
+
isUnknownType(args[i][STATS]) &&
|
1099
|
+
args[i][STATS].retried < MAX_RETRY_DEFINITION
|
900
1100
|
) {
|
901
|
-
|
902
|
-
env
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
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
|
+
}
|
915
1116
|
}
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
)
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
)
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
local
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
|
973
|
-
|
974
|
-
|
975
|
-
|
976
|
-
|
977
|
-
|
978
|
-
|
979
|
-
|
980
|
-
|
981
|
-
|
982
|
-
)}) but got (${toTypeNames(
|
983
|
-
actual[STATS][RETURNS][0]
|
984
|
-
)}) (${stringifyArgs(
|
985
|
-
exp
|
986
|
-
)}) (check #779)`
|
987
|
-
)
|
988
|
-
} else if (
|
989
|
-
actual[STATS].retried <
|
990
|
-
MAX_RETRY_DEFINITION
|
991
|
-
) {
|
992
|
-
actual[STATS].retried += 1
|
993
|
-
stack.unshift(() => match1())
|
994
|
-
}
|
995
|
-
}
|
996
|
-
match1()
|
997
|
-
for (
|
998
|
-
let j = 0;
|
999
|
-
j < args[i][STATS][ARGUMENTS].length;
|
1000
|
-
++j
|
1001
|
-
) {
|
1002
|
-
const match2 = () => {
|
1003
|
-
const actual =
|
1004
|
-
local[lambdaName][STATS][ARGUMENTS][j]
|
1005
|
-
const expected =
|
1006
|
-
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]
|
1007
1183
|
if (
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
1014
|
-
)
|
1184
|
+
!isUnknownReturn(expected[STATS]) &&
|
1185
|
+
!isUnknownReturn(actual[STATS]) &&
|
1186
|
+
!compareReturns(
|
1187
|
+
expected[STATS],
|
1188
|
+
actual[STATS]
|
1189
|
+
)
|
1190
|
+
) {
|
1015
1191
|
errorStack.add(
|
1016
|
-
`Incorrect type for (
|
1017
|
-
|
1018
|
-
})
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
}). Expected (${toTypeNames(
|
1023
|
-
args[i][STATS][ARGUMENTS][j][
|
1024
|
-
STATS
|
1025
|
-
][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])
|
1026
1198
|
)}) but got (${toTypeNames(
|
1027
|
-
|
1028
|
-
ARGUMENTS
|
1029
|
-
][j][STATS][TYPE_PROP][0]
|
1199
|
+
getReturn(actual[STATS])
|
1030
1200
|
)}) (${stringifyArgs(
|
1031
1201
|
exp
|
1032
|
-
)}) (check #
|
1202
|
+
)}) (check #779)`
|
1033
1203
|
)
|
1034
|
-
else if (
|
1204
|
+
} else if (
|
1035
1205
|
actual[STATS].retried <
|
1036
1206
|
MAX_RETRY_DEFINITION
|
1037
1207
|
) {
|
1038
1208
|
actual[STATS].retried += 1
|
1039
|
-
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
|
+
}
|
1040
1255
|
}
|
1256
|
+
match2()
|
1041
1257
|
}
|
1042
|
-
match2()
|
1043
1258
|
}
|
1044
|
-
|
1045
|
-
//
|
1046
|
-
// STATS
|
1047
|
-
// ],
|
1048
|
-
// args[i][STATS]
|
1049
|
-
// )
|
1259
|
+
} else {
|
1260
|
+
// TODO fix curry: lambdas enter here as undefined
|
1050
1261
|
}
|
1051
|
-
} else {
|
1052
|
-
// TODO fix curry: lambdas enter here as undefined
|
1053
1262
|
}
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1263
|
+
break
|
1264
|
+
// case ATOM:
|
1265
|
+
// case COLLECTION:
|
1266
|
+
// break
|
1267
|
+
}
|
1059
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())
|
1060
1275
|
}
|
1061
|
-
} else if (
|
1062
|
-
expected[0] === UNKNOWN &&
|
1063
|
-
args[i][STATS].retried < MAX_RETRY_DEFINITION
|
1064
|
-
) {
|
1065
|
-
args[i][STATS].retried += 1
|
1066
|
-
stack.unshift(() => match())
|
1067
1276
|
}
|
1277
|
+
match()
|
1068
1278
|
}
|
1069
|
-
match()
|
1070
1279
|
}
|
1071
1280
|
}
|
1072
|
-
}
|
1073
|
-
})
|
1281
|
+
})
|
1074
1282
|
for (let i = 0; i < rest.length; ++i) {
|
1075
1283
|
const r = rest[i]
|
1076
1284
|
if (isLeaf(r) && r[TYPE] !== ATOM) {
|
@@ -1094,8 +1302,10 @@ export const typeCheck = (ast) => {
|
|
1094
1302
|
const copy = JSON.parse(JSON.stringify(ast))
|
1095
1303
|
check(copy, root, copy)
|
1096
1304
|
while (stack.length) stack.pop()()
|
1097
|
-
|
1098
|
-
|
1305
|
+
if (error) {
|
1306
|
+
const issues = [...errorStack, ...warningStack]
|
1307
|
+
if (issues.length) throw new TypeError(issues.join('\n'))
|
1308
|
+
}
|
1099
1309
|
return [ast, Types]
|
1100
1310
|
}
|
1101
1311
|
export const type = (ast) => typeCheck(ast)[0]
|