txlyre 2 天之前
父节点
当前提交
1882ee2166
共有 1 个文件被更改,包括 69 次插入1 次删除
  1. 69 1
      qirt.c

+ 69 - 1
qirt.c

@@ -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);