Intrinsics
The built-in routines: lengths and sizes, wide text, printing, program arguments, memory, exceptions and weak references.
The test assertions are on Unit testing; the guard statement on guard; the exception codes and the heap report on The runtime.
Not keywords
The intrinsic names live in an outer scope of their own, not as reserved words. A declaration of yours shadows one: a routine named print, a local named len. A C function named like one is still called through its C++ name, ::size(21); where nothing shadows it, the intrinsic answers.
- An intrinsic is always called:
LN := len;is SM0423, "'len' is an intrinsic: it is called, never used as a value". freemem,setlength,create,destroy,raise,raisecode,printandprintlnare statements; used as a value they are SM0408, "'freemem' is a statement, not a value".getmemandresizememare both expressions and statements.- A wrong argument is SM0409, naming what the intrinsic takes:
len(5)is "'len' takes (string, wstring or array)",size()"'size' takes (a type)". - Each argument takes the exact type the runtime takes, with no hidden conversion: the index of
paramstrand the code ofraisecodeare int32; the size ofgetmemandresizememand the length ofsetlengthare int64. An int64 index is SM0409, "'paramstr' takes (int32)". - A routine of your own that shadows
sizetakes no type:size(int32)there is SM0411.
Length and size
len(x)is an int64: the bytes of a string, the wide characters of a wstring, the elements of a dynamic or static array.lenof a string literal counts its characters, never a terminator:len("four")is 4,len("")0,len("a\tb")3, and joined literals are one text.size(T)is the byte size of a type, an int64 constant: a builtin, a pointer, a record, an array type or a C/C++ type. Text that is plainly a type is read as one; a lone name must name a type, sosize(LN)of a variable is SM0410, "size needs a type, got the value 'LN'".
module exe intrinsics_values;
type
TPoint = record
X: int32;
Y: int32;
end;
var
LS: string = "hello";
LW: wstring = L"caf\u00e9";
LA: array of int32;
LF: array[0..3] of int32;
LP: ptr to int32;
LC: ptr to const char;
begin
setlength(LA, 3);
println("len {} {} {} {}", len(LS), len(LW), len(LA), len(LF));
println("literal {} {}", len("four"), len("a\tb"));
println("size {} {} {}", size(int64), size(TPoint), size(array[0..3] of int32));
println("utf8 {} bytes {}", utf8(LW), len(utf8(LW)));
print("no newline, ");
println("then one");
println("width [{:>4}] [{:04}]", 42, 42);
println("nil pointer {} nil text {}", LP, LC);
LF[1] := 7;
println("array {}", LF);
end.
len 5 4 3 4
literal 4 3
size 8 8 16
utf8 café bytes 5
no newline, then one
width [ 42] [0042]
nil pointer 0x0 nil text nil
array [0, 7, 0, 0]
[Heap] Allocs: 0, Frees: 0, Leaked: 0
Text and printing
utf8(W)converts a wstring to a string in UTF-8:L"caf\u00e9"has 4 wide characters, its UTF-8 text 5 bytes.print(f, ...)andprintln(f, ...)write std::format text,printlnwith a newline:{:>4}right-aligns,{:04}pads with zeros. The format string is std::format's, checked when the program is built: it is a string literal or a string const holding one, more{}than arguments is SM0502, and any other format (a string variable) is SM0500.- Every argument prints by its PaskalCPP type: a wchar or wstring as UTF-8 text (
int32(W)gives the number), aptr to charas its text (nil printsnil), any other pointer as its address (nil prints0x0), an array element by element, text elements quoted. - A record, an object or an overlay cannot be printed: SM0425, "'TP' cannot be printed: print the fields of a record, object or overlay". Neither can an overload set's name or a method (no single address), nor a C/C++ value with no formatter, reported at the argument.
Program arguments
paramcount() is the number of program arguments (int32) and paramstr(i) argument i as a string: 1-based, 0 is the program itself, "" out of range. The arguments come after -- on the pcpp command line: see The pcpp command.
Memory
getmem(n)gives n bytes (nil for 0),resizemem(p, n)resizes a block and keeps its bytes (from nil it allocates, to 0 it frees),freemem(p)frees it.setlength(v, n)sets the length of a dynamic array or a string variable: growing adds zeroed elements, shrinking drops the tail. A negative length raises code 12, "negative length -1", and leaves the variable as it was.create(p)builds a zeroed record, overlay or C/C++ value behind the pointer p;destroy(p)frees it and sets p to nil. Any other argument is SM0409, "'create' takes (record, overlay or C/C++ pointer variable)".- An object is never built so:
createof a pointer to an object is SM0361, namingown T(...)orref T(...), the owners that hold an object on the heap and free it (Objects). - The debug build's heap report counts each
createas an alloc and eachdestroyas a free; a create never destroyed is leaked and named by its line.
module exe intrinsics_memory;
type
TPoint = record
X: int32;
Y: int32;
end;
var
LP: ptr to TPoint;
LKept: ptr to TPoint;
LI: ptr to int32;
LA: array of int32;
begin
create(LP);
println("zeroed {} {}", LP^.X, LP^.Y);
destroy(LP);
println("nil after destroy {}", LP = nil);
create(LKept);
LI := ptr to int32(getmem(16));
LI^ := 7;
LI := ptr to int32(resizemem(LI, 64));
println("resized keeps {}", LI^);
freemem(LI);
guard
setlength(LA, -1);
except
println("{} {}", exccode(), excmsg());
end;
guard
raisecode(42, "answer");
except
println("{} {}", exccode(), excmsg());
end;
println("end of body");
end.
zeroed 0 0
nil after destroy true
resized keeps 7
12 negative length -1
42 answer
end of body
[Heap] Allocs: 3, Frees: 2, Leaked: 1
[Heap] Leaked object created at intrinsics_memory.pcpp(53)
Exceptions
raise(m)raises code 1 with the text m,raisecode(c, m)code c. A guard's except reads them withexccode()andexcmsg(); a raise reaches the nearest guard through routine calls, and code 0 is still caught.exccode()andexcmsg()exist only inside an except body: anywhere else they are SM0615.- A raise no guard catches ends the program with "unhandled exception <code>: <text>" on stderr, after what it printed, and exit code 1: see Unhandled exceptions.
Weak references
alive(w) is true while the object a weak T watches still exists; lock(w) gives a ref T holding it, nil once it is gone. Their argument is a weak: alive of a ref is SM0409, "'alive' takes (weak T)".