diff --git a/src/dlltest.cpp b/src/dlltest.cpp new file mode 100644 index 0000000..7f96c18 --- /dev/null +++ b/src/dlltest.cpp @@ -0,0 +1,24 @@ +#include "dlltest.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +void testprint() +{ + printf("Hola, soy %s\n", "C"); + return; +} + +//clang -v -std=c11 -DCALCDLL_EXPORTS src/dlltest.c -shared -o src/dlltest.dll +//clang++ -v -std=c++11 -DCALCDLL_EXPORTS src/dlltest.cpp -shared -o src/dlltest.dll +CALCDLL_API BOOL __cdecl DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) +{ + return TRUE; +} + +#ifdef __cplusplus +} +#endif + diff --git a/src/dlltest.dll b/src/dlltest.dll new file mode 100644 index 0000000..a88141e Binary files /dev/null and b/src/dlltest.dll differ diff --git a/src/dlltest.h b/src/dlltest.h new file mode 100644 index 0000000..af1d15e --- /dev/null +++ b/src/dlltest.h @@ -0,0 +1,24 @@ +#ifndef TEST_H +#define TEST_H + +#define WIN32_LEAN_AND_MEAN +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef CALCDLL_EXPORTS + #define CALCDLL_API __declspec(dllexport) +#else + #define CALCDLL_API __declspec(dllimport) +#endif + +CALCDLL_API void __cdecl testprint(); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/dlltest32.dll b/src/dlltest32.dll new file mode 100644 index 0000000..6d51989 Binary files /dev/null and b/src/dlltest32.dll differ diff --git a/src/main.lua b/src/main.lua index 7d7add0..720cf17 100644 --- a/src/main.lua +++ b/src/main.lua @@ -280,4 +280,250 @@ print("Function anonimity demonstration") foo = function (x) return x, 2*x end -print(foo(2)) +print(foo(2)) ; foo = nil +print() + +print("Function as a first-class value and closures test") +function bruh (x) + local transform = x * 2 + print(transform) + return function () + transform = transform + 1 + return transform + end +end + +incrementFunc = bruh(2) +print(incrementFunc()) +print(incrementFunc()) +print(incrementFunc()) +incrementFunc, bruh = nil, nil +print() + +print("Local functions (packages!: this way, we get functions only visible on the current chunk)") +local a = function () return 3 end +local function a () return 3 end --equivalent, again + +function c () return a() end +print(c()) -- Since we're on the same chunk, this functions is still accesible + +-- But beware! A function is compiled before its assignment is done, so it will ignore its own assignment and look for the +-- definition scopes above until getting to globals! +-- the local function name () syntax sidesteps this limitation, but indirect recursion still forces you to forward declare +local c = nil +local a = nil + +print("Tail calls") +--Only this syntax performs a proper tail call: +--[[ function g(x) + return funcname(params) + end + + it works with anonymous functions too! +]] + +tablajemplo = { "a", "b", "c" } +tablajemplo[4] = 54 +print("Iterators with closures (complex state)") + +function return_ilist_values(list) + local i = 0 + local num = #list + print("List size: " .. num) + return function () + i = i + 1 + if i <= num then return list[i] end + end +end + +for value in return_ilist_values(tablajemplo) do + print(value) +end + +print("Iterators without closures") +--Also like a generic for's internal structure exploration +function direct_iter_func(list, i) + --print("hey"..i) + num = #list + i = i + 1 + if i <= num then return i, list[i] end +end + +local idx = 0 +for idx, value in direct_iter_func, tablajemplo, idx do + print(value) +end + +print("Stateless iterators") +-- Really your most common use case, imo. State (dataset) is given with each call instead of being hardcoded into the factory's +-- code + +function diypair(list) + return function (state, cvar) + cvar = cvar + 1 + if state[cvar] then return cvar, state[cvar] end + end, list, 0 +end + +for idx, value in diypair(tablajemplo) do + print(value) +end + +noenterotabla = {x = 2, b = 43, c = "si"} +for idx, value in next, noenterotabla do + print(idx .. " " .. value) +end +tablajemplo, noenterotabla = nil, nil + +-- loadstring loads code from a string and assigns it to a var! Can only see global variables! loadfile, same for files! dofile +-- is an autoexec for this function with an assert! Errors as 2nd param in both load*! +--[[ + f = loadstring("c = 'españa'; print(c); + function hola(letra) print(c .. ' a tope') end; hola(c)") --ret func as 1st, err as 2nd. Easier to use assert! + f() +]] + +-- print("_LOADED variable (shows which files have been already loaded by require") +-- print(_REQUIREDNAME) +-- print(_LOADED) + +print("Loading C dynamic libraries") +-- dll included! example compile command: +-- clang -v -std=c11 src/dlltest.h -shared -o src/test.dll +path = "F:\\carpincho\\cositas\\luar\\src\\dlltest32.dll" +local examplint = assert(package.loadlib(path, "testprint")) +examplint() + +print("Using protected calls to handle errors") +--error("error test") This will stop execution +print(pcall(function () error("error test") end)) --This will not! 1st retval is bool indicating success, 2nd is error msg +local status, err = pcall(function () error({code=6667}) end) +print(tostring(status) .. " " .. tostring(err.code)) +print("Still here!") +print() + +print("Error tracing") +--Custom error handler +local value = 3 +local status +local err +function fakebug() print("fake ass debugging") end +status, err = xpcall(function () + if type(value) ~= "string" then + error("no coinside", 1) + end +end, fakebug) + +print(tostring(status) .. " " .. tostring(err) .. "\n") + +--Changing error level indication: level 1 (default: where error is called)/ 2 (where the func that calls error is used) +status, err = pcall(function () + if type(value) ~= "string" then + error("no coinside", 2) + end +end) + +print(tostring(status) .. " " .. tostring(err).. "\n") + +status, err = pcall(function () + if type(value) ~= "string" then + error("no coinside", 1) + end +end) + +print(tostring(status) .. " " .. tostring(err).. "\n") +status, err = nil, nil + +print("Coroutines:") +function base(x) print("vaya" .. tostring(x)) coroutine.yield("yieldturn") print("adiós" .. tostring(x)) return x + 4 end +cor = coroutine.create(base) +cor2 = coroutine.create(base) +print(coroutine.status(cor) .. " " .. coroutine.status(cor2)) + +print(coroutine.resume(cor, 1)) +print(coroutine.resume(cor2, 3)) +print(coroutine.status(cor) .. " " .. coroutine.status(cor2)) + +print(coroutine.resume(cor,2)) --See that params are now ignored +print(coroutine.resume(cor2,4)) +print(coroutine.status(cor) .. " " .. coroutine.status(cor2)) +print() + +--Producer/consumer example +function producer(filename) + for line in io.lines("lines.txt") do + print("DEBUG " .. line) + coroutine.yield(line) + end +end + +function consumer(filename) + if type(filename) ~= "string" then return "Not a string" end + local line + local status + produtine = coroutine.create(producer) + repeat + --print(coroutine.resume(produtine)) + --line = false + status, line = coroutine.resume(produtine) + if (line) then + print(tostring(status) .. " " .. line) + end + until not line +end + + +print(consumer("lines.txt")) + +print("Coroutines as iterators") +for i=1,3 do + print(i) +end +print() + +function permgen (a, n) + --if n == 0 then + --printResult(a) + if n == 0 then + coroutine.yield(a) + else + for i=1,n do + + -- put i-th element as the last one + a[n], a[i] = a[i], a[n] + + -- generate all permutations of the other elements + permgen(a, n - 1) + + -- restore i-th element + a[n], a[i] = a[i], a[n] + + end + end +end + +function perm (a) + local n = table.getn(a) + local co = coroutine.create(function () permgen(a, n) end) + return function () -- iterator + local code, res = coroutine.resume(co) + return res + end +end + +function printResult (a) + for i,v in ipairs(a) do + io.write(v, " ") + end + io.write("\n") + end + +local i = 1 +for p in perm{"a", "b", "c", "d"} do + printResult(p) + print(i) + i = i + 1 + end +--table = {1, 2, 3} +--function all_permutations(list, n) +