File: Word8.sml

package info (click to toggle)
polyml 5.2.1-1.1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd, wheezy
  • size: 19,692 kB
  • ctags: 17,567
  • sloc: cpp: 37,221; sh: 9,591; asm: 4,120; ansic: 428; makefile: 203; ml: 191; awk: 91; sed: 10
file content (187 lines) | stat: -rw-r--r-- 6,473 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
(*
    Title:      Standard Basis Library: Word8 Structure
    Author:     David Matthews
    Copyright   David Matthews 1999

	This library is free software; you can redistribute it and/or
	modify it under the terms of the GNU Lesser General Public
	License as published by the Free Software Foundation; either
	version 2.1 of the License, or (at your option) any later version.
	
	This library is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
	Lesser General Public License for more details.
	
	You should have received a copy of the GNU Lesser General Public
	License along with this library; if not, write to the Free Software
	Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*)

(* G&R 2004 status: checked, no change *)

structure Word8 :> WORD =
struct
	(* This structure is largely derived from Word but we use opaque
	   signature matching so that it is a different type. *)
	open Word
	
	(* Values of type Word8.word can be in the range 0..255 and
	   are implemented using tagged integers.  *)
	(* There seem to be two ways to implement this, given that the underlying
	   representation is a tagged 30/31 bit integer.  We could either ensure
	   that the top 22/23 bits are always zero and mask them after every
	   operation (or if the code-generator was clever, after several) or 
	   we could allow these bits to be undefined and mask them before any
	   operation which could expose them.  For the moment we choose the
	   former.  *)
	(* N.B. The Byte structure contains functions which map between
	   Word8.word values and Char.char.  It assumes that the underlying
	   representation is the same. *)
	open RuntimeCalls

	val wordSize = 8
	val maxWord = 255
	val maxWordAsWord: word = RunCall.unsafeCast maxWord
	
	infix 8 << >> ~>> ;

	(* Comparison operations, min, max and compare, fmt, toString,
	   orb, andb, xorb can be inherited directly from Word.
	   Similarly div and mod since the results will always be no
	   larger than the arguments. *)
	(* ... but this can't because the second argument is still Word.word
	   even in this structure. *)
	val op >> : word*Word.word->word = RunCall.run_call2 POLY_SYS_shift_right_word

	(* Not the same as Word.notb because it only affects the bottom 8 bits.  *)
	fun notb x = xorb(maxWordAsWord, x)

	(* Internal function to convert from Word.word. *)
	fun fromWord (w: Word.word) = andb(w, maxWordAsWord)

	(* Converting from LargeWord.word.  First convert to Word.word and
	   then mask. *)
	fun fromLargeWord (w: LargeWord.word) =
		fromWord(Word.fromLargeWord w)
	and fromInt (i: int): word = fromWord(Word.fromInt i)
	
	val fromLarge = fromLargeWord

			(* Arithmetic shift - sign extends. *)
	(* TODO: Replace by built-in?  We need a separate function from
	   arithmetic shift for Word because the sign bit is in a different
	   place.  *)
	(* Shift the "sign" bit into the real sign bit position then
	   shift right down again. *)
	local
		val toSignBit = Word.fromInt(Int.-(Word.wordSize,wordSize))
	in
		fun op ~>> (a: word, b: Word.word): word =
			fromWord(Word.~>>(Word.<<(a, toSignBit), Word.+(b, toSignBit)))
	end
	
	(* TODO: Replace with built-in?  We need to mask the result so
	   that it remains in the range 0..255 *)
	local
		val wordshift = RunCall.run_call2 POLY_SYS_shift_left_word
	in
		fun op << (a: word, b: Word.word): word =
			andb(wordshift(a,b), maxWordAsWord)
	end

	(* Conversion to unsigned integer.  This is simpler than for Word
	   because all Word8 values correspond to short integers. *)
	val toInt: word->int = RunCall.unsafeCast
	
	(* Conversion to signed integer. *)
	(* TODO: This could be implemented using shifts. i.e logical shift
	   left by (Word.wordSize-Word8.wordSize) then arithmetic shift
	   right by the same amount. *)
	fun toIntX (x: word) : int =
		let
			val intx = toInt x
			open Int (* We want integer arithmetic here. *)
		in
			if intx >= 128
			then intx-maxWord-1
			else intx
		end
	
	val fromLargeInt = fromInt
	and toLargeInt = toInt
	and toLargeIntX = toIntX

	(* Convert to a large word by sign extending. *)
	fun toLargeWordX (w: word): LargeWord.word =
		LargeWord.fromInt(toIntX w);
	val toLargeX = toLargeWordX
	
	(* Use Word.scan but check that the result is in the range. *)
	val wordScan = scan;

	fun scan radix getc src =
		case wordScan radix getc src of
			NONE => NONE
		 |  SOME(res, src') =>
		 		if res > maxWordAsWord
				then raise General.Overflow
				else SOME(res, src')

	val fromString = StringCvt.scanString (scan StringCvt.HEX)

	(* TODO: Replace by built-ins? *)
	fun op + (a, b) = fromWord(Word.+(a, b))
	and op - (a, b) = fromWord(Word.-(a, b))
	and op * (a, b) = fromWord(Word.*(a, b))

end;

(* Because we are using opaque signature matching we have to install
   type-dependent functions OUTSIDE the structure. *)
local
	open RuntimeCalls
    structure Conversion =
      RunCall.Run_exception1
        (
          type ex_type = string;
          val ex_iden  = EXC_conversion
        );
    exception Conversion = Conversion.ex;
	(* The string may be either 0wnnn or 0wxXXX *)
	fun convWord s : Word8.word =
		let
		val radix =
			(* The word value must consist of at least 0w and a digit. *)
			if String.sub(s, 2) = #"x" then StringCvt.HEX else StringCvt.DEC
		in
			case StringCvt.scanString (Word8.scan radix) s of
				NONE => raise Conversion "Invalid word8 constant"
			  | SOME res => res
		end
		
	(* Install the pretty printer for Word8.word *)
	fun pretty(p, _, _, _) _ _ x = p("0wx" ^ Word8.toString x)
in
	val () = RunCall.addOverload convWord "convWord"
	val () = PolyML.install_pp pretty
end;

(* Add the overloaded operators. *)
RunCall.addOverload Word8.+ "+";
RunCall.addOverload Word8.- "-";
RunCall.addOverload Word8.* "*";
RunCall.addOverload Word8.div "div";
RunCall.addOverload Word8.mod "mod";
RunCall.addOverload Word8.< "<";
RunCall.addOverload Word8.> ">";
RunCall.addOverload Word8.<= "<=";
RunCall.addOverload Word8.>= ">=";
(* Add overloadings for = and <>.  The effect of this is to provide
   more efficient implementations than the default structure equality. *)
val it : Word8.word * Word8.word -> bool =
	RunCall.run_call2 RuntimeCalls.POLY_SYS_word_eq;
RunCall.addOverload it "=";
val it : Word8.word * Word8.word -> bool =
	RunCall.run_call2 RuntimeCalls.POLY_SYS_word_neq;
RunCall.addOverload it "<>";