We are not ISO; we'll be brief. We don't believe in 1,200 page
specifications, especially since in this day and age, EDL is not the
first language of its kind and in fact borrows from a lot of other
languages.
If ENIGMA isn't actually following the specification here, but you would
like it to, please let is know. This specification is part plan, part
fact of life.
Variables in EDL begin with a letter as defined in the Unicode standard.
To be brief, this includes a-z and A-Z. Letters after the first letter
may be any word character as defined in the Unicode standard, which
includes all letter characters and all number characters.
Numerals in ENIGMA are not common in other languages. Decimal literals
are denoted per C++ specification, except they may be preceded by zeros.
For compatibility with similar languages, the dollar sign may be used to
denote a hexadecimal literal. To improve on numeric support, the
prefixes 0x, 0o, and 0b may be used to denote hexadecimal, octal, and
binary literals, respectively.
a = 135790; // Decimal literal
b = 013579; // Decimal literal
c = $DECAFF; // Hex literal
d = 0xBADF00D; // Hex literal
e = 0o12345670; // Octal literal
f = 0b00011011; // Binary literal
EDL breaks from C++ for class definitions. The point of classes in
ENIGMA is to behave like structures in C, and so the struct keyword is
adopted to denote them. This decision was made for two simple reasons:
Structures in EDL can still contain methods as well as fields. These
methods, as in C++, are meant only to manipulate variables declared
explicitly in the structure.
Constructors and destructors can be defined as per ISO C++. A
constructor is denoted as a typeless function with the same name as the
class. A destructor is similar to the constructor, but is prefixed with
a tilde. Constructors can have parameters, which are passed while
initializing or instantiating with operator new.
Unlike C++, member initialization is not done in a list before the body,
but instead is either done during the declaration or during the first
lines of the body.
Often, visibility settings (such as private, public, or protected) serve
to confuse or hinder in development. EDL does not enforce these
attributes, except where required by the host language while crawling
definitions. EDL instead shifts the responsibility to developers to
select an appropriate naming convention and follow the rules.
struct circle {
var x = 0, y = 0;
double radius;
double get_area() { return pi * radius * radius; } // Simple method
circle(double r = 1) { radius = r }; // Optimizing this falls on the language plugin
~circle() { destroy_radius(x,y,radius); }
}
As in ISO C++, enumeration values are to be regarded as strict
constants. When values are specified, they should be evaluable at the
time of parse. A sample enumeration is as follows:
enum {
a,
b,
c,
d = 10,
e,
f
}
In the above enumeration, as per ISO C++, the values of a, b, c, d, e
and f are respectively 0, 1, 2, 10, 11, 12. These values should be
assigned by the language-independent lexer upon initial parse. The
assignment operand for initialized constants is to be regarded as a
single token, though it may contain more complex expressions provided
that these expressions do not entail runtime computations.
As with EDL structures, EDL enumerations need not be followed by a
semicolon, as declarations using the new type must be made separately.
Unions are also allowed in ENIGMA, but are not guaranteed to exhibit the
size of the largest type. Depending on the language plugin, the union
may in fact have the same size as the structure. As in ISO C++, EDL
unions do not permit objects with constructors as members.
Unions are also allowed in ENIGMA, but are not guaranteed to exhibit the
size of the largest type. Depending on the language plugin, the union
may in fact have the same size as the structure. As in ISO C++, EDL
unions do not permit objects with constructors as members.
EDL inherits JavaScript-like arrays rather than C++-like arrays. This is
so an array can serve as an lvalue, as in the following code:
[x,y] = get_coordinates();
var fruits = ["apples", "oranges", "cherries"];
In the above case, x and y are set to the first and second elements
in the array returned by get_coordinates(), respectively. The second
line then declares a var and assigns the given array values to it.
How this is accomplished after compile is outside the scope of this
specification. Consult the appropriate export language plug-in page for
details on implementation.
EDL supports a subset of preprocessors available in C. This subset
presently comprises define, error, elif, elifdef, elifndef,
else, endif, if, ifdef, ifndef, undef, and warning.
Unlike in C, preprocessors in EDL need not begin the line. Instead of
being set off by a pound symbol at the start of a line, they are
enclosed in double braces. For example, consider the following code:
{{if 0}} {{define count 10}} something = true;
{{else}} {{define count 20}} something = false; {{endif}}
Typing in EDL is strictly static, though primitive types exist which
simulate dynamic
typing.
| Primitive | Range |
|---|---|
| bool | A boolean value of true or false. |
| char | Integers from -128 to 127; often representing an ASCII letter |
| short | Short integer from -32768 to 32767 |
| int | A standard, 32-bit integer; any number between -2147483648 and 2147483647 |
| long | A long integer; any number between -9223372036854775808 and 9223372036854775807 |
| float | A 32-bit floating point number; any revalues representedal number which can be represented by the IEEE floating point specification |
| double | A 64-bit floating point number; any real number which can be represented by the IEEE floating point specification |
| instance_t | The type needed to refer to any instance in ENIGMA. |
| string | An alias of std::string; any reasonably sized string of characters |
| variant | Any value that can be stored by a double, or any string |
| var | A matrix of any positive dimension storing any number of values representable as double and any number of strings |
Casting in ENIGMA is valid between any two numeric types. Casting from a
floating point type to an integer type will truncate the value, and
limit it to the max value of the given data type. Thus, char(500.9)
= 127, and char(100.9) = 100.
Casting from a numeric type to string is also valid, but this must
be done explicitly using string(number), where number is any
real-valued variable.
Casting from var to any scalar type will cast only the index [0,0] in
the matrix.
Casting to boolean differs by data type.
Type |
Cast Method |
|---|---|
bool |
Casting a boolean to a boolean is not needed. |
char, short, |
Casting from a numeric type to boolean is done per hardware specification; it is equivalent to |
instance_t |
Casting instance_t n to boolean is the same as comparing |
variant, var |
If the value represented is a string, then the cast is undefined. Otherwise, the cast is the same as |
No special treatment is given to floats as such systems usually create
bizarre corner cases. If you are looking for a fast way to compare two
doubles with some laxity, cast both to float before running the
comparison.