Luasm

= Luasm =
Luasm: The mid-level Lua compiler, made by User: Alx. (Aliases: LLua, LuaW, LuaF)
== Luasm - What is it? ==
Luasm, as the name suggests, is a mid-level Lua derivative, designed with performance in mind, and a routine for doing mid-level programming in a high-level sense.
Luasm aims to be like C, in the way that it is memory-oriented, except without all of the extra confusing jargon which comes along with C, but keeping fundamental practices.
In comparison to Lua, there are a number of syntactical differences, and a lot of semantic differences, the main semantic difference being that it is not object-oriented (as aforementioned implicitly).
The Luasm compiler utilizes the Lua++ syntax, and is also syntactically compatible, though operators and general flow is extremely different.
== Luasm - Semantics ==
=== Semantics: Syntactical Differences ===
In Luasm, there are two more unary operators, being the * (read/write memory) operator, and the & (get memory address) operator. Pointers in Luasm in comparison to C are quite different, in the way that
they do not require declaration, and they are arguably not too similar understanding them and how they work. Unlike in C, the read/write memory operator may take any operand as long as it is a valid
memory address, and then read from / write to that position in memory. E.G:
-- Initialize value to 1, write value `123` to the address of value, print value, and memory address of value.
function main(PE_CONSOLE)
 value = 1
 -- [[ you could also construct C-like pointers like so:
 value = 1
 ptr = &value
 *ptr = 1 -- write value at memory address
 ptr = &othervalue -- change memory address ptr points to
 ]]
 *(&value) = 123
 printf("%d, %d\n", value, &value)
end
In Luasm, you can also `create types`, by using the struct keyword, and then instantiate it via a function call. E.G:
function main(PE_CONSOLE)
 struct "structure" --[[must be string and not identifier for parsing purposes]] {
 member_a;
 member_b;
 }
 instance = structure(123, "456") -- the memory address of the string will be member_b.
 printf("%d\n", instance.member_a) -- 123
 printf("%s\n", instance.member_b) -- 456
end
In Luasm, inplace arithmetic operators also are supported. E.G:
function main(PE_CONSOLE)
 v = 1
 while v < 10 do
 printf("%d\n", v)
 v += 1
 end
end
In Luasm, array indexes start at 0. E.G:
function main(PE_CONSOLE)
 arr = {1, 2, 3}
 for i=0, 2 do
 printf("The %d-nth element of the array is %d.\n", i, arr[i])
 end
end
In Luasm, since array types are always numbers (non-numbers, such as strings, are passed as addresses if defined within the array), strings can be mutated and index using the get_char and set_char functions. E.G:
function main(PE_CONSOLE)
 string = "hello world"
 set_char(string, 1, 97) -- // string[1] = 'a';
 printf("%s\n", string)
end
=== Semantics: Typing ===
In Luasm, there exist conceptual types, being number, string and array. There is no static typing, or type declaration in Luasm, a partial reason being binary width. Here is an example of instantiating such types:
function main(PE_CONSOLE)
 my_number = 1234 -- // uint32_t my_number = 1234;
 my_array = {1, 2, my_number} -- // uint32_t my_array[] = {1, 2, my_number};
 my_string = "hello" -- // uint8_t my_string[] = "hello";
 my_empty_string = new_string(256, 0) -- preprocessor directive // uint8_t my_empty_string[256];
 my_empty_array = new_array(256, 0) -- preprocessor directive // uint32_t my_empty_array[256];
end
As aforementioned, you can create and instantiate your own `types` as structs.
=== Semantics: Microsoft API Compatibility ===
The Microsoft API (32 bit) utilizes the __cdecl calling convention, in which the caller clears up the stack, as opposed to the callee, which would be __stdcall.
Due to vararg functions, it is assumed that every function uses the __cdecl calling convention unless explicitly declared otherwise. A Microsoft API function also
usually must be bound to the memory-indexing invoking method, in which the __mcall directive tells the compiler to use such an invocation method. E.G:
function main(PE_CONSOLE)
 import "time" __mcall(time) -- // from msvcrt
 import "srand" __mcall(srand)
 srand(time(nil))
