ENIGMA:Specification

From ENIGMA
Jump to navigation Jump to search

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

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

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

Classes

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:

  1. In C and C++, structures are public while classes are private. Classes are protected or private in most languages which support visibility.
  2. The odds of a user attempting to use the word 'class' as an identifier far outweigh those of using 'struct'.

Methods

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/Destructors

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.

Visibility

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.

Sample

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); }
}

Enumerations

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. Enums are designed to be inline in the new parser, but until then don't forget your the semicolon after the closing brace. 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.

Declarations of enumerations are currently not possible in scripts or objects, however you can include them in definitions, under ENIGMA settings.

Unions

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.

Arrays

An array is always declared as a variant data type with the keyword var, followed by its name. Variant variables are not restricted to a specific data type and can hold any value you want. In order to access the element of an array, you add after its name the element index rounded by square brackets:

var myarray;

myarray[1] = 10;

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.

Preprocessors

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}}

Types

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

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,
int, long,
float, double,
long double
Casting from a numeric type to boolean is done per hardware specification; it is equivalent to value != 0.
instance_t Casting instance_t n to boolean is the same as comparing value > 0.
variant, var If the value represented is a string, then the cast is undefined. Otherwise, the cast is the same as value > .5.

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.