From 19111b5aebdb7589a76030e266eb4e1e9f346209 Mon Sep 17 00:00:00 2001 From: Quinten Kock Date: Sun, 12 Mar 2023 23:35:40 +0100 Subject: [PATCH] Add hooks and C structs --- README.md | 1 + c.lua | 30 +++++++++++++++++++++++ examples/linkedlist.c.mpp | 49 ++++++++++++++++++++++++++++++++++++++ examples/template.c.mpp | 32 +++++++++++++++++++++++++ init.lua | 50 ++++++++++++++++++++++++++++++--------- template.c | 18 -------------- template.c.mpp | 23 ------------------ 7 files changed, 151 insertions(+), 52 deletions(-) create mode 100644 README.md create mode 100644 c.lua create mode 100644 examples/linkedlist.c.mpp create mode 100644 examples/template.c.mpp delete mode 100644 template.c delete mode 100644 template.c.mpp diff --git a/README.md b/README.md new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ + diff --git a/c.lua b/c.lua new file mode 100644 index 0000000..a177f30 --- /dev/null +++ b/c.lua @@ -0,0 +1,30 @@ +local c = {} + +function c.struct(name, fields_init) + local fields = fields_init or {} + local struct = {} + output:expression(function() + local s = "struct " .. name .. " {\n" + for _,v in pairs(fields) do + s = s .. "\t" .. v .. ";\n" + end + return s.. "};\n" + end) + setmetatable(struct, { + __index = fields, + __newindex = function(self, key, value) + if self[key] and self[key] ~= value then + error("Conflicting defintions of " .. name .. "." .. key .. ":\n\t'" .. self[key] .. "'\n\t'" .. value .. "'"); + else + fields[key] = value + end + end, + __tostring = function() + return "struct " .. name + end + }) + _G[name] = struct + return struct +end + +return c diff --git a/examples/linkedlist.c.mpp b/examples/linkedlist.c.mpp new file mode 100644 index 0000000..2b85c05 --- /dev/null +++ b/examples/linkedlist.c.mpp @@ -0,0 +1,49 @@ +#include + +@function linkedlist(T, plugins) + @local l = mpp.c.struct("linkedlist_" .. T) + @local hooks = mpp.hooks() + @l.value = T.." value" + @l.next = tostring(l) .. " *next" + + $T$ *ll_$T$_index(struct linkedlist_$T$ *list, size_t index) { + while(index > 0) { + if(!list->next) { + return NULL; + } else { + list = list->next; + } + } + return &list->value; + } + + struct linkedlist_$T$ ll_$T$_cons($T$ value, struct linkedlist_$T$ *tail) { + struct linkedlist_$T$ l; + l.value = value; + l.next = tail; + @hooks("cons") + return l; + } + @for _,plugin in ipairs(plugins or {}) do plugin(T, l, hooks) end +@end + +@function linkedlist_len_naive(T, l, hooks) + size_t ll_$T$_len(struct linkedlist_$T$ *list) { + size_t len = 0; + for(; list; len++) { + list = list->next; + } + return len; + } +@end + +@function linkedlist_len_cached(T, l, hooks) + @l.size = "size_t size" + @hooks.cons("l.size = tail ? tail->size + 1 : 1;") + size_t ll_$T$_len(struct linkedlist_$T$ *list) { + return list->size; + } +@end + +@linkedlist("int", {linkedlist_len_naive}) +@linkedlist("float", {linkedlist_len_cached}) diff --git a/examples/template.c.mpp b/examples/template.c.mpp new file mode 100644 index 0000000..144fbf6 --- /dev/null +++ b/examples/template.c.mpp @@ -0,0 +1,32 @@ +#include +#include + +@mpp.c.struct("stats") +@function counter(name) stats[name] = "size_t " .. name end +struct stats stats; + +@function sum_t(type, base) + @local base = base or 0 + $type$ sum_$type$($type$ *xs, size_t len) { + $type$ sum = $base$; + for(size_t i = 0; i < len; i++) { + @counter("summed" .. type) + stats.summed$type$++; + sum += xs[i]; + } + return sum; + } +@end + +@sum_t("int") +@sum_t("float") + +int main() { + int xs[3] = {1, strlen("foo"), strlen("bar")}; + int x = sum_int(xs, 3); + float ys[3] = {1.0, 3.14, 9.81}; + float y = sum_float(ys, 3); + printf("%i %f\n", x, y); + return 0; +} + diff --git a/init.lua b/init.lua index 19d5a99..e682f50 100644 --- a/init.lua +++ b/init.lua @@ -1,12 +1,11 @@ -local mpp = {} +mpp = {} -local output = {} +mpp.c = require "c" local function process(file) - local script = "" - local f = io.open(file, "r") + local f = assert(io.open(file, "r")) coroutine.yield([[ -local output = {} +output = {} function output:literal(x) table.insert(self, x) end @@ -14,7 +13,7 @@ function output:expression(f) table.insert(self, f) end ]]) - + for line in f:lines() do if line:find("^%s-" .. mpp.directive) then -- Line starts with MPP directive @@ -46,7 +45,7 @@ end local function outputmpp(file) local generator = coroutine.wrap(function() process(file) end) - local f = io.open(file .. ".lua", "w") + local f = assert(io.open(file .. ".lua", "w")) for line in generator do f:write(line) end @@ -55,12 +54,14 @@ end function mpp.execute(files) local outputs = {} for i,file in ipairs(files) do - outputmpp(file .. ".mpp") + print("executing file " .. file) + -- outputmpp(file .. ".mpp") outputs[i] = loadmpp(file .. ".mpp")() end for i,output in ipairs(outputs) do - local file = io.open(files[i], "w") - for j, o in ipairs(output) do + print("outputting file " .. files[i]) + local file = assert(io.open(files[i], "w")) + for _, o in ipairs(output) do if type(o) == "string" then file:write(o) elseif type(o) == "function" then @@ -71,6 +72,33 @@ function mpp.execute(files) end end +function mpp.hook() + local hook = {} + setmetatable(hook, { + __call = function(self, code) + table.insert(self, code .. "\n") + end + }) + return hook +end + +function mpp.hooks() + local hooks = {} + setmetatable(hooks, { + __index = function(self, key) + self[key] = mpp.hook() + return self[key] + end, + __call = function(self, key) + output:expression(function() + return table.concat(self[key]) + end) + end, + }) + return hooks +end + mpp.directive = "@" -mpp.execute{ "template.c" } \ No newline at end of file +-- mpp.execute{ "examples/template.c" } +mpp.execute{"examples/linkedlist.c"} diff --git a/template.c b/template.c deleted file mode 100644 index c065a6b..0000000 --- a/template.c +++ /dev/null @@ -1,18 +0,0 @@ -#include - - - - int sum_int(int *xs, size_t len) { - int sum = 0; - for(size_t i = 0; i < len; i++) { - sum += xs[i]; - } - return sum; - } - -int main() { - int x = sum_int({strlen("foo"), strlen("bar")}); - printf("%i\n", x) - return 0; -} - diff --git a/template.c.mpp b/template.c.mpp deleted file mode 100644 index ef2b753..0000000 --- a/template.c.mpp +++ /dev/null @@ -1,23 +0,0 @@ -#include - -@print("foo") - -@function sum_t(type, base) - @local base = base or 0 - int sum_$type$($type$ *xs, size_t len) { - $type$ sum = $base$; - for(size_t i = 0; i < len; i++) { - sum += xs[i]; - } - return sum; - } -@end - -@sum_t("int") - -int main() { - int x = sum_int({strlen("foo"), strlen("bar")}); - printf("%i\n", x) - return 0; -} - \ No newline at end of file