1(* 2 Title: Standard Basis Library: Word8 Structure 3 Author: David Matthews 4 Copyright David Matthews 1999 5 6 This library is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Lesser General Public 8 License as published by the Free Software Foundation; either 9 version 2.1 of the License, or (at your option) any later version. 10 11 This library is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public 17 License along with this library; if not, write to the Free Software 18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19*) 20 21(* G&R 2004 status: checked, no change *) 22 23structure Word8 :> WORD = 24struct 25 (* This structure is largely derived from Word but we use opaque 26 signature matching so that it is a different type. *) 27 open Word 28 29 (* Values of type Word8.word can be in the range 0..255 and 30 are implemented using tagged integers. *) 31 (* There seem to be two ways to implement this, given that the underlying 32 representation is a tagged 30/31 bit integer. We could either ensure 33 that the top 22/23 bits are always zero and mask them after every 34 operation (or if the code-generator was clever, after several) or 35 we could allow these bits to be undefined and mask them before any 36 operation which could expose them. For the moment we choose the 37 former. *) 38 (* N.B. The Byte structure contains functions which map between 39 Word8.word values and Char.char. It assumes that the underlying 40 representation is the same. *) 41 42 val wordSize = 8 43 val maxWord = 255 44 val maxWordAsWord: word = RunCall.unsafeCast maxWord 45 46 infix 8 << >> ~>> 47 48 (* Comparison operations, min, max and compare, fmt, toString, 49 orb, andb, xorb can be inherited directly from Word. 50 Similarly div and mod since the results will always be no 51 larger than the arguments. *) 52 53 (* Not the same as Word.notb because it only affects the bottom 8 bits. *) 54 fun notb x = xorb(maxWordAsWord, x) 55 56 (* Internal function to convert from Word.word. *) 57 fun fromWord (w: Word.word) = andb(w, maxWordAsWord) 58 59 (* Converting from LargeWord.word. First convert to Word.word and 60 then mask. *) 61 val fromLargeWord = fromWord o Word.fromLargeWord 62 and fromInt = fromWord o Word.fromInt 63 and fromLargeInt = fromWord o Word.fromLargeInt 64 65 val fromLarge = fromLargeWord 66 67 (* Arithmetic shift - sign extends. *) 68 (* TODO: Replace by built-in? We need a separate function from 69 arithmetic shift for Word because the sign bit is in a different 70 place. *) 71 (* Shift the "sign" bit into the real sign bit position then 72 shift right down again. *) 73 local 74 val toSignBit = Word.fromInt(Int.-(Word.wordSize,wordSize)) 75 in 76 fun op ~>> (a: word, b: Word.word): word = 77 fromWord(Word.~>>(Word.<<(a, toSignBit), Word.+(b, toSignBit))) 78 end 79 80 (* TODO: Replace with built-in? We need to mask the result so 81 that it remains in the range 0..255 *) 82 fun op << (a: word, b: Word.word): word = andb(Word.<<(a,b), maxWordAsWord) 83 84 (* Conversion to unsigned integer. This is simpler than for Word 85 because all Word8 values correspond to short integers. *) 86 val toInt: word->int = RunCall.unsafeCast 87 88 (* Conversion to signed integer. *) 89 (* TODO: This could be implemented using shifts. i.e logical shift 90 left by (Word.wordSize-Word8.wordSize) then arithmetic shift 91 right by the same amount. *) 92 fun toIntX (x: word) : int = 93 let 94 val intx = toInt x 95 open Int (* We want integer arithmetic here. *) 96 in 97 if intx >= 128 98 then intx-maxWord-1 99 else intx 100 end 101 102 val toLargeInt = LargeInt.fromInt o toInt 103 and toLargeIntX = LargeInt.fromInt o toIntX 104 105 (* Convert to a large word by sign extending. *) 106 fun toLargeWordX (w: word): LargeWord.word = 107 LargeWord.fromInt(toIntX w); 108 val toLargeX = toLargeWordX 109 110 (* Use Word.scan but check that the result is in the range. *) 111 val wordScan = scan; 112 113 fun scan radix getc src = 114 case wordScan radix getc src of 115 NONE => NONE 116 | SOME(res, src') => 117 if res > maxWordAsWord 118 then raise General.Overflow 119 else SOME(res, src') 120 121 val fromString = StringCvt.scanString (scan StringCvt.HEX) 122 123 (* TODO: Replace by built-ins? *) 124 fun op + (a, b) = fromWord(Word.+(a, b)) 125 and op - (a, b) = fromWord(Word.-(a, b)) 126 and op * (a, b) = fromWord(Word.*(a, b)) 127 128 fun ~ x = 0w0 - x 129 130end; 131 132(* Because we are using opaque signature matching we have to install 133 type-dependent functions OUTSIDE the structure. *) 134local 135 (* The string may be either 0wnnn or 0wxXXX *) 136 fun convWord s : Word8.word = 137 let 138 val radix = 139 (* The word value must consist of at least 0w and a digit. *) 140 if String.sub(s, 2) = #"x" then StringCvt.HEX else StringCvt.DEC 141 in 142 case StringCvt.scanString (Word8.scan radix) s of 143 NONE => raise RunCall.Conversion "Invalid word8 constant" 144 | SOME res => res 145 end 146 147 (* Install the pretty printer for Word8.word *) 148 fun pretty _ _ x = PolyML.PrettyString("0wx" ^ Word8.toString x) 149in 150 val () = RunCall.addOverload convWord "convWord" 151 val () = PolyML.addPrettyPrinter pretty 152end; 153 154(* Add the overloaded operators. *) 155val () = RunCall.addOverload Word8.~ "~"; 156val () = RunCall.addOverload Word8.+ "+"; 157val () = RunCall.addOverload Word8.- "-"; 158val () = RunCall.addOverload Word8.* "*"; 159val () = RunCall.addOverload Word8.div "div"; 160val () = RunCall.addOverload Word8.mod "mod"; 161val () = RunCall.addOverload Word8.< "<"; 162val () = RunCall.addOverload Word8.> ">"; 163val () = RunCall.addOverload Word8.<= "<="; 164val () = RunCall.addOverload Word8.>= ">="; 165