Marz

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.

Scope

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.
Examples:

$"_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.

Variables

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

Data types

Marz has three main data types: String, Number, 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.
Examples:

(Note: You do not have to prefix a literal with its type, only functions. This is done for clarification)

→$String "abcdef";→←
         →←
         ;
→$Number 1057.521;→←

→$Number 0xBADBEEF;→←

→$Number 0b110111001011101111000100110101011110011011101111;→←

         0
→$Number 10↓    1010110001 in decimal
         1 1
         ↑0←

→$String "Whitespace matters in Strings but not in Numbers.";→←

→$String(){↓
↓          ←
→  return "Abc";↓
↓               ←
→}→←
 
→$Number[]($Number a, $Number b){↓    Function that returns Number[]
↓                                ←
→  return [a + b];↓
↓                 ←
→}→←

→(Number()=>5)();→←    x()=>y Is a function that returns y. Adding () and arguments after a function calls it

→$Number: (-1):;→←    Reference to the number -1 (decimal). To deference, do :((-1):). Similar to pointers in C

→$Number →1←    1111111... (decimal). See Infinite Strings and Numbers (when I get around to writing that section)

→[1,2,3][0];→←    Indexing arrays works like expected.

→$Void;→←    Null type.

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

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/B.mz", "C.mz"
//A/B.mz
→$Number x = 5;
//C.mz
→$Number y = $"A/B.mz".x + 2;→←

This results in the following grid for C.mz:

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

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

Import and export statements

Syntax Description Example
import SCOPE; Gets a list of all variables in SCOPE. Creates a reference of the appropriate type to each of those variables and stores those references in the current scope. import $"A.mz";
export SCOPE; Same as import, but creates references to this scope on SCOPE. export $"B.mz";

Example:

//index file
//A.mz
→$Number getX()=>5;
//B.mz
→import $"A.mz";↓
↓               ←
→(:getX)();→←    5;

List of variables in global scope

Name Description
class Number Literal class for Numbers. Not instantiable.
class String Literal class for Strings. Not instantiable.
class Void Literal class for Voids. Not instantiable.
Void print(String str) Writes str to the output.
String inputLine() Returns the next line of input (might be changed/removed).
String inputChar() Returns the next character of input (might be changed/removed).

//Adding more later. Need a break.