ARITH.ob07 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792
  1. MODULE ARITH;
  2. IMPORT STRINGS IN "./strings/STRINGS.ob07",
  3. UTILS IN "./utils/UTILS.ob07",
  4. LISTS;
  5. CONST
  6. tINTEGER* = 1; tREAL* = 2; tSET* = 3;
  7. tBOOLEAN* = 4; tCHAR* = 5; tWCHAR* = 6;
  8. tSTRING* = 7;
  9. opEQ* = 0; opNE* = 1; opLT* = 2; opLE* = 3; opGT* = 4; opGE* = 5;
  10. opIN* = 6; opIS* = 7;
  11. TYPE
  12. VALUE* = RECORD
  13. typ*: INTEGER;
  14. int: INTEGER;
  15. float: REAL;
  16. set: SET;
  17. bool: BOOLEAN;
  18. string*: LISTS.ITEM
  19. END;
  20. VAR
  21. digit: ARRAY 256 OF INTEGER;
  22. PROCEDURE Int* (v: VALUE): INTEGER;
  23. VAR
  24. res: INTEGER;
  25. BEGIN
  26. CASE v.typ OF
  27. |tINTEGER, tCHAR, tWCHAR:
  28. res := v.int
  29. |tSET:
  30. res := UTILS.Long(ORD(v.set))
  31. |tBOOLEAN:
  32. res := ORD(v.bool)
  33. END
  34. RETURN res
  35. END Int;
  36. PROCEDURE getBool* (v: VALUE): BOOLEAN;
  37. BEGIN
  38. ASSERT(v.typ = tBOOLEAN);
  39. RETURN v.bool
  40. END getBool;
  41. PROCEDURE Float* (v: VALUE): REAL;
  42. BEGIN
  43. ASSERT(v.typ = tREAL);
  44. RETURN v.float
  45. END Float;
  46. PROCEDURE range* (i: VALUE; a, b: INTEGER): BOOLEAN;
  47. RETURN (a <= i.int) & (i.int <= b)
  48. END range;
  49. PROCEDURE check* (v: VALUE): BOOLEAN;
  50. VAR
  51. res: BOOLEAN;
  52. BEGIN
  53. CASE v.typ OF
  54. |tINTEGER: res := range(v, UTILS.target.minInt, UTILS.target.maxInt)
  55. |tCHAR: res := range(v, 0, 255)
  56. |tWCHAR: res := range(v, 0, 65535)
  57. |tREAL: res := (-UTILS.target.maxReal <= v.float) & (v.float <= UTILS.target.maxReal)
  58. END
  59. RETURN res
  60. END check;
  61. PROCEDURE isZero* (v: VALUE): BOOLEAN;
  62. VAR
  63. res: BOOLEAN;
  64. BEGIN
  65. CASE v.typ OF
  66. |tINTEGER: res := v.int = 0
  67. |tREAL: res := v.float = 0.0
  68. END
  69. RETURN res
  70. END isZero;
  71. PROCEDURE iconv* (s: ARRAY OF CHAR; VAR v: VALUE; VAR error: INTEGER);
  72. VAR
  73. value: INTEGER;
  74. i: INTEGER;
  75. d: INTEGER;
  76. BEGIN
  77. error := 0;
  78. value := 0;
  79. i := 0;
  80. WHILE STRINGS.digit(s[i]) & (error = 0) DO
  81. d := digit[ORD(s[i])];
  82. IF value <= (UTILS.maxint - d) DIV 10 THEN
  83. value := value * 10 + d;
  84. INC(i)
  85. ELSE
  86. error := 1
  87. END
  88. END;
  89. IF error = 0 THEN
  90. v.int := value;
  91. v.typ := tINTEGER;
  92. IF ~check(v) THEN
  93. error := 1
  94. END
  95. END
  96. END iconv;
  97. PROCEDURE hconv* (s: ARRAY OF CHAR; VAR v: VALUE; VAR error: INTEGER);
  98. VAR
  99. value: INTEGER;
  100. i: INTEGER;
  101. n: INTEGER;
  102. d: INTEGER;
  103. BEGIN
  104. ASSERT(STRINGS.digit(s[0]));
  105. error := 0;
  106. value := 0;
  107. n := -1;
  108. i := 0;
  109. WHILE (s[i] # "H") & (s[i] # "X") & (s[i] # "h") & (s[i] # "x") & (error = 0) DO
  110. d := digit[ORD(s[i])];
  111. IF (n = -1) & (d # 0) THEN
  112. n := i
  113. END;
  114. IF (n # -1) & (i - n + 1 > UTILS.target.maxHex) THEN
  115. error := 2
  116. ELSE
  117. value := value * 16 + d;
  118. INC(i)
  119. END
  120. END;
  121. value := UTILS.Long(value);
  122. IF ((s[i] = "X") OR (s[i] = "x")) & (n # -1) & (i - n > 4) THEN
  123. error := 3
  124. END;
  125. IF error = 0 THEN
  126. v.int := value;
  127. IF (s[i] = "X") OR (s[i] = "x") THEN
  128. v.typ := tCHAR;
  129. IF ~check(v) THEN
  130. v.typ := tWCHAR;
  131. IF ~check(v) THEN
  132. error := 3
  133. END
  134. END
  135. ELSE
  136. v.typ := tINTEGER;
  137. IF ~check(v) THEN
  138. error := 2
  139. END
  140. END
  141. END
  142. END hconv;
  143. PROCEDURE opFloat2 (VAR a: REAL; b: REAL; op: CHAR): BOOLEAN;
  144. BEGIN
  145. CASE op OF
  146. |"+": a := a + b
  147. |"-": a := a - b
  148. |"*": a := a * b
  149. |"/": a := a / b
  150. END
  151. RETURN (-UTILS.maxreal <= a) & (a <= UTILS.maxreal) (* +inf > UTILS.maxreal *)
  152. END opFloat2;
  153. PROCEDURE fconv* (s: ARRAY OF CHAR; VAR v: VALUE; VAR error: INTEGER);
  154. VAR
  155. value: REAL;
  156. exp10: REAL;
  157. i, n, d: INTEGER;
  158. minus: BOOLEAN;
  159. BEGIN
  160. error := 0;
  161. value := 0.0;
  162. minus := FALSE;
  163. n := 0;
  164. exp10 := 0.0;
  165. WHILE (error = 0) & (STRINGS.digit(s[i]) OR (s[i] = ".")) DO
  166. IF s[i] = "." THEN
  167. exp10 := 1.0;
  168. INC(i)
  169. ELSE
  170. IF opFloat2(value, 10.0, "*") & opFloat2(value, FLT(digit[ORD(s[i])]), "+") & opFloat2(exp10, 10.0, "*") THEN
  171. INC(i)
  172. ELSE
  173. error := 4
  174. END
  175. END
  176. END;
  177. IF ~opFloat2(value, exp10, "/") THEN
  178. error := 4
  179. END;
  180. IF (s[i] = "E") OR (s[i] = "e") THEN
  181. INC(i)
  182. END;
  183. IF (s[i] = "-") OR (s[i] = "+") THEN
  184. minus := s[i] = "-";
  185. INC(i)
  186. END;
  187. WHILE (error = 0) & STRINGS.digit(s[i]) DO
  188. d := digit[ORD(s[i])];
  189. IF n <= (UTILS.maxint - d) DIV 10 THEN
  190. n := n * 10 + d;
  191. INC(i)
  192. ELSE
  193. error := 5
  194. END
  195. END;
  196. exp10 := 1.0;
  197. WHILE (error = 0) & (n > 0) DO
  198. IF opFloat2(exp10, 10.0, "*") THEN
  199. DEC(n)
  200. ELSE
  201. error := 4
  202. END
  203. END;
  204. IF error = 0 THEN
  205. IF minus THEN
  206. IF ~opFloat2(value, exp10, "/") THEN
  207. error := 4
  208. END
  209. ELSE
  210. IF ~opFloat2(value, exp10, "*") THEN
  211. error := 4
  212. END
  213. END
  214. END;
  215. IF error = 0 THEN
  216. v.float := value;
  217. v.typ := tREAL;
  218. IF ~check(v) THEN
  219. error := 4
  220. END
  221. END
  222. END fconv;
  223. PROCEDURE setChar* (VAR v: VALUE; ord: INTEGER);
  224. BEGIN
  225. v.typ := tCHAR;
  226. v.int := ord
  227. END setChar;
  228. PROCEDURE setWChar* (VAR v: VALUE; ord: INTEGER);
  229. BEGIN
  230. v.typ := tWCHAR;
  231. v.int := ord
  232. END setWChar;
  233. PROCEDURE addInt (VAR a: INTEGER; b: INTEGER): BOOLEAN;
  234. VAR
  235. error: BOOLEAN;
  236. BEGIN
  237. IF (a > 0) & (b > 0) THEN
  238. error := a > UTILS.maxint - b
  239. ELSIF (a < 0) & (b < 0) THEN
  240. error := a < UTILS.minint - b
  241. ELSE
  242. error := FALSE
  243. END;
  244. IF ~error THEN
  245. a := a + b
  246. ELSE
  247. a := 0
  248. END
  249. RETURN ~error
  250. END addInt;
  251. PROCEDURE subInt (VAR a: INTEGER; b: INTEGER): BOOLEAN;
  252. VAR
  253. error: BOOLEAN;
  254. BEGIN
  255. IF (a > 0) & (b < 0) THEN
  256. error := a > UTILS.maxint + b
  257. ELSIF (a < 0) & (b > 0) THEN
  258. error := a < UTILS.minint + b
  259. ELSIF (a = 0) & (b < 0) THEN
  260. error := b = UTILS.minint
  261. ELSE
  262. error := FALSE
  263. END;
  264. IF ~error THEN
  265. a := a - b
  266. ELSE
  267. a := 0
  268. END
  269. RETURN ~error
  270. END subInt;
  271. PROCEDURE lg2 (x: INTEGER): INTEGER;
  272. VAR
  273. n: INTEGER;
  274. BEGIN
  275. ASSERT(x > 0);
  276. n := UTILS.Log2(x);
  277. IF n = -1 THEN
  278. n := 255
  279. END
  280. RETURN n
  281. END lg2;
  282. PROCEDURE mulInt* (VAR a: INTEGER; b: INTEGER): BOOLEAN;
  283. VAR
  284. error: BOOLEAN;
  285. min, max: INTEGER;
  286. BEGIN
  287. min := UTILS.minint;
  288. max := UTILS.maxint;
  289. IF ((a > 1) & (b > 1)) OR ((a < 0) & (b < 0)) THEN
  290. error := (a = min) OR (b = min) OR (ABS(a) > max DIV ABS(b))
  291. ELSIF ((a > 1) & (b < 0)) OR ((a < 0) & (b > 1)) THEN
  292. error := (a = min) OR (b = min);
  293. IF ~error THEN
  294. IF lg2(ABS(a)) + lg2(ABS(b)) >= UTILS.bit_depth THEN
  295. error := ABS(a) > max DIV ABS(b)
  296. END
  297. END
  298. ELSE
  299. error := FALSE
  300. END;
  301. IF ~error THEN
  302. a := a * b
  303. ELSE
  304. a := 0
  305. END
  306. RETURN ~error
  307. END mulInt;
  308. PROCEDURE _ASR (x, n: INTEGER): INTEGER;
  309. RETURN ASR(UTILS.Long(x), n)
  310. END _ASR;
  311. PROCEDURE _LSR (x, n: INTEGER): INTEGER;
  312. RETURN UTILS.Long(LSR(UTILS.Short(x), n))
  313. END _LSR;
  314. PROCEDURE _LSL (x, n: INTEGER): INTEGER;
  315. RETURN UTILS.Long(LSL(x, n))
  316. END _LSL;
  317. PROCEDURE _ROR1_32 (x: INTEGER): INTEGER;
  318. BEGIN
  319. x := UTILS.Short(x);
  320. x := ORD(BITS(LSR(x, 1)) + BITS(LSL(x, 31)))
  321. RETURN UTILS.Long(x)
  322. END _ROR1_32;
  323. PROCEDURE _ROR1_16 (x: INTEGER): INTEGER;
  324. BEGIN
  325. x := x MOD 65536;
  326. x := ORD(BITS(LSR(x, 1)) + BITS(LSL(x, 15)))
  327. RETURN UTILS.Long(x)
  328. END _ROR1_16;
  329. PROCEDURE _ROR (x, n: INTEGER): INTEGER;
  330. BEGIN
  331. CASE UTILS.bit_diff OF
  332. |0: x := ROR(x, n)
  333. |16, 48:
  334. n := n MOD 16;
  335. WHILE n > 0 DO
  336. x := _ROR1_16(x);
  337. DEC(n)
  338. END
  339. |32:
  340. n := n MOD 32;
  341. WHILE n > 0 DO
  342. x := _ROR1_32(x);
  343. DEC(n)
  344. END
  345. END
  346. RETURN x
  347. END _ROR;
  348. PROCEDURE opInt* (VAR a: VALUE; b: VALUE; op: CHAR): BOOLEAN;
  349. VAR
  350. success: BOOLEAN;
  351. BEGIN
  352. success := TRUE;
  353. CASE op OF
  354. |"+": success := addInt(a.int, b.int)
  355. |"-": success := subInt(a.int, b.int)
  356. |"*": success := mulInt(a.int, b.int)
  357. |"/": success := FALSE
  358. |"D": a.int := a.int DIV b.int
  359. |"M": a.int := a.int MOD b.int
  360. |"L": a.int := _LSL(a.int, b.int)
  361. |"A": a.int := _ASR(a.int, b.int)
  362. |"O": a.int := _ROR(a.int, b.int)
  363. |"R": a.int := _LSR(a.int, b.int)
  364. |"m": a.int := MIN(a.int, b.int)
  365. |"x": a.int := MAX(a.int, b.int)
  366. END;
  367. a.typ := tINTEGER
  368. RETURN success & check(a)
  369. END opInt;
  370. PROCEDURE charToStr* (c: VALUE; VAR s: ARRAY OF CHAR);
  371. BEGIN
  372. s[0] := CHR(c.int);
  373. s[1] := 0X
  374. END charToStr;
  375. PROCEDURE opSet* (VAR a: VALUE; b: VALUE; op: CHAR);
  376. BEGIN
  377. CASE op OF
  378. |"+": a.set := a.set + b.set
  379. |"-": a.set := a.set - b.set
  380. |"*": a.set := a.set * b.set
  381. |"/": a.set := a.set / b.set
  382. END;
  383. a.typ := tSET
  384. END opSet;
  385. PROCEDURE opFloat* (VAR a: VALUE; b: VALUE; op: CHAR): BOOLEAN;
  386. BEGIN
  387. a.typ := tREAL
  388. RETURN opFloat2(a.float, b.float, op) & check(a)
  389. END opFloat;
  390. PROCEDURE ord* (VAR v: VALUE);
  391. BEGIN
  392. CASE v.typ OF
  393. |tCHAR, tWCHAR:
  394. |tBOOLEAN: v.int := ORD(v.bool)
  395. |tSET: v.int := UTILS.Long(ORD(v.set))
  396. END;
  397. v.typ := tINTEGER
  398. END ord;
  399. PROCEDURE odd* (VAR v: VALUE);
  400. BEGIN
  401. v.typ := tBOOLEAN;
  402. v.bool := ODD(v.int)
  403. END odd;
  404. PROCEDURE bits* (VAR v: VALUE);
  405. BEGIN
  406. v.typ := tSET;
  407. v.set := BITS(v.int)
  408. END bits;
  409. PROCEDURE abs* (VAR v: VALUE): BOOLEAN;
  410. VAR
  411. res: BOOLEAN;
  412. BEGIN
  413. res := FALSE;
  414. CASE v.typ OF
  415. |tREAL:
  416. v.float := ABS(v.float);
  417. res := TRUE
  418. |tINTEGER:
  419. IF v.int # UTILS.minint THEN
  420. v.int := ABS(v.int);
  421. res := TRUE
  422. END
  423. END
  424. RETURN res
  425. END abs;
  426. PROCEDURE floor* (VAR v: VALUE): BOOLEAN;
  427. VAR
  428. res: BOOLEAN;
  429. BEGIN
  430. v.typ := tINTEGER;
  431. res := (FLT(UTILS.minint) <= v.float) & (v.float <= FLT(UTILS.maxint));
  432. IF res THEN
  433. v.int := FLOOR(v.float)
  434. END
  435. RETURN res
  436. END floor;
  437. PROCEDURE flt* (VAR v: VALUE);
  438. BEGIN
  439. v.typ := tREAL;
  440. v.float := FLT(v.int)
  441. END flt;
  442. PROCEDURE neg* (VAR v: VALUE): BOOLEAN;
  443. VAR
  444. z: VALUE;
  445. res: BOOLEAN;
  446. BEGIN
  447. res := TRUE;
  448. z.typ := tINTEGER;
  449. z.int := 0;
  450. CASE v.typ OF
  451. |tREAL: v.float := -v.float
  452. |tSET: v.set := -v.set
  453. |tINTEGER: res := opInt(z, v, "-"); v := z
  454. |tBOOLEAN: v.bool := ~v.bool
  455. END
  456. RETURN res
  457. END neg;
  458. PROCEDURE setbool* (VAR v: VALUE; b: BOOLEAN);
  459. BEGIN
  460. v.bool := b;
  461. v.typ := tBOOLEAN
  462. END setbool;
  463. PROCEDURE opBoolean* (VAR a: VALUE; b: VALUE; op: CHAR);
  464. BEGIN
  465. CASE op OF
  466. |"&": a.bool := a.bool & b.bool
  467. |"|": a.bool := a.bool OR b.bool
  468. END;
  469. a.typ := tBOOLEAN
  470. END opBoolean;
  471. PROCEDURE less (v, v2: VALUE; VAR error: INTEGER): BOOLEAN;
  472. VAR
  473. res: BOOLEAN;
  474. BEGIN
  475. res := FALSE;
  476. IF (v.typ = v2.typ) OR (v.typ IN {tCHAR, tWCHAR}) & (v2.typ IN {tCHAR, tWCHAR}) THEN
  477. CASE v.typ OF
  478. |tINTEGER,
  479. tWCHAR,
  480. tCHAR: res := v.int < v2.int
  481. |tREAL: res := v.float < v2.float
  482. |tBOOLEAN,
  483. tSET: error := 1
  484. END
  485. ELSE
  486. error := 1
  487. END
  488. RETURN res
  489. END less;
  490. PROCEDURE equal (v, v2: VALUE; VAR error: INTEGER): BOOLEAN;
  491. VAR
  492. res: BOOLEAN;
  493. BEGIN
  494. res := FALSE;
  495. IF (v.typ = v2.typ) OR (v.typ IN {tCHAR, tWCHAR}) & (v2.typ IN {tCHAR, tWCHAR}) THEN
  496. CASE v.typ OF
  497. |tINTEGER,
  498. tWCHAR,
  499. tCHAR: res := v.int = v2.int
  500. |tREAL: res := v.float = v2.float
  501. |tBOOLEAN: res := v.bool = v2.bool
  502. |tSET: res := v.set = v2.set
  503. END
  504. ELSE
  505. error := 1
  506. END
  507. RETURN res
  508. END equal;
  509. PROCEDURE relation* (VAR v: VALUE; v2: VALUE; op: INTEGER; VAR error: INTEGER);
  510. VAR
  511. res: BOOLEAN;
  512. BEGIN
  513. error := 0;
  514. res := FALSE;
  515. CASE op OF
  516. |opEQ:
  517. res := equal(v, v2, error)
  518. |opNE:
  519. res := ~equal(v, v2, error)
  520. |opLT:
  521. res := less(v, v2, error)
  522. |opLE:
  523. res := less(v, v2, error);
  524. IF error = 0 THEN
  525. res := equal(v, v2, error) OR res
  526. END
  527. |opGE:
  528. res := ~less(v, v2, error)
  529. |opGT:
  530. res := less(v, v2, error);
  531. IF error = 0 THEN
  532. res := equal(v, v2, error) OR res
  533. END;
  534. res := ~res
  535. |opIN:
  536. IF (v.typ = tINTEGER) & (v2.typ = tSET) THEN
  537. IF range(v, 0, UTILS.target.maxSet) THEN
  538. res := v.int IN v2.set
  539. ELSE
  540. error := 2
  541. END
  542. ELSE
  543. error := 1
  544. END
  545. END;
  546. IF error = 0 THEN
  547. v.bool := res;
  548. v.typ := tBOOLEAN
  549. END
  550. END relation;
  551. PROCEDURE emptySet* (VAR v: VALUE);
  552. BEGIN
  553. v.typ := tSET;
  554. v.set := {}
  555. END emptySet;
  556. PROCEDURE constrSet* (VAR v: VALUE; a, b: VALUE);
  557. BEGIN
  558. v.typ := tSET;
  559. v.set := {a.int .. b.int}
  560. END constrSet;
  561. PROCEDURE getInt* (v: VALUE): INTEGER;
  562. BEGIN
  563. ASSERT(check(v))
  564. RETURN v.int
  565. END getInt;
  566. PROCEDURE setInt* (VAR v: VALUE; i: INTEGER): BOOLEAN;
  567. BEGIN
  568. v.int := i;
  569. v.typ := tINTEGER
  570. RETURN check(v)
  571. END setInt;
  572. PROCEDURE concat* (VAR s: ARRAY OF CHAR; s1: ARRAY OF CHAR): BOOLEAN;
  573. VAR
  574. res: BOOLEAN;
  575. BEGIN
  576. res := LENGTH(s) + LENGTH(s1) < LEN(s);
  577. IF res THEN
  578. STRINGS.append(s, s1)
  579. END
  580. RETURN res
  581. END concat;
  582. PROCEDURE init;
  583. VAR
  584. i: INTEGER;
  585. BEGIN
  586. FOR i := 0 TO LEN(digit) - 1 DO
  587. digit[i] := -1
  588. END;
  589. FOR i := ORD("0") TO ORD("9") DO
  590. digit[i] := i - ORD("0")
  591. END;
  592. FOR i := ORD("A") TO ORD("F") DO
  593. digit[i] := i - ORD("A") + 10
  594. END
  595. END init;
  596. BEGIN
  597. init
  598. END ARITH.