refactor: use Exit(X) shorthand for Result-then-Exit early returns
Now that Exit(X) is supported (0f63626), replace the historical
'Result := X; Exit;' workaround with the Exit(X) function-result shorthand
across compiler, runtime, and stdlib (305 sites).
Only same-indentation pairs are merged: a 'Result := X;' immediately followed
by an 'Exit;' at the same indentation level. Sites where the trailing 'Exit;'
is less-indented than the assignment are left untouched — there the Exit
belongs to an enclosing for/else/if block, not to the assignment, so merging
would change control flow (e.g. the xor/and numeric-result branch in
uSemantic falling through to the Boolean-operand check). 14 such sites are
deliberately not converted.
Three converted sites sit inside a real try/finally (uSemantic overload/
generic resolution); each try body already contained bare Exit; statements
and its finally body is a plain local-list Free, so control flow is unchanged.
A new e2e test (TestRun_ExitValueThroughFinally) confirms Exit(X) from inside
a try/finally runs the finally body and returns the value.
Self-hosting fixpoint verified clean (stage-2 IR == stage-3 IR).
This commit is contained in:
parent
0f63626397
commit
99b7761bf4
|
|
@ -175,8 +175,7 @@ begin
|
||||||
Arg := ParamStr(I);
|
Arg := ParamStr(I);
|
||||||
if (Length(Arg) >= 2) and (StrAt(Arg, 0) = Ord('-')) and (StrAt(Arg, 1) <> Ord('-')) then
|
if (Length(Arg) >= 2) and (StrAt(Arg, 0) = Ord('-')) and (StrAt(Arg, 1) <> Ord('-')) then
|
||||||
begin
|
begin
|
||||||
Result := True;
|
Exit(True);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
|
||||||
|
|
@ -145,8 +145,7 @@ function IntByteSize(AType: TTypeDesc): Integer;
|
||||||
begin
|
begin
|
||||||
if AType = nil then
|
if AType = nil then
|
||||||
begin
|
begin
|
||||||
Result := 4;
|
Exit(4);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
case AType.Kind of
|
case AType.Kind of
|
||||||
tyByte, tyBoolean: Result := 1;
|
tyByte, tyBoolean: Result := 1;
|
||||||
|
|
@ -165,8 +164,7 @@ function IsUnsignedInt(AType: TTypeDesc): Boolean;
|
||||||
begin
|
begin
|
||||||
if AType = nil then
|
if AType = nil then
|
||||||
begin
|
begin
|
||||||
Result := False;
|
Exit(False);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
Result := AType.Kind in [tyByte, tyBoolean, tyWord, tyUInt32, tyUInt64, tyEnum];
|
Result := AType.Kind in [tyByte, tyBoolean, tyWord, tyUInt32, tyUInt64, tyEnum];
|
||||||
end;
|
end;
|
||||||
|
|
@ -404,8 +402,7 @@ begin
|
||||||
T := Self.GlobalType(TIdentExpr(AExpr).Name);
|
T := Self.GlobalType(TIdentExpr(AExpr).Name);
|
||||||
if T <> nil then
|
if T <> nil then
|
||||||
begin
|
begin
|
||||||
Result := T;
|
Exit(T);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
Result := AExpr.ResolvedType;
|
Result := AExpr.ResolvedType;
|
||||||
|
|
|
||||||
|
|
@ -143,8 +143,7 @@ begin
|
||||||
for I := 0 to (AIndex - Seen) - 1 do
|
for I := 0 to (AIndex - Seen) - 1 do
|
||||||
Entry := Pointer(Entry) + 16; { skip name + addr pair }
|
Entry := Pointer(Entry) + 16; { skip name + addr pair }
|
||||||
EntName := Entry^;
|
EntName := Entry^;
|
||||||
Result := string(PChar(EntName));
|
Exit(string(PChar(EntName)));
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
Seen := Seen + Local;
|
Seen := Seen + Local;
|
||||||
end;
|
end;
|
||||||
|
|
@ -238,8 +237,7 @@ var
|
||||||
begin
|
begin
|
||||||
if (AFilters = nil) or (AFilters.Count = 0) then
|
if (AFilters = nil) or (AFilters.Count = 0) then
|
||||||
begin
|
begin
|
||||||
Result := True;
|
Exit(True);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
for I := 0 to AFilters.Count - 1 do
|
for I := 0 to AFilters.Count - 1 do
|
||||||
begin
|
begin
|
||||||
|
|
@ -248,8 +246,7 @@ begin
|
||||||
Continue;
|
Continue;
|
||||||
if (FMethod = '') or (FMethod = AMethod) then
|
if (FMethod = '') or (FMethod = AMethod) then
|
||||||
begin
|
begin
|
||||||
Result := True;
|
Exit(True);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
Result := False;
|
Result := False;
|
||||||
|
|
@ -267,16 +264,14 @@ var
|
||||||
begin
|
begin
|
||||||
if (AFilters = nil) or (AFilters.Count = 0) then
|
if (AFilters = nil) or (AFilters.Count = 0) then
|
||||||
begin
|
begin
|
||||||
Result := True;
|
Exit(True);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
for I := 0 to AFilters.Count - 1 do
|
for I := 0 to AFilters.Count - 1 do
|
||||||
begin
|
begin
|
||||||
SplitSuiteSpec(AFilters.Strings[I], FSuite, FMethod);
|
SplitSuiteSpec(AFilters.Strings[I], FSuite, FMethod);
|
||||||
if FSuite = ASuite then
|
if FSuite = ASuite then
|
||||||
begin
|
begin
|
||||||
Result := True;
|
Exit(True);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
Result := False;
|
Result := False;
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -223,8 +223,7 @@ var
|
||||||
begin
|
begin
|
||||||
if AType = nil then
|
if AType = nil then
|
||||||
begin
|
begin
|
||||||
Result := 'Pointer';
|
Exit('Pointer');
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
case AType.Kind of
|
case AType.Kind of
|
||||||
tyString:
|
tyString:
|
||||||
|
|
|
||||||
|
|
@ -194,8 +194,7 @@ begin
|
||||||
begin
|
begin
|
||||||
Advance; { consume 'class' }
|
Advance; { consume 'class' }
|
||||||
Expect(tkOf);
|
Expect(tkOf);
|
||||||
Result := 'class of ' + Self.ParseTypeName;
|
Exit('class of ' + Self.ParseTypeName);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
if not Check(tkIdent) then
|
if not Check(tkIdent) then
|
||||||
raise EParseError.Create(Format('Expected type name at line %d col %d in %s',
|
raise EParseError.Create(Format('Expected type name at line %d col %d in %s',
|
||||||
|
|
@ -1860,38 +1859,32 @@ begin
|
||||||
|
|
||||||
if Check(tkIf) then
|
if Check(tkIf) then
|
||||||
begin
|
begin
|
||||||
Result := ParseIfStmt;
|
Exit(ParseIfStmt);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if Check(tkWhile) then
|
if Check(tkWhile) then
|
||||||
begin
|
begin
|
||||||
Result := ParseWhileStmt;
|
Exit(ParseWhileStmt);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if Check(tkRepeat) then
|
if Check(tkRepeat) then
|
||||||
begin
|
begin
|
||||||
Result := ParseRepeatStmt;
|
Exit(ParseRepeatStmt);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if Check(tkFor) then
|
if Check(tkFor) then
|
||||||
begin
|
begin
|
||||||
Result := ParseForStmt;
|
Exit(ParseForStmt);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if Check(tkTry) then
|
if Check(tkTry) then
|
||||||
begin
|
begin
|
||||||
Result := ParseTryStmt;
|
Exit(ParseTryStmt);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if Check(tkRaise) then
|
if Check(tkRaise) then
|
||||||
begin
|
begin
|
||||||
Result := ParseRaiseStmt;
|
Exit(ParseRaiseStmt);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if Check(tkExit) then
|
if Check(tkExit) then
|
||||||
|
|
@ -1909,8 +1902,7 @@ begin
|
||||||
ExitS.Value := Self.ParseExpr;
|
ExitS.Value := Self.ParseExpr;
|
||||||
Expect(tkRParen);
|
Expect(tkRParen);
|
||||||
end;
|
end;
|
||||||
Result := ExitS;
|
Exit(ExitS);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if Check(tkBreak) then
|
if Check(tkBreak) then
|
||||||
|
|
@ -1933,20 +1925,17 @@ begin
|
||||||
|
|
||||||
if Check(tkInherited) then
|
if Check(tkInherited) then
|
||||||
begin
|
begin
|
||||||
Result := ParseInheritedStmt;
|
Exit(ParseInheritedStmt);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if Check(tkCase) then
|
if Check(tkCase) then
|
||||||
begin
|
begin
|
||||||
Result := ParseCaseStmt;
|
Exit(ParseCaseStmt);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if Check(tkBegin) then
|
if Check(tkBegin) then
|
||||||
begin
|
begin
|
||||||
Result := ParseCompoundStmt;
|
Exit(ParseCompoundStmt);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if not Check(tkIdent) then
|
if not Check(tkIdent) then
|
||||||
|
|
@ -1976,8 +1965,7 @@ begin
|
||||||
SubAssign.Free;
|
SubAssign.Free;
|
||||||
raise;
|
raise;
|
||||||
end;
|
end;
|
||||||
Result := SubAssign;
|
Exit(SubAssign);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if Check(tkCaret) then
|
if Check(tkCaret) then
|
||||||
|
|
@ -2148,8 +2136,7 @@ begin
|
||||||
MCall.Free;
|
MCall.Free;
|
||||||
MCall := nil;
|
MCall := nil;
|
||||||
FldAssign.Expr := ParseExpr;
|
FldAssign.Expr := ParseExpr;
|
||||||
Result := FldAssign;
|
Exit(FldAssign);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
Result := MCall;
|
Result := MCall;
|
||||||
end
|
end
|
||||||
|
|
@ -2201,8 +2188,7 @@ begin
|
||||||
if not Check(tkRParen) then
|
if not Check(tkRParen) then
|
||||||
ParseMethodCallArgList(MCall);
|
ParseMethodCallArgList(MCall);
|
||||||
Expect(tkRParen);
|
Expect(tkRParen);
|
||||||
Result := MCall;
|
Exit(MCall);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
FldNode := TFieldAccessExpr.Create;
|
FldNode := TFieldAccessExpr.Create;
|
||||||
FldNode.Line := Line;
|
FldNode.Line := Line;
|
||||||
|
|
@ -2222,8 +2208,7 @@ begin
|
||||||
TFieldAccessExpr(CastRcv).Base := nil;
|
TFieldAccessExpr(CastRcv).Base := nil;
|
||||||
CastRcv.Free;
|
CastRcv.Free;
|
||||||
FldAssign.Expr := ParseExpr;
|
FldAssign.Expr := ParseExpr;
|
||||||
Result := FldAssign;
|
Exit(FldAssign);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
raise EParseError.Create(Format(
|
raise EParseError.Create(Format(
|
||||||
'Expected method call or assignment after chain at line %d col %d in %s',
|
'Expected method call or assignment after chain at line %d col %d in %s',
|
||||||
|
|
@ -2291,8 +2276,7 @@ begin
|
||||||
if not Check(tkRParen) then
|
if not Check(tkRParen) then
|
||||||
ParseMethodCallArgList(MCall);
|
ParseMethodCallArgList(MCall);
|
||||||
Expect(tkRParen);
|
Expect(tkRParen);
|
||||||
Result := MCall;
|
Exit(MCall);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
FldNode := TFieldAccessExpr.Create;
|
FldNode := TFieldAccessExpr.Create;
|
||||||
FldNode.Line := Line;
|
FldNode.Line := Line;
|
||||||
|
|
@ -2313,8 +2297,7 @@ begin
|
||||||
TFieldAccessExpr(CastRcv).Base := nil; { transfer ownership }
|
TFieldAccessExpr(CastRcv).Base := nil; { transfer ownership }
|
||||||
CastRcv.Free;
|
CastRcv.Free;
|
||||||
FldAssign.Expr := ParseExpr;
|
FldAssign.Expr := ParseExpr;
|
||||||
Result := FldAssign;
|
Exit(FldAssign);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
{ No-arg method call: Func(...).Field treated as Func(...).Method }
|
{ No-arg method call: Func(...).Field treated as Func(...).Method }
|
||||||
if CastRcv is TFieldAccessExpr then
|
if CastRcv is TFieldAccessExpr then
|
||||||
|
|
@ -2327,8 +2310,7 @@ begin
|
||||||
MCall.ObjExpr := TFieldAccessExpr(CastRcv).Base;
|
MCall.ObjExpr := TFieldAccessExpr(CastRcv).Base;
|
||||||
TFieldAccessExpr(CastRcv).Base := nil;
|
TFieldAccessExpr(CastRcv).Base := nil;
|
||||||
CastRcv.Free;
|
CastRcv.Free;
|
||||||
Result := MCall;
|
Exit(MCall);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
raise EParseError.Create(Format(
|
raise EParseError.Create(Format(
|
||||||
'Expected method call after typecast at line %d col %d in %s',
|
'Expected method call after typecast at line %d col %d in %s',
|
||||||
|
|
@ -2343,8 +2325,7 @@ begin
|
||||||
while FCallNode.Args.Count > 0 do
|
while FCallNode.Args.Count > 0 do
|
||||||
Call.Args.Add(FCallNode.Args.Extract(FCallNode.Args.Items[0]));
|
Call.Args.Add(FCallNode.Args.Extract(FCallNode.Args.Items[0]));
|
||||||
FCallNode.Free;
|
FCallNode.Free;
|
||||||
Result := Call;
|
Exit(Call);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
Call := TProcCall.Create;
|
Call := TProcCall.Create;
|
||||||
Call.Line := Line;
|
Call.Line := Line;
|
||||||
|
|
|
||||||
|
|
@ -248,8 +248,7 @@ var
|
||||||
begin
|
begin
|
||||||
if SameText(AAttrName, ACanonical) then
|
if SameText(AAttrName, ACanonical) then
|
||||||
begin
|
begin
|
||||||
Result := True;
|
Exit(True);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
Suffix := ACanonical + 'Attribute';
|
Suffix := ACanonical + 'Attribute';
|
||||||
Result := SameText(AAttrName, Suffix);
|
Result := SameText(AAttrName, Suffix);
|
||||||
|
|
@ -261,14 +260,12 @@ var
|
||||||
begin
|
begin
|
||||||
if AAttrs = nil then
|
if AAttrs = nil then
|
||||||
begin
|
begin
|
||||||
Result := False;
|
Exit(False);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
for I := 0 to AAttrs.Count - 1 do
|
for I := 0 to AAttrs.Count - 1 do
|
||||||
if AttrMatches(AAttrs.Strings[I], 'Weak') then
|
if AttrMatches(AAttrs.Strings[I], 'Weak') then
|
||||||
begin
|
begin
|
||||||
Result := True;
|
Exit(True);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
Result := False;
|
Result := False;
|
||||||
end;
|
end;
|
||||||
|
|
@ -279,14 +276,12 @@ var
|
||||||
begin
|
begin
|
||||||
if AAttrs = nil then
|
if AAttrs = nil then
|
||||||
begin
|
begin
|
||||||
Result := False;
|
Exit(False);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
for I := 0 to AAttrs.Count - 1 do
|
for I := 0 to AAttrs.Count - 1 do
|
||||||
if AttrMatches(AAttrs.Strings[I], 'Unretained') then
|
if AttrMatches(AAttrs.Strings[I], 'Unretained') then
|
||||||
begin
|
begin
|
||||||
Result := True;
|
Exit(True);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
Result := False;
|
Result := False;
|
||||||
end;
|
end;
|
||||||
|
|
@ -307,8 +302,7 @@ begin
|
||||||
begin
|
begin
|
||||||
if SameText(Walk.Name, 'TCustomAttribute') then
|
if SameText(Walk.Name, 'TCustomAttribute') then
|
||||||
begin
|
begin
|
||||||
Result := True;
|
Exit(True);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
Walk := Walk.Parent;
|
Walk := Walk.Parent;
|
||||||
end;
|
end;
|
||||||
|
|
@ -325,8 +319,7 @@ begin
|
||||||
if (Sym <> nil) and (Sym.TypeDesc is TRecordTypeDesc) and
|
if (Sym <> nil) and (Sym.TypeDesc is TRecordTypeDesc) and
|
||||||
IsCustomAttributeClass(ARawName) then
|
IsCustomAttributeClass(ARawName) then
|
||||||
begin
|
begin
|
||||||
Result := ARawName;
|
Exit(ARawName);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
Sym := FTable.Lookup(ARawName + 'Attribute');
|
Sym := FTable.Lookup(ARawName + 'Attribute');
|
||||||
if (Sym <> nil) and (Sym.TypeDesc is TRecordTypeDesc) and
|
if (Sym <> nil) and (Sym.TypeDesc is TRecordTypeDesc) and
|
||||||
|
|
@ -424,8 +417,7 @@ begin
|
||||||
begin
|
begin
|
||||||
if Walk = AExpected then
|
if Walk = AExpected then
|
||||||
begin
|
begin
|
||||||
Result := True;
|
Exit(True);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
Walk := Walk.Parent;
|
Walk := Walk.Parent;
|
||||||
end;
|
end;
|
||||||
|
|
@ -1414,14 +1406,12 @@ begin
|
||||||
for I := 0 to AParamNames.Count - 1 do
|
for I := 0 to AParamNames.Count - 1 do
|
||||||
if SameText(Result, AParamNames.Strings[I]) then
|
if SameText(Result, AParamNames.Strings[I]) then
|
||||||
begin
|
begin
|
||||||
Result := AArgs.Strings[I];
|
Exit(AArgs.Strings[I]);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
{ Prefix caret: ^T → ^Integer, ^^T → ^^Integer, etc. }
|
{ Prefix caret: ^T → ^Integer, ^^T → ^^Integer, etc. }
|
||||||
if (Length(Result) > 0) and (StrAt(Result, 0) = Ord('^')) then
|
if (Length(Result) > 0) and (StrAt(Result, 0) = Ord('^')) then
|
||||||
begin
|
begin
|
||||||
Result := '^' + Self.SubstTypeParam(StrCopyTail(Result, 1), AParamNames, AArgs);
|
Exit('^' + Self.SubstTypeParam(StrCopyTail(Result, 1), AParamNames, AArgs));
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
{ Generic instantiation: SomeName<T,...> — substitute each type argument }
|
{ Generic instantiation: SomeName<T,...> — substitute each type argument }
|
||||||
BrOpen := StrPos('<', Result);
|
BrOpen := StrPos('<', Result);
|
||||||
|
|
@ -1856,8 +1846,7 @@ begin
|
||||||
Sym := FTable.Lookup(ATypeName);
|
Sym := FTable.Lookup(ATypeName);
|
||||||
if (Sym <> nil) and (Sym.TypeDesc is TInterfaceTypeDesc) then
|
if (Sym <> nil) and (Sym.TypeDesc is TInterfaceTypeDesc) then
|
||||||
begin
|
begin
|
||||||
Result := TInterfaceTypeDesc(Sym.TypeDesc);
|
Exit(TInterfaceTypeDesc(Sym.TypeDesc));
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Build mangled name: IEqualityComparer<Integer> → IEqualityComparer_Integer }
|
{ Build mangled name: IEqualityComparer<Integer> → IEqualityComparer_Integer }
|
||||||
|
|
@ -3255,8 +3244,7 @@ begin
|
||||||
Idx := FMethodIndex.IndexOf(Key);
|
Idx := FMethodIndex.IndexOf(Key);
|
||||||
if Idx >= 0 then
|
if Idx >= 0 then
|
||||||
begin
|
begin
|
||||||
Result := TMethodDecl(FMethodIndex.Objects[Idx]);
|
Exit(TMethodDecl(FMethodIndex.Objects[Idx]));
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
{ Walk to parent }
|
{ Walk to parent }
|
||||||
Sym := FTable.Lookup(CurrName);
|
Sym := FTable.Lookup(CurrName);
|
||||||
|
|
@ -3344,8 +3332,7 @@ begin
|
||||||
begin
|
begin
|
||||||
if ArityMatch.Count = 1 then
|
if ArityMatch.Count = 1 then
|
||||||
begin
|
begin
|
||||||
Result := TMethodDecl(ArityMatch.Items[0]);
|
Exit(TMethodDecl(ArityMatch.Items[0]));
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
Exit; { ambiguous-by-arity-only — caller must score with args }
|
Exit; { ambiguous-by-arity-only — caller must score with args }
|
||||||
end;
|
end;
|
||||||
|
|
@ -3758,8 +3745,7 @@ begin
|
||||||
for I := 0 to ADecl.Params.Count - 1 do
|
for I := 0 to ADecl.Params.Count - 1 do
|
||||||
if SameText(TMethodParam(ADecl.Params.Items[I]).ParamName, AName) then
|
if SameText(TMethodParam(ADecl.Params.Items[I]).ParamName, AName) then
|
||||||
begin
|
begin
|
||||||
Result := True;
|
Exit(True);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
@ -3792,8 +3778,7 @@ begin
|
||||||
end;
|
end;
|
||||||
if AExpr is TNotExpr then
|
if AExpr is TNotExpr then
|
||||||
begin
|
begin
|
||||||
Result := ExprRejectsInline(TNotExpr(AExpr).Expr, ASelfDecl);
|
Exit(ExprRejectsInline(TNotExpr(AExpr).Expr, ASelfDecl));
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
@ -3834,15 +3819,13 @@ begin
|
||||||
for I := 0 to Cmp.Stmts.Count - 1 do
|
for I := 0 to Cmp.Stmts.Count - 1 do
|
||||||
if StmtRejectsInline(TASTStmt(Cmp.Stmts.Items[I]), ASelfDecl, AStmtCount) then
|
if StmtRejectsInline(TASTStmt(Cmp.Stmts.Items[I]), ASelfDecl, AStmtCount) then
|
||||||
Exit;
|
Exit;
|
||||||
Result := False;
|
Exit(False);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if AStmt is TExitStmt then
|
if AStmt is TExitStmt then
|
||||||
begin
|
begin
|
||||||
Inc(AStmtCount);
|
Inc(AStmtCount);
|
||||||
Result := False;
|
Exit(False);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if AStmt is TIfStmt then
|
if AStmt is TIfStmt then
|
||||||
|
|
@ -3853,8 +3836,7 @@ begin
|
||||||
if StmtRejectsInline(Ifs.ThenStmt, ASelfDecl, AStmtCount) then Exit;
|
if StmtRejectsInline(Ifs.ThenStmt, ASelfDecl, AStmtCount) then Exit;
|
||||||
if (Ifs.ElseStmt <> nil) and
|
if (Ifs.ElseStmt <> nil) and
|
||||||
StmtRejectsInline(Ifs.ElseStmt, ASelfDecl, AStmtCount) then Exit;
|
StmtRejectsInline(Ifs.ElseStmt, ASelfDecl, AStmtCount) then Exit;
|
||||||
Result := False;
|
Exit(False);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if AStmt is TAssignment then
|
if AStmt is TAssignment then
|
||||||
|
|
@ -3865,8 +3847,7 @@ begin
|
||||||
{ Assignment to a parameter requires updating the caller-side temp,
|
{ Assignment to a parameter requires updating the caller-side temp,
|
||||||
which the simple inliner does not support. Reject. }
|
which the simple inliner does not support. Reject. }
|
||||||
if AssignmentTargetsParameter(Asg.Name, ASelfDecl) then Exit;
|
if AssignmentTargetsParameter(Asg.Name, ASelfDecl) then Exit;
|
||||||
Result := False;
|
Exit(False);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if AStmt is TProcCall then
|
if AStmt is TProcCall then
|
||||||
|
|
@ -3879,8 +3860,7 @@ begin
|
||||||
for I := 0 to TProcCall(AStmt).Args.Count - 1 do
|
for I := 0 to TProcCall(AStmt).Args.Count - 1 do
|
||||||
if ExprRejectsInline(TASTExpr(TProcCall(AStmt).Args.Items[I]), ASelfDecl) then
|
if ExprRejectsInline(TASTExpr(TProcCall(AStmt).Args.Items[I]), ASelfDecl) then
|
||||||
Exit;
|
Exit;
|
||||||
Result := False;
|
Exit(False);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if AStmt is TCaseStmt then
|
if AStmt is TCaseStmt then
|
||||||
|
|
@ -3897,8 +3877,7 @@ begin
|
||||||
end;
|
end;
|
||||||
if (Cs.ElseStmt <> nil) and
|
if (Cs.ElseStmt <> nil) and
|
||||||
StmtRejectsInline(Cs.ElseStmt, ASelfDecl, AStmtCount) then Exit;
|
StmtRejectsInline(Cs.ElseStmt, ASelfDecl, AStmtCount) then Exit;
|
||||||
Result := False;
|
Exit(False);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Unknown statement form: reject conservatively. }
|
{ Unknown statement form: reject conservatively. }
|
||||||
|
|
@ -5037,8 +5016,7 @@ var
|
||||||
begin
|
begin
|
||||||
if AType = nil then
|
if AType = nil then
|
||||||
begin
|
begin
|
||||||
Result := '?';
|
Exit('?');
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
case AType.Kind of
|
case AType.Kind of
|
||||||
tyInteger: Base := 'i';
|
tyInteger: Base := 'i';
|
||||||
|
|
@ -5098,8 +5076,7 @@ begin
|
||||||
for I := 0 to ADecl.Params.Count - 1 do
|
for I := 0 to ADecl.Params.Count - 1 do
|
||||||
if TMethodParam(ADecl.Params.Items[I]).DefaultValue <> nil then
|
if TMethodParam(ADecl.Params.Items[I]).DefaultValue <> nil then
|
||||||
begin
|
begin
|
||||||
Result := I;
|
Exit(I);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
Result := ADecl.Params.Count;
|
Result := ADecl.Params.Count;
|
||||||
end;
|
end;
|
||||||
|
|
@ -5282,15 +5259,13 @@ begin
|
||||||
Elem := TASTExpr(AExpr.Elements.Items[I]);
|
Elem := TASTExpr(AExpr.Elements.Items[I]);
|
||||||
if not (Elem is TIdentExpr) then
|
if not (Elem is TIdentExpr) then
|
||||||
begin
|
begin
|
||||||
Result := nil;
|
Exit(nil);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
Sym := FTable.Lookup(TIdentExpr(Elem).Name);
|
Sym := FTable.Lookup(TIdentExpr(Elem).Name);
|
||||||
if (Sym = nil) or (Sym.Kind <> skConstant) or (Sym.TypeDesc = nil) or
|
if (Sym = nil) or (Sym.Kind <> skConstant) or (Sym.TypeDesc = nil) or
|
||||||
(Sym.TypeDesc.Kind <> tyEnum) then
|
(Sym.TypeDesc.Kind <> tyEnum) then
|
||||||
begin
|
begin
|
||||||
Result := nil;
|
Exit(nil);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
if Result = nil then
|
if Result = nil then
|
||||||
Result := Sym.TypeDesc
|
Result := Sym.TypeDesc
|
||||||
|
|
@ -5346,30 +5321,26 @@ begin
|
||||||
(TOpenArrayTypeDesc(AParam).ElementType =
|
(TOpenArrayTypeDesc(AParam).ElementType =
|
||||||
TOpenArrayTypeDesc(AArg).ElementType) then
|
TOpenArrayTypeDesc(AArg).ElementType) then
|
||||||
begin
|
begin
|
||||||
Result := 2;
|
Exit(2);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
{ Static array coerced to open-array: widening match (score 1) }
|
{ Static array coerced to open-array: widening match (score 1) }
|
||||||
if (AParam.Kind = tyOpenArray) and (AArg.Kind = tyStaticArray) and
|
if (AParam.Kind = tyOpenArray) and (AArg.Kind = tyStaticArray) and
|
||||||
(TOpenArrayTypeDesc(AParam).ElementType =
|
(TOpenArrayTypeDesc(AParam).ElementType =
|
||||||
TStaticArrayTypeDesc(AArg).ElementType) then
|
TStaticArrayTypeDesc(AArg).ElementType) then
|
||||||
begin
|
begin
|
||||||
Result := 1;
|
Exit(1);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
{ Same numeric kind = exact match (same kind, just possibly different
|
{ Same numeric kind = exact match (same kind, just possibly different
|
||||||
descriptor instance). }
|
descriptor instance). }
|
||||||
if AParam.IsNumeric and AArg.IsNumeric and (AParam.Kind = AArg.Kind) then
|
if AParam.IsNumeric and AArg.IsNumeric and (AParam.Kind = AArg.Kind) then
|
||||||
begin
|
begin
|
||||||
Result := 2;
|
Exit(2);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
{ Numeric widening: both numerics, kinds differ. Captures
|
{ Numeric widening: both numerics, kinds differ. Captures
|
||||||
Integer→Int64, Integer→Double, Single→Double, Byte→Integer, etc. }
|
Integer→Int64, Integer→Double, Single→Double, Byte→Integer, etc. }
|
||||||
if AParam.IsNumeric and AArg.IsNumeric then
|
if AParam.IsNumeric and AArg.IsNumeric then
|
||||||
begin
|
begin
|
||||||
Result := 1;
|
Exit(1);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
{ Fall-through: probe full assignability via CheckTypesMatch. This
|
{ Fall-through: probe full assignability via CheckTypesMatch. This
|
||||||
covers nil-literal, class subtypes, untyped-Pointer compatibility,
|
covers nil-literal, class subtypes, untyped-Pointer compatibility,
|
||||||
|
|
@ -5430,8 +5401,7 @@ begin
|
||||||
begin
|
begin
|
||||||
if ArityMatch.Count = 1 then
|
if ArityMatch.Count = 1 then
|
||||||
begin
|
begin
|
||||||
Result := TMethodDecl(ArityMatch.Items[0]);
|
Exit(TMethodDecl(ArityMatch.Items[0]));
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
{ zero-arg ambiguity is impossible — same name + zero params would
|
{ zero-arg ambiguity is impossible — same name + zero params would
|
||||||
have been rejected by the symbol-table chain, but be defensive. }
|
have been rejected by the symbol-table chain, but be defensive. }
|
||||||
|
|
@ -5817,8 +5787,7 @@ begin
|
||||||
AExpr.Line, AExpr.Col);
|
AExpr.Line, AExpr.Col);
|
||||||
AExpr.IsBuiltinHasClassAttr := True;
|
AExpr.IsBuiltinHasClassAttr := True;
|
||||||
AExpr.ResolvedType := FTable.TypeBoolean;
|
AExpr.ResolvedType := FTable.TypeBoolean;
|
||||||
Result := AExpr.ResolvedType;
|
Exit(AExpr.ResolvedType);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ SizeOf(TypeName) or SizeOf(expression) — compile-time byte size,
|
{ SizeOf(TypeName) or SizeOf(expression) — compile-time byte size,
|
||||||
|
|
@ -6906,8 +6875,7 @@ begin
|
||||||
AExpr.ResolvedMethod := MDecl;
|
AExpr.ResolvedMethod := MDecl;
|
||||||
AExpr.ResolvedClassType := ObjSym.TypeDesc;
|
AExpr.ResolvedClassType := ObjSym.TypeDesc;
|
||||||
AExpr.IsConstructorCall := True;
|
AExpr.IsConstructorCall := True;
|
||||||
Result := ObjSym.TypeDesc;
|
Exit(ObjSym.TypeDesc);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if not (ObjSym.Kind in [skVariable, skParameter, skVarParameter]) then
|
if not (ObjSym.Kind in [skVariable, skParameter, skVarParameter]) then
|
||||||
|
|
@ -7202,15 +7170,13 @@ begin
|
||||||
begin
|
begin
|
||||||
AAccess.IsClassNameAccess := True;
|
AAccess.IsClassNameAccess := True;
|
||||||
AAccess.ResolvedType := FTable.TypeString;
|
AAccess.ResolvedType := FTable.TypeString;
|
||||||
Result := FTable.TypeString;
|
Exit(FTable.TypeString);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
if SameText(AAccess.FieldName, 'ClassType') and (BaseType.Kind = tyClass) then
|
if SameText(AAccess.FieldName, 'ClassType') and (BaseType.Kind = tyClass) then
|
||||||
begin
|
begin
|
||||||
AAccess.IsClassTypeAccess := True;
|
AAccess.IsClassTypeAccess := True;
|
||||||
AAccess.ResolvedType := FTable.TypePointer; { TClass = Pointer for now }
|
AAccess.ResolvedType := FTable.TypePointer; { TClass = Pointer for now }
|
||||||
Result := FTable.TypePointer;
|
Exit(FTable.TypePointer);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
RT := TRecordTypeDesc(BaseType);
|
RT := TRecordTypeDesc(BaseType);
|
||||||
FldInfo := RT.FindField(AAccess.FieldName);
|
FldInfo := RT.FindField(AAccess.FieldName);
|
||||||
|
|
@ -7221,8 +7187,7 @@ begin
|
||||||
begin
|
begin
|
||||||
AAccess.FieldName := PropInfo.ReadField;
|
AAccess.FieldName := PropInfo.ReadField;
|
||||||
AAccess.FieldInfo := RT.FindField(PropInfo.ReadField);
|
AAccess.FieldInfo := RT.FindField(PropInfo.ReadField);
|
||||||
Result := PropInfo.TypeDesc;
|
Exit(PropInfo.TypeDesc);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
{ Method-backed property (including indexed: the parser attaches the
|
{ Method-backed property (including indexed: the parser attaches the
|
||||||
'[idx]' to AAccess.PropIndexExpr when it parses 'Base.Prop[idx]'). }
|
'[idx]' to AAccess.PropIndexExpr when it parses 'Base.Prop[idx]'). }
|
||||||
|
|
@ -7248,8 +7213,7 @@ begin
|
||||||
if AAccess.ResolvedMethod <> nil then
|
if AAccess.ResolvedMethod <> nil then
|
||||||
begin
|
begin
|
||||||
AAccess.IsMethodCall := True;
|
AAccess.IsMethodCall := True;
|
||||||
Result := TMethodDecl(AAccess.ResolvedMethod).ResolvedReturnType;
|
Exit(TMethodDecl(AAccess.ResolvedMethod).ResolvedReturnType);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
{ Built-in TObject.ToString: virtual dispatch yielding string.
|
{ Built-in TObject.ToString: virtual dispatch yielding string.
|
||||||
Every class inherits this via vtable slot 1. }
|
Every class inherits this via vtable slot 1. }
|
||||||
|
|
@ -7275,8 +7239,7 @@ begin
|
||||||
AAccess.ConstArrayType := Sym.TypeDesc;
|
AAccess.ConstArrayType := Sym.TypeDesc;
|
||||||
end;
|
end;
|
||||||
AAccess.ResolvedType := Sym.TypeDesc;
|
AAccess.ResolvedType := Sym.TypeDesc;
|
||||||
Result := Sym.TypeDesc;
|
Exit(Sym.TypeDesc);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
SemanticError(
|
SemanticError(
|
||||||
Format('Type ''%s'' has no field ''%s''',
|
Format('Type ''%s'' has no field ''%s''',
|
||||||
|
|
@ -7441,13 +7404,11 @@ begin
|
||||||
begin
|
begin
|
||||||
AnalyseExpr(AAccess.PropIndexExpr);
|
AnalyseExpr(AAccess.PropIndexExpr);
|
||||||
AAccess.ResolvedType := TStaticArrayTypeDesc(Sym.TypeDesc).ElementType;
|
AAccess.ResolvedType := TStaticArrayTypeDesc(Sym.TypeDesc).ElementType;
|
||||||
Result := AAccess.ResolvedType;
|
Exit(AAccess.ResolvedType);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
AAccess.ResolvedType := Sym.TypeDesc;
|
AAccess.ResolvedType := Sym.TypeDesc;
|
||||||
Result := Sym.TypeDesc;
|
Exit(Sym.TypeDesc);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
SemanticError(
|
SemanticError(
|
||||||
Format('Unknown class method ''%s'' on type ''%s''',
|
Format('Unknown class method ''%s'' on type ''%s''',
|
||||||
|
|
@ -7460,8 +7421,7 @@ begin
|
||||||
AAccess.Line, AAccess.Col);
|
AAccess.Line, AAccess.Col);
|
||||||
AAccess.IsConstructorCall := True;
|
AAccess.IsConstructorCall := True;
|
||||||
AAccess.ResolvedMethod := FindMethodDecl(TRecordTypeDesc(RecSym.TypeDesc).Name, 'Create');
|
AAccess.ResolvedMethod := FindMethodDecl(TRecordTypeDesc(RecSym.TypeDesc).Name, 'Create');
|
||||||
Result := RecSym.TypeDesc;
|
Exit(RecSym.TypeDesc);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Field access on variable or parameter }
|
{ Field access on variable or parameter }
|
||||||
|
|
@ -7511,15 +7471,13 @@ begin
|
||||||
begin
|
begin
|
||||||
AAccess.IsClassNameAccess := True;
|
AAccess.IsClassNameAccess := True;
|
||||||
AAccess.ResolvedType := FTable.TypeString;
|
AAccess.ResolvedType := FTable.TypeString;
|
||||||
Result := FTable.TypeString;
|
Exit(FTable.TypeString);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
if SameText(AAccess.FieldName, 'ClassType') and (RecSym.TypeDesc.Kind = tyClass) then
|
if SameText(AAccess.FieldName, 'ClassType') and (RecSym.TypeDesc.Kind = tyClass) then
|
||||||
begin
|
begin
|
||||||
AAccess.IsClassTypeAccess := True;
|
AAccess.IsClassTypeAccess := True;
|
||||||
AAccess.ResolvedType := FTable.TypePointer;
|
AAccess.ResolvedType := FTable.TypePointer;
|
||||||
Result := FTable.TypePointer;
|
Exit(FTable.TypePointer);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
RT := TRecordTypeDesc(RecSym.TypeDesc);
|
RT := TRecordTypeDesc(RecSym.TypeDesc);
|
||||||
|
|
@ -7592,13 +7550,11 @@ begin
|
||||||
begin
|
begin
|
||||||
AnalyseExpr(AAccess.PropIndexExpr);
|
AnalyseExpr(AAccess.PropIndexExpr);
|
||||||
AAccess.ResolvedType := TStaticArrayTypeDesc(Sym.TypeDesc).ElementType;
|
AAccess.ResolvedType := TStaticArrayTypeDesc(Sym.TypeDesc).ElementType;
|
||||||
Result := AAccess.ResolvedType;
|
Exit(AAccess.ResolvedType);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
AAccess.ResolvedType := Sym.TypeDesc;
|
AAccess.ResolvedType := Sym.TypeDesc;
|
||||||
Result := Sym.TypeDesc;
|
Exit(Sym.TypeDesc);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
SemanticError(
|
SemanticError(
|
||||||
Format('Type ''%s'' has no field ''%s''',
|
Format('Type ''%s'' has no field ''%s''',
|
||||||
|
|
@ -7724,8 +7680,7 @@ begin
|
||||||
Format('Right operand of ''%s'' must be Boolean, got ''%s''',
|
Format('Right operand of ''%s'' must be Boolean, got ''%s''',
|
||||||
[BinaryOpName(ABin.Op), RType.Name]),
|
[BinaryOpName(ABin.Op), RType.Name]),
|
||||||
ABin.Line, ABin.Col);
|
ABin.Line, ABin.Col);
|
||||||
Result := FTable.TypeBoolean;
|
Exit(FTable.TypeBoolean);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if IsComparisonOp(ABin.Op) then
|
if IsComparisonOp(ABin.Op) then
|
||||||
|
|
@ -7774,20 +7729,17 @@ begin
|
||||||
{ String concatenation: s1 + s2 → string }
|
{ String concatenation: s1 + s2 → string }
|
||||||
if (ABin.Op = boAdd) and LType.IsString and RType.IsString then
|
if (ABin.Op = boAdd) and LType.IsString and RType.IsString then
|
||||||
begin
|
begin
|
||||||
Result := FTable.TypeString;
|
Exit(FTable.TypeString);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Pointer arithmetic: Pointer/PChar + Integer or Integer + Pointer → same type }
|
{ Pointer arithmetic: Pointer/PChar + Integer or Integer + Pointer → same type }
|
||||||
if (ABin.Op in [boAdd, boSub]) and (LType.Kind in [tyPointer, tyPChar]) and RType.IsNumeric then
|
if (ABin.Op in [boAdd, boSub]) and (LType.Kind in [tyPointer, tyPChar]) and RType.IsNumeric then
|
||||||
begin
|
begin
|
||||||
Result := LType;
|
Exit(LType);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
if (ABin.Op = boAdd) and LType.IsNumeric and (RType.Kind in [tyPointer, tyPChar]) then
|
if (ABin.Op = boAdd) and LType.IsNumeric and (RType.Kind in [tyPointer, tyPChar]) then
|
||||||
begin
|
begin
|
||||||
Result := RType;
|
Exit(RType);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Shift operators: result has the left operand's type; right is the shift amount }
|
{ Shift operators: result has the left operand's type; right is the shift amount }
|
||||||
|
|
@ -8068,8 +8020,7 @@ begin
|
||||||
ProcDesc.ReturnType := MD.ResolvedReturnType;
|
ProcDesc.ReturnType := MD.ResolvedReturnType;
|
||||||
FldExpr.ResolvedType := ProcDesc;
|
FldExpr.ResolvedType := ProcDesc;
|
||||||
AExpr.ResolvedType := ProcDesc;
|
AExpr.ResolvedType := ProcDesc;
|
||||||
Result := ProcDesc;
|
Exit(ProcDesc);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
@ -8223,8 +8174,7 @@ begin
|
||||||
SemanticError(
|
SemanticError(
|
||||||
'Expression is not callable — expected procedural type',
|
'Expression is not callable — expected procedural type',
|
||||||
AExpr.Line, AExpr.Col);
|
AExpr.Line, AExpr.Col);
|
||||||
Result := FTable.TypeInteger;
|
Exit(FTable.TypeInteger);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
ProcDesc := TProceduralTypeDesc(CalleeType);
|
ProcDesc := TProceduralTypeDesc(CalleeType);
|
||||||
AExpr.ResolvedProcType := ProcDesc;
|
AExpr.ResolvedProcType := ProcDesc;
|
||||||
|
|
@ -8364,8 +8314,7 @@ begin
|
||||||
if AExpr.Elements.Count = 0 then
|
if AExpr.Elements.Count = 0 then
|
||||||
begin
|
begin
|
||||||
AExpr.ResolvedType := nil;
|
AExpr.ResolvedType := nil;
|
||||||
Result := nil;
|
Exit(nil);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
ElemType := AnalyseExpr(TASTExpr(AExpr.Elements.Items[0]));
|
ElemType := AnalyseExpr(TASTExpr(AExpr.Elements.Items[0]));
|
||||||
for I := 1 to AExpr.Elements.Count - 1 do
|
for I := 1 to AExpr.Elements.Count - 1 do
|
||||||
|
|
|
||||||
|
|
@ -731,8 +731,7 @@ begin
|
||||||
E := TVTableEntry(FVTable.Items[I]);
|
E := TVTableEntry(FVTable.Items[I]);
|
||||||
if SameText(E.MethName, AMethodName) then
|
if SameText(E.MethName, AMethodName) then
|
||||||
begin
|
begin
|
||||||
Result := I;
|
Exit(I);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
@ -812,8 +811,7 @@ begin
|
||||||
for I := 0 to Walk.FProperties.Count - 1 do
|
for I := 0 to Walk.FProperties.Count - 1 do
|
||||||
if SameText(TPropertyInfo(Walk.FProperties.Items[I]).Name, AName) then
|
if SameText(TPropertyInfo(Walk.FProperties.Items[I]).Name, AName) then
|
||||||
begin
|
begin
|
||||||
Result := TPropertyInfo(Walk.FProperties.Items[I]);
|
Exit(TPropertyInfo(Walk.FProperties.Items[I]));
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
Walk := Walk.Parent;
|
Walk := Walk.Parent;
|
||||||
end;
|
end;
|
||||||
|
|
@ -834,8 +832,7 @@ begin
|
||||||
P := TPropertyInfo(Walk.FProperties.Items[I]);
|
P := TPropertyInfo(Walk.FProperties.Items[I]);
|
||||||
if (P.IndexParamName <> '') and (P.ReadMethod <> '') then
|
if (P.IndexParamName <> '') and (P.ReadMethod <> '') then
|
||||||
begin
|
begin
|
||||||
Result := P;
|
Exit(P);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
Walk := Walk.Parent;
|
Walk := Walk.Parent;
|
||||||
|
|
@ -931,8 +928,7 @@ begin
|
||||||
CurPar := CurPar + 1
|
CurPar := CurPar + 1
|
||||||
else if CurPar = AParamIndex then
|
else if CurPar = AParamIndex then
|
||||||
begin
|
begin
|
||||||
Result := Flags[Idx] = '1';
|
Exit(Flags[Idx] = '1');
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
Idx := Idx + 1;
|
Idx := Idx + 1;
|
||||||
end;
|
end;
|
||||||
|
|
@ -1010,11 +1006,9 @@ begin
|
||||||
Tail := Tail.NextOverload;
|
Tail := Tail.NextOverload;
|
||||||
Tail.NextOverload := ASymbol;
|
Tail.NextOverload := ASymbol;
|
||||||
FSymbols.Add(ASymbol); { take ownership; lookup walks the chain via Existing }
|
FSymbols.Add(ASymbol); { take ownership; lookup walks the chain via Existing }
|
||||||
Result := True;
|
Exit(True);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
Result := False;
|
Exit(False);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
FSymbols.Add(ASymbol);
|
FSymbols.Add(ASymbol);
|
||||||
{ Store the TSymbol pointer directly in the string list's Objects slot. }
|
{ Store the TSymbol pointer directly in the string list's Objects slot. }
|
||||||
|
|
@ -1072,8 +1066,7 @@ begin
|
||||||
for I := 0 to Members.Count - 1 do
|
for I := 0 to Members.Count - 1 do
|
||||||
if SameText(Members.Strings[I], AMember) then
|
if SameText(Members.Strings[I], AMember) then
|
||||||
begin
|
begin
|
||||||
Result := I;
|
Exit(I);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
Result := -1;
|
Result := -1;
|
||||||
end;
|
end;
|
||||||
|
|
|
||||||
|
|
@ -100,8 +100,7 @@ begin
|
||||||
Candidate := IncludeTrailingPathDelimiter(ADir) + ABaseName;
|
Candidate := IncludeTrailingPathDelimiter(ADir) + ABaseName;
|
||||||
if FileExists(Candidate) then
|
if FileExists(Candidate) then
|
||||||
begin
|
begin
|
||||||
Result := Candidate;
|
Exit(Candidate);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
{ Blaise Pos: -1 = not found. `< 0` is the "not present" test. }
|
{ Blaise Pos: -1 = not found. `< 0` is the "not present" test. }
|
||||||
if IsWindowsHost and (Pos('.exe', LowerCase(ABaseName)) < 0) then
|
if IsWindowsHost and (Pos('.exe', LowerCase(ABaseName)) < 0) then
|
||||||
|
|
@ -109,8 +108,7 @@ begin
|
||||||
Candidate := IncludeTrailingPathDelimiter(ADir) + ABaseName + '.exe';
|
Candidate := IncludeTrailingPathDelimiter(ADir) + ABaseName + '.exe';
|
||||||
if FileExists(Candidate) then
|
if FileExists(Candidate) then
|
||||||
begin
|
begin
|
||||||
Result := Candidate;
|
Exit(Candidate);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
Result := '';
|
Result := '';
|
||||||
|
|
@ -144,8 +142,7 @@ begin
|
||||||
Hit := TrySingleName(Entry, ABaseName);
|
Hit := TrySingleName(Entry, ABaseName);
|
||||||
if Hit <> '' then
|
if Hit <> '' then
|
||||||
begin
|
begin
|
||||||
Result := Hit;
|
Exit(Hit);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
@ -181,8 +178,7 @@ begin
|
||||||
EnvPath := GetEnvironmentVariable(AEnvVar);
|
EnvPath := GetEnvironmentVariable(AEnvVar);
|
||||||
if (EnvPath <> '') and FileExists(EnvPath) then
|
if (EnvPath <> '') and FileExists(EnvPath) then
|
||||||
begin
|
begin
|
||||||
Result := EnvPath;
|
Exit(EnvPath);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
Hit := TryCandidate(ACandA);
|
Hit := TryCandidate(ACandA);
|
||||||
|
|
|
||||||
|
|
@ -68,15 +68,13 @@ begin
|
||||||
Path := Base + LowerCase(AName) + '.pas';
|
Path := Base + LowerCase(AName) + '.pas';
|
||||||
if FileExists(Path) then
|
if FileExists(Path) then
|
||||||
begin
|
begin
|
||||||
Result := Path;
|
Exit(Path);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
{ Fallback: exact case as written in the uses clause }
|
{ Fallback: exact case as written in the uses clause }
|
||||||
Path := Base + AName + '.pas';
|
Path := Base + AName + '.pas';
|
||||||
if FileExists(Path) then
|
if FileExists(Path) then
|
||||||
begin
|
begin
|
||||||
Result := Path;
|
Exit(Path);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
Result := '';
|
Result := '';
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ type
|
||||||
|
|
||||||
{ Non-local exit (Exit/Break) must run intervening finally bodies. }
|
{ Non-local exit (Exit/Break) must run intervening finally bodies. }
|
||||||
procedure TestRun_ExitThroughFinally;
|
procedure TestRun_ExitThroughFinally;
|
||||||
|
procedure TestRun_ExitValueThroughFinally;
|
||||||
procedure TestRun_ExitThroughNestedFinally;
|
procedure TestRun_ExitThroughNestedFinally;
|
||||||
procedure TestRun_BreakThroughFinally;
|
procedure TestRun_BreakThroughFinally;
|
||||||
|
|
||||||
|
|
@ -124,6 +125,29 @@ const
|
||||||
end.
|
end.
|
||||||
''';
|
''';
|
||||||
|
|
||||||
|
{ Exit(X) from inside a try/finally must assign the result, run the finally
|
||||||
|
body, then return the value to the caller. Guards the refactor that
|
||||||
|
replaces the 'Result := X; Exit;' workaround with 'Exit(X)' in source
|
||||||
|
that sits inside try/finally. }
|
||||||
|
SrcExitValueThroughFinally = '''
|
||||||
|
program P;
|
||||||
|
function Pick(b: Boolean): Integer;
|
||||||
|
begin
|
||||||
|
Result := -1;
|
||||||
|
try
|
||||||
|
if b then Exit(42);
|
||||||
|
WriteLn('unreached')
|
||||||
|
finally
|
||||||
|
WriteLn('in_finally')
|
||||||
|
end;
|
||||||
|
Result := 7
|
||||||
|
end;
|
||||||
|
begin
|
||||||
|
WriteLn(Pick(True));
|
||||||
|
WriteLn(Pick(False))
|
||||||
|
end.
|
||||||
|
''';
|
||||||
|
|
||||||
{ Exit nested two levels deep must run both finally bodies, innermost first. }
|
{ Exit nested two levels deep must run both finally bodies, innermost first. }
|
||||||
SrcExitThroughNestedFinally = '''
|
SrcExitThroughNestedFinally = '''
|
||||||
program P;
|
program P;
|
||||||
|
|
@ -350,6 +374,19 @@ begin
|
||||||
'in_try' + LE + 'in_finally' + LE + 'after' + LE, Output);
|
'in_try' + LE + 'in_finally' + LE + 'after' + LE, Output);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TE2EExceptionTests.TestRun_ExitValueThroughFinally;
|
||||||
|
var Output: string; RCode: Integer;
|
||||||
|
begin
|
||||||
|
if not ToolchainAvailable then begin Ignore('toolchain unavailable'); Exit; end;
|
||||||
|
AssertTrue('compile+run', CompileAndRun(SrcExitValueThroughFinally, Output, RCode));
|
||||||
|
AssertEquals('exit code', 0, RCode);
|
||||||
|
{ True: Exit(42) sets Result, runs finally, returns 42.
|
||||||
|
False: falls through, runs finally, then Result := 7. }
|
||||||
|
AssertEquals('stdout',
|
||||||
|
'in_finally' + LE + '42' + LE +
|
||||||
|
'unreached' + LE + 'in_finally' + LE + '7' + LE, Output);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TE2EExceptionTests.TestRun_ExitThroughNestedFinally;
|
procedure TE2EExceptionTests.TestRun_ExitThroughNestedFinally;
|
||||||
var Output: string; RCode: Integer;
|
var Output: string; RCode: Integer;
|
||||||
begin
|
begin
|
||||||
|
|
|
||||||
|
|
@ -411,8 +411,7 @@ var
|
||||||
begin
|
begin
|
||||||
if S1 = S2 then
|
if S1 = S2 then
|
||||||
begin
|
begin
|
||||||
Result := 1;
|
Exit(1);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
if S1 = nil then
|
if S1 = nil then
|
||||||
Len1 := 0
|
Len1 := 0
|
||||||
|
|
@ -430,13 +429,11 @@ begin
|
||||||
end;
|
end;
|
||||||
if Len1 <> Len2 then
|
if Len1 <> Len2 then
|
||||||
begin
|
begin
|
||||||
Result := 0;
|
Exit(0);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
if Len1 = 0 then
|
if Len1 = 0 then
|
||||||
begin
|
begin
|
||||||
Result := 1;
|
Exit(1);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
C1 := PChar(S1); { data IS the pointer }
|
C1 := PChar(S1); { data IS the pointer }
|
||||||
C2 := PChar(S2);
|
C2 := PChar(S2);
|
||||||
|
|
@ -506,8 +503,7 @@ var
|
||||||
begin
|
begin
|
||||||
if Self = nil then
|
if Self = nil then
|
||||||
begin
|
begin
|
||||||
Result := nil;
|
Exit(nil);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
Slot := Self; { instance: first 8 bytes = vptr }
|
Slot := Self; { instance: first 8 bytes = vptr }
|
||||||
VTable := Slot^; { VTable points to vtable data }
|
VTable := Slot^; { VTable points to vtable data }
|
||||||
|
|
@ -561,8 +557,7 @@ begin
|
||||||
Entry := Pointer(Entry) + 8;
|
Entry := Pointer(Entry) + 8;
|
||||||
if _StringEquals(EntName, Name) <> 0 then
|
if _StringEquals(EntName, Name) <> 0 then
|
||||||
begin
|
begin
|
||||||
Result := EntAddr;
|
Exit(EntAddr);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
@ -588,8 +583,7 @@ begin
|
||||||
begin
|
begin
|
||||||
if Current = AParent then
|
if Current = AParent then
|
||||||
begin
|
begin
|
||||||
Result := True;
|
Exit(True);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
TI := Current; { typeinfo[0] = parent pointer }
|
TI := Current; { typeinfo[0] = parent pointer }
|
||||||
Current := TI^;
|
Current := TI^;
|
||||||
|
|
@ -690,8 +684,7 @@ begin
|
||||||
begin
|
begin
|
||||||
if Entry^ = AAttrTI then
|
if Entry^ = AAttrTI then
|
||||||
begin
|
begin
|
||||||
Result := True;
|
Exit(True);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
Entry := Pointer(Entry) + 8;
|
Entry := Pointer(Entry) + 8;
|
||||||
end;
|
end;
|
||||||
|
|
|
||||||
|
|
@ -72,8 +72,7 @@ begin
|
||||||
Base := _BlaiseGetMem(13);
|
Base := _BlaiseGetMem(13);
|
||||||
if Base = nil then
|
if Base = nil then
|
||||||
begin
|
begin
|
||||||
Result := nil;
|
Exit(nil);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
RC := Base;
|
RC := Base;
|
||||||
RC^ := 0;
|
RC^ := 0;
|
||||||
|
|
@ -140,8 +139,7 @@ begin
|
||||||
Exc := g_current_exception;
|
Exc := g_current_exception;
|
||||||
if Exc = nil then
|
if Exc = nil then
|
||||||
begin
|
begin
|
||||||
Result := ExcStrEmpty;
|
Exit(ExcStrEmpty);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
MsgSlot := Exc + 8;
|
MsgSlot := Exc + 8;
|
||||||
Msg := MsgSlot^;
|
Msg := MsgSlot^;
|
||||||
|
|
@ -174,8 +172,7 @@ begin
|
||||||
begin
|
begin
|
||||||
if TI = Target then
|
if TI = Target then
|
||||||
begin
|
begin
|
||||||
Result := 1;
|
Exit(1);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
ParentSlot := TI;
|
ParentSlot := TI;
|
||||||
TI := ParentSlot^;
|
TI := ParentSlot^;
|
||||||
|
|
@ -202,8 +199,7 @@ begin
|
||||||
begin
|
begin
|
||||||
if Impl^ = IntfTI then
|
if Impl^ = IntfTI then
|
||||||
begin
|
begin
|
||||||
Result := 1;
|
Exit(1);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
Impl := Pointer(Impl) + 16;
|
Impl := Pointer(Impl) + 16;
|
||||||
end;
|
end;
|
||||||
|
|
@ -234,8 +230,7 @@ begin
|
||||||
if Impl^ = IntfTI then
|
if Impl^ = IntfTI then
|
||||||
begin
|
begin
|
||||||
ItabSlot := Pointer(Impl) + 8;
|
ItabSlot := Pointer(Impl) + 8;
|
||||||
Result := ItabSlot^;
|
Exit(ItabSlot^);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
Impl := Pointer(Impl) + 16;
|
Impl := Pointer(Impl) + 16;
|
||||||
end;
|
end;
|
||||||
|
|
|
||||||
|
|
@ -54,8 +54,7 @@ begin
|
||||||
Base := _BlaiseGetMem(BLAISE_STR_HDR + Cap);
|
Base := _BlaiseGetMem(BLAISE_STR_HDR + Cap);
|
||||||
if Base = nil then
|
if Base = nil then
|
||||||
begin
|
begin
|
||||||
Result := nil;
|
Exit(nil);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
RC := Base; RC^ := 1;
|
RC := Base; RC^ := 1;
|
||||||
LN := Base + 4; LN^ := Len;
|
LN := Base + 4; LN^ := Len;
|
||||||
|
|
@ -123,8 +122,7 @@ var
|
||||||
begin
|
begin
|
||||||
if X = 0 then
|
if X = 0 then
|
||||||
begin
|
begin
|
||||||
Result := 64;
|
Exit(64);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
N := 0;
|
N := 0;
|
||||||
if (X shr 32) = 0 then begin N := N + 32; X := X shl 32; end;
|
if (X shr 32) = 0 then begin N := N + 32; X := X shl 32; end;
|
||||||
|
|
@ -645,8 +643,7 @@ var
|
||||||
begin
|
begin
|
||||||
if E = 0 then
|
if E = 0 then
|
||||||
begin
|
begin
|
||||||
Result := 1.0;
|
Exit(1.0);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
if E < 0 then
|
if E < 0 then
|
||||||
N := -E
|
N := -E
|
||||||
|
|
@ -682,8 +679,7 @@ var
|
||||||
begin
|
begin
|
||||||
if S = nil then
|
if S = nil then
|
||||||
begin
|
begin
|
||||||
Result := 0.0;
|
Exit(0.0);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
P := PChar(S);
|
P := PChar(S);
|
||||||
I := 0;
|
I := 0;
|
||||||
|
|
@ -710,14 +706,12 @@ begin
|
||||||
Bits := Int64($FFF0000000000000)
|
Bits := Int64($FFF0000000000000)
|
||||||
else
|
else
|
||||||
Bits := Int64($7FF0000000000000);
|
Bits := Int64($7FF0000000000000);
|
||||||
Result := BitsToDouble(Bits);
|
Exit(BitsToDouble(Bits));
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
if (C = 110) or (C = 78) then
|
if (C = 110) or (C = 78) then
|
||||||
begin
|
begin
|
||||||
Bits := Int64($7FF8000000000000);
|
Bits := Int64($7FF8000000000000);
|
||||||
Result := BitsToDouble(Bits);
|
Exit(BitsToDouble(Bits));
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Parse mantissa digits }
|
{ Parse mantissa digits }
|
||||||
|
|
|
||||||
|
|
@ -172,8 +172,7 @@ begin
|
||||||
Base := MmapAlloc(Int64(ARENA_SIZE));
|
Base := MmapAlloc(Int64(ARENA_SIZE));
|
||||||
if Base = nil then
|
if Base = nil then
|
||||||
begin
|
begin
|
||||||
Result := nil;
|
Exit(nil);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
A := PArena(Base);
|
A := PArena(Base);
|
||||||
A^.Base := Base;
|
A^.Base := Base;
|
||||||
|
|
@ -200,15 +199,13 @@ begin
|
||||||
Hdr^.AllocSize := Size;
|
Hdr^.AllocSize := Size;
|
||||||
Hdr^.Flags := FLAG_SMALL;
|
Hdr^.Flags := FLAG_SMALL;
|
||||||
A^.Offset := A^.Offset + Needed;
|
A^.Offset := A^.Offset + Needed;
|
||||||
Result := Pointer(PtrUInt(Hdr) + HEADER_SIZE);
|
Exit(Pointer(PtrUInt(Hdr) + HEADER_SIZE));
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
A := AllocArena;
|
A := AllocArena;
|
||||||
if A = nil then
|
if A = nil then
|
||||||
begin
|
begin
|
||||||
Result := nil;
|
Exit(nil);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
Hdr := Pointer(PtrUInt(A^.Base) + PtrUInt(A^.Offset));
|
Hdr := Pointer(PtrUInt(A^.Base) + PtrUInt(A^.Offset));
|
||||||
Hdr^.AllocSize := Size;
|
Hdr^.AllocSize := Size;
|
||||||
|
|
@ -231,8 +228,7 @@ begin
|
||||||
FreeLists[Idx] := Node^.Next;
|
FreeLists[Idx] := Node^.Next;
|
||||||
Hdr := PBlockHeader(Pointer(PtrUInt(Node) - HEADER_SIZE));
|
Hdr := PBlockHeader(Pointer(PtrUInt(Node) - HEADER_SIZE));
|
||||||
Hdr^.AllocSize := Size;
|
Hdr^.AllocSize := Size;
|
||||||
Result := Pointer(Node);
|
Exit(Pointer(Node));
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
Result := ArenaAlloc(Size);
|
Result := ArenaAlloc(Size);
|
||||||
|
|
@ -273,8 +269,7 @@ begin
|
||||||
Hdr^.TotalMapped := CachedSize;
|
Hdr^.TotalMapped := CachedSize;
|
||||||
Hdr^.AllocSize := Size;
|
Hdr^.AllocSize := Size;
|
||||||
Hdr^.Flags := FLAG_LARGE;
|
Hdr^.Flags := FLAG_LARGE;
|
||||||
Result := Pointer(PtrUInt(Hdr) + LARGE_HEADER);
|
Exit(Pointer(PtrUInt(Hdr) + LARGE_HEADER));
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
Base := _libc_mremap(Pointer(Node), CachedSize, Needed, MREMAP_MAYMOVE);
|
Base := _libc_mremap(Pointer(Node), CachedSize, Needed, MREMAP_MAYMOVE);
|
||||||
if not MapFailed(Base) then
|
if not MapFailed(Base) then
|
||||||
|
|
@ -283,8 +278,7 @@ begin
|
||||||
Hdr^.TotalMapped := Needed;
|
Hdr^.TotalMapped := Needed;
|
||||||
Hdr^.AllocSize := Size;
|
Hdr^.AllocSize := Size;
|
||||||
Hdr^.Flags := FLAG_LARGE;
|
Hdr^.Flags := FLAG_LARGE;
|
||||||
Result := Pointer(PtrUInt(Base) + LARGE_HEADER);
|
Exit(Pointer(PtrUInt(Base) + LARGE_HEADER));
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
_libc_munmap(Pointer(Node), CachedSize);
|
_libc_munmap(Pointer(Node), CachedSize);
|
||||||
end;
|
end;
|
||||||
|
|
@ -293,8 +287,7 @@ begin
|
||||||
Base := MmapAlloc(Total);
|
Base := MmapAlloc(Total);
|
||||||
if Base = nil then
|
if Base = nil then
|
||||||
begin
|
begin
|
||||||
Result := nil;
|
Exit(nil);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
Hdr := PLargeHeader(Base);
|
Hdr := PLargeHeader(Base);
|
||||||
Hdr^.TotalMapped := Total;
|
Hdr^.TotalMapped := Total;
|
||||||
|
|
@ -352,8 +345,7 @@ function _BlaiseGetMem(Size: Integer): Pointer;
|
||||||
begin
|
begin
|
||||||
if Size <= 0 then
|
if Size <= 0 then
|
||||||
begin
|
begin
|
||||||
Result := nil;
|
Exit(nil);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
if Size > LARGE_THRESHOLD then
|
if Size > LARGE_THRESHOLD then
|
||||||
Result := LargeGetMem(Size)
|
Result := LargeGetMem(Size)
|
||||||
|
|
@ -380,14 +372,12 @@ var
|
||||||
begin
|
begin
|
||||||
if Ptr = nil then
|
if Ptr = nil then
|
||||||
begin
|
begin
|
||||||
Result := _BlaiseGetMem(NewSize);
|
Exit(_BlaiseGetMem(NewSize));
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
if NewSize <= 0 then
|
if NewSize <= 0 then
|
||||||
begin
|
begin
|
||||||
_BlaiseFreeMem(Ptr);
|
_BlaiseFreeMem(Ptr);
|
||||||
Result := nil;
|
Exit(nil);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
OldSize := GetAllocSize(Ptr);
|
OldSize := GetAllocSize(Ptr);
|
||||||
if (not IsLarge(Ptr)) and (NewSize <= LARGE_THRESHOLD) then
|
if (not IsLarge(Ptr)) and (NewSize <= LARGE_THRESHOLD) then
|
||||||
|
|
@ -396,8 +386,7 @@ begin
|
||||||
begin
|
begin
|
||||||
Hdr := PBlockHeader(Pointer(PtrUInt(Ptr) - HEADER_SIZE));
|
Hdr := PBlockHeader(Pointer(PtrUInt(Ptr) - HEADER_SIZE));
|
||||||
Hdr^.AllocSize := NewSize;
|
Hdr^.AllocSize := NewSize;
|
||||||
Result := Ptr;
|
Exit(Ptr);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
if IsLarge(Ptr) and (NewSize > LARGE_THRESHOLD) then
|
if IsLarge(Ptr) and (NewSize > LARGE_THRESHOLD) then
|
||||||
|
|
@ -408,8 +397,7 @@ begin
|
||||||
if NewMapped = OldMapped then
|
if NewMapped = OldMapped then
|
||||||
begin
|
begin
|
||||||
LHdr^.AllocSize := NewSize;
|
LHdr^.AllocSize := NewSize;
|
||||||
Result := Ptr;
|
Exit(Ptr);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
Base := Pointer(LHdr);
|
Base := Pointer(LHdr);
|
||||||
NewBase := _libc_mremap(Base, OldMapped, NewMapped, MREMAP_MAYMOVE);
|
NewBase := _libc_mremap(Base, OldMapped, NewMapped, MREMAP_MAYMOVE);
|
||||||
|
|
@ -419,8 +407,7 @@ begin
|
||||||
LHdr^.TotalMapped := NewMapped;
|
LHdr^.TotalMapped := NewMapped;
|
||||||
LHdr^.AllocSize := NewSize;
|
LHdr^.AllocSize := NewSize;
|
||||||
LHdr^.Flags := FLAG_LARGE;
|
LHdr^.Flags := FLAG_LARGE;
|
||||||
Result := Pointer(PtrUInt(NewBase) + LARGE_HEADER);
|
Exit(Pointer(PtrUInt(NewBase) + LARGE_HEADER));
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
Result := _BlaiseGetMem(NewSize);
|
Result := _BlaiseGetMem(NewSize);
|
||||||
|
|
|
||||||
|
|
@ -153,8 +153,7 @@ begin
|
||||||
Base := _BlaiseGetMem(Integer(TotalL));
|
Base := _BlaiseGetMem(Integer(TotalL));
|
||||||
if Base = nil then
|
if Base = nil then
|
||||||
begin
|
begin
|
||||||
Result := nil;
|
Exit(nil);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
RC := Base; { RefCount at base+0 }
|
RC := Base; { RefCount at base+0 }
|
||||||
RC^ := 0;
|
RC^ := 0;
|
||||||
|
|
@ -191,13 +190,11 @@ begin
|
||||||
SubLen := StrLen(Sub);
|
SubLen := StrLen(Sub);
|
||||||
if SubLen = 0 then
|
if SubLen = 0 then
|
||||||
begin
|
begin
|
||||||
Result := 0;
|
Exit(0);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
if SubLen > SLen then
|
if SubLen > SLen then
|
||||||
begin
|
begin
|
||||||
Result := -1;
|
Exit(-1);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
SData := StrData(S);
|
SData := StrData(S);
|
||||||
SubData := StrData(Sub);
|
SubData := StrData(Sub);
|
||||||
|
|
@ -217,8 +214,7 @@ begin
|
||||||
end;
|
end;
|
||||||
if Match then
|
if Match then
|
||||||
begin
|
begin
|
||||||
Result := I;
|
Exit(I);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
Inc(I);
|
Inc(I);
|
||||||
end;
|
end;
|
||||||
|
|
@ -241,13 +237,11 @@ begin
|
||||||
SubLen := StrLen(Sub);
|
SubLen := StrLen(Sub);
|
||||||
if SubLen = 0 then
|
if SubLen = 0 then
|
||||||
begin
|
begin
|
||||||
Result := 0;
|
Exit(0);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
if (SubLen > SLen) or (StartPos >= SLen) then
|
if (SubLen > SLen) or (StartPos >= SLen) then
|
||||||
begin
|
begin
|
||||||
Result := -1;
|
Exit(-1);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
SData := StrData(S);
|
SData := StrData(S);
|
||||||
SubData := StrData(Sub);
|
SubData := StrData(Sub);
|
||||||
|
|
@ -268,8 +262,7 @@ begin
|
||||||
end;
|
end;
|
||||||
if Match then
|
if Match then
|
||||||
begin
|
begin
|
||||||
Result := I;
|
Exit(I);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
Inc(I);
|
Inc(I);
|
||||||
end;
|
end;
|
||||||
|
|
@ -289,8 +282,7 @@ begin
|
||||||
if From < 0 then From := 0;
|
if From < 0 then From := 0;
|
||||||
if From >= SLen then
|
if From >= SLen then
|
||||||
begin
|
begin
|
||||||
Result := StrAlloc(0);
|
Exit(StrAlloc(0));
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
{ Avoid signed overflow when Count is large (Copy(S, N, MaxInt) idiom) —
|
{ Avoid signed overflow when Count is large (Copy(S, N, MaxInt) idiom) —
|
||||||
compare Count against (SLen - From) instead of (From + Count) > SLen. }
|
compare Count against (SLen - From) instead of (From + Count) > SLen. }
|
||||||
|
|
@ -468,8 +460,7 @@ begin
|
||||||
Len2 := StrLen(S2);
|
Len2 := StrLen(S2);
|
||||||
if Len1 <> Len2 then
|
if Len1 <> Len2 then
|
||||||
begin
|
begin
|
||||||
Result := 0;
|
Exit(0);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
D1 := StrData(S1);
|
D1 := StrData(S1);
|
||||||
D2 := StrData(S2);
|
D2 := StrData(S2);
|
||||||
|
|
@ -481,8 +472,7 @@ begin
|
||||||
if (C2 >= 65) and (C2 <= 90) then C2 := C2 + 32;
|
if (C2 >= 65) and (C2 <= 90) then C2 := C2 + 32;
|
||||||
if C1 <> C2 then
|
if C1 <> C2 then
|
||||||
begin
|
begin
|
||||||
Result := 0;
|
Exit(0);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
Result := 1;
|
Result := 1;
|
||||||
|
|
@ -755,8 +745,7 @@ begin
|
||||||
Len := StrLen(S);
|
Len := StrLen(S);
|
||||||
if (I < 0) or (I >= Len) then
|
if (I < 0) or (I >= Len) then
|
||||||
begin
|
begin
|
||||||
Result := 0;
|
Exit(0);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
Data := StrData(S);
|
Data := StrData(S);
|
||||||
Result := Data[I];
|
Result := Data[I];
|
||||||
|
|
@ -811,8 +800,7 @@ begin
|
||||||
C2 := D2[I];
|
C2 := D2[I];
|
||||||
if C1 <> C2 then
|
if C1 <> C2 then
|
||||||
begin
|
begin
|
||||||
Result := C1 - C2;
|
Exit(C1 - C2);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
Result := Len1 - Len2;
|
Result := Len1 - Len2;
|
||||||
|
|
@ -841,8 +829,7 @@ begin
|
||||||
if (C2 >= 65) and (C2 <= 90) then C2 := C2 + 32;
|
if (C2 >= 65) and (C2 <= 90) then C2 := C2 + 32;
|
||||||
if C1 <> C2 then
|
if C1 <> C2 then
|
||||||
begin
|
begin
|
||||||
Result := C1 - C2;
|
Exit(C1 - C2);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
Result := Len1 - Len2;
|
Result := Len1 - Len2;
|
||||||
|
|
@ -858,8 +845,7 @@ var
|
||||||
begin
|
begin
|
||||||
if P = nil then
|
if P = nil then
|
||||||
begin
|
begin
|
||||||
Result := StrAlloc(0);
|
Exit(StrAlloc(0));
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
Len := 0;
|
Len := 0;
|
||||||
while P[Len] <> 0 do
|
while P[Len] <> 0 do
|
||||||
|
|
@ -1115,8 +1101,7 @@ begin
|
||||||
if P[I] = 47 then SlashPos := I;
|
if P[I] = 47 then SlashPos := I;
|
||||||
if SlashPos < 0 then
|
if SlashPos < 0 then
|
||||||
begin
|
begin
|
||||||
Result := StrAlloc(0);
|
Exit(StrAlloc(0));
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
Result := StrAlloc(SlashPos + 1);
|
Result := StrAlloc(SlashPos + 1);
|
||||||
if Result <> nil then MemCopy(Result, P, SlashPos + 1);
|
if Result <> nil then MemCopy(Result, P, SlashPos + 1);
|
||||||
|
|
@ -1134,8 +1119,7 @@ begin
|
||||||
if P[I] = 47 then SlashPos := I;
|
if P[I] = 47 then SlashPos := I;
|
||||||
if (SlashPos < 0) or (SlashPos = 0) then
|
if (SlashPos < 0) or (SlashPos = 0) then
|
||||||
begin
|
begin
|
||||||
Result := StrAlloc(0);
|
Exit(StrAlloc(0));
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
Result := StrAlloc(SlashPos);
|
Result := StrAlloc(SlashPos);
|
||||||
if Result <> nil then MemCopy(Result, P, SlashPos);
|
if Result <> nil then MemCopy(Result, P, SlashPos);
|
||||||
|
|
@ -1158,8 +1142,7 @@ begin
|
||||||
end;
|
end;
|
||||||
if (LastDot < 0) or ((LastSep >= 0) and (LastDot < LastSep)) then
|
if (LastDot < 0) or ((LastSep >= 0) and (LastDot < LastSep)) then
|
||||||
begin
|
begin
|
||||||
Result := StrAlloc(0);
|
Exit(StrAlloc(0));
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
ExtLen := PLen - LastDot;
|
ExtLen := PLen - LastDot;
|
||||||
Result := StrAlloc(ExtLen);
|
Result := StrAlloc(ExtLen);
|
||||||
|
|
@ -1213,8 +1196,7 @@ var
|
||||||
begin
|
begin
|
||||||
if Ptr = nil then
|
if Ptr = nil then
|
||||||
begin
|
begin
|
||||||
Result := 0;
|
Exit(0);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
{ length is stored at offset −4 from data pointer }
|
{ length is stored at offset −4 from data pointer }
|
||||||
LenPtr := Ptr - 4;
|
LenPtr := Ptr - 4;
|
||||||
|
|
@ -1240,8 +1222,7 @@ begin
|
||||||
begin
|
begin
|
||||||
if Ptr <> nil then
|
if Ptr <> nil then
|
||||||
_BlaiseFreeMem(Ptr - DA_HDR);
|
_BlaiseFreeMem(Ptr - DA_HDR);
|
||||||
Result := nil;
|
Exit(nil);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
DataSz := DA_HDR + NewLen * ElemSize;
|
DataSz := DA_HDR + NewLen * ElemSize;
|
||||||
NewBase := _BlaiseGetMem(DataSz);
|
NewBase := _BlaiseGetMem(DataSz);
|
||||||
|
|
|
||||||
|
|
@ -85,16 +85,14 @@ begin
|
||||||
begin
|
begin
|
||||||
if E^.Target = ATarget then
|
if E^.Target = ATarget then
|
||||||
begin
|
begin
|
||||||
Result := E;
|
Exit(E);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
E := E^.Next;
|
E := E^.Next;
|
||||||
end;
|
end;
|
||||||
E := PWeakEntry(_BlaiseGetMem(24));
|
E := PWeakEntry(_BlaiseGetMem(24));
|
||||||
if E = nil then
|
if E = nil then
|
||||||
begin
|
begin
|
||||||
Result := nil;
|
Exit(nil);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
E^.Target := ATarget;
|
E^.Target := ATarget;
|
||||||
E^.Slots := nil;
|
E^.Slots := nil;
|
||||||
|
|
|
||||||
|
|
@ -1050,8 +1050,7 @@ begin
|
||||||
begin
|
begin
|
||||||
libc_close(P^.PipeFd);
|
libc_close(P^.PipeFd);
|
||||||
P^.PipeFd := -1;
|
P^.PipeFd := -1;
|
||||||
Result := StrAlloc(0);
|
Exit(StrAlloc(0));
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
R := StrAlloc(Integer(N));
|
R := StrAlloc(Integer(N));
|
||||||
if R <> nil then
|
if R <> nil then
|
||||||
|
|
|
||||||
|
|
@ -310,8 +310,7 @@ begin
|
||||||
for I := 0 to High(Arr) do
|
for I := 0 to High(Arr) do
|
||||||
if Arr[I] = Str then
|
if Arr[I] = Str then
|
||||||
begin
|
begin
|
||||||
Result := I;
|
Exit(I);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
Result := -1;
|
Result := -1;
|
||||||
end;
|
end;
|
||||||
|
|
@ -328,8 +327,7 @@ begin
|
||||||
EL := LowerCase(Arr[I]);
|
EL := LowerCase(Arr[I]);
|
||||||
if EL = SL then
|
if EL = SL then
|
||||||
begin
|
begin
|
||||||
Result := I;
|
Exit(I);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
Result := -1;
|
Result := -1;
|
||||||
|
|
@ -354,8 +352,7 @@ begin
|
||||||
NewLen := Length(NewP);
|
NewLen := Length(NewP);
|
||||||
if (SLen = 0) or (OldLen = 0) then
|
if (SLen = 0) or (OldLen = 0) then
|
||||||
begin
|
begin
|
||||||
Result := S;
|
Exit(S);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
SP := PChar(S);
|
SP := PChar(S);
|
||||||
OP := PChar(OldP);
|
OP := PChar(OldP);
|
||||||
|
|
@ -421,8 +418,7 @@ var
|
||||||
begin
|
begin
|
||||||
if (Count <= 0) or (Length(S) = 0) then
|
if (Count <= 0) or (Length(S) = 0) then
|
||||||
begin
|
begin
|
||||||
Result := '';
|
Exit('');
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
SB := TStringBuilder.Create;
|
SB := TStringBuilder.Create;
|
||||||
for I := 1 to Count do
|
for I := 1 to Count do
|
||||||
|
|
@ -501,8 +497,7 @@ begin
|
||||||
Len := Length(S);
|
Len := Length(S);
|
||||||
if Len >= Width then
|
if Len >= Width then
|
||||||
begin
|
begin
|
||||||
Result := S;
|
Exit(S);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
PadCount := Width - Len;
|
PadCount := Width - Len;
|
||||||
SB := TStringBuilder.Create;
|
SB := TStringBuilder.Create;
|
||||||
|
|
@ -521,8 +516,7 @@ begin
|
||||||
Len := Length(S);
|
Len := Length(S);
|
||||||
if Len >= Width then
|
if Len >= Width then
|
||||||
begin
|
begin
|
||||||
Result := S;
|
Exit(S);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
PadCount := Width - Len;
|
PadCount := Width - Len;
|
||||||
SB := TStringBuilder.Create;
|
SB := TStringBuilder.Create;
|
||||||
|
|
@ -604,8 +598,7 @@ var
|
||||||
begin
|
begin
|
||||||
if High(Parts) < 0 then
|
if High(Parts) < 0 then
|
||||||
begin
|
begin
|
||||||
Result := '';
|
Exit('');
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
SB := TStringBuilder.Create;
|
SB := TStringBuilder.Create;
|
||||||
for I := 0 to High(Parts) do
|
for I := 0 to High(Parts) do
|
||||||
|
|
|
||||||
|
|
@ -81,8 +81,7 @@ var
|
||||||
begin
|
begin
|
||||||
if APath = '' then
|
if APath = '' then
|
||||||
begin
|
begin
|
||||||
Result := GetCurrentDir;
|
Exit(GetCurrentDir);
|
||||||
Exit;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Determine base: absolute or relative }
|
{ Determine base: absolute or relative }
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue