fez-lisp 1.5.100 → 1.5.102
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/logo.svg +5 -5
- package/package.json +1 -1
- package/src/check.js +118 -175
- package/src/types.js +12 -4
package/src/check.js
CHANGED
@@ -66,6 +66,10 @@ const deepLambdaReturn = (rest, condition) => {
|
|
66
66
|
const rem = hasBlock(body) ? body.at(-1) : body
|
67
67
|
return condition(rem) ? rem : deepLambdaReturn(rem, condition)
|
68
68
|
}
|
69
|
+
export const isUnknownNotAnyType = (stats) =>
|
70
|
+
stats && !isAnyType(stats) && isUnknownType(stats)
|
71
|
+
export const isUnknownNotAnyReturn = (stats) =>
|
72
|
+
stats && !isAnyReturn(stats) && isUnknownReturn(stats)
|
69
73
|
export const castType = (stats, type) =>
|
70
74
|
(stats[TYPE_PROP][0] = type[RETURNS][0])
|
71
75
|
export const castReturn = (stats, type) =>
|
@@ -142,12 +146,12 @@ export const compareReturns = (a, b) =>
|
|
142
146
|
isAnyReturn(a) || isAnyReturn(b) || a[RETURNS][0] === b[RETURNS][0]
|
143
147
|
export const compareTypeWithReturn = (a, b) =>
|
144
148
|
isAnyType(a) || isAnyReturn(b) || a[TYPE_PROP][0] === b[RETURNS][0]
|
145
|
-
const checkPredicateName = (exp, rest
|
149
|
+
const checkPredicateName = (exp, rest) => {
|
146
150
|
if (getSuffix(rest[0][VALUE]) === PREDICATE_SUFFIX) {
|
147
151
|
const last = rest.at(-1)
|
148
152
|
if (isLeaf(last)) {
|
149
153
|
if (last[TYPE] === ATOM && last[VALUE] !== TRUE && last[VALUE] !== FALSE)
|
150
|
-
|
154
|
+
throw new TypeError(
|
151
155
|
`Assigning predicate (ending in ?) variable (${
|
152
156
|
rest[0][VALUE]
|
153
157
|
}) to an (${
|
@@ -159,7 +163,7 @@ const checkPredicateName = (exp, rest, errors) => {
|
|
159
163
|
getSuffix(last[VALUE]) !== PREDICATE_SUFFIX &&
|
160
164
|
!PREDICATES_OUTPUT_SET.has(last[VALUE])
|
161
165
|
)
|
162
|
-
|
166
|
+
throw new TypeError(
|
163
167
|
`Assigning predicate (ending in ?) variable (${
|
164
168
|
rest[0][VALUE]
|
165
169
|
}) to another variable which is not a predicate (also ending in ?) (${stringifyArgs(
|
@@ -177,7 +181,7 @@ const checkPredicateName = (exp, rest, errors) => {
|
|
177
181
|
getSuffix(application[VALUE]) !== PREDICATE_SUFFIX &&
|
178
182
|
!PREDICATES_OUTPUT_SET.has(application[VALUE])
|
179
183
|
)
|
180
|
-
|
184
|
+
throw new TypeError(
|
181
185
|
`Assigning predicate (ending in ?) variable (${
|
182
186
|
application[VALUE]
|
183
187
|
}) to another variable which is not a predicate (also ending in ?) (${stringifyArgs(
|
@@ -189,21 +193,17 @@ const checkPredicateName = (exp, rest, errors) => {
|
|
189
193
|
}
|
190
194
|
}
|
191
195
|
}
|
192
|
-
const checkPredicateNameDeep = (name, exp, rest, returns
|
196
|
+
const checkPredicateNameDeep = (name, exp, rest, returns) => {
|
193
197
|
if (returns[VALUE] === KEYWORDS.CALL_FUNCTION) {
|
194
198
|
const fn = rest.at(-1).at(-1).at(-1)
|
195
|
-
checkPredicateName(
|
196
|
-
|
197
|
-
|
198
|
-
[
|
199
|
-
|
200
|
-
|
201
|
-
: drillReturnType(fn, (r) => r[VALUE] === KEYWORDS.CALL_FUNCTION) // when apply is an annonymous lambda // (let fn? (lambda x (apply x (lambda x (array:empty! [])))))
|
202
|
-
],
|
203
|
-
errors
|
204
|
-
)
|
199
|
+
checkPredicateName(exp, [
|
200
|
+
[WORD, name],
|
201
|
+
isLeaf(fn)
|
202
|
+
? fn // when apply is a word (let x? (lambda (apply [] array:empty!)))
|
203
|
+
: drillReturnType(fn, (r) => r[VALUE] === KEYWORDS.CALL_FUNCTION) // when apply is an annonymous lambda // (let fn? (lambda x (apply x (lambda x (array:empty! [])))))
|
204
|
+
])
|
205
205
|
} else {
|
206
|
-
checkPredicateName(exp, [[WORD, name], returns]
|
206
|
+
checkPredicateName(exp, [[WORD, name], returns])
|
207
207
|
}
|
208
208
|
}
|
209
209
|
const fillUknownArgs = (n) =>
|
@@ -234,7 +234,21 @@ const withScope = (name, scope) => {
|
|
234
234
|
const chain = getScopeNames(scope)
|
235
235
|
return `${chain.length === 1 ? '; ' : ''}${chain.join(' ')} ${name}`
|
236
236
|
}
|
237
|
-
|
237
|
+
const retry = (stats, stack, cb) => {
|
238
|
+
if (
|
239
|
+
(isUnknownNotAnyType(stats) || isUnknownNotAnyReturn(stats)) &&
|
240
|
+
stats.retried < MAX_RETRY_DEFINITION
|
241
|
+
) {
|
242
|
+
stats.retried += 1
|
243
|
+
stack.unshift(() => cb())
|
244
|
+
}
|
245
|
+
}
|
246
|
+
const retryArgs = (stats, stack, cb) => {
|
247
|
+
if (stats.counter < MAX_ARGUMENT_RETRY) {
|
248
|
+
stats.counter++
|
249
|
+
stack.unshift(cb)
|
250
|
+
}
|
251
|
+
}
|
238
252
|
const ifExpression = ({ re, env, ref }) => {
|
239
253
|
if (re[0][TYPE] === ATOM || re[1][TYPE] === ATOM) setReturnToAtom(ref[STATS])
|
240
254
|
// TODO check that both brancehs are predicates if one is
|
@@ -259,18 +273,23 @@ const ifExpression = ({ re, env, ref }) => {
|
|
259
273
|
}
|
260
274
|
}
|
261
275
|
}
|
262
|
-
const
|
276
|
+
const resolveApplyAssigment = (re, name, env) => {
|
277
|
+
if (re[0][TYPE] === APPLY) {
|
278
|
+
switch (re[0][VALUE]) {
|
279
|
+
case KEYWORDS.ANONYMOUS_FUNCTION:
|
280
|
+
// FN ASSIGMENT
|
281
|
+
env[name][STATS][TYPE_PROP] = [APPLY]
|
282
|
+
env[name][STATS][RETURNS] = [UNKNOWN]
|
283
|
+
env[name][STATS][ARG_COUNT] = re.length - 2
|
284
|
+
env[name][STATS][ARGUMENTS] = fillUknownArgs(re.length - 2)
|
285
|
+
break
|
286
|
+
}
|
287
|
+
}
|
288
|
+
}
|
289
|
+
const resolveIfAssigment = ({ rem, name, env, exp, prop }) => {
|
263
290
|
const re = rem.slice(2)
|
264
|
-
checkPredicateName(
|
265
|
-
|
266
|
-
[[WORD, name], isLeaf(re[0]) ? re[0] : re[0][0]],
|
267
|
-
errors
|
268
|
-
)
|
269
|
-
checkPredicateName(
|
270
|
-
exp,
|
271
|
-
[[WORD, name], isLeaf(re[1]) ? re[1] : re[1][0]],
|
272
|
-
errors
|
273
|
-
)
|
291
|
+
checkPredicateName(exp, [[WORD, name], isLeaf(re[0]) ? re[0] : re[0][0]])
|
292
|
+
checkPredicateName(exp, [[WORD, name], isLeaf(re[1]) ? re[1] : re[1][0]])
|
274
293
|
if (re[0][TYPE] === ATOM || re[1][TYPE] === ATOM)
|
275
294
|
// ATOM ASSIGMENT
|
276
295
|
setPropToAtom(env[name][STATS], prop)
|
@@ -280,17 +299,7 @@ const resolveIfAssigment = ({ rem, name, env, exp, errors, prop }) => {
|
|
280
299
|
!isUnknownReturn(env[re[0][0][VALUE]][STATS])
|
281
300
|
) {
|
282
301
|
setPropToReturnRef(env[name][STATS], prop, env[re[0][0][VALUE]][STATS])
|
283
|
-
|
284
|
-
switch (re[0][0][VALUE]) {
|
285
|
-
case KEYWORDS.ANONYMOUS_FUNCTION:
|
286
|
-
// FN UKNONW ASSIGMENT
|
287
|
-
env[name][STATS][TYPE_PROP] = [APPLY]
|
288
|
-
env[name][STATS][RETURNS] = [UNKNOWN]
|
289
|
-
env[name][STATS][ARG_COUNT] = re[0].length - 2
|
290
|
-
env[name][STATS][ARGUMENTS] = fillUknownArgs(re[0].length - 2)
|
291
|
-
break
|
292
|
-
}
|
293
|
-
}
|
302
|
+
resolveApplyAssigment(re[0], name, env)
|
294
303
|
// env[name][STATS] = env[re[0][0][VALUE]][STATS]
|
295
304
|
} else if (
|
296
305
|
!isLeaf(re[1]) &&
|
@@ -298,17 +307,7 @@ const resolveIfAssigment = ({ rem, name, env, exp, errors, prop }) => {
|
|
298
307
|
!isUnknownReturn(env[re[1][0][VALUE]][STATS])
|
299
308
|
) {
|
300
309
|
setPropToReturnRef(env[name][STATS], prop, env[re[1][0][VALUE]][STATS])
|
301
|
-
|
302
|
-
switch (re[1][0][VALUE]) {
|
303
|
-
case KEYWORDS.ANONYMOUS_FUNCTION:
|
304
|
-
// FN ASSIGMENT
|
305
|
-
env[name][STATS][TYPE_PROP] = [APPLY]
|
306
|
-
env[name][STATS][RETURNS] = [UNKNOWN]
|
307
|
-
env[name][STATS][ARG_COUNT] = re[1].length - 2
|
308
|
-
env[name][STATS][ARGUMENTS] = fillUknownArgs(re[1].length - 2)
|
309
|
-
break
|
310
|
-
}
|
311
|
-
}
|
310
|
+
resolveApplyAssigment(re[1], name, env)
|
312
311
|
} else if (env[re[0][VALUE]])
|
313
312
|
// ASSIGMENT
|
314
313
|
setPropRef(env[name][STATS], prop, env[re[0][VALUE]][STATS])
|
@@ -316,20 +315,13 @@ const resolveIfAssigment = ({ rem, name, env, exp, errors, prop }) => {
|
|
316
315
|
// ASSIGMENT
|
317
316
|
setPropRef(env[name][STATS], prop, env[re[1][VALUE]][STATS])
|
318
317
|
}
|
319
|
-
const resolveCondition = ({ rem, name, env, exp
|
318
|
+
const resolveCondition = ({ rem, name, env, exp }) => {
|
320
319
|
const ret = rem[0]
|
321
320
|
const re = rem.slice(2)
|
321
|
+
resolveApplyAssigment(re, name, env)
|
322
322
|
const ref = env[name]
|
323
|
-
checkPredicateName(
|
324
|
-
|
325
|
-
[[WORD, name], isLeaf(re[0]) ? re[0] : re[0][0]],
|
326
|
-
errors
|
327
|
-
)
|
328
|
-
checkPredicateName(
|
329
|
-
exp,
|
330
|
-
[[WORD, name], isLeaf(re[1]) ? re[1] : re[1][0]],
|
331
|
-
errors
|
332
|
-
)
|
323
|
+
checkPredicateName(exp, [[WORD, name], isLeaf(re[0]) ? re[0] : re[0][0]])
|
324
|
+
checkPredicateName(exp, [[WORD, name], isLeaf(re[1]) ? re[1] : re[1][0]])
|
333
325
|
switch (ret[VALUE]) {
|
334
326
|
case KEYWORDS.IF:
|
335
327
|
ifExpression({ re, env, ref })
|
@@ -343,27 +335,18 @@ const resolveCondition = ({ rem, name, env, exp, errors }) => {
|
|
343
335
|
break
|
344
336
|
}
|
345
337
|
}
|
346
|
-
const resolveRetunType = ({
|
347
|
-
returns,
|
348
|
-
rem,
|
349
|
-
stack,
|
350
|
-
prop,
|
351
|
-
exp,
|
352
|
-
name,
|
353
|
-
errors,
|
354
|
-
env
|
355
|
-
}) => {
|
338
|
+
const resolveRetunType = ({ returns, rem, stack, prop, exp, name, env }) => {
|
356
339
|
if (returns[TYPE] === ATOM) {
|
357
340
|
// ATOM ASSIGMENT
|
358
341
|
setPropToAtom(env[name][STATS], prop)
|
359
|
-
checkPredicateName(exp, [[WORD, name], returns]
|
342
|
+
checkPredicateName(exp, [[WORD, name], returns])
|
360
343
|
} else {
|
361
344
|
switch (returns[VALUE]) {
|
362
345
|
case KEYWORDS.IF:
|
363
|
-
resolveIfAssigment({ rem, name, env, exp,
|
346
|
+
resolveIfAssigment({ rem, name, env, exp, prop })
|
364
347
|
break
|
365
348
|
default:
|
366
|
-
checkPredicateNameDeep(name, exp, exp.slice(1), returns
|
349
|
+
checkPredicateNameDeep(name, exp, exp.slice(1), returns)
|
367
350
|
if (!env[returns[VALUE]]) return false
|
368
351
|
else if (getType(env[returns[VALUE]][STATS]) === APPLY) {
|
369
352
|
if (returns[TYPE] === WORD) setReturnToAbbstraction(env[name][STATS])
|
@@ -388,7 +371,7 @@ const resolveRetunType = ({
|
|
388
371
|
}
|
389
372
|
return true
|
390
373
|
}
|
391
|
-
const checkReturnType = ({ exp, stack, name,
|
374
|
+
const checkReturnType = ({ exp, stack, name, env }) => {
|
392
375
|
const last = exp.at(-1).at(-1)
|
393
376
|
const body = hasApplyLambdaBlock(last) ? last.at(-1).at(-1) : last
|
394
377
|
const rem = hasBlock(body) ? body.at(-1) : body
|
@@ -399,7 +382,6 @@ const checkReturnType = ({ exp, stack, name, errors, env }) => {
|
|
399
382
|
prop: RETURNS,
|
400
383
|
exp,
|
401
384
|
name,
|
402
|
-
errors,
|
403
385
|
env,
|
404
386
|
stack
|
405
387
|
})
|
@@ -407,7 +389,6 @@ const checkReturnType = ({ exp, stack, name, errors, env }) => {
|
|
407
389
|
export const typeCheck = (ast, error = true) => {
|
408
390
|
let scopeIndex = 0
|
409
391
|
const root = structuredClone(SPECIAL_FORM_TYPES)
|
410
|
-
const errors = new Set()
|
411
392
|
const Types = new Map()
|
412
393
|
const stack = []
|
413
394
|
const check = (exp, env, scope) => {
|
@@ -421,14 +402,14 @@ export const typeCheck = (ast, error = true) => {
|
|
421
402
|
switch (first[TYPE]) {
|
422
403
|
case WORD:
|
423
404
|
if (!isSpecial)
|
424
|
-
stack.push(
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
errors.add(
|
405
|
+
stack.push(() => {
|
406
|
+
// Figure out how to determine if varible is define after it's used
|
407
|
+
if (env[first[VALUE]] === undefined) {
|
408
|
+
throw new TypeError(
|
429
409
|
`Trying to access undefined variable ${first[VALUE]} (check #11)`
|
430
410
|
)
|
431
|
-
|
411
|
+
}
|
412
|
+
})
|
432
413
|
break
|
433
414
|
case ATOM:
|
434
415
|
break
|
@@ -470,35 +451,30 @@ export const typeCheck = (ast, error = true) => {
|
|
470
451
|
stack,
|
471
452
|
exp,
|
472
453
|
env,
|
473
|
-
name
|
474
|
-
errors
|
454
|
+
name
|
475
455
|
}) ||
|
476
|
-
|
477
|
-
env[name][STATS].retried < MAX_RETRY_DEFINITION)
|
456
|
+
isUnknownReturn(env[name][STATS])
|
478
457
|
) {
|
479
|
-
env[name][STATS]
|
480
|
-
stack.unshift(() => {
|
458
|
+
retry(env[name][STATS], stack, () => {
|
481
459
|
checkReturnType({
|
482
460
|
stack,
|
483
461
|
exp,
|
484
462
|
env,
|
485
|
-
name
|
486
|
-
errors
|
463
|
+
name
|
487
464
|
})
|
488
465
|
check(rightHand, env, exp)
|
489
466
|
})
|
490
467
|
check(rightHand, env, exp)
|
491
468
|
} else check(rightHand, env, exp)
|
492
469
|
} else {
|
493
|
-
checkPredicateName(exp, rest
|
470
|
+
checkPredicateName(exp, rest)
|
494
471
|
const isLeafNode = isLeaf(rightHand)
|
495
472
|
if (isLeafNode && rightHand[TYPE] === WORD) {
|
496
473
|
// TODO make sure this prevents the assigment all together
|
497
474
|
if (env[rest[1][VALUE]] === undefined)
|
498
|
-
|
475
|
+
throw new TypeError(
|
499
476
|
`Trying to access undefined variable ${rest[1][VALUE]} (check #22)`
|
500
477
|
)
|
501
|
-
|
502
478
|
// Used to be checkin if it's an assigment to a special form
|
503
479
|
// but this should not cause problems
|
504
480
|
// env[name] = SPECIAL_FORMS_SET.has(rest[1][VALUE])
|
@@ -519,7 +495,7 @@ export const typeCheck = (ast, error = true) => {
|
|
519
495
|
}
|
520
496
|
} else if (rightHand[0]) {
|
521
497
|
const right = rightHand[0]
|
522
|
-
//DECLARATION
|
498
|
+
// DECLARATION
|
523
499
|
env[name] = {
|
524
500
|
[STATS]: {
|
525
501
|
retried: 0,
|
@@ -545,8 +521,7 @@ export const typeCheck = (ast, error = true) => {
|
|
545
521
|
prop: TYPE_PROP,
|
546
522
|
exp,
|
547
523
|
env,
|
548
|
-
name
|
549
|
-
errors
|
524
|
+
name
|
550
525
|
})
|
551
526
|
}
|
552
527
|
check(rightHand, env, scope)
|
@@ -564,7 +539,7 @@ export const typeCheck = (ast, error = true) => {
|
|
564
539
|
const param = params[i]
|
565
540
|
// TODO move this somewhere else
|
566
541
|
if (!isLeaf(param))
|
567
|
-
|
542
|
+
throw new TypeError(
|
568
543
|
`Invalid body for (${
|
569
544
|
first[VALUE]
|
570
545
|
}) if it takes more than one expression it must be wrapped in a (${
|
@@ -607,7 +582,6 @@ export const typeCheck = (ast, error = true) => {
|
|
607
582
|
name: ref[STATS][SIGNATURE],
|
608
583
|
env: copy,
|
609
584
|
exp,
|
610
|
-
errors,
|
611
585
|
stack
|
612
586
|
})
|
613
587
|
break
|
@@ -619,7 +593,6 @@ export const typeCheck = (ast, error = true) => {
|
|
619
593
|
if (copy[ret[VALUE]])
|
620
594
|
setReturnRef(ref[STATS], copy[ret[VALUE]][STATS])
|
621
595
|
})
|
622
|
-
|
623
596
|
break
|
624
597
|
}
|
625
598
|
}
|
@@ -648,7 +621,7 @@ export const typeCheck = (ast, error = true) => {
|
|
648
621
|
default:
|
649
622
|
stack.push(() => {
|
650
623
|
if (!isSpecial && env[first[VALUE]] === undefined)
|
651
|
-
|
624
|
+
throw new TypeError(
|
652
625
|
`Trying to call undefined (lambda) ${first[VALUE]} (check #9)`
|
653
626
|
)
|
654
627
|
else if (
|
@@ -656,7 +629,7 @@ export const typeCheck = (ast, error = true) => {
|
|
656
629
|
env[first[VALUE]][STATS][ARG_COUNT] !== VARIADIC &&
|
657
630
|
env[first[VALUE]][STATS][ARG_COUNT] !== rest.length
|
658
631
|
)
|
659
|
-
|
632
|
+
throw new TypeError(
|
660
633
|
`Incorrect number of arguments for (${
|
661
634
|
first[VALUE]
|
662
635
|
}). Expected (= ${
|
@@ -666,7 +639,7 @@ export const typeCheck = (ast, error = true) => {
|
|
666
639
|
else {
|
667
640
|
if (first[TYPE] === APPLY && !isSpecial) {
|
668
641
|
if (getType(env[first[VALUE]][STATS]) === ATOM)
|
669
|
-
|
642
|
+
throw new TypeError(
|
670
643
|
`(${first[VALUE]}) is not a (lambda) (${stringifyArgs(
|
671
644
|
exp
|
672
645
|
)}) (check #12)`
|
@@ -737,7 +710,7 @@ export const typeCheck = (ast, error = true) => {
|
|
737
710
|
const fnName = rest[i].at(-1)[VALUE]
|
738
711
|
const fn = env[fnName]
|
739
712
|
if (fn && getReturn(fn[STATS]) !== ATOM)
|
740
|
-
|
713
|
+
throw new TypeError(
|
741
714
|
`Incorrect type of argument (${i}) for (${
|
742
715
|
first[VALUE]
|
743
716
|
}). Expected (${toTypeNames(
|
@@ -752,7 +725,7 @@ export const typeCheck = (ast, error = true) => {
|
|
752
725
|
const returns = isLeaf(rem) ? rem : rem[0]
|
753
726
|
if (returns[TYPE] === ATOM) {
|
754
727
|
if (MAIN_TYPE !== ATOM)
|
755
|
-
|
728
|
+
throw new TypeError(
|
756
729
|
`Incorrect type of argument ${i} for (${
|
757
730
|
first[VALUE]
|
758
731
|
}). Expected (${toTypeNames(
|
@@ -766,7 +739,7 @@ export const typeCheck = (ast, error = true) => {
|
|
766
739
|
!isUnknownReturn(env[returns[VALUE]][STATS]) &&
|
767
740
|
getReturn(env[returns[VALUE]][STATS]) !== ATOM
|
768
741
|
)
|
769
|
-
|
742
|
+
throw new TypeError(
|
770
743
|
`Incorrect type of argument ${i} for (${
|
771
744
|
first[VALUE]
|
772
745
|
}). Expected (${toTypeNames(
|
@@ -789,7 +762,7 @@ export const typeCheck = (ast, error = true) => {
|
|
789
762
|
env[name][STATS]
|
790
763
|
)
|
791
764
|
)
|
792
|
-
|
765
|
+
throw new TypeError(
|
793
766
|
`Incorrect type of argument (${i}) for special form (${
|
794
767
|
first[VALUE]
|
795
768
|
}). Expected (${toTypeNames(
|
@@ -829,7 +802,7 @@ export const typeCheck = (ast, error = true) => {
|
|
829
802
|
env[name][STATS]
|
830
803
|
)
|
831
804
|
)
|
832
|
-
|
805
|
+
throw new TypeError(
|
833
806
|
`Incorrect type of argument (${i}) for special form (${
|
834
807
|
first[VALUE]
|
835
808
|
}). Expected (${toTypeNames(
|
@@ -847,7 +820,7 @@ export const typeCheck = (ast, error = true) => {
|
|
847
820
|
rest[i][TYPE] !==
|
848
821
|
expectedArgs[i][STATS][TYPE_PROP][0]
|
849
822
|
)
|
850
|
-
|
823
|
+
throw new TypeError(
|
851
824
|
`Incorrect type of argument (${i}) for special form (${
|
852
825
|
first[VALUE]
|
853
826
|
}). Expected (${toTypeNames(
|
@@ -874,7 +847,7 @@ export const typeCheck = (ast, error = true) => {
|
|
874
847
|
!isUnknownType(args[i][STATS]) &&
|
875
848
|
getType(args[i][STATS]) !== ATOM
|
876
849
|
) {
|
877
|
-
|
850
|
+
throw new TypeError(
|
878
851
|
`Incorrect type of arguments ${i} for (${
|
879
852
|
first[VALUE]
|
880
853
|
}). Expected (${toTypeNames(
|
@@ -894,7 +867,7 @@ export const typeCheck = (ast, error = true) => {
|
|
894
867
|
env[rest[i][VALUE]][STATS][ARG_COUNT] !==
|
895
868
|
args[i][STATS][ARG_COUNT]
|
896
869
|
) {
|
897
|
-
|
870
|
+
throw new TypeError(
|
898
871
|
`Incorrect number of arguments for (${
|
899
872
|
args[i][STATS][SIGNATURE]
|
900
873
|
}) the (lambda) argument of (${
|
@@ -918,7 +891,7 @@ export const typeCheck = (ast, error = true) => {
|
|
918
891
|
!isUnknownReturn(actual[STATS]) &&
|
919
892
|
!compareReturns(expected[STATS], actual[STATS])
|
920
893
|
) {
|
921
|
-
|
894
|
+
throw new TypeError(
|
922
895
|
`Incorrect return type for (${
|
923
896
|
expected[STATS][SIGNATURE]
|
924
897
|
}) the (lambda) argument of (${
|
@@ -929,12 +902,7 @@ export const typeCheck = (ast, error = true) => {
|
|
929
902
|
getReturn(actual[STATS])
|
930
903
|
)}) (${stringifyArgs(exp)}) (check #782)`
|
931
904
|
)
|
932
|
-
} else
|
933
|
-
actual[STATS].retried < MAX_RETRY_DEFINITION
|
934
|
-
) {
|
935
|
-
actual[STATS].retried += 1
|
936
|
-
stack.unshift(() => match1())
|
937
|
-
}
|
905
|
+
} else retry(actual[STATS], stack, () => match1())
|
938
906
|
}
|
939
907
|
match1()
|
940
908
|
for (
|
@@ -951,7 +919,7 @@ export const typeCheck = (ast, error = true) => {
|
|
951
919
|
!isUnknownType(expected[STATS]) &&
|
952
920
|
!compareTypes(actual[STATS], expected[STATS])
|
953
921
|
)
|
954
|
-
|
922
|
+
throw new TypeError(
|
955
923
|
`Incorrect type for (lambda) (${
|
956
924
|
args[i][STATS][SIGNATURE]
|
957
925
|
}) argument at position (${j}) named as (${
|
@@ -962,12 +930,7 @@ export const typeCheck = (ast, error = true) => {
|
|
962
930
|
getType(actual[STATS])
|
963
931
|
)}) (${stringifyArgs(exp)}) (check #781)`
|
964
932
|
)
|
965
|
-
else
|
966
|
-
actual[STATS].retried < MAX_RETRY_DEFINITION
|
967
|
-
) {
|
968
|
-
actual[STATS].retried += 1
|
969
|
-
stack.unshift(() => match2())
|
970
|
-
}
|
933
|
+
else retry(actual[STATS], stack, () => match2())
|
971
934
|
}
|
972
935
|
match2()
|
973
936
|
}
|
@@ -980,7 +943,7 @@ export const typeCheck = (ast, error = true) => {
|
|
980
943
|
!isUnknownType(args[i][STATS]) &&
|
981
944
|
!compareTypes(env[rest[i][VALUE]][STATS], args[i][STATS])
|
982
945
|
) {
|
983
|
-
|
946
|
+
throw new TypeError(
|
984
947
|
`Incorrect type of arguments ${i} for (${
|
985
948
|
first[VALUE]
|
986
949
|
}). Expected (${toTypeNames(
|
@@ -989,37 +952,28 @@ export const typeCheck = (ast, error = true) => {
|
|
989
952
|
exp
|
990
953
|
)}) (check #30)`
|
991
954
|
)
|
992
|
-
} else if (
|
993
|
-
|
994
|
-
|
955
|
+
} else if (isUnknownType(args[i][STATS]))
|
956
|
+
retry(args[i][STATS], stack, () => check(exp, env, scope))
|
957
|
+
else if (
|
958
|
+
env[rest[i][VALUE]] &&
|
959
|
+
!isUnknownType(args[i][STATS]) &&
|
960
|
+
isUnknownType(env[rest[i][VALUE]][STATS]) &&
|
961
|
+
getType(args[i][STATS]) !== APPLY
|
995
962
|
) {
|
996
|
-
|
997
|
-
|
998
|
-
|
999
|
-
|
1000
|
-
|
1001
|
-
!isUnknownType(args[i][STATS]) &&
|
1002
|
-
isUnknownType(env[rest[i][VALUE]][STATS]) &&
|
1003
|
-
getType(args[i][STATS]) !== APPLY
|
1004
|
-
) {
|
1005
|
-
// REFF ASSIGMENT
|
1006
|
-
env[rest[i][VALUE]][STATS][TYPE_PROP] =
|
1007
|
-
args[i][STATS][TYPE_PROP]
|
1008
|
-
env[rest[i][VALUE]][STATS][RETURNS] =
|
1009
|
-
args[i][STATS][RETURNS]
|
1010
|
-
}
|
963
|
+
// REFF ASSIGMENT
|
964
|
+
env[rest[i][VALUE]][STATS][TYPE_PROP] =
|
965
|
+
args[i][STATS][TYPE_PROP]
|
966
|
+
env[rest[i][VALUE]][STATS][RETURNS] =
|
967
|
+
args[i][STATS][RETURNS]
|
1011
968
|
}
|
1012
969
|
} else if (env[rest[i][0][VALUE]]) {
|
1013
970
|
const match = () => {
|
1014
971
|
const actual = env[rest[i][0][VALUE]][STATS]
|
1015
972
|
const expected = args[i][STATS]
|
1016
|
-
|
1017
|
-
args[i][STATS].counter++
|
1018
|
-
stack.unshift(() => match())
|
1019
|
-
}
|
973
|
+
retryArgs(args[i][STATS], stack, () => match())
|
1020
974
|
if (!isUnknownType(expected) && !isUnknownReturn(actual))
|
1021
975
|
if (!compareTypeWithReturn(expected, actual))
|
1022
|
-
|
976
|
+
throw new TypeError(
|
1023
977
|
`Incorrect type of arguments ${i} for (${
|
1024
978
|
first[VALUE]
|
1025
979
|
}). Expected (${toTypeNames(
|
@@ -1039,7 +993,7 @@ export const typeCheck = (ast, error = true) => {
|
|
1039
993
|
KEYWORDS.ANONYMOUS_FUNCTION
|
1040
994
|
) {
|
1041
995
|
if (argsN !== args[i][STATS][ARG_COUNT])
|
1042
|
-
|
996
|
+
throw new TypeError(
|
1043
997
|
`Incorrect number of arguments for (${
|
1044
998
|
args[i][STATS][SIGNATURE]
|
1045
999
|
}) the (lambda) argument of (${
|
@@ -1077,7 +1031,7 @@ export const typeCheck = (ast, error = true) => {
|
|
1077
1031
|
actual[STATS]
|
1078
1032
|
)
|
1079
1033
|
)
|
1080
|
-
|
1034
|
+
throw new TypeError(
|
1081
1035
|
`Incorrect return type for (${
|
1082
1036
|
expected[STATS][SIGNATURE]
|
1083
1037
|
}) the (lambda) argument of (${
|
@@ -1090,13 +1044,10 @@ export const typeCheck = (ast, error = true) => {
|
|
1090
1044
|
exp
|
1091
1045
|
)}) (check #779)`
|
1092
1046
|
)
|
1093
|
-
else
|
1094
|
-
actual[STATS]
|
1095
|
-
|
1096
|
-
|
1097
|
-
actual[STATS].retried += 1
|
1098
|
-
stack.unshift(() => match1())
|
1099
|
-
}
|
1047
|
+
else
|
1048
|
+
retry(actual[STATS], stack, () =>
|
1049
|
+
match1()
|
1050
|
+
)
|
1100
1051
|
}
|
1101
1052
|
match1()
|
1102
1053
|
for (
|
@@ -1117,7 +1068,7 @@ export const typeCheck = (ast, error = true) => {
|
|
1117
1068
|
expected[STATS]
|
1118
1069
|
)
|
1119
1070
|
)
|
1120
|
-
|
1071
|
+
throw new TypeError(
|
1121
1072
|
`Incorrect type for (lambda) (${
|
1122
1073
|
args[i][STATS][SIGNATURE]
|
1123
1074
|
}) argument at position (${j}) named as (${
|
@@ -1132,13 +1083,10 @@ export const typeCheck = (ast, error = true) => {
|
|
1132
1083
|
exp
|
1133
1084
|
)}) (check #780)`
|
1134
1085
|
)
|
1135
|
-
else
|
1136
|
-
actual[STATS]
|
1137
|
-
|
1138
|
-
|
1139
|
-
actual[STATS].retried += 1
|
1140
|
-
stack.unshift(() => match2())
|
1141
|
-
}
|
1086
|
+
else
|
1087
|
+
retry(actual[STATS], stack, () =>
|
1088
|
+
match2()
|
1089
|
+
)
|
1142
1090
|
}
|
1143
1091
|
match2()
|
1144
1092
|
}
|
@@ -1153,24 +1101,20 @@ export const typeCheck = (ast, error = true) => {
|
|
1153
1101
|
// break
|
1154
1102
|
}
|
1155
1103
|
}
|
1156
|
-
else if (
|
1157
|
-
|
1158
|
-
args[i][STATS].retried < MAX_RETRY_DEFINITION
|
1159
|
-
) {
|
1160
|
-
args[i][STATS].retried += 1
|
1161
|
-
stack.unshift(() => match())
|
1162
|
-
}
|
1104
|
+
else if (isUnknownType(expected))
|
1105
|
+
retry(args[i][STATS], stack, () => match())
|
1163
1106
|
}
|
1164
1107
|
match()
|
1165
1108
|
}
|
1166
1109
|
}
|
1167
1110
|
}
|
1168
1111
|
})
|
1112
|
+
|
1169
1113
|
for (let i = 0; i < rest.length; ++i) {
|
1170
1114
|
const r = rest[i]
|
1171
1115
|
if (isLeaf(r) && r[TYPE] !== ATOM)
|
1172
1116
|
if (env[r[VALUE]] == undefined)
|
1173
|
-
|
1117
|
+
throw new TypeError(
|
1174
1118
|
`(${
|
1175
1119
|
first[VALUE]
|
1176
1120
|
}) is trying to access undefined variable (${
|
@@ -1187,7 +1131,6 @@ export const typeCheck = (ast, error = true) => {
|
|
1187
1131
|
const copy = JSON.parse(JSON.stringify(ast))
|
1188
1132
|
check(copy, root, copy)
|
1189
1133
|
while (stack.length) stack.pop()()
|
1190
|
-
if (error && errors.size) throw new TypeError([...errors.values()].join('\n'))
|
1191
1134
|
return [ast, Types]
|
1192
1135
|
}
|
1193
1136
|
export const type = (ast) => typeCheck(ast)[0]
|