refactor(rtl): drop legacy platform aliases, derive constants from target

Remove sLineBreak (Delphi alias for LineEnding) and PathDelim (Delphi
alias for DirectorySeparator).  Blaise keeps exactly three platform
constants: LineEnding, DirectorySeparator, PathSeparator.

Platform constant values are now derived from GTarget (the compilation
target) via TargetLineEnding/TargetDirectorySeparator/TargetPathSeparator
in blaise.codegen.target, so cross-compilation produces the correct
values without conditional compilation.
This commit is contained in:
Graeme Geldenhuys 2026-06-05 17:01:04 +01:00
parent fe63b2559d
commit 0c5910195c
7 changed files with 104 additions and 32 deletions

View file

@ -294,6 +294,7 @@ begin
SearchPaths.Free;
Exit;
end;
GTarget := Target;
end
else if (Arg = '--help') or (Arg = '-h') then
begin

View file

@ -60,6 +60,14 @@ function TargetName(const ATarget: TTargetDesc): string;
{ True when the native backend can actually generate code for this target. }
function TargetHasNativeBackend(const ATarget: TTargetDesc): Boolean;
{ Platform constants derived from the target OS. }
function TargetLineEnding(const ATarget: TTargetDesc): string;
function TargetDirectorySeparator(const ATarget: TTargetDesc): string;
function TargetPathSeparator(const ATarget: TTargetDesc): string;
var
GTarget: TTargetDesc;
implementation
uses
@ -136,4 +144,34 @@ begin
Result := (ATarget.OS = osLinux) and (ATarget.CPU = cpuX86_64);
end;
function TargetLineEnding(const ATarget: TTargetDesc): string;
begin
case ATarget.OS of
osWindows: Result := #13#10;
else
Result := #10;
end;
end;
function TargetDirectorySeparator(const ATarget: TTargetDesc): string;
begin
case ATarget.OS of
osWindows: Result := '\';
else
Result := '/';
end;
end;
function TargetPathSeparator(const ATarget: TTargetDesc): string;
begin
case ATarget.OS of
osWindows: Result := ';';
else
Result := ':';
end;
end;
initialization
GTarget := HostTarget;
end.

View file

@ -560,6 +560,9 @@ function MangleUnitPrefix(const AUnitName: string): string;
implementation
uses
blaise.codegen.target;
{ ------------------------------------------------------------------ }
{ TUsesChainProvider }
{ ------------------------------------------------------------------ }
@ -1479,19 +1482,17 @@ begin
Sym.ConstValue := 2147483647;
Define(Sym);
{ System string/path constants defined in system.pas; pre-seeded here
so they resolve even before system.pas is loaded as a unit. }
{ Platform constants values derived from the compilation target (GTarget).
Defined in system.pas; pre-seeded here so they resolve even before
system.pas is loaded as a unit. }
Sym := TSymbol.Create('LineEnding', skConstant, FTypeString);
Sym.ConstString := #10;
Define(Sym);
Sym := TSymbol.Create('sLineBreak', skConstant, FTypeString);
Sym.ConstString := #10;
Sym.ConstString := TargetLineEnding(GTarget);
Define(Sym);
Sym := TSymbol.Create('DirectorySeparator', skConstant, FTypeString);
Sym.ConstString := '/';
Sym.ConstString := TargetDirectorySeparator(GTarget);
Define(Sym);
Sym := TSymbol.Create('PathSeparator', skConstant, FTypeString);
Sym.ConstString := ':';
Sym.ConstString := TargetPathSeparator(GTarget);
Define(Sym);
{ Built-in I/O procedures }

View file

