Expand/Shrink

Glossary

Let me know of anything else that should be clarified here, or anything that needs further simplification for those completely new to computers and programming, obviously within reason and assuming they have access to several other sources of educational material. Of particular importance are any words and phrases used elsewhere in this document and/or the sources of Phix that might be slightly ambiguous.

abstraction The simple act of giving something a clear, meaningful, and intuitive name. Often this term is explained in the most baroque, confusing, and unhelpful way possible, especially layers within layers to hide and protect things. I would argue it is all about careful choices that avoid distraction and let you focus on other matters, and the real benefits are not usually immediate but in months or years from now.

Now, if you asked me where I’d been, and I said "a building", then at best you might assume I meant a building site, maybe to check on progress or some kind of foundation or topping out ceremony. You would not assume I meant "a restaurant" or whatever. Clearly, "building" is a terrible abstraction, with little valid use outside construction, insurance, and planning, or non-abstract uses such as "clear the building". There are good and useful abstractions, bad abstractions, and programming abstractions.

There is a subtly different use of "abstract" in classes: just as you might have a cat or dog but cannot actually have a pet "animal", you cannot create an instance of an abstract class but can create instances of non-abstract subclasses or extensions of an abstract class. Consider it an "incomplete specification". Of course polymorphism requires an abstraction but that should still be as meaningful as possible, for instance the price of an asset rather than a "thing", or perhaps to make it clear you simply cannot get the length of a weight or a colour or any of those of each other.

Obviously within a class, "this" is almost not an abstraction, whereas "this" in JavaScript is a ripe source of bugs and the subject of many a stupid trick to restore its magical meaningless status. I might accept a capture for later use such as "let restaurant = this;", but "that = this" is just drivel, unless you can do the right thing with peanut butter, dying flowers, Matt Damon on a bicycle, hyenas, and India. As disparate as those are, I can effortlessly invent meaningful abstractions for them: foods, emotives, film scenes, animals, countries.
If an abstraction cannot separate any of them, then it is truly not just abysmal, but obstructively unhelpful.
The only routines that can do anything useful without the slightest idea what/which it is, are almost inevitably so completely and utterly banal and trivial that they are indeed completely and utterly pointless themselves.
Even those few that get close, such as print() and sort(), are likely to fail miserably should you throw them structs/classes or mpfr variables, as will throwing such at dictionaries and priority queues, at least that is without also providing a suitable comparison routine or limiting classes to those that implement a specific printable or comparable interface, with hopefully the latter not so meaninglessly generic it will happily let you compare (say) emotives, colours, and counties - the only half-meaningful ordering of cheerful, chestnut, and chinese is alphabetical, and certainly not whatever enum they ended up with, though I guess {category,enum} might be ok.
Not a fan, be I, of deliberately meaningless abstraction, but should you be, you have my heartfelt pity.

“The purpose of abstracting is not to be vague, but to create a new semantic level in which one can be absolutely precise.” - Edsger W. Dijkstra
allocation Can mean reserving a block of memory (see allocate()) or a register.
assignment The simple act of storing a value in a variable.
atom A variable that can hold an integer or a floating point value.
BOM A Byte Order Mark is a special byte sequence at the start of a text file which indicates UTF8, UTF16LE/BE, or UTF32 [etc]. See edita.exw(or edix.exw)/readFile() and ptok.e/loadFile() for examples of use, and utfconv for some of the more common values.
calling convention Most entry points in the run-time VM (virtual machine) require parameters in specific registers and precise stack content. These are documented in the sources (builtins\VM).
Personally, I use builtins\VM\pHeap.e\::pGetMem as my go-to place for a quick recap on the various operating-system-api-specific calling conventions.
closure See closures in Other Libraries/programming.
compilation In Phix, this specifically means creating an executable file. See also interpretation.
compiler directive A command line option or programming statement that does not directly generate code but instead instructs the compiler how to subsequently generate code.
Examples include "with trace", "-c", and "format".
constant Technically in Phix a constant is just a normal variable that you are not allowed to modify post-declaration.
In C-based languages, parameters are often "const" to prevent accidental modification with catastrophic consequences,
however Phix relies on copy-on-write semantics to prevent any such dramatic consequences in the first place.
Note that "const" in a routine scope in JavaScript often reconstructs it one every invocation, whereas Phix (and for that matter Phix code transpiled to JavaScript) tries a bit harder to construct things only once.
delegate Something (or someone) that does something on another’s behalf. You might, for instance, decide that shapes are part of the business logic, but actually drawing them is part of the gui subsystem, hence each shape might have a reference to a fill delegate that it can instruct to draw the background, without ever actually knowing where to get it or even what it is actually called. From the shape’s perspective, it is just a single field it holds, and knows as little about it as possible. Perfectly applicable to all programming paradigms, not just OOP (except perhaps functional, since that’s not allowed to have side effects, tee hee).
delta debugging A very efficient technique for locating a recently introduced bug. Let me document what just happened while I remember it: I noticed the fonts on the gCanvas demo were all off, in fact all bold with no normal or italics. I had a 3 month old xpGUI3.e (which was the second thing I tried) on which they still worked, however a source code diff showed ~2,600 differences but nothing stood out as the obvious culprit. With a heavy sight of resignation I set to work and wasted maybe an hour and a half making small edits to bring the old version more up-to-date and testing regularly, before realising I really should be using delta debugging (in my defense I originally assumed I wouldn’t have the backups I needed any more). I opened up the demo\xpGUI\backups directory and scrolled to the end to see what I still had, and in less that quarter of an hour had selected and tested as replacements for the "include xpGUI.e" line:

--include backup\xpGUI.5875.e -- good fonts
--include backup\xpGUI.5877.e -- good fonts
--include backup\xpGUI.5878.e -- duff fonts (& background)
--include backup\xpGUI.5881.e -- duff fonts (& background)
--include backup\xpGUI.5890.e -- duff fonts
--include backup\xpGUI.5909.e -- duff fonts
--include backup\xpGUI.5960.e -- duff
--include backup\xpGUI.5965.e -- duff fonts

The first one I picked, 5960, about two weeks old, had a compiler error. Using the date/times, on the basis that four edits in the space of two minutes were probably all fixing compiler errors, I tried 5965. Jump back another week or so and 5909 is also wrong, ditto 5890, one more hop and 5875 worked. With no significant thought/effort involved I binary chopped to 5877/8, which differed in just 36 places, a little over 1% of the original rather daunting task, and from there the answer was pretty clear: I had created a compatible display context to eliminate flickering, but completely forgotten to copy in the fonts.
Should you ever find yourself in a similar situation, with an old version that works and a new one that doesn’t, delta debugging is an often incredibly efficient and pretty darn easy way of eliminating the vast majority of potential culprits.
Edix/xpEditer create backups specifically designed to assist with delta debugging, though I recommend regularly renaming the backup directory(/ies) to backup.date and permanently deleting them 3-6 months later.
dll hell Historically a very real problem for sysadmins and service desk staff, but never had to be. The problem is utilising say "somelib.dll" and getting version conflicts, especially when installing some other application clobbers that file (in a central location) with something incompatible. Can also happen when you want to run two versions of your own application side-by-side. Compounded (in other programming languages) by load-time resolution from details stored in a resource section, which many programmers (myself included) find rather cryptic, and luckily phix does not have/need. A similar issue can be caused by 32/64 bit, though Windows has C:\Windows\System32\ for 64-bit dlls and C:\Windows\SysWOW64\ for 32-bit dlls, and Linux something similar, but less confusing.

Some suggested ways to avoid these kinds of issues are:
  • Put the dll/so in the application directory, and hope it looks there first (flakey on Linux)
  • Name the dll/so appropriately, eg phix ships with builtins\bz32.dll and builtins\bz64.dll
  • Put then in separate directories, eg phix ships with demo\pGUI\win32\ and demo\pGUI\win64\
  • Use the version in the name or path, eg somelib.1.0.4.dll and|or somelib.1.12.3.dll
Changing the filename only tends to work for single files that don’t load anything else, unless all properly rebuilt.
Using directories typically needs a chdir() in before the open_dll() and an undo/back out after.
While the last option is clearly preferred on Linux, it also has symlinks to help you quickly and completely knobble it.
[Strong be the Force in this one to use freshly built latest, Master Luke. Reverse polarity of symlink must we, to reach ancients... nb: not advice ! ]
Should you deliberately lie about the version when renaming a dll/so, you fully deserve every bit of pain you get.
Note I often use the term dll to refer to both Windows .dll files and Linux .so, since they are effectively the same thing.

While other programming languages rely on the operating system to resolve everything at load-time, via cryptic constructs such as got/plt, and should it go wrong you are totally hosed, instead phix uses open_dll() and friends, in your code, where you do have the opportunity to catch any errors and try something else, and indeed initially constuct paths and filenames dynamically when desired.
In truth, phix is perfectly capable of load time resolution, but reserves that for really critical things such as LoadLibrary and GetProcAddress or dlopen and dlsym, for which there is no potential conflict and you have no say of any kind over either the name or the location of those specific things anyway.
While I may regularly ridicule the slow load times of many an executable created from other programming languages, in this one particular aspect an extra few milliseconds (if even that) is totally worth it, and almost completely insignificant.
In other words, Phix/open_dll() can be a smidgen slower than load-time resolution, but I defy you to even measure that when resolving less than a hundred globals in something being loaded less than a hundred times. One known exception is GTK, which in having at least 21,774 public entry points is or can be a tad slow to launch, esp the first time. Then again, I don’t have a proper load-time resolution version of that to compare against, and that may or may not be just as slow.

The main downside of open_dll() is there is no one true way to use it that will necessarily solve all such potential issues.
[Then again, there is absolutely no one true way to use cryptic resource section constructs to achieve that either...]
Probably the most tested (relevant) use of open_dll() is demo\pGUI\pGUI.e and tbh not quite as bad as I remember it.
The simplest one I can point you at is builtins\LiteZip.e though I only ever found a 32-bit windows dll for that.
Least tested would be demo\pSQLite\pSQLite.e whereas builtins\mpfr.e would easily be the messiest.
Ideally after navigating to a dll/so in a file manager the version/bitsize should be obvious, not that I always manage that.
Should you open a dll/so with filedump.exw (or on Windows dependency walker/dependencies) it will be obvious what bitsize it is.
dword-sequence Specifically used to indicate a sequence which is not a string but (on 32-bit) 4 bytes per element. On 64-bit, they are (of course) technically qword-sequences, 8 bytes per element, but are still usually referred to as dword-sequences. You cannot natively declare a variable as dword-sequence-but-not-string, however the following user defined type has the same effect, and in fact [x]pGUI.e has a very similar private dword_seq type.

    type dword_sequence(object o)
        return (sequence(o) and not string(o))
    end type

You can (sometimes) alternatively use a #isginfo{} statement to instruct the compiler to perform an equivalent compile-time check.
dynamic typing Otherwise known as duck typing, as in "if it walks like a duck and it quacks like a duck, then it must be a duck". Programming languages are generally either statically typed (eg C, Java) or dynamically typed (eg JavaScript, Python), though other type systems exist, such as manifest, inferred, nominal, and structural, and even abstract, dependent, flow-sensitive, gradual, intersection, latent, refinement, substructural, unique, and session!! Duck typing is often claimed to enable easier code reuse, but I have never noticed a case of that, at least that is not compared to Phix, thanks mainly to the more cautious and selective use of object.

Phix is more of a hybrid: if you have integer i, then i is a strongly statically typed variable, whereas some object o is dynamically typed, unless the compiler manages to apply type inference and determine it is only ever assigned one or some subset of the standard builtin types.
The biggest problem imo with most dynamically typed languages is the complete failure to catch, say "fleg = false" when you meant to set "flag", which can be very hard to spot and fix.
The biggest problem imo with (some) statically typed languages is implicit type coercion, whereby eg 1/2 is 0, whereas in Phix you would need to explicitly code floor(1/2) to get that 0, rather than 0.5.
era The effective return address, a low-level implementation detail of how the debugger actually works.

Normally, in day-to-day use of Phix, the era is correctly translated to a hll line number and is of no concern to you.

Quite often the era is just the same as a usual return address. However, suppose that opApnd invokes opDealloc, and something goes wrong in the latter. Rather than using the real return address into the middle of opApnd, we want an era that can be converted to a hll line number. Or perhaps during the statement s[1][2][3][4][5][6] = x, we might find that s[1][2][3][4] is 0, and need to issue an "attempt to subscript an atom" error when 4 out of 6 subscripts have been processed (popped from the stack). While it may have little or no impact on runtime performance, correctly maintaining an era (propagating it through nested calls) may consume a not entirely insignificant amount of effort when modifying the low-level back end. If an error message shows line number -1, your first suspicion should be that some low level code is not getting the era quite right.

Note that era often have a -1 applied. Consider the following (fictional) listing fragment

                    112     n = <lexpr>
                                ...
                                call :%pStoreFlt        ;#004020145
                    113     s = t
                                add [ebx+esi*4-16],1    ;#00402014A
            

ie pStoreFlt preserves all registers, and the first instruction for line 113, assuming the compiler knows that [t] is already in esi and that t is not unassigned, is to increase the reference count on it. If we catch an exception at #402014A, we want to point the user at line 113, however if there is a problem in pStoreFlt, then rather than use the actual return address of #402014A we use an era of #4020149, to point the error message at line 112. Naturally the above instructions would normally work just fine, but if n/t/esi have been corrupted somehow, we need to say something.

All memory allocations also have an era stored against them for use in memory leak checking and suchlike.
fail fast The subtle art of making your programs brittle (locally) as a means of making them robust (overall).

It is a "learn from your mistakes without reproach" mindset whereby any irritation or annoyance there is yet another bug is completely overwhelmed by the joy of having found it, especially before your customers and when under minimal pressure. It is the complete opposite of "let’s catch all exceptions and quietly ignore them", and somewhat rather more akin to "design by contract", marked by plentiful assertions and explicit crash instructions to ensure everything is spot-on. The main aim is to get errors to occur as soon as and as close as possible to the original mistake in the source code, rather than in some completely unrelated and potentially highly misleading statement miles away from it.
false positives When an antivirus(AV) program proclaims there is a problem in a file, but in fact there is nothing wrong with it. The ever increasing rate of malware production has forced AV makers to adopt "heuristic" and "reputation" based mechanisms, with an unavoidable hike in false positives, and is the lastest bane of many a developer. One in particular has caused me problems: Avast/evo-gen. The good news is that once a program "matures", or reaches a certain size, the problem stops. Obviously I report these as and when I see fit, but response times are painfully slow. While submission may or may not achieve miracles, not doing so almost guarantees that things will simply never get fixed. See also Recommended Tools for links to several on-line scanners, which obviously would not exist if all or even any AV were perfect.

Some of the (smaller) included demos have a trailing "--/**/include ..\test\t02parms.exw" or similar as that can make some false positives go away. My hope is that any such measures prove to be temporary.
float Specifically used to indicate an atom which is not an integer but (on 32-bit) a 64 bit floating point value, ranging from approximately -1.79e308 to +1.79e308 with around 15 decimal digits of precision. On 64-bit, floats are 80-bit (tbyte), ranging from roughly -1.18e4932 to +1.18e4932 with about 19 decimal digits of precision. You cannot natively declare a variable as float-but-not-integer, however the following user defined type has the same effect:

    type float(object o)
        return (atom(o) and not integer(o))
    end type

You can (sometimes) alternatively use a #isginfo{} statement to instruct the compiler to perform an equivalent compile-time check. Note however that the result of 1.5+1.5 is the integer 3, not the float 3.0, hence the above type is highly likely to cause a wholly unnecessary type check failure at some point and rather rudely terminate the application.
Greek letters Mathematical papers are fond of using greek letters, so here is a quick lookup. Use (say) &alpha; for α and &Alpha; for Α.
You can also use the unicode points 0x391 .. 0x3A9 but not 0x3A2 for uppercase and 0x3B1 .. 0x3C9 for lowercase. Note that 0x3C2 is used for ς (&sigmaf;) instead of σ (&sigma;) at the end of a word, which is why there is no 0x3A2.
&alpha: αΑ &beta: βΒ &gamma: γΓ &delta: δΔ &epsilon: εΕ &zeta: ζΖ &eta: ηΗ &theta: θΘ &iota: ιΙ &kappa: κΚ &lambda: λΛ &mu: μΜ &nu: νΝ &xi: ξΞ &omicron: οΟ &pi: πΠ &rho: ρΡ &sigma: σςΣ &tau: τΤ &upsilon: υΥ &phi: φΦ &chi: χΧ &psi: ψΨ &omega: ωΩ.   Other useful letters/symbols include:
&not: ¬ &plusmn: ± &middot: · &rarr: → &rArr: ⇒ &hArr: ⇔ &forall: ∀ &part: ∂ (partial) &exist: ∃ (exists) &empty: ∅ (emptyset) &nabla: ∇ &isin: ∈ (in) &notin: ∉ &prod: ∏ &sum: ∑ &radic: √ &infin: ∞ &and: ∧ &or: ∨ &cap: ∩ (intersection) &cup: ∪ (union) &int: ∫ (integral/integrate) &asymp: ≈ (approx) &ne: ≠ &equiv: ≡ &le: ≤ (leq) &ge: ≥ (geq) &sub: ⊂ (subset) &sup: ⊃ (superset) &deg: ° &times: × &lfloor: ⌊ &rfloor: ⌋ &lceil: ⌈ &rceil: ⌉ &varepsilon: ϵ &vartheta: ϑ (curly theta) &varpi: ϖ &varrho: ϱ &varsigma: ς (same as &sigmaf;) &varphi: ϕ
Gregorian calendar While (most) Catholic countries adopted the Gregorian calendar in 1582, Protestant countries (including Great Britain and its colonies) did not adopt it until 1752, and others even later: Turkey in 1926, and Saudi Arabia, astonishingly, 2016.
gvar Internal compiler/back-end term. Constants, file-level, global, and any unnamed temporary variables in top-level code are all gvars. They are stored in a static table at the start of the data section, see pemit2.e/filedump.exw for more details. See also/contrast with tvar.
integer A variable that (on 32-bit) can hold a 31-bit signed integer value in the range -1073741824..1073741823 (#C0000000..#3FFFFFFF).
On 64-bit, the 63-bit signed integer range is -4611686018427387904..4611686018427387903 (#C000000000000000..#3FFFFFFFFFFFFFFF).
Note that "int" in other languages is usually 32/64 bit, which (may) need to use an atom in Phix instead.
interpretation Running a program "from source". Technically speaking, interpretation in Phix is in fact compilation, but without creating an executable file. Some other steps are also omitted, in particular populating the symbol table with actual names instead of ternary tree indexes, unless there is an error that needs reporting, and the re-use of some builtin routines that are already available as part of the compiler, though that practice never achieved any mearurable gain, is getting quite rare, and should be gone completely in 2.x. In many cases an interpreted program runs just as fast as a compiled one, quite unlike other interpreted programming languages.
isginfo Not recommended for general use. An internal compile-time type check. Statements of the form #isginfo{name,0b0101,MIN,MAX,integer,-2} are checked at the end of compilation in an attempt to ensure a variable is being assigned the right kinds of things and will require the minimum of run-time type-checks. They were introduced to streamline the compiler development, where they are still quite widely used, but proved less than spectacularly successful. All too often the only sensible way to create a new statement is to copy an existing one and then copy the actual details from the resulting compiler error message. They can often trigger in subtle and irrelevant ways and can be extremely difficult to debug. That said, sometimes the compiler ones do indeed catch stupid coding errors in a fairly helpful and immediate manner. There is also a full (t49, 800+ lines) test file, run as part of p -test, dedicated entirely to #isginfo{}. By the time you know enough to use these in anger, you won’t need me to tell you what each of the individual fields mean, and if you have to ask you’re probably not ready.
lint The command line -lint option is not formally supported. It performs a few extra checks which may be helpful, but if anything untoward happens my advice is simply going to be "well, don't use -lint then".

When you compile a program, some extra analysis takes place which gives scope for a few more error messages. By far the biggest use of the internal flag behind the -lint option is to make an interpret perform the same checks as a compile, and obviously that is not massively helpful - you may as well just use -c instead.

Otherwise, -lint causes additional warnings when files are auto-included, routines are implicitly forward referenced, or when functions may modify something being modified on return, and disables "without warning". Occasionally implicit forward references can go wrong (especially wrt local/global assumptions) and adding the appropriate include/explicit forward declarations can help. Sometimes a statement such as "table[i] = modify_table()" is going to use an outdated index when the function call returns, and of course a misjudged "without warning" may be hiding something you really ought to see.

More often than not, "fixing" such messages will achieve absolutely nothing. Wasting time getting a "clean lint" is unlikely to be very productive, except for ensuring that the next time you use -lint it only shows new findings.
MCVE Minimal complete verifiable example. The smallest thing that exhibits a problem, which should hopefully make it much easier to read and understand, build, debug, and otherwise experiment with, than the equivalent issue buried somewhere deep inside a much larger (/the original) program. Putting in the extra effort to make an mcve will very likely be worthwhile and lead to getting an answer much quicker when asking for help. It is also acceptable to ask first and then start working on creating an mcve, though you might earn a bit of a reputation should you do that every time. Many a programmer has solved an issue without anyone else’s help just by writing an mcve, and doing so often eliminates obvious mistakes and omissions, without publicly embarassing yourself.
namespace A namespace allows the programmer to explicitly specify in which source file, or source sub-tree, a particular identifier is declared. This is most useful when a particular global identifier occurs in more than one file, but might just be there to clarify intent. Traditionally a namespace is declared using "as <namespace>" on an include statement, but it can also be declared at the start of the included file. Note that a namespace is always deemed local rather than global and may therefore require a source file to be re-included by any source files that want to qualify a reference with it. See scope.
naming is hard Shorthand for: The code I write is complete drivel, I need therapy.
OOP Object oriented programming. A mechanism for making source code increasingly difficult and eventually impossible to understand. See main entry.
p2js violation Phix has copy-on-write semantics whereas JavaScript has pass-by-sharing semantics. In truth neither rely on that as much as we might think they do, so with js effectively disables both and that way allows the same source code to run both on the desktop and in a web browser. When desktop/Phix detects an internal clone has been triggered as part of its copy-on-write semantics it terminates with a fatal "p2js violation" error, forcing the introduction of an appropriate deep_copy() or other means of getting the program to work. Note that p2js.exw itself does nothing in this regard, just relies on that sort of debugging/testing having previously happened. Occasionally also referred to as a cow-violation (where cow stands for copy-on-write).
qword-sequence See dword-sequence. The use of qword-sequence implies a 64-bit-only situation.
RAII Resource Acquisition Is Instantiation, aka grab absolutely everything you might ever need, even if you never need it, use as much memory as you can as soon as possible, ideally making multiple copies of things you would only ever need one of, connect to some backwater place in the Australian outback, right now, just on the offchance that’ll be the first place you need to look, and otherwise generally make your program startup as slow as feasibly possible. These days computers are so fast no-one cares if your application takes an extra 20 minutes to half an hour to start, and if the previous version used to start instantly, rest assured all your users will genuinely be thinking "this is great" and never complaining. See also reify.
register In a 32-bit x86 application, one of eight temporary storage places in the heart of the physical CPU (Central Processing Unit), or 16 in a 64-bit X64 application. Careful selection of these ("register allocation") can significantly improve performance.

The existing method (a naive, most recently used affair, in pilx86.e) is adequate rather than exceptional and is overdue for a complete rewrite (to a suitably lightweight linear scan or something similar, but definitely not graph colouring).

There are also several floating-point and SSE (etc) registers, however the use of an unqualified "register" usually means one of the integer-only registers in the main CPU.
reify Bizzare word used by the oop-brainwashed when making one of their abstract abominations "more real", whatever that actually means. See also concrete instance instantiation, RAII. Concrete used to be such a lovely down-to-earth word, but now whenever I see it my brain goes into self-protection mode and all it will let me think of is "Is it Con-Crete or Conk-Reet?"...
scope The term scope is a general concept used when describing how the compiler resolves references to identifiers. In most cases it is simple and intuitive, involving nothing more than plain old common sense. It may be helpful to think of "in scope" as simply meaning "does not cause a compilation error".

The scope of an identifier is where, in terms of which lines of code, it can be referenced.
The scope of a variable starts at the point of declaration and ends at the end of the declaring block, routine, file, or in the case of globals, on the last line of the main file.
The scope of a routine is anywhere in the file it is declared in, or in the case of global routines, anywhere in the entire application.
Namespaces and explicit forward declarations can be used to further qualify and clarify matters. See scope. NB: namespaces are not pwa/p2js-compatible.
sequence A variable-length array of elements, which can be integer, float, string, or a nested sub-sequence, to any depth. A variable declared as sequence can also hold a string but not vice versa.
singleton An outrageously stupid concept from the cloud-cuckoo land of the OOP-infected. I might accept that you may have little choice when adamant about using a fundamentally broken programming paradigm, but I just cannot see any logical sense it in or proper justification for that sort of nonsense at all. In Phix, rather than jump through bizarre hoops to ensure there is only one of something, you simply just define one thing: no trickery, no overhead, no pain.
string A variable-length array of 8-bit characters/bytes/integers with values from 0 to 255. Strings can be stored in variables declared as sequence, however variables declared as string cannot hold a dword-sequence. Strings can also be used to hold raw binary data, though you would normally use allocate() for that. Likewise unicode text other than UTF8 is normally best kept in raw memory or a dword-sequence.
subclass v: The act of increasing overall meaninglessness by making a new meaningless thing as a subset of some other meaningless thing.
Bears some similarity to giving someone directions by starting "Ah, now, if I were you, I wouldn't start from here".
Alternatively: Selectively substitute symptomatic subroutines while preserving the problematic parts in support of the so-called open-closed principle, so that something somewhere subsequently successfully suffers the same sad strange symptoms seamlessly.
Please, just don’t bother to either try and explain, or ask me why.
tbyte When I use tbyte, I really mean ten-byte, ie an 80-bit float. This is the same meaning as FASM, and has been copied into the inline assembler of Phix. Thankfully it does not cause any known conflicts, but in the crazy C/C++-land, tbyte or TBYTE is often used to mean "an 8 or 16-bit byte" (I kid thee not). We are probably all wrong.
TCB Thread Control Block. Used in and private to builtins\VM\pHeap.e, contains tables of owned and non-owned lists of free blocks, which minimises lock contention by allocate and free and their low-level internal equivalents (:%pAllocStr etc).
technicalia A made-up word loosely meaning one of "technical details you do not need to know for day-to-day use" or "some useless trivia" or "extremely unlikely scenario" or "covering my ass", or all four. Several pages in this document end with a technicalia drop-down. They are initially hidden to avoid breaking the flow of my (or more acurately Rob Craig’s) otherwise achingly beautiful prose. smile They can be skipped on first reading, may help when you hit a difficult problem, and above all are not worth getting all hot and bothered about, he says hopefully.
threadstack An outdated internal compiler/back-end term, from before making tvars ebp-relative. Where this is still used, it probably just means the gvar table, or quite likely should just be completely ignored.
tvar Internal compiler/back-end term. Routine parameters, local variables, and any unnamed temporaries required inside a routine are all tvars. They are stored relative to ebp, with storage for them created by opFrame and destroyed by opRetf, see the comments in builtins\VM\pStack.e for more details. See also/contrast with gvar. Note that while gvars can have an associated compile-time value for constant and assignment-on-declaration purposes, that is not the case for tvars, which only have run-time values.
type safety Phix implements a (probably weak) form of type safety in the form of compile-time checks, but makes no grandious claims, preferring to focus on making debugging easier, instead of trying to avoid it at all costs, and inevitably failing. Phix also avoids any implicit type conversion; should you want a 3 from PI, you would have to explicitly code floor(PI).
typeless I often refer to JavaScript as a typeless language. More strictly speaking it has very strong notions of quite a few (thousand) types, but no variable is ever constrained to only holding some subset of those types, not even a "const". Using Phix terminology, I might say that every variable in JavaScript is of "type" object.
UTF8 An international standard for holding non-ascii text. Phix source files may be stored as UTF8 (but not UTF16) and Edita can edit UTF8/16 files seamlessly, as long as they begin with a proper BOM. Note that UTF8 string characters can be difficult to process using normal subscripts; since unicode characters can be composed of more than one byte, the third character (for instance) is not necessarily stored at s[3]. However substring matching, and subsequent replacement, generally works perfectly well, without any known issues.
VM The term Virtual Machine has several meanings in the computer world; quite commonly it is used for a software imitation of an entire operating system running inside another. However in Phix it is simply a collection of software components that augment the physical hardware and wrap many (but not all) OS-specific requirements. These components can be found in the builtins\VM directory. For example the hardware add can only operate on two integers and fadd on two floats, whereas :%opAdd (in builtins\VM\pMath.e) can operate on any combination of integer and float, and yield either an integer or floating point result.
Windows
    key
I’ve always felt my life would be much easier if I knew how to use this key properly, but not really...

Windows key (or Ctrl + Esc) Open/Close the Start menu.
Windows key + A Open Action center (aka notifications).
Windows key + B Activate/show the taskbar.
Windows key + D Display and hide the desktop (see also M,).
Windows key + Alt + D Open date and time in the Taskbar.
Windows key + E Open File Explorer.
Windows key + F Open Feedback Hub.
Windows key + G Lauch Game bar app.
Windows key + H Open dictation feature.
Windows key + I Open Settings app.
Windows key + K Open Connect devices.
Windows key + L Lock device.
Windows key + M Minimise all windows.
Windows key + O Lock device orientation.
Windows key + Shift + M Restore minimized windows on the desktop.
Windows key + P Open Project settings.
Windows key + R Open Run popup.
Windows key + S (or Q) Open Search.
Windows key + T Cycle through apps in the Taskbar.
Windows key + U Open display/ease of access settings.
Windows key + V Open Clipboard bin.
Windows key + W Open Whiteboard.
Windows key + X Open Quick Link menu.
Windows key + Period (.) or Semicolon (;) Open emoji panel.
Windows key + Comma (,) Temporarily peek at the desktop.
Windows key + Plus (+) Zoom in using the magnifier.
Windows key + Minus (-) Zoom out using the magnifier.
Windows key + Esc Exit magnifier.
Windows key + PrtScn Capture a full screenshot in the "Screenshots" folder.
Windows key + Pause/Break Open System Properties dialog box/About.
Windows key + Shift + S Capture part of the screen with Snip & Sketch.
Windows key + Left arrow key Snap app or window left.
Windows key + Right arrow key Snap app or window right.
Windows key + Number (0-9) Open the app in number position from the Taskbar.
Windows key + Alt + Number (0-9) Open Jump List of the app in number position from the Taskbar.
Windows key + Home Minimize or maximize all but the active desktop window.
Windows key + Shift + Up arrow key Stretch desktop window to the top and bottom of the screen.
Windows key + Shift + Down arrow key Maximize or minimize active desktop windows vertically while maintaining width.
Windows key + Shift + Left arrow key Move active window to monitor on the left.
Windows key + Shift + Right arrow key Move active window to monitor on the right.
Windows key + Left arrow key Snap app or window left.
Windows key + Right arrow key Snap app or window right.
Windows key + Spacebar Change keyboard layout and input language.
Windows key + Ctrl + D Create new virtual desktop.
Windows key + Ctrl + F4 Close active virtual desktop.
Windows key + Ctrl + Right arrow Switch to the virtual desktop on the right.
Windows key + Ctrl + Left arrow Switch to the virtual desktop on the left.
Windows key + Shift + S Create part of the screen screenshot.
Windows key + Shift + V Cycle through notifications.
Windows key + Ctrl + F Open search for the device on a domain network.
Windows key + Ctrl + Q Open Quick Assist.
Windows key + Tab Open Task View.
Windows key + F1 Open Windows Help Centre (a webpage).
Windows key + Ctrl + Shift + B Wake up the device when black or a blank screen.
word When I use "word", I usually mean a 16-bit value (and dword/qword for 32/64 bits). Many academic papers use it to mean "machine word", which of course these days means "32 or 64 depending on how you compiled it", as opposed to the physical hardware.