fez-lisp 1.5.84 → 1.5.86
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 +180 -506
- package/src/keywords.js +8 -1
package/src/check.js
CHANGED
@@ -1,16 +1,12 @@
|
|
1
1
|
import {
|
2
2
|
APPLY,
|
3
3
|
ATOM,
|
4
|
-
DEBUG,
|
5
|
-
FALSE,
|
6
4
|
KEYWORDS,
|
7
|
-
MUTATION_SUFFIX,
|
8
5
|
PLACEHOLDER,
|
9
|
-
|
6
|
+
PREDICATES_SET,
|
10
7
|
SPECIAL_FORMS_SET,
|
11
8
|
STATIC_TYPES,
|
12
9
|
STATIC_TYPES_SET,
|
13
|
-
TRUE,
|
14
10
|
TYPE,
|
15
11
|
VALUE,
|
16
12
|
WORD
|
@@ -28,19 +24,13 @@ import {
|
|
28
24
|
SCOPE_NAME,
|
29
25
|
TYPE_PROP,
|
30
26
|
SIGNATURE,
|
31
|
-
PREDICATE,
|
32
|
-
COLLECTION,
|
33
27
|
MAX_RETRY_DEFINITION,
|
34
28
|
MAX_ARGUMENT_RETRY,
|
35
29
|
ORDER,
|
36
|
-
VARIABLE_ORDER_INDEX
|
30
|
+
VARIABLE_ORDER_INDEX,
|
31
|
+
COLLECTION
|
37
32
|
} from './types.js'
|
38
|
-
import {
|
39
|
-
getSuffix,
|
40
|
-
hasApplyLambdaBlock,
|
41
|
-
hasBlock,
|
42
|
-
stringifyArgs
|
43
|
-
} from './utils.js'
|
33
|
+
import { hasApplyLambdaBlock, hasBlock, stringifyArgs } from './utils.js'
|
44
34
|
|
45
35
|
export const identity = (name) => [
|
46
36
|
[0, 'let'],
|
@@ -94,18 +84,15 @@ export const formatType = (name, env) => {
|
|
94
84
|
`${
|
95
85
|
x[STATS][TYPE_PROP][0] === APPLY
|
96
86
|
? `${formatType(i, stats[ARGUMENTS])}`
|
97
|
-
: `${toTypeNames(
|
98
|
-
x[STATS][TYPE_PROP][1] ?? x[STATS][TYPE_PROP][0]
|
99
|
-
)}`
|
87
|
+
: `${toTypeNames(x[STATS][TYPE_PROP][0])}`
|
100
88
|
}`
|
101
89
|
)
|
102
90
|
.join(' ')
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
)})`
|
91
|
+
// TODO format returned functions when type support is added
|
92
|
+
} (${KEYWORDS.BLOCK} ${toTypeNames(stats[RETURNS][0])})${
|
93
|
+
isAnonymous ? '' : ')'
|
94
|
+
})`
|
95
|
+
: `(let ${name} ${toTypeNames(stats[TYPE_PROP][0])})`
|
109
96
|
: name
|
110
97
|
}
|
111
98
|
const formatTypes = (env) => {
|
@@ -157,37 +144,6 @@ export const typeCheck = (ast) => {
|
|
157
144
|
errorStack.add(
|
158
145
|
`Trying to access undefined variable ${first[VALUE]} (check #11)`
|
159
146
|
)
|
160
|
-
} else {
|
161
|
-
const T = env[first[VALUE]][STATS]
|
162
|
-
const isKnown = T[TYPE_PROP][0] !== UNKNOWN
|
163
|
-
switch (first[VALUE]) {
|
164
|
-
case 'xs':
|
165
|
-
case 'arr':
|
166
|
-
case 'matrix':
|
167
|
-
case 'table':
|
168
|
-
if (isKnown && T[TYPE_PROP][0] !== COLLECTION) {
|
169
|
-
warningStack.add(
|
170
|
-
`A variable named ${first[VALUE]} must be of type (${
|
171
|
-
STATIC_TYPES.COLLECTION
|
172
|
-
}) but got type (${toTypeNames(
|
173
|
-
T[TYPE_PROP][0]
|
174
|
-
)}) (check #32)`
|
175
|
-
)
|
176
|
-
}
|
177
|
-
//else T[TYPE_PROP] = [COLLECTION]
|
178
|
-
break
|
179
|
-
default:
|
180
|
-
{
|
181
|
-
const isPredicate =
|
182
|
-
getSuffix(first[VALUE]) === PREDICATE_SUFFIX
|
183
|
-
if (isPredicate) {
|
184
|
-
// PRED ASSIGMENT
|
185
|
-
if (isKnown) T[TYPE_PROP][1] = PREDICATE
|
186
|
-
T[RETURNS] = [ATOM, PREDICATE]
|
187
|
-
}
|
188
|
-
}
|
189
|
-
break
|
190
|
-
}
|
191
147
|
}
|
192
148
|
})
|
193
149
|
}
|
@@ -208,7 +164,7 @@ export const typeCheck = (ast) => {
|
|
208
164
|
)
|
209
165
|
} else {
|
210
166
|
const name = rest[0][VALUE]
|
211
|
-
const resolveRetunType = (returns, rem, prop
|
167
|
+
const resolveRetunType = (returns, rem, prop) => {
|
212
168
|
if (returns[TYPE] === ATOM) {
|
213
169
|
// ATOM ASSIGMENT
|
214
170
|
env[name][STATS][prop][0] = ATOM
|
@@ -221,15 +177,8 @@ export const typeCheck = (ast) => {
|
|
221
177
|
if (re[0][TYPE] === ATOM || re[1][TYPE] === ATOM) {
|
222
178
|
// ATOM ASSIGMENT
|
223
179
|
env[name][STATS][prop][0] = ATOM
|
180
|
+
// TODO maybe delete this
|
224
181
|
env[name][STATS][RETURNS][0] = ATOM
|
225
|
-
if (
|
226
|
-
getSuffix(re[0][VALUE]) === PREDICATE_SUFFIX ||
|
227
|
-
getSuffix(re[1][VALUE]) === PREDICATE_SUFFIX
|
228
|
-
) {
|
229
|
-
// ATOM ASSIGMENT PREDICATE ASSIGMENT
|
230
|
-
env[name][STATS][TYPE_PROP][1] = [PREDICATE]
|
231
|
-
env[name][STATS][RETURNS] = [ATOM, PREDICATE]
|
232
|
-
}
|
233
182
|
} else if (
|
234
183
|
!isLeaf(re[0]) &&
|
235
184
|
env[re[0][0][VALUE]] &&
|
@@ -288,102 +237,47 @@ export const typeCheck = (ast) => {
|
|
288
237
|
}
|
289
238
|
break
|
290
239
|
default:
|
291
|
-
if (env[returns[VALUE]])
|
292
|
-
if (
|
293
|
-
env[returns[VALUE]][STATS][TYPE_PROP][0] === APPLY
|
294
|
-
) {
|
295
|
-
if (returns[VALUE] === KEYWORDS.CALL_FUNCTION) {
|
296
|
-
if (isLeaf(rest.at(-1).at(-1).at(-1))) {
|
297
|
-
const fnName = rest.at(-1).at(-1).at(-1)[VALUE]
|
298
|
-
const fn = env[fnName]
|
299
|
-
if (
|
300
|
-
!isPredicate &&
|
301
|
-
fn[STATS][RETURNS][1] === PREDICATE
|
302
|
-
) {
|
303
|
-
warningStack.add(
|
304
|
-
`${name} is assigned to ${fnName} which ends in (${PREDICATE_SUFFIX}) so ${name} must also end in (${PREDICATE_SUFFIX}) (check #24)`
|
305
|
-
)
|
306
|
-
} else if (
|
307
|
-
isPredicate &&
|
308
|
-
fn[STATS][RETURNS][1] !== PREDICATE
|
309
|
-
) {
|
310
|
-
warningStack.add(
|
311
|
-
`${name} ends in (${PREDICATE_SUFFIX}) and is expected to return (Predicate) but it doesn't (check #25)`
|
312
|
-
)
|
313
|
-
}
|
314
|
-
env[name][STATS][TYPE_PROP][0] =
|
315
|
-
fn[STATS][RETURNS][0]
|
316
|
-
env[name][STATS][RETURNS][1] =
|
317
|
-
fn[STATS][RETURNS][1]
|
318
|
-
} else {
|
319
|
-
const [returns, rem] = drillReturnType(
|
320
|
-
rest.at(-1).at(-1).at(-1),
|
321
|
-
(returns) =>
|
322
|
-
returns[VALUE] === KEYWORDS.CALL_FUNCTION
|
323
|
-
)
|
324
|
-
resolveRetunType(
|
325
|
-
returns,
|
326
|
-
rem,
|
327
|
-
TYPE_PROP,
|
328
|
-
isPredicate
|
329
|
-
)
|
330
|
-
}
|
331
|
-
}
|
332
|
-
// ALWAYS APPLY
|
333
|
-
// rest.at(-1)[0][TYPE] === APPLY
|
334
|
-
// Here is upon application to store the result in the variable
|
335
|
-
if (env[name][STATS][TYPE_PROP][0] === UNKNOWN)
|
336
|
-
stack.unshift(() => {
|
337
|
-
env[name][STATS][TYPE_PROP][0] =
|
338
|
-
env[returns[VALUE]][STATS][RETURNS][0]
|
339
|
-
env[name][STATS][TYPE_PROP][1] =
|
340
|
-
env[returns[VALUE]][STATS][RETURNS][1]
|
341
|
-
})
|
342
|
-
env[name][STATS][RETURNS] =
|
343
|
-
env[returns[VALUE]][STATS][RETURNS]
|
344
|
-
} else {
|
345
|
-
// Enclose function with it's own scope
|
346
|
-
const args = env[name][STATS][ARGUMENTS] ?? []
|
347
|
-
const fnScope = args.length
|
348
|
-
? Object.create(env)
|
349
|
-
: env
|
350
|
-
for (const arg of args)
|
351
|
-
fnScope[arg[STATS][SIGNATURE]] = arg
|
352
|
-
// RETURN TYPE OF FUNCTION ASSIGGMENT
|
353
|
-
fnScope[name][STATS][RETURNS] =
|
354
|
-
fnScope[returns[VALUE]][STATS][RETURNS]
|
355
|
-
// assign(env[name][STATS][RETURNS],env[returns[VALUE]][STATS][RETURNS], 0)
|
356
|
-
fnScope[name][STATS][RETURNS][0] =
|
357
|
-
fnScope[returns[VALUE]][STATS][TYPE_PROP][0]
|
358
|
-
}
|
359
|
-
} else {
|
240
|
+
if (!env[returns[VALUE]])
|
360
241
|
env[name][STATS][RETURNS] = [UNKNOWN]
|
361
|
-
|
242
|
+
// env[name][STATS][RETURNS] = APPLY
|
243
|
+
else if (
|
244
|
+
env[returns[VALUE]][STATS][TYPE_PROP][0] === APPLY
|
245
|
+
) {
|
246
|
+
// TODO This seems to be able to be deleted
|
247
|
+
// FOR NOT IT CAN BE
|
248
|
+
// if (returns[VALUE] === KEYWORDS.CALL_FUNCTION) {
|
249
|
+
// if (isLeaf(rest.at(-1).at(-1).at(-1))) {
|
250
|
+
// const fnName = rest.at(-1).at(-1).at(-1)[VALUE]
|
251
|
+
// const fn = env[fnName]
|
252
|
+
// env[name][STATS][TYPE_PROP][0] =
|
253
|
+
// fn[STATS][RETURNS][0]
|
254
|
+
// } else {
|
255
|
+
// const [returns, rem] = drillReturnType(
|
256
|
+
// rest.at(-1).at(-1).at(-1),
|
257
|
+
// (returns) =>
|
258
|
+
// returns[VALUE] === KEYWORDS.CALL_FUNCTION
|
259
|
+
// )
|
260
|
+
// resolveRetunType(returns, rem, TYPE_PROP)
|
261
|
+
// }
|
262
|
+
// }
|
263
|
+
|
264
|
+
// ALWAYS APPLY
|
265
|
+
// rest.at(-1)[0][TYPE] === APPLY
|
266
|
+
// Here is upon application to store the result in the variable
|
267
|
+
if (env[name][STATS][TYPE_PROP][0] === UNKNOWN)
|
268
|
+
stack.unshift(() => {
|
269
|
+
env[name][STATS][TYPE_PROP][0] =
|
270
|
+
env[returns[VALUE]][STATS][RETURNS][0]
|
271
|
+
// this seems to be able to be deleted
|
272
|
+
// env[name][STATS][TYPE_PROP][1] =
|
273
|
+
// env[returns[VALUE]][STATS][RETURNS][1]
|
274
|
+
})
|
275
|
+
env[name][STATS][RETURNS] =
|
276
|
+
env[returns[VALUE]][STATS][RETURNS]
|
362
277
|
}
|
363
278
|
break
|
364
279
|
}
|
365
280
|
}
|
366
|
-
if (
|
367
|
-
isPredicate &&
|
368
|
-
env[name][STATS][prop][0] !== UNKNOWN &&
|
369
|
-
env[name][STATS][RETURNS][1] !== PREDICATE
|
370
|
-
) {
|
371
|
-
warningStack.add(
|
372
|
-
`${name} ends in (${PREDICATE_SUFFIX}) and is expected to return (Predicate) but it doesn't (check #7)`
|
373
|
-
)
|
374
|
-
} else if (
|
375
|
-
!isPredicate &&
|
376
|
-
env[name][STATS][RETURNS][1] === PREDICATE
|
377
|
-
) {
|
378
|
-
warningStack.add(
|
379
|
-
`${name} should end in (${PREDICATE_SUFFIX}) because it return (Predicate) (try adding ? at the end of the lambda name) (check #8)`
|
380
|
-
)
|
381
|
-
}
|
382
|
-
if (isPredicate) {
|
383
|
-
// ATOM ASSIGMENT PREDICATE ASSIGMENT
|
384
|
-
env[name][STATS][prop] = [ATOM, PREDICATE]
|
385
|
-
env[name][STATS][RETURNS] = [ATOM, PREDICATE]
|
386
|
-
}
|
387
281
|
}
|
388
282
|
const checkReturnType = () => {
|
389
283
|
const last = rest.at(-1).at(-1)
|
@@ -392,8 +286,7 @@ export const typeCheck = (ast) => {
|
|
392
286
|
: last
|
393
287
|
const rem = hasBlock(body) ? body.at(-1) : body
|
394
288
|
const returns = isLeaf(rem) ? rem : rem[0]
|
395
|
-
|
396
|
-
resolveRetunType(returns, rem, RETURNS, isPredicate)
|
289
|
+
resolveRetunType(returns, rem, RETURNS)
|
397
290
|
}
|
398
291
|
const rightHand = rest.at(-1)
|
399
292
|
if (
|
@@ -432,7 +325,6 @@ export const typeCheck = (ast) => {
|
|
432
325
|
}
|
433
326
|
} else {
|
434
327
|
const isL = isLeaf(rightHand)
|
435
|
-
// if (!(name in env)) {
|
436
328
|
if (isL && rightHand[TYPE] === WORD) {
|
437
329
|
// TODO make sure this prevents the assigment all together
|
438
330
|
if (env[rest[1][VALUE]] === undefined) {
|
@@ -444,30 +336,7 @@ export const typeCheck = (ast) => {
|
|
444
336
|
env[name] = SPECIAL_FORMS_SET.has(rest[1][VALUE])
|
445
337
|
? structuredClone(env[rest[1][VALUE]])
|
446
338
|
: env[rest[1][VALUE]]
|
447
|
-
|
448
|
-
if (
|
449
|
-
getSuffix(rest[1][VALUE]) === PREDICATE_SUFFIX &&
|
450
|
-
getSuffix(name) !== PREDICATE_SUFFIX
|
451
|
-
)
|
452
|
-
warningStack.add(
|
453
|
-
`${name} is assigned to ${rest[1][VALUE]} which ends in (${PREDICATE_SUFFIX}) so ${name} must also end in (${PREDICATE_SUFFIX}) (check #17)`
|
454
|
-
)
|
455
|
-
else if (
|
456
|
-
getSuffix(rest[1][VALUE]) === MUTATION_SUFFIX &&
|
457
|
-
getSuffix(name) !== MUTATION_SUFFIX
|
458
|
-
)
|
459
|
-
warningStack.add(
|
460
|
-
`${name} is assigned to ${rest[1][VALUE]} which ends in (${MUTATION_SUFFIX}) so ${name} must also end in (${MUTATION_SUFFIX}) (check #18)`
|
461
|
-
)
|
462
339
|
} else if (isL && rightHand[TYPE] === ATOM) {
|
463
|
-
const isPredicate = getSuffix(name) === PREDICATE_SUFFIX
|
464
|
-
// This never happens
|
465
|
-
// if (
|
466
|
-
// isPredicate &&
|
467
|
-
// right[VALUE] !== TRUE &&
|
468
|
-
// right[VALUE] !== FALSE
|
469
|
-
// ) {
|
470
|
-
// }
|
471
340
|
// DECLARATION of ATOM
|
472
341
|
env[name] = {
|
473
342
|
[STATS]: {
|
@@ -479,31 +348,8 @@ export const typeCheck = (ast) => {
|
|
479
348
|
[RETURNS]: [ATOM]
|
480
349
|
}
|
481
350
|
}
|
482
|
-
|
483
|
-
if (rightHand[VALUE] !== TRUE && rightHand !== FALSE) {
|
484
|
-
warningStack.add(
|
485
|
-
`${name} ends in (${PREDICATE_SUFFIX}) and is expected to return (Predicate) but the (Atom) value is neither ${TRUE} or ${FALSE} (${stringifyArgs(
|
486
|
-
exp
|
487
|
-
)}) (check #14)`
|
488
|
-
)
|
489
|
-
} else {
|
490
|
-
// PREDICATE ASSIGMENT
|
491
|
-
env[name][STATS][TYPE_PROP][1] = PREDICATE
|
492
|
-
env[name][STATS][RETURNS] = [ATOM, PREDICATE]
|
493
|
-
}
|
494
|
-
}
|
495
|
-
} else {
|
351
|
+
} else if (rightHand[0]) {
|
496
352
|
const right = rightHand[0]
|
497
|
-
const isPredicate = getSuffix(name) === PREDICATE_SUFFIX
|
498
|
-
if (
|
499
|
-
right &&
|
500
|
-
right[VALUE] &&
|
501
|
-
getSuffix(right[VALUE]) === PREDICATE_SUFFIX &&
|
502
|
-
!isPredicate
|
503
|
-
)
|
504
|
-
warningStack.add(
|
505
|
-
`${name} is assigned to ${right[VALUE]} which ends in (${PREDICATE_SUFFIX}) so ${name} must also end in (${PREDICATE_SUFFIX}) (check #19)`
|
506
|
-
)
|
507
353
|
//DECLARATION
|
508
354
|
env[name] = {
|
509
355
|
[STATS]: {
|
@@ -514,71 +360,27 @@ export const typeCheck = (ast) => {
|
|
514
360
|
[TYPE_PROP]: [
|
515
361
|
isL
|
516
362
|
? right[TYPE]
|
517
|
-
: env[right
|
518
|
-
|
363
|
+
: env[right[VALUE]] == undefined
|
364
|
+
? UNKNOWN
|
365
|
+
: env[right[VALUE]][STATS][RETURNS][0]
|
519
366
|
],
|
520
367
|
[RETURNS]: [UNKNOWN]
|
521
368
|
}
|
522
369
|
}
|
523
|
-
if (
|
524
|
-
|
525
|
-
|
526
|
-
env[name][STATS][RETURNS] = [ATOM, PREDICATE]
|
527
|
-
}
|
528
|
-
if (right && right[VALUE]) {
|
529
|
-
if (right[VALUE] === KEYWORDS.CALL_FUNCTION) {
|
530
|
-
if (isLeaf(rightHand.at(-1))) {
|
531
|
-
const fnName = rightHand.at(-1)[VALUE]
|
532
|
-
const fn = env[fnName]
|
533
|
-
if (
|
534
|
-
!isPredicate &&
|
535
|
-
fn[STATS][RETURNS][1] === PREDICATE
|
536
|
-
) {
|
537
|
-
warningStack.add(
|
538
|
-
`${name} is assigned to ${fnName} which ends in (${PREDICATE_SUFFIX}) so ${name} must also end in (${PREDICATE_SUFFIX}) (check #24)`
|
539
|
-
)
|
540
|
-
} else if (
|
541
|
-
isPredicate &&
|
542
|
-
fn[STATS][RETURNS][1] !== PREDICATE
|
543
|
-
) {
|
544
|
-
warningStack.add(
|
545
|
-
`${name} ends in (${PREDICATE_SUFFIX}) and is expected to return (Predicate) but it doesn't (check #25)`
|
546
|
-
)
|
547
|
-
}
|
548
|
-
// FB assigment
|
549
|
-
env[name][STATS][TYPE_PROP] = fn[STATS][RETURNS]
|
550
|
-
env[name][STATS][RETURNS] = fn[STATS][RETURNS]
|
551
|
-
} else {
|
552
|
-
const body = rightHand.at(-1).at(-1)
|
553
|
-
const rem = hasBlock(body) ? body.at(-1) : body
|
554
|
-
const returns = isLeaf(rem) ? rem : rem[0]
|
555
|
-
resolveRetunType(returns, rem, TYPE_PROP, isPredicate)
|
556
|
-
}
|
557
|
-
} else {
|
558
|
-
const body = rightHand
|
370
|
+
if (right[VALUE] === KEYWORDS.CALL_FUNCTION) {
|
371
|
+
if (!isLeaf(rightHand.at(-1))) {
|
372
|
+
const body = rightHand.at(-1).at(-1)
|
559
373
|
const rem = hasBlock(body) ? body.at(-1) : body
|
560
374
|
const returns = isLeaf(rem) ? rem : rem[0]
|
561
|
-
resolveRetunType(returns, rem, TYPE_PROP
|
562
|
-
}
|
563
|
-
if (env[right[VALUE]]?.[STATS]?.[RETURNS]?.[1]) {
|
564
|
-
if (
|
565
|
-
env[right[VALUE]][STATS][RETURNS][1] === PREDICATE &&
|
566
|
-
!isPredicate
|
567
|
-
) {
|
568
|
-
warningStack.add(
|
569
|
-
`${name} is assigned to the result of a (${toTypeNames(
|
570
|
-
PREDICATE
|
571
|
-
)}) so ${name} must end in (${PREDICATE_SUFFIX}) (check #23)`
|
572
|
-
)
|
573
|
-
}
|
574
|
-
|
575
|
-
// FN assigment
|
576
|
-
env[name][STATS][RETURNS] =
|
577
|
-
env[right[VALUE]][STATS][RETURNS]
|
375
|
+
resolveRetunType(returns, rem, TYPE_PROP)
|
578
376
|
}
|
377
|
+
} else {
|
378
|
+
const body = rightHand
|
379
|
+
const rem = hasBlock(body) ? body.at(-1) : body
|
380
|
+
const returns = isLeaf(rem) ? rem : rem[0]
|
381
|
+
resolveRetunType(returns, rem, TYPE_PROP)
|
579
382
|
}
|
580
383
|
}
|
581
|
-
// }
|
582
384
|
check(rightHand, env, scope)
|
583
385
|
}
|
584
386
|
Types.set(withScope(name, env), () => formatType(name, env))
|
@@ -629,99 +431,82 @@ export const typeCheck = (ast) => {
|
|
629
431
|
const ref = env[copy[SCOPE_NAME]]
|
630
432
|
if (ref) {
|
631
433
|
ref[STATS][ARGUMENTS][i] = copy[param[VALUE]]
|
632
|
-
|
633
|
-
|
634
|
-
|
434
|
+
const returns = deepLambdaReturn(
|
435
|
+
hasBlock(exp) ? exp.at(-1) : exp,
|
436
|
+
(result) => result[VALUE] !== KEYWORDS.IF
|
437
|
+
)
|
438
|
+
if (isLeaf(returns)) {
|
439
|
+
// TODO figure out what we do here
|
440
|
+
// this here is a variable WORD
|
441
|
+
// so return type of that function is that varible type
|
442
|
+
if (copy[returns[VALUE]])
|
443
|
+
ref[STATS][RETURNS] =
|
444
|
+
copy[returns[VALUE]][STATS][TYPE_PROP]
|
445
|
+
else
|
446
|
+
stack.push(() => {
|
447
|
+
if (copy[returns[VALUE]])
|
448
|
+
ref[STATS][RETURNS] =
|
449
|
+
copy[returns[VALUE]][STATS][TYPE_PROP]
|
450
|
+
})
|
635
451
|
} else {
|
636
|
-
const
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
copy[returns[VALUE]][STATS][TYPE_PROP]
|
652
|
-
})
|
653
|
-
} else {
|
654
|
-
const ret = returns[0]
|
655
|
-
switch (ret[VALUE]) {
|
656
|
-
case KEYWORDS.IF:
|
657
|
-
const re = returns.slice(2)
|
658
|
-
// If either is an ATOM then IF returns an ATOM
|
659
|
-
if (re[0][TYPE] === ATOM || re[1][TYPE] === ATOM) {
|
660
|
-
ref[STATS][RETURNS][0] = ATOM
|
661
|
-
// TODO check that both brancehs are predicates if one is
|
662
|
-
if (
|
663
|
-
getSuffix(re[0][VALUE]) === PREDICATE_SUFFIX ||
|
664
|
-
getSuffix(re[1][VALUE]) === PREDICATE_SUFFIX
|
665
|
-
) {
|
666
|
-
ref[STATS][TYPE_PROP][1] = PREDICATE
|
667
|
-
ref[STATS][RETURNS][1] = PREDICATE
|
668
|
-
}
|
669
|
-
} else {
|
670
|
-
const concequent = isLeaf(re[0])
|
671
|
-
? copy[re[0][VALUE]]
|
672
|
-
: copy[re[0][0][VALUE]]
|
673
|
-
const alternative = isLeaf(re[1])
|
674
|
-
? copy[re[1][VALUE]]
|
675
|
-
: copy[re[1][0][VALUE]]
|
452
|
+
const ret = returns[0]
|
453
|
+
switch (ret[VALUE]) {
|
454
|
+
case KEYWORDS.IF:
|
455
|
+
const re = returns.slice(2)
|
456
|
+
// If either is an ATOM then IF returns an ATOM
|
457
|
+
if (re[0][TYPE] === ATOM || re[1][TYPE] === ATOM) {
|
458
|
+
ref[STATS][RETURNS][0] = ATOM
|
459
|
+
// TODO check that both brancehs are predicates if one is
|
460
|
+
} else {
|
461
|
+
const concequent = isLeaf(re[0])
|
462
|
+
? copy[re[0][VALUE]]
|
463
|
+
: copy[re[0][0][VALUE]]
|
464
|
+
const alternative = isLeaf(re[1])
|
465
|
+
? copy[re[1][VALUE]]
|
466
|
+
: copy[re[1][0][VALUE]]
|
676
467
|
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
)
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
else
|
703
|
-
ref[STATS][RETURNS] =
|
704
|
-
concequent[STATS][TYPE_PROP]
|
705
|
-
}
|
468
|
+
// todo check if condition matches alternative
|
469
|
+
// TODO make this more simple - it's so many different things just because types are functions or not
|
470
|
+
// WHY not consiter making return types for everything
|
471
|
+
if (
|
472
|
+
concequent &&
|
473
|
+
concequent[STATS][TYPE_PROP][0] !== UNKNOWN
|
474
|
+
) {
|
475
|
+
if (concequent[STATS][TYPE_PROP][0] === APPLY)
|
476
|
+
ref[STATS][RETURNS] = concequent[STATS][RETURNS]
|
477
|
+
else
|
478
|
+
ref[STATS][RETURNS] = concequent[STATS][TYPE_PROP]
|
479
|
+
} else if (
|
480
|
+
alternative &&
|
481
|
+
alternative[STATS][TYPE_PROP][0] !== UNKNOWN
|
482
|
+
) {
|
483
|
+
if (alternative[STATS][TYPE_PROP][0] === APPLY)
|
484
|
+
ref[STATS][RETURNS] = alternative[STATS][RETURNS]
|
485
|
+
else
|
486
|
+
ref[STATS][RETURNS] =
|
487
|
+
alternative[STATS][TYPE_PROP]
|
488
|
+
} else if (concequent) {
|
489
|
+
if (concequent[STATS][TYPE_PROP][0] === APPLY)
|
490
|
+
ref[STATS][RETURNS] = concequent[STATS][RETURNS]
|
491
|
+
else
|
492
|
+
ref[STATS][RETURNS] = concequent[STATS][TYPE_PROP]
|
706
493
|
}
|
494
|
+
}
|
495
|
+
break
|
496
|
+
default:
|
497
|
+
if (copy[ret[VALUE]])
|
498
|
+
ref[STATS][RETURNS] = copy[ret[VALUE]][STATS][RETURNS]
|
499
|
+
else
|
500
|
+
stack.push(() => {
|
501
|
+
if (copy[ret[VALUE]])
|
502
|
+
ref[STATS][RETURNS] =
|
503
|
+
copy[ret[VALUE]][STATS][RETURNS]
|
504
|
+
})
|
707
505
|
|
708
|
-
|
709
|
-
default:
|
710
|
-
if (copy[ret[VALUE]])
|
711
|
-
ref[STATS][RETURNS] =
|
712
|
-
copy[ret[VALUE]][STATS][RETURNS]
|
713
|
-
else
|
714
|
-
stack.push(() => {
|
715
|
-
if (copy[ret[VALUE]])
|
716
|
-
ref[STATS][RETURNS] =
|
717
|
-
copy[ret[VALUE]][STATS][RETURNS]
|
718
|
-
})
|
719
|
-
|
720
|
-
break
|
721
|
-
}
|
506
|
+
break
|
722
507
|
}
|
723
|
-
// TODO overwrite return type check here
|
724
508
|
}
|
509
|
+
// TODO overwrite return type check here
|
725
510
|
}
|
726
511
|
}
|
727
512
|
check(rest.at(-1), copy, copy)
|
@@ -794,133 +579,67 @@ export const typeCheck = (ast) => {
|
|
794
579
|
const args = env[first[VALUE]][STATS][ARGUMENTS] ?? []
|
795
580
|
for (let i = 0; i < args.length; ++i) {
|
796
581
|
// type check
|
797
|
-
|
582
|
+
// TODO get rof pred type
|
583
|
+
// const PRED_TYPE = args[i][STATS][TYPE_PROP][1]
|
798
584
|
const MAIN_TYPE = args[i][STATS][TYPE_PROP][0]
|
799
|
-
if (
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
585
|
+
if (first[TYPE] === APPLY && isSpecial) {
|
586
|
+
if (
|
587
|
+
MAIN_TYPE === ATOM &&
|
588
|
+
PREDICATES_SET.has(first[VALUE]) &&
|
589
|
+
!isLeaf(rest[i]) &&
|
590
|
+
rest[i][0][TYPE] === APPLY &&
|
591
|
+
rest[i][0][VALUE] === KEYWORDS.CALL_FUNCTION
|
592
|
+
) {
|
593
|
+
if (isLeaf(rest[i].at(-1))) {
|
594
|
+
const fnName = rest[i].at(-1)[VALUE]
|
595
|
+
const fn = env[fnName]
|
596
|
+
if (fn && fn[STATS][RETURNS][0] !== MAIN_TYPE) {
|
597
|
+
errorStack.add(
|
598
|
+
`Incorrect type of argument (${i}) for (${
|
599
|
+
first[VALUE]
|
600
|
+
}). Expected (${toTypeNames(
|
601
|
+
MAIN_TYPE
|
602
|
+
)}) but got an (${toTypeNames(
|
603
|
+
fn[STATS][RETURNS][0]
|
604
|
+
)}) (${stringifyArgs(exp)}) (check #26)`
|
605
|
+
)
|
606
|
+
}
|
607
|
+
} else {
|
608
|
+
const body = rest[i].at(-1).at(-1)
|
609
|
+
const rem = hasBlock(body) ? body.at(-1) : body
|
610
|
+
const returns = isLeaf(rem) ? rem : rem[0]
|
611
|
+
if (returns[TYPE] === ATOM) {
|
612
|
+
if (MAIN_TYPE !== ATOM) {
|
807
613
|
errorStack.add(
|
808
|
-
`Incorrect type of argument
|
614
|
+
`Incorrect type of argument ${i} for (${
|
809
615
|
first[VALUE]
|
810
616
|
}). Expected (${toTypeNames(
|
811
617
|
MAIN_TYPE
|
812
618
|
)}) but got an (${toTypeNames(
|
813
|
-
|
814
|
-
)})
|
619
|
+
ATOM
|
620
|
+
)}) (${stringifyArgs(exp)}) (check #27)`
|
815
621
|
)
|
816
622
|
}
|
817
|
-
|
818
|
-
errorStack.add(
|
819
|
-
`Incorrect type of argument (${i}) for (${
|
820
|
-
first[VALUE]
|
821
|
-
}). Expected (${toTypeNames(
|
822
|
-
PRED_TYPE
|
823
|
-
)}) but got an (${toTypeNames(
|
824
|
-
fn[STATS][RETURNS][1] ?? fn[STATS][RETURNS][0]
|
825
|
-
)}) which is neither ${TRUE} or ${FALSE} (${stringifyArgs(
|
826
|
-
exp
|
827
|
-
)}) (check #27)`
|
828
|
-
)
|
829
|
-
}
|
830
|
-
} else {
|
831
|
-
const body = rest[i].at(-1).at(-1)
|
832
|
-
const rem = hasBlock(body) ? body.at(-1) : body
|
833
|
-
const returns = isLeaf(rem) ? rem : rem[0]
|
834
|
-
if (returns[TYPE] === ATOM) {
|
835
|
-
if (MAIN_TYPE !== ATOM) {
|
836
|
-
errorStack.add(
|
837
|
-
`Incorrect type of argument ${i} for (${
|
838
|
-
first[VALUE]
|
839
|
-
}). Expected (${toTypeNames(
|
840
|
-
MAIN_TYPE
|
841
|
-
)}) but got an (${toTypeNames(
|
842
|
-
ATOM
|
843
|
-
)}) (${stringifyArgs(exp)}) (check #27)`
|
844
|
-
)
|
845
|
-
}
|
846
|
-
if (
|
847
|
-
PRED_TYPE &&
|
848
|
-
PRED_TYPE === PREDICATE &&
|
849
|
-
returns[VALUE] !== TRUE &&
|
850
|
-
returns[VALUE] !== FALSE
|
851
|
-
) {
|
852
|
-
errorStack.add(
|
853
|
-
`Incorrect type of argument ${i} for (${
|
854
|
-
first[VALUE]
|
855
|
-
}). Expected (${toTypeNames(
|
856
|
-
PRED_TYPE
|
857
|
-
)}) but got an (${toTypeNames(
|
858
|
-
ATOM
|
859
|
-
)}) which is neither ${TRUE} or ${FALSE} (${stringifyArgs(
|
860
|
-
exp
|
861
|
-
)}) (check #27)`
|
862
|
-
)
|
863
|
-
}
|
864
|
-
} else if (env[returns[VALUE]]) {
|
865
|
-
if (
|
866
|
-
MAIN_TYPE !==
|
867
|
-
env[returns[VALUE]][STATS][RETURNS][0]
|
868
|
-
) {
|
869
|
-
errorStack.add(
|
870
|
-
`Incorrect type of argument ${i} for (${
|
871
|
-
first[VALUE]
|
872
|
-
}). Expected (${toTypeNames(
|
873
|
-
MAIN_TYPE
|
874
|
-
)}) but got (${toTypeNames(
|
875
|
-
env[returns[VALUE]][STATS][TYPE_PROP]
|
876
|
-
)}) (${stringifyArgs(exp)}) (check #29)`
|
877
|
-
)
|
878
|
-
}
|
879
|
-
// Never happens because there is only 1 sub type at the moment
|
880
|
-
// if (
|
881
|
-
// PRED_TYPE &&
|
882
|
-
// PRED_TYPE !==
|
883
|
-
// env[returns[VALUE]][STATS][RETURNS][1]
|
884
|
-
// ) {
|
885
|
-
// }
|
886
|
-
}
|
887
|
-
}
|
888
|
-
} else if (
|
889
|
-
PRED_TYPE &&
|
890
|
-
env[current[VALUE]] &&
|
891
|
-
env[current[VALUE]][STATS][RETURNS][1] !== PRED_TYPE
|
892
|
-
) {
|
893
|
-
if (current[VALUE] === KEYWORDS.ANONYMOUS_FUNCTION) {
|
894
|
-
const body = rest[i].at(-1)
|
895
|
-
const rem = hasBlock(body) ? body.at(-1) : body
|
896
|
-
const returns = isLeaf(rem) ? rem : rem[0]
|
623
|
+
} else if (env[returns[VALUE]]) {
|
897
624
|
if (
|
898
|
-
env[returns[VALUE]]
|
899
|
-
root[returns[VALUE]][STATS][RETURNS][1] ===
|
900
|
-
PREDICATE
|
625
|
+
MAIN_TYPE !== env[returns[VALUE]][STATS][RETURNS][0]
|
901
626
|
) {
|
902
|
-
// TODO invert this logic
|
903
|
-
} else {
|
904
627
|
errorStack.add(
|
905
|
-
`Incorrect type of
|
628
|
+
`Incorrect type of argument ${i} for (${
|
906
629
|
first[VALUE]
|
907
630
|
}). Expected (${toTypeNames(
|
908
|
-
|
631
|
+
MAIN_TYPE
|
909
632
|
)}) but got (${toTypeNames(
|
910
|
-
env[
|
911
|
-
|
912
|
-
)}) (${stringifyArgs(exp)}) (check #21)`
|
633
|
+
env[returns[VALUE]][STATS][TYPE_PROP]
|
634
|
+
)}) (${stringifyArgs(exp)}) (check #29)`
|
913
635
|
)
|
914
636
|
}
|
915
637
|
}
|
916
638
|
}
|
917
639
|
}
|
918
|
-
}
|
919
|
-
if (first[TYPE] === APPLY && isSpecial) {
|
920
640
|
const isCast = STATIC_TYPES_SET.has(first[VALUE])
|
921
641
|
const expectedArgs = env[first[VALUE]][STATS][ARGUMENTS]
|
922
642
|
for (let i = 0; i < rest.length; ++i) {
|
923
|
-
const PRED_TYPE = args[i][STATS][TYPE_PROP][1]
|
924
643
|
const MAIN_TYPE = expectedArgs[i][STATS][TYPE_PROP][0]
|
925
644
|
if (MAIN_TYPE === UNKNOWN && !isCast) continue
|
926
645
|
if (!isLeaf(rest[i])) {
|
@@ -967,32 +686,18 @@ export const typeCheck = (ast) => {
|
|
967
686
|
env[CAR][STATS][TYPE_PROP][0]
|
968
687
|
)}) (${stringifyArgs(exp)}) (check #3)`
|
969
688
|
)
|
970
|
-
}
|
971
|
-
|
972
|
-
env[CAR][STATS][RETURNS][1] !== PRED_TYPE &&
|
973
|
-
!isCast
|
974
|
-
)
|
975
|
-
errorStack.add(
|
976
|
-
`Incorrect type of argument (${i}) for special form (${
|
977
|
-
first[VALUE]
|
978
|
-
}). Expected (${toTypeNames(
|
979
|
-
PRED_TYPE
|
980
|
-
)}) but got (${toTypeNames(
|
981
|
-
env[CAR][STATS][RETURNS][1] ??
|
982
|
-
env[CAR][STATS][TYPE_PROP][0]
|
983
|
-
)}) (${stringifyArgs(exp)}) (check #6)`
|
984
|
-
)
|
985
|
-
} else if (env[rest[i][VALUE]]) {
|
689
|
+
}
|
690
|
+
} else if (env[CAR]) {
|
986
691
|
if (isCast) {
|
987
692
|
// CAST assigment
|
988
|
-
env[rest[i][VALUE]][STATS][TYPE_PROP] =
|
989
|
-
root[first[VALUE]][STATS][RETURNS]
|
990
|
-
|
991
|
-
|
693
|
+
env[rest[i][VALUE]][STATS][TYPE_PROP][0] =
|
694
|
+
root[first[VALUE]][STATS][RETURNS][0]
|
695
|
+
|
696
|
+
// root[first[VALUE]][STATS][RETURNS] =
|
697
|
+
// root[first[VALUE]][STATS][RETURNS]
|
992
698
|
} else {
|
993
699
|
// VALUE assigment
|
994
|
-
env[
|
995
|
-
MAIN_TYPE
|
700
|
+
env[CAR][STATS][TYPE_PROP][0] = MAIN_TYPE
|
996
701
|
}
|
997
702
|
}
|
998
703
|
}
|
@@ -1009,22 +714,6 @@ export const typeCheck = (ast) => {
|
|
1009
714
|
)}) (${stringifyArgs(exp)}) (check #2)`
|
1010
715
|
)
|
1011
716
|
}
|
1012
|
-
if (
|
1013
|
-
PRED_TYPE === PREDICATE &&
|
1014
|
-
rest[i][VALUE] !== TRUE &&
|
1015
|
-
rest[i][VALUE] !== FALSE
|
1016
|
-
) {
|
1017
|
-
errorStack.add(
|
1018
|
-
`Incorrect type of argument (${i}) for special form (${
|
1019
|
-
first[VALUE]
|
1020
|
-
}). Expected (${toTypeNames(
|
1021
|
-
PRED_TYPE
|
1022
|
-
)}) but got (${toTypeNames(
|
1023
|
-
rest[i][VALUE]
|
1024
|
-
)}) (${stringifyArgs(exp)}) (check #5)`
|
1025
|
-
)
|
1026
|
-
}
|
1027
|
-
|
1028
717
|
break
|
1029
718
|
}
|
1030
719
|
}
|
@@ -1051,22 +740,6 @@ export const typeCheck = (ast) => {
|
|
1051
740
|
exp
|
1052
741
|
)}) (check #10)`
|
1053
742
|
)
|
1054
|
-
} else if (
|
1055
|
-
T === ATOM &&
|
1056
|
-
args[i][STATS][RETURNS][0] === ATOM &&
|
1057
|
-
args[i][STATS][RETURNS][1] === PREDICATE &&
|
1058
|
-
rest[i][VALUE] !== TRUE &&
|
1059
|
-
rest[i][VALUE] !== FALSE
|
1060
|
-
) {
|
1061
|
-
errorStack.add(
|
1062
|
-
`Incorrect type of arguments ${i} for (${
|
1063
|
-
first[VALUE]
|
1064
|
-
}). Expected (${toTypeNames(
|
1065
|
-
args[i][STATS][RETURNS][1]
|
1066
|
-
)}) but got (${toTypeNames(T)}) (${stringifyArgs(
|
1067
|
-
exp
|
1068
|
-
)}) (check #13)`
|
1069
|
-
)
|
1070
743
|
} else if (
|
1071
744
|
T === APPLY &&
|
1072
745
|
args[i][STATS][TYPE_PROP][0] !== UNKNOWN &&
|
@@ -1092,6 +765,7 @@ export const typeCheck = (ast) => {
|
|
1092
765
|
}
|
1093
766
|
}
|
1094
767
|
if (
|
768
|
+
T === COLLECTION &&
|
1095
769
|
env[rest[i][VALUE]] &&
|
1096
770
|
env[rest[i][VALUE]][STATS][TYPE_PROP][0] !== UNKNOWN &&
|
1097
771
|
args[i][STATS][TYPE_PROP][0] !== UNKNOWN &&
|