GithubHelp home page GithubHelp logo

edubart / nelua-lang Goto Github PK

View Code? Open in Web Editor NEW
2.0K 52.0 64.0 4.6 MB

Minimal, efficient, statically-typed and meta-programmable systems programming language heavily inspired by Lua, which compiles to C and native code.

Home Page: https://nelua.io

License: MIT License

Lua 59.75% Dockerfile 0.02% Makefile 0.35% C 39.85% Shell 0.02% Batchfile 0.01%
nelua programming-language language compiler lua luajit metaprogramming efficient minimal statically-typed

nelua-lang's Introduction

Nelua Logo

nelua.io

Test Status Discord

Nelua (stands for Native Extensible Lua) is a minimal, efficient, statically-typed and meta-programmable systems programming language heavily inspired by Lua, which compiles to C and native code.

Note: The language is in alpha state and still evolving.

Quick start

  • For basic information check the Website.
  • For first steps and how to use Nelua, start at the Tutorial.
  • For a tour of the language's syntax, features and usage read the Overview.
  • For small examples written in Nelua look the Examples folder .
  • For questions and discussions go to the Discussions.
  • For a chat with the community join the Discord server.
  • For cool stuff made with Nelua check Awesome Nelua wiki page and #showcase channel in the Discord server.

After installing, you might want to check out the featured example, a Snake game leveraging the famous SDL2 library:

nelua examples/snakesdl.nelua

About

Nelua is a systems programming language for performance-sensitive applications where Lua would not be efficient, such as operating systems, real-time applications and game engines. While it has syntax and semantics similar to Lua, it primarily focuses on generating efficient C code and provide support for highly-optimizable low-level programming. Using Nelua idioms such as records, arrays, manual memory management and pointers should result in performance as efficient as pure C; on the other hand, when using Lua idioms such as tables, metatables and untyped variables, the compiler will bake a runtime library for this sort of dynamic functionality into the program, which could incur some runtime overhead.

Nelua can do meta programming at compile time through preprocessor constructs written in Lua; since the compiler itself is also written in Lua, it means that user-provided preprocessor code can interact at any point with the compiler's internals and the source code's AST. Such system allows for ad-hoc implementation of high level constructs such as classes, generics and polymorphism, all without having to add them into the core specification, thus keeping the language simple, extensible and compact. The same way that Lua's object-oriented patterns are not built into the language, but can be nonetheless achieved through metatables, in Nelua you could yourself implement a similar functionality which is fully decided at compile time or dynamically dispatched at runtime.

Nelua can do extensible programming as the programmer may add extensions to the language such as new grammars, AST definitions, semantics, type checkers, code generation and behaviors to the compiler at compile time via the preprocessor.

Nelua provides support for both garbage-collected and manual memory management in a way that the developer can easily choose between using garbage collection, or completely disabling garbage collection, or mixing both.

Nelua first compiles to C, then it executes a C compiler to produce native code. This way existing C code and libraries can be leveraged and new C libraries can be created. Another benefit is that Nelua can reach the same target platforms as C99 compilers, such GCC or Clang, while also enjoying state-of-the-art compiler optimizations provided by them.

The initial motivation for its creation was to replace C/C++ parts of projects which currently uses Lua with a language that has syntax and semantics similar to Lua, but allows for fine-grained performance optimizations and does not lose the ability to go low level, therefore unifying the syntax and semantics across both compiled and dynamic languages.

Goals

  • Be minimal with a small syntax, manual and API, but powerful
  • Be efficient by compiling to optimized C code then native code
  • Have syntax, semantics and features similar to Lua
  • Optionally statically typed with type checking
  • Achieve classes, generics, polymorphism and other higher constructs by meta programming
  • Have an optional garbage collector
  • Make possible to create clean DSLs by extending the language grammar
  • Make programming safe for non experts by doing run/compile-time checks and avoiding undefined behavior
  • Possibility to emit low level code (C, assembly)
  • Be modular and make users capable of creating compiler plugins to extended
  • Generate readable, simple and efficient C code
  • Possibility to output freestanding code (dependency free, for kernel dev or minimal runtime)
  • No single memory management model, choose for your use case GC or manual

Why?

  • We love to script in Lua.
  • We love C performance.
  • We want best of both worlds in a single language and with a unified syntax.
  • We want to reuse or mix existing C/C++/Lua code.
  • We want type safety and optimizations.
  • We want to have efficient code while maintaining readability and safety.
  • We want the language features and manual to be minimal and fit our brain.
  • We want to deploy anywhere C runs.
  • We want to extended the language features by meta programming or modding the compiler.
  • We want to code with or without garbage collection depending on our use case.
  • We want to abuse of static dispatch instead of dynamic dispatch to gain performance and correctness.

Contributing

You can support or contribute to Nelua in many ways, giving the project a star on github, testing out its features, reporting bugs, discussing ideas, helping other users, spreading it to the world, sharing projects made with it on github, creating tutorials or blog posts, improving its documentation or through a donation or sponsorship.

Nelua is open source, but not very open to contributions in the form of pull requests, if you would like something fixed or implemented in the core language try first submitting a bug report or opening a discussion instead of doing a PR. The authors prefer it this way, so that the ideal solution is always provided, without unwanted consequences on the project, thus keeping the quality of the software.

Read more about contributing in the contributing page.

Become a Patron

License

MIT License

nelua-lang's People

Contributors

andre-la avatar apexdevelopment avatar bjornbytes avatar dependabot[bot] avatar edubart avatar er2off avatar gitspartv avatar kisaragieffective avatar mgred avatar resolritter avatar ryanford avatar stefanos82 avatar w32zhong avatar xvxx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nelua-lang's Issues

Possible bug with paths

I have started writing a shell script to automate my Nelua tests and instead of going in the directory where the files are located, I have decided to let the script test them for me, from a separate location of course.

The script looks like this:

$ cat validatenelua.sh 
#!/bin/sh

tput reset

