Nelua Programming Language

website·Indexed 32 days ago

https://nelua.io/

A minimal, efficient, statically typed, compiled, and metaprogrammable systems programming language. Documentation includes language fundamentals for Lua and C users, C library bindings, core primitives, and installation guides.

Tokens
29.8K
Snippets
188
Records
227
Agent score
65%

What's inside Nelua

  1. Overview of the Nelua Programming Language

    Nelua is a minimal, statically typed, and compiled systems programming language designed for performance-sensitive applications such as game engines and real-time systems. It features a syntax and semantics similar to Lua but uses ahead-of-time (AOT) compilation to generate optimized native binaries via C compilers (like GCC or Clang). Key characteristics include:

    • Optional Typing: Provides type notations for compile-time checks and efficiency, though many are optional and can be inferred.
    • Memory Management: Uses a garbage collector by default, but it is optional and can be replaced by manual memory management for predictable performance.
    • Metaprogramming: Extensible at compile-time using Lua, allowing for the creation of generics and polymorphic functions.
    • C Compatibility: Compiles to C first, allowing developers to debug generated C code, mix in C libraries, and run on any system where a C compiler is available.
    • Self-Contained: The standard library is written in Nelua and requires only a C compiler to function.
  2. Retrieve type information using the traits library

    The traits library allows developers to gather type identifiers and detailed information about types at runtime or compile-time.
    -- Get the type ID of a value or type
    local id = traits.typeidof(my_variable)
    
    -- Get detailed type information
    local info = traits.typeinfoof(my_variable)
    print(info.name, info.nickname)
  3. Manage memory with HeapAllocator

    The HeapAllocator is an experimental, single-threaded memory allocator designed for constant-time allocations and alignment (typically 16 bytes). It uses a fixed-size buffer and cannot grow automatically; for dynamic growth, use the system's general-purpose allocator. It is not thread-safe.
  4. Create complex concepts with validation logic

    Concepts can include complex logic to verify type properties (e.g., checking for specific metamethods or pointer subtypes). If a concept returns false along with a string, the compiler will emit that string as a compile-time error explaining why the type did not match the concept.
    local indexable_concept = #[concept(function(attr)
      local type = attr.type
      if type.is_pointer then type = type.subtype end
      if type.is_array then return true end
      if not type.is_record then return false, 'the container is not a record' end
      if not type.metafields.__index then return false, 'the container must have the __index metamethod' end
      return true
    end)]#
    
    local function sum_container(container: indexable_concept)
      -- implementation
    end
  5. Check atomic lock-free capabilities

    Use C.atomic_is_lock_free to determine if a specific atomic object is lock-free. Additionally, several global constants provide information about whether specific types are lock-free on the current platform.
    -- Function check
    C.atomic_is_lock_free(obj: is_atomicable_ptr <const,volatile>): boolean
    
    -- Type constants
    global C.ATOMIC_BOOL_LOCK_FREE: cint
    global C.ATOMIC_INT_LOCK_FREE: cint
    global C.ATOMIC_LONG_LOCK_FREE: cint
    global C.ATOMIC_POINTER_LOCK_FREE: cint
    -- (Also available for CHAR, CHAR16_T, CHAR32_T, WCHAR_T, SHORT, LLONG)
  6. Implement type constraints using Concepts

    Concepts allow the specialization of polymorphic functions at compile time. By using the concept preprocessor function, you can define a predicate that checks if a type's attributes (via the attr object) meet specific requirements. The compiler generates a specialized C function for each unique set of matching types, avoiding runtime type branching.
    -- Define a concept for scalar types
    local an_scalar = #[concept(function(attr)
      return attr.type.is_scalar
    end)]#
    
    -- Use the concept in a polymorphic function
    local function add(x: an_scalar, y: an_scalar)
      return x + y
    end
    
    print(add(1, 2)) -- Works
    -- add(1, true) -- Compile error: type 'boolean' could not match concept 'an_scalar'
  7. Use the list generic for doubly linked lists

    The list generic creates a doubly linked list type list(T, Allocator). It supports constant-time O(1) insertion and removal from any position but does not support fast random access. It is instantiated as list(T, Allocator), defaulting to DefaultAllocator if the second argument is omitted.
    -- Example of instantiating a list of strings
    local my_list = list(string)
  8. Access C standard library bindings in Nelua

    Nelua provides a comprehensive set of bindings to the C standard library organized into modules. These bindings allow developers to call C functions and use C types directly within Nelua. Key modules include:

    • C.arg: Command line arguments (argc, argv).
    • C.ctype: Character classification and conversion (e.g., isalnum, tolower).
    • C.errno: Error number definitions and constants.
    • C.locale: Localization and locale settings.
    • C.math: Mathematical functions for various floating-point precisions (e.g., sin, cos, pow, sqrt).
    • C.signal: Signal handling and constants (e.g., SIGINT, SIGTERM).
    • C.stdarg: Variable argument list macros (va_start, va_arg, va_end).
    • C.stdio: Standard input/output operations (e.g., printf, fopen, fread, fwrite).
    • C.stdlib: General purpose utilities, memory management, and process control (e.g., malloc, free, exit).
  9. Nelua language overview and stability

    Nelua (Native Extensible Lua) is a statically typed, compiled language with syntax similar to Lua, designed for real-time applications requiring efficiency and predictable performance (e.g., games, game engines, and libraries). It is currently in an alpha state. While most syntax and C-like low-level features are implemented, some Lua features like exceptions, tables, runtime dynamic typing, and closures are not yet available.
  10. Use the sequence generic for efficient fixed-type arrays

    The sequence generic is used to create a sequence type sequence(T, Allocator), where T is the value type and Allocator is the allocator (defaults to DefaultAllocator). Sequences are more efficient than tables for holding sequences of a fixed value type. They can be initialized using curly braces {} via the __convert method.
    -- Example of instantiating a sequence of integers
    local my_seq = sequence(int)
  11. Nelua Language Overview and Design Goals

    Nelua is a language that combines Lua-like syntax and semantics with C-like performance. It compiles directly to native machine code via a C file, meaning there is no VM or interpreter. Key characteristics include:

    • Performance: Near-C performance when using type notations, manual memory management, pointers, and records.
    • Static Compilation: Code cannot be loaded at runtime; code generation must happen at compile-time via the preprocessor.
    • Lua Compatibility: While it mirrors Lua's syntax, dynamic features like tables and dynamic typing are not fully implemented; records and explicit type notations are required instead.
    • C Differences: Nelua initializes variables to zero by default and rounds integer division towards negative infinity to maintain consistency with Lua.
  12. Use facultative and overload concept shortcuts

    Nelua provides two built-in shortcuts for common concept patterns to avoid runtime costs and reduce boilerplate:

    1. facultative(type): Matches the specified type or niltype. It can be used to implement optional arguments that specialize at compile-time.
    2. overload(type1, type2, ...): Matches any of the listed types, allowing a single function to handle multiple distinct types via compile-time specialization.
    -- Facultative example
    local function get_number(x: facultative(number))
      ## if x.type.is_niltype then return 0 ## else return x ## end
    end
    
    -- Overload example
    local function foo(x: overload(integer, string, niltype))
      ## if x.type.is_integral then
        print('got integer ', x)
      ## elseif x.type.is_string then
        print('got string ', x)
      ## end
    end