Added basic functionality for interpreter platform functions

This commit is contained in:
Fabio Scotto di Santolo
2025-12-08 00:31:13 +01:00
parent 95b5d3b97b
commit 7461069855

View File

@@ -37,14 +37,15 @@ typedef struct tfparser {
/* Function table entry: each of this entry represents a symbol name
* associated with a function implementation.
*/
struct FunctionTableEntry {
struct tfctx;
typedef struct FunctionTableEntry {
tfobj *name;
void (*callback) (tfctx *ctx, tfobj *name);
tfobj *user_list;
};
void (*callback) (struct tfctx *ctx, tfobj *name);
tfobj *user_func;
} tffuncentry;
struct FunctionTable {
struct FunctionTableEntry **func_table;
tffuncentry **func_table;
size_t func_count;
};
@@ -54,6 +55,11 @@ typedef struct tfctx {
struct FunctionTable functable;
} tfctx;
/* ############################# Function Prototypes #################################### */
void retain(tfobj *o);
void release(tfobj *o);
/* ############################# Allocations wrappers ################################### */
void *xmalloc(size_t size)
@@ -89,16 +95,6 @@ tfobj *createObject(int type)
return o;
}
tfobj *createStringObject(char *s, size_t len)
{
tfobj *obj = createObject(TFOBJ_TYPE_STR);
obj->str.ptr = xmalloc(len+1);
obj->str.len = len;
memcpy(obj->str.ptr, s, len);
obj->str.ptr[len] = 0;
return obj;
}
tfobj *createIntObject(int i)
{
tfobj *obj = createObject(TFOBJ_TYPE_INT);
@@ -113,13 +109,6 @@ tfobj *createBoolObject(int b)
return obj;
}
tfobj *createSymbolObject(char *s, size_t len)
{
tfobj *obj = createStringObject(s, len);
obj->type = TFOBJ_TYPE_SYMBOL;
return obj;
}
/* Free an object and all the other nested objects. */
void freeObject(tfobj *obj) {
switch (obj->type) {
@@ -178,7 +167,43 @@ void printObject(tfobj *obj) {
}
}
/* ############################ List Object ############################################ */
/* ############################ String Object ########################################## */
tfobj *createStringObject(char *s, size_t len)
{
tfobj *obj = createObject(TFOBJ_TYPE_STR);
obj->str.ptr = xmalloc(len+1);
obj->str.len = len;
memcpy(obj->str.ptr, s, len);
obj->str.ptr[len] = 0;
return obj;
}
tfobj *createSymbolObject(char *s, size_t len)
{
tfobj *obj = createStringObject(s, len);
obj->type = TFOBJ_TYPE_SYMBOL;
return obj;
}
/* Compare the two string objects 'a' and 'b', returns 0 if they are
* the same, '1' if a > b , '-1' if a < b.
* The comparison is performed using memcmp(). */
int compareStringObject(tfobj *a, tfobj *b)
{
size_t minlen = a->str.len < b->str.len ? a->str.len : b->str.len;
int cmp = memcmp(a->str.ptr, b->str.ptr, minlen);
if (cmp == 0) {
if (a->str.len == b->str.len) return 0;
else if (a->str.len > b->str.len) return 1;
else return -1;
} else {
if (cmp < 0) return -1;
else return 1;
}
}
/* ############################ List Object ############################################ */
tfobj *createListObject(void)
{
@@ -280,25 +305,88 @@ tfobj *compile(char *prg)
return parsed;
}
/* ############################# Basic Standard Library ################################# */
void basicMathFunctions(tfctx *ctx, tfobj *name)
{
// TODO unimplemeted function
/* if (ctxCheckStackMinLen(ctx, 2)) return; */
/* tfobj *b = ctxStackPop(ctx, TFOBJ_TYPE_INT); */
/* tfobj *a = ctxStackPop(ctx, TFOBJ_TYPE_INT); */
/* if (a == NULL || b == NULL) return; */
/* int result = a->i + b->i; */
/* ctxStackPush(ctx, createIntObject(result)); */
}
/* ############################# Execution and context ################################## */
tffuncentry *getFunctionByName(tfctx *ctx, tfobj *name)
{
for (size_t j = 0; j < ctx->functable.func_count; j++) {
tffuncentry *fe = ctx->functable.func_table[j];
if (compareStringObject(fe->name, name) == 0)
return fe;
}
return NULL;
}
/* Push a new function entry in the context. It's up to the caller
* to set either the C callback or the list representing the user
* defined function */
tffuncentry *registerFunction(tfctx *ctx, tfobj *name)
{
ctx->functable.func_table = xrealloc(ctx->functable.func_table,
sizeof(tffuncentry*) * ctx->functable.func_count + 1);
tffuncentry *fe = xmalloc(sizeof(tffuncentry));
ctx->functable.func_table[ctx->functable.func_count] = fe;
ctx->functable.func_count++;
fe->name = name;
retain(name);
fe->callback = NULL;
fe->user_func = NULL;
return fe;
}
/* Register a new function with the given name in the function table
* of the context. The function can't fail since if a function with the
* same name already exist, it gets replaced by the new one. */
void registerCFunction(tfctx *ctx, char *name, void (*callback)(tfctx *ctx, tfobj *name))
{
tffuncentry *fe;
tfobj *oname = createStringObject(name, strlen(name));
fe = getFunctionByName(ctx, oname);
if (fe) {
if (fe->user_func) {
release(fe->user_func);
fe->user_func = NULL;
}
fe->callback = callback;
} else {
fe = registerFunction(ctx, oname);
fe->callback = callback;
}
release(oname);
}
tfctx *createContext(void)
{
tfctx *ctx = xmalloc(sizeof(*ctx));
ctx->stack = createListObject();
ctx->functable.func_table = NULL;
ctx->functable.func_count = 0;
registerFunction(ctx, "+", basicMathFunctions);
registerCFunction(ctx, "+", basicMathFunctions);
return ctx;
}
/* Try to resolve and call the function associated with the symbol
* name 'word'. Return 0 if the symbol was actually bound to some
* function, return 1 otherwise.
* function and was executed, return 1 otherwise (on error).
*/
int callSymbol(tfctx *ctx, tfobj *word)
{
tffuncentry *fe = getFunctionByName(ctx, word);
if (fe == NULL) return 1;
return 0;
}