From Esolang
Jump to navigation Jump to search

Marz is a 2D, self-modifying, object-oriented esoteric programming language in development by a madman User:SoundOfScripting.
This specification may or may not be representative of the future specification and is subject to change without discretion.

Wait, what?

Yes, you read that right.

Programming in Marz

Marz programs are one of the following:
1) A single program file.
2) A collection of files including an index file. The index files lists the order that the program files are loaded/executed in. The format for index files is not decided.
Marz program files should have the file extension .mz.


Marz uses lexical scope for variables. A "scope"/grid is a two-dimensional grid of characters which holds variables or code.
Variables of a scope are parsed at runtime when accessed.
Each program file in Marz is its own scope. There is also a global scope, which holds each of the program file scopes in variables.
An in-place/one-dimensional scope is a scope that is not a two-dimensional grid of characters. These scopes are not self-modifying and cannot be created by the program. The global scope is in-place.

Parser and IP

For each program file, the starting position of the scope is initialized to the top left corner. The starting position marks where parsing and execution begin.
Each two-dimensional scope has its own parser, which moves over the characters to store and retrieve variables. Every time a variable is accessed by name from a scope, the parser moves through the scope until it finds the variable and returns it (if it is not found the program gets stuck in an infinite loop). If a syntax error is parsed, parsing stops.
The IP (instruction pointer) is similar to the parser. There is only one instruction pointer for the whole program. The instruction pointer moves through scopes executing code, not parsing for variables.
Note: A scope's parser only begins parsing when one of its variables are accessed.

Control flow

If the IP or parser moves off of the edge of a scope, it loops around to the opposite edge. Directional arrows (, , , ) change the direction of the IP and parser.

↓ Starting point: top left      
← wraps    →     Inf     ↓ wraps
           ↑    loop     ←      

Note: the above code snippet is not valid syntax. It is just an example of control flow.

Referencing variables

Variable names may consist of any characters.
Variables with names only consisting of alpha-numeric characters (and with a letter as the first character) may be refered to simply by writing the variables name.

Scope addressing

Placing an addressing prefix before a variable name will access that variable in a different scope.
Without an addressing prefix, the current scope is accessed.

Prefix Description
# Refers to the current scope.
$ Refers to the global scope.
_ Refers to the scope containing this one (the scope above it). Stackable.

To refer to a variable with a non-alphanumeric name, you must use an addressing prefix followed by the name in quotation marks.

$"_abacaba()[]]" Refers to the variable named _abacaba()[]] of the global scope.
foobar Refers to the variable named foobar of the current/local scope (the scope this line is executed in).
__str Refers to the variable named str two scopes above this one.
#"fizz buzz" Refers to the variable named fizz buzz of the current scope.

Global scope

Variable on global scope Description
class Number Literal class for Numbers.
class String Literal class for Strings.
class Void Literal class for Voids.
Void print(String str) Writes str to the output.
Void println(String str) Writes str to the output followed by a newline.
String inputLine() Returns the next line of input (might be changed/removed).
String inputChar() Returns the next character of input (might be changed/removed).


Variables in Marz can store literal data, scopes, and classes and instances (both contain their own scopes).

Data types

Marz has four main data types: String, Number, Boolean, and Void (null). These data types are classes stored on the global scope and are not instantiable.
There are also three sub-types --- Array [], Function () and Reference : --- which may be appended to the end of a type to create a new one.
Compound types, written as (Type1, Type2, ...), denote a value of any of the types compounded. For example, (String[], Number) may store an array of strings or a number.


A Void in Marz stores no data. Typically, when a value is not written, a Void is supplied.


Booleans in Marz can store two values, true and false.
//TODO: write Boolean section


Numbers in Marz are all instances of the base number class, $Number.
Numbers are stored as computable real numbers ?with infinite precision?.
Numbers may be written in any base according to the following prefix table.

Prefix Base Example
None Decimal 123 = 123
0x Hexadecimal 0x7B = 123
0c 0c173 = 123 Octal
0b Binary 0b1111011 = 123
0(X), where X is a number (nestable) Base X 0(0(7)12)146 = 0(9)146 = 123

Prefixing a number with a - denotes a negative value. Any whitespace read while parsing a number is ignored.
Numbers may not start with ., it must be prefixed by a 0 (ex: 0x.8A9 is invalid, but 0c0.417 is).
Note: Although 0(10)64 and 64 are equivalent, they are still stored differently.

Number operators

Numeric operations take two numbers as arguments and return a result written in the same base and representation as the first.
Numbers are never rounded and may use "infinite" decimal places (see infinite numbers and strings and stuff when I write the things and stuff about them). Numeric operations are evaluated using the order of operations and () to indicate evaluation order.

Operator Description Example
N1 + N2 The sum of N1 and N2 13 + 0x1F ==> 44
N1 - N2 The difference of N1 and N2 0(9)65 - 0c15 ==> 46
N1 * N2 The product of N1 and N2 0(10)6 * 4 ==> 0(10)24
N1 / N2 The quotient of N1 and N2 0c1 / 0(8)3 ==> 0c0.252525...
N1 ** N2 N1 to the power of N2 2 ** 3 ==> 8
1 ** 2 ** 3 is read as 1 ** (2 ** 3)
NaN, Infinity, and -Infinity

