UNPKG

fez-lisp

Version:

Lisp interpreted & compiled to JavaScript

1,562 lines (1,545 loc) 39.1 kB
import stdT from '../lib/baked/std-T.js' import std from '../lib/baked/std.js' import { getReturn, getReturns, getType, getTypes, isSubType } from './check.js' import { APPLY, ATOM, DEBUG, FLAG, KEYWORDS, PLACEHOLDER, STATIC_TYPES, TYPE, VALUE, WORD } from './keywords.js' import { isLeaf } from './parser.js' import { shakedList, stringifyArgs } from './utils.js' export const ARG_COUNT = 'argumentsN' export const VARIADIC = Infinity export const STATS = '__stats__' export const ARGUMENTS = 'arguments' export const RETURNS = 'returns' export const SCOPE_NAME = '__scope__' export const TYPE_PROP = 'type' export const SIGNATURE = 'name' export const TYPE_NAME = 'type_name' export const RETURN_NAME = 'return_name' export const UNBOUND_VARIABLE = '__unbound__' export const UNKNOWN = -1 export const COLLECTION = 3 export const BOOLEAN = 5 export const NUMBER = 6 export const ANY = 4 export const GENERIC = 7 export const ANONYMOUS_FUNCTION_TYPE_PREFIX = 'lambda::annonymous::' export const MAX_ARGUMENT_RETRY = 1 export const MAX_RETRY_DEFINITION = 30 export const IS_ARGUMENT = 'is_arg' export const NIL = 'nil' export const TRUE_WORD = 'true' export const FALSE_WORD = 'false' export const GET_ARRAY_INFERENCE_SET = new Set([ KEYWORDS.GET_ARRAY, 'array:get', 'array:at', 'array:first', 'array:second', 'array:third', 'array:last', 'array:pop!' ]) export class SubType { constructor(args) { this.types = [] this.types.push(...args) } add(type) { this.types.push(type) return this } has(type) { return this.types[0] === type } nestedLevels() { return this.types.length - 1 } isMatching(b) { for (let i = 0; i < this.types.length; ++i) { if ( this.types[i] == undefined || b.types[i] == undefined || this.types[i] === UNKNOWN || b.types[i] === UNKNOWN || this.types[i] === ANY || b.types[i] === ANY || this.types[i] === GENERIC || b.types[i] === GENERIC ) return true if (this.types[i] !== b.types[i]) return false } return true } get size() { return this.types.length } *[Symbol.iterator]() { for (let i = 0, len = this.size; i < len; ++i) yield this.types[i] } } export const BOOLEAN_SUBTYPE = () => new SubType([BOOLEAN]) export const COLLECTION_SUBTYPE = () => new SubType([COLLECTION]) export const NUMBER_SUBTYPE = () => new SubType([NUMBER]) export const GENERIC_SUBTYPE = () => new SubType([GENERIC]) export const ABSTRACTION_SUBTYPE = () => new SubType([APPLY]) export const UNKNOWN_SUBTYPE = () => new SubType([UNKNOWN]) const SPECIAL_BOOLEAN = BOOLEAN_SUBTYPE() const SPECIAL_COLLECTION = COLLECTION_SUBTYPE() const SPECIAL_NUMBER = NUMBER_SUBTYPE() const SPECIAL_ABSTRACTION = ABSTRACTION_SUBTYPE() export const toTypeNames = (type) => { switch (type) { case APPLY: return 'Abstraction' case BOOLEAN: return 'Boolean' case ATOM: return 'Atom' case NUMBER: return 'Number' case UNKNOWN: return 'Unknown' case COLLECTION: return 'Unknown[]' case ANY: return 'Any' case GENERIC: // return 'T' default: return 'Unknown' } } export const extractArrayType = (type) => { const arr = [...type].filter((x) => x === '[') return [type.replaceAll('[]', ''), arr.length] } const fillArrayType = (n) => Array.from({ length: n - 1 }).fill(COLLECTION) export const toTypeCodes = (type, i) => { const [t, n] = extractArrayType(type) switch (t) { case 'Abstraction': if (n) return [COLLECTION, new SubType(fillArrayType(n).concat(APPLY))] return [APPLY] case 'Boolean': if (n) return [COLLECTION, new SubType(fillArrayType(n).concat(BOOLEAN))] return [ATOM, BOOLEAN_SUBTYPE()] case 'Atom': if (n) return [COLLECTION, new SubType(fillArrayType(n).concat(ATOM))] return [ATOM] case 'Number': if (n) return [COLLECTION, new SubType(fillArrayType(n).concat(NUMBER))] return [ATOM, NUMBER_SUBTYPE()] case 'Unknown': if (n) return [COLLECTION, new SubType(fillArrayType(n))] return [UNKNOWN] case 'Any': return [ANY] default: { const d = type[0] === '[' ? -1 : 1 if (n) return [ COLLECTION, new SubType(fillArrayType(n).concat(UNKNOWN)), [i, d] ] return [UNKNOWN, undefined, [i, d]] } } } export const toTypeNamesAnyToUknown = (type) => { switch (type) { case ANY: return toTypeNames(UNKNOWN) default: return toTypeNames(type) } } export const GETTER = 1 export const SETTER = 2 export const SPECIAL_FORM_TYPES = { [SCOPE_NAME]: ';', // [ORDER]: 0, [STATIC_TYPES.ABSTRACTION]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: STATIC_TYPES.ABSTRACTION, retried: Infinity, [ARG_COUNT]: 1, [ARGUMENTS]: [ { [STATS]: { retried: Infinity, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [UNKNOWN], [RETURNS]: [UNKNOWN], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [APPLY] } }, [STATIC_TYPES.ABSTRACTIONS]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: STATIC_TYPES.ABSTRACTIONS, retried: Infinity, [ARG_COUNT]: 1, [ARGUMENTS]: [ { [STATS]: { retried: Infinity, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [UNKNOWN], [RETURNS]: [UNKNOWN], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [COLLECTION, SPECIAL_ABSTRACTION] } }, [STATIC_TYPES.ATOM]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: STATIC_TYPES.ATOM, retried: Infinity, [ARG_COUNT]: 1, [ARGUMENTS]: [ { [STATS]: { retried: Infinity, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [UNKNOWN], [RETURNS]: [UNKNOWN], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [ATOM] } }, [STATIC_TYPES.BOOLEAN]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: STATIC_TYPES.BOOLEAN, retried: Infinity, [ARG_COUNT]: 1, [ARGUMENTS]: [ { [STATS]: { retried: Infinity, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [UNKNOWN], [RETURNS]: [UNKNOWN], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [ATOM, SPECIAL_BOOLEAN] } }, [STATIC_TYPES.BOOLEANS]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: STATIC_TYPES.BOOLEANS, retried: Infinity, [ARG_COUNT]: 1, [ARGUMENTS]: [ { [STATS]: { retried: Infinity, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [UNKNOWN], [RETURNS]: [UNKNOWN], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [COLLECTION, SPECIAL_BOOLEAN] } }, [STATIC_TYPES.NUMBER]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: STATIC_TYPES.NUMBER, retried: Infinity, [ARG_COUNT]: 1, [ARGUMENTS]: [ { [STATS]: { retried: Infinity, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [UNKNOWN], [RETURNS]: [UNKNOWN], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [ATOM, SPECIAL_NUMBER] } }, [STATIC_TYPES.NUMBERS]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: STATIC_TYPES.NUMBERS, retried: Infinity, [ARG_COUNT]: 1, [ARGUMENTS]: [ { [STATS]: { retried: Infinity, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [UNKNOWN], [RETURNS]: [UNKNOWN], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [COLLECTION, SPECIAL_NUMBER] } }, [STATIC_TYPES.COLLECTION]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: STATIC_TYPES.COLLECTION, retried: Infinity, [ARG_COUNT]: 1, [ARGUMENTS]: [ { [STATS]: { retried: Infinity, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [UNKNOWN], [RETURNS]: [UNKNOWN], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [COLLECTION] } }, [STATIC_TYPES.COLLECTIONS]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: STATIC_TYPES.COLLECTIONS, retried: Infinity, [ARG_COUNT]: 1, [ARGUMENTS]: [ { [STATS]: { retried: Infinity, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [UNKNOWN], [RETURNS]: [UNKNOWN], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [COLLECTION, SPECIAL_COLLECTION] } }, [STATIC_TYPES.UNKNOWN]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: STATIC_TYPES.UNKNOWN, retried: Infinity, [ARG_COUNT]: 1, [ARGUMENTS]: [ { [STATS]: { retried: Infinity, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [UNKNOWN], [RETURNS]: [UNKNOWN], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [UNKNOWN] } }, [STATIC_TYPES.ANY]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: STATIC_TYPES.ANY, retried: Infinity, [ARG_COUNT]: 1, [ARGUMENTS]: [ { [STATS]: { retried: Infinity, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [UNKNOWN], [RETURNS]: [UNKNOWN], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [ANY] } }, [DEBUG.LOG]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: DEBUG.LOG, retried: Infinity, [ARGUMENTS]: [ { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [UNKNOWN], [RETURNS]: [UNKNOWN], [ARGUMENTS]: [], [ARG_COUNT]: 0 } }, { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [COLLECTION], [RETURNS]: [COLLECTION], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [ARG_COUNT]: 2, [RETURNS]: [UNKNOWN] } }, [DEBUG.STRING]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: DEBUG.STRING, retried: Infinity, [ARG_COUNT]: 1, [ARGUMENTS]: [ { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [COLLECTION], [RETURNS]: [COLLECTION], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [COLLECTION] } }, [DEBUG.UNQUOTED_STRING]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: DEBUG.UNQUOTED_STRING, retried: Infinity, [ARG_COUNT]: 1, [ARGUMENTS]: [ { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [COLLECTION], [RETURNS]: [COLLECTION], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [COLLECTION] } }, [DEBUG.SIGNATURE]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: DEBUG.SIGNATURE, retried: Infinity, [ARG_COUNT]: VARIADIC, [RETURNS]: [UNKNOWN] } }, [DEBUG.TYPE_SIGNATURE]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: DEBUG.TYPE_SIGNATURE, retried: Infinity, [ARG_COUNT]: VARIADIC, [RETURNS]: [UNKNOWN] } }, [KEYWORDS.BLOCK]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: KEYWORDS.BLOCK, retried: Infinity, [ARG_COUNT]: VARIADIC, [RETURNS]: [UNKNOWN] } }, [KEYWORDS.ANONYMOUS_FUNCTION]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: KEYWORDS.ANONYMOUS_FUNCTION, retried: Infinity, [ARG_COUNT]: VARIADIC, [RETURNS]: [APPLY] } }, [KEYWORDS.CALL_FUNCTION]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: KEYWORDS.CALL_FUNCTION, retried: Infinity, [ARG_COUNT]: VARIADIC, [RETURNS]: [UNKNOWN] } }, [KEYWORDS.CREATE_ARRAY]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: KEYWORDS.CREATE_ARRAY, retried: Infinity, [ARG_COUNT]: VARIADIC, [RETURNS]: [COLLECTION] } }, [KEYWORDS.LOOP]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: KEYWORDS.LOOP, retried: Infinity, [ARG_COUNT]: 2, [ARGUMENTS]: [ { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM], [RETURNS]: [ATOM], [ARGUMENTS]: [], [ARG_COUNT]: 0 } }, { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ANY], [RETURNS]: [ANY], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [ATOM] } }, [KEYWORDS.ADDITION]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: KEYWORDS.ADDITION, retried: Infinity, [ARG_COUNT]: 2, [ARGUMENTS]: [ { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_NUMBER], [RETURNS]: [ATOM, SPECIAL_NUMBER], [ARGUMENTS]: [], [ARG_COUNT]: 0 } }, { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_NUMBER], [RETURNS]: [ATOM, SPECIAL_NUMBER], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [ATOM, SPECIAL_NUMBER] } }, [KEYWORDS.MULTIPLICATION]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: KEYWORDS.MULTIPLICATION, retried: Infinity, [ARG_COUNT]: 2, [ARGUMENTS]: [ { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_NUMBER], [RETURNS]: [ATOM, SPECIAL_NUMBER], [ARGUMENTS]: [], [ARG_COUNT]: 0 } }, { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_NUMBER], [RETURNS]: [ATOM, SPECIAL_NUMBER], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [ATOM, SPECIAL_NUMBER] } }, [KEYWORDS.SUBTRACTION]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: KEYWORDS.SUBTRACTION, retried: Infinity, [ARG_COUNT]: 2, [ARGUMENTS]: [ { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_NUMBER], [RETURNS]: [ATOM, SPECIAL_NUMBER], [ARGUMENTS]: [], [ARG_COUNT]: 0 } }, { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_NUMBER], [RETURNS]: [ATOM, SPECIAL_NUMBER], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [ATOM, SPECIAL_NUMBER] } }, [KEYWORDS.DIVISION]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: KEYWORDS.DIVISION, retried: Infinity, [ARG_COUNT]: 2, [ARGUMENTS]: [ { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_NUMBER], [RETURNS]: [ATOM, SPECIAL_NUMBER], [ARGUMENTS]: [], [ARG_COUNT]: 0 } }, { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_NUMBER], [RETURNS]: [ATOM, SPECIAL_NUMBER], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [ATOM, SPECIAL_NUMBER] } }, [KEYWORDS.REMAINDER_OF_DIVISION]: { [STATS]: { [TYPE_PROP]: [APPLY], retried: Infinity, [ARG_COUNT]: 2, [ARGUMENTS]: [ { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_NUMBER], [RETURNS]: [ATOM, SPECIAL_NUMBER], [ARGUMENTS]: [], [ARG_COUNT]: 0 } }, { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_NUMBER], [RETURNS]: [ATOM, SPECIAL_NUMBER], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [ATOM, SPECIAL_NUMBER] } }, [KEYWORDS.BITWISE_AND]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: KEYWORDS.BITWISE_AND, retried: Infinity, [ARG_COUNT]: 2, [ARGUMENTS]: [ { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_NUMBER], [RETURNS]: [ATOM, SPECIAL_NUMBER], [ARGUMENTS]: [], [ARG_COUNT]: 0 } }, { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_NUMBER], [RETURNS]: [ATOM, SPECIAL_NUMBER], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [ATOM, SPECIAL_NUMBER] } }, [KEYWORDS.BITWISE_NOT]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: KEYWORDS.BITWISE_NOT, retried: Infinity, [ARG_COUNT]: 1, [ARGUMENTS]: [ { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_NUMBER], [RETURNS]: [ATOM, SPECIAL_NUMBER], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [ATOM, SPECIAL_NUMBER] } }, [KEYWORDS.BITWISE_OR]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: KEYWORDS.BITWISE_OR, retried: Infinity, [ARG_COUNT]: 2, [ARGUMENTS]: [ { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_NUMBER], [RETURNS]: [ATOM, SPECIAL_NUMBER], [ARGUMENTS]: [], [ARG_COUNT]: 0 } }, { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_NUMBER], [RETURNS]: [ATOM, SPECIAL_NUMBER], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [ATOM, SPECIAL_NUMBER] } }, [KEYWORDS.BITWISE_XOR]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: KEYWORDS.BITWISE_XOR, retried: Infinity, [ARG_COUNT]: 2, [ARGUMENTS]: [ { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_NUMBER], [RETURNS]: [ATOM, SPECIAL_NUMBER], [ARGUMENTS]: [], [ARG_COUNT]: 0 } }, { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_NUMBER], [RETURNS]: [ATOM, SPECIAL_NUMBER], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [ATOM, SPECIAL_NUMBER] } }, [KEYWORDS.BITWISE_LEFT_SHIFT]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: KEYWORDS.BITWISE_LEFT_SHIFT, retried: Infinity, [ARG_COUNT]: 2, [ARGUMENTS]: [ { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_NUMBER], [RETURNS]: [ATOM, SPECIAL_NUMBER], [ARGUMENTS]: [], [ARG_COUNT]: 0 } }, { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_NUMBER], [RETURNS]: [ATOM, SPECIAL_NUMBER], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [ATOM, SPECIAL_NUMBER] } }, [KEYWORDS.BITWISE_RIGHT_SHIFT]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: KEYWORDS.BITWISE_RIGHT_SHIFT, retried: Infinity, [ARG_COUNT]: 2, [ARGUMENTS]: [ { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_NUMBER], [RETURNS]: [ATOM, SPECIAL_NUMBER], [ARGUMENTS]: [], [ARG_COUNT]: 0 } }, { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_NUMBER], [RETURNS]: [ATOM, SPECIAL_NUMBER], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [ATOM, SPECIAL_NUMBER] } }, [KEYWORDS.GET_ARRAY]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: KEYWORDS.GET_ARRAY, tag: GETTER, retried: Infinity, [ARG_COUNT]: 2, [ARGUMENTS]: [ { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [COLLECTION], [RETURNS]: [COLLECTION], [ARGUMENTS]: [], [ARG_COUNT]: 0 } }, { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_NUMBER], [RETURNS]: [ATOM, SPECIAL_NUMBER], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [ANY] } }, [KEYWORDS.SET_ARRAY]: { [STATS]: { [TYPE_PROP]: [APPLY], tag: SETTER, retried: Infinity, [ARG_COUNT]: 3, [ARGUMENTS]: [ { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [COLLECTION], [RETURNS]: [COLLECTION], [ARGUMENTS]: [], [ARG_COUNT]: 0 } }, { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_NUMBER], [RETURNS]: [ATOM, SPECIAL_NUMBER], [ARGUMENTS]: [], [ARG_COUNT]: 0 } }, { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ANY], [RETURNS]: [ANY], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [COLLECTION] } }, [KEYWORDS.POP_ARRAY]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: KEYWORDS.POP_ARRAY, retried: Infinity, [ARG_COUNT]: 1, [ARGUMENTS]: [ { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [COLLECTION], [RETURNS]: [COLLECTION], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], // [GENERIC, new SubType([PLACEHOLDER]), 0] [RETURNS]: [COLLECTION] } }, [KEYWORDS.ARRAY_LENGTH]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: KEYWORDS.ARRAY_LENGTH, retried: Infinity, [ARG_COUNT]: 1, [ARGUMENTS]: [ { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [COLLECTION], [RETURNS]: [COLLECTION], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [ATOM, SPECIAL_NUMBER] } }, [KEYWORDS.IF]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: KEYWORDS.IF, retried: Infinity, [ARG_COUNT]: 3, [ARGUMENTS]: [ { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_BOOLEAN], [RETURNS]: [ATOM, SPECIAL_BOOLEAN], [ARGUMENTS]: [], [ARG_COUNT]: 0 } }, { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ANY], [RETURNS]: [ANY], [ARGUMENTS]: [], [ARG_COUNT]: 0 } }, { [STATS]: { retried: 0, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ANY], [RETURNS]: [ANY], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [ANY] } }, [KEYWORDS.NOT]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: KEYWORDS.NOT, retried: Infinity, [ARG_COUNT]: 1, [ARGUMENTS]: [ { [STATS]: { retried: Infinity, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_BOOLEAN], [RETURNS]: [ATOM, SPECIAL_BOOLEAN], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [ATOM, SPECIAL_BOOLEAN] } }, [KEYWORDS.EQUAL]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: KEYWORDS.EQUAL, retried: Infinity, [ARG_COUNT]: 2, [ARGUMENTS]: [ { [STATS]: { retried: Infinity, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM], [RETURNS]: [ATOM], [ARGUMENTS]: [], [ARG_COUNT]: 0 } }, { [STATS]: { retried: Infinity, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM], [RETURNS]: [ATOM], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [ATOM, SPECIAL_BOOLEAN] } }, [KEYWORDS.LESS_THAN]: { [STATS]: { [TYPE_PROP]: [APPLY], retried: Infinity, [SIGNATURE]: KEYWORDS.LESS_THAN, [ARG_COUNT]: 2, [ARGUMENTS]: [ { [STATS]: { retried: Infinity, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_NUMBER], [RETURNS]: [ATOM, SPECIAL_NUMBER], [ARGUMENTS]: [], [ARG_COUNT]: 0 } }, { [STATS]: { retried: Infinity, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_NUMBER], [RETURNS]: [ATOM, SPECIAL_NUMBER], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [ATOM, SPECIAL_BOOLEAN] } }, [KEYWORDS.GREATHER_THAN]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: KEYWORDS.GREATHER_THAN, retried: Infinity, [ARG_COUNT]: 2, [ARGUMENTS]: [ { [STATS]: { retried: Infinity, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_NUMBER], [RETURNS]: [ATOM, SPECIAL_NUMBER], [ARGUMENTS]: [], [ARG_COUNT]: 0 } }, { [STATS]: { retried: Infinity, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_NUMBER], [RETURNS]: [ATOM, SPECIAL_NUMBER], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [ATOM, SPECIAL_BOOLEAN] } }, [KEYWORDS.GREATHER_THAN_OR_EQUAL]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: KEYWORDS.GREATHER_THAN_OR_EQUAL, retried: Infinity, [ARG_COUNT]: 2, [ARGUMENTS]: [ { [STATS]: { retried: Infinity, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_NUMBER], [RETURNS]: [ATOM, SPECIAL_NUMBER], [ARGUMENTS]: [], [ARG_COUNT]: 0 } }, { [STATS]: { retried: Infinity, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_NUMBER], [RETURNS]: [ATOM, SPECIAL_NUMBER], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [ATOM, SPECIAL_BOOLEAN] } }, [KEYWORDS.LESS_THAN_OR_EQUAL]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: KEYWORDS.LESS_THAN_OR_EQUAL, retried: Infinity, [ARG_COUNT]: 2, [ARGUMENTS]: [ { [STATS]: { retried: Infinity, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_NUMBER], [RETURNS]: [ATOM, SPECIAL_NUMBER], [ARGUMENTS]: [], [ARG_COUNT]: 0 } }, { [STATS]: { retried: Infinity, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_NUMBER], [RETURNS]: [ATOM, SPECIAL_NUMBER], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [ATOM, SPECIAL_BOOLEAN] } }, [KEYWORDS.AND]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: KEYWORDS.AND, retried: Infinity, [ARG_COUNT]: 2, [ARGUMENTS]: [ { [STATS]: { retried: Infinity, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_BOOLEAN], [RETURNS]: [ATOM, SPECIAL_BOOLEAN], [ARGUMENTS]: [], [ARG_COUNT]: 0 } }, { [STATS]: { retried: Infinity, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_BOOLEAN], [RETURNS]: [ATOM, SPECIAL_BOOLEAN], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [ATOM, SPECIAL_BOOLEAN] } }, [KEYWORDS.OR]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: KEYWORDS.OR, retried: Infinity, [ARG_COUNT]: 2, [ARGUMENTS]: [ { [STATS]: { retried: Infinity, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_BOOLEAN], [RETURNS]: [ATOM, SPECIAL_BOOLEAN], [ARGUMENTS]: [], [ARG_COUNT]: 0 } }, { [STATS]: { retried: Infinity, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ATOM, SPECIAL_BOOLEAN], [RETURNS]: [ATOM, SPECIAL_BOOLEAN], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [ATOM, SPECIAL_BOOLEAN] } }, [KEYWORDS.IS_ATOM]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: KEYWORDS.IS_ATOM, retried: Infinity, [ARG_COUNT]: 1, [ARGUMENTS]: [ { [STATS]: { retried: Infinity, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ANY], [RETURNS]: [ANY], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [ATOM, SPECIAL_BOOLEAN] } }, [KEYWORDS.IS_LAMBDA]: { [STATS]: { [TYPE_PROP]: [APPLY], [SIGNATURE]: KEYWORDS.IS_LAMBDA, retried: Infinity, [ARG_COUNT]: 1, [ARGUMENTS]: [ { [STATS]: { retried: Infinity, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [ANY], [RETURNS]: [ANY], [ARGUMENTS]: [], [ARG_COUNT]: 0 } } ], [RETURNS]: [ATOM, SPECIAL_BOOLEAN] } } } export const formatSubType = (T) => { switch (T[0]) { case COLLECTION: return `${ isSubType(T[1]) ? T[1].has(COLLECTION) ? `${toTypeNamesAnyToUknown(T[1].types.at(-1))}${'[]'.repeat( T[1].types.length - 1 )}` : toTypeNamesAnyToUknown(T[1].types[0]) || toTypeNames(UNKNOWN) : toTypeNames(UNKNOWN) }[]` case ATOM: return `${ isSubType(T[1]) ? toTypeNamesAnyToUknown(T[1].types[0]) : toTypeNamesAnyToUknown(NUMBER) }` default: return toTypeNamesAnyToUknown(T[0]) } } export const formatType = (name, env) => { const stats = env[name][STATS] const isAnonymous = typeof name === 'number' return stats ? getType(stats) === APPLY ? `${isAnonymous ? '' : `(${STATIC_TYPES.DEFINE_TYPE} ${name} `}(lambda ${ stats[ARG_COUNT] === VARIADIC ? '... ' : stats[ARGUMENTS]?.length ? stats[ARGUMENTS].map( (x, i) => `${ getType(x[STATS]) === APPLY ? `${formatType(i, stats[ARGUMENTS])}` : `${formatSubType(getTypes(x[STATS]))}` }` ).join(' ') + ' ' : '' // TODO format returned functions when type support is added }(${KEYWORDS.BLOCK} ${formatSubType(getReturns(stats))})${ isAnonymous ? '' : ')' })` : `(${STATIC_TYPES.DEFINE_TYPE} ${name} ${formatSubType( getTypes(stats) )})` : name } export const formatInlineType = (name, env) => { const stats = env[name][STATS] return stats ? getType(stats) === APPLY ? `(lambda ${ stats[ARG_COUNT] === VARIADIC ? '... ' : stats[ARGUMENTS]?.length ? stats[ARGUMENTS].map( (x, i) => `${ getType(x[STATS]) === APPLY ? `${formatType(i, stats[ARGUMENTS])}` : `${formatSubType(getTypes(x[STATS]))}` }` ).join(' ') + ' ' : '' // TODO format returned functions when type support is added }(${KEYWORDS.BLOCK} ${formatSubType(getReturns(stats))}))` : formatSubType(getTypes(stats)) : name } export const formatAstSubType = (T) => { switch (T[0]) { case COLLECTION: return `${ isSubType(T[1]) ? [...T[1]] .map((x) => x === COLLECTION ? formatAstSubType([x]) : toTypeNamesAnyToUknown(x) ) .join(' ') || toTypeNames(UNKNOWN) : toTypeNames(UNKNOWN) }[]` case ATOM: return `${ isSubType(T[1]) ? [...T[1]].map((x) => toTypeNamesAnyToUknown(x)).join(' ') : toTypeNamesAnyToUknown(NUMBER) }` default: return toTypeNamesAnyToUknown(T[0]) } } export const formatAstTypes = (name, env) => { const stats = env[name][STATS] return stats ? getType(stats) === APPLY ? [ FLAG, ...(stats[ARG_COUNT] === VARIADIC ? [] : stats[ARGUMENTS]?.length ? stats[ARGUMENTS].map((x, i) => getType(x[STATS]) === APPLY ? formatAstTypes(i, stats[ARGUMENTS]) : formatAstSubType(getTypes(x[STATS])) ) : []), formatAstSubType(getReturns(stats)) ] : [FLAG, formatAstSubType(getTypes(stats))] : [FLAG, name] } export const validateLambda = (exp, name) => { if (exp.length === 1) throw new TypeError( `Incorrect number of arguments for (${ KEYWORDS.ANONYMOUS_FUNCTION }). Expected at least 1 (the lambda body) but got 1 (${stringifyArgs( exp )})` ) if (name) for (let i = 0; i < exp.length - 1; ++i) if (exp[i][VALUE] === name) throw new TypeError( `Arguments of (${ KEYWORDS.ANONYMOUS_FUNCTION }) Should not have the same name as they were declared (${stringifyArgs( exp )})` ) } export const lambdaType = (t) => [t.slice(1, -1), t.at(-1)[1]] export const toArgType = (A, i) => { const out = [] const arg = isLeaf(A) ? A : A[0] if (arg[TYPE] === APPLY) { const [args, returns] = lambdaType(A) out.push({ [STATS]: { argIndex: i, retried: Infinity, [IS_ARGUMENT]: true, [SIGNATURE]: PLACEHOLDER, [TYPE_PROP]: [APPLY], [TYPE_NAME]: PLACEHOLDER, [RETURN_NAME]: returns[VALUE].replaceAll('[', '').replaceAll(']', ''), [RETURNS]: toTypeCodes(returns[VALUE], i), [ARGUMENTS]: args.map(toArgType).flat(1), [ARG_COUNT]: args.length } }) } else { out.push({ [STATS]: { argIndex: i, retried: Infinity, [IS_ARGUMENT]: true, [SIGNATURE]: PLACEHOLDER, [TYPE_NAME]: arg[VALUE].replaceAll('[', '').replaceAll(']', ''), [TYPE_PROP]: toTypeCodes(arg[VALUE], i), [RETURNS]: toTypeCodes(arg[VALUE], i), [ARGUMENTS]: [], [ARG_COUNT]: 0 } }) } return out } export const fromSourceToType = (T) => { const out = {} for (const t of T) { const name = t[1][VALUE] const [args, returns] = lambdaType(t[2]) out[name] = { [STATS]: { retried: Infinity, [TYPE_PROP]: [APPLY], [SIGNATURE]: name, [TYPE_NAME]: name, [RETURN_NAME]: returns[VALUE].replaceAll('[', '').replaceAll(']', ''), [ARG_COUNT]: args.length, [ARGUMENTS]: args.map(toArgType).flat(1), [RETURNS]: toTypeCodes( returns[VALUE], args.findIndex( (x) => !Array.isArray(x[VALUE]) && x[VALUE] === returns[VALUE].replaceAll('[', '').replaceAll(']', '') ) ) } } } return out } export const withCtxTypes = (T) => ({ ...SPECIAL_FORM_TYPES, ...T }) export const filteredDefinedTypes = (program, lib, libT) => { const deps = new Set(shakedList(program, lib)) return libT.filter((x) => deps.has(x[1][1])) } export const definedTypes = (T) => fromSourceToType(T) export const withStdDefinedTypes = (ast) => withCtxTypes(definedTypes(filteredDefinedTypes(ast, std, stdT))) export const extractTypes = (source) => { let types = '' const src = source.replaceAll(/\(the.+\)/g, (match, token) => { types += match + '\n' return '' }) return [src, types] }