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/lines.txt b/src/lines.txt new file mode 100644 index 0000000..7387381 --- /dev/null +++ b/src/lines.txt @@ -0,0 +1,5 @@ +linea1 +linea2 +linea3 +linea4 +linea5 diff --git a/src/main.lua b/src/main.lua new file mode 100644 index 0000000..720cf17 --- /dev/null +++ b/src/main.lua @@ -0,0 +1,529 @@ +local dbg = require 'debugger' +-- Func asand type test +-- print("hello world") + +-- function factos (n) +-- -- dbg() +-- if n == 0 then +-- return 1 +-- else +-- return n * factos(n - 1) +-- end +-- end + +-- print("Enter a number: ") +-- a = io.read("*number") +-- print(factos(a)) +-- print(type(factos)) +-- print(type(false)) + +print("String test") +asciicore = "alo123\thola\n" +asciicore2 = "\97lo\9hola\49 \10" +io.write(asciicore); print(asciicore2); +paragraphcore = [[ +increible +la maravilla +interpretada ]] +print(paragraphcore) +print(10 .. 20) --string conversion, concat +print(10 + 20) --int sum, string conversion +print(10 == "10") + +print("Table test") +a = {} -- create a table and store its reference in `a' +k = "x" +a[k] = 10 -- new entry, with key="x" and value=10 +a[20] = "great" -- new entry, with key=20 and value="great" +print(a["x"]) --> 10 +k = 20 +print(a[k]) --> "great" +a["x"] = a["x"] + 1 -- increments entry "x" +print(a["x"]) --> 11 +print() + +print(a["z"]) +a["z"] = nil +print(a["z"]) +a = nil +print() + + print("Convention: tables in lua are usually indexed starting with 1, the stdlib follows this") +arr = {} +for i=0,9 do + arr[i] = i*2 +end +for i=0,9 do + print(arr[i]) +end +print() + print("Convention: using nil as table end. ipairs follows this") +arr[10] = nil +arr[11] = 34 +for i,number in ipairs(arr) do + print(number) +end +arr = nil +print() + + print("Array indexing doesn't perform any type conversion") +i = 10; j = "10"; k = "+10" +a = {} +a[i] = "one value" +a[j] = "another value" +a[k] = "yet another value" +print(a[i]) --> one value +print(a[j]) --> another value +print(a[k]) --> yet another value +print(a[tonumber(j)]) --> one value +print(a[tonumber(k)]) --> one value +a = nil +print() + +print("Logical operators test") +v = 3 +--x = 4 +x = false -- boolean, while a value, is evaluated as it should and replaced by the expression: +print(type(x)) +if not x then x = v end +print(tostring(x)) +print(type(x).."\n") + + +print(nil and false) +print(4 and false) +print(4 and 5) +if (4 and false) then + print("si") +else + print("no") +end +print() + +val = v and 7 or 14 +print(val) +v = false +val = v and 7 or 14 +print(val) +val = (v == false) and 7 or 14 +print(val) +val = (v ~= false) and 7 or 14 +print(val) +v = nil; print() + +print("Operator precedence") +x = 3 +print(x^3) + +print("Tables") +local math = require 'math' +tab = {math.sin(1), math.sin(2), math.cos(3)} +print(tab[1] .. " " .. tab[3]) + +print("Using table to implement linked list") +list = nil +for line in io.lines("lines.txt") do + list = {next=list, value=line} + print(tostring(list.next) .. " " .. list.value) +end + +l = list +while l do + print(l.value) + l = l.next +end +l = nil; list = nil; value = nil; +print() + +print("Mixing initializations and constructing tables within tables") +polyline = {color="blue", thickness=2, npoints=4, + {x=0, y=0}, + {x=-10, y=0}, + {x=-10, y=1}, + {x=0, y=1} +} + +print(polyline[1]) +print(polyline[1].x) +print(polyline.color) +print(polyline[2]) +print(polyline[2].x) +polyline = nil +print() + +print("Explicitly writing index as an expr") +opnames = {["+"] = "add", ["-"] = "sub", + ["*"] = "mul", ["/"] = "div"} + +i = 20; s = "-" +a = {[i+0] = s, [i+1] = s..s, [i+2] = s..s..s} + +print(opnames[s]) --> sub +print(a[22]) --> --- +a = nil; i = nil; opnames = nil; +print() + +print("Assignments") +x = 1; y = 2; +x, y, c = y, x --[[Variables are first evalueated and then swapped. Extra var is set to nil, extra value is discarded. + Always 1 value per var, no multi assignments]] +print(x .. " " .. y) +x = nil; y = nil + +print("Local variables: chunk, func or control block. On repl") +local a = 3; print(a) --Would print 3 +local a = 3 +print(a) --Would print nil on repl since we're not anymore at the scope where a was declared. Use do-end (equiv to { }, scope delimiters)! +local a = nil +print() + +print("Control structures: numeric for") +for i=1,4,2 do --initial value, max value, increment(optional = 1) + print(i) +end + +function f() + return 3 +end +print() + +for i=1,f() do + print(i) +end +print() +f = nil + +print("Control structures: generic for (foreach)") +a = {1, 2} +for i, v in ipairs(a) do print(i .. " " .. v) end +a = {x=1, y=2} +for i, v in pairs(a) do print(i .. " " .. v) end +for v in pairs(a) do print(v) end --only print keys +a = nil; print() + +print("Functions") + --No strict control of number of parameters passed to func (extra params = discarded, missing params = vars set to nil) +function f(x, y, z) + z = z or 1 + y = y or 1 + x = x or 1 + return x + y + z +end +print(f(2)) --4 +print(f(2,3)) --6 +print(f(2,3,4)) --9 +print(f(2,3,4,9)) --9 + + + + --Tables can be used as references for the content within, although with multiple retvals this should be seldomly used +function ft(a) + if (type(a) ~= "table") then + return + end + a[1] = 3 + return +end +a = {6} +ft(a); print(a[1]) +print() + + --Functions only return multiple values if they're the single or last expression: +function multireturn(a, b) + return a, b +end + +do +local a, b, c = multireturn(1, 2) +print(tostring(a) .. " " .. tostring(b) .. " " .. tostring(c)) +local a, b, c = 10, multireturn(1, 2) +print(tostring(a) .. " " .. tostring(b) .. " " .. tostring(c)) +local a, b, c = multireturn(1, 2), 10 +print(tostring(a) .. " " .. tostring(b) .. " " .. tostring(c)) --See how c is nil? We only kept the function's first retval +end +print() + + --Same thing happens when expr is part of another function call (args) +print(multireturn(1,2)) +print(10, multireturn(1,2)) +print(multireturn(1,2), 10) +print(multireturn(1,2) .. 10) +print(10 .. multireturn(1,2)) --And when it's a part of a expression, it always truncates extra retvals +print() + + --Variadic functions +function nsum(...) + local nsum = 0 + for i,v in ipairs(arg) do + nsum = nsum + v + end + print(nsum .. "\n") + --[[Equivalent to + for i = 1,arg.n do + nsum = nsum + arg[i] + end + print(nsum .. "\n") + ]] + + for i,v in pairs(arg) do + print(i .. " " .. v) + end + print() + return nsum +end + +print(nsum(2,3,4)) + +--TODO: Re-read chapter 5 + +print("Function anonimity demonstration") +foo = function (x) + return x, 2*x +end +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) +