mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-06-05 16:18:36 +02:00
pastojs: intrinsics lo/hi, issue #34964, patch from Kryvichh
git-svn-id: trunk@41148 -
This commit is contained in:
parent
70c4d45474
commit
6160a2ad51
@ -25,7 +25,7 @@ Works:
|
||||
- int/uint
|
||||
- unary +, -
|
||||
- binary: +, -, *, div, mod, ^^, =, <>, <, >, <=, >=, and, or, xor, not, shl, shr
|
||||
- low(), high(), pred(), succ(), ord()
|
||||
- Low(), High(), Pred(), Succ(), Ord(), Lo(), Hi()
|
||||
- typecast longint(-1), word(-2), intsingle(-1), uintsingle(1)
|
||||
- float:
|
||||
- typecast single(double), double(single), float(integer)
|
||||
@ -714,6 +714,8 @@ type
|
||||
function EvalStrFunc(Params: TParamsExpr; Flags: TResEvalFlags): TResEvalValue; virtual;
|
||||
function EvalStringAddExpr(Expr, LeftExpr, RightExpr: TPasExpr;
|
||||
LeftValue, RightValue: TResEvalValue): TResEvalValue; virtual;
|
||||
function LoHiValue(Value: TResEvalValue; ShiftSize: Integer; Mask: LongWord;
|
||||
ErrorEl: TPasElement): TResEvalValue; virtual;
|
||||
function EnumTypeCast(EnumType: TPasEnumType; Expr: TPasExpr;
|
||||
Flags: TResEvalFlags): TResEvalEnum; virtual;
|
||||
{$ifdef FPC_HAS_CPSTRING}
|
||||
@ -735,6 +737,7 @@ type
|
||||
TResExprEvaluatorClass = class of TResExprEvaluator;
|
||||
|
||||
procedure ReleaseEvalValue(var Value: TResEvalValue);
|
||||
function NumberIsFloat(const Value: string): boolean;
|
||||
|
||||
{$ifdef FPC_HAS_CPSTRING}
|
||||
function RawStrToCaption(const r: RawByteString; MaxLength: integer): string;
|
||||
@ -757,6 +760,17 @@ begin
|
||||
Value:=nil;
|
||||
end;
|
||||
|
||||
function NumberIsFloat(const Value: string): boolean;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
if Value='' then exit(false);
|
||||
if Value[1] in ['$','%','&'] then exit(false);
|
||||
for i:=2 to length(Value) do
|
||||
if Value[i] in ['.','E','e'] then exit(true);
|
||||
Result:=false;
|
||||
end;
|
||||
|
||||
{$ifdef FPC_HAS_CPSTRING}
|
||||
function RawStrToCaption(const r: RawByteString; MaxLength: integer): string;
|
||||
var
|
||||
@ -4849,6 +4863,35 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TResExprEvaluator.LoHiValue(Value: TResEvalValue; ShiftSize: Integer;
|
||||
Mask: LongWord; ErrorEl: TPasElement): TResEvalValue;
|
||||
var
|
||||
uint: LongWord;
|
||||
begin
|
||||
case Value.Kind of
|
||||
revkInt:
|
||||
{$IFDEF Pas2js}
|
||||
if ShiftSize=32 then
|
||||
uint := (TResEvalInt(Value).Int div $100000000) and Mask;
|
||||
else
|
||||
{$ENDIF}
|
||||
uint := (TResEvalInt(Value).Int shr ShiftSize) and Mask;
|
||||
revkUInt:
|
||||
{$IFDEF Pas2js}
|
||||
if ShiftSize=32 then
|
||||
uint := (TResEvalUInt(Value).UInt div $100000000) and Mask;
|
||||
else
|
||||
{$ENDIF}
|
||||
uint := (TResEvalUInt(Value).UInt shr ShiftSize) and Mask;
|
||||
else
|
||||
{$IFDEF VerbosePasResEval}
|
||||
writeln('TResExprEvaluator.LoHiValue ',Value.AsDebugString);
|
||||
{$ENDIF}
|
||||
RaiseNotYetImplemented(20190129012100,ErrorEl);
|
||||
end;
|
||||
Result := TResEvalInt.CreateValue(uint);
|
||||
end;
|
||||
|
||||
function TResExprEvaluator.EnumTypeCast(EnumType: TPasEnumType; Expr: TPasExpr;
|
||||
Flags: TResEvalFlags): TResEvalEnum;
|
||||
var
|
||||
|
@ -228,6 +228,13 @@ Works:
|
||||
- with
|
||||
- self
|
||||
- built-in procedure Val(const s: string; var e: enumtype; out Code: integertype);
|
||||
- intrinsic functions Lo and Hi, depending on $mode (ObjFPC or Delphi):
|
||||
- In $MODE DELPHI:
|
||||
function Lo/Hi(i: <any integer type>): Byte
|
||||
- In $MODE OBJFPC:
|
||||
function Lo/Hi(i: Byte/ShortInt/Word/SmallInt): Byte
|
||||
function Lo/Hi(i: LongWord/LongInt/UIntSingle/IntSingle): Word
|
||||
function Lo/Hi(i: QWord/Int64/UIntDouble/IntDouble): LongWord
|
||||
- helpers:
|
||||
- class
|
||||
- record
|
||||
@ -549,6 +556,8 @@ type
|
||||
bfStrFunc,
|
||||
bfWriteStr,
|
||||
bfVal,
|
||||
bfLo,
|
||||
bfHi,
|
||||
bfConcatArray,
|
||||
bfConcatString,
|
||||
bfCopyArray,
|
||||
@ -584,6 +593,8 @@ const
|
||||
'Str',
|
||||
'WriteStr',
|
||||
'Val',
|
||||
'Lo',
|
||||
'Hi',
|
||||
'Concat',
|
||||
'Concat',
|
||||
'Copy',
|
||||
@ -1689,6 +1700,12 @@ type
|
||||
Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
|
||||
procedure BI_Val_OnFinishParamsExpr(Proc: TResElDataBuiltInProc;
|
||||
Params: TParamsExpr); virtual;
|
||||
function BI_LoHi_OnGetCallCompatibility(Proc: TResElDataBuiltInProc;
|
||||
Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
|
||||
procedure BI_LoHi_OnGetCallResult(Proc: TResElDataBuiltInProc;
|
||||
Params: TParamsExpr; out ResolvedEl: TPasResolverResult); virtual;
|
||||
procedure BI_LoHi_OnEval(Proc: TResElDataBuiltInProc;
|
||||
Params: TParamsExpr; Flags: TResEvalFlags; out Evaluated: TResEvalValue); virtual;
|
||||
function BI_ConcatArray_OnGetCallCompatibility(Proc: TResElDataBuiltInProc;
|
||||
Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
|
||||
procedure BI_ConcatArray_OnGetCallResult({%H-}Proc: TResElDataBuiltInProc;
|
||||
@ -2015,6 +2032,8 @@ type
|
||||
function IsElementSkipped(El: TPasElement): boolean; virtual;
|
||||
function FindLocalBuiltInSymbol(El: TPasElement): TPasElement; virtual;
|
||||
function GetLastSection: TPasSection;
|
||||
function GetShiftAndMaskForLoHiFunc(BaseType: TResolverBaseType;
|
||||
isLoFunc: Boolean; out Mask: LongWord): Integer;
|
||||
public
|
||||
// options
|
||||
property Options: TPasResolverOptions read FOptions write FOptions;
|
||||
@ -14387,6 +14406,77 @@ begin
|
||||
FinishCallArgAccess(P[2],rraOutParam);
|
||||
end;
|
||||
|
||||
function TPasResolver.BI_LoHi_OnGetCallCompatibility(
|
||||
Proc: TResElDataBuiltInProc; Expr: TPasExpr; RaiseOnError: boolean): integer;
|
||||
var
|
||||
Params: TParamsExpr;
|
||||
Param: TPasExpr;
|
||||
ParamResolved: TPasResolverResult;
|
||||
begin
|
||||
if not CheckBuiltInMinParamCount(Proc,Expr,1,RaiseOnError) then
|
||||
Exit(cIncompatible);
|
||||
Params:=TParamsExpr(Expr);
|
||||
// first Param: any integer type
|
||||
Param:=Params.params[0];
|
||||
ComputeElement(Param,ParamResolved,[]);
|
||||
Result:=cIncompatible;
|
||||
if (rrfReadable in ParamResolved.Flags)
|
||||
and (ParamResolved.BaseType in btAllInteger)
|
||||
then
|
||||
Result:=cExact;
|
||||
if Result=cIncompatible then
|
||||
Exit(CheckRaiseTypeArgNo(20190128232600,1,Param,ParamResolved,'integer type',RaiseOnError));
|
||||
Result:=CheckBuiltInMaxParamCount(Proc,Params,1,RaiseOnError);
|
||||
end;
|
||||
|
||||
procedure TPasResolver.BI_LoHi_OnGetCallResult(Proc: TResElDataBuiltInProc;
|
||||
Params: TParamsExpr; out ResolvedEl: TPasResolverResult);
|
||||
var
|
||||
ResolvedParam: TPasResolverResult;
|
||||
BaseType: TResolverBaseType;
|
||||
Mask: LongWord;
|
||||
begin
|
||||
ComputeElement(Params.Params[0],ResolvedParam,[]);
|
||||
GetShiftAndMaskForLoHiFunc(ResolvedParam.BaseType, Proc.BuiltIn=bfLo, Mask);
|
||||
case Mask of
|
||||
$F, $FF: BaseType := btByte;
|
||||
$FFFF: BaseType := btWord;
|
||||
else { $FFFFFFFF } BaseType := btLongWord;
|
||||
end;
|
||||
SetResolverIdentifier(ResolvedEl,BaseType,Proc.Proc,
|
||||
FBaseTypes[BaseType],FBaseTypes[BaseType],[rrfReadable]);
|
||||
end;
|
||||
|
||||
procedure TPasResolver.BI_LoHi_OnEval(Proc: TResElDataBuiltInProc;
|
||||
Params: TParamsExpr; Flags: TResEvalFlags; out Evaluated: TResEvalValue);
|
||||
var
|
||||
Param: TPasExpr;
|
||||
ResolvedParam: TPasResolverResult;
|
||||
Value: TResEvalValue;
|
||||
Shift: Integer;
|
||||
Mask: LongWord;
|
||||
begin
|
||||
Evaluated := nil;
|
||||
Param := Params.Params[0];
|
||||
Value := Eval(Param,Flags);
|
||||
{$IFDEF VerbosePasResEval}
|
||||
{AllowWriteln}
|
||||
if value=nil then
|
||||
writeln('TPasResolver.BI_LoHi_OnEval Value=NIL')
|
||||
else
|
||||
writeln('TPasResolver.BI_LoHi_OnEval Value=',value.AsDebugString);
|
||||
{AllowWriteln-}
|
||||
{$ENDIF}
|
||||
if Value=nil then exit;
|
||||
try
|
||||
ComputeElement(Param,ResolvedParam,[]);
|
||||
Shift := GetShiftAndMaskForLoHiFunc(ResolvedParam.BaseType, Proc.BuiltIn=bfLo, Mask);
|
||||
Evaluated := fExprEvaluator.LoHiValue(Value,Shift,Mask,Params);
|
||||
finally
|
||||
ReleaseEvalValue(Value);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TPasResolver.BI_ConcatArray_OnGetCallCompatibility(
|
||||
Proc: TResElDataBuiltInProc; Expr: TPasExpr; RaiseOnError: boolean): integer;
|
||||
var
|
||||
@ -16337,6 +16427,14 @@ begin
|
||||
AddBuiltInProc('Val','procedure Val(const String; var Value: bool|int|float|enum; out Int)',
|
||||
@BI_Val_OnGetCallCompatibility,nil,nil,
|
||||
@BI_Val_OnFinishParamsExpr,bfVal,[bipfCanBeStatement]);
|
||||
if bfLo in TheBaseProcs then
|
||||
AddBuiltInProc('Lo','function Lo(X: any integer type): Byte|Word)',
|
||||
@BI_LoHi_OnGetCallCompatibility,@BI_LoHi_OnGetCallResult,
|
||||
@BI_LoHi_OnEval,nil,bfLo);
|
||||
if bfHi in TheBaseProcs then
|
||||
AddBuiltInProc('Hi','function Hi(X: any integer type): Byte|Word)',
|
||||
@BI_LoHi_OnGetCallCompatibility,@BI_LoHi_OnGetCallResult,
|
||||
@BI_LoHi_OnEval,nil,bfHi);
|
||||
if bfConcatArray in TheBaseProcs then
|
||||
AddBuiltInProc('Concat','function Concat(const Array1, Array2, ...): Array',
|
||||
@BI_ConcatArray_OnGetCallCompatibility,@BI_ConcatArray_OnGetCallResult,
|
||||
@ -21095,6 +21193,8 @@ var
|
||||
ElClass: TClass;
|
||||
bt: TResolverBaseType;
|
||||
TypeEl: TPasType;
|
||||
Value: TResEvalValue;
|
||||
Int: TMaxPrecInt;
|
||||
begin
|
||||
if StartEl=nil then StartEl:=El;
|
||||
ResolvedEl:=Default(TPasResolverResult);
|
||||
@ -21114,14 +21214,35 @@ begin
|
||||
ComputeIdentifier(TPrimitiveExpr(El));
|
||||
end;
|
||||
pekNumber:
|
||||
if Pos('.',TPrimitiveExpr(El).Value)>0 then
|
||||
SetResolverValueExpr(ResolvedEl,BaseTypeExtended,
|
||||
FBaseTypes[BaseTypeExtended],FBaseTypes[BaseTypeExtended],
|
||||
TPrimitiveExpr(El),[rrfReadable])
|
||||
else
|
||||
SetResolverValueExpr(ResolvedEl,btLongint,
|
||||
FBaseTypes[btLongint],FBaseTypes[btLongint],
|
||||
TPrimitiveExpr(El),[rrfReadable]);
|
||||
begin
|
||||
if NumberIsFloat(TPrimitiveExpr(El).Value) then
|
||||
bt:=BaseTypeExtended
|
||||
else if length(TPrimitiveExpr(El).Value)<10 then
|
||||
bt:=btLongint
|
||||
else
|
||||
begin
|
||||
Value:=Eval(TPrimitiveExpr(El),[]);
|
||||
if Value=nil then
|
||||
RaiseNotYetImplemented(20190130162601,El);
|
||||
try
|
||||
case Value.Kind of
|
||||
revkInt:
|
||||
begin
|
||||
Int:=TResEvalInt(Value).Int;
|
||||
bt:=GetSmallestIntegerBaseType(Int,Int);
|
||||
end;
|
||||
revkUInt:
|
||||
bt:=btQWord;
|
||||
else
|
||||
bt:=BaseTypeExtended;
|
||||
end;
|
||||
finally
|
||||
ReleaseEvalValue(Value);
|
||||
end;
|
||||
end;
|
||||
SetResolverValueExpr(ResolvedEl,bt,FBaseTypes[bt],FBaseTypes[bt],
|
||||
TPrimitiveExpr(El),[rrfReadable])
|
||||
end;
|
||||
pekString:
|
||||
begin
|
||||
{$IFDEF VerbosePasResolver}
|
||||
@ -22599,6 +22720,43 @@ begin
|
||||
Result:=Module.InterfaceSection;
|
||||
end;
|
||||
|
||||
function TPasResolver.GetShiftAndMaskForLoHiFunc(BaseType: TResolverBaseType;
|
||||
isLoFunc: Boolean; out Mask: LongWord): Integer;
|
||||
const
|
||||
SHIFT_SIZE: array[btByte..{$IFDEF HasInt64}btComp{$ELSE}btIntDouble{$ENDIF}] of Integer = (
|
||||
4, // btByte
|
||||
8, // btShortInt FPC lo/hi(shortint) works like SmallInt
|
||||
8, 8, // btWord, btSmallInt
|
||||
16, 16, 16, 16, // btUIntSingle, btIntSingle, btLongWord, btLongint
|
||||
32, 32 // btUIntDouble, btIntDouble
|
||||
{$IFDEF HasInt64}
|
||||
, 32, 32, 32 // btQWord, btInt64, btComp
|
||||
{$endif}
|
||||
);
|
||||
begin
|
||||
if (BaseType >= Low(SHIFT_SIZE)) and (BaseType <= High(SHIFT_SIZE)) then
|
||||
begin
|
||||
if msDelphi in CurrentParser.CurrentModeswitches then
|
||||
Result := 8
|
||||
else
|
||||
Result := SHIFT_SIZE[BaseType];
|
||||
case Result of
|
||||
8: Mask := $FF;
|
||||
16: Mask := $FFFF;
|
||||
32: Mask := $FFFFFFFF;
|
||||
else
|
||||
{4} Mask := $F;
|
||||
end;
|
||||
if isLoFunc then
|
||||
Result := 0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
RaiseInternalError(20190130122300);
|
||||
Result := -1;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TPasResolver.CheckSrcIsADstType(const ResolvedSrcType,
|
||||
ResolvedDestType: TPasResolverResult): integer;
|
||||
// finds distance between classes SrcType and DestType
|
||||
|
@ -2797,6 +2797,20 @@ begin
|
||||
' r=low(word)+high(int64);',
|
||||
' s=low(longint)+high(integer);',
|
||||
' t=succ(2)+pred(2);',
|
||||
' lo1:byte=lo(word($1234));',
|
||||
' hi1:byte=hi(word($1234));',
|
||||
' lo2:word=lo(longword($1234CDEF));',
|
||||
' hi2:word=hi(longword($1234CDEF));',
|
||||
' lo3:word=lo(LongInt(-$1234CDEF));',
|
||||
' hi3:word=hi(LongInt(-$1234CDEF));',
|
||||
' lo4:byte=lo(byte($34));',
|
||||
' hi4:byte=hi(byte($34));',
|
||||
' lo5:byte=lo(shortint(-$34));',
|
||||
' hi5:byte=hi(shortint(-$34));',
|
||||
' lo6:longword=lo($123456789ABCDEF0);',
|
||||
' hi6:longword=hi($123456789ABCDEF0);',
|
||||
' lo7:longword=lo(-$123456789ABCDEF0);',
|
||||
' hi7:longword=hi(-$123456789ABCDEF0);',
|
||||
'begin']);
|
||||
ParseProgram;
|
||||
CheckResolverUnexpectedHints;
|
||||
@ -4359,6 +4373,10 @@ begin
|
||||
Add(' if i>=j then;');
|
||||
Add(' if i<j then;');
|
||||
Add(' if i<=j then;');
|
||||
Add(' i:=lo($1234);');
|
||||
Add(' i:=lo($1234CDEF);');
|
||||
Add(' i:=hi($1234);');
|
||||
Add(' i:=hi($1234CDEF);');
|
||||
ParseProgram;
|
||||
end;
|
||||
|
||||
|
@ -1836,6 +1836,7 @@ type
|
||||
Function ConvertBuiltInStrParam(El: TPasExpr; AContext: TConvertContext; IsStrFunc, IsFirst: boolean): TJSElement; virtual;
|
||||
Function ConvertBuiltIn_WriteStr(El: TParamsExpr; AContext: TConvertContext): TJSElement; virtual;
|
||||
Function ConvertBuiltIn_Val(El: TParamsExpr; AContext: TConvertContext): TJSElement; virtual;
|
||||
Function ConvertBuiltIn_LoHi(El: TParamsExpr; AContext: TConvertContext; IsLoFunc: Boolean): TJSElement; virtual;
|
||||
Function ConvertBuiltIn_ConcatArray(El: TParamsExpr; AContext: TConvertContext): TJSElement; virtual;
|
||||
Function ConvertBuiltIn_ConcatString(El: TParamsExpr; AContext: TConvertContext): TJSElement; virtual;
|
||||
Function ConvertBuiltIn_CopyArray(El: TParamsExpr; AContext: TConvertContext): TJSElement; virtual;
|
||||
@ -9020,6 +9021,8 @@ begin
|
||||
bfStrFunc: Result:=ConvertBuiltIn_StrFunc(El,AContext);
|
||||
bfWriteStr: Result:=ConvertBuiltIn_WriteStr(El,AContext);
|
||||
bfVal: Result:=ConvertBuiltIn_Val(El,AContext);
|
||||
bfLo: Result := ConvertBuiltIn_LoHi(El,AContext,True);
|
||||
bfHi: Result := ConvertBuiltIn_LoHi(El,AContext,False);
|
||||
bfConcatArray: Result:=ConvertBuiltIn_ConcatArray(El,AContext);
|
||||
bfConcatString: Result:=ConvertBuiltIn_ConcatString(El,AContext);
|
||||
bfCopyArray: Result:=ConvertBuiltIn_CopyArray(El,AContext);
|
||||
@ -11099,6 +11102,66 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TPasToJSConverter.ConvertBuiltIn_LoHi(El: TParamsExpr;
|
||||
AContext: TConvertContext; IsLoFunc: Boolean): TJSElement;
|
||||
var
|
||||
ResolvedParam: TPasResolverResult;
|
||||
Param: TPasExpr;
|
||||
Mask: LongWord;
|
||||
Shift, Digits: Integer;
|
||||
ShiftEx: TJSShiftExpression;
|
||||
AndEx: TJSBitwiseAndExpression;
|
||||
begin
|
||||
Result := nil;
|
||||
if AContext.Resolver=nil then
|
||||
RaiseInconsistency(20190129102200,El);
|
||||
Param := El.Params[0];
|
||||
AContext.Resolver.ComputeElement(Param,ResolvedParam,[]);
|
||||
if not (ResolvedParam.BaseType in btAllInteger) then
|
||||
DoError(20190129121100,nXExpectedButYFound,sXExpectedButYFound,['integer type',
|
||||
AContext.Resolver.GetResolverResultDescription(ResolvedParam)],Param);
|
||||
Shift := AContext.Resolver.GetShiftAndMaskForLoHiFunc(ResolvedParam.BaseType,IsLoFunc,Mask);
|
||||
Result := ConvertExpression(Param,AContext);
|
||||
// Note: convert Param first, as it might raise an exception
|
||||
if Shift > 0 then
|
||||
begin
|
||||
if Shift=32 then
|
||||
begin
|
||||
// JS bitwise operations work only 32bit -> use division for bigger shifts
|
||||
Result:=CreateMathFloor(El,CreateDivideNumber(El,Result,$100000000));
|
||||
end
|
||||
else
|
||||
begin
|
||||
ShiftEx := TJSRShiftExpression(CreateElement(TJSRShiftExpression,El));
|
||||
ShiftEx.A := Result;
|
||||
ShiftEx.B := CreateLiteralNumber(El, Shift);
|
||||
Result := ShiftEx;
|
||||
end;
|
||||
end;
|
||||
case Mask of
|
||||
$FF: Digits := 2;
|
||||
$FFFF: Digits := 4;
|
||||
$FFFFFFFF: Digits := 8;
|
||||
else { $F } Digits := 1;
|
||||
end;
|
||||
if Digits<8 then
|
||||
begin
|
||||
// & Mask
|
||||
AndEx := TJSBitwiseAndExpression(CreateElement(TJSBitwiseAndExpression,El));
|
||||
AndEx.A := Result;
|
||||
AndEx.B := CreateLiteralHexNumber(El,Mask,Digits);
|
||||
Result := AndEx;
|
||||
end
|
||||
else
|
||||
begin
|
||||
// mask to longword -> >>> 0
|
||||
ShiftEx:=TJSURShiftExpression(CreateElement(TJSURShiftExpression,El));
|
||||
ShiftEx.A:=Result;
|
||||
ShiftEx.B:=CreateLiteralNumber(El,0);
|
||||
Result:=ShiftEx;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TPasToJSConverter.ConvertBuiltIn_ConcatArray(El: TParamsExpr;
|
||||
AContext: TConvertContext): TJSElement;
|
||||
// concat(array1, array2)
|
||||
|
@ -370,6 +370,8 @@ type
|
||||
// statements
|
||||
Procedure TestNestBegin;
|
||||
Procedure TestIncDec;
|
||||
Procedure TestLoHiFpcMode;
|
||||
Procedure TestLoHiDelphiMode;
|
||||
Procedure TestAssignments;
|
||||
Procedure TestArithmeticOperators1;
|
||||
Procedure TestLogicalOperators;
|
||||
@ -2683,6 +2685,154 @@ begin
|
||||
]));
|
||||
end;
|
||||
|
||||
procedure TTestModule.TestLoHiFpcMode;
|
||||
begin
|
||||
StartProgram(false);
|
||||
Add([
|
||||
'{$mode objfpc}',
|
||||
'const',
|
||||
' LoByte1 = Lo(Word($1234));',
|
||||
' HiByte1 = Hi(Word($1234));',
|
||||
' LoByte2 = Lo(SmallInt($1234));',
|
||||
' HiByte2 = Hi(SmallInt($1234));',
|
||||
' LoWord1 = Lo($1234CDEF);',
|
||||
' HiWord1 = Hi($1234CDEF);',
|
||||
' LoWord2 = Lo(-$1234CDEF);',
|
||||
' HiWord2 = Hi(-$1234CDEF);',
|
||||
' lo4:byte=lo(byte($34));',
|
||||
' hi4:byte=hi(byte($34));',
|
||||
' lo5:byte=lo(shortint(-$34));',
|
||||
' hi5:byte=hi(shortint(-$34));',
|
||||
' lo6:longword=lo($123456789ABCDE);',
|
||||
' hi6:longword=hi($123456789ABCDE);',
|
||||
' lo7:longword=lo(-$123456789ABCDE);',
|
||||
' hi7:longword=hi(-$123456789ABCDE);',
|
||||
'var',
|
||||
' b: Byte;',
|
||||
' ss: shortint;',
|
||||
' w: Word;',
|
||||
' si: SmallInt;',
|
||||
' lw: LongWord;',
|
||||
' li: LongInt;',
|
||||
' b2: Byte;',
|
||||
' ni: nativeint;',
|
||||
'begin',
|
||||
' w := $1234;',
|
||||
' ss := -$12;',
|
||||
' b := lo(ss);',
|
||||
' b := HI(ss);',
|
||||
' b := lo(w);',
|
||||
' b := HI(w);',
|
||||
' b2 := lo(b);',
|
||||
' b2 := hi(b);',
|
||||
' lw := $1234CDEF;',
|
||||
' w := lo(lw);',
|
||||
' w := hi(lw);',
|
||||
' ni := $123456789ABCDE;',
|
||||
' lw := lo(ni);',
|
||||
' lw := hi(ni);',
|
||||
'']);
|
||||
ConvertProgram;
|
||||
CheckSource('TestLoHiFpcMode',
|
||||
LinesToStr([ // statements
|
||||
'this.LoByte1 = 0x1234 & 0xFF;',
|
||||
'this.HiByte1 = (0x1234 >> 8) & 0xFF;',
|
||||
'this.LoByte2 = 0x1234 & 0xFF;',
|
||||
'this.HiByte2 = (0x1234 >> 8) & 0xFF;',
|
||||
'this.LoWord1 = 0x1234CDEF & 0xFFFF;',
|
||||
'this.HiWord1 = (0x1234CDEF >> 16) & 0xFFFF;',
|
||||
'this.LoWord2 = -0x1234CDEF & 0xFFFF;',
|
||||
'this.HiWord2 = (-0x1234CDEF >> 16) & 0xFFFF;',
|
||||
'this.lo4 = 0x34 & 0xF;',
|
||||
'this.hi4 = (0x34 >> 4) & 0xF;',
|
||||
'this.lo5 = (((-0x34 & 255) << 24) >> 24) & 0xFF;',
|
||||
'this.hi5 = ((((-0x34 & 255) << 24) >> 24) >> 8) & 0xFF;',
|
||||
'this.lo6 = 0x123456789ABCDE >>> 0;',
|
||||
'this.hi6 = 1193046 >>> 0;',
|
||||
'this.lo7 = -0x123456789ABCDE >>> 0;',
|
||||
'this.hi7 = Math.floor(-0x123456789ABCDE / 4294967296) >>> 0;',
|
||||
'this.b = 0;',
|
||||
'this.ss = 0;',
|
||||
'this.w = 0;',
|
||||
'this.si = 0;',
|
||||
'this.lw = 0;',
|
||||
'this.li = 0;',
|
||||
'this.b2 = 0;',
|
||||
'this.ni = 0;',
|
||||
'']),
|
||||
LinesToStr([ // this.$main
|
||||
'$mod.w = 0x1234;',
|
||||
'$mod.ss = -0x12;',
|
||||
'$mod.b = $mod.ss & 0xFF;',
|
||||
'$mod.b = ($mod.ss >> 8) & 0xFF;',
|
||||
'$mod.b = $mod.w & 0xFF;',
|
||||
'$mod.b = ($mod.w >> 8) & 0xFF;',
|
||||
'$mod.b2 = $mod.b & 0xF;',
|
||||
'$mod.b2 = ($mod.b >> 4) & 0xF;',
|
||||
'$mod.lw = 0x1234CDEF;',
|
||||
'$mod.w = $mod.lw & 0xFFFF;',
|
||||
'$mod.w = ($mod.lw >> 16) & 0xFFFF;',
|
||||
'$mod.ni = 0x123456789ABCDE;',
|
||||
'$mod.lw = $mod.ni >>> 0;',
|
||||
'$mod.lw = Math.floor($mod.ni / 4294967296) >>> 0;',
|
||||
'']));
|
||||
end;
|
||||
|
||||
procedure TTestModule.TestLoHiDelphiMode;
|
||||
begin
|
||||
StartProgram(false);
|
||||
Add([
|
||||
'{$mode delphi}',
|
||||
'const',
|
||||
' LoByte1 = Lo(Word($1234));',
|
||||
' HiByte1 = Hi(Word($1234));',
|
||||
' LoByte2 = Lo(SmallInt($1234));',
|
||||
' HiByte2 = Hi(SmallInt($1234));',
|
||||
' LoByte3 = Lo($1234CDEF);',
|
||||
' HiByte3 = Hi($1234CDEF);',
|
||||
' LoByte4 = Lo(-$1234CDEF);',
|
||||
' HiByte4 = Hi(-$1234CDEF);',
|
||||
'var',
|
||||
' b: Byte;',
|
||||
' w: Word;',
|
||||
' si: SmallInt;',
|
||||
' lw: LongWord;',
|
||||
' li: LongInt;',
|
||||
'begin',
|
||||
' w := $1234;',
|
||||
' b := lo(w);',
|
||||
' b := HI(w);',
|
||||
' lw := $1234CDEF;',
|
||||
' b := lo(lw);',
|
||||
' b := hi(lw);',
|
||||
'']);
|
||||
ConvertProgram;
|
||||
CheckSource('TestLoHiDelphiMode',
|
||||
LinesToStr([ // statements
|
||||
'this.LoByte1 = 0x1234 & 0xFF;',
|
||||
'this.HiByte1 = (0x1234 >> 8) & 0xFF;',
|
||||
'this.LoByte2 = 0x1234 & 0xFF;',
|
||||
'this.HiByte2 = (0x1234 >> 8) & 0xFF;',
|
||||
'this.LoByte3 = 0x1234CDEF & 0xFF;',
|
||||
'this.HiByte3 = (0x1234CDEF >> 8) & 0xFF;',
|
||||
'this.LoByte4 = -0x1234CDEF & 0xFF;',
|
||||
'this.HiByte4 = (-0x1234CDEF >> 8) & 0xFF;',
|
||||
'this.b = 0;',
|
||||
'this.w = 0;',
|
||||
'this.si = 0;',
|
||||
'this.lw = 0;',
|
||||
'this.li = 0;'
|
||||
]),
|
||||
LinesToStr([ // this.$main
|
||||
'$mod.w = 0x1234;',
|
||||
'$mod.b = $mod.w & 0xFF;',
|
||||
'$mod.b = ($mod.w >> 8) & 0xFF;',
|
||||
'$mod.lw = 0x1234CDEF;',
|
||||
'$mod.b = $mod.lw & 0xFF;',
|
||||
'$mod.b = ($mod.lw >> 8) & 0xFF;'
|
||||
]));
|
||||
end;
|
||||
|
||||
procedure TTestModule.TestAssignments;
|
||||
begin
|
||||
StartProgram(false);
|
||||
|
@ -26,8 +26,6 @@ begin
|
||||
P.Directory:=ADirectory;
|
||||
P.Version:='3.3.1';
|
||||
P.OSes:=AllUnixOSes+AllBSDOSes+AllWindowsOSes-[WinCE];
|
||||
if Defaults.CPU=jvm then
|
||||
P.OSes := P.OSes - [android];
|
||||
P.Dependencies.Add('fcl-json');
|
||||
P.Dependencies.Add('fcl-js');
|
||||
P.Dependencies.Add('fcl-passrc');
|
||||
|
Loading…
Reference in New Issue
Block a user