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