Lua++

From Esolang
Jump to navigation Jump to search

Lua++

Lua++: The (in-development) Lua 5.1 superset, made by User: Alx.

Associated file extensions Descriptor
.lpp The non-compiled extension type recognised by the Lua++ interpreter.
.lppc The compiled extension type recognised by the Lua++ interpreter.

Lua++ - What is it?

Lua++ is a superset of Lua that changes the flow of how Lua programs are written to enhance readability and introduce new features into the language.

Lua++ - Types

The current implementation of Lua++ utilizes Python base types, being str, dict (as table), NoneType and int.

This may be changed in the future.

Lua++ - Features

1. Lua++ - Inplace operations

Lua++ introduces the ability to utilize inplace operators as shorthand alternative. Eg:

local ctr = 0
while ctr < 10 do
 ctr += 1
 print(ctr)

end

The existing inplace operators are:

Operator Descriptor
+= Inplace add operator.
-= Inplace sub operator.
*= Inplace multiplication operator.
/= Inplace true division operator.
//= Inplace floor division operator.
%= Inplace modulo operator.
^= Inplace pow operator.
&= Inplace bitwise AND operator.
= Inplace bitwise OR operator.
>>= Inplace bitwise left-shift operator.
<<= Inplace bitwise right-shift operator.
#= Inplace length operator. Is equivalent to integer += #"example".

2. Lua++ - Local initialization-as

In Lua++, you can initialize a local variable as an instance of a type, rather than it being none. Eg:

local int v

for i=0, 10 do
 v += i
end

It is syntaxically constructed as: local <T> <name> <, names>

It is NOT required for cases such as local v = 1, etcetera. But, you must specify a type if you are just declaring a variable with no value. For nil/None, you can use local None v.

3. Lua++ - Statement Scopes

In Lua++, statements, i.e the if-statement, while-statement and all other statements do not have scopes of their own. Eg:

if true then
 local int i
end

i += 1

4. Lua++ - Function call argument unpacking

Values can be unpacked as arguments in Lua++ via the * symbol. The unpackable is expected to be a table/dict. Eg:

local args = {1, 2, 3, 4}
local positional_argument = "I'm an argument"
print(*args, positional_argument)

5. Lua++ - Varargs

Varargs are not notated by the ... symbol. It is notated by the same symbol that unpacking is, and a name must be specified as the varargs variable, as it holds the varargs in a table. Eg:

local function f(pos1, pos2, *var)
 local int i local res = pos1 + pos2
 for i=1, #var do
  print(var[i])

 end
 return res

end

print(f(4, 10, 11, 12, 13))

6. Lua++ - String Slicing

String slicing in Lua++ is done by making a general index on a string, then specifying a start and stop seperated by two dots. Eg:

local string, start, stop = "hello world", 2, 7
print(string[start..stop])

7. Lua++ - String Indexing

Strings can be indexed to retrieve a character. String indexes start at 0, unlike tables, which start at 1. Eg:

local s = "example"
print(s[0])

8. Lua++ - Additional Hexadecimal Literal Notation

In Lua++, hexadecimal literals can be written with an 0x / 0X prefix, or end in h / H. Eg:

local ints = {
 80H,
 4Eh,
 0A3h,
 0FEH
}

Of course, leading 0's must be prefixed to a literal if using the latter syntax, to avoid confusion with an identifier.

9. Lua++ Classes, Class Inheritance

Classes in Lua++ are defined as a normal table, with an initializer. Class metamethods can be defined in the same table as normal methods. The & symbol can be used before a class to perform a shallow copy of the class, and prepare it for instantiating. Eg:

class = {
 initialize = function(self)
  self.tbl = {}

 end;


 set = function(self, key, value)
  self.tbl[key] = value

 end
}

instance = &class
instance2 = &class

instance:initialize()
instance2:initialize()

instance:set(5, 10)
instance2:set(5, 11)

print(instance.tbl)
print(instance2.tbl)

Class inheritance can be done by creating a class and then parenthesizing a class name as the class to inherit from. (Note that inherited classes are always local) Eg:

local basecls = {
 init = function(self, num)
  self.num = num

 end;

 add = function(self, num)
  self.num += num
  return self.num

 end;
}

extcls(basecls) = {
 mul = function(self, num)
  self.num *= num
  return self.num

 end
}


local instance = &extcls
instance:init(5)

print(instance:add(5))
print(instance:add(10))
print(instance:mul(15))
print(instance:mul(20))

10. Lua++ - Importing

Importing a module can be done with the import or require function. Both are aliases to the same function. Eg:

local module = import "mymodule"
module.module_function()

11. Lua++ - break Keyword

The break keyword does not exist in Lua++. Use gotos instead.

12. Lua++ - Arithmetic Operators

All standard Lua 5.1 operators are supported, with the addition of the following operators:

Symbol Descriptor
< Bitwise left-shift.
>> Bitwise right-shift.
// Floor division.
I Bitwise OR.
& Bitwise AND.
~ Bitwise XOR.

Lua++ - Builtins

The following table notates some Lua++ builtins and default variables as of Lua++ version Lua++ Stbl r2.

