ARITH.ob07 17 KB

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