fez-lisp 1.5.95 → 1.5.98
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 +696 -687
- package/src/evaluator.js +1 -3
- package/src/types.js +56 -12
package/src/check.js
CHANGED
@@ -33,7 +33,8 @@ import {
|
|
33
33
|
COLLECTION,
|
34
34
|
ANY,
|
35
35
|
formatType,
|
36
|
-
ANONYMOUS_FUNCTION_TYPE_PREFIX
|
36
|
+
ANONYMOUS_FUNCTION_TYPE_PREFIX,
|
37
|
+
validateLambda
|
37
38
|
} from './types.js'
|
38
39
|
import {
|
39
40
|
getSuffix,
|
@@ -65,28 +66,32 @@ const deepLambdaReturn = (rest, condition) => {
|
|
65
66
|
const rem = hasBlock(body) ? body.at(-1) : body
|
66
67
|
return condition(rem) ? rem : deepLambdaReturn(rem, condition)
|
67
68
|
}
|
69
|
+
export const castType = (stats, type) =>
|
70
|
+
(stats[TYPE_PROP][0] = type[RETURNS][0])
|
71
|
+
export const castReturn = (stats, type) =>
|
72
|
+
(stats[RETURNS][0] = type[RETURNS][0])
|
68
73
|
export const isTypeAbstraction = (stats) => stats[TYPE_PROP] === APPLY
|
69
74
|
export const setPropToAtom = (stats, prop) =>
|
70
75
|
(stats[prop][0] === UNKNOWN || stats[prop][0] === ANY) &&
|
71
76
|
(stats[prop][0] = ATOM)
|
72
77
|
export const setProp = (stats, prop, value) =>
|
73
|
-
stats[prop][0] === UNKNOWN &&
|
78
|
+
(stats[prop][0] === UNKNOWN || stats[prop][0] === ANY) &&
|
74
79
|
value[prop][0] !== UNKNOWN &&
|
75
80
|
(stats[prop][0] = value[prop][0])
|
76
81
|
export const setPropToReturn = (stats, prop, value) =>
|
77
|
-
stats[prop][0] === UNKNOWN &&
|
82
|
+
(stats[prop][0] === UNKNOWN || stats[prop][0] === ANY) &&
|
78
83
|
value[RETURNS][0] !== UNKNOWN &&
|
79
84
|
(stats[prop][0] = value[RETURNS][0])
|
80
85
|
export const setPropToReturnRef = (stats, prop, value) =>
|
81
|
-
stats[prop][0] === UNKNOWN &&
|
86
|
+
(stats[prop][0] === UNKNOWN || stats[prop][0] === ANY) &&
|
82
87
|
value[RETURNS][0] !== UNKNOWN &&
|
83
88
|
(stats[prop] = value[RETURNS])
|
84
89
|
export const setPropToType = (stats, prop, value) =>
|
85
|
-
stats[prop][0] === UNKNOWN &&
|
90
|
+
(stats[prop][0] === UNKNOWN || stats[prop][0] === ANY) &&
|
86
91
|
value[UNKNOWN][0] !== UNKNOWN &&
|
87
92
|
(stats[prop][0] = value[UNKNOWN][0])
|
88
93
|
export const setPropToTypeRef = (stats, prop, value) =>
|
89
|
-
stats[prop][0] === UNKNOWN &&
|
94
|
+
(stats[prop][0] === UNKNOWN || stats[prop][0] === ANY) &&
|
90
95
|
value[TYPE_PROP][0] !== UNKNOWN &&
|
91
96
|
(stats[prop] = value[TYPE_PROP])
|
92
97
|
export const setReturnToAtom = (stats) =>
|
@@ -137,13 +142,12 @@ export const compareReturns = (a, b) =>
|
|
137
142
|
isAnyReturn(a) || isAnyReturn(b) || a[RETURNS][0] === b[RETURNS][0]
|
138
143
|
export const compareTypeWithReturn = (a, b) =>
|
139
144
|
isAnyType(a) || isAnyReturn(b) || a[TYPE_PROP][0] === b[RETURNS][0]
|
140
|
-
|
141
|
-
const checkPredicateName = (exp, rest, warningStack) => {
|
145
|
+
const checkPredicateName = (exp, rest, errors) => {
|
142
146
|
if (getSuffix(rest[0][VALUE]) === PREDICATE_SUFFIX) {
|
143
147
|
const last = rest.at(-1)
|
144
148
|
if (isLeaf(last)) {
|
145
149
|
if (last[TYPE] === ATOM && last[VALUE] !== TRUE && last[VALUE] !== FALSE)
|
146
|
-
|
150
|
+
errors.add(
|
147
151
|
`Assigning predicate (ending in ?) variable (${
|
148
152
|
rest[0][VALUE]
|
149
153
|
}) to an (${
|
@@ -155,7 +159,7 @@ const checkPredicateName = (exp, rest, warningStack) => {
|
|
155
159
|
getSuffix(last[VALUE]) !== PREDICATE_SUFFIX &&
|
156
160
|
!PREDICATES_OUTPUT_SET.has(last[VALUE])
|
157
161
|
)
|
158
|
-
|
162
|
+
errors.add(
|
159
163
|
`Assigning predicate (ending in ?) variable (${
|
160
164
|
rest[0][VALUE]
|
161
165
|
}) to another variable which is not a predicate (also ending in ?) (${stringifyArgs(
|
@@ -173,7 +177,7 @@ const checkPredicateName = (exp, rest, warningStack) => {
|
|
173
177
|
getSuffix(application[VALUE]) !== PREDICATE_SUFFIX &&
|
174
178
|
!PREDICATES_OUTPUT_SET.has(application[VALUE])
|
175
179
|
)
|
176
|
-
|
180
|
+
errors.add(
|
177
181
|
`Assigning predicate (ending in ?) variable (${
|
178
182
|
application[VALUE]
|
179
183
|
}) to another variable which is not a predicate (also ending in ?) (${stringifyArgs(
|
@@ -185,7 +189,7 @@ const checkPredicateName = (exp, rest, warningStack) => {
|
|
185
189
|
}
|
186
190
|
}
|
187
191
|
}
|
188
|
-
const checkPredicateNameDeep = (name, exp, rest, returns,
|
192
|
+
const checkPredicateNameDeep = (name, exp, rest, returns, errors) => {
|
189
193
|
if (returns[VALUE] === KEYWORDS.CALL_FUNCTION) {
|
190
194
|
const fn = rest.at(-1).at(-1).at(-1)
|
191
195
|
checkPredicateName(
|
@@ -196,15 +200,12 @@ const checkPredicateNameDeep = (name, exp, rest, returns, warningStack) => {
|
|
196
200
|
? fn // when apply is a word (let x? (lambda (apply [] array:empty!)))
|
197
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! [])))))
|
198
202
|
],
|
199
|
-
|
203
|
+
errors
|
200
204
|
)
|
201
205
|
} else {
|
202
|
-
checkPredicateName(exp, [[WORD, name], returns],
|
206
|
+
checkPredicateName(exp, [[WORD, name], returns], errors)
|
203
207
|
}
|
204
208
|
}
|
205
|
-
// const assign = (a, b, i) => {
|
206
|
-
// a[i] = b[i]
|
207
|
-
// }
|
208
209
|
const fillUknownArgs = (n) =>
|
209
210
|
Array.from({ length: n })
|
210
211
|
.fill(null)
|
@@ -233,13 +234,180 @@ const withScope = (name, scope) => {
|
|
233
234
|
const chain = getScopeNames(scope)
|
234
235
|
return `${chain.length === 1 ? '; ' : ''}${chain.join(' ')} ${name}`
|
235
236
|
}
|
237
|
+
|
238
|
+
const ifExpression = ({ re, env, ref }) => {
|
239
|
+
if (re[0][TYPE] === ATOM || re[1][TYPE] === ATOM) setReturnToAtom(ref[STATS])
|
240
|
+
// TODO check that both brancehs are predicates if one is
|
241
|
+
else {
|
242
|
+
const concequent = isLeaf(re[0]) ? env[re[0][VALUE]] : env[re[0][0][VALUE]]
|
243
|
+
const alternative = isLeaf(re[1]) ? env[re[1][VALUE]] : env[re[1][0][VALUE]]
|
244
|
+
// todo check if condition matches alternative
|
245
|
+
// TODO make this more simple - it's so many different things just because types are functions or not
|
246
|
+
// WHY not consiter making return types for everything
|
247
|
+
if (concequent && getType(concequent[STATS]) !== UNKNOWN) {
|
248
|
+
if (getType(concequent[STATS]) === APPLY)
|
249
|
+
setReturnRef(ref[STATS], concequent[STATS])
|
250
|
+
else ref[STATS][RETURNS] = concequent[STATS][TYPE_PROP]
|
251
|
+
} else if (alternative && isUnknownType(alternative[STATS])) {
|
252
|
+
if (getType(alternative[STATS]) === APPLY)
|
253
|
+
setReturnRef(ref[STATS], alternative[STATS])
|
254
|
+
else setReturnToTypeRef(ref[STATS], alternative[STATS])
|
255
|
+
} else if (concequent) {
|
256
|
+
if (getType(concequent[STATS]) === APPLY)
|
257
|
+
setReturnRef(ref[STATS], concequent[STATS])
|
258
|
+
else setReturnToTypeRef(ref[STATS], concequent[STATS])
|
259
|
+
}
|
260
|
+
}
|
261
|
+
}
|
262
|
+
const resolveIfAssigment = ({ rem, name, env, exp, errors, prop }) => {
|
263
|
+
const re = rem.slice(2)
|
264
|
+
checkPredicateName(
|
265
|
+
exp,
|
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
|
+
)
|
274
|
+
if (re[0][TYPE] === ATOM || re[1][TYPE] === ATOM)
|
275
|
+
// ATOM ASSIGMENT
|
276
|
+
setPropToAtom(env[name][STATS], prop)
|
277
|
+
else if (
|
278
|
+
!isLeaf(re[0]) &&
|
279
|
+
env[re[0][0][VALUE]] &&
|
280
|
+
!isUnknownReturn(env[re[0][0][VALUE]][STATS])
|
281
|
+
) {
|
282
|
+
setPropToReturnRef(env[name][STATS], prop, env[re[0][0][VALUE]][STATS])
|
283
|
+
if (re[0][0][TYPE] === APPLY) {
|
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
|
+
}
|
294
|
+
// env[name][STATS] = env[re[0][0][VALUE]][STATS]
|
295
|
+
} else if (
|
296
|
+
!isLeaf(re[1]) &&
|
297
|
+
env[re[1][0][VALUE]] &&
|
298
|
+
!isUnknownReturn(env[re[1][0][VALUE]][STATS])
|
299
|
+
) {
|
300
|
+
setPropToReturnRef(env[name][STATS], prop, env[re[1][0][VALUE]][STATS])
|
301
|
+
if (re[1][0][TYPE] === APPLY) {
|
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
|
+
}
|
312
|
+
} else if (env[re[0][VALUE]])
|
313
|
+
// ASSIGMENT
|
314
|
+
setPropRef(env[name][STATS], prop, env[re[0][VALUE]][STATS])
|
315
|
+
else if (env[re[1][VALUE]])
|
316
|
+
// ASSIGMENT
|
317
|
+
setPropRef(env[name][STATS], prop, env[re[1][VALUE]][STATS])
|
318
|
+
}
|
319
|
+
const resolveCondition = ({ rem, name, env, exp, errors }) => {
|
320
|
+
const ret = rem[0]
|
321
|
+
const re = rem.slice(2)
|
322
|
+
const ref = env[name]
|
323
|
+
checkPredicateName(
|
324
|
+
exp,
|
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
|
+
)
|
333
|
+
switch (ret[VALUE]) {
|
334
|
+
case KEYWORDS.IF:
|
335
|
+
ifExpression({ re, env, ref })
|
336
|
+
break
|
337
|
+
default:
|
338
|
+
if (env[ret[VALUE]]) setReturnRef(ref[STATS], env[ret[VALUE]][STATS])
|
339
|
+
else
|
340
|
+
stack.push(() => {
|
341
|
+
if (env[ret[VALUE]]) setReturnRef(ref[STATS], env[ret[VALUE]][STATS])
|
342
|
+
})
|
343
|
+
break
|
344
|
+
}
|
345
|
+
}
|
346
|
+
const resolveRetunType = ({
|
347
|
+
returns,
|
348
|
+
rem,
|
349
|
+
stack,
|
350
|
+
prop,
|
351
|
+
exp,
|
352
|
+
name,
|
353
|
+
errors,
|
354
|
+
env
|
355
|
+
}) => {
|
356
|
+
if (returns[TYPE] === ATOM) {
|
357
|
+
// ATOM ASSIGMENT
|
358
|
+
setPropToAtom(env[name][STATS], prop)
|
359
|
+
checkPredicateName(exp, [[WORD, name], returns], errors)
|
360
|
+
} else {
|
361
|
+
switch (returns[VALUE]) {
|
362
|
+
case KEYWORDS.IF:
|
363
|
+
resolveIfAssigment({ rem, name, env, exp, errors, prop })
|
364
|
+
break
|
365
|
+
default:
|
366
|
+
checkPredicateNameDeep(name, exp, exp.slice(1), returns, errors)
|
367
|
+
if (!env[returns[VALUE]]) return false
|
368
|
+
else if (getType(env[returns[VALUE]][STATS]) === APPLY) {
|
369
|
+
if (returns[TYPE] === WORD) setReturnToAbbstraction(env[name][STATS])
|
370
|
+
else {
|
371
|
+
// ALWAYS APPLY
|
372
|
+
// rest.at(-1)[0][TYPE] === APPLY
|
373
|
+
// Here is upon application to store the result in the variable
|
374
|
+
if (isUnknownType(env[name][STATS]))
|
375
|
+
stack.unshift(() => {
|
376
|
+
setTypeToReturn(env[name][STATS], env[returns[VALUE]][STATS])
|
377
|
+
// env[name][STATS][TYPE_PROP][0] =
|
378
|
+
// env[returns[VALUE]][STATS][RETURNS][0]
|
379
|
+
// this seems to be able to be deleted
|
380
|
+
// env[name][STATS][TYPE_PROP][1] =
|
381
|
+
// env[returns[VALUE]][STATS][RETURNS][1]
|
382
|
+
})
|
383
|
+
else setReturnRef(env[name][STATS], env[returns[VALUE]][STATS])
|
384
|
+
}
|
385
|
+
}
|
386
|
+
break
|
387
|
+
}
|
388
|
+
}
|
389
|
+
return true
|
390
|
+
}
|
391
|
+
const checkReturnType = ({ exp, stack, name, errors, env }) => {
|
392
|
+
const last = exp.at(-1).at(-1)
|
393
|
+
const body = hasApplyLambdaBlock(last) ? last.at(-1).at(-1) : last
|
394
|
+
const rem = hasBlock(body) ? body.at(-1) : body
|
395
|
+
const returns = isLeaf(rem) ? rem : rem[0]
|
396
|
+
return resolveRetunType({
|
397
|
+
returns,
|
398
|
+
rem,
|
399
|
+
prop: RETURNS,
|
400
|
+
exp,
|
401
|
+
name,
|
402
|
+
errors,
|
403
|
+
env,
|
404
|
+
stack
|
405
|
+
})
|
406
|
+
}
|
236
407
|
export const typeCheck = (ast, error = true) => {
|
237
408
|
let scopeIndex = 0
|
238
409
|
const root = structuredClone(SPECIAL_FORM_TYPES)
|
239
|
-
const
|
240
|
-
const warningStack = new Set()
|
241
|
-
// TODO delete this
|
242
|
-
// const tempStack = new Set()
|
410
|
+
const errors = new Set()
|
243
411
|
const Types = new Map()
|
244
412
|
const stack = []
|
245
413
|
const check = (exp, env, scope) => {
|
@@ -248,7 +416,8 @@ export const typeCheck = (ast, error = true) => {
|
|
248
416
|
throw new TypeError(
|
249
417
|
`(lambda) invocation with missing (Abstraction) name () Provide an (Abstraction) name as the (1) argument.`
|
250
418
|
)
|
251
|
-
const isSpecial =
|
419
|
+
const isSpecial =
|
420
|
+
SPECIAL_FORMS_SET.has(first[VALUE]) || STATIC_TYPES_SET.has(first[VALUE])
|
252
421
|
switch (first[TYPE]) {
|
253
422
|
case WORD:
|
254
423
|
if (!isSpecial)
|
@@ -256,7 +425,7 @@ export const typeCheck = (ast, error = true) => {
|
|
256
425
|
() =>
|
257
426
|
// Figure out how to determine if varible is define after it's used
|
258
427
|
env[first[VALUE]] === undefined &&
|
259
|
-
|
428
|
+
errors.add(
|
260
429
|
`Trying to access undefined variable ${first[VALUE]} (check #11)`
|
261
430
|
)
|
262
431
|
)
|
@@ -277,138 +446,6 @@ export const typeCheck = (ast, error = true) => {
|
|
277
446
|
else {
|
278
447
|
const name = rest[0][VALUE]
|
279
448
|
// Predicate name consistency
|
280
|
-
const resolveRetunType = (returns, rem, prop) => {
|
281
|
-
if (returns[TYPE] === ATOM) {
|
282
|
-
// ATOM ASSIGMENT
|
283
|
-
setPropToAtom(env[name][STATS], prop)
|
284
|
-
checkPredicateName(exp, [[WORD, name], returns], warningStack)
|
285
|
-
} else {
|
286
|
-
switch (returns[VALUE]) {
|
287
|
-
case KEYWORDS.IF:
|
288
|
-
{
|
289
|
-
const re = rem.slice(2)
|
290
|
-
checkPredicateName(
|
291
|
-
exp,
|
292
|
-
[[WORD, name], isLeaf(re[0]) ? re[0] : re[0][0]],
|
293
|
-
warningStack
|
294
|
-
)
|
295
|
-
checkPredicateName(
|
296
|
-
exp,
|
297
|
-
[[WORD, name], isLeaf(re[1]) ? re[1] : re[1][0]],
|
298
|
-
warningStack
|
299
|
-
)
|
300
|
-
if (re[0][TYPE] === ATOM || re[1][TYPE] === ATOM)
|
301
|
-
// ATOM ASSIGMENT
|
302
|
-
setPropToAtom(env[name][STATS], prop)
|
303
|
-
else if (
|
304
|
-
!isLeaf(re[0]) &&
|
305
|
-
env[re[0][0][VALUE]] &&
|
306
|
-
!isUnknownReturn(env[re[0][0][VALUE]][STATS])
|
307
|
-
) {
|
308
|
-
env[name][STATS][prop] =
|
309
|
-
env[re[0][0][VALUE]][STATS][RETURNS]
|
310
|
-
if (re[0][0][TYPE] === APPLY) {
|
311
|
-
switch (re[0][0][VALUE]) {
|
312
|
-
case KEYWORDS.ANONYMOUS_FUNCTION:
|
313
|
-
// FN UKNONW ASSIGMENT
|
314
|
-
env[name][STATS][TYPE_PROP] = [APPLY]
|
315
|
-
env[name][STATS][RETURNS] = [UNKNOWN]
|
316
|
-
env[name][STATS][ARG_COUNT] = re[0].length - 2
|
317
|
-
env[name][STATS][ARGUMENTS] = fillUknownArgs(
|
318
|
-
re[0].length - 2
|
319
|
-
)
|
320
|
-
break
|
321
|
-
}
|
322
|
-
}
|
323
|
-
// env[name][STATS] = env[re[0][0][VALUE]][STATS]
|
324
|
-
} else if (
|
325
|
-
!isLeaf(re[1]) &&
|
326
|
-
env[re[1][0][VALUE]] &&
|
327
|
-
!isUnknownReturn(env[re[1][0][VALUE]][STATS])
|
328
|
-
) {
|
329
|
-
setProp(
|
330
|
-
env[name][STATS],
|
331
|
-
prop,
|
332
|
-
env[re[1][0][VALUE]][STATS]
|
333
|
-
)
|
334
|
-
if (re[1][0][TYPE] === APPLY) {
|
335
|
-
switch (re[1][0][VALUE]) {
|
336
|
-
case KEYWORDS.ANONYMOUS_FUNCTION:
|
337
|
-
// FN ASSIGMENT
|
338
|
-
env[name][STATS][TYPE_PROP] = [APPLY]
|
339
|
-
env[name][STATS][RETURNS] = [UNKNOWN]
|
340
|
-
env[name][STATS][ARG_COUNT] = re[1].length - 2
|
341
|
-
env[name][STATS][ARGUMENTS] = fillUknownArgs(
|
342
|
-
re[1].length - 2
|
343
|
-
)
|
344
|
-
break
|
345
|
-
}
|
346
|
-
}
|
347
|
-
} else if (env[re[0][VALUE]])
|
348
|
-
// ASSIGMENT
|
349
|
-
setPropRef(
|
350
|
-
env[name][STATS],
|
351
|
-
prop,
|
352
|
-
env[re[0][VALUE]][STATS]
|
353
|
-
)
|
354
|
-
else if (env[re[1][VALUE]])
|
355
|
-
// ASSIGMENT
|
356
|
-
setPropRef(
|
357
|
-
env[name][STATS],
|
358
|
-
prop,
|
359
|
-
env[re[1][VALUE]][STATS]
|
360
|
-
)
|
361
|
-
}
|
362
|
-
break
|
363
|
-
default:
|
364
|
-
checkPredicateNameDeep(
|
365
|
-
name,
|
366
|
-
exp,
|
367
|
-
rest,
|
368
|
-
returns,
|
369
|
-
warningStack
|
370
|
-
)
|
371
|
-
if (!env[returns[VALUE]]) return false
|
372
|
-
else if (getType(env[returns[VALUE]][STATS]) === APPLY) {
|
373
|
-
if (returns[TYPE] === WORD)
|
374
|
-
setReturnToAbbstraction(env[name][STATS])
|
375
|
-
else {
|
376
|
-
// ALWAYS APPLY
|
377
|
-
// rest.at(-1)[0][TYPE] === APPLY
|
378
|
-
// Here is upon application to store the result in the variable
|
379
|
-
if (isUnknownType(env[name][STATS]))
|
380
|
-
stack.unshift(() => {
|
381
|
-
setTypeToReturn(
|
382
|
-
env[name][STATS],
|
383
|
-
env[returns[VALUE]][STATS]
|
384
|
-
)
|
385
|
-
// env[name][STATS][TYPE_PROP][0] =
|
386
|
-
// env[returns[VALUE]][STATS][RETURNS][0]
|
387
|
-
// this seems to be able to be deleted
|
388
|
-
// env[name][STATS][TYPE_PROP][1] =
|
389
|
-
// env[returns[VALUE]][STATS][RETURNS][1]
|
390
|
-
})
|
391
|
-
else
|
392
|
-
setReturnRef(
|
393
|
-
env[name][STATS],
|
394
|
-
env[returns[VALUE]][STATS]
|
395
|
-
)
|
396
|
-
}
|
397
|
-
}
|
398
|
-
break
|
399
|
-
}
|
400
|
-
}
|
401
|
-
return true
|
402
|
-
}
|
403
|
-
const checkReturnType = () => {
|
404
|
-
const last = rest.at(-1).at(-1)
|
405
|
-
const body = hasApplyLambdaBlock(last)
|
406
|
-
? last.at(-1).at(-1)
|
407
|
-
: last
|
408
|
-
const rem = hasBlock(body) ? body.at(-1) : body
|
409
|
-
const returns = isLeaf(rem) ? rem : rem[0]
|
410
|
-
return resolveRetunType(returns, rem, RETURNS)
|
411
|
-
}
|
412
449
|
const rightHand = rest.at(-1)
|
413
450
|
if (
|
414
451
|
rightHand &&
|
@@ -416,6 +453,7 @@ export const typeCheck = (ast, error = true) => {
|
|
416
453
|
rightHand[0][TYPE] === APPLY &&
|
417
454
|
rightHand[0][VALUE] === KEYWORDS.ANONYMOUS_FUNCTION
|
418
455
|
) {
|
456
|
+
validateLambda(rightHand, name)
|
419
457
|
const n = rightHand.length
|
420
458
|
env[name] = {
|
421
459
|
[STATS]: {
|
@@ -429,24 +467,36 @@ export const typeCheck = (ast, error = true) => {
|
|
429
467
|
}
|
430
468
|
}
|
431
469
|
if (
|
432
|
-
!checkReturnType(
|
470
|
+
!checkReturnType({
|
471
|
+
stack,
|
472
|
+
exp,
|
473
|
+
env,
|
474
|
+
name,
|
475
|
+
errors
|
476
|
+
}) ||
|
433
477
|
(isUnknownReturn(env[name][STATS]) &&
|
434
478
|
env[name][STATS].retried < MAX_RETRY_DEFINITION)
|
435
479
|
) {
|
436
480
|
env[name][STATS].retried += 1
|
437
481
|
stack.unshift(() => {
|
438
|
-
checkReturnType(
|
482
|
+
checkReturnType({
|
483
|
+
stack,
|
484
|
+
exp,
|
485
|
+
env,
|
486
|
+
name,
|
487
|
+
errors
|
488
|
+
})
|
439
489
|
check(rightHand, env, exp)
|
440
490
|
})
|
441
491
|
check(rightHand, env, exp)
|
442
492
|
} else check(rightHand, env, exp)
|
443
493
|
} else {
|
444
|
-
checkPredicateName(exp, rest,
|
494
|
+
checkPredicateName(exp, rest, errors)
|
445
495
|
const isLeafNode = isLeaf(rightHand)
|
446
496
|
if (isLeafNode && rightHand[TYPE] === WORD) {
|
447
497
|
// TODO make sure this prevents the assigment all together
|
448
498
|
if (env[rest[1][VALUE]] === undefined)
|
449
|
-
|
499
|
+
errors.add(
|
450
500
|
`Trying to access undefined variable ${rest[1][VALUE]} (check #22)`
|
451
501
|
)
|
452
502
|
|
@@ -489,7 +539,16 @@ export const typeCheck = (ast, error = true) => {
|
|
489
539
|
const body = rightHand
|
490
540
|
const rem = hasBlock(body) ? body.at(-1) : body
|
491
541
|
const returns = isLeaf(rem) ? rem : rem[0]
|
492
|
-
resolveRetunType(
|
542
|
+
resolveRetunType({
|
543
|
+
stack,
|
544
|
+
returns,
|
545
|
+
rem,
|
546
|
+
prop: TYPE_PROP,
|
547
|
+
exp,
|
548
|
+
env,
|
549
|
+
name,
|
550
|
+
errors
|
551
|
+
})
|
493
552
|
}
|
494
553
|
check(rightHand, env, scope)
|
495
554
|
}
|
@@ -497,14 +556,7 @@ export const typeCheck = (ast, error = true) => {
|
|
497
556
|
}
|
498
557
|
break
|
499
558
|
case KEYWORDS.ANONYMOUS_FUNCTION:
|
500
|
-
|
501
|
-
throw new TypeError(
|
502
|
-
`Incorrect number of arguments for (${
|
503
|
-
first[VALUE]
|
504
|
-
}). Expected at least 1 (the lambda body) but got 1 (${stringifyArgs(
|
505
|
-
exp
|
506
|
-
)})`
|
507
|
-
)
|
559
|
+
validateLambda(exp)
|
508
560
|
const params = exp.slice(1, -1)
|
509
561
|
const copy = Object.create(env)
|
510
562
|
if (Array.isArray(scope[1]) && scope[1][TYPE] === WORD)
|
@@ -514,7 +566,7 @@ export const typeCheck = (ast, error = true) => {
|
|
514
566
|
const param = params[i]
|
515
567
|
// TODO move this somewhere else
|
516
568
|
if (!isLeaf(param))
|
517
|
-
|
569
|
+
errors.add(
|
518
570
|
`Invalid body for (${
|
519
571
|
first[VALUE]
|
520
572
|
}) if it takes more than one expression it must be wrapped in a (${
|
@@ -549,44 +601,17 @@ export const typeCheck = (ast, error = true) => {
|
|
549
601
|
)
|
550
602
|
else {
|
551
603
|
const ret = returns[0]
|
604
|
+
|
552
605
|
switch (ret[VALUE]) {
|
553
606
|
case KEYWORDS.IF:
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
: copy[re[0][0][VALUE]]
|
563
|
-
const alternative = isLeaf(re[1])
|
564
|
-
? copy[re[1][VALUE]]
|
565
|
-
: copy[re[1][0][VALUE]]
|
566
|
-
|
567
|
-
// todo check if condition matches alternative
|
568
|
-
// TODO make this more simple - it's so many different things just because types are functions or not
|
569
|
-
// WHY not consiter making return types for everything
|
570
|
-
if (
|
571
|
-
concequent &&
|
572
|
-
getType(concequent[STATS]) !== UNKNOWN
|
573
|
-
) {
|
574
|
-
if (getType(concequent[STATS]) === APPLY)
|
575
|
-
setReturnRef(ref[STATS], concequent[STATS])
|
576
|
-
else ref[STATS][RETURNS] = concequent[STATS][TYPE_PROP]
|
577
|
-
} else if (
|
578
|
-
alternative &&
|
579
|
-
isUnknownType(alternative[STATS])
|
580
|
-
) {
|
581
|
-
if (getType(alternative[STATS]) === APPLY)
|
582
|
-
setReturnRef(ref[STATS], alternative[STATS])
|
583
|
-
else setReturnToTypeRef(ref[STATS], alternative[STATS])
|
584
|
-
} else if (concequent) {
|
585
|
-
if (getType(concequent[STATS]) === APPLY)
|
586
|
-
setReturnRef(ref[STATS], concequent[STATS])
|
587
|
-
else setReturnToTypeRef(ref[STATS], concequent[STATS])
|
588
|
-
}
|
589
|
-
}
|
607
|
+
resolveCondition({
|
608
|
+
rem: returns,
|
609
|
+
name: ref[STATS][SIGNATURE],
|
610
|
+
env: copy,
|
611
|
+
exp,
|
612
|
+
errors,
|
613
|
+
stack
|
614
|
+
})
|
590
615
|
break
|
591
616
|
default:
|
592
617
|
if (copy[ret[VALUE]])
|
@@ -604,563 +629,550 @@ export const typeCheck = (ast, error = true) => {
|
|
604
629
|
}
|
605
630
|
check(rest.at(-1), copy, copy)
|
606
631
|
break
|
632
|
+
case STATIC_TYPES.ABSTRACTION:
|
633
|
+
case STATIC_TYPES.COLLECTION:
|
634
|
+
case STATIC_TYPES.UNKNOWN:
|
635
|
+
case STATIC_TYPES.ATOM:
|
636
|
+
case STATIC_TYPES.PREDICATE:
|
637
|
+
case STATIC_TYPES.ANY:
|
638
|
+
{
|
639
|
+
const ret = isLeaf(rest[0]) ? rest[0] : rest[0][0]
|
640
|
+
const ref = env[ret[VALUE]]
|
641
|
+
if (!ref) break
|
642
|
+
const caster = root[first[VALUE]]
|
643
|
+
if (ret[TYPE] === APPLY && isUnknownReturn(ref[STATS]))
|
644
|
+
castReturn(ref[STATS], caster[STATS])
|
645
|
+
else if (isUnknownType(ref[STATS]))
|
646
|
+
castType(ref[STATS], caster[STATS])
|
647
|
+
check(rest[0], env, env)
|
648
|
+
}
|
649
|
+
break
|
607
650
|
default:
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
`Trying to call undefined (lambda) ${first[VALUE]} (check #9)`
|
613
|
-
)
|
614
|
-
else if (
|
615
|
-
env[first[VALUE]][STATS][TYPE_PROP][0] === APPLY &&
|
616
|
-
env[first[VALUE]][STATS][ARG_COUNT] !== VARIADIC &&
|
617
|
-
env[first[VALUE]][STATS][ARG_COUNT] !== rest.length
|
651
|
+
stack.push(() => {
|
652
|
+
if (!isSpecial && env[first[VALUE]] === undefined)
|
653
|
+
errors.add(
|
654
|
+
`Trying to call undefined (lambda) ${first[VALUE]} (check #9)`
|
618
655
|
)
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
)
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
)
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
if (!env[ARG[VALUE]]) continue
|
660
|
-
switch (ARG[TYPE]) {
|
661
|
-
// THERE ARE NO ATOM ARGUMENTS
|
662
|
-
// case ATOM:
|
663
|
-
// break
|
664
|
-
case APPLY:
|
665
|
-
// passing arg asA APPLICATION
|
666
|
-
if (isUnknownType(arg[i][STATS]))
|
667
|
-
arg[i][STATS][TYPE_PROP] =
|
668
|
-
env[ARG[VALUE]][STATS][RETURNS]
|
669
|
-
break
|
670
|
-
case WORD:
|
671
|
-
// if param is a word we assosiate them by referanc
|
672
|
-
if (isUnknownType(arg[i][STATS]))
|
673
|
-
arg[i][STATS] = env[ARG[VALUE]][STATS]
|
674
|
-
break
|
656
|
+
else if (
|
657
|
+
env[first[VALUE]][STATS][TYPE_PROP][0] === APPLY &&
|
658
|
+
env[first[VALUE]][STATS][ARG_COUNT] !== VARIADIC &&
|
659
|
+
env[first[VALUE]][STATS][ARG_COUNT] !== rest.length
|
660
|
+
)
|
661
|
+
errors.add(
|
662
|
+
`Incorrect number of arguments for (${
|
663
|
+
first[VALUE]
|
664
|
+
}). Expected (= ${
|
665
|
+
env[first[VALUE]][STATS][ARG_COUNT]
|
666
|
+
}) but got ${rest.length} (${stringifyArgs(exp)}) (check #15)`
|
667
|
+
)
|
668
|
+
else {
|
669
|
+
if (first[TYPE] === APPLY && !isSpecial) {
|
670
|
+
if (getType(env[first[VALUE]][STATS]) === ATOM)
|
671
|
+
errors.add(
|
672
|
+
`(${first[VALUE]}) is not a (lambda) (${stringifyArgs(
|
673
|
+
exp
|
674
|
+
)}) (check #12)`
|
675
|
+
)
|
676
|
+
else if (!env[first[VALUE]][STATS][ARG_COUNT]) {
|
677
|
+
// TODO recursively take return type of applicaion
|
678
|
+
// FN ASSIGMENT
|
679
|
+
// ASSIGMENT of paramaters of lambda that are a lambda
|
680
|
+
// minus one to remove the body
|
681
|
+
env[first[VALUE]][STATS][TYPE_PROP] = [APPLY]
|
682
|
+
env[first[VALUE]][STATS][ARG_COUNT] = rest.length
|
683
|
+
env[first[VALUE]][STATS][ARGUMENTS] = fillUknownArgs(
|
684
|
+
rest.length
|
685
|
+
)
|
686
|
+
for (let i = 0; i < rest.length; ++i) {
|
687
|
+
const arg = env[first[VALUE]][STATS][ARGUMENTS]
|
688
|
+
arg[i] = {
|
689
|
+
[STATS]: {
|
690
|
+
retried: 0,
|
691
|
+
[SIGNATURE]: PLACEHOLDER,
|
692
|
+
[TYPE_PROP]: [UNKNOWN],
|
693
|
+
[RETURNS]: [UNKNOWN],
|
694
|
+
[ARGUMENTS]: [],
|
695
|
+
[ARG_COUNT]: 0
|
675
696
|
}
|
676
697
|
}
|
698
|
+
const ARG = isLeaf(rest[i]) ? rest[i] : rest[i][0]
|
699
|
+
if (!env[ARG[VALUE]]) continue
|
700
|
+
switch (ARG[TYPE]) {
|
701
|
+
// THERE ARE NO ATOM ARGUMENTS
|
702
|
+
// case ATOM:
|
703
|
+
// break
|
704
|
+
case APPLY:
|
705
|
+
// passing arg asA APPLICATION
|
706
|
+
if (isUnknownType(arg[i][STATS]))
|
707
|
+
arg[i][STATS][TYPE_PROP] =
|
708
|
+
env[ARG[VALUE]][STATS][RETURNS]
|
709
|
+
break
|
710
|
+
case WORD:
|
711
|
+
// if param is a word we assosiate them by referanc
|
712
|
+
if (isUnknownType(arg[i][STATS]))
|
713
|
+
arg[i][STATS] = env[ARG[VALUE]][STATS]
|
714
|
+
break
|
715
|
+
}
|
677
716
|
}
|
678
717
|
}
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
718
|
+
}
|
719
|
+
// also type of arg
|
720
|
+
const args = env[first[VALUE]][STATS][ARGUMENTS] ?? []
|
721
|
+
for (let i = 0; i < args.length; ++i) {
|
722
|
+
const isRestILeaf = isLeaf(rest[i])
|
723
|
+
// type check
|
724
|
+
// TODO get rof pred type
|
725
|
+
// const PRED_TYPE = args[i][STATS][TYPE_PROP][1]
|
726
|
+
const MAIN_TYPE = getType(args[i][STATS])
|
727
|
+
if (MAIN_TYPE === ANY) continue
|
728
|
+
if (first[TYPE] === APPLY && isSpecial) {
|
729
|
+
if (
|
730
|
+
MAIN_TYPE === ATOM &&
|
731
|
+
PREDICATES_INPUT_SET.has(first[VALUE])
|
732
|
+
) {
|
689
733
|
if (
|
690
|
-
|
691
|
-
|
734
|
+
!isRestILeaf &&
|
735
|
+
rest[i][0][TYPE] === APPLY &&
|
736
|
+
rest[i][0][VALUE] === KEYWORDS.CALL_FUNCTION
|
692
737
|
) {
|
693
|
-
if (
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
}). Expected (${toTypeNames(
|
706
|
-
ATOM
|
707
|
-
)}) but got an (${toTypeNames(
|
708
|
-
getReturn(fn[STATS])
|
709
|
-
)}) (${stringifyArgs(exp)}) (check #26)`
|
710
|
-
)
|
711
|
-
} else {
|
712
|
-
const body = rest[i].at(-1).at(-1)
|
713
|
-
const rem = hasBlock(body) ? body.at(-1) : body
|
714
|
-
const returns = isLeaf(rem) ? rem : rem[0]
|
715
|
-
if (returns[TYPE] === ATOM) {
|
716
|
-
if (MAIN_TYPE !== ATOM)
|
717
|
-
errorStack.add(
|
718
|
-
`Incorrect type of argument ${i} for (${
|
719
|
-
first[VALUE]
|
720
|
-
}). Expected (${toTypeNames(
|
721
|
-
MAIN_TYPE
|
722
|
-
)}) but got an (${toTypeNames(
|
723
|
-
ATOM
|
724
|
-
)}) (${stringifyArgs(exp)}) (check #27)`
|
725
|
-
)
|
726
|
-
} else if (
|
727
|
-
env[returns[VALUE]] &&
|
728
|
-
!isUnknownReturn(env[returns[VALUE]][STATS]) &&
|
729
|
-
getReturn(env[returns[VALUE]][STATS]) !== ATOM
|
738
|
+
if (isLeaf(rest[i].at(-1))) {
|
739
|
+
const fnName = rest[i].at(-1)[VALUE]
|
740
|
+
const fn = env[fnName]
|
741
|
+
if (fn && getReturn(fn[STATS]) !== ATOM)
|
742
|
+
errors.add(
|
743
|
+
`Incorrect type of argument (${i}) for (${
|
744
|
+
first[VALUE]
|
745
|
+
}). Expected (${toTypeNames(
|
746
|
+
ATOM
|
747
|
+
)}) but got an (${toTypeNames(
|
748
|
+
getReturn(fn[STATS])
|
749
|
+
)}) (${stringifyArgs(exp)}) (check #26)`
|
730
750
|
)
|
731
|
-
|
751
|
+
} else {
|
752
|
+
const body = rest[i].at(-1).at(-1)
|
753
|
+
const rem = hasBlock(body) ? body.at(-1) : body
|
754
|
+
const returns = isLeaf(rem) ? rem : rem[0]
|
755
|
+
if (returns[TYPE] === ATOM) {
|
756
|
+
if (MAIN_TYPE !== ATOM)
|
757
|
+
errors.add(
|
732
758
|
`Incorrect type of argument ${i} for (${
|
733
759
|
first[VALUE]
|
734
760
|
}). Expected (${toTypeNames(
|
761
|
+
MAIN_TYPE
|
762
|
+
)}) but got an (${toTypeNames(
|
735
763
|
ATOM
|
736
|
-
)})
|
737
|
-
getReturn(env[returns[VALUE]][STATS])
|
738
|
-
)}) (${stringifyArgs(exp)}) (check #29)`
|
764
|
+
)}) (${stringifyArgs(exp)}) (check #27)`
|
739
765
|
)
|
740
|
-
}
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
const expectedArgs = env[first[VALUE]][STATS][ARGUMENTS]
|
745
|
-
if (!isRestILeaf) {
|
746
|
-
const CAR = rest[i][0][VALUE]
|
747
|
-
if (!env[CAR]) continue
|
748
|
-
const isKnown = !isUnknownReturn(env[CAR][STATS])
|
749
|
-
if (isKnown && !isCast) {
|
750
|
-
if (
|
751
|
-
!compareTypeWithReturn(
|
752
|
-
expectedArgs[i][STATS],
|
753
|
-
env[CAR][STATS]
|
754
|
-
)
|
766
|
+
} else if (
|
767
|
+
env[returns[VALUE]] &&
|
768
|
+
!isUnknownReturn(env[returns[VALUE]][STATS]) &&
|
769
|
+
getReturn(env[returns[VALUE]][STATS]) !== ATOM
|
755
770
|
)
|
756
|
-
|
757
|
-
`Incorrect type of argument
|
771
|
+
errors.add(
|
772
|
+
`Incorrect type of argument ${i} for (${
|
758
773
|
first[VALUE]
|
759
774
|
}). Expected (${toTypeNames(
|
760
|
-
|
775
|
+
ATOM
|
761
776
|
)}) but got (${toTypeNames(
|
762
|
-
getReturn(env[
|
763
|
-
)})
|
777
|
+
getReturn(env[returns[VALUE]][STATS])
|
778
|
+
)}) (${stringifyArgs(exp)}) (check #29)`
|
764
779
|
)
|
765
|
-
} else if (!isKnown && !isCast) {
|
766
|
-
if (env[CAR] && getType(env[CAR][STATS]) === APPLY)
|
767
|
-
switch (first[VALUE]) {
|
768
|
-
case KEYWORDS.IF:
|
769
|
-
break
|
770
|
-
default:
|
771
|
-
// TODO fix this assigment
|
772
|
-
// It turns out it's not possible to determine return type of function here
|
773
|
-
// what if it's a global function used elsewhere where the return type mwould be different
|
774
|
-
// THIS willgive lambda return types but refactor is needed still
|
775
|
-
setReturn(
|
776
|
-
env[CAR][STATS],
|
777
|
-
expectedArgs[i][STATS]
|
778
|
-
)
|
779
|
-
break
|
780
|
-
}
|
781
|
-
// TODO also handle casting
|
782
780
|
}
|
783
|
-
}
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
827
|
-
|
781
|
+
}
|
782
|
+
}
|
783
|
+
const expectedArgs = env[first[VALUE]][STATS][ARGUMENTS]
|
784
|
+
if (!isRestILeaf) {
|
785
|
+
const name = rest[i][0][VALUE]
|
786
|
+
if (!env[name]) continue
|
787
|
+
if (
|
788
|
+
!isUnknownReturn(env[name][STATS]) &&
|
789
|
+
!compareTypeWithReturn(
|
790
|
+
expectedArgs[i][STATS],
|
791
|
+
env[name][STATS]
|
792
|
+
)
|
793
|
+
)
|
794
|
+
errors.add(
|
795
|
+
`Incorrect type of argument (${i}) for special form (${
|
796
|
+
first[VALUE]
|
797
|
+
}). Expected (${toTypeNames(
|
798
|
+
getType(expectedArgs[i][STATS])
|
799
|
+
)}) but got (${toTypeNames(
|
800
|
+
getReturn(env[name][STATS])
|
801
|
+
)}) (${stringifyArgs(exp)}) (check #1)`
|
802
|
+
)
|
803
|
+
else {
|
804
|
+
if (env[name] && getType(env[name][STATS]) === APPLY)
|
805
|
+
switch (first[VALUE]) {
|
806
|
+
case KEYWORDS.IF:
|
807
|
+
break
|
808
|
+
default:
|
809
|
+
// TODO fix this assigment
|
810
|
+
// It turns out it's not possible to determine return type of function here
|
811
|
+
// what if it's a global function used elsewhere where the return type mwould be different
|
812
|
+
// THIS willgive lambda return types but refactor is needed still
|
813
|
+
setReturn(
|
814
|
+
env[name][STATS],
|
815
|
+
expectedArgs[i][STATS]
|
816
|
+
)
|
817
|
+
break
|
818
|
+
}
|
819
|
+
// TODO also handle casting
|
820
|
+
}
|
821
|
+
} else {
|
822
|
+
switch (rest[i][TYPE]) {
|
823
|
+
case WORD:
|
824
|
+
{
|
825
|
+
const name = rest[i][VALUE]
|
826
|
+
if (!env[name]) continue
|
828
827
|
if (
|
829
|
-
|
830
|
-
|
828
|
+
!isUnknownType(env[name][STATS]) &&
|
829
|
+
!compareTypes(
|
830
|
+
expectedArgs[i][STATS],
|
831
|
+
env[name][STATS]
|
832
|
+
)
|
831
833
|
)
|
832
|
-
|
834
|
+
errors.add(
|
833
835
|
`Incorrect type of argument (${i}) for special form (${
|
834
836
|
first[VALUE]
|
835
837
|
}). Expected (${toTypeNames(
|
836
|
-
expectedArgs[i][STATS]
|
838
|
+
getType(expectedArgs[i][STATS])
|
837
839
|
)}) but got (${toTypeNames(
|
838
|
-
|
839
|
-
)}) (${stringifyArgs(exp)}) (check #
|
840
|
+
getType(env[name][STATS])
|
841
|
+
)}) (${stringifyArgs(exp)}) (check #3)`
|
840
842
|
)
|
841
|
-
|
843
|
+
else
|
844
|
+
setType(env[name][STATS], expectedArgs[i][STATS])
|
842
845
|
}
|
846
|
+
break
|
847
|
+
case ATOM: {
|
848
|
+
if (
|
849
|
+
rest[i][TYPE] !==
|
850
|
+
expectedArgs[i][STATS][TYPE_PROP][0]
|
851
|
+
)
|
852
|
+
errors.add(
|
853
|
+
`Incorrect type of argument (${i}) for special form (${
|
854
|
+
first[VALUE]
|
855
|
+
}). Expected (${toTypeNames(
|
856
|
+
expectedArgs[i][STATS][TYPE_PROP][0]
|
857
|
+
)}) but got (${toTypeNames(
|
858
|
+
rest[i][TYPE]
|
859
|
+
)}) (${stringifyArgs(exp)}) (check #2)`
|
860
|
+
)
|
861
|
+
break
|
843
862
|
}
|
844
863
|
}
|
845
864
|
}
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
:
|
865
|
+
}
|
866
|
+
// type checking
|
867
|
+
else if (isRestILeaf) {
|
868
|
+
const T =
|
869
|
+
rest[i][TYPE] === WORD
|
870
|
+
? env[rest[i][VALUE]]
|
871
|
+
? getType(env[rest[i][VALUE]][STATS])
|
872
|
+
: UNKNOWN
|
873
|
+
: rest[i][TYPE]
|
874
|
+
if (
|
875
|
+
T === ATOM &&
|
876
|
+
!isUnknownType(args[i][STATS]) &&
|
877
|
+
getType(args[i][STATS]) !== ATOM
|
878
|
+
) {
|
879
|
+
errors.add(
|
880
|
+
`Incorrect type of arguments ${i} for (${
|
881
|
+
first[VALUE]
|
882
|
+
}). Expected (${toTypeNames(
|
883
|
+
getType(args[i][STATS])
|
884
|
+
)}) but got (${toTypeNames(T)}) (${stringifyArgs(
|
885
|
+
exp
|
886
|
+
)}) (check #10)`
|
887
|
+
)
|
888
|
+
} else if (
|
889
|
+
T === APPLY &&
|
890
|
+
!isUnknownType(args[i][STATS]) &&
|
891
|
+
!isUnknownType(env[rest[i][VALUE]][STATS]) &&
|
892
|
+
env[rest[i][VALUE]][STATS][ARG_COUNT] !== VARIADIC
|
893
|
+
) {
|
894
|
+
// Handles words that are Lambdas
|
854
895
|
if (
|
855
|
-
|
856
|
-
|
857
|
-
getType(args[i][STATS]) !== ATOM
|
896
|
+
env[rest[i][VALUE]][STATS][ARG_COUNT] !==
|
897
|
+
args[i][STATS][ARG_COUNT]
|
858
898
|
) {
|
859
|
-
|
860
|
-
`Incorrect
|
899
|
+
errors.add(
|
900
|
+
`Incorrect number of arguments for (${
|
901
|
+
args[i][STATS][SIGNATURE]
|
902
|
+
}) the (lambda) argument of (${
|
861
903
|
first[VALUE]
|
862
|
-
}). Expected (${
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
)}) (check #
|
904
|
+
}) at position (${i}). Expected (= ${
|
905
|
+
args[i][STATS][ARG_COUNT]
|
906
|
+
}) but got ${
|
907
|
+
env[rest[i][VALUE]][STATS][ARG_COUNT]
|
908
|
+
} (${stringifyArgs(exp)}) (check #778)`
|
867
909
|
)
|
868
|
-
} else
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
910
|
+
} else {
|
911
|
+
// DEFINED LAMBDAS TYPE CHECKING
|
912
|
+
// #C1
|
913
|
+
// TODO delete this maybe
|
914
|
+
// It will not be possilbe to know return type
|
915
|
+
const match1 = () => {
|
916
|
+
const actual = env[rest[i][VALUE]]
|
917
|
+
const expected = args[i]
|
918
|
+
if (
|
919
|
+
!isUnknownReturn(expected[STATS]) &&
|
920
|
+
!isUnknownReturn(actual[STATS]) &&
|
921
|
+
!compareReturns(expected[STATS], actual[STATS])
|
922
|
+
) {
|
923
|
+
errors.add(
|
924
|
+
`Incorrect return type for (${
|
925
|
+
expected[STATS][SIGNATURE]
|
926
|
+
}) the (lambda) argument of (${
|
927
|
+
first[VALUE]
|
928
|
+
}) at position (${i}). Expected (${toTypeNames(
|
929
|
+
getReturn(expected[STATS])
|
930
|
+
)}) but got (${toTypeNames(
|
931
|
+
getReturn(actual[STATS])
|
932
|
+
)}) (${stringifyArgs(exp)}) (check #782)`
|
933
|
+
)
|
934
|
+
} else if (
|
935
|
+
actual[STATS].retried < MAX_RETRY_DEFINITION
|
936
|
+
) {
|
937
|
+
actual[STATS].retried += 1
|
938
|
+
stack.unshift(() => match1())
|
939
|
+
}
|
940
|
+
}
|
941
|
+
match1()
|
942
|
+
for (
|
943
|
+
let j = 0;
|
944
|
+
j < args[i][STATS][ARGUMENTS].length;
|
945
|
+
++j
|
878
946
|
) {
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
first[VALUE]
|
884
|
-
}) at position (${i}). Expected (= ${
|
885
|
-
args[i][STATS][ARG_COUNT]
|
886
|
-
}) but got ${
|
887
|
-
env[rest[i][VALUE]][STATS][ARG_COUNT]
|
888
|
-
} (${stringifyArgs(exp)}) (check #778)`
|
889
|
-
)
|
890
|
-
} else {
|
891
|
-
// DEFINED LAMBDAS TYPE CHECKING
|
892
|
-
// #C1
|
893
|
-
// TODO delete this maybe
|
894
|
-
// It will not be possilbe to know return type
|
895
|
-
const match1 = () => {
|
896
|
-
const actual = env[rest[i][VALUE]]
|
897
|
-
const expected = args[i]
|
947
|
+
const match2 = () => {
|
948
|
+
const actual =
|
949
|
+
env[rest[i][VALUE]][STATS][ARGUMENTS][j]
|
950
|
+
const expected = args[i][STATS][ARGUMENTS][j]
|
898
951
|
if (
|
899
|
-
!
|
900
|
-
!
|
901
|
-
!
|
902
|
-
)
|
903
|
-
|
904
|
-
`Incorrect
|
905
|
-
|
906
|
-
})
|
907
|
-
|
908
|
-
})
|
909
|
-
|
952
|
+
!isUnknownType(actual[STATS]) &&
|
953
|
+
!isUnknownType(expected[STATS]) &&
|
954
|
+
!compareTypes(actual[STATS], expected[STATS])
|
955
|
+
)
|
956
|
+
errors.add(
|
957
|
+
`Incorrect type for (lambda) (${
|
958
|
+
args[i][STATS][SIGNATURE]
|
959
|
+
}) argument at position (${j}) named as (${
|
960
|
+
actual[STATS][SIGNATURE]
|
961
|
+
}). Expected (${toTypeNames(
|
962
|
+
getType(expected[STATS])
|
910
963
|
)}) but got (${toTypeNames(
|
911
|
-
|
912
|
-
)}) (${stringifyArgs(exp)}) (check #
|
964
|
+
getType(actual[STATS])
|
965
|
+
)}) (${stringifyArgs(exp)}) (check #781)`
|
913
966
|
)
|
914
|
-
|
967
|
+
else if (
|
915
968
|
actual[STATS].retried < MAX_RETRY_DEFINITION
|
916
969
|
) {
|
917
970
|
actual[STATS].retried += 1
|
918
|
-
stack.unshift(() =>
|
971
|
+
stack.unshift(() => match2())
|
919
972
|
}
|
920
973
|
}
|
921
|
-
|
922
|
-
for (
|
923
|
-
let j = 0;
|
924
|
-
j < args[i][STATS][ARGUMENTS].length;
|
925
|
-
++j
|
926
|
-
) {
|
927
|
-
const match2 = () => {
|
928
|
-
const actual =
|
929
|
-
env[rest[i][VALUE]][STATS][ARGUMENTS][j]
|
930
|
-
const expected = args[i][STATS][ARGUMENTS][j]
|
931
|
-
if (
|
932
|
-
!isUnknownType(actual[STATS]) &&
|
933
|
-
!isUnknownType(expected[STATS]) &&
|
934
|
-
!compareTypes(actual[STATS], expected[STATS])
|
935
|
-
)
|
936
|
-
errorStack.add(
|
937
|
-
`Incorrect type for (lambda) (${
|
938
|
-
args[i][STATS][SIGNATURE]
|
939
|
-
}) argument at position (${j}) named as (${
|
940
|
-
actual[STATS][SIGNATURE]
|
941
|
-
}). Expected (${toTypeNames(
|
942
|
-
getType(expected[STATS])
|
943
|
-
)}) but got (${toTypeNames(
|
944
|
-
getType(actual[STATS])
|
945
|
-
)}) (${stringifyArgs(exp)}) (check #781)`
|
946
|
-
)
|
947
|
-
else if (
|
948
|
-
actual[STATS].retried < MAX_RETRY_DEFINITION
|
949
|
-
) {
|
950
|
-
actual[STATS].retried += 1
|
951
|
-
stack.unshift(() => match2())
|
952
|
-
}
|
953
|
-
}
|
954
|
-
match2()
|
955
|
-
}
|
974
|
+
match2()
|
956
975
|
}
|
957
976
|
}
|
977
|
+
}
|
978
|
+
if (
|
979
|
+
T === COLLECTION &&
|
980
|
+
env[rest[i][VALUE]] &&
|
981
|
+
!isUnknownType(env[rest[i][VALUE]][STATS]) &&
|
982
|
+
!isUnknownType(args[i][STATS]) &&
|
983
|
+
!compareTypes(env[rest[i][VALUE]][STATS], args[i][STATS])
|
984
|
+
) {
|
985
|
+
errors.add(
|
986
|
+
`Incorrect type of arguments ${i} for (${
|
987
|
+
first[VALUE]
|
988
|
+
}). Expected (${toTypeNames(
|
989
|
+
getType(args[i][STATS])
|
990
|
+
)}) but got (${toTypeNames(T)}) (${stringifyArgs(
|
991
|
+
exp
|
992
|
+
)}) (check #30)`
|
993
|
+
)
|
994
|
+
} else if (
|
995
|
+
isUnknownType(args[i][STATS]) &&
|
996
|
+
args[i][STATS].retried < MAX_RETRY_DEFINITION
|
997
|
+
) {
|
998
|
+
args[i][STATS].retried += 1
|
999
|
+
stack.unshift(() => check(exp, env, scope))
|
1000
|
+
} else {
|
958
1001
|
if (
|
959
|
-
T === COLLECTION &&
|
960
1002
|
env[rest[i][VALUE]] &&
|
961
|
-
!isUnknownType(env[rest[i][VALUE]][STATS]) &&
|
962
1003
|
!isUnknownType(args[i][STATS]) &&
|
963
|
-
|
964
|
-
|
965
|
-
args[i][STATS]
|
966
|
-
)
|
1004
|
+
isUnknownType(env[rest[i][VALUE]][STATS]) &&
|
1005
|
+
getType(args[i][STATS]) !== APPLY
|
967
1006
|
) {
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
|
973
|
-
)}) but got (${toTypeNames(T)}) (${stringifyArgs(
|
974
|
-
exp
|
975
|
-
)}) (check #30)`
|
976
|
-
)
|
977
|
-
} else if (
|
978
|
-
isUnknownType(args[i][STATS]) &&
|
979
|
-
args[i][STATS].retried < MAX_RETRY_DEFINITION
|
980
|
-
) {
|
981
|
-
args[i][STATS].retried += 1
|
982
|
-
stack.unshift(() => check(exp, env, scope))
|
983
|
-
} else {
|
984
|
-
if (
|
985
|
-
env[rest[i][VALUE]] &&
|
986
|
-
!isUnknownType(args[i][STATS]) &&
|
987
|
-
isUnknownType(env[rest[i][VALUE]][STATS]) &&
|
988
|
-
getType(args[i][STATS]) !== APPLY
|
989
|
-
) {
|
990
|
-
// REFF ASSIGMENT
|
991
|
-
env[rest[i][VALUE]][STATS][TYPE_PROP] =
|
992
|
-
args[i][STATS][TYPE_PROP]
|
993
|
-
env[rest[i][VALUE]][STATS][RETURNS] =
|
994
|
-
args[i][STATS][RETURNS]
|
995
|
-
}
|
1007
|
+
// REFF ASSIGMENT
|
1008
|
+
env[rest[i][VALUE]][STATS][TYPE_PROP] =
|
1009
|
+
args[i][STATS][TYPE_PROP]
|
1010
|
+
env[rest[i][VALUE]][STATS][RETURNS] =
|
1011
|
+
args[i][STATS][RETURNS]
|
996
1012
|
}
|
997
|
-
}
|
998
|
-
|
999
|
-
|
1000
|
-
|
1001
|
-
|
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
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1013
|
+
}
|
1014
|
+
} else if (env[rest[i][0][VALUE]]) {
|
1015
|
+
const match = () => {
|
1016
|
+
const actual = env[rest[i][0][VALUE]][STATS]
|
1017
|
+
const expected = args[i][STATS]
|
1018
|
+
if (args[i][STATS].counter < MAX_ARGUMENT_RETRY) {
|
1019
|
+
args[i][STATS].counter++
|
1020
|
+
stack.unshift(() => match())
|
1021
|
+
}
|
1022
|
+
if (!isUnknownType(expected) && !isUnknownReturn(actual))
|
1023
|
+
if (!compareTypeWithReturn(expected, actual))
|
1024
|
+
errors.add(
|
1025
|
+
`Incorrect type of arguments ${i} for (${
|
1026
|
+
first[VALUE]
|
1027
|
+
}). Expected (${toTypeNames(
|
1028
|
+
getType(expected)
|
1029
|
+
)}) but got (${toTypeNames(
|
1030
|
+
getReturn(actual)
|
1031
|
+
)}) (${stringifyArgs(exp)}) (check #16)`
|
1032
|
+
)
|
1033
|
+
else {
|
1034
|
+
switch (getType(expected)) {
|
1035
|
+
// almost exclusively for anonymous lambdas
|
1036
|
+
case APPLY:
|
1037
|
+
{
|
1038
|
+
const argsN = rest[i].length - 2
|
1039
|
+
if (
|
1040
|
+
env[rest[i][0][VALUE]][STATS][SIGNATURE] ===
|
1041
|
+
KEYWORDS.ANONYMOUS_FUNCTION
|
1042
|
+
) {
|
1043
|
+
if (argsN !== args[i][STATS][ARG_COUNT])
|
1044
|
+
errors.add(
|
1045
|
+
`Incorrect number of arguments for (${
|
1046
|
+
args[i][STATS][SIGNATURE]
|
1047
|
+
}) the (lambda) argument of (${
|
1048
|
+
first[VALUE]
|
1049
|
+
}) at position (${i}). Expected (= ${
|
1050
|
+
args[i][STATS][ARG_COUNT]
|
1051
|
+
}) but got ${argsN} (${stringifyArgs(
|
1052
|
+
exp
|
1053
|
+
)}) (check #777)`
|
1054
|
+
)
|
1055
|
+
else {
|
1056
|
+
// ANONYMOUS LAMBDAS TYPE CHECKING
|
1057
|
+
const local = Object.create(env)
|
1058
|
+
const lambdaName = `${ANONYMOUS_FUNCTION_TYPE_PREFIX}${i}::${++scopeIndex}`
|
1059
|
+
check(
|
1060
|
+
[
|
1061
|
+
[APPLY, KEYWORDS.DEFINE_VARIABLE],
|
1062
|
+
[WORD, lambdaName],
|
1063
|
+
rest[i]
|
1064
|
+
],
|
1065
|
+
local,
|
1066
|
+
scope
|
1067
|
+
)
|
1068
|
+
// TODO delete this maybe
|
1069
|
+
// #C2
|
1070
|
+
// It will not be possilbe to know return type
|
1071
|
+
const match1 = () => {
|
1072
|
+
const actual = local[lambdaName]
|
1073
|
+
const expected = args[i]
|
1074
|
+
if (
|
1075
|
+
!isUnknownReturn(expected[STATS]) &&
|
1076
|
+
!isUnknownReturn(actual[STATS]) &&
|
1077
|
+
!compareReturns(
|
1078
|
+
expected[STATS],
|
1079
|
+
actual[STATS]
|
1080
|
+
)
|
1053
1081
|
)
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1082
|
+
errors.add(
|
1083
|
+
`Incorrect return type for (${
|
1084
|
+
expected[STATS][SIGNATURE]
|
1085
|
+
}) the (lambda) argument of (${
|
1086
|
+
first[VALUE]
|
1087
|
+
}) at position (${i}). Expected (${toTypeNames(
|
1088
|
+
getReturn(expected[STATS])
|
1089
|
+
)}) but got (${toTypeNames(
|
1090
|
+
getReturn(actual[STATS])
|
1091
|
+
)}) (${stringifyArgs(
|
1092
|
+
exp
|
1093
|
+
)}) (check #779)`
|
1094
|
+
)
|
1095
|
+
else if (
|
1096
|
+
actual[STATS].retried <
|
1097
|
+
MAX_RETRY_DEFINITION
|
1098
|
+
) {
|
1099
|
+
actual[STATS].retried += 1
|
1100
|
+
stack.unshift(() => match1())
|
1101
|
+
}
|
1102
|
+
}
|
1103
|
+
match1()
|
1104
|
+
for (
|
1105
|
+
let j = 0;
|
1106
|
+
j < args[i][STATS][ARGUMENTS].length;
|
1107
|
+
++j
|
1108
|
+
) {
|
1109
|
+
const match2 = () => {
|
1110
|
+
const actual =
|
1111
|
+
local[lambdaName][STATS][ARGUMENTS][j]
|
1112
|
+
const expected =
|
1113
|
+
args[i][STATS][ARGUMENTS][j]
|
1060
1114
|
if (
|
1061
|
-
!
|
1062
|
-
!
|
1063
|
-
!
|
1064
|
-
|
1065
|
-
|
1115
|
+
!isUnknownType(actual[STATS]) &&
|
1116
|
+
!isUnknownType(expected[STATS]) &&
|
1117
|
+
!compareTypes(
|
1118
|
+
actual[STATS],
|
1119
|
+
expected[STATS]
|
1066
1120
|
)
|
1067
1121
|
)
|
1068
|
-
|
1069
|
-
`Incorrect
|
1070
|
-
|
1071
|
-
})
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1122
|
+
errors.add(
|
1123
|
+
`Incorrect type for (lambda) (${
|
1124
|
+
args[i][STATS][SIGNATURE]
|
1125
|
+
}) argument at position (${j}) named as (${
|
1126
|
+
local[lambdaName][STATS][
|
1127
|
+
ARGUMENTS
|
1128
|
+
][j][STATS][SIGNATURE]
|
1129
|
+
}). Expected (${toTypeNames(
|
1130
|
+
getType(expected[STATS])
|
1075
1131
|
)}) but got (${toTypeNames(
|
1076
|
-
|
1132
|
+
getType(actual[STATS])
|
1077
1133
|
)}) (${stringifyArgs(
|
1078
1134
|
exp
|
1079
|
-
)}) (check #
|
1135
|
+
)}) (check #780)`
|
1080
1136
|
)
|
1081
1137
|
else if (
|
1082
1138
|
actual[STATS].retried <
|
1083
1139
|
MAX_RETRY_DEFINITION
|
1084
1140
|
) {
|
1085
1141
|
actual[STATS].retried += 1
|
1086
|
-
stack.unshift(() =>
|
1142
|
+
stack.unshift(() => match2())
|
1087
1143
|
}
|
1088
1144
|
}
|
1089
|
-
|
1090
|
-
for (
|
1091
|
-
let j = 0;
|
1092
|
-
j < args[i][STATS][ARGUMENTS].length;
|
1093
|
-
++j
|
1094
|
-
) {
|
1095
|
-
const match2 = () => {
|
1096
|
-
const actual =
|
1097
|
-
local[lambdaName][STATS][ARGUMENTS][
|
1098
|
-
j
|
1099
|
-
]
|
1100
|
-
const expected =
|
1101
|
-
args[i][STATS][ARGUMENTS][j]
|
1102
|
-
if (
|
1103
|
-
!isUnknownType(actual[STATS]) &&
|
1104
|
-
!isUnknownType(expected[STATS]) &&
|
1105
|
-
!compareTypes(
|
1106
|
-
actual[STATS],
|
1107
|
-
expected[STATS]
|
1108
|
-
)
|
1109
|
-
)
|
1110
|
-
errorStack.add(
|
1111
|
-
`Incorrect type for (lambda) (${
|
1112
|
-
args[i][STATS][SIGNATURE]
|
1113
|
-
}) argument at position (${j}) named as (${
|
1114
|
-
local[lambdaName][STATS][
|
1115
|
-
ARGUMENTS
|
1116
|
-
][j][STATS][SIGNATURE]
|
1117
|
-
}). Expected (${toTypeNames(
|
1118
|
-
getType(expected[STATS])
|
1119
|
-
)}) but got (${toTypeNames(
|
1120
|
-
getType(actual[STATS])
|
1121
|
-
)}) (${stringifyArgs(
|
1122
|
-
exp
|
1123
|
-
)}) (check #780)`
|
1124
|
-
)
|
1125
|
-
else if (
|
1126
|
-
actual[STATS].retried <
|
1127
|
-
MAX_RETRY_DEFINITION
|
1128
|
-
) {
|
1129
|
-
actual[STATS].retried += 1
|
1130
|
-
stack.unshift(() => match2())
|
1131
|
-
}
|
1132
|
-
}
|
1133
|
-
match2()
|
1134
|
-
}
|
1145
|
+
match2()
|
1135
1146
|
}
|
1136
|
-
} else {
|
1137
|
-
// TODO fix curry: lambdas enter here as undefined
|
1138
1147
|
}
|
1148
|
+
} else {
|
1149
|
+
// TODO fix curry: lambdas enter here as undefined
|
1139
1150
|
}
|
1140
|
-
|
1141
|
-
|
1142
|
-
|
1143
|
-
|
1144
|
-
|
1151
|
+
}
|
1152
|
+
break
|
1153
|
+
// case ATOM:
|
1154
|
+
// case COLLECTION:
|
1155
|
+
// break
|
1145
1156
|
}
|
1146
|
-
else if (
|
1147
|
-
isUnknownType(expected) &&
|
1148
|
-
args[i][STATS].retried < MAX_RETRY_DEFINITION
|
1149
|
-
) {
|
1150
|
-
args[i][STATS].retried += 1
|
1151
|
-
stack.unshift(() => match())
|
1152
1157
|
}
|
1158
|
+
else if (
|
1159
|
+
isUnknownType(expected) &&
|
1160
|
+
args[i][STATS].retried < MAX_RETRY_DEFINITION
|
1161
|
+
) {
|
1162
|
+
args[i][STATS].retried += 1
|
1163
|
+
stack.unshift(() => match())
|
1153
1164
|
}
|
1154
|
-
match()
|
1155
1165
|
}
|
1166
|
+
match()
|
1156
1167
|
}
|
1157
1168
|
}
|
1158
|
-
}
|
1169
|
+
}
|
1170
|
+
})
|
1159
1171
|
for (let i = 0; i < rest.length; ++i) {
|
1160
1172
|
const r = rest[i]
|
1161
1173
|
if (isLeaf(r) && r[TYPE] !== ATOM)
|
1162
1174
|
if (env[r[VALUE]] == undefined)
|
1163
|
-
|
1175
|
+
errors.add(
|
1164
1176
|
`(${
|
1165
1177
|
first[VALUE]
|
1166
1178
|
}) is trying to access undefined variable (${
|
@@ -1177,10 +1189,7 @@ export const typeCheck = (ast, error = true) => {
|
|
1177
1189
|
const copy = JSON.parse(JSON.stringify(ast))
|
1178
1190
|
check(copy, root, copy)
|
1179
1191
|
while (stack.length) stack.pop()()
|
1180
|
-
if (error)
|
1181
|
-
const issues = [...errorStack, ...warningStack]
|
1182
|
-
if (issues.length) throw new TypeError(issues.join('\n'))
|
1183
|
-
}
|
1192
|
+
if (error && errors.size) throw new TypeError([...errors.values()].join('\n'))
|
1184
1193
|
return [ast, Types]
|
1185
1194
|
}
|
1186
1195
|
export const type = (ast) => typeCheck(ast)[0]
|