This variant of micron is derived from the original by @Z3RYX.
This variant focuses more on strong typing and modularization by having slightly different behaviours of some specific instructions. Also, better errors.
Keep in mind that this implementation is still in development so some features are subjected to change.
- micron-rust
- Usage
- Specification
- Data Types
- Slots
- Instructions
- Labels
- Functions
- Set (Int, Value) -> None
- Get (Int) -> Value
- Print (Value) -> None
- Write (Value) -> None
- Add (Value, Value) -> Value
- Jump (Str) -> !
- If (Value, Value) -> Value | !
- Equal (Value, Value) -> Int
- Extract (Str, Int) -> Str
- Convert (Value) -> Value
- Input () -> Str
- KeyChar () -> Str
- Number (Str) -> Int
- Text (Int) -> Str
- EmptySlot () -> Int
- Exit
- CatchError (Str, Value) -> Value | !
- ThrowError (Str) -> !
- Function (Str) -> Value
- Return (Value)
- Truthy and Falsy
- Comments
- Errors
To build, you need Rust 1.54.0+ installed.
git clone https://github.com/loyston500/micron-rust
cd micron-rust/micron
cargo build --release
target/release/micron # path of the executable
# to run, you simply have to pass a file
target/release/micron ../examples/mul.mc
Int
, holds a signed integer. (isize)Str
, holds a string. (String)None
, a None type, holds null value, though not intended to be used like other two data types.
Value
is used to indicate any data type.
They are the variables of micron, denoted by a unique integer ranging from MIN to MAX of an isize.
By default, slots hold None
.
Let's talk about the internals..
The interpreter basically iterates through every instruction (from an array) and executes them one by one.
There are two types of instructions, namely LabelPlaceHolder
and FunCall
.
LabelPlaceHolder
, self explanatory, doesn't do much. Since labels are compile-time, the interpreter wants their locations on the array to be known.FunCall
, this is where everything happens, they are just like normal function calls you see in every other programming languages, you'll know more about them later on.
Labels are defined using ;
For example, ;foo
. They allow you to jump to desired locations during the execution of the program using goto-like functions.
Just like in every programming language, they take some values, process them and give out some values. This is true for all functions here but there are some exceptions, we'll discuss about them further down.
Syntax: s:
This is used to set a value to the slot.
s:0 20 [sets value 20 to the slot 0]
likewise, you can also set an Str value.
s:0 "hi"
But the slot name should always be an Int, otherwise, it'll throw an error.
s:"lol" "hi" [this will not work]
Syntax: g:
This function returns the value of the slot. Remember that all the slots come predefined with None value, so if you try to access them, you get None.
g:0 [returns the value of slot 0]
Examples:
s:0 10 [sets the value of slot 0 to 10]
s:1 g:0 [gets the value of slot 0 and sets it to slot 1]
Since this function is going to be used a lot, you can use the short hand .0
which is same as g:0
Syntax: p:
Prints the given value.
p:10 [this prints 10]
p:"never gonna give you up" [this prints whats expected]
s:0 "hello world"
p:.0 [prints hello world]
Syntax: w:
Same as Print but it doesn't put a new line at the end.
Syntax: a:
Adds two values.
If both the values are Int then you get the sum.
If both the values are Str then it will concat them and return.
Else, an error is raised.
Example:
p:a: 10 20 [prints 30]
p:a: "Hello, " "World" [prints Hello, World]
p:a: 10 "uhh" [errors out]
Syntax: j:
This one is a bit different. On calling, it jumps to the given label. Yeah, it's basically goto.
p:"Hello, "
j:"foo" [jump occurs here]
p:"human" [This instruction is skipped]
;foo [it reaches here]
p:"world" [this gets printed]
This behaviour is consistent, regardless of it being nested or not.
p:a:"hi " j:"foo"
[The evaluation of the line above is abruptly stopped and the pointer jumps to ;foo]
;foo
p:"hello" [this gets evaluated]
Syntax: ?:
If the first value is truthy, then the second value is (evaluated and) returned; If not, None is returned.
p:?:10 "yay" [prints yay because 10 is truthy]
p:?:0 "not yay" [prints None because 0 is falsy]
Remember, the second value is evaluated ONLY if the first value is truthy. This means you can do stuff like,
?:10 j:"foo" [10 is truthy so the jump function is evaluated which then performes the jump]
p:"Hello!" [this line is skipped]
;foo [that jump gets you here]
p:"Worked!" [this gets printed]
Syntax: =:
Checks if the given values are equal, both must be of same data type, else an error is raised.
When equal, 1 (a truthy value) is returned.
When not equal, 0 (a falsy value) is returned.
None
can't be compared, so an error is raised.
Example:
p:=:10 10 [this prints 1]
p:=:20 10 [this prints 0]
p:=:"hello" "hello" [this prints 1]
p:=:"hello" "hi" [this prints 0]
p:=:"hello" 20 [this raises type error]
Syntax: x:
Extracts a character from the Str with the given index value. If the index is out of bounds, an empty string is returned.
Example:
p:x:"hello" 1 [prints e]
p:x:"hello" 100 [prints just a newline because the extract function returns an empty string]
p:x:"hello" "1" [raises error]
Syntax: c:
Used to convert Int to it's ASCII equivalent Str and vise versa.
Passing None or invalid values will raise ValueError
.
Example:
p:c:"f" [prints 102]
p:c:420 [prints Ƥ]
p:c:"ab" [value error is raised]
p:c:999999 [value error is raised]
Syntax: i
This function takes no argument so it doesn't require a colon (:
) next to it.
Used to get user input.
Example:
p:i [this prints the given input]
Syntax: k
Same as Input function, but it doesn't need you to click enter. The given char is collected and returned.
While implementing this function, I realised that getting a key char is an OS specific thing, and apparently in some scenarios, it'll not work on terminals of Windows. So I've decided to leave it unimplemented. It will return None instead.
Syntax: n:
Converts the given Str to an Int (isize). On failure, an error is raised.
Example:
p:n:"123" [prints 123]
s:1 n:"123"
p:a:.1 1 [this should print 124]
n:"foo" [raises error]
n:123 [this raises error as well but this behaviour is subjected to change]
Syntax t:
Converts the given Int to Str. On failure, an error is raised.
Example:
p:t:123 [prints 123 as usual]
s:1 t:123
p:a:.1 "1" [this should print 1231]
t:"foo" [this raises error but this behaviour is subjected to change]
Syntax: ~
Returns the first empty slot (the slot which is set to None). Starting from 0 to MAX.
Example:
p:~ [prints 0]
s:~ 10 [sets the value of slot 0 to 10]
p:~ [now it prints 1 because slot 0 is already aquired]
s:2 20 [sets the value of slot 2 to 20]
p:~ [still prints 1 because slot 1 is unused]
Syntax: $
Halts the entire program immediately.
Example:
p:"Hi" [prints Hi]
$ [the program halts]
p:":(" [this does not print]
Example program that halts/exits on entering exit
w:"Enter something: "
s:0 i
?:=:.0 "exit" $
p:"You didn't enter exit"
Syntax: #:
This is a special kind of jump function.
If an error is raised while the given value gets evaluated, it jumps to the given label while also setting the error code to slot -1
.
Otherwise, it returns the evaluated value.
Example:
p:#:"error" a:10 20 [prints 30 because no error occurs]
p:#:"error" a:10 "20" [error occurs so the pointer jumps to ;error]
;error
w:"Error has occured! The error code is: "
p:.-1 [-1 as described above holds the error code]
We'll talk about error codes later.
Syntax: !:
Throws error with an arbitrary message.
Example:
?:.0 !:"Slot 0 is not empty/None!" [error is not raised because None is falsy]
s:0 10
?:.0 !:"Slot 0 is not empty/None!" [now the error is raised because 10 is truthy]
Remember CatchError function? Yes, you can use it to catch errors thrown by this method.
#:"error" !:"My error" [
the raised error is caught by the
catcherror function so the pointer moves to
label ;error
]
;error
w:"Got an error: "
p:.-1
Syntax: f:
Works just like jump function, except it returns back to where it started on encountering either EOF or a return function.
On encountering EOF, the function returns None.
On encountering a return function, it essentially returns what the return function holds.
Example:
w:"hello "
p:f:"return_world" [this jumps to ;return_world] [the print function receives value "world"]
$ [exit to prevent the below instructions to be executed again]
;return_world [the pointer arrives here]
r:"world" [
the return function returns the value so it
rewinds back to where the function was called
]
Syntax: r:
This functions returns the given value, if it's invoked by a function, then it returns it's value to it, if it's invoked during the normal execution, the program halts. The given value does get returned, you can capture it if the script itself is invoked by another script, but that feature is yet to be implemented.
r:"foo"
All numbers are truthy except for 0
.
All strings are truthy except for an empty string.
None is always falsy.
[
]
are used to specify a comment. A comment can span multiple lines.
s:10 "
hi,
I can
span multiple lines
" [
just like strings
I can also span multiple lines
]
Each kind of error is associated with a unique Int.
TypeError
=> 401
, Raised when there's a type mismatch.
LabelError
=> 402
, Raised when the label it's supposed to jump isn't defined.
ValueError
=> 403
, Raised when the value is invalid or not supported.
NoSlotError
=> 404
, Raised if there are no empty slots available from 0 to MAX.
Error
=> 400
, Raised if there's an ambiguous error.
When an error is raised, the error code is set to slot -1
Example:
#:"error" j:69 [this raises TypeError since jump function always expects an Str]
;error
?:=.-1 401 j:"typeerror"
p:"Some error was raised"
$
;typeerror
p:"TypeError was raised"