NaN is a special number returned when a numeric operations has no valid value. Infinity reciprocal of 0, and -Infinity is its opposite.
Similar to their floating-point equivalents, NaN swallows all numeric operations, and +/-Infinity do the same in some scenarios.
On the global scope, $NaN holds NaN, and $Infinity holds Infinity. However, the values may still be computed as follows:

→123←              1232123212... -> Infinity
→0←                0000000000... -> NaN
→123.→123→←        123.123123... -> Not infinite.
→1/0→←             Infinity
→-1/0→←            -Infinity
→1 / $Infinity→←   0
→1/-0→←            Infinity (there is no negative 0, so -0 = 0)
→-1 ** 0.5→←       NaN (only real numbers are supported)
→0/0→←             NaN
→0 * $Infinity→←   NaN
→2 ** $Infinity→←  Infinity
→2 ** -$Infinity→← 0
→1 ** $Infinity→←  NaN

Definitely not stolen from JavaScript
Number class

The Number class, $Number may be instantiated as follows:

→Number( (Number, Boolean, Void) num )←                                      Converts num to decimal (no prefix)
                                                                                          Void -> 0, true -> 1, false -> 0
                                                                                          Equivalent to casting the value (($Number) true ==> 1)
→Number( (Number, Boolean, Void) num, Number base )←            Converts num to base base (prefix 0(base))
→Number( String str )←                                                       Parses str, returns a number in the base/representation of str
                                                                                          Also equivalent to casting the value.
    Ex: Number("0xF3B0") = 0xF3B0
        Number("0(8)11") = 0(8)11
        Number("72")     = 72
        Number("abc")    = NaN
→Number( String str, Number base )←                             Parses str, returns a number in base base
→Number( String str, Number base1, Number base2 )← Parses str as a base base1 number, returns a number in base base2

There are also the following properties of the class:

Property Description Example
static Boolean $Number.valuesEqual( Number a, Number b ) Compares two numbers' values (not bases).
Equivalent to the comparison operator ==.
$Number.equal(12, 0xC) ==> true
static Boolean $Number.basesEqual( Number a, Number b ) Compares two numbers' bases (not values). $Number.basesEqual(0(10)75, 43) ==> true
static Boolean $Number.equal( Number a, Number b ) Returns whether two numbers are the exact same value, base, and representation. $Number.equal(75, 75) ==> true
Comparing numbers

Marz's comparison operator is ==. When applied to numbers, == will return whether the Numbers' values are equal (not their bases). To compare values and bases, use static $Number.basesEqual( Number a, Number b ).


Strings are a sequence of characters surrounded by "".



Note: Literal Strings and Number do NOT wrap around edges, only the IP/parser do.

//TODO: finish this

Declaration statement

Finally, what you're probably been waiting for. How does one create a variable?

→$String str = "Hello, World!";→←    As expected.

The above is a declaration statement. The statement itself stores the value of the variable.
Changing a variable's value will write into the declaration statement (if the parser can find it, if not infinite loop).
The parser will only find the first declaration statement of a variable, then exits. So, any duplicate statements are ignored, and redefining a variable sets its value.
Executing this:

→$String part1 = "Hello,";↓
↓                         ←
→$String part2 = "World!";↓
↓                         ←
→part1 = part1 + " " + part2;→←    Assignment statement.

Results in the following grid:

→$String part1 = "Hello, World!";
↓                         ←
→$String part2 = "World!";↓
↓                         ←
→part1 = part1 + " " + part2;→←    Assignment statement.

As you can see, writing to part1 overwrote the . This leaves the parser stuck looping over line 1 (due to wrapping), so it can no longer see the declaration statement for part2 (meaning that variable no longer exists).
The IP, however, is not affected by this overwriting. It still continues on line 5 and gets stuck in its own infinite loop.

Auto-evaluation of declaration statements

When a declaration statement is executed, it evaluates it and writes the result (like an assignment statement).
For example:

→$Number x = getX();↓
↓                   ←
→$Number getX(){↓    The ()/[]/: may be placed after the variable name instead of the type, which does the same thing.
↓               ←
→  return 12345678;↓
↓                  ←

When executing line 1 of the above, the IP stops at the ;. Then, the expression getX() is evaluated, returning 12345678, which is written to x.
This results in the being overwritten with an 8. The IP and parser get stuck on line 1, repeatedly rewriting 12345678 to x.
Note: When writing a value to a variable, a ; is placed at the end. Written values start at the first character of the previous value in the declaration statement. No extra whitespace is written.

Storing an unbounded value

Here is an easy method of storing an unbounded value (using wrapping).

↓→$String str = "aaaaaaa";
→str += "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";→←    Will never cause any problems.

Of course, this is assuming that str never contains any directional arrows, which still work when written in Strings (see: Escape characters, once I write about them).

Variables in scopes

To refer to a variable in a scope, use a ..
On the global scope, for each program file, a variable with a name consisting of the file name and relative path to the index file of that program file stores that program file's scope.
For example:

//index file format TBD, order is "A/", ""
→$Number x = 5;
→$Number y = $"A/".x + 2;→←

This results in the following grid for

→$Number y = 7;A/".x + 2;→←

which causes a syntax error for the parser (exiting parsing at that point (the ")).