Migol 09

From Esolang
Jump to navigation Jump to search

Migol 09 (MigoMipo Algorithmic Language) is a simple imperative, interpreting, assembly-like language. It is designed by User:MigoMipo. Migol 09 has been succeeded by Migol 11, which adds a more complicated I/O system but is otherwise almost backwards-compatible with Migol 09 programs.

Basics

The memory is a mutable array of signed 32-bit integers. Most of the commands in the language serve to modify the memory or the program pointer. First address in the memory is 0.

A Migol program consists of a number of statements, separated by commas or newlines. The instruction pointer points to a certain statement.

Absolute assignment

One of the most important commands in the language is absolute assignment, which looks like this:

(address)<(value)

It assigns the value at the right side to the address at the left side. For example,

 0<3

assigns 3 to the memory at address 0.

Modifying assignment

These operators lets you modify an already existing memory position, and store (<) a value in the adress, after applying a self ($) operating operation. This could be compared to the syntax "a += b" in many C-like languages. Migol supports most arithmetic and bitwise operations. Memory can be modified with

(address)<$(op)(value)

The supported operations in Migol 09 are:

op description
+ addition (adds value to the value at the address).
- subtraction (substracts value from the value at the address).
* multiplication.
/ division.
% modulo.
^ bitwise xor.
& bitwise and.
| bitwise or.
! bitwise not.*
<< left bitshift.
>> signed right bitshift.
>>> unsigned right bitshift.
<<_ left bit rotation
>>_ right bit rotation

* Note that right side should not contain any value in this case.

For example, if we remember that we assigned 3 to memory address 0,

 0<$+2

will increase memory at address 0 by 2, resulting in address 0 having the value 5.

Sequential operations

Operations (absolute and modificational assignments) can be trimmed together, to form a bigger statement. It may seem odd at first, but this is how it works:

 (address)(op-1)(value-1)(op-2)(value-2) [...] (op-n)(value-n)

This gets transformed during execution to the following statement:

 (address)(op-1)(value-1)
 (address)(op-2)(value-2)
      [...]
 (address)(op-n)(value-n)

That is, every subsequent operation is applied to the leftmost address only.

An example:

 8<10<$+5<$>>2

This would mean "store 10 to addr. 8, increase value in addr. 8 by 5, and shift value in addr. 8 two steps to the right (signed)".

An important note is that each sequential statement still counts as only one statement. This gets important when we get to the flow control section. Apart from this, there is no semantical difference between a sequential statement and having the same operations in separate statements. This means that each step writes directly to the destination address, so if the sequential assignment reads from the destination address, it will return the current value, and not the initial value. If the destination address is a deferring expression, it will be reevaluated after each step.

Branching and looping et al.

Memory deferring

Migol also supports dereferencing of variables. The [] operator allows you to use variables as pointers, and it is also the only way to read from variables.

[0]

will yield the value in address 0, in this example 5.

But it gets even better! Several levels of dereferencing are allowed. This can be used to create advanced data structures with pointers, such as arrays, linked lists, stacks and queues (all of these has been implemented with relative ease).

 5<7
 1<[[0]]

This will set address 1 to 7. First, address 0 is read, yielding 5. Then, [5] is dereferenced, yielding the value at address 5, which is 7. An unlimited amount of dereferencing is allowed.

 3<[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[56]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]

is correct syntax, as long as the brackets match.

Pointers can of course be used on the left side of an assignment.

 [1]<10

will read the value in address 1, and write 10 to that address.

Flow control

Controlling the flow is very easy. The only way of redirecting flow control is through the special # "address". # represents the program pointer, and contains the current statement number to execute. Dereferencing it will yield the statement number.

It is automatically increased after every operation, allowing the interpreter to execute the next statement. To perform loops, the program pointer must be modified.

 #<12

Will move the program pointer to line 12. The semantics are a bit similar to goto. It easily supports computed goto and modification.

 #<$+10

will move control flow 10 lines forward from where it is currently.

 #<$<<[6]

will read the value in address 6 and bitshift the program pointer by said amount of steps to the left.

When combined with the sequential operator, the variable will change instantly with each operation, just like with normal variables. Note however, that the entire sequential statement must be executed before directing control flow to the new position.

Conditionals

The last important feature is conditionals. Conditionals in Migol are basically modifiers of ordinary commands.

The current syntax for conditionals works with appending the conditional statement to a command, which is only executed if the condition is true.

  (statement)?(op)(value)

(without the parenthesises.)

This will check if (value) (op) 0 is true; if it is, then the statement is executed. Else, it continues to the next statement.

An example of this syntax in use:

  8<4?>[2]

"If the value at address 2 is greater than zero, then set 4 to address 8."

These comparing operators may be used:

op name
= equals
<> not equal to
> greater than
< less than
>= greater than or equal to
<= less than or equal to

Superfluous features

Whilst Migol is aiming for being a clean, non-bloated language with rich support for many types of data structures, there are yet some features which has been added due to demands from the community.

Characters

A practical command which will make output easier is '. Is it used like this:

'(char)

It evaluates to the ASCII value of the character.

'A

evaluates to 65.

Output

Note: This syntax is soon to be replaced, cooccuring with the introduction of interrupts to the Migol language, most likely in the next version.

Besides assignment operations, there are also two output operators. One operator is for outputting a character

op description
(value)> outputs the number as an ASCII character. Expressions or pointer can of course be used.
(value)>- outputs the number as an integer. Same here, pointers can be used.

'A' can be written with

65>

or

'A>

or

4<'A, [4]>

Input

Currently, input is done by derefering the '@' character (similar to how '#' represents the instruction pointer). The following example reads one character from stdin to address 4:

4<[@]

Comments

Due to popular demand, comments has been added to Migol. Two forward slashes ("//") start an until-end-of-line comment.

In addition to comments, leading and trailing whitespace should also be allowed, as well as unnecessary newlines.

Computational class

Migol 09 is not precisely Turing-complete, because the language can't address an infinite amount of memory cells. Additionally, memory cells can't be addressed with negative addresses. Since the integer type is signed 32-bit, Migol can address 2147483648 integers (2 GiB), as negative memory addresses generally aren't permitted. This is the only limitation to Migol, and a (finite-memory) Brainfuck interpreter has been written in Migol, therefore making it usable for computation.

Changelog

Here is a changelog of the reference implementation written by User:MigoMipo.

  • Version 2.3.1
    • Interpreter now supports -e option (works like in Perl)
  • Version 2.2.0
    • Improved error messages.
    • Lots of code modifications to make the classes more reuseable.
  • Version 2.0.5
    • Greatly improved performance.
  • Version 1.x (Migol 09.x)
    • Old version.


External resources

Implementations

Sample programs