@ -45,7 +45,7 @@ type
procedure TestRun_SetCurrentDir_ChangesDir;
procedure TestRun_ExtractFileExt_ReturnsExt;
procedure TestRun_BoolToStr_TrueAndFalse;
procedure TestRun_SysUtils_LineEndingConst;
procedure TestRun_PlatformConstants;
procedure TestRun_GetCurrentDir_ReturnsNonEmpty;
end;
@ -533,13 +533,13 @@ const
end.
''';
SrcLineEndingConst =
SrcPlatformConstants =
'''
program P;
uses SysUtils;
begin
WriteLn(sLineBreak = #10);
WriteLn(LineEnding = #10)
WriteLn(LineEnding = #10);
WriteLn(DirectorySeparator = '/');
WriteLn(PathSeparator = ':')
end.
''';
@ -647,20 +647,21 @@ begin
end;
end;
procedure TE2ESysUtilsTests.TestRun_SysUtils_LineEndingConst;
procedure TE2ESysUtilsTests.TestRun_PlatformConstants;
var
Output: string;
RCode: Integer;
Lines: TStringList;
begin
if not ToolchainAvailable then begin Ignore('toolchain unavailable'); Exit; end;
AssertTrue('compile+run', CompileAndRunWithRTL(SrcLineEndingConst, Output, RCode));
AssertTrue('compile+run', CompileAndRunWithRTL(SrcPlatformConstants, Output, RCode));
AssertEquals('exit code 0', 0, RCode);
Lines := TStringList.Create;
try
Lines.Text := Trim(Output);
AssertEquals('sLineBreak = #10', '1', Lines.Strings[0]);
AssertEquals('LineEnding = #10', '1', Lines.Strings[1]);
AssertEquals('LineEnding = #10', '1', Lines.Strings[0]);
AssertEquals('DirectorySeparator = /', '1', Lines.Strings[1]);
AssertEquals('PathSeparator = :', '1', Lines.Strings[2]);
finally
Lines.Free;
end;

View file

@ -3135,3 +3135,40 @@ string `TFoo<>` in `TFieldAccessExpr.RecordName`. The semantic pass — in
which replaces the sentinel with the full concrete type name taken from
`ResolvedLhsType.Name`. Subsequent semantic analysis proceeds identically to
an explicit constructor call.
== Platform constants — one name per concept
Delphi and FPC carry multiple aliases for the same platform constant:
* `LineEnding` (FPC), `sLineBreak` (Delphi), and sometimes `LineBreak`
* `DirectorySeparator` (both), `PathDelim` (Delphi SysUtils alias)
* `PathSeparator` (both) — no alias, the one exception
Blaise retains exactly three names, one per concept:
[cols="1,1,1"]
|===
| Constant | POSIX value | Windows value
| `LineEnding`
| `#10`
| `#13#10`
| `DirectorySeparator`
| `/`
| `\`
| `PathSeparator`
| `:`
| `;`
|===
*Dropped:* `sLineBreak`, `PathDelim`. They were Delphi compatibility aliases
that added no meaning — two names for the same value is a maintenance trap, not
backwards compatibility.
All three constants are defined in `system.pas` and pre-seeded as compiler
built-ins in `RegisterBuiltins`. Their values are derived from the compilation
target (`GTarget` in `blaise.codegen.target`), so cross-compilation to a
different OS produces the correct constants without conditional compilation.

View file

@ -87,17 +87,14 @@ type
{ ------------------------------------------------------------------ }
const
{ Line ending for the current platform. POSIX = #10, Windows = #13#10.
Blaise currently targets POSIX only. }
{ Line ending for the current platform. POSIX = #10, Windows = #13#10.
Set at compile time based on the target platform. }
LineEnding = #10;
{ Delphi compatibility alias for LineEnding. }
sLineBreak = LineEnding;
{ Directory separator character. }
{ Directory separator character. POSIX = '/', Windows = '\'. }
DirectorySeparator = '/';
{ PATH environment variable separator. }
{ PATH environment variable separator. POSIX = ':', Windows = ';'. }
PathSeparator = ':';
{ ------------------------------------------------------------------ }

View file

@ -10,11 +10,12 @@ unit SysUtils;
// Blaise RTL SysUtils unit.
//
// Provides the Exception base class, PathDelim (Delphi compat alias for
// DirectorySeparator), and the BoolToStr helper.
// Provides the Exception base class and the BoolToStr helper.
//
// LineEnding, sLineBreak, DirectorySeparator, and PathSeparator are defined
// in system.pas they are platform fundamentals, not SysUtils concerns.
// Platform constants (LineEnding, DirectorySeparator, PathSeparator) are
// defined in system.pas they are platform fundamentals, not SysUtils
// concerns. Blaise does not carry the Delphi/FPC legacy aliases
// (sLineBreak, PathDelim).
//
// Functions that are already compiler built-ins (FileExists, DeleteFile,
// RenameFile, SetCurrentDir, ExtractFileExt, IntToStr, StrToInt, Format,
@ -24,10 +25,6 @@ unit SysUtils;
interface
const
{ Delphi compatibility alias for system.DirectorySeparator. }
PathDelim = '/';
type
Exception = class
FMessage: string;