Add hooks and C structs

This commit is contained in:
Quinten Kock 2023-03-12 23:35:40 +01:00
parent 68e979fcec
commit 19111b5aeb
7 changed files with 151 additions and 52 deletions

1
README.md Normal file
View File

@ -0,0 +1 @@

30
c.lua Normal file
View File

@ -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

49
examples/linkedlist.c.mpp Normal file
View File

@ -0,0 +1,49 @@
#include <stdlib.h>
@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})

32
examples/template.c.mpp Normal file
View File

@ -0,0 +1,32 @@
#include <stdio.h>
#include <string.h>
@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;
}

View File

@ -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" }
-- mpp.execute{ "examples/template.c" }
mpp.execute{"examples/linkedlist.c"}

View File

@ -1,18 +0,0 @@
#include <stdio.h>
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;
}

View File

@ -1,23 +0,0 @@
#include <stdio.h>
@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;
}