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