for name in /home/stefanos/code/nelua/*.nelua
do
    echo "$name"
    nelua -tb "$name"
done

for name in /home/stefanos/code/nelua/Overview/*.nelua
do
    echo "$name"
    nelua -tb "$name"
done

When executed from $HOME/programming/ directory that is located, it throws an error for this particular module only:

image

The interesting part is...when I go to /home/stefanos/code/nelua/Overview/ and run for name in *.nelua; do echo "$name"; nelua -tb "$name"; done, everything works as expected.

Is it something that has to do with the relative / absolute paths?

I always confuse these two how they should work or behave.

My suspicion is telling me is related to b17a77b where you introduced support for relative requires in the preprocessor.

make test failed in Fedora Rawhide

At the same time tests passed in VoidLinux.

$ make test
<SKIP>
[PASS] standard library | require
[FAIL] standard library | builtins (./spec/stdlib_spec.lua:13/14)
./spec/tools/expect.lua:39: Expected string to contains.
Passed in:

Expected:
warning: hi
stack traceback:
        [C]: in function 'error'
        /root/nelua-lang/lualib/nelua/utils/errorer.lua:16: in function 'nelua.utils.errorer.assertf'
        ./spec/tools/expect.lua:39: in function 'spec.tools.expect.contains'
        ./spec/tools/expect.lua:126: in function 'spec.tools.expect.run'
        ./spec/tools/expect.lua:199: in function 'spec.tools.expect.run_c_from_f                                                               ile'
        ./spec/stdlib_spec.lua:14: in function <./spec/stdlib_spec.lua:13>
        [C]: in function 'xpcall'
        /root/nelua-lang/lualib/nelua/thirdparty/lester.lua:238: in function 'nelua.thirdparty.lester.it'
        ./spec/stdlib_spec.lua:13: in local 'func'
        /root/nelua-lang/lualib/nelua/thirdparty/lester.lua:163: in function 'nelua.thirdparty.lester.describe'
        ./spec/stdlib_spec.lua:7: in main chunk
        [C]: in function 'require'
        spec/init.lua:18: in main chunk
        [C]: in ?
[PASS] standard library | traits
[PASS] standard library | libc
[PASS] standard library | math
<SKIP>

Document how to modularize pre-processor macros

Nelua's overview documentation shows the following pattern for defining new Pre-processor macros.

##[[
function unroll(count, block)
  for i=1,count do
    block()
  end
end
]]

-- code here

Problems:

  • I might want to use this same definition in more than one module. How to achieve that?
  • You can't format Lua code inside of a string.
  • You also might not get syntax highlighting in the editor, since everything is wrapped into a string.
  • Although it isn't very noticeable for one-off small functions, it doesn't feel good for it the whole thing to be embedded into a string for huge macros. It implies syntaxes limitations, e.g.
    foo = dict[bar[baz]]
                      ^ this `]]` breaks the syntax because the whole thing is inside of a multiline string

I would like to have the option to do the following: define an arbitrary Lua module which could have big and reusable macros

   function unroll(input)
       -- some code...
   end

then import it in my Nelua code

## require <macros> 'project.module' 

Their usage would only be valid inside of other pre-processor blocks.

arguments aren't visible when preprocessing function return when the return type is composed

  • I tested it on latest Nelua version from master branch.
  • I checked there is no similar issue already reported.
  • My code has no errors or misuse of Nelua.

Bug description

Argument atrrs are visible when preprocessing a function return type, like as introduced on commit 5394c97, however, when the return type is composed, it get invisible, unless is 100% preprocessed.

Code example

local A = 10

-- this works
local function x(t: type): #[types.PointerType(t.value)]#
  ## staticassert(t.value.is_integral)
  return &A
end
print('x:', x(@integer))

-- this doesn't
local function y(t: type): pointer(#[t.value]#)
  ## staticassert(t.value.is_scalar)
  return &A
end
print('y:', y(@integer))

Expected behavior

Works just as with non-argument types:

local A: integer = 10

local function x(t: type): pointer(#[A.type]#)
  ## staticassert(t.value.is_integral)
  return &A
end
print('x:', x(@integer))

Environment

  • Nelua version:
    • Nelua 0.2.0-dev
    • Build number: 994
    • Git date: 2021-04-15 16:40:44 -0300
    • Git hash: 88f0bd0
  • Platform
    • Pop!_OS 20.10 (Ubuntu 20.10)

solaris 11, compilation failed

$ gmake
<SKIP>
rpmalloc/rpmalloc.c:162:15: error: conflicting types for ‘madvise’
  162 |    extern int madvise(caddr_t, size_t, int);
      |               ^~~~~~~
In file included from rpmalloc/rpmalloc.c:155:
/usr/include/sys/mman.h:232:12: note: previous declaration of ‘madvise’ was here
  232 | extern int madvise(void *, size_t, int);
      |            ^~~~~~~
gmake[1]: *** [Makefile:63: nelua-lua] Error 1
$

This diff helped here:

bash-5.0$ git diff
diff --git a/src/rpmalloc/rpmalloc.c b/src/rpmalloc/rpmalloc.c
index 282a1dc..1d37e17 100644
--- a/src/rpmalloc/rpmalloc.c
+++ b/src/rpmalloc/rpmalloc.c
@@ -159,7 +159,7 @@ static DWORD fls_key;
 #    define MAP_HUGETLB MAP_ALIGNED_SUPER
 #  endif
 #  ifdef __sun
-   extern int madvise(caddr_t, size_t, int);
+   extern int madvise(void *, size_t, int);
 #  endif
 #  ifndef MAP_UNINITIALIZED
 #    define MAP_UNINITIALIZED 0
$

You have to handle Solaris 10 and 11.

Obscure behavior when dealing with name clashes

While I was testing content for #133, I have discovered what in my humble opinion can be considered a very VERY dangerous behavior in generated code.

I have a tmp.nelua located in /home/stefanos/code/nelua/ and decided to create another tmp.nelua, but this new file located in /home/stefanos/tmp/.

The contents of /home/stefanos/code/nelua/tmp.nelua were obviously replaced by contents of /home/stefanos/tmp/tmp.nelua, so was my generated executable.

What would happen if I had original tmp executable running during the compilation of the newly created tmp?

Should not it better to generate name that consists of the entire path, plus the file name instead?

E.g.: /home/stefanos/code/nelua/tmp.nelua should become in /home/stefanos/.cache/ something like home_stefanos_code_nelua_tmp.c; this could reduce the chances to have a conflict.

unexpected `defer` calls

The following calls the defer block twice:

local function A(n: integer)
  print'BEGIN'
  defer print'END' end

  local r = (do
    if n % 2 == 0 then
      return n + 1
    else
      return n
    end
  end)
end

local function B(n: integer)
  print'BEGIN'
  defer print'END' end

  local function x(xn: integer): integer
    if xn % 2 == 0 then
      return xn + 1
    else
      return xn
    end
  end

  local r = x(n)
end


A(1)
print'---'
B(2)

output:

BEGIN
END
END
---
BEGIN
END
END

Feedback for documentation inconsistencies and unnoticed bugs

In Global Symbol of documentation, we have the following example:

global function global_f()
end

This throws an error when called:

useglobals.nelua:3:6: error: cannot handle type "void" in print
print(global_f())   -- outputs: f
     ^~~~~~~~~~~~


shell returned 1

If I add return 'f' inside global_f(), I get the desired output.

What is the behavior we initially expected in the first place?

Proposal: Shorthand syntax for records (a.k.a Field Punning)

Problem

Given a struct Point

local Point = @record {x: integer, y: integer, z: integer}

It is currently possible to initialize it in order

local x = 1
local y = 2
local z = 3

local p = Point {x, y, z}

but having it rely on order can lead to bugs

-- this is a bug: `x` and `y` are flipped in order
-- however, since they have the same type, the type checker can't catch it
local p = Point {y, x, z}

the following pattern is very common in Lua

local p = Point{
  x = x,
  y = y,
  z = z
}

However, it is repetitive, error-prone and verbose.

Proposal

Have a shorter initialization syntax. For example:

local p = Point { z, y, x }

That would look exactly like the array initialization syntax, though, so it could be changed to something else

local p = Point { =z, =y, =x }

Either syntax would be expanded to the same:

local p = Point { z = z, y = y, x = x }

Ordering doesn't matter on either case. Each variable gets assigned to the correct struct field with the same name.

Inspiration

Question: why jobs don't work with make?

I usually run make -j $(nproc) to take advantage of all my CPU cores.

I have noticed the following output, while my CPU uses only a single core:

$ make -j $(nproc)
gcc -o nelua-lua \
	-DNDEBUG -DLUA_COMPAT_5_3 -DLUA_ROOT='"/usr/local/"' -DLUA_USE_RPMALLOC -DENABLE_GLOBAL_CACHE=0 -DENABLE_UNLIMITED_CACHE=1 -DBUILD_DYNAMIC_LINK -DLUA_USE_LINUX \
	-Ilua \
	-Wall -O2 -fno-plt -fno-stack-protector -flto  \
	-s -Wl,-E  \
	lua/onelua.c lfs.c sys.c hasher.c lpeglabel/*.c rpmalloc/rpmalloc.c  \
	-lm -ldl 

Is this the expected behavior?

unexpected behavior on different function declaration syntax


Bug description

In Lua, local function x() print 'hello world' end is a syntax sugar to local x = function() print 'hello world' end, however, in nelua both can have different behaviors.

Code example

local function A() print 'hello world' end
A()

output:

$ nelua test.nelua 
hello world

local A = function() print 'hello world' end
A()

output:

$ nelua test.nelua 
C compilation for '/home/dreunix/.cache/nelua/teste' failed:
/home/dreunix/.cache/nelua/teste.c: In function ‘teste_anonfunc’:
/home/dreunix/.cache/nelua/teste.c:101:17: error: expected expression before ‘{’ token
  101 |   nelua_print_1({(uint8_t*)"hello world", 11});
      |                 ^

Expected behavior

The same behavior on both functions

Environment

  • Nelua version:
Nelua 0.2.0-dev
Build number: 1270
Git date: 2021-08-28 08:05:55 -0300
Git hash: e11f12e03649502b997f78349241e1ed1c506704
  • Platform: Pop!_OS 21.04
  • Architecture: x86_64
  • C compiler: gcc version 10.3.0 (Ubuntu 10.3.0-1ubuntu1)

Quession about write DSL like using lua table

sometimes I dont know what my data will look like, i just write the data directly like this in lua.

local item = {
	name = "someName",
	child = {
		name = "someName",
	},
}

print(item.child.name)

Then I want to write it in nelua, I tried like this:

local Item = @record{
	name : string,
 	child: pointer,
}

local item1 = (@Item){
	name = "someName",
	child = nilptr,
}

local item2 = (@Item){
	name = "someName",
	child = &item1,
}

-- ???
print(((@Item)$(item2.child)).name)

But I dont know how to convert the pointer child to type Item and read the name, Is it possible in nelua to write this DSL? If not, Is there any other way to achieve similar purpose?

Bug or limitation: Lua Busted for Lua 5.4 not supported yet in GNU / Debian testing 64-bit

I have installed busted on my GNU / Linux Debian testing 64-bit and it does not support yet Lua 5.4.

$ dpkg -L lua-busted 
/.
/usr
/usr/bin
/usr/bin/busted
/usr/share
/usr/share/doc
/usr/share/doc/lua-busted
/usr/share/doc/lua-busted/changelog.Debian.gz
/usr/share/doc/lua-busted/copyright
/usr/share/lua
/usr/share/lua/5.1
/usr/share/lua/5.1/busted
/usr/share/lua/5.1/busted/block.lua
/usr/share/lua/5.1/busted/compatibility.lua
/usr/share/lua/5.1/busted/context.lua
/usr/share/lua/5.1/busted/core.lua
/usr/share/lua/5.1/busted/done.lua
/usr/share/lua/5.1/busted/environment.lua
/usr/share/lua/5.1/busted/execute.lua
/usr/share/lua/5.1/busted/init.lua
/usr/share/lua/5.1/busted/languages
/usr/share/lua/5.1/busted/languages/ar.lua
/usr/share/lua/5.1/busted/languages/de.lua
/usr/share/lua/5.1/busted/languages/en.lua
/usr/share/lua/5.1/busted/languages/es.lua
/usr/share/lua/5.1/busted/languages/fr.lua
/usr/share/lua/5.1/busted/languages/it.lua
/usr/share/lua/5.1/busted/languages/ja.lua
/usr/share/lua/5.1/busted/languages/nl.lua
/usr/share/lua/5.1/busted/languages/pt-BR.lua
/usr/share/lua/5.1/busted/languages/ru.lua
/usr/share/lua/5.1/busted/languages/th.lua
/usr/share/lua/5.1/busted/languages/ua.lua
/usr/share/lua/5.1/busted/languages/zh.lua
/usr/share/lua/5.1/busted/modules
/usr/share/lua/5.1/busted/modules/cli.lua
/usr/share/lua/5.1/busted/modules/configuration_loader.lua
/usr/share/lua/5.1/busted/modules/files
/usr/share/lua/5.1/busted/modules/files/lua.lua
/usr/share/lua/5.1/busted/modules/files/moonscript.lua
/usr/share/lua/5.1/busted/modules/files/terra.lua
/usr/share/lua/5.1/busted/modules/filter_loader.lua
/usr/share/lua/5.1/busted/modules/helper_loader.lua
/usr/share/lua/5.1/busted/modules/luacov.lua
/usr/share/lua/5.1/busted/modules/output_handler_loader.lua
/usr/share/lua/5.1/busted/modules/standalone_loader.lua
/usr/share/lua/5.1/busted/modules/test_file_loader.lua
/usr/share/lua/5.1/busted/options.lua
/usr/share/lua/5.1/busted/outputHandlers
/usr/share/lua/5.1/busted/outputHandlers/TAP.lua
/usr/share/lua/5.1/busted/outputHandlers/base.lua
/usr/share/lua/5.1/busted/outputHandlers/gtest.lua
/usr/share/lua/5.1/busted/outputHandlers/json.lua
/usr/share/lua/5.1/busted/outputHandlers/junit.lua
/usr/share/lua/5.1/busted/outputHandlers/plainTerminal.lua
/usr/share/lua/5.1/busted/outputHandlers/sound.lua
/usr/share/lua/5.1/busted/outputHandlers/utfTerminal.lua
/usr/share/lua/5.1/busted/runner.lua
/usr/share/lua/5.1/busted/status.lua
/usr/share/lua/5.1/busted/utils.lua
/usr/share/lua/5.1/busted.lua
/usr/share/lua/5.2
/usr/share/lua/5.2/busted
/usr/share/lua/5.2/busted/languages
/usr/share/lua/5.2/busted/modules
/usr/share/lua/5.2/busted/modules/files
/usr/share/lua/5.2/busted/outputHandlers
/usr/share/lua/5.3
/usr/share/lua/5.3/busted
/usr/share/lua/5.3/busted/languages
/usr/share/lua/5.3/busted/modules
/usr/share/lua/5.3/busted/modules/files
/usr/share/lua/5.3/busted/outputHandlers
/usr/share/zsh
/usr/share/zsh/vendor-completions
/usr/share/zsh/vendor-completions/_busted
/usr/share/lua/5.2/busted/block.lua
/usr/share/lua/5.2/busted/compatibility.lua
/usr/share/lua/5.2/busted/context.lua
/usr/share/lua/5.2/busted/core.lua
/usr/share/lua/5.2/busted/done.lua
/usr/share/lua/5.2/busted/environment.lua
/usr/share/lua/5.2/busted/execute.lua
/usr/share/lua/5.2/busted/init.lua
/usr/share/lua/5.2/busted/languages/ar.lua
/usr/share/lua/5.2/busted/languages/de.lua
/usr/share/lua/5.2/busted/languages/en.lua
/usr/share/lua/5.2/busted/languages/es.lua
/usr/share/lua/5.2/busted/languages/fr.lua
/usr/share/lua/5.2/busted/languages/it.lua
/usr/share/lua/5.2/busted/languages/ja.lua
/usr/share/lua/5.2/busted/languages/nl.lua
/usr/share/lua/5.2/busted/languages/pt-BR.lua
/usr/share/lua/5.2/busted/languages/ru.lua
/usr/share/lua/5.2/busted/languages/th.lua
/usr/share/lua/5.2/busted/languages/ua.lua
/usr/share/lua/5.2/busted/languages/zh.lua
/usr/share/lua/5.2/busted/modules/cli.lua
/usr/share/lua/5.2/busted/modules/configuration_loader.lua
/usr/share/lua/5.2/busted/modules/files/lua.lua
/usr/share/lua/5.2/busted/modules/files/moonscript.lua
/usr/share/lua/5.2/busted/modules/files/terra.lua
/usr/share/lua/5.2/busted/modules/filter_loader.lua
/usr/share/lua/5.2/busted/modules/helper_loader.lua
/usr/share/lua/5.2/busted/modules/luacov.lua
/usr/share/lua/5.2/busted/modules/output_handler_loader.lua
/usr/share/lua/5.2/busted/modules/standalone_loader.lua
/usr/share/lua/5.2/busted/modules/test_file_loader.lua
/usr/share/lua/5.2/busted/options.lua
/usr/share/lua/5.2/busted/outputHandlers/TAP.lua
/usr/share/lua/5.2/busted/outputHandlers/base.lua
/usr/share/lua/5.2/busted/outputHandlers/gtest.lua
/usr/share/lua/5.2/busted/outputHandlers/json.lua
/usr/share/lua/5.2/busted/outputHandlers/junit.lua
/usr/share/lua/5.2/busted/outputHandlers/plainTerminal.lua
/usr/share/lua/5.2/busted/outputHandlers/sound.lua
/usr/share/lua/5.2/busted/outputHandlers/utfTerminal.lua
/usr/share/lua/5.2/busted/runner.lua
/usr/share/lua/5.2/busted/status.lua
/usr/share/lua/5.2/busted/utils.lua
/usr/share/lua/5.2/busted.lua
/usr/share/lua/5.3/busted/block.lua
/usr/share/lua/5.3/busted/compatibility.lua
/usr/share/lua/5.3/busted/context.lua
/usr/share/lua/5.3/busted/core.lua
/usr/share/lua/5.3/busted/done.lua
/usr/share/lua/5.3/busted/environment.lua
/usr/share/lua/5.3/busted/execute.lua
/usr/share/lua/5.3/busted/init.lua
/usr/share/lua/5.3/busted/languages/ar.lua
/usr/share/lua/5.3/busted/languages/de.lua
/usr/share/lua/5.3/busted/languages/en.lua
/usr/share/lua/5.3/busted/languages/es.lua
/usr/share/lua/5.3/busted/languages/fr.lua
/usr/share/lua/5.3/busted/languages/it.lua
/usr/share/lua/5.3/busted/languages/ja.lua
/usr/share/lua/5.3/busted/languages/nl.lua
/usr/share/lua/5.3/busted/languages/pt-BR.lua
/usr/share/lua/5.3/busted/languages/ru.lua
/usr/share/lua/5.3/busted/languages/th.lua
/usr/share/lua/5.3/busted/languages/ua.lua
/usr/share/lua/5.3/busted/languages/zh.lua
/usr/share/lua/5.3/busted/modules/cli.lua
/usr/share/lua/5.3/busted/modules/configuration_loader.lua
/usr/share/lua/5.3/busted/modules/files/lua.lua
/usr/share/lua/5.3/busted/modules/files/moonscript.lua
/usr/share/lua/5.3/busted/modules/files/terra.lua
/usr/share/lua/5.3/busted/modules/filter_loader.lua
/usr/share/lua/5.3/busted/modules/helper_loader.lua
/usr/share/lua/5.3/busted/modules/luacov.lua
/usr/share/lua/5.3/busted/modules/output_handler_loader.lua
/usr/share/lua/5.3/busted/modules/standalone_loader.lua
/usr/share/lua/5.3/busted/modules/test_file_loader.lua
/usr/share/lua/5.3/busted/options.lua
/usr/share/lua/5.3/busted/outputHandlers/TAP.lua
/usr/share/lua/5.3/busted/outputHandlers/base.lua
/usr/share/lua/5.3/busted/outputHandlers/gtest.lua
/usr/share/lua/5.3/busted/outputHandlers/json.lua
/usr/share/lua/5.3/busted/outputHandlers/junit.lua
/usr/share/lua/5.3/busted/outputHandlers/plainTerminal.lua
/usr/share/lua/5.3/busted/outputHandlers/sound.lua
/usr/share/lua/5.3/busted/outputHandlers/utfTerminal.lua
/usr/share/lua/5.3/busted/runner.lua
/usr/share/lua/5.3/busted/status.lua
/usr/share/lua/5.3/busted/utils.lua
/usr/share/lua/5.3/busted.lua

Here's the problem:

$ make test-full
make[1]: Nothing to be done for 'default'.
make[1]: Entering directory '/home/stefanos/git_codes/nelua'
rm -f luacov.report.out luacov.stats.out *.gcov *.gcda
make[1]: Leaving directory '/home/stefanos/git_codes/nelua'
busted --lua=src/nelua-lua --coverage
src/nelua-lua: /usr/bin/busted:3: module 'busted.runner' not found:
	no field package.preload['busted.runner']
	no file '/usr/local/share/lua/5.4/busted/runner.lua'
	no file '/usr/local/share/lua/5.4/busted/runner/init.lua'
	no file '/usr/local/lib/lua/5.4/busted/runner.lua'
	no file '/usr/local/lib/lua/5.4/busted/runner/init.lua'
	no file './busted/runner.lua'
	no file './busted/runner/init.lua'
	no file '/usr/local/lib/lua/5.4/busted/runner.so'
	no file '/usr/local/lib/lua/5.4/loadall.so'
	no file './busted/runner.so'
	no file '/usr/local/lib/lua/5.4/busted.so'
	no file '/usr/local/lib/lua/5.4/loadall.so'
	no file './busted.so'
stack traceback:
	[C]: in function 'require'
	/usr/bin/busted:3: in main chunk
	[C]: in ?
make: *** [Makefile:93: coverage-test] Error 1

Any suggestion about this problem?

Bug when closing parethesis is placed in new line for ## print()

Bug description

When I place the closing parenthesis of ## print() in a new line, it breaks.

t.nelua:8:1: syntax error: unexpected syntax
)
^


shell returned 1

I'm trying to print the type(s) of nested records and caused a bug by mistake.

Code example

Provide minimal reproduction code to test the bug.
Please, format the code properly and try to keep it as simple as possible, just focusing on the experienced bug.

require 'string'

local A = @record{}
global A.B = @record{ x: integer}

## print(string.format("A.type: '%s'\nA.value.metafields.B: '%s'", A.type, A.value.metafields.B))

The problematic code looks like this:

require 'string'

local A = @record{}
global A.B = @record{ x: integer}

## print(
    string.format("A.type: '%s'\nA.value.metafields.B: '%s'", A.type, A.value.metafields.B)
)

Expected behavior

It should print

A.type: 'type'
A.value.metafields.B: 'A.B: type = A.B'

Workaround

If you have already found a way to workaround the issue,
then please share how you did it,
this may help others with the same issue.

Environment

Provide relevant information about your environment:

  • Nelua version:
Nelua 0.2.0-dev
Build number: 1268
Git date: 2021-08-27 13:07:25 -0300
Git hash: 97d5c391e12bb16b026e9d636b49ea18a42a8fd1
Copyright (C) 2019-2021 Eduardo Bart (https://nelua.io/)
  • Platform: GNU / Linux Debian
  • Architecture: Linux debian 5.10.0-3-amd64 #1 SMP Debian 5.10.13-1 (2021-02-06) x86_64 GNU/Linux
  • C compiler: gcc (Debian 10.2.1-6) 10.2.1 20210110

can't preprocess "statement replacement macros" while unrolling

Bug description

The compiler can't generate code with statement replacement macros inside a loop unrolling scope

Code example

## local function macrox(x)
  print(#[x]#)
## end

## for i = 1, 20 do
  #[macrox]#(10)
## end

output:

$ nelua test.nelua 
test.nelua:7:3: error: cannot convert preprocess value of type "function" to an AST node
  #[macrox]#(10)
  ^~~~~~~~~~

Expected behavior

The same behaviour as repeating the code manually.

Workaround

Wrap the statement replacement macro with a runtime function:

## local function macrox(x)
  print(#[x]#)
## end

local function macro_x(x: auto)
  #[macrox]#(x)
end

## for i = 1, 20 do
  macro_x(10)
## end

Environment

Provide relevant information about your environment:

  • Nelua version: 0.2.0-dev.1365+e6a91c19
  • Pop!_OS 21.04 (Ubuntu)
  • Architecture: x86_64

Creating a C library ?

The "Overview" section on Nelua website says :

You can use Nelua to create C libraries, when doing this you may want to fix the name of the generated C function and export it:

It shows a code example, but i'm unable to find how to actually generate that library.
Doing nelua --help doesn't show any options regarding that and the documentation doesn't show any options to enable for this.

Thanks

Proposal: More straightforward API for injecting AST nodes into the source code

Problem

Nelua's overview has this example

##[[
function unroll(count, block)
  for i=1,count do
    block()
  end
end
]]

local counter = 1
## unroll(4, function()
  print(counter) -- outputs: 1 2 3 4
  counter = counter + 1
## end)

This approach is limited

  • Can't create intermediate variables without runtime cost.
  • Can't memoize results - imagining if it was costly to compute the node: you'd need to compute the node 4 times, instead of only evaluating the macro once and returning the same value on future runs.
  • Doesn't exemplify a way of using a return value for building the node.

What I would like to do is:

##[[
function ast_builder(input)
   return aster.Block { ... }
end
]]

## inject_my_ast(ast_builder(input))

i.e. be able to create new arbitrary AST nodes and inject it directly into the source code.

This would also be useful in, for instance, programmatically injecting generated bindings at compile time depending on some input (it would inject those global EXTERNAL: T <cimport, nodecl> nodes at some point in the program).


The following approach is currently viable

##[[
function my_macro(input)
  local n = aster
  return n.Block{{n.Call{{}, n.Id{'a'}}}}
end
]]

## ppcontext:add_statnode(my_macro(custom_input))

however, it exposes this ppcontext internal and also isn't documented.

Proposal

  • Create an API which exposes both aster and ppcontext through a common module for manipulating ASTs
  • Create a wiki with community-contributed examples
  • Compare the approach with ppcontext:add_statnode with what's called Pre-processor macros

About the last point, from what I've seen so far, ppcontext:add_statnode is more powerful because it allows you to define a whole block of code arbitrarily, whereas Pre-processor macros have more limitations of where they can be injected, since they are manipulating existing source code AST instead of creating a new one.

SEGFAULT about __tostring and `..` operator

Bug description

combine __tostring with .. operator cause runtime crash
seems the __tostring need return a copied string?

Code example

require 'string'

local StringView = @record{
  src: string,
}

function StringView:__tostring(): string
  return string.subview(self.src, 1, 1)
end

local test = (@StringView){ 'bc' }

print('a'..test:__tostring()..'c') -- just fine
print('a'..test..'c') -- trigger SEGFAULT here

Expected behavior

no crash and no memory leak
got output:

abc
abc

Workaround

https://github.com/edubart/nelua-lang/blob/master/lib/string.nelua#L430
Disable a:destroy when pragmas.nogc
(also for b)

Environment

Provide relevant information about your environment:

  • Nelua version (you can check with nelua -v).
Nelua 0.2.0-dev
Build number: 1258
Git date: 2021-08-25 07:59:18 -0300
Git hash: bb5e71784f4065d255e0ef3bc27b6ce06191e370
Copyright (C) 2019-2021 Eduardo Bart (https://nelua.io/)
  • Platform (e.g. Windows/MSYS2, Ubuntu Linux, MacOS)
    Tested in linux/musl linux/glibc linux/bionic(android) windows/msys2 windows/zig-cc, all crash
  • Architecture (e.g. x86_64, arm64)
    x86_64 and aarch64
  • C compiler if your bug has C compiler errors. (e.g. GCC 10.2, Clang 11)
    gcc 10.3.1

--lua option doens't change the used lua interpreter

$ cat test.nelua 
## print("_VERSION: " .. _VERSION)
$ 
$ nelua test.nelua -q
_VERSION: Lua 5.4
$ 
$ nelua test.nelua -q --lua lua5.3 --lua-version 5.3
_VERSION: Lua 5.4
$ 
$ nelua test.nelua -q --lua lua5.3 --lua-version 5.3 --print-config
{
  add_path = { "/home/andre_la/Downloads/git/nelua-projs/nRotor/", "/home/andre_la/Downloads/git/nelua-projs/nelua-raylib/", "/home/andre_la/Downloads/git/nelua-projs/nprof/" },
  cache_dir = "nelua_cache",
  cc = "gcc",
  cflags = "",
  cpu_bits = 64,
  define = {},
  gdb = "gdb",
  generator = "c",
  input = "test.nelua",
  lib_path = "/usr/local/lib/nelua/lib",
  lua = "lua5.3",
  lua_version = "5.3",
  path = "./?.nelua;./?/init.nelua;/home/andre_la/Downloads/git/nelua-projs/nRotor//?.nelua;/home/andre_la/Downloads/git/nelua-projs/nRotor//?/init.nelua;/home/andre_la/Downloads/git/nelua-projs/nelua-raylib//?.nelua;/home/andre_la/Downloads/git/nelua-projs/nelua-raylib//?/init.nelua;/home/andre_la/Downloads/git/nelua-projs/nprof//?.nelua;/home/andre_la/Downloads/git/nelua-projs/nprof//?/init.nelua;/usr/local/lib/nelua/lib/?.nelua;/usr/local/lib/nelua/lib/?/init.nelua",
  pragma = {},
  quiet = true
}

Installed using make, when installed with luarocks, it uses 5.3, but still can't change to, for example, lua5.2.

Cannot call methods using method syntax sugar with comptime arguments

Base code to reproduce:

local X = @record{y: integer}

function X:A(a: facultative(stringview) <comptime>)
  ## if a.type.is_niltype then
    print'A is niltype'
  ## else
    print(#['a is ' .. a.value]#)
  ## end
end

Using it without method call syntax sugar works:

local z: X = {0}

X.A(z)
print'---'
X.A(z, 'hello world')

However, using the syntax sugar produces an error:

local z: X = {0}

z:A()
print'---'
z:A('hello world')

error code (gcc):

C compilation for 'nelua_cache/testes' failed:
nelua_cache/testes.c: In function ‘nelua_main’:
nelua_cache/testes.c:90:28: error: incompatible type for argument 2 of ‘testes_X_A__2’
   90 |   testes_X_A__2(&testes_z, ((nlstringview){(uint8_t*)__strlit4, 11}));
      |                            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |                            |
      |                            nlstringview
nelua_cache/testes.c:80:49: note: expected ‘nlniltype’ but argument is of type ‘nlstringview’
   80 | void testes_X_A__2(testes_X_ptr self, nlniltype a) {
      |                                       ~~~~~~~~~~^

Problem by rpmalloc when installing on Windows 10

Hi there!

Anyway, I followed tutorial and tried to installed nelua, When i build on my Windows 10 device i get weird error related to rpmalloc, Here is log:

D:\msys64\home\steri\nelua-lang>make install

make --no-print-directory -C src
gcc -o nelua-lua.exe \
        -DNDEBUG -DLUA_COMPAT_5_3 -DLUAI_MAXCSTACK=16384 -DLUA_USE_RPMALLOC -DENABLE_GLOBAL_CACHE=0 -DBUILD_DYNAMIC_LINK -DLUA_ROOT='"/usr/local/"' \
        -Ilua \
        -Wall -O2 -fno-plt -fno-stack-protector -flto  \
        -s  \
        lua/onelua.c rpmalloc/rpmalloc.c lfs.c sys.c hasher.c lpeglabel/*.c  \
        -lm
rpmalloc/rpmalloc.c: In function '_rpmalloc_mmap_os':
rpmalloc/rpmalloc.c:776:68: error: 'MEM_LARGE_PAGES' undeclared (first use in this function); did you mean 'MEM_4MB_PAGES'?
  776 |  void* ptr = VirtualAlloc(0, size + padding, (_memory_huge_pages ? MEM_LARGE_PAGES : 0) | MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
      |                                                                    ^~~~~~~~~~~~~~~
      |                                                                    MEM_4MB_PAGES
rpmalloc/rpmalloc.c:776:68: note: each undeclared identifier is reported only once for each function it appears in
rpmalloc/rpmalloc.c: In function 'rpmalloc_initialize_config':
rpmalloc/rpmalloc.c:2422:31: warning: implicit declaration of function 'GetLargePageMinimum' [-Wimplicit-function-declaration]
 2422 |   size_t large_page_minimum = GetLargePageMinimum();
      |                               ^~~~~~~~~~~~~~~~~~~
lfs.c: In function 'push_link_target':
lfs.c:1115:9: warning: implicit declaration of function 'memmove_s'; did you mean 'memmove'? [-Wimplicit-function-declaration]
 1115 |         memmove_s(target, tsize - 3, target + 4, tsize - 3);
      |         ^~~~~~~~~
      |         memmove
make[1]: *** [Makefile:55: nelua-lua.exe] Error 1
make: *** [Makefile:188: install] Error 2

idk what causes this, I also tried to rename 'MEM_LARGE_PAGES' to 'MEM_4MB_PAGES' but didn't solved problem and still give error related to large page by rpmalloc...

I need help to know what causes this, Thanks for everything!

return doesn't stop execution of an expression block

Please, before submitting a new issue verify and check:

  • I tested it on latest Nelua version from master branch.
  • I checked there is no similar issue already reported.
  • My code has no errors or misuse of Nelua.

Bug description

On an expression block, the expression evaluation should be done at a return.
However, there is a case where this doesn't happens.

Code example

local x = (do
  if true then
    print "x is 10"
    return 10
  else
    print "x is 20"
    return 20
  end
  print "x is 30"
  return 30
end)

print "x evaluated, it should be 10"
print('x is', x)
assert(x == 10, 'x is not 10')

Expected behavior

Expected output:

x is 10
x evaluated, it should be 10
x is	10

Output:

x is 10
x is 30
x evaluated, it should be 10
x is	30
x is not 10

Environment

  • Nelua version is:
Nelua 0.2.0-dev
Build number: 808
Git date: 2020-12-27 14:57:30 -0300
Git hash: d44947ba5fef36fe0a8c25c3f04fa72d061f6bdb
  • Platform: Pop_OS! 20.10 (based on Ubuntu 20.10)

The operator bitwise not isn't working:

Hello :)

I installed it yesterday through luarocks, I've been testing it and found that ~0 (or any other number) triggers an error:

local x = ~10
$ nelua bnot_test.nelua 
bnot_test.nelua:1:12: error: in unary operation `bnot`: invalid operation for type 'int64'
local x = ~10
           ^

(edit: typo)

Can't run on Linux

When running a nelua code on my Linux system (Ubuntu 18.04), 2 problems occurs:

/usr/local/bin/nelua: 45: /usr/local/bin/nelua: [[: not found
/usr/local/bin/nelua: 50: printf: %q: invalid directive

full log:

$ cat test.nelua 
print "hello world!"
$ nelua main.nelua 
/usr/local/bin/nelua: 45: /usr/local/bin/nelua: [[: not found
/usr/local/bin/nelua: 50: printf: %q: invalid directive
/usr/local/bin/nelua-lua: /usr/local/lib/nelua/lualib/nelua.lua:2: module 'nelua.runner' not found:
    no field package.preload['nelua.runner']
    no file 'nelua/runner.lua'
    no file '/usr/local/share/lua/5.4/nelua/runner.lua'
    no file '/usr/local/share/lua/5.4/nelua/runner/init.lua'
    no file '/usr/local/lib/lua/5.4/nelua/runner.lua'
    no file '/usr/local/lib/lua/5.4/nelua/runner/init.lua'
    no file './nelua/runner.lua'
    no file './nelua/runner/init.lua'
    no file '/usr/local/lib/lua/5.4/nelua/runner.so'
    no file '/usr/local/lib/lua/5.4/loadall.so'
    no file './nelua/runner.so'
    no file '/usr/local/lib/lua/5.4/nelua.so'
    no file '/usr/local/lib/lua/5.4/loadall.so'
    no file './nelua.so'
stack traceback:
    [C]: in function 'require'
    /usr/local/lib/nelua/lualib/nelua.lua:2: in main chunk
    [C]: in ?

This quick hack "solves" both issues respectively on my system, but it causes problems on others platforms off course:

 # determine nelua's lua package path
-if [[ "$OSTYPE" = "msys" ]]; then
+if [ "$OSTYPE" = "msys" ]; then
   NELUA_PACKAGE_PATH="$(cygpath -w $NELUA_LUALIB/)"
 else
   NELUA_PACKAGE_PATH="$NELUA_LUALIB/"
 fi
-NELUA_PACKAGE_PATH="$(printf "%q\n" "$NELUA_PACKAGE_PATH")"
 
 # execute nelua compiler
 exec $NELUA_LUA -e "package.path='${NELUA_PACKAGE_PATH}?.lua;'..package.path" $NELUA_LUALIB/nelua.lua "$@"

can't build on windows .. ?

can't build on Windows 8.1 64bits. (Mingw-w64 8.1.0 already installed)
just installed Luarock, with no error and I got those errors when trying to build nelua :

# luarocks install https://raw.githubusercontent.com/edubart/nelua-lang/master/rockspecs/nelua-dev-1.rockspec
Cloning into 'nelua-lang'...
remote: Enumerating objects: 169, done.
remote: Counting objects: 100% (169/169), done.
remote: Compressing objects: 100% (158/158), done.
remote: Total 169 (delta 0), reused 65 (delta 0), pack-reused 0
Receiving objects: 100% (169/169), 200.60 KiB | 769.00 KiB/s, done.
Missing dependencies for nelua dev-1:
   penlight >= 1.7.0 (not installed)
   lpeglabel >= 1.6.0 (not installed)
   tableshape >= 2.1.0 (not installed)
   lua-term >= 0.7 (not installed)
   argparse >= 0.7.0 (not installed)
   hasher >= 0.1.0 (not installed)
   chronos >= 0.2 (not installed)
   lbc >= 20180729 (not installed)
   busted >= 2.0.0 (not installed)
   luacheck >= 0.23.0 (not installed)
   luacov >= 0.13.0 (not installed)
   cluacov >= 0.1.1 (not installed)
   dumper >= 0.1.1 (not installed)

nelua dev-1 depends on lua >= 5.1 (5.1-1 provided by VM)
nelua dev-1 depends on penlight >= 1.7.0 (not installed)
Installing https://luarocks.org/penlight-1.7.0-1.src.rock
Missing dependencies for penlight 1.7.0-1:
   luafilesystem (not installed)

penlight 1.7.0-1 depends on luafilesystem (not installed)
Installing https://luarocks.org/luafilesystem-1.7.0-2.src.rock

luafilesystem 1.7.0-2 depends on lua >= 5.1 (5.1-1 provided by VM)
C:\Programs\mingw-w64\mingw64\bin\gcc.exe -O2 -c -o src/lfs.o -Ic:\programs\luarock\include src/lfs.c
C:\Programs\mingw-w64\mingw64\bin\gcc.exe -shared -o lfs.dll src/lfs.o c:\programs\luarock/lua5.1.dll -lMSVCR80
collect2.exe: error: ld returned 5 exit status

Error: Failed installing dependency: https://luarocks.org/penlight-1.7.0-1.src.rock - Failed installing dependency: https://luarocks.org/luafilesystem-1.7.0-2.src.rock - Build error: Failed compiling module lfs.dll

got a error window with a message about ld.exe crashing during the process...
just starting with nelua, first try. will look more at home later, but if you see something obvious, please let me know.
thanks.

about -fno-crossjumping -fno-gcse

I test the two option, and the benchmark result is nearly same. here is the code

function fibonacci(n)
    if n<3 then
        return 1
    else
        return fibonacci(n-1) + fibonacci(n-2)
    end
end

print(fibonacci(39))

Nelua crashes when using calling a method and the function declaration doesn't contain any parameters

  • I tested it on latest Nelua version from master branch.
  • I checked there is no similar issue already reported.
  • My code has no errors or misuse of Nelua. (well, is a misuse actually)

Bug description

When trying to use a method on variable which the type actually declares, but in this declaration there is no parameters, the Nelua compiler crashes and gives the compiler's traceback instead of giving an error message.

Code example

local R = @record{a: integer}

function R.hello()
  print'hello'
end

local x: R = {}
x:hello()

This problem doesn't happens when the : syntax sugar is not used:

local R = @record{a: integer}

function R.hello()
  print'hello'
end

local x: R = {}
R.hello(x)

output:

 nelua ../teste.nelua 
../teste.nelua:8:8: error: in call of function 'R.hello': expected at most 0 arguments but got 1
R.hello(x)
       ^~~

Expected behavior

An error message is expected, something like the output when not using the : syntax sugar.

Environment

  • Nelua version:
    • Nelua 0.2.0-dev
    • Build number: 866
    • Git date: 2021-02-05 16:35:19 -0300
    • Git hash: 3464918
  • Platform (e.g. Windows/MSYS2, Ubuntu Linux, MacOS)
    • Pop!_OS 20.10 (Based on Ubuntu 20.10)

segfault fault filestream:close()

WARNING: Please, read this note carefully before submitting a new bug:

It is important to realise that this is NOT A SUPPORT FORUM, this is for reproducible BUGS ONLY.

If you need support, have questions, ideas to discuss you should use
the Nelua Discussions forum or
the Nelua Discord server.

Please, before submitting a new issue verify and check:

  • I tested it on latest Nelua version from master branch.
  • I checked there is no similar issue already reported.
  • My code has no errors or misuse of Nelua.

Bug description

i made a program to download something from internet example.com
and write it to a file. but its always Segmentation fault (core dumped)
when i call filestream:close()

Code example

Provide minimal reproduction code to test the bug.
Please, format the code properly and try to keep it as simple as possible, just focusing on the experienced bug.

require "modules/curl/curl"
require "io"

print("open a file")
local s:string, i:integer
local file:filestream
file,s,i = io.open("example", "w+")
print(file,s,i)

local function write_func(ptr:cstring, size:csize, nmemb:csize, userdata:pointer):csize
	local b:boolean, s:string, i:integer
	b, s, i = file:write(ptr)
	print("write callback", b, s, i)
	return size*nmemb
end


local client:pointer = curl_easy_init()
curl_easy_setopt(client, CURLOPT_URL, "https://example.com")
curl_easy_setopt(client, CURLOPT_WRITEFUNCTION, write_func)
local response:CURLcode = curl_easy_perform(client)
print(file:flush())
print("closing tmpfile", file:close()) -- always segfault after printing text.
print("curl cleanup")
curl_easy_cleanup(client)

Expected behavior

no error

Environment

Provide relevant information about your environment:

  • Nelua version (you can check with nelua -v).
~ $ nelua --version
Nelua 0.2.0-dev
Build number: 1020
Git date: 2021-05-12 17:25:40 -0300
Git hash: e9de5bbeabd77e1c1b8099c3ab53eaabec1a1774
  • Platform (e.g. Windows/MSYS2, Ubuntu Linux, MacOS)
    Arch linux

  • C compiler if your bug has C compiler errors. (e.g. GCC 10.2, Clang 11)

~ $ gcc --version
gcc (GCC) 10.2.0

better type inference for facultative arguments

Please, before submitting a new feature verify and check:

  • I tested it on latest Nelua version from master branch.
  • I checked there is no similar feature already implemented or requested.
  • I checked that the feature is not in the roadmap.

Feature motivation

When using facultatives, nelua recognize the argument as a table and not as the desired type, this is resolved using casting.

Feature description

While is resolved using a cast, it would be nice if nelua could recognize the type without it. This feature can also be useful when the type is not accessible.

Code example

local R = @record{a: integer, b: number}

local function hello(r: facultative(R))
  ## if not r.type.is_niltype then
    print("r is: ", r.a, r.b)
  ## else
    print("r is not given")
  ## end
end

hello()
hello({10, 20}) -- currently must be hello((@R){10, 20})

Describe alternatives you've considered

Using casting and exposing the type when it would be not accessible.

Weird behavior when messing with type inference

I have hard time understanding how type inference works and decided to play more to finally grasp its semantics.

While I was doing so, the following code caused a problem:

require 'io'
require 'string'

do
  local msgv1 : auto = "hello"
  io.printf("%s from Nelua world!\n", msgv1)
  local msgv2 : string = "greetings"
  io.printf("%s from Nelua world!\n", msgv2)
  local msgv3 : type = #[msgv1.type]#
  io.printf("%s from New Nelua world!\n", msgv3)
end

image

The problem takes place when I attempt to use #[msgv1.type]# to get my first variable's type.

Now, I know that local msgv3 : type = #[msgv1.type]# is wrong and it should be msgv3 : #[msgv1.type]# = "Saludos" in order to work.

Why has it tried to build in the first place without complaining about its logic is the real question...

P.S.: would not it be nice to have a shortcut for types? For instance, in my case it could be @"" to get the strings type.

solaris 11 failed for require

I have successfully ported nelua to Solaris 11 SPARC, it failed to compile and install out of box.

$ pkg info entire | grep Version
Version: 11.4 (Oracle Solaris 11.4.35.94.4)

Some code works:

$ ./nelua.sh examples/matmul.nelua 
-18.8963499125
$ ./nelua.sh examples/mersenne.nelua 
0.8780107
0.2555161
0.4640734
0.94218546979306
0.79106567887208
0.0079998746971573
$

any code with require keyword failed and must be fixed:

$ cat examples/helloworld.nelua 
require 'math'
print 'hello world'
$ ./nelua.sh examples/helloworld.nelua 
examples/helloworld.nelua:1:1: from: AST node Block
require 'math'
^~~~~~~~~~~~~~
/export/home/cddr/nelua-lang/lib/math.nelua:6:1: from: AST node Block
global math: type = @record{}
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/export/home/cddr/nelua-lang/lib/math.nelua:6:1: error: error while preprocessing block: /export/home/cddr/nelua-lang/nelua/utils/bn.lua:89: malformed number
global math: type = @record{}
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~

stack traceback:
        [C]: in function 'assert'
        /export/home/cddr/nelua-lang/nelua/utils/bn.lua:89: in function 'nelua.utils.bn.from'
        /export/home/cddr/nelua-lang/nelua/analyzer.lua:30: in field '?'
        /export/home/cddr/nelua-lang/nelua/analyzercontext.lua:112: in function 'nelua.analyzercontext.traverse_node'
        /export/home/cddr/nelua-lang/nelua/analyzer.lua:2245: in field '?'
        /export/home/cddr/nelua-lang/nelua/analyzercontext.lua:112: in function 'nelua.analyzercontext.traverse_node'
        /export/home/cddr/nelua-lang/nelua/ppcontext.lua:199: in function 'nelua.ppcontext.inject_statement'
        /export/home/cddr/nelua-lang/lib/math.nelua:@ppcode:518: in function </export/home/cddr/nelua-lang/lib/math.nelua:@ppcode:1>
        [C]: in function 'xpcall'
        /export/home/cddr/nelua-lang/nelua/utils/except.lua:154: in function 'nelua.utils.except.trycall'
        ...     (skipping 7 levels)
        /export/home/cddr/nelua-lang/nelua/analyzer.lua:3298: in function 'nelua.analyzer.analyze'
        /export/home/cddr/nelua-lang/nelua/runner.lua:107: in function </export/home/cddr/nelua-lang/nelua/runner.lua:106>
        [C]: in function 'xpcall'
        /export/home/cddr/nelua-lang/nelua/utils/except.lua:135: in function 'nelua.utils.except.try'
        /export/home/cddr/nelua-lang/nelua/runner.lua:106: in upvalue 'run'
        /export/home/cddr/nelua-lang/nelua/runner.lua:188: in function </export/home/cddr/nelua-lang/nelua/runner.lua:187>
        [C]: in function 'xpcall'
        /export/home/cddr/nelua-lang/nelua/utils/except.lua:135: in function 'nelua.utils.except.try'
        /export/home/cddr/nelua-lang/nelua/runner.lua:187: in function 'nelua.runner.run'
        /export/home/cddr/nelua-lang/nelua.lua:2: in main chunk
        [C]: in ?

Bug in generated C code while using <const>

Seems like there's a bug during generating C code for the following code:

require 'io'

do
  local last <const> = -1
  for i=5,0,last do
    io.printf("%d",i)
  end
end

This is the error:

/home/stefanos/.cache/nelua/tmp.c: In function ‘nelua_main’:
/home/stefanos/.cache/nelua/tmp.c:1816:34: error: ‘_step’ undeclared (first use in this function); did you mean ‘_setjmp’?
 1816 |     for(int64_t i = 5, _end = 0; _step >= 0 ? i <= _end : i >= _end; i = i + last) {
      |                                  ^~~~~
      |                                  _setjmp
/home/stefanos/.cache/nelua/tmp.c:1816:34: note: each undeclared identifier is reported only once for each function it appears in
error: C compilation for '/home/stefanos/.cache/nelua/tmp' failed

shell returned 1

Press ENTER or type command to continue

bug

Bug description

I'm not sure this is really a bug but when you follow the documentation and type
make install PREFIX=~/.nelua
this won't install and will create a directory ~ in the current git repository where sources have been fetched.
To make it work I had to type
make install PREFIX=/Users/$USER/.nelua

Code example

Expected behavior

make install PREFIX=~/.nelua
would create a .nelua directory inside my home folder and put bin and lib there :)

Workaround

make install PREFIX=/Users/$USER/.nelua

Environment

Provide relevant information about your environment:

  • Nelua version : 0.2.0-dev
  • Platform : MacOS
  • Architecture (Apple Sillicon aarm64?)

C structs in record

When writing C bindings, it's nice to be able to put the functions into a single record, e.g. Sdl.Init() instead of SDL_Init. But the compiler doesn't accept it to refactor structs the same way:

global Sdl.Event <cimport, cinclude'<SDL2/SDL.h>', nodecl> = @record {
  type: uint32,
  padding: [56]byte
}

function Sdl.PollEvent(event: *Sdl.Event): int32 <cimport, cinclude'<SDL2/SDL.h>', nodecl> end

leads to:

sdl.nelua:51:35: syntax error: unclosed parenthesis, did you forget a `)`?
function Sdl.PollEvent(event: *Sdl.Event): int32 <cimport, cinclude'<SDL2/SDL.h>', nodecl> end
                                  ^

Question: plans on error handling?

Hello,

I really like what I've read on nelua so far, being a big fan of Lua I love the idea of using a similar language with native code, AOT, low-level properties. I noticed in the Differences page (https://nelua.io/diffs/), [x]pcall are marked as never/n.a. Does that mean that error handling is to be done strictly via the return nil, err idiom, and there wouldn't be a way to recover from a runtime panic? Or is it TBD later in the project?

Thanks,
Martin

Deference error

The following code:

local PLAYER_JUMP_SPD: number <comptime> = 350

local Player = @record{
   speed: number,
   canJump: boolean
}

local function UpdatePlayer(player: Player*)
   ($player).speed = -PLAYER_JUMP_SPD
   ($player).canJump = false
end

Produces the following error:

$ nelua -b examples/2d-camera-platformer.nelua 
examples/2d-camera-platformer.nelua:23:22: syntax error: expected `end` keyword
   ($player).canJump = false
                     ^

However, the following code compiles succefully:

local PLAYER_JUMP_SPD: number <comptime> = 350

local Player = @record{
   speed: number,
   canJump: boolean
}

local function UpdatePlayer(player: Player*)
   ($player).speed = -PLAYER_JUMP_SPD; -- the only difference is this ;
   ($player).canJump = false
end

This also compiles:

local PLAYER_JUMP_SPD: number <comptime> = 350

local Player = @record{
   speed: number,
   canJump: boolean
}

local function UpdatePlayer(player: Player*)
   ($player).speed = -350
   ($player).canJump = false
end

crash instead of error report on nested record return typos

Bug description

If the user write a typo on the return type, and the return type is nested on a record, then nelua crsah instead of reporting a proper error message.

Code example

local R = @record{}
global R.Foo = @record{ x: integer }

local function x(): R.Fooo
  return R.Foo{10}
end

Expected behavior

An error message

Environment

Provide relevant information about your environment:

  • Nelua version:
Nelua 0.2.0-dev
Build number: 1270
Git hash: e11f12e03649502b997f78349241e1ed1c506704
  • Platform: Pop!_OS 21.04
  • Architecture: x86_64

Proposal: Expression Blocks

An Expression Block is a scoped construct which yields the last evaluated value for a given branch.

Suppose an Expression Block would be syntactically defined as expr ... end, then the following block of code would work:

local baz = 3

local Foo = @record { bar: integer }

local foo: Foo = expr
  if baz == 3 then
    local tmp = baz + 1
    -- this the last evaluated expression, so it gets returned from this block automatically
    { bar = tmp  }
  else
    { bar = 0 }
  end
end

They are more powerful and flexible than ternary operators, mainly because other instructions can be put between the if s and the assignment (in this case, local tmp = a).

Expression Blocks don't bloat the syntax - they look very similar to how do and block (from the draft) constructs look like, thus there's no need to invent a special assignment syntax for ternary operators.

For inspiration:

Unable to compile on DOS

WARNING: Please, read this note carefully before submitting a new bug:

It is important to realize that this is NOT A SUPPORT FORUM, this is for reproducible BUGS ONLY.

If you need support, have questions, ideas to discuss you should use
the Nelua Discussions forum or
the Nelua Discord server.

Please, before submitting a new issue, verify the following:

  • You have tested it on latest Nelua version from master branch.
  • You have checked that there is no similar issue already reported.
  • You have checked that your code has no errors or misuse of Nelua.

Bug description

A clear and concise description of the bug you are experiencing.
Tell what you were trying to do and what happened instead.

I'm trying to build Nelua on DOSBox-X using DJGPP, but it failed to compile.
Screenshot_20210831-215453

Expected behavior

A clear and concise description of what you expected to happen.

It should compile correctly

Environment

Provide relevant information about your environment:

  • Nelua version (you can check with nelua -v). Nelua from the master branch
  • Platform (e.g. Windows/MSYS2, Ubuntu Linux, MacOS) DOSBox-X
  • Architecture (e.g. x86_64, arm64) i386 (DOSBox-X)
  • C compiler if your bug has C compiler errors. (e.g. GCC 10.2, Clang 11) GCC 9.3.0

error: assignment of read-only variable ‘const_a’

WARNING: Please, read this note carefully before submitting a new bug:

It is important to realise that this is NOT A SUPPORT FORUM, this is for reproducible BUGS ONLY.

If you need support, have questions, ideas to discuss you should use
the Nelua Discussions forum or
the Nelua Discord server.

Please, before submitting a new issue verify and check:

  • I tested it on latest Nelua version from master branch.
  • I checked there is no similar issue already reported.
  • My code has no errors or misuse of Nelua.

Bug description

A clear and concise description of the bug you are experiencing.
Tell what you were trying to do and what happened instead.

The latest commit f448b29 breaks the code below.

$ nelua const.nelua 
C compilation for 'nelua_cache/const' failed:
nelua_cache/const.c: In function ‘nelua_main’:
nelua_cache/const.c:53:11: error: assignment of read-only variable ‘const_a’
   53 |   const_a = const_x;
      |           ^

Code example

Provide minimal reproduction code to test the bug.
Please, format the code properly and try to keep it as simple as possible, just focusing on the experienced bug.

local x <const> = 1
local a <const> = x
print(a) -- outputs: 1

-- uncommenting the following will trigger the compile error:
-- error: cannot assign a constant variable
-- a = 2

Expected behavior

A clear and concise description of what you expected to happen.

To see 1 as output

Environment

Provide relevant information about your environment:

  • Nelua version (you can check with nelua -v).
Nelua 0.2.0-dev
Build number: 1155
Git date: 2021-07-15 17:28:09 -0300
Git hash: f448b29674a399600d4f1b19cd74b273233b5b36
Copyright (C) 2019-2021 Eduardo Bart (https://nelua.io/)
  • Platform (e.g. Windows/MSYS2, Ubuntu Linux, MacOS)
OS: GNU / Linux Debian testing 64-bit
  • C compiler if your bug has C compiler errors. (e.g. GCC 10.2, Clang 11)
gcc version 10.2.1 20210110 (Debian 10.2.1-6) 

how to use linklib ?

Hello,
can you please tell me how is linklib used ?
for example in your snake sample, I found : ## linklib 'SDL2'
what kind of file should I give to it ?
thanks

'which' versus 'command -v'

At https://github.com/edubart/nelua-lang/blob/master/nelua.sh#L29 you use which command which on GNU / Debian is installed as an external binary that is located in /usr/bin/which, that happens to be a classic shell itself.

The question is, what happens if it's not installed?

As far as I know, command -v does the exact thing and it's a builtin command which is also POSIX-compliant.

Would you like to replace it with the aforementioned suggestion?

Discord Server

would be cool to have a discord server
EDIT: sorry, didn't realize exist

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.