type.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547
  1. /**
  2. * Type System
  3. *
  4. * Types are runtime-manipulatable objects in this language. This idea is
  5. * inspired by the Set Theory.
  6. * A type object T contains a [Checker] function that takes an argument x,
  7. * and returns a boolean value which indicates whether x ∈ T.
  8. * In other words, a type object is no more than an encapsulation of a
  9. * single-parameter boolean-valued function.
  10. */
  11. const Checker = Symbol('Checker')
  12. const ValueName = Symbol('ValueName')
  13. /**
  14. * Simplist type object containing no extra data.
  15. */
  16. class SimpleType {
  17. constructor (checker) {
  18. assert(typeof checker == 'function')
  19. this[Checker] = checker
  20. Object.freeze(this)
  21. }
  22. get [Symbol.toStringTag]() {
  23. return 'SimpleType'
  24. }
  25. }
  26. /* shorthand */
  27. let $ = f => new SimpleType(f)
  28. /* universe set Ω */
  29. let Any = $(x => true)
  30. /* empty set ∅ */
  31. let Never = $(x => false)
  32. /**
  33. * `Type` is the definition of type object,
  34. * which is also a type object.
  35. */
  36. let Type = $(x => (
  37. (x !== null)
  38. && typeof x == 'object'
  39. && typeof x[Checker] == 'function'
  40. && assert(Object.isFrozen(x))
  41. ))
  42. /**
  43. * Definition of value ∈ type
  44. */
  45. function is (value, type) {
  46. assert(Type[Checker](type))
  47. let r = type[Checker](value)
  48. assert(typeof r == 'boolean')
  49. return r
  50. }
  51. /**
  52. * Definition of intersect ⋂, union ⋃, and complement ∁
  53. *
  54. * An instance of CompoundType is called compound type, meanwhile
  55. * a type that isn't a compound type is called an atomic type.
  56. * The propose to define this class is to provide a mechanics to
  57. * determine if two types are logical equivalent, such as
  58. * ∁(Ω, A ∪ B) ⇔ ∁(Ω, A) ∩ ∁(Ω, B) but ⇎ ∁(Ω, A) ∪ ∁(Ω, B),
  59. * Above equivalency checking is possible because through extracting
  60. * all atomic types depended by the compound type, we can treat
  61. * the compond type as a propositional formula and evaluate it
  62. * over a truth table of all atomic types depended by it.
  63. */
  64. class CompoundType {
  65. constructor (op, args) {
  66. /**
  67. * Opcode Definition:
  68. * 0. intersect: ⋂ T, for T in args
  69. * 1. union: ⋃ T, for T in args
  70. * 2. complement: ∁(Ω, T), where T = args[0]
  71. * 3. wrap: equivalence of T, where T = args[0]
  72. */
  73. assert(exists([0,1,2,3], v => op == v))
  74. assert(args instanceof Array)
  75. assert(forall(args, arg => is(arg, Type)))
  76. if (op == 2 || op == 3) { assert(args.length == 1) }
  77. this.op = op
  78. this.args = copy(args)
  79. if (this.op == 0) {
  80. // ∀ T, T ∩ Ω = T
  81. this.args = this.args.filter(T => !is_any(T))
  82. // ∀ T, T ∩ ∅ = ∅
  83. if (exists(this.args, T => is_never(T))) {
  84. this.op = 3
  85. this.args = [Never]
  86. }
  87. }
  88. if (this.op == 1) {
  89. // ∀ T, T ∪ ∅ = T
  90. this.args = this.args.filter(T => !is_never(T))
  91. // ∀ T, T ∪ Ω = Ω
  92. if (exists(this.args, T => is_any(T))) {
  93. this.op = 3
  94. this.args = [Any]
  95. }
  96. }
  97. if (this.op == 2) {
  98. let arg = this.args[0]
  99. if (is_any(arg)) {
  100. // ∁(Ω, Ω) = ∅
  101. this.op = 3
  102. this.args = [Never]
  103. } else if (is_never(arg)) {
  104. // C(Ω, ∅) = Ω
  105. this.op = 3
  106. this.args = [Any]
  107. }
  108. }
  109. this.atomic_args = extract_atomic_args(this.args)
  110. Object.freeze(this.args)
  111. Object.freeze(this.atomic_args)
  112. if (this.op == 0) {
  113. this[Checker] = x => forall(this.args, T => T[Checker](x))
  114. } else if (this.op == 1) {
  115. this[Checker] = x => exists(this.args, T => T[Checker](x))
  116. } else if (this.op == 2) {
  117. this[Checker] = x => !(this.args[0][Checker](x))
  118. } else {
  119. this[Checker] = this.args[0][Checker]
  120. }
  121. Object.freeze(this)
  122. }
  123. evaluate (value_map) {
  124. // evaluate the type using a truth table of its atomic arguments
  125. assert(value_map instanceof Map)
  126. if (this.op == 0) {
  127. // intersect
  128. return forall(this.args, T => evaluate_type(T, value_map))
  129. } else if (this.op == 1) {
  130. // union
  131. return exists(this.args, T => evaluate_type(T, value_map))
  132. } else if (this.op == 2) {
  133. // complement
  134. return !(evaluate_type(this.args[0], value_map))
  135. } else if (this.op == 3) {
  136. // just wrap it
  137. return evaluate_type(this.args[0], value_map)
  138. }
  139. }
  140. }
  141. function is_any (T) {
  142. return (
  143. (T === Any)
  144. || (T instanceof CompoundType && T.op == 3 && T.args[0] === Any)
  145. )
  146. }
  147. function is_never (T) {
  148. return (
  149. (T === Never)
  150. || (T instanceof CompoundType && T.op == 3 && T.args[0] === Never)
  151. )
  152. }
  153. function extract_atomic_args (args) {
  154. return new Set((function* () {
  155. for (let T of args) {
  156. assert(is(T, Type))
  157. if (T instanceof CompoundType) {
  158. for (let arg of T.atomic_args) {
  159. yield arg
  160. }
  161. } else {
  162. yield T
  163. }
  164. }
  165. })())
  166. }
  167. function evaluate_type (T, value_map) {
  168. if (T instanceof CompoundType) {
  169. // evaluate recursively
  170. return T.evaluate(value_map)
  171. } else {
  172. // read from the truth table
  173. assert(value_map.has(T))
  174. return Boolean(value_map.get(T))
  175. }
  176. }
  177. function type_equivalent (T1, T2) {
  178. assert(is(T1, Type) && is(T2, Type))
  179. // optimization
  180. if (T1 === T2) {
  181. return true
  182. }
  183. // wrap atomic types
  184. if (!(T1 instanceof CompoundType)) {
  185. T1 = new CompoundType(3, [T1])
  186. }
  187. if (!(T2 instanceof CompoundType)) {
  188. T2 = new CompoundType(3, [T2])
  189. }
  190. // check if T1 and T2 have same dependencies
  191. if (!set_equal(T1.atomic_args, T2.atomic_args)) {
  192. return false
  193. }
  194. // prepare the truth table
  195. let args = list(T1.atomic_args)
  196. let L = args.length
  197. let N = Math.pow(2, L)
  198. assert(Number.isSafeInteger(N))
  199. let value_map = new Map()
  200. for (let arg of args) {
  201. value_map.set(arg, false)
  202. }
  203. // iterate over the truth table
  204. let i = 0
  205. let j = 0
  206. while (i < N) {
  207. if (T1.evaluate(value_map) != T2.evaluate(value_map)) {
  208. return false
  209. }
  210. // do a binary addition
  211. for (j = 0; j < L; j++) {
  212. if (value_map.get(args[j]) == false) {
  213. value_map.set(args[j], true)
  214. break
  215. } else {
  216. value_map.set(args[j], false)
  217. }
  218. }
  219. i += 1
  220. }
  221. return true
  222. }
  223. /**
  224. * Basic Type Operators
  225. */
  226. function intersect (types) {
  227. // (⋂ T), for T in types
  228. return new CompoundType(0, types)
  229. }
  230. function union (types) {
  231. // (⋃ T), for T in types
  232. return new CompoundType(1, types)
  233. }
  234. function complement (type) {
  235. // (∁ T)
  236. return new CompoundType(2, [type])
  237. }
  238. /* shorthand */
  239. let Uni = ((...args) => union(args)) // (A,B,...) => A ∪ B ∪ ...
  240. let Ins = ((...args) => intersect(args)) // (A,B,...) => A ∩ B ∩ ...
  241. let Not = (arg => complement(arg)) // A => ∁(Ω, A)
  242. /**
  243. * Singleton Type
  244. *
  245. * A singleton type S is defined by S = { x | x === S },
  246. * i.e. (x ∈ S) if and only if (x === S).
  247. * Singleton types may be used as unique special values or enum values,
  248. * such as Nil, Void and FoobarEnum.Foo.
  249. */
  250. function create_value (name) {
  251. assert(typeof name == 'string')
  252. // use a null prototype to disable == conversion with primitive values
  253. let value = Object.create(null)
  254. value[ValueName] = name
  255. value[Checker] = (x => x === value)
  256. Object.freeze(value)
  257. return value
  258. }
  259. let Singleton = $(x => typeof x[ValueName] == 'string')
  260. let Nil = create_value('Nil')
  261. let Void = create_value('Void')
  262. /**
  263. * Collection type that only contains a specific list of objects.
  264. */
  265. class FiniteSetType {
  266. constructor (objects) {
  267. assert(objects instanceof Array)
  268. assert(objects.length > 0)
  269. this.objects = copy(objects)
  270. Object.freeze(this.objects)
  271. this[Checker] = x => {
  272. if (is(x, Type)) {
  273. return exists (
  274. this.objects,
  275. o => is(o, Type) && type_equivalent(o, x)
  276. )
  277. } else {
  278. return exists(this.objects, o => o === x)
  279. }
  280. }
  281. Object.freeze(this)
  282. }
  283. get [Symbol.toStringTag]() {
  284. return 'FiniteSetType'
  285. }
  286. }
  287. // shorthand
  288. let one_of = ((...objects) => new FiniteSetType(objects))
  289. /**
  290. * ES6 Raw Types (Modified from Original Definition)
  291. */
  292. let ES = {
  293. Undefined: $(x => typeof x == 'undefined'),
  294. Null: $(x => x === null),
  295. Boolean: $(x => typeof x == 'boolean'),
  296. Number: $(x => (
  297. typeof x == 'number'
  298. && !Number.isNaN(x) // NaN is called "not a number"
  299. && Number.isFinite(x) // Inifinite breaks the number system
  300. )),
  301. NaN: $(x => Number.isNaN(x)),
  302. Infinite: $(x => !Number.isFinite(x) && !Number.isNaN(x)),
  303. String: $(x => typeof x == 'string'),
  304. Symbol: $(x => typeof x == 'symbol'),
  305. Function: $(x => typeof x == 'function'),
  306. Object: $(x => typeof x == 'object' && x !== null),
  307. Iterable: $(x => (
  308. typeof x == 'string'
  309. || (
  310. typeof x == 'object'
  311. && x !== null
  312. && typeof x[Symbol.iterator] == 'function'
  313. )
  314. )),
  315. AsyncIterable: $(x => (
  316. typeof x == 'object'
  317. && x !== null
  318. && typeof x[Symbol.asyncIterator] == 'function'
  319. ))
  320. }
  321. /**
  322. * Basic Types
  323. */
  324. let Types = {
  325. /* Special Types */
  326. Type, Any, Never, Nil, Void,
  327. Object: Any,
  328. /* Primitive Value Types */
  329. String: ES.String,
  330. Bool: ES.Boolean,
  331. Number: ES.Number,
  332. NaN: ES.NaN,
  333. Infinite: ES.Infinite,
  334. Int: $(x => Number.isSafeInteger(x)),
  335. GeneralNumber: $(x => typeof x == 'number'),
  336. Primitive: Uni(ES.Number, ES.String, ES.Boolean),
  337. /* Basic Container Types */
  338. List: $(x => x instanceof Array),
  339. Hash: Ins(ES.Object, $(x => get_proto(x) === Object.prototype)),
  340. /* ECMAScript Compatible Types */
  341. ES_Object: Uni(Ins(ES.Object, $(x => {
  342. // objects that aren't in control of our runtime
  343. let p = get_proto(x)
  344. if (get_proto(x) === Object.prototype) { return false }
  345. if (is(x, Type)) { return false }
  346. return forall(
  347. [Array, Error, Function, Promise, Instance, Struct, Observer],
  348. T => !(x instanceof T)
  349. )
  350. })), $(x => x === Function.prototype)),
  351. ES_Symbol: ES.Symbol,
  352. ES_Key: Uni(ES.String, ES.Symbol),
  353. ES_Class: Ins(ES.Function, $(
  354. f => is(f.prototype, ES.Object) || f === Function
  355. )),
  356. ES_Iterable: ES.Iterable,
  357. ES_AsyncIterable: ES.AsyncIterable
  358. // this list will keep growing until the init of runtime is finished
  359. }
  360. /**
  361. * Typed Container/Structure Types for Internal Use
  362. *
  363. * These types are fragile and cost a lot,
  364. * therefore should be only used by internal runtime code.
  365. */
  366. let TypedList = {
  367. of: T => assert(is(T, Type)) && Ins(Types.List, $(
  368. l => forall(l, e => is(e, T))
  369. ))
  370. }
  371. let TypedHash = {
  372. of: T => assert(is(T, Type)) && Ins(Types.Hash, $(
  373. h => forall(Object.keys(h), k => is(h[k], T))
  374. ))
  375. }
  376. class HashFormat {
  377. constructor (table, requirement = (x => true)) {
  378. assert(is(table, TypedHash.of(Type)))
  379. assert(is(requirement, ES.Function))
  380. this.table = copy(table)
  381. Object.freeze(table)
  382. this.requirement = requirement
  383. this[Checker] = (x => {
  384. if (!is(x, Types.Hash)) { return false }
  385. for (let key of Object.keys(this.table)) {
  386. let required_type = this.table[key]
  387. if (has(key, x) && is(x[key], required_type)) {
  388. continue
  389. } else {
  390. return false
  391. }
  392. }
  393. let result = this.requirement(x)
  394. assert(is(result, Types.Bool))
  395. return result
  396. })
  397. Object.freeze(this)
  398. }
  399. get [Symbol.toStringTag]() {
  400. return 'HashFormat'
  401. }
  402. }
  403. // shorthand
  404. let format = ((table, def, req) => new HashFormat(table, def, req))
  405. /**
  406. * Object Id Assigner (used by VectorMapCache)
  407. */
  408. class ObjectRegistry {
  409. constructor () {
  410. let self = {
  411. map: new Map(), // value --> id
  412. next_id: 0
  413. }
  414. this.get_id = this.get_id.bind(self)
  415. Object.freeze(this)
  416. }
  417. get_id (value) {
  418. if (this.map.has(value)) {
  419. return this.map.get(value)
  420. } else {
  421. if (is(value, Type)) {
  422. for (let item of this.map) {
  423. let [T, id] = item
  424. if (is(T, Type) && type_equivalent(T, value)) {
  425. this.map.set(value, id)
  426. return id
  427. }
  428. }
  429. }
  430. let id = this.next_id
  431. this.map.set(value, id)
  432. this.next_id = id + 1
  433. assert(is(this.next_id, Types.Int))
  434. return id
  435. }
  436. }
  437. }
  438. /**
  439. * Cache for map: [Object, Object, ...] --> Object
  440. *
  441. * This class is used by TypeTemplate and FunSig
  442. * to store their caches.
  443. * Important: this implementation is naive now, but won't be
  444. * improved, because the whole JavaScript-based runtime is also naive.
  445. */
  446. class VectorMapCache {
  447. constructor () {
  448. let self = {
  449. registry: new ObjectRegistry(),
  450. groups: new Map(),
  451. hash: this.hash
  452. }
  453. this.set = this.set.bind(self)
  454. this.find = this.find.bind(self)
  455. Object.freeze(this)
  456. }
  457. hash (id_vector) {
  458. assert(!(this instanceof VectorMapCache))
  459. assert(is(id_vector, TypedList.of(Types.Int)))
  460. let L = id_vector.length
  461. let value = L % 10
  462. let offset = 100
  463. for (let i = 0; i < L && i < 7; i += 1) {
  464. value += offset * (id_vector[i] % 97)
  465. offset *= 100
  466. }
  467. return value
  468. }
  469. set (vector, value) {
  470. assert(is(vector, Types.List))
  471. let id_vector = vector.map(element => this.registry.get_id(element))
  472. let h = this.hash(id_vector)
  473. if (this.groups.has(h)) {
  474. let group = this.groups.get(h)
  475. assert(is(group, Types.List))
  476. for (let item of group) {
  477. let [iv, _] = item
  478. assert(!equal(iv, id_vector))
  479. }
  480. group.push([id_vector, value])
  481. } else {
  482. this.groups.set(h, [[id_vector, value]])
  483. }
  484. }
  485. find (vector) {
  486. assert(is(vector, Types.List))
  487. let id_vector = vector.map(element => this.registry.get_id(element))
  488. let h = this.hash(id_vector)
  489. if (this.groups.has(h)) {
  490. let group = this.groups.get(h)
  491. assert(is(group, Types.List))
  492. for (let item of group) {
  493. let [iv, value] = item
  494. if (equal(iv, id_vector)) {
  495. return value
  496. }
  497. }
  498. return NotFound
  499. } else {
  500. return NotFound
  501. }
  502. }
  503. }