end
=== Semantics: Importation and Inclusion ===
There exist two preprocessor directives to import modules, being the "import" directive and the "include" directive. The include directive expects a FASM source file path, which
is statically appended, whereas the import directive expects a function name to import. If not found in msvcrt, a library must be prepended to the name, via a dot. E.G: import "library.function"
. I forgot to write support for Luasm source-including, I'll probably add that soon.
=== Semantics: Entry point ===
The entry point must be named `main`, and must have a parameter of either PE_CONSOLE, or PE_GUI, to specify the application interface type.
== Luasm - How does it work? ==
Luasm compiles straight to FASM/A (Flat Assembler Assembly), via an AST. The code is generated through recursive node visiting, and utilizing the stack if no node optimizations can occur, which
in turn creates very inefficient, redundant and slow assembly code. A redundant instruction omitter and peephole optimizer will organise, and optimize the code, ensuring that most redundancies
and slow instruction sequences are rectified and improved.
* Luasm is explicitly 32-bit, therefore using 8/16/32 bit registers, and operands.
* Return values for Luasm functions are passed through the EAX register, changed from moving to a DWORD RETURN memory address belonging to the function.
* The most common registers used are EAX, EBX and ESP.
* Luasm utilizes the __cdecl calling convention.
== Luasm - Example Programs ==
=== Hello World ===
function main(PE_CONSOLE)
 printf("Hello world!\n")
end
--[[
STDOUT: Hello world!
]]
=== 99 Bottles of Beer ===
function main(PE_CONSOLE)
 bcount = 99
 while bcount > 0 do
 if bcount > 1 then
 printf("%d bottles of beer on the wall,\n%d bottles of beer\n", bcount, bcount)
 printf("Take one down, pass it around,\n")
 bcount = bcount - 1
 printf("%d bottles of beer on the wall.\n\n", bcount)
 elseif bcount == 1 then
 printf("%d bottle of beer on the wall,\n%d bottle of beer\n", bcount, bcount)
 printf("Take one down, pass it around,\n")
 bcount = bcount - 1
 printf("No more bottles of beer on the wall.\n")
 goto end_beer
 end
 end
 ::end_beer::
end
--[[
STDOUT:
99 bottles of beer on the wall,
99 bottles of beer
Take one down, pass it around,
98 bottles of beer on the wall.
98 bottles of beer on the wall,
98 bottles of beer
Take one down, pass it around,
97 bottles of beer on the wall.
97 bottles of beer on the wall,
97 bottles of beer
Take one down, pass it around,
96 bottles of beer on the wall.
...
3 bottles of beer on the wall,
3 bottles of beer
Take one down, pass it around,
2 bottles of beer on the wall.
2 bottles of beer on the wall,
2 bottles of beer
Take one down, pass it around,
1 bottles of beer on the wall.
1 bottle of beer on the wall,
1 bottle of beer
Take one down, pass it around,
No more bottles of beer on the wall.
]]
=== ROT13 Cipher ===
function rot13(straddr)
 for i=0, 0ffffh do
 char = get_char(straddr, i)
 if char == 0 then
 goto end_rot
 elseif (char < 96) & (char < 123) then
 goto start_rot_again
 end
 sum = char + 13
 if sum > 122 then
 sum = (sum % 123) + 97
 end
 set_char(straddr, i, sum)
 ::start_rot_again::
 end
 ::end_rot::
 return 1
end
function main(PE_CONSOLE)
 text = "hello world!\n"
 rot13(text)
 printf(text)
 rot13(text)
 printf(text)
end
--[[
STDOUT: uryyb jbeyq!
 hello world!
]]
=== Truth machine ===
function main(PE_CONSOLE)
 d = new_string(2, 0)
 scanf("%d", &d)
 if d == 1 then
 while true do
 printf("1")
 end
 elseif d == 0 then
 printf("0")
 end
end
--[[
STDIN: 1
STDOUT: 1111111111...
STDIN: 0
STDOUT: 0
]]
=== Palindrome ===
function main(PE_CONSOLE)
 v = new_string(1024, 0)
 scanf("%s", v)
 printf(v)
 c = 1024
 while c >= 0 do
 printf("%c", get_char(v, c))
 c -= 1
 end
end
--[[
STDIN: hello
STDOUT: helloolleh
]]
Category:Languages
Category:Implemented
Category:Turing complete