Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. (*
  2.     BSD 2-Clause License
  3.  
  4.     Copyright (c) 2018, 2019, Anton Krotov
  5.     All rights reserved.
  6. *)
  7.  
  8. MODULE ARITH;
  9.  
  10. IMPORT AVLTREES, STRINGS, MACHINE, UTILS;
  11.  
  12.  
  13. CONST
  14.  
  15.     tINTEGER* = 1;  tREAL* = 2;  tSET*    = 3;
  16.     tBOOLEAN* = 4;  tCHAR* = 5;  tWCHAR*  = 6;
  17.     tSTRING*  = 7;
  18.  
  19.  
  20. TYPE
  21.  
  22.     RELATION* = ARRAY 3 OF CHAR;
  23.  
  24.     VALUE* = RECORD
  25.  
  26.         typ*:      INTEGER;
  27.  
  28.         int:       INTEGER;
  29.         float:     REAL;
  30.         set:       SET;
  31.         bool:      BOOLEAN;
  32.  
  33.         string*:   AVLTREES.DATA
  34.  
  35.     END;
  36.  
  37.  
  38. VAR
  39.  
  40.     digit: ARRAY 256 OF INTEGER;
  41.  
  42.  
  43. PROCEDURE Int* (v: VALUE): INTEGER;
  44. VAR
  45.     res: INTEGER;
  46.  
  47. BEGIN
  48.  
  49.     IF v.typ = tINTEGER THEN
  50.         res := v.int
  51.     ELSIF v.typ = tCHAR THEN
  52.         res := v.int
  53.     ELSIF v.typ = tWCHAR THEN
  54.         res := v.int
  55.     ELSIF v.typ = tSET THEN
  56.         res := ORD(v.set);
  57.         IF MACHINE._64to32 THEN
  58.             res := MACHINE.Int32To64(res)
  59.         END
  60.     ELSIF v.typ = tBOOLEAN THEN
  61.         res := ORD(v.bool)
  62.     END
  63.  
  64.     RETURN res
  65. END Int;
  66.  
  67.  
  68. PROCEDURE getBool* (v: VALUE): BOOLEAN;
  69. BEGIN
  70.     ASSERT(v.typ = tBOOLEAN);
  71.  
  72.     RETURN v.bool
  73. END getBool;
  74.  
  75.  
  76. PROCEDURE Float* (v: VALUE): REAL;
  77. BEGIN
  78.     ASSERT(v.typ = tREAL);
  79.  
  80.     RETURN v.float
  81. END Float;
  82.  
  83.  
  84. PROCEDURE check* (v: VALUE): BOOLEAN;
  85. VAR
  86.     error: BOOLEAN;
  87.  
  88. BEGIN
  89.     error := FALSE;
  90.  
  91.     IF (v.typ = tINTEGER) & ((v.int < MACHINE.target.minInt) OR (v.int > MACHINE.target.maxInt)) THEN
  92.         error := TRUE
  93.     ELSIF (v.typ = tCHAR) & ((v.int < 0) OR (v.int > 255)) THEN
  94.         error := TRUE
  95.     ELSIF (v.typ = tWCHAR) & ((v.int < 0) OR (v.int > 65535)) THEN
  96.         error := TRUE
  97.     ELSIF (v.typ = tREAL) & ((v.float < -MACHINE.target.maxReal) OR (v.float > MACHINE.target.maxReal)) THEN
  98.         error := TRUE
  99.     END
  100.  
  101.     RETURN ~error
  102. END check;
  103.  
  104.  
  105. PROCEDURE isZero* (v: VALUE): BOOLEAN;
  106. VAR
  107.     res: BOOLEAN;
  108. BEGIN
  109.     ASSERT(v.typ IN {tINTEGER, tREAL});
  110.  
  111.     IF v.typ = tINTEGER THEN
  112.         res := v.int = 0
  113.     ELSIF v.typ = tREAL THEN
  114.         res := v.float = 0.0
  115.     END
  116.  
  117.     RETURN res
  118. END isZero;
  119.  
  120.  
  121. PROCEDURE iconv* (s: ARRAY OF CHAR; VAR v: VALUE; VAR error: INTEGER);
  122. VAR
  123.     value: INTEGER;
  124.     i:     INTEGER;
  125.     d:     INTEGER;
  126.  
  127. BEGIN
  128.     error := 0;
  129.     value := 0;
  130.  
  131.     i := 0;
  132.     WHILE STRINGS.digit(s[i]) & (error = 0) DO
  133.         d := digit[ORD(s[i])];
  134.         IF value <= (UTILS.maxint - d) DIV 10 THEN
  135.             value := value * 10 + d;
  136.             INC(i)
  137.         ELSE
  138.             error := 1
  139.         END
  140.     END;
  141.  
  142.     IF error = 0 THEN
  143.         v.int := value;
  144.         v.typ := tINTEGER;
  145.         IF ~check(v) THEN
  146.             error := 1
  147.         END
  148.     END
  149.  
  150. END iconv;
  151.  
  152.  
  153. PROCEDURE hconv* (s: ARRAY OF CHAR; VAR v: VALUE; VAR error: INTEGER);
  154. VAR
  155.     value: INTEGER;
  156.     i:     INTEGER;
  157.     n:     INTEGER;
  158.     d:     INTEGER;
  159.  
  160. BEGIN
  161.     ASSERT(STRINGS.digit(s[0]));
  162.  
  163.     error := 0;
  164.     value := 0;
  165.  
  166.     n := -1;
  167.     i := 0;
  168.     WHILE (s[i] # "H") & (s[i] # "X") & (error = 0) DO
  169.  
  170.         d := digit[ORD(s[i])];
  171.         IF (n = -1) & (d # 0) THEN
  172.             n := i
  173.         END;
  174.  
  175.         IF (n # -1) & (i - n + 1 > MACHINE.target.maxHex) THEN
  176.             error := 2
  177.         ELSE
  178.             value := value * 16 + d;
  179.             INC(i)
  180.         END
  181.  
  182.     END;
  183.  
  184.     IF MACHINE._64to32 THEN
  185.         value := MACHINE.Int32To64(value);
  186.     END;
  187.  
  188.     IF (s[i] = "X") & (n # -1) & (i - n > 4) THEN
  189.         error := 3
  190.     END;
  191.  
  192.     IF error = 0 THEN
  193.         v.int := value;
  194.         IF s[i] = "X" THEN
  195.             v.typ := tCHAR;
  196.             IF ~check(v) THEN
  197.                 v.typ := tWCHAR;
  198.                 IF ~check(v) THEN
  199.                     error := 3
  200.                 END
  201.             END
  202.         ELSE
  203.             v.typ := tINTEGER;
  204.             IF ~check(v) THEN
  205.                 error := 2
  206.             END
  207.         END
  208.     END
  209.  
  210. END hconv;
  211.  
  212.  
  213. PROCEDURE opFloat2 (VAR a: REAL; b: REAL; op: CHAR): BOOLEAN;
  214. VAR
  215.     max: REAL;
  216.     res: BOOLEAN;
  217.  
  218. BEGIN
  219.     max := UTILS.maxreal;
  220.  
  221.     CASE op OF
  222.     |"+":
  223.         IF (a < 0.0) & (b < 0.0) THEN
  224.             res := a > -max - b
  225.         ELSIF (a > 0.0) & (b > 0.0) THEN
  226.             res := a <  max - b
  227.         ELSE
  228.             res := TRUE
  229.         END;
  230.         IF res THEN
  231.             a := a + b
  232.         END
  233.  
  234.     |"-":
  235.         IF (a < 0.0) & (b > 0.0) THEN
  236.             res := a > b - max
  237.         ELSIF (a > 0.0) & (b < 0.0) THEN
  238.             res := a < b + max
  239.         ELSE
  240.             res := TRUE
  241.         END;
  242.         IF res THEN
  243.             a := a - b
  244.         END
  245.  
  246.     |"*":
  247.         IF (ABS(a) > 1.0) & (ABS(b) > 1.0) THEN
  248.             res := ABS(a) < max / ABS(b)
  249.         ELSE
  250.             res := TRUE
  251.         END;
  252.         IF res THEN
  253.             a := a * b
  254.         END
  255.  
  256.     |"/":
  257.         IF ABS(b) < 1.0 THEN
  258.             res := ABS(a) < max * ABS(b)
  259.         ELSE
  260.             res := TRUE
  261.         END;
  262.         IF res THEN
  263.             a := a / b
  264.         END
  265.  
  266.     END
  267.  
  268.     RETURN res
  269. END opFloat2;
  270.  
  271.  
  272. PROCEDURE fconv* (s: ARRAY OF CHAR; VAR v: VALUE; VAR error: INTEGER);
  273. VAR
  274.     value:    REAL;
  275.     exp10:    REAL;
  276.     i, n, d:  INTEGER;
  277.     minus:    BOOLEAN;
  278.  
  279. BEGIN
  280.     error := 0;
  281.     value := 0.0;
  282.     exp10 := 10.0;
  283.     minus := FALSE;
  284.     n := 0;
  285.  
  286.     i := 0;
  287.     WHILE (error = 0) & STRINGS.digit(s[i]) DO
  288.         IF opFloat2(value, 10.0, "*") & opFloat2(value, FLT(digit[ORD(s[i])]), "+") THEN
  289.             INC(i)
  290.         ELSE
  291.             error := 4
  292.         END
  293.     END;
  294.  
  295.     INC(i);
  296.  
  297.     WHILE (error = 0) & STRINGS.digit(s[i]) DO
  298.         IF opFloat2(value, FLT(digit[ORD(s[i])]) / exp10, "+") & opFloat2(exp10, 10.0, "*") THEN
  299.             INC(i)
  300.         ELSE
  301.             error := 4
  302.         END
  303.     END;
  304.  
  305.     IF s[i] = "E" THEN
  306.         INC(i)
  307.     END;
  308.  
  309.     IF (s[i] = "-") OR (s[i] = "+") THEN
  310.         minus := s[i] = "-";
  311.         INC(i)
  312.     END;
  313.  
  314.     WHILE (error = 0) & STRINGS.digit(s[i]) DO
  315.         d := digit[ORD(s[i])];
  316.         IF n <= (UTILS.maxint - d) DIV 10 THEN
  317.             n := n * 10 + d;
  318.             INC(i)
  319.         ELSE
  320.             error := 5
  321.         END
  322.     END;
  323.  
  324.     exp10 := 1.0;
  325.     WHILE (error = 0) & (n > 0) DO
  326.         IF opFloat2(exp10, 10.0, "*") THEN
  327.             DEC(n)
  328.         ELSE
  329.             error := 4
  330.         END
  331.     END;
  332.  
  333.     IF error = 0 THEN
  334.         IF minus THEN
  335.             IF ~opFloat2(value, exp10, "/") THEN
  336.                 error := 4
  337.             END
  338.         ELSE
  339.             IF ~opFloat2(value, exp10, "*") THEN
  340.                 error := 4
  341.             END
  342.         END
  343.     END;
  344.  
  345.     IF error = 0 THEN
  346.         v.float := value;
  347.         v.typ := tREAL;
  348.         IF ~check(v) THEN
  349.             error := 4
  350.         END
  351.     END
  352.  
  353. END fconv;
  354.  
  355.  
  356. PROCEDURE setChar* (VAR v: VALUE; ord: INTEGER);
  357. BEGIN
  358.     v.typ := tCHAR;
  359.     v.int := ord
  360. END setChar;
  361.  
  362.  
  363. PROCEDURE setWChar* (VAR v: VALUE; ord: INTEGER);
  364. BEGIN
  365.     v.typ := tWCHAR;
  366.     v.int := ord
  367. END setWChar;
  368.  
  369.  
  370. PROCEDURE addInt (VAR a: INTEGER; b: INTEGER): BOOLEAN;
  371. VAR
  372.     error: BOOLEAN;
  373.  
  374. BEGIN
  375.     IF (a > 0) & (b > 0) THEN
  376.         error := a > UTILS.maxint - b
  377.     ELSIF (a < 0) & (b < 0) THEN
  378.         error := a < UTILS.minint - b
  379.     ELSE
  380.         error := FALSE
  381.     END;
  382.  
  383.     IF ~error THEN
  384.         a := a + b
  385.     ELSE
  386.         a := 0
  387.     END
  388.  
  389.     RETURN ~error
  390. END addInt;
  391.  
  392.  
  393. PROCEDURE subInt (VAR a: INTEGER; b: INTEGER): BOOLEAN;
  394. VAR
  395.     error: BOOLEAN;
  396.  
  397. BEGIN
  398.     IF (a > 0) & (b < 0) THEN
  399.         error := a > UTILS.maxint + b
  400.     ELSIF (a < 0) & (b > 0) THEN
  401.         error := a < UTILS.minint + b
  402.     ELSIF (a = 0) & (b < 0) THEN
  403.         error := b = UTILS.minint
  404.     ELSE
  405.         error := FALSE
  406.     END;
  407.  
  408.     IF ~error THEN
  409.         a := a - b
  410.     ELSE
  411.         a := 0
  412.     END
  413.  
  414.     RETURN ~error
  415. END subInt;
  416.  
  417.  
  418. PROCEDURE lg2 (x: INTEGER): INTEGER;
  419. VAR
  420.     n: INTEGER;
  421.  
  422. BEGIN
  423.     ASSERT(x > 0);
  424.  
  425.     n := 0;
  426.     WHILE ~ODD(x) DO
  427.         x := x DIV 2;
  428.         INC(n)
  429.     END;
  430.  
  431.     IF x # 1 THEN
  432.         n := 255
  433.     END
  434.  
  435.     RETURN n
  436. END lg2;
  437.  
  438.  
  439. PROCEDURE mulInt* (VAR a: INTEGER; b: INTEGER): BOOLEAN;
  440. VAR
  441.     error:    BOOLEAN;
  442.     min, max: INTEGER;
  443.  
  444. BEGIN
  445.     min := UTILS.minint;
  446.     max := UTILS.maxint;
  447.  
  448.     IF ((a > 1) & (b > 1)) OR ((a < 0) & (b < 0)) THEN
  449.         error := (a = min) OR (b = min) OR (ABS(a) > max DIV ABS(b))
  450.  
  451.     ELSIF ((a > 1) & (b < 0)) OR ((a < 0) & (b > 1)) THEN
  452.         error := (a = min) OR (b = min);
  453.         IF ~error THEN
  454.             IF lg2(ABS(a)) + lg2(ABS(b)) >= UTILS.bit_depth THEN
  455.                 error := ABS(a) > max DIV ABS(b)
  456.             END
  457.         END
  458.  
  459.     ELSE
  460.         error := FALSE
  461.     END;
  462.  
  463.     IF ~error THEN
  464.         a := a * b
  465.     ELSE
  466.         a := 0
  467.     END
  468.  
  469.     RETURN ~error
  470. END mulInt;
  471.  
  472.  
  473. PROCEDURE _ASR (x, n: INTEGER): INTEGER;
  474. BEGIN
  475.     IF MACHINE._64to32 THEN
  476.         x := MACHINE.Int32To64(x)
  477.     END
  478.  
  479.     RETURN ASR(x, n)
  480. END _ASR;
  481.  
  482.  
  483. PROCEDURE _LSR (x, n: INTEGER): INTEGER;
  484. BEGIN
  485.     IF MACHINE._64to32 THEN
  486.         x := MACHINE.Int64To32(x);
  487.         x := LSR(x, n);
  488.         x := MACHINE.Int32To64(x)
  489.     ELSE
  490.         x := LSR(x, n)
  491.     END
  492.  
  493.     RETURN x
  494. END _LSR;
  495.  
  496.  
  497. PROCEDURE _LSL (x, n: INTEGER): INTEGER;
  498. BEGIN
  499.     x := LSL(x, n);
  500.     IF MACHINE._64to32 THEN
  501.         x := MACHINE.Int32To64(x)
  502.     END
  503.  
  504.     RETURN x
  505. END _LSL;
  506.  
  507.  
  508. PROCEDURE _ROR1_32 (x: INTEGER): INTEGER;
  509. BEGIN
  510.     x := MACHINE.Int64To32(x);
  511.     x := ORD(BITS(LSR(x, 1)) + BITS(LSL(x, 31)))
  512.     RETURN MACHINE.Int32To64(x)
  513. END _ROR1_32;
  514.  
  515.  
  516. PROCEDURE _ROR (x, n: INTEGER): INTEGER;
  517. BEGIN
  518.     IF MACHINE._64to32 THEN
  519.         n := n MOD 32;
  520.         WHILE n > 0 DO
  521.             x := _ROR1_32(x);
  522.             DEC(n)
  523.         END
  524.     ELSE
  525.         x := ROR(x, n)
  526.     END
  527.  
  528.     RETURN x
  529. END _ROR;
  530.  
  531.  
  532. PROCEDURE opInt* (VAR a: VALUE; b: VALUE; op: CHAR): BOOLEAN;
  533. VAR
  534.     success: BOOLEAN;
  535.  
  536. BEGIN
  537.     success := TRUE;
  538.  
  539.     CASE op OF
  540.     |"+": success := addInt(a.int, b.int)
  541.     |"-": success := subInt(a.int, b.int)
  542.     |"*": success := mulInt(a.int, b.int)
  543.     |"/": success := FALSE
  544.     |"D": IF (b.int # -1) OR (a.int # UTILS.minint) THEN a.int := a.int DIV b.int ELSE success := FALSE END
  545.     |"M": a.int := a.int MOD b.int
  546.     |"L": a.int := _LSL(a.int, b.int)
  547.     |"A": a.int := _ASR(a.int, b.int)
  548.     |"O": a.int := _ROR(a.int, b.int)
  549.     |"R": a.int := _LSR(a.int, b.int)
  550.     |"m": a.int := MIN(a.int, b.int)
  551.     |"x": a.int := MAX(a.int, b.int)
  552.     END;
  553.     a.typ := tINTEGER
  554.  
  555.     RETURN success & check(a)
  556. END opInt;
  557.  
  558.  
  559. PROCEDURE charToStr* (c: VALUE; VAR s: ARRAY OF CHAR);
  560. BEGIN
  561.     s[0] := CHR(c.int);
  562.     s[1] := 0X
  563. END charToStr;
  564.  
  565.  
  566. PROCEDURE opSet* (VAR a: VALUE; b: VALUE; op: CHAR);
  567. BEGIN
  568.     CASE op OF
  569.     |"+": a.set := a.set + b.set
  570.     |"-": a.set := a.set - b.set
  571.     |"*": a.set := a.set * b.set
  572.     |"/": a.set := a.set / b.set
  573.     END;
  574.     a.typ := tSET
  575. END opSet;
  576.  
  577.  
  578. PROCEDURE opFloat* (VAR a: VALUE; b: VALUE; op: CHAR): BOOLEAN;
  579. BEGIN
  580.     a.typ := tREAL
  581.     RETURN opFloat2(a.float, b.float, op) & check(a)
  582. END opFloat;
  583.  
  584.  
  585. PROCEDURE ord* (VAR v: VALUE);
  586. BEGIN
  587.     CASE v.typ OF
  588.     |tCHAR, tWCHAR:
  589.     |tBOOLEAN: v.int := ORD(v.bool)
  590.     |tSET:
  591.         v.int := ORD(v.set);
  592.         IF MACHINE._64to32 THEN
  593.             v.int := MACHINE.Int32To64(v.int)
  594.         END
  595.     END;
  596.     v.typ := tINTEGER
  597. END ord;
  598.  
  599.  
  600. PROCEDURE odd* (VAR v: VALUE);
  601. BEGIN
  602.     v.typ := tBOOLEAN;
  603.     v.bool := ODD(v.int)
  604. END odd;
  605.  
  606.  
  607. PROCEDURE bits* (VAR v: VALUE);
  608. BEGIN
  609.     v.typ := tSET;
  610.     v.set := BITS(v.int)
  611. END bits;
  612.  
  613.  
  614. PROCEDURE abs* (VAR v: VALUE): BOOLEAN;
  615. VAR
  616.     res: BOOLEAN;
  617.  
  618. BEGIN
  619.     res := FALSE;  
  620.  
  621.     CASE v.typ OF
  622.     |tREAL:
  623.         v.float := ABS(v.float);
  624.         res := TRUE
  625.     |tINTEGER:
  626.         IF v.int # UTILS.minint THEN
  627.             v.int := ABS(v.int);
  628.             res := TRUE
  629.         END
  630.     END
  631.    
  632.     RETURN res
  633. END abs;
  634.  
  635.  
  636. PROCEDURE floor* (VAR v: VALUE): BOOLEAN;
  637. VAR
  638.     res: BOOLEAN;
  639.  
  640. BEGIN
  641.     v.typ := tINTEGER;
  642.     res := (FLT(UTILS.minint) <= v.float) & (v.float <= FLT(UTILS.maxint));
  643.     IF res THEN
  644.         v.int := FLOOR(v.float)
  645.     END
  646.  
  647.     RETURN res
  648. END floor;
  649.  
  650.  
  651. PROCEDURE flt* (VAR v: VALUE);
  652. BEGIN
  653.     v.typ := tREAL;
  654.     v.float := FLT(v.int)
  655. END flt;
  656.  
  657.  
  658. PROCEDURE neg* (VAR v: VALUE): BOOLEAN;
  659. VAR
  660.     z: VALUE;
  661.     res: BOOLEAN;
  662.  
  663. BEGIN
  664.     res := TRUE;
  665.  
  666.     z.typ := tINTEGER;
  667.     z.int := 0;
  668.  
  669.     CASE v.typ OF
  670.     |tREAL:     v.float := -v.float
  671.     |tSET:      v.set := -v.set
  672.     |tINTEGER:  res := opInt(z, v, "-"); v := z
  673.     |tBOOLEAN:  v.bool := ~v.bool
  674.     END
  675.  
  676.     RETURN res
  677. END neg;
  678.  
  679.  
  680. PROCEDURE setbool* (VAR v: VALUE; b: BOOLEAN);
  681. BEGIN
  682.     v.bool := b;
  683.     v.typ := tBOOLEAN
  684. END setbool;
  685.  
  686.  
  687. PROCEDURE opBoolean* (VAR a: VALUE; b: VALUE; op: CHAR);
  688. BEGIN
  689.     CASE op OF
  690.     |"&": a.bool := a.bool & b.bool
  691.     |"|": a.bool := a.bool OR b.bool
  692.     END;
  693.     a.typ := tBOOLEAN
  694. END opBoolean;
  695.  
  696.  
  697. PROCEDURE range* (i: VALUE; a, b: INTEGER): BOOLEAN;
  698.     RETURN (a <= i.int) & (i.int <= b)
  699. END range;
  700.  
  701.  
  702. PROCEDURE less (v, v2: VALUE; VAR error: INTEGER): BOOLEAN;
  703. VAR
  704.     res: BOOLEAN;
  705.  
  706. BEGIN
  707.     res := FALSE;
  708.  
  709.     IF (v.typ = v2.typ) OR (v.typ IN {tCHAR, tWCHAR}) & (v2.typ IN {tCHAR, tWCHAR}) THEN
  710.         CASE v.typ OF
  711.         |tINTEGER,
  712.          tWCHAR,
  713.          tCHAR:     res := v.int < v2.int
  714.         |tREAL:     res := v.float < v2.float
  715.         |tBOOLEAN,
  716.          tSET:      error := 1
  717.         END
  718.     ELSE
  719.         error := 1
  720.     END
  721.  
  722.     RETURN res
  723. END less;
  724.  
  725.  
  726. PROCEDURE equal (v, v2: VALUE; VAR error: INTEGER): BOOLEAN;
  727. VAR
  728.     res: BOOLEAN;
  729.  
  730. BEGIN
  731.     res := FALSE;
  732.  
  733.     IF (v.typ = v2.typ) OR (v.typ IN {tCHAR, tWCHAR}) & (v2.typ IN {tCHAR, tWCHAR}) THEN
  734.         CASE v.typ OF
  735.         |tINTEGER,
  736.          tWCHAR,
  737.          tCHAR:     res := v.int = v2.int
  738.         |tREAL:     res := v.float = v2.float
  739.         |tBOOLEAN:  res := v.bool = v2.bool
  740.         |tSET:      res := v.set = v2.set
  741.         END
  742.     ELSE
  743.         error := 1
  744.     END
  745.  
  746.     RETURN res
  747. END equal;
  748.  
  749.  
  750. PROCEDURE relation* (VAR v: VALUE; v2: VALUE; operator: RELATION; VAR error: INTEGER);
  751. VAR
  752.     res: BOOLEAN;
  753.  
  754. BEGIN
  755.     error := 0;
  756.  
  757.     res := FALSE;
  758.  
  759.     CASE operator[0] OF
  760.  
  761.     |"=":
  762.         res := equal(v, v2, error)
  763.  
  764.     |"#":
  765.         res := ~equal(v, v2, error)
  766.  
  767.     |"<":
  768.         IF operator[1] = "=" THEN
  769.             res := less(v, v2, error);
  770.             IF error = 0 THEN
  771.                 res := equal(v, v2, error) OR res
  772.             END
  773.         ELSE
  774.             res := less(v, v2, error)
  775.         END
  776.  
  777.     |">":
  778.         IF operator[1] = "=" THEN
  779.             res := ~less(v, v2, error)
  780.         ELSE
  781.             res := less(v, v2, error);
  782.             IF error = 0 THEN
  783.                 res := equal(v, v2, error) OR res
  784.             END;
  785.             res := ~res
  786.         END
  787.  
  788.     |"I":
  789.         IF (v.typ = tINTEGER) & (v2.typ = tSET) THEN
  790.             IF range(v, 0, MACHINE.target.maxSet) THEN
  791.                 res := v.int IN v2.set
  792.             ELSE
  793.                 error := 2
  794.             END
  795.         ELSE
  796.             error := 1
  797.         END
  798.  
  799.     END;
  800.  
  801.     IF error = 0 THEN
  802.         v.bool := res;
  803.         v.typ  := tBOOLEAN
  804.     END
  805.  
  806. END relation;
  807.  
  808.  
  809. PROCEDURE emptySet* (VAR v: VALUE);
  810. BEGIN
  811.     v.typ := tSET;
  812.     v.set := {}
  813. END emptySet;
  814.  
  815.  
  816. PROCEDURE constrSet* (VAR v: VALUE; a, b: VALUE);
  817. BEGIN
  818.     v.typ := tSET;
  819.     v.set := {a.int .. b.int}
  820. END constrSet;
  821.  
  822.  
  823. PROCEDURE getInt* (v: VALUE): INTEGER;
  824. BEGIN
  825.     ASSERT(check(v))
  826.  
  827.     RETURN v.int
  828. END getInt;
  829.  
  830.  
  831. PROCEDURE setInt* (VAR v: VALUE; i: INTEGER): BOOLEAN;
  832. BEGIN
  833.     v.int := i;
  834.     v.typ := tINTEGER
  835.  
  836.     RETURN check(v)
  837. END setInt;
  838.  
  839.  
  840. PROCEDURE init;
  841. VAR
  842.     i: INTEGER;
  843.  
  844. BEGIN
  845.     FOR i := 0 TO LEN(digit) - 1 DO
  846.         digit[i] := -1
  847.     END;
  848.  
  849.     FOR i := ORD("0") TO ORD("9") DO
  850.         digit[i] := i - ORD("0")
  851.     END;
  852.  
  853.     FOR i := ORD("A") TO ORD("F") DO
  854.         digit[i] := i - ORD("A") + 10
  855.     END
  856. END init;
  857.  
  858.  
  859. BEGIN
  860.     init
  861. END ARITH.