Builtin Name Descriptor
_G Contains the global scope table/dict.
math Builtin library containing mathematical functions.
io Builtin library containing IO-related functions.
table Builtin library containing table-related functions.
os Builtin library containing OS-related functions.
_VERSION Current Lua++ version as a string.
b Encodes a string into a bytes string.
str String type object instantiator.
type Returns type name of object as a string.
dict Dict/table type object instantiator.
int int type object instantiator.
assert Assertion function.
tostring Typecasts an object to a string.
tonumber Typecasts a string to an integer.
print Writes objects as strings to stdout.
pcall Calls a function. If fails, returns False. Does not stop program.
error Stops the program with an optional error note.
require Module importer function.
import Module importer function.
input Retrieves input from stdin.

LUAPP VM Notes

The Lua++ Virtual Machine operates on a CISC ISA and is a stack machine.

LUAPP VM Specs

Lua++ VM ISA

The Lua++ Instruction Format is notated as follows:

Instruction Size Type: Fixed
Instruction Size: 40bi

Instruction Type A:
 Opcode: 6bi
 Opmode: 2bi
 Operand A: 8bi
 Operand B: 8bi
 Operand C: 8bi
 Operand D: 8bi

Instruction Type B:
 Opcode: 6bi
 Opmode: 2bi
 Operand A: 16bi
 Operand B: 16bi

Instruction Type C:
 Opcode: 6bi
 Opmode: 2bi
 Operand A: 32bi

The following table notates all Lua++ instructions.

Opcode Name Descriptor
LDVAR Loads a variable onto the stack. Checks locals before globals.
GENSUB Performs subscription on values. If operand A is 0, the subscriptable is assumed to be the topmost stack item. The index is assumed to be a number as operand B. If operand A is 1, the subscriptable is also assumed to be the topmost stack item. Operand B points to a constant in the constants pool to be used as the index for the subscriptable. If operand A is 2, Both the subscriptable and the index is assumed to be on the stack.
LDFLOAT Obselete opcode. Floats are stored in the constants pool.
LDKST Loads a constant from the constants pool onto the stack. Operand A points to the index in the constants pool for the constant.
LDULONG Loads operand A onto the stack, which is an unsigned 32-bit integer.
SETVAR Pops an item off the stack as the value, and stores it under the name of the variable pointed to in the constants pool by operand A. Stores in the local scope if the name has been defined. Stored as a global if not.
SETGENSUB Pops 3 items off the stack, being the index, subscriptable and finally the value. Stores the value under the key of the subscriptable.
JMPABS Jumps to the offset pointed to by operand A.
JMPTST Conditionally jumps to the offset pointed to by operand A if the topmost stack item is False. Topmost stack item is popped.
CMPOP Pops two items off the stack, and compares them, the comparator being pointed to by operand A.
AROP Arithmetic handler. If operand A is 0, the operands for the operation are stored as 8-bit integers in operand C and operand D. If operand A is 1, the operands for the operation are assumed to be on the stack and are popped off. Operand B points to the operation to do.
LGOP Logical operator. If operand A is 0, handles unary operations. If unary and operand B is 0, pushes the unary negative of the topmost stack item. If unary and operand B is 1, pushes the logical unary NOT of the topmost stack item. If unary and operand B is 2, pushes the unary negative of the topmost stack item. If operand A is 1, the operation is no longer a unary operation. Operand A now points to the operands for the operation and decides if they are on the stack or as operand C or operand D. If operand B is 0, pushes a logical AND of the operands. If operand B is 1, pushes a logical OR of the operands.
LDBOOL If operand A is 0, pushes False to the stack. If operand A is 1, pushes True to the stack. If operand A is 2, pushes nil/None to the stack.
FORLOOP Pushes the next value from the assumed iterator on the top of the stack. If the iterator is exhausted, jumps to offset pointed to by operand A and pops the topmost stack item.
SETUPFOR Creates an iterator on the top of the stack for an assumed for-loop.
MKTABLE Creates a new table consuming x*2 amount of items from the stack pointed to by operand A, assumed to be the key and then the value. Pushes the created table once finished.
ASMPROTO Assembles a proto into a closure, the proto assumed to be the topmost stack item. Operand A tells the proto assembler if it is varargs, or not.
ALLOC Declares a local variable. If operand A is 0, initializes variable as nil/None. If operand A is 1, it is instantiated as an instance of a type pointed to by operand C in the constants pool. If the type is not found in either scopes, the variable is instantiated as nil/None.
DISCARD Removes the topmost stack item.
CALL First calling convention, consuming x amount of items from the stack pointed to by operand A. The callable, retrieved by its name in the scope, or in the global scope if it is not found in the local scope.
CALLSAFE Second calling convention, also consuming stack items pointed to by operand A. The callable is assumed to be on the stack, and popped off.
CALLSPLAT Third calling convention for splatting / unpacking an unpackable as arguments for a function call. The arguments are assumed to be on the stack as one table, and so is the callable.
INSERT Pops two items off the stack, assumed to be a value and then a table. Inserts the value at the highest index +1 of the table.
EXTEND Pops two items off the stack, assumed to be a two tables, and extends / combines them.
SLICE Performs string slicing. If operand A is 0, the slices are assumed to be on the stack. If operand A is 1, the slices are assumed to be operand B and operand C. The sliceable is always assumed to be on the stack.
GETLEN Pops an item off the stack and pushes back the length of it.
RETURN If operand A is 0, pops an item off the stack and returns it. If operand A is 1, returns operand B as an integer. If operand A is 2, returns an item from the constants pool pointed to by operand B.
INSTANTIATE Performs a shallow copy of the topmost stack item.
MERGEMETH Pops two items off the stack, and merges them. Used for class inheritance.