txlyre 2 weeks ago
parent
commit
4a01a56845
4 changed files with 77 additions and 0 deletions
  1. 60 0
      qirt.c
  2. 1 0
      qirt.h
  3. 14 0
      qistd.c
  4. 2 0
      std.qi

+ 60 - 0
qirt.c

@@ -2099,6 +2099,28 @@ qi_value_t *qi_cast(qi_state_t *state, qi_type_t type, qi_value_t *value) {
     }
     }
   }
   }
 
 
+  case QI_REFERENCE: {
+    qi_value_t *meta;
+    if ((meta = qi_call_meta(state, &fail, value, "__ref", 1, value))) {
+      if (meta->type != QI_REFERENCE)
+        qi_throw_format(state, "__ref returned non-reference value (%s)",
+                        _qi_type(state, meta));
+
+      return meta;
+    }
+
+    if (fail)
+      goto leave;
+
+    switch (value->type) {
+    case QI_STRING:
+      return qi_make_ref(state, value->value.string);
+
+    default:
+      break;
+    }
+  } break;
+
   default:
   default:
     break;
     break;
   }
   }
@@ -3969,6 +3991,8 @@ qi_value_t *qi_builtin_chr(qi_state_t *state, qi_size_t pargc,
                     _qi_type(state, a));
                     _qi_type(state, a));
 
 
   unsigned char c = (int)(a->value.number);
   unsigned char c = (int)(a->value.number);
+  if (c == 0)
+    qi_throw_format(state, "illegal character code");
 
 
   return qi_make_char(state, c);
   return qi_make_char(state, c);
 }
 }
@@ -4291,6 +4315,38 @@ qi_value_t *qi_builtin_table(qi_state_t *state, qi_size_t pargc,
   return qi_to_table(state, a);
   return qi_to_table(state, a);
 }
 }
 
 
