From: cassowarii Date: Mon, 13 Jul 2026 02:34:09 +0000 (-0700) Subject: bound methods for intrinsic types X-Git-Url: https://git.cassowary.me/gitweb.cgi?a=commitdiff_plain;h=245008fbe0dd67b8f2b1479dd569d79b3d8009bc;p=sarabande.git bound methods for intrinsic types --- diff --git a/src/data/value.h b/src/data/value.h index 804eb13..6aa6a63 100644 --- a/src/data/value.h +++ b/src/data/value.h @@ -3,7 +3,7 @@ #include "global.h" -#define FLAG_SQUIGGLY (1ULL << 62) +#define IT_FLAG_BOUND_METHOD (1ULL << 62) #define HVINT(n) ((hV) { .type = IT_INTEGER, .integer = n }) #define HVFLOAT(f) ((hV) { .type = IT_FLOAT, .float_val = f }) @@ -15,8 +15,8 @@ #define HVNIL ((hV) { .type = IT_NIL }) #define HVNOTHING ((hV) {0}) #define HVFUNC(i, c) ((hV) { .type = i, .closure = c }) -#define HVFUNC2(i, c) ((hV) { .type = i | FLAG_SQUIGGLY, .closure = c }) #define HVBUILTIN(b) ((hV) { .type = IT_BUILTIN, .builtin = b }) +#define HVBOUNDMETHOD(m, t) ((hV) { .type = m | IT_FLAG_BOUND_METHOD, .ref = t }) #define HVMODULE(m) ((hV) { .type = IT_MODULE, .module = m }) struct sbVm; diff --git a/src/lib/lib.c b/src/lib/lib.c index 11dcc28..c0dea9d 100644 --- a/src/lib/lib.c +++ b/src/lib/lib.c @@ -1,7 +1,9 @@ #include "common.h" -#include "data/symbol.h" #include "vm/exec.h" +#include "data/symbol.h" +#include "data/reference.h" + #include "lib/table.h" #include "lib/sentinel.h" #include "lib/method.h" @@ -96,8 +98,6 @@ void sbLib_resolve_method(hVm vm) { * (non-intrinsic types are always functions, so they can be resolved just by * calling them)*/ void sbLib_resolve_property(hVm vm) { - printf("Resolving property\n"); - sbVm_print_stack(vm); hV *target = sbVm_pop(vm); hV *argc = sbVm_pop(vm); if (argc->type != IT_INTEGER) { @@ -132,7 +132,8 @@ void sbLib_resolve_property(hVm vm) { } else { /* it is a method, but it is being called without parameters. * annoyingly, we need to construct a bound version of this method. */ - PANIC("I haven't done this yet!"); + hRef ref = sbRef_create(target); + sbVm_push_immediate(vm, &HVBOUNDMETHOD(method_name_val->symbol, ref)); } } else { PANIC("invalid method name for type %lld: %s", (long long)target->type, sbSymbol_name(method_name_val->symbol)); diff --git a/src/vm/exec.c b/src/vm/exec.c index f4dd780..2d2ee7c 100644 --- a/src/vm/exec.c +++ b/src/vm/exec.c @@ -8,6 +8,7 @@ void call_block(hVm vm, usize block_id, hClosure closure); void call_builtin(hVm vm, hV *to_call); +void call_bound_method(hVm vm, hV *to_call); void return_from_block(hVm vm); void execute_instruction(hVm vm); void push_stack(hVm vm, hV *value); @@ -82,6 +83,12 @@ void sbVm_swap(hVm vm) { void sbVm_call_func(hVm vm, hV *func) { if (func->type == IT_BUILTIN) { call_builtin(vm, func); + } else if (func->type <= 0) { + /* intrinsic type: resolve a property on it */ + push_stack(vm, func); + sbLib_resolve_property(vm); + } else if (func->type & IT_FLAG_BOUND_METHOD) { + call_bound_method(vm, func); } else { call_block(vm, func->type, func->closure); } @@ -164,6 +171,27 @@ void call_block(hVm vm, usize block_id, hClosure closure) { vm->ip = &blk->bytecode[0]; } +void call_bound_method(hVm vm, hV *to_call) { + if (!(to_call->type & IT_FLAG_BOUND_METHOD)) { + CHECK("call_bound_method can only call bound methods!"); + } + + /* bound method is just a symbol + a closure containing one variable */ + hSymbol sym = (hSymbol)(to_call->type & ~IT_FLAG_BOUND_METHOD); + hRef ref = (to_call->ref); + + /* we should already have parameters, so we just need to line it back up + * on the stack and call the method again */ + push_stack_immediate(vm, &HVSYM(sym)); + swap_stack_top(vm); + if (peek_stack(vm, 0)->type != IT_INTEGER) { + CHECK("bound method call should receive an integer arg count!"); + } + peek_stack(vm, 0)->integer ++; + push_stack(vm, sbRef_deref(ref)); + sbLib_resolve_method(vm); +} + void return_from_block(hVm vm) { for (usize i = 0; i < vm->fp->num_locals; i++) { sbV_release(&vm->fp->locals[i]); @@ -483,15 +511,7 @@ void execute_instruction(hVm vm) { break; case BC_CALL: v = pop_stack(vm); - if (v->type == IT_BUILTIN) { - call_builtin(vm, v); - } else if (v->type <= 0) { - /* intrinsic type: resolve a property on it */ - push_stack(vm, v); - sbLib_resolve_property(vm); - } else { - call_block(vm, v->type, v->closure); - } + sbVm_call_func(vm, v); break; case BC_SEND: sbLib_resolve_method(vm);