Skip to content

Instantly share code, notes, and snippets.

@44100hertz
Last active May 26, 2022 18:32
Show Gist options
  • Save 44100hertz/e80c9ff959996f50c3a069b19359fb1e to your computer and use it in GitHub Desktop.
Save 44100hertz/e80c9ff959996f50c3a069b19359fb1e to your computer and use it in GitHub Desktop.
Possible lua extension concepts

Extended Lua concept

Intro

This is a pet project of mine, a sort of thought experiment about what would fit into lua without breaking convention (except the minimalist convention lol). I think many of the elements could combine into a new language, but there is no current plan to do that.

Goals

  • Make lua more pleasent
  • Maintain lua conventions
  • Stay intuitive to a lua programmer
  • Avoid breaking most lua code, though will add keywords
  • Improve signal to noise, but not too dense
  • Have fun

Non-Goals

  • Bikeshedding syntax
  • Investigating edge cases (for now)
  • Making things familiar to programmers of X language
  • Importing OOP or FP concepts directly
  • ‘magic’ or heavily abstracted features

Sources

This URL has some patches and documentation, which are later linked to in this file as examples of what has been made. http://lua-users.org/wiki/LuaPowerPatches

I am also examining moonscript for ideas: https://moonscript.org/reference

Extensions

do expression

local x, y = do
  local a,b = 10,20
  give a * b, a + b
end
-- Turns into (roughly)
local x, y
do
  local a,b = 10,20
  x,y = a * b, a + b
end

if expression

local t = if cond then
  give 10
else
  give 20
end
-- Turns into (roughly)
local t
if cond then
  t=10
else
  t=20
end

for expression

loop expressions introduce the new form break x which exits the loop and returns value x from the loop.

-- For expression --
local i,v = for i,v in ipairs(t) do
  if v == 8 then
    break i,v
  end
end
-- Functions like
local i,v
for _i,_v in ipairs(t) do
  if _v == 8 then
    i,v = _i,_v
  end
end

through expression

Similar to ‘for’, but is an expression that operates on a temporary table which is returned to lhs.

In moonscript: https://moonscript.org/reference/#the-language/comprehensions

local multiples_of_2 = through i = 1,10 do
  give i * 2
end
-- Gives {2,4,6,8,10,12}

local my_list = through i, v in {1,2,3,4,5,9} do
  if v ~= 4 then
    give v * 2
  end
end
-- Gives {2,4,6,10,18}

local tab = {{1,0,1},{2,0,2},{3,0,3}}
local doubled = through _,v in tab do
  give through _,w in v do
    if w > 0 then
      give w * 2
    end
  end
end
-- Gives {{2,2},{4,4},{6,6}}

local backwards_map = through k,v in {a=10, b=20, c=30} do
  give v=k
end
-- Gives {[10]='a', [20]='b', [30]='c'}

short const (5.4 only)

This interacts nicely with the expression extensions, allowing for flexible constant initialization.

const x=2, <mut>y=3, <close>z = 4
-- Turns into
local <const> x=2, y=3, <close> z = 4

self-iterating Objects

This patch gives a default way of handling ‘for’ http://lua-users.org/files/wiki_insecure/power_patches/5.3/jh-lua-iter-5.3.1.patch

for x in y do ... end
-- Turns into (roughly)
local function iter (t)
    local mt = getmetatable(t)
    if type(t)=='function' or mt.__call then
       return t
    else
       if mt.__iter then
          return mt.__iter(t)
       else
          return ipairs(t)
       end
    end
end
for x in iter(y) do ... end

toliteral (built-in serialization)

toliteral could serialize to a lua expression to a functional piece of code.

assert(toliteral(true) == 'true')
assert(toliteral('hello') == '"hello"')
assert(toliteral(100) == '100')

This could be used in debug prints.

For tables, toliteral({'hello', a='b'}) could turn into {[1] = 'hello', ['a'] = 'b'} or similar.

Destructuring Assignment

http://lua-users.org/files/wiki_insecure/power_patches/5.2/unpack-5.2.2.patch

-- This already works:
local a, b = unpack{10, 20}
-- This patch allows for this:
local a, b in {a=10, b=20}
-- Which would mean:
local t = {a=10, b=10}
local a, b = t.a, t.b

I like this, but I want to extend it so that local vars can be renamed to something other than a field of the expression. local {a, c=b} in {a=10, b=20} or something along those lines.

easier runtime type checking

Function type guards

Allow type checking for function arguments. If arguments don’t match the provided type(s), throw an error.

Lua should make sure the default value matches the type specified in the type guard, if applicable.

function (:number: x, :table|number:y, :string:z = 'ree', :!nil:zz)
   ...
end
-- Turns into (roughly)
function (x,y,z,zz)
   assert(type(x)=='number')
   assert(type(y)=='table' or type(y)=='number')
   z = z or 'ree'
   assert(type(z)=='string')
   assert(not type(zz)=='nil')
   ...
end

Possible type specifiers:

  • table|number for multiple possible types
  • !nil or !table to exclude a type
  • integer is a number with no fractional component
  • number[0,9] is a number >= 0 and <= 9
  • number(-5,9) is a number > -5 and < 9

metamethod

A __type or __class metamethod could make this a bit more effective.

Default Args

function (x, y=2, z=y)
   ...
end
-- Turns into
function (x, y, z)
   y = (y~=nil) or 2
   z = (z~=nil) or y
   ...
end

Compound Assignment Operators

This patch adds += -= *= /= as well as <<= >>= &= |= ^=. http://lua-users.org/files/wiki_insecure/power_patches/5.4/plusequals-5.4.patch

Assign-operator metamethods

I want to add __addassign, __subassign, __mulassign, __divassign, and possible same for bitwise ops. These would fall back on __add, etc.

table library functions

table.merge({a=1, b=2}, {z=1, 10})
-- Gives
{10, a=1, b=2, z=1}

table.deepcopy({a=1, b=2, {c=3}})
-- Gives an identical copy of the table. Will not copy metatables. Unsure what
-- intended behavior is for reference loops.

Question mark indexing

turns t?.u?.v into t and t.u and t.u.v http://lua-users.org/files/wiki_insecure/power_patches/5.2/safe2.patch

Set Constructor Shortcut

This patch enables alternate syntax, good for ‘set’ types http://lua-users.org/files/wiki_insecure/power_patches/5.3/jh-lua-setinit-5.3.1.patch

{.cat, x=true} turns into {cat = true, x = true} among other things. I do think it may be more useful to set things to 1,2,3 etc. instead of ‘true’ because it would allow for a sort of enum type.

Function fields

Allows obj = {function x () end} to mean obj = {x = function (self) end} http://lua-users.org/files/wiki_insecure/power_patches/5.2/oofunc.diff

Boolean ‘xor’

<a> xor <b> -- Assume <a> and <b> are expressions
-- Turns into
local a,b = <a>,<b>
(a and (not b) and a) or ((not a) and b)

Extra Number literals

Binary numbers: http://lua-users.org/files/wiki_insecure/power_patches/5.2/jh-lua-bin-5.2.1.patch

Octal numbers may be wanted. Also, being able to put underscores in number literals would make large numbers easier to read.

__tonumber metamethod

Returns a number representing an object’s value. This would help with handling of numerical-representative types such as fractions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment