Skip to content

Commit 54f5e7a

Browse files
committed
Native methods
1 parent 37ef09a commit 54f5e7a

File tree

4 files changed

+60
-39
lines changed

4 files changed

+60
-39
lines changed

README.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,8 @@ Native functions in C must follow this signature:
219219
tea_val_t your_function_name(tea_fn_args_t* args)
220220
```
221221
222-
The function receives a context and a list of arguments, and must return a `tea_value_t`. Arguments are accessed by
223-
calling `tea_function_args_pop()` in a loop. Here's an example:
222+
The function receives a context and a list of arguments, and must return a `tea_val_t`. Arguments are accessed by
223+
calling `tea_fn_args_pop()` in a loop. Here's an example:
224224
225225
```c
226226
// Native function to print values (similar to built-in print)
@@ -279,9 +279,11 @@ int main() {
279279
tea_interp_init(&context, "example.tea");
280280

281281
// Bind native functions
282-
tea_bind_native_fn(&context, "print", tea_print);
283-
tea_bind_native_fn(&context, "add_numbers", tea_add_numbers);
284-
tea_bind_native_fn(&context, "print_values", tea_print_values);
282+
// Second NULL agument means that the function is global, but you can use your own types here instead
283+
// For example 'Point', 'Foo', 'Bar' and e.t.c
284+
tea_bind_native_fn(&context, NULL, "print", tea_print);
285+
tea_bind_native_fn(&context, NULL, "add_numbers", tea_add_numbers);
286+
tea_bind_native_fn(&context, NULL, "print_values", tea_print_values);
285287

286288
// Execute Tea code...
287289

include/tea_fn.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ typedef tea_val_t (*tea_native_fn_cb_t)(tea_fn_args_t *args);
2121

2222
typedef struct {
2323
tea_list_entry_t link;
24-
const char *name;
24+
const char *owner_name;
25+
const char *fn_name;
2526
tea_native_fn_cb_t cb;
2627
} tea_native_fn_t;
2728

@@ -33,7 +34,8 @@ typedef struct {
3334
tea_var_t *tea_fn_args_pop(tea_fn_args_t *args);
3435

3536
const tea_native_fn_t *tea_ctx_find_native_fn(const tea_list_entry_t *functions,
36-
const char *name);
37+
const char *owner_name,
38+
const char *fn_name);
3739
const tea_fn_t *tea_ctx_find_fn(const tea_list_entry_t *functions,
3840
const char *name);
3941

@@ -45,5 +47,5 @@ tea_val_t tea_eval_native_fn_call(tea_ctx_t *ctx, tea_scope_t *scp,
4547
const tea_native_fn_t *nat_fn,
4648
const tea_node_t *args);
4749

48-
void tea_bind_native_fn(tea_ctx_t *ctx, const char *name,
49-
tea_native_fn_cb_t cb);
50+
void tea_bind_native_fn(tea_ctx_t *ctx, const char *owner_name,
51+
const char *fn_name, tea_native_fn_cb_t cb);

main.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,8 @@ int main(const int argc, char *argv[])
119119
tea_ctx_t context;
120120
tea_interp_init(&context, filename);
121121

122-
tea_bind_native_fn(&context, "print", tea_print);
123-
tea_bind_native_fn(&context, "println", tea_println);
122+
tea_bind_native_fn(&context, NULL, "print", tea_print);
123+
tea_bind_native_fn(&context, NULL, "println", tea_println);
124124

125125
tea_scope_t global_scope;
126126
tea_scope_init(&global_scope, NULL);

src/tea_fn.c

Lines changed: 45 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,21 @@ tea_var_t *tea_fn_args_pop(tea_fn_args_t *args)
2424
}
2525

2626
const tea_native_fn_t *tea_ctx_find_native_fn(const tea_list_entry_t *functions,
27-
const char *name)
27+
const char *owner_name,
28+
const char *fn_name)
2829
{
2930
tea_list_entry_t *entry;
3031
tea_list_for_each(entry, functions)
3132
{
3233
const tea_native_fn_t *function =
3334
tea_list_record(entry, tea_native_fn_t, link);
34-
if (!strcmp(function->name, name)) {
35-
return function;
35+
if (!strcmp(function->fn_name, fn_name)) {
36+
if (!owner_name && !function->owner_name) {
37+
return function;
38+
}
39+
if (!strcmp(function->owner_name, owner_name)) {
40+
return function;
41+
}
3642
}
3743
}
3844

@@ -218,8 +224,8 @@ tea_val_t tea_eval_fn_call(tea_ctx_t *ctx, tea_scope_t *scp,
218224
}
219225
}
220226

221-
const tea_fn_t *function = NULL;
222-
const char *function_name = NULL;
227+
const tea_fn_t *func = NULL;
228+
const char *func_name = NULL;
223229

224230
tea_ret_ctx_t return_context = { 0 };
225231
return_context.is_set = false;
@@ -262,61 +268,71 @@ tea_val_t tea_eval_fn_call(tea_ctx_t *ctx, tea_scope_t *scp,
262268
return tea_val_undef();
263269
}
264270

265-
tea_struct_decl_t *struct_declaration =
271+
tea_struct_decl_t *struct_decl =
266272
tea_find_struct_decl(ctx, variable->val.obj->type);
267-
if (!struct_declaration) {
273+
if (!struct_decl) {
268274
tea_log_err(
269275
"Runtime error: Cannot find type declaration for type '%s' when calling method",
270276
variable->val.obj->type);
271277
tea_scope_cleanup(ctx, &inner_scope);
272278
return tea_val_undef();
273279
}
274280

275-
function_name = field_token->buf;
276-
function = tea_ctx_find_fn(&struct_declaration->funcs, function_name);
281+
unsigned int flags = 0;
277282

278-
if (function) {
279-
// declare 'self' for the scope
280-
tea_decl_var(ctx, &inner_scope, "self", function->mut ? TEA_VAR_MUT : 0,
281-
NULL, object_node);
283+
const tea_native_fn_t *native_func = tea_ctx_find_native_fn(
284+
&ctx->native_funcs, variable->val.obj->type, field_token->buf);
285+
if (native_func) {
286+
// TODO: Pass 'self'
287+
return tea_eval_native_fn_call(ctx, scp, native_func, args);
282288
}
289+
290+
func_name = field_token->buf;
291+
func = tea_ctx_find_fn(&struct_decl->funcs, func_name);
292+
293+
if (func && func->mut) {
294+
flags |= TEA_VAR_MUT;
295+
}
296+
297+
// declare 'self' for the scope
298+
tea_decl_var(ctx, &inner_scope, "self", flags, NULL, object_node);
283299
} else {
284300
const tea_tok_t *token = node->tok;
285301
if (token) {
286-
const tea_native_fn_t *nat_fn =
287-
tea_ctx_find_native_fn(&ctx->native_funcs, token->buf);
288-
if (nat_fn) {
289-
return tea_eval_native_fn_call(ctx, scp, nat_fn, args);
302+
const tea_native_fn_t *native_func =
303+
tea_ctx_find_native_fn(&ctx->native_funcs, NULL, token->buf);
304+
if (native_func) {
305+
return tea_eval_native_fn_call(ctx, scp, native_func, args);
290306
}
291307

292-
function_name = token->buf;
293-
function = tea_ctx_find_fn(&ctx->funcs, token->buf);
308+
func_name = token->buf;
309+
func = tea_ctx_find_fn(&ctx->funcs, token->buf);
294310
}
295311
}
296312

297-
if (!function) {
313+
if (!func) {
298314
if (field_access) {
299315
const tea_tok_t *field_token = field_access->field_acc.field->tok;
300316
tea_log_err(
301317
"Runtime error: Undefined method '%s' called at line %d, column %d",
302-
function_name, field_token->line, field_token->col);
318+
func_name, field_token->line, field_token->col);
303319
} else {
304320
const tea_tok_t *token = node->tok;
305321
if (token) {
306322
tea_log_err(
307323
"Runtime error: Undefined function '%s' called at line %d, column %d",
308-
function_name, token->line, token->col);
324+
func_name, token->line, token->col);
309325
} else {
310326
tea_log_err(
311327
"Runtime error: Undefined function '%s' called (no position information available)",
312-
function_name);
328+
func_name);
313329
}
314330
}
315331

316332
return tea_val_undef();
317333
}
318334

319-
const tea_node_t *function_params = function->params;
335+
const tea_node_t *function_params = func->params;
320336
if (function_params && args) {
321337
tea_list_entry_t *param_name_entry =
322338
tea_list_first(&function_params->children);
@@ -380,7 +396,7 @@ tea_val_t tea_eval_fn_call(tea_ctx_t *ctx, tea_scope_t *scp,
380396
}
381397

382398
const bool result =
383-
tea_exec(ctx, &inner_scope, function->body, &return_context, NULL);
399+
tea_exec(ctx, &inner_scope, func->body, &return_context, NULL);
384400
tea_scope_cleanup(ctx, &inner_scope);
385401

386402
if (result && return_context.is_set) {
@@ -394,12 +410,13 @@ tea_val_t tea_eval_fn_call(tea_ctx_t *ctx, tea_scope_t *scp,
394410
return tea_val_undef();
395411
}
396412

397-
void tea_bind_native_fn(tea_ctx_t *ctx, const char *name,
398-
const tea_native_fn_cb_t cb)
413+
void tea_bind_native_fn(tea_ctx_t *ctx, const char *owner_name,
414+
const char *fn_name, const tea_native_fn_cb_t cb)
399415
{
400416
tea_native_fn_t *function = tea_malloc(sizeof(*function));
401417
if (function) {
402-
function->name = name;
418+
function->owner_name = owner_name;
419+
function->fn_name = fn_name;
403420
function->cb = cb;
404421
tea_list_add_tail(&ctx->native_funcs, &function->link);
405422
}

0 commit comments

Comments
 (0)