Using the Luart syntax extensions

By Samir Tine, published on April 2026

Introduction

Since version 2.2.0, Luart includes a powerful built-in preprocessor that extends the standard Lua syntax with modern features. To enable the preprocessor in a script, you must add the following directive to the very first line of your Lua script:

--! luart-extensions

You can view exactly how the preprocessor translates your extended syntax into standard Lua code. By using the -p option with the LuaRT interpreter, the parsed code will be printed directly to the standard output instead of being executed:

luart.exe -p myscript.lua

String Interpolation

The preprocessor makes string formatting effortless. You can inject variables and expressions directly into double or single-quoted strings using the ${} syntax :

local framework = "LuaRT" local version = 3 print("Welcome to ${framework} version ${version/2}")

import

Loading modules is simplified with the import keyword, providing a much cleaner alternative to standard require calls. You can even import multiple modules on a single line. Each imported modules are affected to a local variable with the same name :

import ui --> local ui = require "ui" import net, crypto --> local net = require "net"; local crypto = require "crypto" -- use the imported modules as usual local window = ui.Window("My Window", 800, 600) window:show()

class

Creating Objects is more intuitive with the dedicated class syntax. You can define properties and methods directly inside the class block without needing external table declarations. Inside a class definition, each field is terminated by a newline (no more comma as with tables), and for methods, the self argument is implicit :

class Animal { name = "Unknown" function speak() print(self.name .. " makes a sound.") end } local dog = Animal() dog.name = "Rex" dog:speak()

try..catch...end

Handling errors gracefully is now possible with try and catch blocks :

try local f = io.open("nonexistent.txt", "r") local content = f:read("*a") catch err print("Failed to open file: " .. err) end

async & await

Luart syntax extensions permits seamless asynchronous code execution. Use async function to define a Task factory : each time a Task factory is called, a new Task with the given function is started.

-- Declares a Task factory async function fetch_data() -- mimics fetching data for 2sec sleep(2000) return "Data loaded successfully" end -- Start a new task using fetch_data local task1 = fetch_data() -- Start a new task using fetch_data local task2 = fetch_data() waitall()

The await syntax extensions is used to pause current execution until the followed task (or function wrapped as a launched Task) completes :

-- Declares a Task factory async function fetch_data() -- mimics fetching data for 2sec sleep(2000) return "Data loaded successfully" end -- Start a new task using fetch_data local task1 = fetch_data() local result = await task1 print(result)

The await syntax expects a function or a Task, so the previous example can be simplifed :

-- Declares a Task factory async function fetch_data() -- mimics fetching data for 2sec sleep(2000) return "Data loaded successfully" end print(await fetch_data())

As you can see, Luart preprocessor is a simple way to extend Lua syntax while still providing full compability with standard Lua scripts (if not used). You are now ready to write cleaner, more modern Lua code !