{ MODULE 15 Object Value Manipulation This chapter implements the interface procedures for creating and manipulating literal object values at compile-time, as defined in Section 5.3. The overriding consideration in determining how these are imple- mented is the distinction between the representation of primitive values such as integers, reals etc. on the host compiling machine and that to be used on the target machine on which compiled pro- grams are run. For many compilers the host and target machines are identical and the distinction is not important, but for cross compilers it is essential that the distinction be maintained and that conversion from host to target representations occur at the correct points. In this version of the Model Implementation the following assump- tions are made. (a) The integer range of the target machine is no greater than that of the host machine. (b) The floating point representations of the host and target machines are identical. (c) The character set representations of the host and target machines are identical. With these assumptions the type ObjectValue, which is used to represent target machine literal values, is easily defined: all ordinal target values are held as a host integer subrange; real target values are held as a host real; string, set and pointer values which may extend over several target words are held as linked lists of target word images. In the case of strings, which may not occupy an integral multiple of words a length in bytes is also maintained. The following procedures isolate the points at which mapping of host to target values occur: } program ObjectValues; #include "globals.x" #include "generator.pf" #include "datareps.pf" procedure SetIval(HostInteger: integer; var Velue: ObjectValue); visible; begin with Velue do begin Kind := IntValue; Ival := HostInteger; WordSize := IntegerRepresentation.WordSize end end ; { setival } procedure SetRval(HostReal: real; var Velue: ObjectValue); begin with Velue do begin Kind := RealValue; Rval := HostReal; WordSize := RealRepresentation.WordSize end end; { setrval } procedure SetBval(HostBoolean: Boolean; var Velue: ObjectValue); visible; begin with Velue do begin Kind := BoolValue; Ival := ord(HostBoolean); WordSize := 1 end end; { setbval } {function MapChar(HostCh: char): MCByte; begin MapChar := ord(HostCh) end; } { The procedure Evaluate carries out the conversion of source literal images in character form to the target values they denote. In addition to the assumptions listed above the following version of Evaluate makes the assumption that a host integer provides suf- ficient accuracy for accumulating the value of the mantissa in a real constant. For many host machines this would not be accept- able and an augmented mantissa representation would be necessary. It is important, however, to avoid accumulating mantissa values as host reals, since inaccuracies introduced during the accumulation may significantly degrade the accuracy of the final mantissa obtained. The strategy below uses real arithmetic only to compute a power-of-1O scale factor required for the final scaling opera- tion. Accuracy may be further increased by using table look-up to obtain the power of 1O required. } procedure Evaluate (var SourceValue : ValueDetails); var Index: integer; ByteIndex: MCByteIndex; Digit: 0..15; Ivalu, Scale, Exponent, Base: integer; Rvalu: real; c: char; StringWord, Element: WordEntry; Negative, Overflow: Boolean; procedure AddDigitTo(var Number: integer); var Digit: 0..9; begin Digit := ord(SourceValue.String[Index]) - ord('0'); Overflow := Overflow or (Number > MCMaxintDiv10) or ((Number = MCMaxintDiv10) and (Digit > MCMaxintMod10)); if not Overflow then Number := Number * 10 + Digit end ; function PowerOf10(n: integer): real; var Factor, Power: real; begin Factor := 10.0; Power := 1.0; repeat if odd(n) then Power := Power * Factor; Factor := sqr(Factor); n := n div 2 until n = 0; PowerOf10 := Power end ; begin with SourceValue do case Kind of OrdValue : SetIval(Ival, Velue); CharValue : with Velue do begin Kind := CharValue; WordSize := 1; Ival := ord(String[1]) end; StringValue : with Velue do begin Kind := StringValue; Stringval := nil; Index := 1; ByteIndex := 0; while Index <= SourceValue.Length do begin if ByteIndex = 0 then begin new(Element); with Element^ do begin Word.WValue := 0; Next := nil end; if Stringval = nil then Stringval := Element else StringWord^.Next := Element; StringWord := Element end; with StringWord^ do MCSetByte (Word, ByteIndex, ord(String[Index])); ByteIndex := (ByteIndex + 1) mod MCBytesPerWord; Index := Index + 1 end; Length := SourceValue.Length; WordSize := WordsFor(Length, MCBytesPerWord) end; IntValue : begin Ivalu := 0; Overflow := false; for Index := 1 to Length do AddDigitTo(Ivalu); if Overflow then begin PredictedError(47); Velue := MaxintValue end else SetIval(Ivalu, Velue) end; BaseValue : with Velue do begin Kind := BaseValue; Base := WVal; Wval:=0; for Index:=1 to Length do begin c := String[Index]; if (c in ['0'..'9']) then Digit := ord(c) - ord('0') else Digit := ord(c) - ord('A') + 10; if (WVal > maxWord div Base) or ((Wval = maxWord div Base) and (Digit > maxWord mod Base )) then WVal := maxWord else Wval := Base * WVal + Digit end; WordSize:=1; end; RealValue : begin Ivalu := 0; Scale := 0; Overflow := false; Index := 1; String[Length + 1] := ' '; while String[Index] in ['0'..'9'] do begin AddDigitTo(Ivalu); if Overflow then Scale := Scale + 1; Index := Index + 1 end; if String[Index] = '.' then begin Index := Index + 1; while String[Index] in ['0'..'9'] do begin AddDigitTo(Ivalu); if not Overflow then Scale := Scale - 1; Index := Index + 1 end end; if String[Index] = 'E' then begin Index := Index + 1; Negative := (String[Index] = '-'); Exponent := 0; for Index := Index + 1 to Length do AddDigitTo(Exponent); if Negative then Scale := Scale - Exponent else Scale := Scale + Exponent end; if Scale = 0 then Rvalu := Ivalu else if Scale < 0 then Rvalu := Ivalu / PowerOf10(Scale) else Rvalu := Ivalu * PowerOf10(Scale); SetRval(Rvalu, Velue) end end end; { evaluate } { The following procedures implement the object value operators required by the analyser, within the assumptions listed above. } procedure NegateValue (var Velue : ObjectValue); begin with Velue do case Kind of OrdValue, IntValue : Ival := -Ival; BoolValue : case Ival of 0 : Ival := 1; 1 : Ival := 0 end; RealValue : Rval := -Rval end end; { negatevalue } function SameValue (Value1,Value2 : ObjectValue ) : Boolean; begin SameValue := Value1.Ival = Value2.Ival end; function OrderedValues (Value1,Value2 : ObjectValue ) : Boolean; begin OrderedValues := Value1.Ival < Value2.Ival end; function Range (Min, Max: ObjectValue): integer; { Computes the range defined by two object values within } { the limits of the host integer-space. The value maxint } { is returned for those values whose range cannot be } { represented by a host integer value. } var Finite: Boolean; begin if Max.Ival < 0 then Finite := true else Finite := (Max.Ival - maxint) < Min.Ival; if Finite then Range := Max.Ival - Min.Ival + 1 else Range := maxint end; { range } { The procedure InitValues is called from within InitCodeGeneration to set up all predefined object values which the generation inter- face provides. } procedure InitValues; visible; begin SetIval(0, ZeroValue); SetIval(1, OneValue); SetIval(0, MinLabValue); SetIval(9999, MaxLabValue); SetIval(0, MinCharValue); SetIval(MCMaxChar, MaxCharValue); SetIval(10, LineFeed); SetIval(12, PageThrow); SetIval(10, DftLayout); SetIval(0, DftValue); SetIval(MCMaxint, MaxintValue); SetRval(0.0, ZeroReal); SetBval(false, FalseValue); SetBval(true, TrueValue); { ZeroValue.IVal := 0; OneValue.IVal :=1; MinLabValue.IVal := 0; MaxLabValue.IVal := 9999; MinCharValue.IVal := 0; MaxCharValue.IVal := MCMaxChar; LineFeed.IVal:= 10; PageThrow.IVal := 12; DftValue.IVal:=0; MaxintValue.IVal := MCMaxint; ZeroReal.WVal := 0; FalseValue.IVal := ord(false); TrueValue.IVal := ord(true); } with NilValue do begin Kind := PntrValue; Pval := nil; WordSize := 0 end; with EmptyValue do begin Kind := SetValue; Setval := nil; WordSize := 0 end end { initvalues }; begin { module ends here } end.