/source/Types.ooc

http://github.com/fperrad/ooc-lua · Unknown · 728 lines · 601 code · 127 blank · 0 comment · 0 complexity · 4c0b24c635cb770a24998e7a6360ca87 MD5 · raw file

  1. import io/Writer
  2. import math
  3. import structs/ArrayList
  4. import Opcodes
  5. LuaAny: abstract class {
  6. toBool: func -> Bool {
  7. return false
  8. }
  9. toInt: func -> Int {
  10. return 0
  11. }
  12. toNum: func -> Double {
  13. return 0.0
  14. }
  15. toPtr: func -> Pointer {
  16. return null
  17. }
  18. toStr: func -> String {
  19. return null
  20. }
  21. hashval: abstract func -> SizeT
  22. type: abstract func -> String
  23. get: func(key: LuaAny) -> LuaAny {
  24. _typeError("index")
  25. return null
  26. }
  27. set: func(key, val: LuaAny) {
  28. _typeError("index")
  29. }
  30. getMetatable: func -> LuaTable {
  31. return null
  32. }
  33. setMetatable: func(mt: LuaTable) {
  34. }
  35. add: func(op: LuaAny) -> LuaAny {
  36. return _arithError(op)
  37. }
  38. sub: func(op: LuaAny) -> LuaAny {
  39. return _arithError(op)
  40. }
  41. mul: func(op: LuaAny) -> LuaAny {
  42. return _arithError(op)
  43. }
  44. div: func(op: LuaAny) -> LuaAny {
  45. return _arithError(op)
  46. }
  47. mod: func(op: LuaAny) -> LuaAny {
  48. return _arithError(op)
  49. }
  50. pow: func(op: LuaAny) -> LuaAny {
  51. return _arithError(op)
  52. }
  53. unm: func -> LuaAny {
  54. return _arithError(this)
  55. }
  56. len: func -> LuaAny {
  57. _typeError("get length of")
  58. return null
  59. }
  60. concat: func(op: ArrayList<LuaAny>) -> LuaAny {
  61. return _concatError()
  62. }
  63. eq: func(op: LuaAny) -> Bool {
  64. return false
  65. }
  66. lt: func(op: LuaAny) -> Bool {
  67. return _orderError(op)
  68. }
  69. le: func(op: LuaAny) -> Bool {
  70. return _orderError(op)
  71. }
  72. _arithError: func(op: LuaAny) -> LuaAny {
  73. _typeError("perform arithmetic on")
  74. return null
  75. }
  76. _concatError: func -> LuaAny {
  77. _typeError("concatenate")
  78. return null
  79. }
  80. _orderError: func(op: LuaAny) -> Bool {
  81. t1 := type()
  82. t2 := op type()
  83. if (t1 equals?(t2))
  84. _msgError("attempt to compare two %s values" format(t1))
  85. else
  86. _msgError("attempt to compare %s with %s" format(t1, t2))
  87. return false
  88. }
  89. _typeError: func(msg: String) {
  90. _msgError("attempt to %s %s " format(msg, type()))
  91. }
  92. _msgError: func(msg: String) {
  93. Exception new(This, msg) throw()
  94. }
  95. }
  96. LuaBoolean: class extends LuaAny {
  97. v: Bool
  98. init: func(=v) {}
  99. toBool: func -> Bool {
  100. return v
  101. }
  102. hashval: func -> SizeT {
  103. return v as SizeT
  104. }
  105. type: func -> String {
  106. return "boolean"
  107. }
  108. eq: func(op: LuaAny) -> Bool {
  109. if (op class != class)
  110. return false
  111. return v == op as LuaBoolean v
  112. }
  113. }
  114. LuaNil: class extends LuaAny {
  115. init: func {}
  116. hashval: func -> SizeT {
  117. return 0
  118. }
  119. type: func -> String {
  120. return "nil"
  121. }
  122. eq: func(op: LuaAny) -> Bool {
  123. if (op class != class)
  124. return false
  125. return true
  126. }
  127. }
  128. LuaNumber: class extends LuaAny {
  129. v: Double
  130. init: func(=v) {}
  131. init: func~int(i: Int) {
  132. v = i
  133. }
  134. toInt: func -> Int {
  135. return v as Int
  136. }
  137. toNum: func -> Double {
  138. return v
  139. }
  140. toStr: func -> String {
  141. buff := CString new(20)
  142. n := sprintf(buff, "%.14g", v)
  143. return String new(buff, n)
  144. }
  145. hashval: func -> SizeT {
  146. return v as SizeT
  147. }
  148. type: func -> String {
  149. return "number"
  150. }
  151. add: func(op: LuaAny) -> LuaAny {
  152. if (op class != class)
  153. return _arithError(op)
  154. return LuaNumber new(v + op as LuaNumber v)
  155. }
  156. sub: func(op: LuaAny) -> LuaAny {
  157. if (op class != class)
  158. return _arithError(op)
  159. return LuaNumber new(v - op as LuaNumber v)
  160. }
  161. mul: func(op: LuaAny) -> LuaAny {
  162. if (op class != class)
  163. return _arithError(op)
  164. return LuaNumber new(v * op as LuaNumber v)
  165. }
  166. div: func(op: LuaAny) -> LuaAny {
  167. if (op class != class)
  168. return _arithError(op)
  169. return LuaNumber new(v / op as LuaNumber v)
  170. }
  171. mod: func(op: LuaAny) -> LuaAny {
  172. if (op class != class)
  173. return _arithError(op)
  174. v2 := op as LuaNumber v
  175. return LuaNumber new(v - (v / v2) floor() * v2)
  176. }
  177. pow: func(op: LuaAny) -> LuaAny {
  178. if (op class != class)
  179. return _arithError(op)
  180. return LuaNumber new(v pow(op as LuaNumber v))
  181. }
  182. unm: func -> LuaAny {
  183. return LuaNumber new(- v)
  184. }
  185. eq: func(op: LuaAny) -> Bool {
  186. if (op class != class)
  187. return false
  188. return v == op as LuaNumber v
  189. }
  190. lt: func(op: LuaAny) -> Bool {
  191. if (op class != class)
  192. return _orderError(op)
  193. return v < op as LuaNumber v
  194. }
  195. le: func(op: LuaAny) -> Bool {
  196. if (op class != class)
  197. return _orderError(op)
  198. return v <= op as LuaNumber v
  199. }
  200. }
  201. LuaString: class extends LuaAny {
  202. v: String
  203. init: func(=v) {}
  204. toStr: func -> String {
  205. return v
  206. }
  207. hashval: func -> SizeT {
  208. return v as SizeT // internalized string
  209. }
  210. type: func -> String {
  211. return "string"
  212. }
  213. len: func -> LuaAny {
  214. return LuaNumber new(v length())
  215. }
  216. concat: func(op: ArrayList<LuaAny>) -> LuaAny {
  217. str := v
  218. for (e in op)
  219. match (e class) {
  220. case LuaString =>
  221. str += e as LuaString v
  222. case LuaNumber =>
  223. str += e toStr()
  224. case =>
  225. return e _concatError()
  226. }
  227. return LuaString new(str)
  228. }
  229. eq: func(op: LuaAny) -> Bool {
  230. if (op class != class)
  231. return false
  232. return v equals?(op as LuaString v)
  233. }
  234. lt: func(op: LuaAny) -> Bool {
  235. if (op class != class)
  236. return _orderError(op)
  237. return strcmp(v, op as LuaString v) < 0
  238. }
  239. le: func(op: LuaAny) -> Bool {
  240. if (op class != class)
  241. return _orderError(op)
  242. return strcmp(v, op as LuaString v) <= 0
  243. }
  244. }
  245. MINPOWER2 := const 4 /* minimum size for "growing" vectors */
  246. Node: cover {
  247. key: LuaAny
  248. val: LuaAny
  249. next: Node*
  250. }
  251. Table: class {
  252. node: Node*
  253. firstfree: Node* /* this position is free; all positions after it are full */
  254. size: Int
  255. init: func(narray, nrec: Int) {
  256. setnodevector(narray + nrec)
  257. }
  258. /*
  259. ** returns the `main' position of an element in a table (that is, the index
  260. ** of its hash value)
  261. */
  262. mainposition: func(key: LuaAny) -> Node* {
  263. h := key hashval()
  264. version(debug) {
  265. assert((h % size) == (h & (size - 1)))
  266. }
  267. return node + (h & (size - 1))
  268. }
  269. get: func(key: LuaAny) -> LuaAny {
  270. n := mainposition(key)
  271. while (n) {
  272. p := n@ key
  273. if (p != null && key eq(p))
  274. return n@ val
  275. n = n@ next
  276. }
  277. return null /* key not found */
  278. }
  279. next: func(key: LuaAny) -> LuaAny {
  280. return null
  281. }
  282. /*
  283. ** inserts a key into a hash table; first, check whether key is
  284. ** already present; if not, check whether key's main position is free;
  285. ** if not, check whether colliding node is in its main position or not;
  286. ** if it is not, move colliding node to an empty place and put new key
  287. ** in its main position; otherwise (colliding node is in its main position),
  288. ** new key goes to an empty position.
  289. */
  290. set: func(key, val: LuaAny) {
  291. mp := mainposition(key)
  292. /* check whether `key' is somewhere in the chain */
  293. n := mp
  294. while (n) {
  295. /* that's all */
  296. p := n@ key
  297. if (p != null && key eq(p)) {
  298. n@ val = val
  299. return
  300. }
  301. else
  302. n = n@ next
  303. }
  304. /* `key' not found; must insert it */
  305. /* main position is not free? */
  306. if (mp@ key) {
  307. othern := mainposition(mp@ key) /* main position of colliding node */
  308. /* get a free place */
  309. n = firstfree
  310. /* is colliding node out of its main position? (can only happen if
  311. its position is after "firstfree") */
  312. if (mp as Pointer > n as Pointer && othern as Pointer != mp as Pointer) {
  313. /* yes; move colliding node into free position */
  314. while (othern@ next as Pointer != mp as Pointer)
  315. othern = othern@ next /* find previous */
  316. /* redo the chain with `n' in place of `mp' */
  317. othern@ next = n
  318. /* copy colliding node into free pos. (mp->next also goes) */
  319. n@ = mp@
  320. /* now `mp' is free */
  321. mp@ next = null
  322. }
  323. /* colliding node is in its own main position */
  324. else {
  325. /* new node will go into free position */
  326. /* chain new position */
  327. n@ next = mp@ next
  328. mp@ next = n
  329. mp = n
  330. }
  331. }
  332. mp@ key = key
  333. /* correct `firstfree' */
  334. while (true) {
  335. /* OK; table still has a free place */
  336. if (! firstfree@ key) {
  337. mp@ val = val
  338. return
  339. }
  340. else if (firstfree as Pointer == node as Pointer)
  341. break /* cannot decrement from here */
  342. else
  343. firstfree -= 1
  344. }
  345. /* no more free places */
  346. rehash()
  347. /* `rehash' invalidates this insertion */
  348. set(key, val)
  349. }
  350. setnodevector: func(_size: Int) {
  351. if (_size < MINPOWER2)
  352. _size = MINPOWER2
  353. size = _size
  354. node = gc_malloc(size * Node size) as Node*
  355. /* first free position to be used */
  356. firstfree = node + (size - 1)
  357. }
  358. numuse: func -> Int {
  359. realuse := 0
  360. for (i in 0..size)
  361. if (node[i] val)
  362. realuse += 1
  363. return realuse
  364. }
  365. rehash: func {
  366. oldsize := size
  367. nold := node
  368. nelems := numuse()
  369. version(debug) {
  370. assert(nelems <= oldsize) // "wrong count"
  371. }
  372. /* using more than 3/4? */
  373. if (nelems >= oldsize - oldsize / 4)
  374. setnodevector(oldsize * 2)
  375. /* less than 1/4? */
  376. else if (nelems <= oldsize / 4 && oldsize > MINPOWER2)
  377. setnodevector(oldsize / 2)
  378. else
  379. setnodevector(oldsize)
  380. for (i in 0..oldsize) {
  381. old := nold + i
  382. if (old@ val)
  383. set(old@ key, old@ val)
  384. }
  385. /* free old array */
  386. gc_free(nold)
  387. }
  388. }
  389. LuaTable: class extends LuaAny {
  390. v: Table
  391. mt: LuaTable
  392. init: func(narray, nrec: Int) {
  393. v = Table new(narray, nrec)
  394. }
  395. toPtr: func -> Pointer {
  396. return null
  397. }
  398. toStr: func -> String {
  399. buff := CString new(20)
  400. n := sprintf(buff, "table: %08X", v)
  401. return String new(buff, n)
  402. }
  403. hashval: func -> SizeT {
  404. return v as SizeT
  405. }
  406. type: func -> String {
  407. return "table"
  408. }
  409. len: func -> LuaAny {
  410. return LuaNumber new(v numuse())
  411. }
  412. eq: func(op: LuaAny) -> Bool {
  413. if (op class != class)
  414. return false
  415. return v == op as LuaTable v
  416. }
  417. get: func(key: LuaAny) -> LuaAny {
  418. val := v get(key)
  419. if (val == null)
  420. val = LuaNil new()
  421. return val
  422. }
  423. set: func(key, val: LuaAny) {
  424. if (val instanceOf?(LuaNil))
  425. val = null
  426. v set(key, val)
  427. }
  428. rawEqual: func(op: LuaAny) -> Bool {
  429. if (op class != class)
  430. return false
  431. return v == op as LuaTable v
  432. }
  433. rawGet: func(key: LuaAny) -> LuaAny {
  434. val := v get(key)
  435. if (val == null)
  436. val = LuaNil new()
  437. return val
  438. }
  439. rawSet: func(key, val: LuaAny) {
  440. if (val instanceOf?(LuaNil))
  441. val = null
  442. v set(key, val)
  443. }
  444. getMetatable: func -> LuaTable {
  445. return mt
  446. }
  447. setMetatable: func(=mt) {}
  448. next: func(idx: LuaAny) -> LuaAny {
  449. return LuaNil new()
  450. }
  451. }
  452. /*
  453. ** Description of an upvalue for function prototypes
  454. */
  455. UpvalDesc: class {
  456. name: String /* upvalue name (for debug information) */
  457. instack: Bool /* whether it is in stack */
  458. idx: UInt8 /* index of upvalue (in stack or in outer function's list) */
  459. init: func(=name, =instack, =idx) {}
  460. }
  461. /*
  462. ** Description of a local variable for function prototypes
  463. ** (used for debug information)
  464. */
  465. LocVar: class {
  466. varname: String
  467. startpc: Int /* first point where variable is active */
  468. endpc: Int /* first point where variable is dead */
  469. init: func(=varname) {}
  470. }
  471. LuaProto: class extends LuaAny {
  472. k: ArrayList<LuaAny> /* constants used by the function */
  473. code: ArrayList<Instruction> //~ Instruction *code;
  474. p: ArrayList<LuaProto> /* functions defined inside the function */
  475. lineinfo: ArrayList<Int> /* map from opcodes to source lines */
  476. locvars: ArrayList<LocVar> /* information about local variables */
  477. upvalues: ArrayList<UpvalDesc> /* upvalue information */
  478. source: String
  479. linedefined: Int
  480. lastlinedefined: Int
  481. numparams: UInt8; /* number of fixed parameters */
  482. is_vararg: Bool
  483. maxstacksize: UInt8 /* maximum stack used by this function */
  484. init: func {
  485. k = ArrayList<LuaAny> new()
  486. code = ArrayList<Instruction> new()
  487. p = ArrayList<LuaProto> new()
  488. lineinfo = ArrayList<Int> new()
  489. locvars = ArrayList<LocVar> new()
  490. upvalues = ArrayList<UpvalDesc> new()
  491. }
  492. hashval: func -> SizeT {
  493. return 0 //
  494. }
  495. type: func -> String {
  496. return "proto"
  497. }
  498. _header: func -> ArrayList<Char> {
  499. i := 1 as Int
  500. h := ArrayList<Char> new(18)
  501. h add(0x1b as Char)
  502. h add('L')
  503. h add('u')
  504. h add('a')
  505. h add(0x52 as Char) /* Lua 5.2 */
  506. h add(0 as Char) /* the official format */
  507. h add((i& as Char*)@ as Char) /* endianness */
  508. h add(Int size as Char)
  509. h add(SizeT size as Char)
  510. h add(Instruction size as Char)
  511. h add(Double size as Char)
  512. h add(0 as Char) /* is lua_Number integral? */
  513. h add(0x19 as Char)
  514. h add(0x93 as Char)
  515. h add('\r')
  516. h add('\n')
  517. h add(0x1a as Char)
  518. h add('\n')
  519. return h
  520. }
  521. dumpHeader: func(w: Writer) {
  522. h := _header()
  523. w write(h data as Char*, h getSize())
  524. }
  525. dump: func(w: Writer, strip: Bool) {
  526. w write(linedefined& as Char*, Int size)
  527. w write(lastlinedefined& as Char*, Int size)
  528. w write(numparams as Char)
  529. w write(is_vararg as Char)
  530. w write(maxstacksize as Char)
  531. n := code getSize()
  532. w write(n& as Char*, Int size)
  533. w write(code data as Char*, n * Instruction size)
  534. n = k getSize()
  535. w write(n& as Char*, Int size)
  536. for (i in 0 .. n) {
  537. cst := k get(i)
  538. match (cst class) {
  539. case LuaNil =>
  540. w write(0 as Char)
  541. case LuaBoolean =>
  542. w write(1 as Char)
  543. w write(cst as LuaBoolean v as Char)
  544. case LuaNumber =>
  545. w write(3 as Char)
  546. num := cst as LuaNumber v
  547. w write(num& as Char*, Double size)
  548. case LuaString =>
  549. w write(4 as Char)
  550. str := cst as LuaString v
  551. _dumpString(w, str)
  552. }
  553. }
  554. n = p getSize()
  555. w write(n& as Char*, Int size)
  556. for (i in 0 .. n)
  557. p get(i) dump(w, strip)
  558. n = upvalues getSize()
  559. w write(n& as Char*, Int size)
  560. for (i in 0 .. n) {
  561. upv := upvalues get(i)
  562. w write(upv instack as Char)
  563. w write(upv idx as Char)
  564. }
  565. if (strip) {
  566. n = 0
  567. w write(n& as Char*, Int size) // source
  568. w write(n& as Char*, Int size) // lineinfo
  569. w write(n& as Char*, Int size) // locvars
  570. w write(n& as Char*, Int size) // upvalues
  571. }
  572. else {
  573. _dumpString(w, source)
  574. n = lineinfo getSize()
  575. w write(n& as Char*, Int size)
  576. w write(lineinfo data as Char*, n * Int size)
  577. n = locvars getSize()
  578. w write(n& as Char*, Int size)
  579. for (i in 0 .. n) {
  580. var := locvars get(i)
  581. _dumpString(w, var varname)
  582. pc := var startpc
  583. w write(pc& as Char*, Int size)
  584. pc = var endpc
  585. w write(pc& as Char*, Int size)
  586. }
  587. n = upvalues getSize()
  588. w write(n& as Char*, Int size)
  589. for (i in 0 .. n)
  590. _dumpString(w, upvalues get(i) name)
  591. }
  592. }
  593. _dumpString: func(w: Writer, str: String) {
  594. len := str length()
  595. len1 := len + 1
  596. w write(len1& as Char*, Int size)
  597. if (len != 0)
  598. w write(str, len)
  599. w write(0 as Char)
  600. }
  601. }