-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add another example #24
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# Copyright (c) 2024, The Pallene Developers | ||
# Pallene Tracer is licensed under the MIT license. | ||
# Please refer to the LICENSE and AUTHORS files for details | ||
# SPDX-License-Identifier: MIT | ||
|
||
OUTPUT_FILE = component.so | ||
|
||
CC = cc | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You don't have to specify the C compiler variable |
||
CFLAGS = -O2 -std=c99 -pedantic -Wall -Wextra -Wformat-security | ||
LIBFLAGS = -fPIC -shared | ||
|
||
ifneq ($(findstring debug, $(MAKECMDGOALS)), ) | ||
CFLAGS += -DPT_DEBUG | ||
endif | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if statements in makefiles are complicated and non-portable. Consider
Another alternative is to recursivelly invoke make, just like Lua's makefile does for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The main point of detaching the Makefiles was to let the users try the examples with and w/o debugging mode enabled. If we turn on PT_DEBUG all the time, it would be better to move the examples build to root Makefile, which just doesn't seem right. Variables sound good though. Or maybe we can do some redundancy here (I just found out BSD and POSIX make do not support if statements). |
||
|
||
.PHONY: all debug clean | ||
|
||
all: $(OUTPUT_FILE) | ||
debug: $(OUTPUT_FILE) | ||
|
||
clean: | ||
rm -rf $(OUTPUT_FILE) | ||
|
||
%.so: %.c | ||
$(CC) $(CFLAGS) $(LDFLAGS) $(LIBFLAGS) $< -o $@ | ||
|
||
%.c: ptracer.h |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
/* | ||
* Copyright (c) 2024, The Pallene Developers | ||
* Pallene Tracer is licensed under the MIT license. | ||
* Please refer to the LICENSE and AUTHORS files for details | ||
* SPDX-License-Identifier: MIT | ||
*/ | ||
|
||
#include <stdlib.h> | ||
|
||
#define PT_IMPLEMENTATION | ||
#include "ptracer.h" | ||
|
||
/* ---------------- PALLENE TRACER LUA INERFACE ---------------- */ | ||
#define CON_LUA_FRAMEENTER(fnptr) \ | ||
PALLENE_TRACER_LUA_FRAMEENTER(L, fnstack, fnptr, \ | ||
lua_upvalueindex(1), _frame) | ||
/* ---------------- PALLENE TRACER LUA INERFACE END ---------------- */ | ||
|
||
/* ---------------- PALLENE TRACER C INTERFACE ---------------- */ | ||
|
||
#define CON_C_FRAMEENTER() \ | ||
PALLENE_TRACER_GENERIC_C_FRAMEENTER(fnstack, _frame) | ||
|
||
#define CON_C_SETLINE() \ | ||
PALLENE_TRACER_GENERIC_C_SETLINE(fnstack) | ||
|
||
#define CON_C_FRAMEEXIT() \ | ||
PALLENE_TRACER_FRAMEEXIT(fnstack) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My main issue with the names are
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. They are not actually "issues" per-se, at-least to my eyes.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
/* ---------------- PALLENE TRACER C INTERFACE END ---------------- */ | ||
|
||
/* This is one way to work with Pallene Tracer call-stack, but certainly not recommended because | ||
this way you loose the flexibility of using multiple Lua states. */ | ||
pt_fnstack_t *fnstack; | ||
|
||
static void internal_dfs(lua_State *L, int *visited, int node) { | ||
CON_C_FRAMEENTER(); | ||
|
||
if(visited[node]) { | ||
CON_C_FRAMEEXIT(); | ||
return; | ||
} | ||
|
||
visited[node] = 1; | ||
|
||
lua_rawgeti(L, 1, node); /* get the connected adjacent nodes of current node */ | ||
CON_C_SETLINE(); | ||
int n = luaL_len(L, -1); /* this line may trigger error */ | ||
lua_pop(L, 1); | ||
|
||
/* for all the adjacent nodes */ | ||
for(int i = 1; i <= n; i++) { | ||
lua_rawgeti(L, 1, node); | ||
lua_rawgeti(L, -1, i); | ||
int adjacent_node = lua_tointeger(L, -1); | ||
lua_pop(L, 2); /* avoid Lua value-stack overflow by not keeping values on the stack. */ | ||
|
||
CON_C_SETLINE(); | ||
internal_dfs(L, visited, adjacent_node); | ||
} | ||
|
||
CON_C_FRAMEEXIT(); | ||
} | ||
|
||
static int find_connected_components(lua_State *L, int *visited, int n) { | ||
CON_C_FRAMEENTER(); | ||
|
||
int result = 0; | ||
|
||
for(int i = 1; i <= n; i++) { | ||
if(!visited[i]) { | ||
result++; | ||
CON_C_SETLINE(); | ||
internal_dfs(L, visited, i); | ||
} | ||
} | ||
|
||
CON_C_FRAMEEXIT(); | ||
return result; | ||
} | ||
|
||
static int find_connected_components_lua(lua_State *L) { | ||
CON_LUA_FRAMEENTER(find_connected_components_lua); | ||
|
||
if(!lua_istable(L, 1)) | ||
luaL_error(L, "expected the first argument to be table"); | ||
if(!lua_isinteger(L, 2)) | ||
luaL_error(L, "expected the second argument to be integer"); | ||
|
||
int nodes = lua_tointeger(L, 2); /* get total number of nodes */ | ||
int *visited = calloc(nodes + 1, sizeof(int)); /* Lua prefers 1 based indexing */ | ||
|
||
/* Dispatch and push the result. */ | ||
lua_pushinteger(L, find_connected_components(L, visited, nodes)); | ||
|
||
free(visited); | ||
return 1; | ||
} | ||
|
||
int luaopen_component(lua_State *L) { | ||
fnstack = pallene_tracer_init(L); | ||
|
||
lua_newtable(L); | ||
int table = lua_gettop(L); | ||
|
||
/* ---- find_connected_components ---- */ | ||
/* `pallene_tracer_init` function pushes the frameexit finalizer to the stack. */ | ||
lua_pushvalue(L, -2); /* passing the finalizer object as upvalue is generally the way to go. */ | ||
lua_pushcclosure(L, find_connected_components_lua, 1); | ||
lua_setfield(L, table, "find_connected_components"); | ||
|
||
return 1; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
local component = require "component" | ||
|
||
local nodes = 12 | ||
local graph = { | ||
{ 2 }, -- 1st node | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider |
||
{ 1, 5 }, -- 2nd node | ||
{ 5 }, -- 3rd node | ||
{ 5 }, | ||
{ 2, 3, 4 }, | ||
{ 7, 8 }, | ||
{ 6 }, | ||
{ 6 }, | ||
{ 10, 12 }, | ||
{ 9, 11, 12 }, | ||
{ 10, 12 }, | ||
{ 9, 10, 11 } -- 12th node | ||
}; | ||
|
||
local total_connected_components = component.find_connected_components(graph, nodes); | ||
print(total_connected_components) -- expect: 3 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# Copyright (c) 2024, The Pallene Developers | ||
# Pallene Tracer is licensed under the MIT license. | ||
# Please refer to the LICENSE and AUTHORS files for details | ||
# SPDX-License-Identifier: MIT | ||
|
||
OUTPUT_FILE = fibonacci.so | ||
|
||
CC = cc | ||
CFLAGS = -O2 -std=c99 -pedantic -Wall -Wextra -Wformat-security | ||
LIBFLAGS = -fPIC -shared | ||
|
||
ifneq ($(findstring debug, $(MAKECMDGOALS)), ) | ||
CFLAGS += -DPT_DEBUG | ||
endif | ||
|
||
.PHONY: all debug clean | ||
|
||
all: $(OUTPUT_FILE) | ||
debug: $(OUTPUT_FILE) | ||
|
||
clean: | ||
rm -rf $(OUTPUT_FILE) | ||
|
||
%.so: %.c | ||
$(CC) $(CFLAGS) $(LDFLAGS) $(LIBFLAGS) $< -o $@ | ||
|
||
%.c: ptracer.h | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Where is this ptracer.h coming from? There should be no ptracer.h in the current directory. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
-- Copyright (c) 2024, The Pallene Developers | ||
-- Pallene Tracer is licensed under the MIT license. | ||
-- Please refer to the LICENSE and AUTHORS files for details | ||
-- SPDX-License-Identifier: MIT | ||
|
||
local util = require "spec.util" | ||
|
||
local function assert_example(example, expected_content) | ||
local cdir = util.shell_quote("examples/"..example) | ||
local ok, err, output_content, _ = | ||
util.outputs_of_execute(string.format("cd %s && make --quiet && ../../pt-lua main.lua", cdir)) | ||
assert(ok, err) | ||
assert.are.same(expected_content, output_content) | ||
|
||
-- With Pallene Tracer tracebacks enabled | ||
local ok, err, output_content, _ = | ||
util.outputs_of_execute(string.format([[ | ||
cd %s | ||
make clean --quiet | ||
make debug --quiet | ||
../../pt-lua main.lua ]], cdir)) | ||
assert(ok, err) | ||
assert.are.same(expected_content, output_content) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why are we compiling and asserting twice? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The first one is w/o Tracebacks, the second one is with tracebacks. Testing twice to ensure we are not doing anything terribly wrong in Pallene Tracer. But there is a nit, we need to run the first assertion with normal system Lua. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could those be two separate |
||
end | ||
|
||
it("Fibonacci", function() | ||
assert_example("fibonacci", "102334155\n") | ||
end) | ||
|
||
it("Find Connected Components", function() | ||
assert_example("connected-components", "3\n") | ||
end) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we have a single makefile for all the examples, instead of copy-pasted makefiles for everyone? These makefiles are too complicated to be copy-pasted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we did/could, what was the point of detaching them from the root Makefile? I don't find them complicated, atleast compared to the root Makefile that we have. A moderate Makefile is far better than having no Makefile at all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main point of detaching them from the root is because we want to compile the examples after we do
make install
for the library, because that way it tests that the compilation will also work for the users.I'd be ok copy-pasting trivial makefiles but these makefiles are not trivial. For starters:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That was not the main point actually, you can compile examples after installation from root Makefile as well, it's not a big deal. The main point was, as Pallene Tracer have 2 modes (debug and release controlled by
PT_DEBUG
macro), we have to show users the techniques to use these modes in a Makefile.I can remember you telling me Makefiles need some love? :3
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.