-
Notifications
You must be signed in to change notification settings - Fork 3
Dcoumentation v3.1
Official documentation for the RAM programming language. Please open an issue if you find any bugs, or want some features to be changed or added.
A program should always start with a main:
label, defining a block. Blocks are like functions where you can jump anytime using jmp
or conditional jumps (see jump reference to learn how to use them). Each label contains a block which is executed when the label is called. The program has a stack which stores integers and there exists some commands to manipulate it.
The language has 4 general purpose variables or registers (as in x86/arm). And rest of all are dynamic user defined variables of certain types.
NOTE: The registers are local to a function, they cannot be modified independently unless you perform a jump to another function. On the other hand, user defined variables are globally mutable, they can be modified independently.
-
lx
andrv
store i32 integers. -
string
andlxstring
stores strings.
They exist in the form of following types-
- :int (i32 integer)
- :string (string literal)
- :vec :string/:int (vector of string or ints)
- todo: u32, i64, u64, i128, u128.
- structs?
- multi dimensional vectors?
NOTE: These variables are truly global. They can change from a block without calling any jump statements.
todo: make a contents table using https://www.tablesgenerator.com/markdown_tables
// this is a one line comment
- print hello world
- print var [can be a register]
The ram command is used to assign variables and store a i32 on the stack.
You can push an i32 on the stack using ram <number>
For registers:
ram lx/rv 10
ram string/lxstring = 'hello world'
For variables:
ram <var_name> :<type_of_var> = <value_of_var>
- ram test :int = 10
- ram test :string = 'hello'
- ram test :vec :int = [1, 2, 4]
- ram test :vec :string = ['hello', 'world']
You can push register values to the stack by using ram lx/rv
ram lx 10
ram lx
You can assign the last value on the stack using ram lx/rv prev
ram 10
ram lx prev
print var lx
// prints 10
halt
exits the program
Drops the value of the variable from the memory, including dependencies in case of a map. Useful in cleaning stuff, or save memory leaks in a loop.
drop <var>
Takes in user input. Print message is optional.
stdin string = "input something: "
print var string
OR
ram x :str = ''
stdin x
print var x
Opens a file with the given path and store the contents as string.
ram lxstring = './readme.txt'
stdfs open lxstring = string
print var string
// string has the contents of the file
rand [1,10]
// sets a random number between 1 to 10 excluding 10 on the stack
rand lx [1,10]
// sets the random number to lx
rand lx [rv, lx]
// generate random number between rv & lx into lx
Parses variables into the given type and stores them into the string
or lx
register.
ram lx 5
parse lx :str
// now string = "5"
ram x :str = '10'
parse x :int
// now lx = 10
-
pop
Removes the last i32 from the stack - Be careful, you might not want to always use it.
Empties the entire stack.
split lxstring > " " = var
// splits lxstring using spaces and stores the data in a string vector named var
split string > "\n" = var
// splits string using a new line and stores the data in a string vector named var
concats two strings and stores the values (registers and vars) in the string
register
main:
ram string = 'hello '
ram lxstring = 'world'
concat string lxstring
print var string
halt
Joins vector of strings into the given string var:
ram x :vec :str = ['hello', 'world']
join x > " " = string
print var string
// hello world
Copy is used to copy the value of one variable/register to another variable/register.
ram x :int = 1
ram y :int = 10
copy x = y
print var x
// prints 10
ram x :vec :int = [1, 2]
vec x pop
print var x
// prints [1]
ram lx 100
ram x :vec :int = [1, 2]
vec x push lx
print var x
// [1, 2, 100]
(works for registers and vars)
ram x :vec :str = ['hello', 'world']
vec string = x[0]
print var string
// hello
ram lx 100
ram x :vec :int = [2, 3, 4]
vec x[1] = lx
print var x
// [1, 100, 4]
ram :vec :str x = ['a', 'b', 'c']
vec x len
// pushes 3 to the stack
Deletes the first item , reducing length of vector
ram :vec :int x = [1, 2, 4]
vec x shift
// x = [2, 4]
Maps are like dicts in python, or objects in JavaScript. They hold key value pairs.
main:
ram lx 100
ram :str x = "test"
ram var :map
insert var { 10: "temst" }
insert var { x: 12 }
delete var 10
ram t :str = ""
get var 10 = t
dbg
This does not yet work with registers so you might have to use copy
to perform operations to it. This also supports nested maps which is pretty cool. Butterflies and vectors as keys are not yet implemented due to issues in deep comparisons.
Drops a variable. Use with caution.
ram x :str = "helloworld"
drop x
// cant access x, cleared from heap
- adds two numbers and pushes the result to the stack
ram 10
ram 20
add
// pushes 30 to the stack, removing the last 2 values
var x :int = 20
ram 10
add x
// adds x to 10 and pops 10 from the stack; pushing result on the stack
var x :int = 10
var y :int = 20
add x y
// pushes 30 to the stack
Works as same as add; subtracts the latest item of the stack from the previous.
ram 20
ram 5
add
// pushes 15 to the stack, removing the last 2 values
var x :int = 10
var y :int = 20
sub x y
// pushes -10 to the stack
multiplies two latest numbers on the stack and pushes the value back to it;
ram 5
ram 2
mul
// pushes 10 to the stack, removing the last 2 values
var x :int = 10
var y :int = 20
mul x y
// pushes 200 to the stack
the number added prior to the last number / last number and pushes to stack.
ram 10
ram 5
mul
// pushes 2 to the stack, removing the last 2 values
var x :int = 25
var y :int = 5
div x y
// pushes 5 to the stack
The program is devided into labels and we can jump on any label to execute the code block below it.
main:
ram 100
ram 300
cmp
jne not_equal:
cmp
je equal:
not_equal:
print Not Equal
equal:
print Equal
The main:
label is considered compulsory at the beginning of the program.
-
jmp <label:>
- jumps to the label -
cmp
pushes -1, 0, 1 to the stack if the previous number smaller, equal or greater than the number after it in the stack.
main:
ram 10
ram 20
cmp
print
// this will print -1 as 10 < 20
- cmp can also be used to compare two variables or registers:
main:
ram x :int = 100
ram y :int = 200
cmp x y
print
// prints -1
cmp y x
print
// prints 1
-
jne <label:>
- jumps to the label if the previous cmp statement is not 0 (not equal) -
je <label:>
- jumps to the label if the previous cmp statement is 0 (equal) -
jgr <label:>
- jumps to the label if the prev cmp statement is 1 (greater) -
jsm <label:>
- jumps to the label if the prev cmp statement is -1 (smaller)
Imports are restricted only to the main file. You can import as many files you want using include <filepath>
and then you shall be able to call all the codeblocks associated with the file.
// main.ram
include "ok.ram"
main:
print hello from main
jmp test:
// ok.ram
test:
print hello from ok.ram