+qi_value_t *qi_builtin_ref(qi_state_t *state, qi_size_t pargc,
+                             qi_list_t *pargs) {
+  qi_value_t *a = qi_list_data(pargs, 0);
+
+  return qi_to_ref(state, a);
+}
+
+qi_value_t *qi_builtin_deref(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_REFERENCE)
+    qi_throw_format(state,
+                    "expected first argument to be: reference, but got: %s",
+                    _qi_type(state, a));
+
+  return qi_deref(state, a);
+}
+
+qi_value_t *qi_builtin_ref_set(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_REFERENCE)
+    qi_throw_format(state,
+                    "expected first argument to be: reference, but got: %s",
+                    _qi_type(state, a));
+
+  return qi_set_ref(state, false, a, b);
+}
+
 qi_value_t *qi_pseudomethod_func_call(qi_state_t *state, qi_size_t pargc,
 qi_value_t *qi_pseudomethod_func_call(qi_state_t *state, qi_size_t pargc,
                                       qi_list_t *pargs) {
                                       qi_list_t *pargs) {
   return qi_builtin_func_call(state, pargc, pargs);
   return qi_builtin_func_call(state, pargc, pargs);
@@ -4510,6 +4566,10 @@ static void qi_state_setup(qi_state_t *state) {
   qi_add_builtin(state, "list", 1, qi_builtin_list);
   qi_add_builtin(state, "list", 1, qi_builtin_list);
   qi_add_builtin(state, "tuple", 1, qi_builtin_tuple);
   qi_add_builtin(state, "tuple", 1, qi_builtin_tuple);
   qi_add_builtin(state, "table", 1, qi_builtin_table);
   qi_add_builtin(state, "table", 1, qi_builtin_table);
+  qi_add_builtin(state, "ref", 1, qi_builtin_ref);
+
+  qi_add_builtin(state, "deref", 1, qi_builtin_deref);
+  qi_add_builtin(state, "ref_set", 2, qi_builtin_ref_set);
 
 
   qi_add_pseudomethod(state, "file.write", 0, qi_pseudomethod_file_write);
   qi_add_pseudomethod(state, "file.write", 0, qi_pseudomethod_file_write);
   qi_add_pseudomethod(state, "file.read", 0, qi_pseudomethod_file_read);
   qi_add_pseudomethod(state, "file.read", 0, qi_pseudomethod_file_read);

+ 1 - 0
qirt.h

@@ -277,6 +277,7 @@ struct _qi_symbol_t {
 #define qi_to_list(state, x) (qi_cast((state), QI_LIST, (x)))
 #define qi_to_list(state, x) (qi_cast((state), QI_LIST, (x)))
 #define qi_to_tuple(state, x) (qi_cast((state), QI_TUPLE, (x)))
 #define qi_to_tuple(state, x) (qi_cast((state), QI_TUPLE, (x)))
 #define qi_to_table(state, x) (qi_cast((state), QI_TABLE, (x)))
 #define qi_to_table(state, x) (qi_cast((state), QI_TABLE, (x)))
+#define qi_to_ref(state, x) (qi_cast((state), QI_REFERENCE, (x)))
 
 
 #define qi_get_boolean(state, x)                                               \
 #define qi_get_boolean(state, x)                                               \
   ((x)->type == QI_BOOLEAN ? (x)->value.boolean                                \
   ((x)->type == QI_BOOLEAN ? (x)->value.boolean                                \

+ 14 - 0
qistd.c

@@ -3712,6 +3712,18 @@ qi_list_data(list, 0) = qi_make_string(state, "file.tell");
 qi_list_data(list, 1) = qi_get(state, "ftell");
 qi_list_data(list, 1) = qi_get(state, "ftell");
 return list;
 return list;
 }
 }
+inline static qi_list_t *__qistd626(qi_state_t *state) {
+qi_list_t *list = qi_list_make_n(2);
+qi_list_data(list, 0) = qi_make_string(state, "reference.deref");
+qi_list_data(list, 1) = qi_get(state, "deref");
+return list;
+}
+inline static qi_list_t *__qistd627(qi_state_t *state) {
+qi_list_t *list = qi_list_make_n(2);
+qi_list_data(list, 0) = qi_make_string(state, "reference.set");
+qi_list_data(list, 1) = qi_get(state, "ref_set");
+return list;
+}
 static void qi_init_std(qi_state_t *state) {
 static void qi_init_std(qi_state_t *state) {
 qi_set(state, false, "head", qi_make_function(state, "head", 1, __qistd0, NULL));
 qi_set(state, false, "head", qi_make_function(state, "head", 1, __qistd0, NULL));
 qi_set(state, false, "tail", qi_make_function(state, "tail", 1, __qistd2, NULL));
 qi_set(state, false, "tail", qi_make_function(state, "tail", 1, __qistd2, NULL));
@@ -3827,4 +3839,6 @@ qi_decl_const(state, "__slice", qi_get(state, "slice"));
 (void)(qi_call(state, qi_get(state, "set_pseudomethod"), __qistd623(state)));
 (void)(qi_call(state, qi_get(state, "set_pseudomethod"), __qistd623(state)));
 (void)(qi_call(state, qi_get(state, "set_pseudomethod"), __qistd624(state)));
 (void)(qi_call(state, qi_get(state, "set_pseudomethod"), __qistd624(state)));
 (void)(qi_call(state, qi_get(state, "set_pseudomethod"), __qistd625(state)));
 (void)(qi_call(state, qi_get(state, "set_pseudomethod"), __qistd625(state)));
+(void)(qi_call(state, qi_get(state, "set_pseudomethod"), __qistd626(state)));
+(void)(qi_call(state, qi_get(state, "set_pseudomethod"), __qistd627(state)));
 }
 }

+ 2 - 0
std.qi

@@ -523,6 +523,8 @@ set_pseudomethod("file.putc", fputc)
 set_pseudomethod("file.gets", fgets)
 set_pseudomethod("file.gets", fgets)
 set_pseudomethod("file.puts", fputs)
 set_pseudomethod("file.puts", fputs)
 set_pseudomethod("file.tell", ftell)
 set_pseudomethod("file.tell", ftell)
+set_pseudomethod("reference.deref", deref)
+set_pseudomethod("reference.set", ref_set)
 class Error {
 class Error {
   msg = nil
   msg = nil