|
@@ -2089,7 +2089,7 @@ qi_value_t *qi_index_set(qi_state_t *state, bool is_pf, qi_value_t *value,
|
|
|
}
|
|
|
|
|
|
leave:
|
|
|
- qi_throw_format(state, "cannot index-set %s with %s", _qi_type(state, value),
|
|
|
+ qi_throw_format(state, "cannot index %s with %s", _qi_type(state, value),
|
|
|
_qi_type(state, index));
|
|
|
|
|
|
return NULL;
|
|
@@ -3097,6 +3097,70 @@ qi_value_t *qi_builtin_delete_method(qi_state_t *state, qi_size_t pargc,
|
|
|
return state->nil;
|
|
|
}
|
|
|
|
|
|
+qi_value_t *qi_builtin_set_pseudomethod(qi_state_t *state, qi_size_t pargc,
|
|
|
+ qi_list_t *pargs) {
|
|
|
+ qi_value_t *a = qi_list_data(pargs, 0);
|
|
|
+ qi_value_t *b = qi_list_data(pargs, 1);
|
|
|
+
|
|
|
+ if (a->type != QI_STRING)
|
|
|
+ qi_throw_format(state, "expected first argument to be: string, but got: %s",
|
|
|
+ _qi_type(state, a));
|
|
|
+
|
|
|
+ if (b->type != QI_FUNCTION)
|
|
|
+ qi_throw_format(state, "expected second argument to be: function, but got: %s",
|
|
|
+ _qi_type(state, b));
|
|
|
+
|
|
|
+ char *name = a->value.string;
|
|
|
+
|
|
|
+ qi_value_t *method = qi_make_function(state, name, b->value.function.pargc, b->value.function.handle, NULL);
|
|
|
+ method->value.function.is_pm = true;
|
|
|
+
|
|
|
+ qi_lock_acquire(state->pseudomethods_lock);
|
|
|
+
|
|
|
+ qi_table_set(state->pseudomethods, name, method);
|
|
|
+
|
|
|
+ qi_lock_release(state->pseudomethods_lock);
|
|
|
+
|
|
|
+ return method;
|
|
|
+}
|
|
|
+
|
|
|
+qi_value_t *qi_builtin_has_pseudomethod(qi_state_t *state, qi_size_t pargc,
|
|
|
+ qi_list_t *pargs) {
|
|
|
+ qi_value_t *a = qi_list_data(pargs, 0);
|
|
|
+
|
|
|
+ if (a->type != QI_STRING)
|
|
|
+ qi_throw_format(state, "expected first argument to be: string, but got: %s",
|
|
|
+ _qi_type(state, a));
|
|
|
+
|
|
|
+ qi_lock_acquire(state->pseudomethods_lock);
|
|
|
+
|
|
|
+ bool res = qi_table_has(state->pseudomethods, a->value.string);
|
|
|
+
|
|
|
+ qi_lock_release(state->pseudomethods_lock);
|
|
|
+
|
|
|
+ return res? state->_true: state->_false;
|
|
|
+}
|
|
|
+
|
|
|
+qi_value_t *qi_builtin_unset_pseudomethod(qi_state_t *state, qi_size_t pargc,
|
|
|
+ qi_list_t *pargs) {
|
|
|
+ qi_value_t *a = qi_list_data(pargs, 0);
|
|
|
+
|
|
|
+ if (a->type != QI_STRING)
|
|
|
+ qi_throw_format(state, "expected first argument to be: string, but got: %s",
|
|
|
+ _qi_type(state, a));
|
|
|
+
|
|
|
+ qi_lock_acquire(state->pseudomethods_lock);
|
|
|
+
|
|
|
+ bool res = qi_table_delete(state->pseudomethods, a->value.string);
|
|
|
+
|
|
|
+ qi_lock_release(state->pseudomethods_lock);
|
|
|
+
|
|
|
+ if (!res)
|
|
|
+ qi_throw_format(state, "no such pseudomethod: '%s'", a->value.string);
|
|
|
+
|
|
|
+ return state->nil;
|
|
|
+}
|
|
|
+
|
|
|
qi_value_t *qi_builtin_set_global(qi_state_t *state, qi_size_t pargc,
|
|
|
qi_list_t *pargs) {
|
|
|
qi_value_t *a = qi_list_data(pargs, 0);
|
|
@@ -3954,6 +4018,10 @@ static void qi_state_setup(qi_state_t *state) {
|
|
|
qi_add_builtin(state, "has_method", 2, qi_builtin_has_method);
|
|
|
qi_add_builtin(state, "delete_method", 2, qi_builtin_delete_method);
|
|
|
|
|
|
+ qi_add_builtin(state, "set_pseudomethod", 2, qi_builtin_set_pseudomethod);
|
|
|
+ qi_add_builtin(state, "has_pseudomethod", 1, qi_builtin_has_pseudomethod);
|
|
|
+ qi_add_builtin(state, "unset_pseudomethod", 1, qi_builtin_unset_pseudomethod);
|
|
|
+
|
|
|
qi_add_builtin(state, "set_global", 2, qi_builtin_set_global);
|
|
|
qi_add_builtin(state, "get_global", 1, qi_builtin_get_global);
|
|
|
qi_add_builtin(state, "get_globals", 0, qi_builtin_get_globals);
|