As a Roblox dev, I’m very used to Lua and it’s actually my favorite scripting language (yet). I am also a Minecraft dev, but the only language available is Java, and it’s not quite my type…
Well there is a plugin that makes you code more easily called Skript, but I don’t like it at all
Because of that, I decided to code my own language (that’s similar to Lua) in Java for a plugin that allows me to script the systems (instead of doing it in Java, like a normal plugin) No, the name of the language is not Lua++, I haven’t decided yet
Current status: Interpreted Scripting Language
Suggestions / Ideas are highly appreciated!
Here’s how it works (latest updates, this message will be edited)
// Comment
-> Comment
-- Comment
do -- you can have scope blocks like this if you want
console("Epic World!")
end
-- VARIABLES
x -- global, nil by default
y = 5
local m1, m2, m3 = 1, 2 -- m3 is nil by default
local final f: nil, string -- nil by default
f = "final variable" -- if final variable is nil (has not been set yet) you can still set it later
local ternary = true and 5 or 3 -- gets 5
local anotherTernary = false or nil or 5 or 10 -- gets 5
x = y = 2 -- chain assignment, translated to x = (y = 5)
x++*/ -- chain operators, translated to x = ((x+1+1)^2)/2 so 8
-- FUNCTIONS
local function lol(arg1, arg2: number = 5) -- params can be separated by , or ; (new line)
console(arg1, arg2) -- default param is set by an =, and its set if its not sent
end
lol(2) -- arg2 will be 5 by default
lol(2, nil) -- arg2 will be nil
local final div = function(x: number; y: number = 2)
return x / y -- separated by ; else it will take y as a type
end
local function print(final args...: string) -- variadic function
for k, v in args do -- its just like a normal parameter, only it has the ... suffix
console("[" + k + "] = " + v)
end
end
-- LOOPS + IF
if true then console(true) end
for i=1, 10 do console(i) end
for i=1, 10, 2 do console(i) end
while true do break end
do break while true
-- ASYNC
-- Runs in another thread
async for i=1, 10 do console(i) end
async lol()
async do console("async") end
-- TABLES
local tbl: {} = {
3, 4, 5 -- by default it starts indexing at [1]
msg = "hi" -- separate either by , or ; (which is a new line)
local x: bool = true
meh = function() console("meh") end
epic = function() console(self) end
}
local strictTable: {number, {string}} = {1, 2, 3, {"lol"}}
console(tbl[2]) -- 4
console(tbl.msg) -- hi
console(#tbl) -- 7 (lengthOf can be applied to strings also)
tbl.meh() -- meh
tbl:meh() -- meh
tbl.epic() -- nil
tbl:epic() -- <tbl>
-- so by calling a function using : it will automatically set self to be that table
for k, v in tbl do -- for-each loop, used for tables (the value is optional)
console("[" + k + "] = " + v)
end
.java files are translated into .class files by the java compiler, which is bytecode. So I guess lua++ being interpreted would mean it is read by a java lua++ parser?, while lua++ being compiled would mean it is read by the java virtual machine directly?
local function div(x: number; y: number; final args...: string) -- just like a normal param, only with ...
for k, v in args do console("[" + k + "] = " + v) end
return x / y
end
div(4, 2, "yey", "lol", "epic is hot")
self is automatically sent as the first argument in a function, so it exists no matter what.
local function lol(x: number)
console(self, x)
end
-- translated as
local function lol(self, x: number)
console(self, x)
end
lol(5)
-- translated to
lol(nil, 5)
This has to do with how globals are referenced & interpreted if non existent in environment.
This is an example:
self = 2
local function test()
print(self) --outputs 2
end
local function test2(self)
print(self) --outputs nil
end
test()
test2()
Self in function context doesn’t mean anything. If you define a function like so, part of a table:
local t = {}
function t.test()
print(self) --outputs variable value of upper scope // global scope
local self = 2 --You can redefine self yourself
end
This writing is the same as
local t = {
test = function() ... end
}
However when you write
local t = {}
function t:test()
print(self) --ouputs parameter self, which is here inferred
local self = 2 --Cannot redefine as self exists as 1st param
end
It’s mostly because the example you provided demonstrates that self is nil, it’s mostly because it’s undefined in global scope, not because it is defined as 1st silent param. I just tested that out on luau-lang to be sure about that
Another example being
function k(x)
print(x)
end
local t = {
k = k
}
t.k(1) --outputs 1
t:k(1) --outputs table0x<@>
Param shifting only occurs whenever you use : on a table to get a function address, and then run the function. All params will be shifted to the right & the table address passed as 1st one
So actually, self is just a fancy keyword, you can see that x became self in my upper example
Right now I’m working on tables, and they will be a bit different from the normal Lua tables, and then I’ll improve the self keyword also, maybe I’ll find more usages for it
I may have missed this information, but out of curiosity, which tools are you using to syntaxic analysis? And yes ! It’s a great thing to make your own project & establish a language
I actually had to do it this year as a project, we used LR analysis with Lex&Yacc, only for the syntaxic part though, not for stack & memory management