All Projects → gnois → Luaty

gnois / Luaty

Licence: other
Lua with more or less typing. You type less; we type check.

Programming Languages

lua
6591 projects
language
365 projects

Labels

Projects that are alternatives of or similar to Luaty

Castl
JavaScript to Lua compiler with runtime library.
Stars: ✭ 323 (+3488.89%)
Mutual labels:  luajit
Nelua Lang
Minimal, efficient, statically-typed and meta-programmable systems programming language heavily inspired by Lua, which compiles to C and native code.
Stars: ✭ 438 (+4766.67%)
Mutual labels:  luajit
Luaradio
A lightweight, embeddable software-defined radio framework built on LuaJIT
Stars: ✭ 509 (+5555.56%)
Mutual labels:  luajit
Apioak
Full Lifecycle Management API Gateway.
Stars: ✭ 335 (+3622.22%)
Mutual labels:  luajit
Ledge
An RFC compliant and ESI capable HTTP cache for Nginx / OpenResty, backed by Redis
Stars: ✭ 412 (+4477.78%)
Mutual labels:  luajit
Picolove
PICO-8 Reimplementation in Love2D
Stars: ✭ 467 (+5088.89%)
Mutual labels:  luajit
Luajit.io
luajit io framework
Stars: ✭ 277 (+2977.78%)
Mutual labels:  luajit
Raptorjit
RaptorJIT: A dynamic language for system programming (LuaJIT fork)
Stars: ✭ 784 (+8611.11%)
Mutual labels:  luajit
Debugger.lua
A simple, embedabble CLI debugger for Lua.
Stars: ✭ 426 (+4633.33%)
Mutual labels:  luajit
Apisix
The Cloud-Native API Gateway
Stars: ✭ 7,920 (+87900%)
Mutual labels:  luajit
Neogfx
Cross-platform GPU-oriented C++ application/game framework
Stars: ✭ 362 (+3922.22%)
Mutual labels:  luajit
Luaposix
Lua bindings for POSIX APIs
Stars: ✭ 393 (+4266.67%)
Mutual labels:  luajit
Luv
Bare libuv bindings for lua
Stars: ✭ 466 (+5077.78%)
Mutual labels:  luajit
Luvit
Lua + libUV + jIT = pure awesomesauce
Stars: ✭ 3,443 (+38155.56%)
Mutual labels:  luajit
Grid Sdk
The Grid SDK - Game engine for Lua
Stars: ✭ 612 (+6700%)
Mutual labels:  luajit
Lua re
reverse engineering for lua(lua/luac/luajit/lua_dec/lua_loader/lua_proc)
Stars: ✭ 299 (+3222.22%)
Mutual labels:  luajit
Completely Unscientific Benchmarks
Naive performance comparison of a few programming languages (JavaScript, Kotlin, Rust, Swift, Nim, Python, Go, Haskell, D, C++, Java, C#, Object Pascal, Ada, Lua, Ruby)
Stars: ✭ 440 (+4788.89%)
Mutual labels:  luajit
Liko 12
LIKO-12 is an open source fantasy computer made using LÖVE.
Stars: ✭ 811 (+8911.11%)
Mutual labels:  luajit
Lua Nginx Redis
🌺 Redis、Lua、Nginx、OpenResty 笔记和资料
Stars: ✭ 757 (+8311.11%)
Mutual labels:  luajit
Turbo
Turbo is a framework built for LuaJIT 2 to simplify the task of building fast and scalable network applications. It uses a event-driven, non-blocking, no thread design to deliver excellent performance and minimal footprint to high-load applications while also providing excellent support for embedded uses.
Stars: ✭ 480 (+5233.33%)
Mutual labels:  luajit

Luaty is yet another indent sensitive language, with some opinionated syntax that compiles to Lua. It comes with an optional type checker with limited type inference.

Differences from Lua

Less syntax boilerplates

  • no more end
  • no more do after for and while
  • no more then after if

Minor syntactical changes

  • repeat becomes do
  • elseif becomes else if
  • local becomes var
  • [[ and ]] become backquote(s) ` that can be repeated multiple times
var x = false               -- `var` compiles to `local`
if not x
   print(`"nay"`)           -- `then` and `end` not needed, `"nay"` compiles to [["nay"]]

--`` this is a long
comment ``

Literal string or keyword as table key

var z = {
   'a-str' = 'a-str'                         -- string as key
   , var = 7                                 -- works as in Lua
   , local = 6                               -- keyword as key
   , function = 5
   , if = \...-> return ...
   , goto = {true, false}
}
assert(z.var == 7)                           -- ok, z.var works as in Lua
assert(z.if(z.goto)[2] == false)             -- works

Mostly desugared functions

  • function is defined using lambda expression with -> or \param1, param2, ... ->
  • function call always require parenthesis
  • colon : is never used. Use self or @ as the first paramenter or call argument instead

function f(x)                       -- error: use '->' instead of 'function'
\x -> print(x)                      -- error: lambda expression by itself not allowed
(\x -> print(x))(3)                 -- ok, immediately invoked lambda
var f = -> print(3)                 -- ok, lambda is assigned, \ optional if no parameter

print 'a'                           -- error: '=' expected instead of 'a'; but this is valid in Lua
print('a')                          -- ok obviously

var obj = {
   value = 3
   , foo = \@, k ->
      return k * @.value            -- `@` compiles to `self`
   , ['long-name'] = \@, n ->       -- function with a special name
      return n + @.value
}

print(obj:foo(2))                   -- error: ')' expected instead of ':'
assert(obj.foo(@, 2) == 6)          -- ok, compiles to obj:foo(2)

var ox = -> return obj
print(ox()['long-name'](@, 10))    -- `@` *just works*, get() is only called once

The differences end here, so that a Lua file can easily be hand converted to a Luaty file. In return, we get

  • arguably shorter codes
  • forced local variable declaration
  • consistent function definition syntax
  • many linting features not unlike luacheck

Due to backquote replacing [[ and ]], long comments need one extra hyphen if we want to use the trick in https://www.lua.org/pil/1.3.html

-- Uncommenting long comment trick

--`
print(10)         -- commented out
---`              -- ** use 3 hyphens at the end of comment **

-- Now, if we add a single hyphen to the first line, the code is in again:

---`
print(10)         --> 10
---`

Builtin static analyzer and type checker

During compiling, Luaty warns about:

  • unused variables
  • shadowed variables in the parent or the same scope
  • unused labels and illegal gotos
  • assignment to undeclared (global) variables
  • assignment having more expressions on the right side than the left
  • duplicate keys in table constructor

It also strives to provide helpful error messages on typos or syntax errors.

An optional type checker can be enabled to check consistent usage of variables. Once enabled, it tries to infer a limited subset of Lua, but is probably wrong in non trivial cases for now. Improving the type checker is a work in progress. Lua code will be generated regardless of warning by the optional type checker.

a = 1                     -- undeclared identifier a

var c, d = 1, 2, 4        -- assigning 3 values to 2 variables

var p = print
var p = 'p'               -- shadowing previous var p

var f = \z->
   var z = 10             -- shadowing previous var z

var tbl = {
   x = 1
   , x = 3                -- duplicate key 'x' in table
}


-- when type checker enabled --
var j = \a -> return a
j(4, 5)                   -- function expects only 1 arguments but got 2

var k = \a -> return a + 0
k('s')                    -- function parameter 1 expects <num> instead of <str>

var p = {q = 5}           
p.q.r = 7                 -- assignment expects {} instead of <num>

Quick start

Luaty only requires LuaJIT to run. With LuaJIT in your path, create a command alias for luaty

Linux/Unix shell

alias luaty='/path/of/luajit -e "package.path=package.path .. '/path/to/luaty/?.lua'" /path/to/luaty/lt.lua'

Windows command prompt

doskey luaty=\path\of\luajit -e "package.path=package.path .. '\\path\\to\\luaty\\?.lua'" \path\to\luaty\lt.lua $*

To begin a REPL

luaty

To run a Luaty source file

luaty /path/to/source

source is assumed to end with .lt

Given a main.lt file with its required .lt files under its subfolders, Luaty can optionally compile and generate a complete mirror folder structure with .lua output. Suppose our source files are laid out like below, where main requires sub, which in turn requires foo and bar under lib folder:

/
├── src
│   ├── main.lt
    ├── sub.lt
    └── lib/
        ├── foo.lt
        ├── bar.lt
        ├── orphan.lt
        └── ...

To compile src/main.lt file and its dependencies to /dst

cd src
luaty main /dst

If compilation succeeds, the output should appear like below, with subfolders mirrored:

/
├── dst
│   ├── main.lua
    ├── sub.lua
    └── lib/
        ├── foo.lua
        ├── bar.lua
        └── ...

Since orphan.lt is not required, it will not be processed. Also, Lua package.path and dynamically constructed require() are not processed, because they are not statically resolvable.

Lua output files will not be overwritten if they exist. To force overwriting, use -f switch.

To compile only main.lt file without its dependencies, provide a destination ending with .lua

luaty [-f] path/main /out/main.lua

Destination without .lua is considered a folder, which will be created if it does not exist. For eg:

luaty -f main main.lt

The output main.lua and its dependencies goes into main.lt/*.lua, so that output file can never overwrite input.

For all the commands above, type checker can be enabled by adding -t switch.

To make and overwrite Luaty itself, use

luaty -f lt.lt .

To run tests in the tests folder, use

luajit run-test.lua

The detailed indent (offside) rule

  1. Either tabs or spaces can be used as indent, but not both in a single file.

  2. Comments have no indent rule.

  3. Blocks such as if, for, while, do and lambda expression -> can have child statement(s).

    • A single child statement may choose to stay at the same line as its parent
    • Multiple child statements must start at an indented newline
if true p(1)                    -- Ok, p(1) is the only child statement of `if`
p(2)

if true p(1) p(2)               -- Error, two statements at the same line, `if` and p(2)

do                              -- Ok, multiple child statements are indented
   p(1)
   p(2)

print((-> return 'a', 1)())     -- Ok, immediately invoked one lined lambda expression

if x == nil for y = 1, 10 do until true else if x == 0 p(x) else if x p(x) else assert(not x)
                -- Ok, `do` is the sole children of `for`, which in turn is the sole children of `if`

  1. A table constructor or function call can be indented, but the line having its closing brace/parenthesis must realign back to its starting indent level.
var y = { 1
   ,
   2}                    -- Error: <dedent> expected

var z = { 1
   ,
   2
}                        -- Ok, last line realign back with a dedent

print(
   1,
   2
   , 3,                  -- commas can be anywhere
4, 5)                    -- Ok, last line realign back to `print(`

  1. For single-lined function, semicolon ; can be used as function terminator if it causes ambiguity in a list of expressions. Note that any needed comma after the semicolon does not become optional.
print(pcall(\x-> return x, 10))                 -- multiple return values. Prints true, nil, 10

print(pcall(\x -> return x;, 10))               -- ok, single lined function ended with `;`. Prints true, 10

print(pcall(\x ->
   return x
, 10))                                          -- ok, same as above, function ended with dedent. Prints true, 10

var o = { fn = -> return 1, 2;, 3, 4 }          -- use `;` to terminate single-lined function
assert(o[2] == 4)

var a, b = -> var d, e, f = 2, -> return -> return 9;;, 5;, 7
assert(b == 7)                                  -- each `;` terminates one single-lined function

See the tests folder for more code examples.

Acknowledgments

Luaty is modified from the excellent LuaJIT Language Toolkit.

Some of the tests are stolen from official Lua test suite.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].