Identifiers - Manhunter07/MFL GitHub Wiki

Identifiers in the sense of programming are names that declared entities from within the current scope can be reached by. The represent the declared names of objects such as packages, constants, variables, functions or similar entities.

Restrictions

Explaination

When declaring an object, its identifier(s) must follow the restrictions put uppon them by the architecture of the programming language. MFL follows the same naming restrictions as most other object-oriented or imperative programming languages. They are identical to those of Pascal, with the slight difference that keywords cannot be escaped using &.

Identifiers may start with an uppercase or lowercase letter from A to Z (a to z respectively) or an underline, and may contain the same set of characters plus the addition of digits from 0 to 9.

Spaces, operators, comments or any other special characters, including language-specific letters like the German umlauts (Ä, Ö, Ü) or eszett (ß) are not possible. They are, however, possible inside Strings literals which pose no restrictions on characters whatsoever.

Examples

Some valid identifiers in MFL could be: sample, SamPle, SAMPLE, Sample_0, _sam_ple or _0_Sample.

Invalid identifiers are for example: 0_Sample, Sam ple, Sam-ple*, Sämple, ?(Sample)* or Sam|ple.

*) Although these would be valid expressions and could be evaluated, they are not a possible identifiers for themselves.

Qualified identifiers

Qualified identifiers are identifiers that include the whole scope path they are declared in. This usually includes the package name and the object name for global identifiers. Function parameters and function-local pseudo objects do not have a qualified identifier and can therefore not be explicitely addressed if re-declared.

Qualified identifiers including the package and object name contain both, separated by a single dot (.). Examples for qualified identifiers are: System.Sin, System.Info.Get, System.Thread.ID or MyPackage.MyObject. For most packages, a qualified identifier is required to get access to an object. An exception to this is the System package, for example. This means, that in the case of System, you can simply write Length which will evaluate to System.Length if there has not been declared an object with that name in any nearer scope.

Dynamic (string) identifiers

See also: Dynamic identifiers

In many situations, identifiers can contain dynamic parts or be even replaced by strings. For example, a qualified identifier may contain a string constant like these:

System."Thread".Current
System.("Thr" + "ead").Current

To be a valid identifier, these dynamic values must evaluate to a string value.

Name conflicts

Name conflicts can occur, especially with overlapping namespaces or duplicate declarations. This applies to both qualified and unqualified identifiers. When resolving an identifier, there are pre-defined rules to determine which part of the name stands for which namespace and to determine which declaration to chose in case of a name conflict. The rules to resolve a name are as follows:

  • Packages are searched for an identifier bottom-up. This means that the later a package had been linked, the higher its priority is.
  • Namespaces are searched for an identifier inside-out. This means that the inner a nested declaration is, the higher its priority is. For example, a function parameter always has priority over a declared constant or variable from within the function body.
  • Members are ignored for resolving. This means that as soon as an identifier has been found in a package or locally, it is chosen, regardless of whether or not it contains a member with the specified name.
  • Local namespace is searched first before any packages. This means that only if an identifier is not declared in the local namespace, linked packages are searched.

To see which object is chosen for an identifier, you can use the resolve command.

See also