From 138ecf4723078cf8ef4342fb3995db23003eff01 Mon Sep 17 00:00:00 2001 From: mattn Date: Fri, 1 Mar 2013 13:37:46 +0900 Subject: [PATCH 1/8] Pluggable Struct --- include/mrbconf.h | 4 --- include/mruby/struct.h | 27 ------------------- include/mruby/value.h | 22 +++++++-------- mrbgems/mruby-struct/mrbgem.rake | 4 +++ {src => mrbgems/mruby-struct/src}/struct.c | 18 ++++++++----- .../t => mrbgems/mruby-struct/test}/struct.rb | 0 src/etc.c | 1 - src/gc.c | 3 --- src/init.c | 4 --- src/object.c | 1 - 10 files changed, 25 insertions(+), 59 deletions(-) delete mode 100644 include/mruby/struct.h create mode 100644 mrbgems/mruby-struct/mrbgem.rake rename {src => mrbgems/mruby-struct/src}/struct.c (98%) rename {test/t => mrbgems/mruby-struct/test}/struct.rb (100%) diff --git a/include/mrbconf.h b/include/mrbconf.h index 45e3d6034..c84480af7 100644 --- a/include/mrbconf.h +++ b/include/mrbconf.h @@ -45,7 +45,6 @@ /* -DDISABLE_XXXX to drop following features */ //#define DISABLE_SPRINTF /* Kernel.sprintf method */ -//#define DISABLE_STRUCT /* Struct class */ //#define DISABLE_STDIO /* use of stdio */ /* -DENABLE_XXXX to enable following features */ @@ -84,9 +83,6 @@ typedef short mrb_sym; #ifndef DISABLE_SPRINTF #define ENABLE_SPRINTF #endif -#ifndef DISABLE_STRUCT -#define ENABLE_STRUCT -#endif #ifndef DISABLE_STDIO #define ENABLE_STDIO #endif diff --git a/include/mruby/struct.h b/include/mruby/struct.h deleted file mode 100644 index cfe6df135..000000000 --- a/include/mruby/struct.h +++ /dev/null @@ -1,27 +0,0 @@ -/* -** mruby/struct.h - Struct class -** -** See Copyright Notice in mruby.h -*/ - -#ifndef MRUBY_STRUCT_H -#define MRUBY_STRUCT_H - -#if defined(__cplusplus) -extern "C" { -#endif - -struct RStruct { - struct RBasic basic; - long len; - mrb_value *ptr; -}; -#define RSTRUCT(st) ((struct RStruct*)((st).value.p)) -#define RSTRUCT_LEN(st) ((int)(RSTRUCT(st)->len)) -#define RSTRUCT_PTR(st) (RSTRUCT(st)->ptr) - -#if defined(__cplusplus) -} /* extern "C" { */ -#endif - -#endif /* MRUBY_STRUCT_H */ diff --git a/include/mruby/value.h b/include/mruby/value.h index 17f51db94..1dfa7b975 100644 --- a/include/mruby/value.h +++ b/include/mruby/value.h @@ -29,12 +29,11 @@ enum mrb_vtype { MRB_TT_HASH, /* 16 */ MRB_TT_STRING, /* 17 */ MRB_TT_RANGE, /* 18 */ - MRB_TT_STRUCT, /* 19 */ - MRB_TT_EXCEPTION, /* 20 */ - MRB_TT_FILE, /* 21 */ - MRB_TT_ENV, /* 22 */ - MRB_TT_DATA, /* 23 */ - MRB_TT_MAXDEFINE /* 24 */ + MRB_TT_EXCEPTION, /* 19 */ + MRB_TT_FILE, /* 20 */ + MRB_TT_ENV, /* 21 */ + MRB_TT_DATA, /* 22 */ + MRB_TT_MAXDEFINE /* 23 */ }; typedef struct mrb_value { @@ -89,12 +88,11 @@ enum mrb_vtype { MRB_TT_HASH, /* 17 */ MRB_TT_STRING, /* 18 */ MRB_TT_RANGE, /* 19 */ - MRB_TT_STRUCT, /* 20 */ - MRB_TT_EXCEPTION, /* 21 */ - MRB_TT_FILE, /* 22 */ - MRB_TT_ENV, /* 23 */ - MRB_TT_DATA, /* 24 */ - MRB_TT_MAXDEFINE /* 25 */ + MRB_TT_EXCEPTION, /* 20 */ + MRB_TT_FILE, /* 21 */ + MRB_TT_ENV, /* 22 */ + MRB_TT_DATA, /* 23 */ + MRB_TT_MAXDEFINE /* 24 */ }; #ifdef MRB_ENDIAN_BIG diff --git a/mrbgems/mruby-struct/mrbgem.rake b/mrbgems/mruby-struct/mrbgem.rake new file mode 100644 index 000000000..476e990da --- /dev/null +++ b/mrbgems/mruby-struct/mrbgem.rake @@ -0,0 +1,4 @@ +MRuby::Gem::Specification.new('mruby-struct') do |spec| + spec.license = 'MIT' + spec.authors = 'mruby developers' +end diff --git a/src/struct.c b/mrbgems/mruby-struct/src/struct.c similarity index 98% rename from src/struct.c rename to mrbgems/mruby-struct/src/struct.c index d7b63259e..131702e9c 100644 --- a/src/struct.c +++ b/mrbgems/mruby-struct/src/struct.c @@ -4,18 +4,23 @@ ** See Copyright Notice in mruby.h */ -#include "mruby.h" -#ifdef ENABLE_STRUCT #include -#include "error.h" -#include "mruby/struct.h" -#include "mruby/array.h" #include - +#include "mruby.h" +#include "mruby/array.h" #include "mruby/string.h" #include "mruby/class.h" #include "mruby/variable.h" +struct RStruct { + struct RBasic basic; + long len; + mrb_value *ptr; +}; + +#define RSTRUCT(st) ((struct RStruct*)((st).value.p)) +#define RSTRUCT_LEN(st) ((int)(RSTRUCT(st)->len)) +#define RSTRUCT_PTR(st) (RSTRUCT(st)->ptr) static struct RClass * struct_class(mrb_state *mrb) @@ -778,4 +783,3 @@ mrb_init_struct(mrb_state *mrb) mrb_define_method(mrb, st, "eql?", mrb_struct_eql, ARGS_REQ(1)); /* 15.2.18.4.12(x) */ } -#endif /* ENABLE_STRUCT */ diff --git a/test/t/struct.rb b/mrbgems/mruby-struct/test/struct.rb similarity index 100% rename from test/t/struct.rb rename to mrbgems/mruby-struct/test/struct.rb diff --git a/src/etc.c b/src/etc.c index 6a43ddd31..644465c80 100644 --- a/src/etc.c +++ b/src/etc.c @@ -170,7 +170,6 @@ mrb_obj_id(mrb_value obj) case MRB_TT_ARRAY: case MRB_TT_HASH: case MRB_TT_RANGE: - case MRB_TT_STRUCT: case MRB_TT_EXCEPTION: case MRB_TT_FILE: case MRB_TT_DATA: diff --git a/src/gc.c b/src/gc.c index 5cc794fd9..c48e6949a 100644 --- a/src/gc.c +++ b/src/gc.c @@ -86,9 +86,6 @@ typedef struct { struct RArray array; struct RHash hash; struct RRange range; -#ifdef ENABLE_STRUCT - struct RStruct strct; -#endif struct RData data; struct RProc proc; } as; diff --git a/src/init.c b/src/init.c index fa2d5d305..0d1a24881 100644 --- a/src/init.c +++ b/src/init.c @@ -20,7 +20,6 @@ void mrb_init_array(mrb_state*); void mrb_init_hash(mrb_state*); void mrb_init_numeric(mrb_state*); void mrb_init_range(mrb_state*); -void mrb_init_struct(mrb_state*); void mrb_init_gc(mrb_state*); void mrb_init_print(mrb_state*); void mrb_init_math(mrb_state*); @@ -48,9 +47,6 @@ mrb_init_core(mrb_state *mrb) mrb_init_hash(mrb); DONE; mrb_init_numeric(mrb); DONE; mrb_init_range(mrb); DONE; -#ifdef ENABLE_STRUCT - mrb_init_struct(mrb); DONE; -#endif mrb_init_gc(mrb); DONE; #ifdef ENABLE_STDIO mrb_init_print(mrb); DONE; diff --git a/src/object.c b/src/object.c index e087c35c0..6707fc6e4 100644 --- a/src/object.c +++ b/src/object.c @@ -379,7 +379,6 @@ static const struct types { {MRB_TT_HASH, "Hash"}, {MRB_TT_STRING, "String"}, {MRB_TT_RANGE, "Range"}, - {MRB_TT_STRUCT, "Struct"}, // {MRB_TT_BIGNUM, "Bignum"}, {MRB_TT_FILE, "File"}, {MRB_TT_DATA, "Data"}, /* internal use: wrapped C pointers */ From 4c4cf0a4ce738fde01a047194b52a5389b400e89 Mon Sep 17 00:00:00 2001 From: mattn Date: Fri, 1 Mar 2013 14:42:34 +0900 Subject: [PATCH 2/8] Pluggable Struct --- src/gc.c | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/src/gc.c b/src/gc.c index 58326d396..7d9d80139 100644 --- a/src/gc.c +++ b/src/gc.c @@ -11,7 +11,6 @@ #include "mruby/hash.h" #include "mruby/range.h" #include -#include "mruby/struct.h" #include "mruby/proc.h" #include "mruby/data.h" #include "mruby/variable.h" @@ -86,9 +85,6 @@ typedef struct { struct RArray array; struct RHash hash; struct RRange range; -#ifdef ENABLE_STRUCT - struct RStruct strct; -#endif struct RData data; struct RProc proc; } as; @@ -455,18 +451,6 @@ gc_mark_children(mrb_state *mrb, struct RBasic *obj) } break; -#ifdef ENABLE_STRUCT - case MRB_TT_STRUCT: - { - struct RStruct *s = (struct RStruct*)obj; - long i; - for (i=0; ilen; i++){ - mrb_gc_mark_value(mrb, s->ptr[i]); - } - } - break; -#endif - default: break; } @@ -539,12 +523,6 @@ obj_free(mrb_state *mrb, struct RBasic *obj) mrb_free(mrb, ((struct RRange*)obj)->edges); break; -#ifdef ENABLE_STRUCT - case MRB_TT_STRUCT: - mrb_free(mrb, ((struct RStruct*)obj)->ptr); - break; -#endif - case MRB_TT_DATA: { struct RData *d = (struct RData*)obj; @@ -664,15 +642,6 @@ gc_gray_mark(mrb_state *mrb, struct RBasic *obj) children+=2; break; -#ifdef ENABLE_STRUCT - case MRB_TT_STRUCT: - { - struct RStruct *s = (struct RStruct*)obj; - children += s->len; - } - break; -#endif - default: break; } From 878fe38b4caad6d775072593d9aa3e737926167d Mon Sep 17 00:00:00 2001 From: mattn Date: Fri, 1 Mar 2013 14:56:28 +0900 Subject: [PATCH 3/8] Gemify --- build_config.rb | 3 +++ mrbgems/mruby-struct/src/struct.c | 24 ++++++++++++++---------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/build_config.rb b/build_config.rb index c0a6eacc6..d3feccd71 100644 --- a/build_config.rb +++ b/build_config.rb @@ -17,6 +17,9 @@ MRuby::Build.new do |conf| # Use standard Time class conf.gem 'mrbgems/mruby-time' + # Use standard Struct class + conf.gem 'mrbgems/mruby-struct' + # Generate binaries # conf.bins = %w(mrbc mruby mirb) diff --git a/mrbgems/mruby-struct/src/struct.c b/mrbgems/mruby-struct/src/struct.c index 131702e9c..6dd208ebf 100644 --- a/mrbgems/mruby-struct/src/struct.c +++ b/mrbgems/mruby-struct/src/struct.c @@ -69,7 +69,7 @@ mrb_value mrb_struct_members(mrb_state *mrb, mrb_value s) { mrb_value members = mrb_struct_s_members(mrb, mrb_obj_value(mrb_obj_class(mrb, s))); - if (mrb_type(s) == MRB_TT_STRUCT) { + if (!strcmp(mrb_class_name(mrb, mrb_obj_class(mrb, s)), "Struct")) { if (RSTRUCT_LEN(s) != RARRAY_LEN(members)) { mrb_raisef(mrb, E_TYPE_ERROR, "struct size differs (%ld required %ld given)", RARRAY_LEN(members), RSTRUCT_LEN(s)); @@ -140,7 +140,7 @@ mrb_struct_getmember(mrb_state *mrb, mrb_value obj, mrb_sym id) return ptr[i]; } } - mrb_name_error(mrb, id, "%s is not struct member", mrb_sym2name(mrb, id)); + mrb_raisef(mrb, E_NAME_ERROR, "%s is not struct member", mrb_sym2name(mrb, id)); return mrb_nil_value(); /* not reached */ } @@ -219,7 +219,7 @@ mrb_struct_set(mrb_state *mrb, mrb_value obj, mrb_value val) } } - mrb_name_error(mrb, mid, "`%s' is not a struct member", + mrb_raisef(mrb, E_NAME_ERROR, "`%s' is not a struct member", mrb_sym2name(mrb, mid)); return mrb_nil_value(); /* not reached */ } @@ -264,7 +264,7 @@ make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass * k name = mrb_str_to_str(mrb, name); id = mrb_to_id(mrb, name); if (!mrb_is_const_id(id)) { - mrb_name_error(mrb, id, "identifier %s needs to be constant", mrb_string_value_ptr(mrb, name)); + mrb_raisef(mrb, E_NAME_ERROR, "identifier %s needs to be constant", mrb_string_value_ptr(mrb, name)); } if (mrb_const_defined_at(mrb, klass, id)) { mrb_warn("redefining constant Struct::%s", mrb_string_value_ptr(mrb, name)); @@ -272,7 +272,6 @@ make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass * k } c = mrb_define_class_under(mrb, klass, RSTRING_PTR(name), klass); } - MRB_SET_INSTANCE_TT(c, MRB_TT_STRUCT); nstr = mrb_obj_value(c); mrb_iv_set(mrb, nstr, mrb_intern(mrb, "__members__"), members); @@ -552,7 +551,7 @@ mrb_struct_aref_id(mrb_state *mrb, mrb_value s, mrb_sym id) return ptr[i]; } } - mrb_name_error(mrb, id, "no member '%s' in struct", mrb_sym2name(mrb, id)); + mrb_raisef(mrb, E_NAME_ERROR, "no member '%s' in struct", mrb_sym2name(mrb, id)); return mrb_nil_value(); /* not reached */ } @@ -624,7 +623,7 @@ mrb_struct_aset_id(mrb_state *mrb, mrb_value s, mrb_sym id, mrb_value val) return val; } } - mrb_name_error(mrb, id, "no member '%s' in struct", mrb_sym2name(mrb, id)); + mrb_raisef(mrb, E_NAME_ERROR, "no member '%s' in struct", mrb_sym2name(mrb, id)); return val; /* not reach */ } @@ -703,7 +702,7 @@ mrb_struct_equal(mrb_state *mrb, mrb_value s) mrb_get_args(mrb, "o", &s2); if (mrb_obj_equal(mrb, s, s2)) return mrb_true_value(); - if (mrb_type(s2) != MRB_TT_STRUCT) return mrb_false_value(); + if (!strcmp(mrb_class_name(mrb, mrb_obj_class(mrb, s)), "Struct")) return mrb_false_value(); if (mrb_obj_class(mrb, s) != mrb_obj_class(mrb, s2)) return mrb_false_value(); if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) { mrb_bug("inconsistent struct"); /* should never happen */ @@ -734,7 +733,7 @@ mrb_struct_eql(mrb_state *mrb, mrb_value s) mrb_get_args(mrb, "o", &s2); if (mrb_obj_equal(mrb, s, s2)) return mrb_true_value(); - if (mrb_type(s2) != MRB_TT_STRUCT) return mrb_false_value(); + if (strcmp(mrb_class_name(mrb, mrb_obj_class(mrb, s2)), "Struct")) return mrb_false_value(); if (mrb_obj_class(mrb, s) != mrb_obj_class(mrb, s2)) return mrb_false_value(); if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) { mrb_bug("inconsistent struct"); /* should never happen */ @@ -765,7 +764,7 @@ mrb_struct_eql(mrb_state *mrb, mrb_value s) * Symbol (such as :name). */ void -mrb_init_struct(mrb_state *mrb) +mrb_mruby_struct_gem_init(mrb_state* mrb) { struct RClass *st; st = mrb_define_class(mrb, "Struct", mrb->object_class); @@ -783,3 +782,8 @@ mrb_init_struct(mrb_state *mrb) mrb_define_method(mrb, st, "eql?", mrb_struct_eql, ARGS_REQ(1)); /* 15.2.18.4.12(x) */ } + +void +mrb_mruby_struct_gem_final(mrb_state* mrb) +{ +} From 3f1814ce3aba08802e0ff73a41cd542ebe9d3def Mon Sep 17 00:00:00 2001 From: mattn Date: Fri, 1 Mar 2013 15:33:52 +0900 Subject: [PATCH 4/8] Move mrblib for Struct --- {mrblib => mrbgems/mruby-struct/mrblib}/struct.rb | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {mrblib => mrbgems/mruby-struct/mrblib}/struct.rb (100%) diff --git a/mrblib/struct.rb b/mrbgems/mruby-struct/mrblib/struct.rb similarity index 100% rename from mrblib/struct.rb rename to mrbgems/mruby-struct/mrblib/struct.rb From d6876aec0973be15ff8c81c2932eb6513964bc44 Mon Sep 17 00:00:00 2001 From: mattn Date: Fri, 1 Mar 2013 17:05:40 +0900 Subject: [PATCH 5/8] Should be MRB_DATA class. RStruct isn't managed by mruby core. So it should be self-managed class instances. --- mrbgems/mruby-struct/src/struct.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/mrbgems/mruby-struct/src/struct.c b/mrbgems/mruby-struct/src/struct.c index 6dd208ebf..847d637ac 100644 --- a/mrbgems/mruby-struct/src/struct.c +++ b/mrbgems/mruby-struct/src/struct.c @@ -10,17 +10,25 @@ #include "mruby/array.h" #include "mruby/string.h" #include "mruby/class.h" +#include "mruby/data.h" #include "mruby/variable.h" struct RStruct { struct RBasic basic; - long len; - mrb_value *ptr; + mrb_value values; }; -#define RSTRUCT(st) ((struct RStruct*)((st).value.p)) -#define RSTRUCT_LEN(st) ((int)(RSTRUCT(st)->len)) -#define RSTRUCT_PTR(st) (RSTRUCT(st)->ptr) +static void +rstruct_free(mrb_state *mrb, void *ptr) +{ + mrb_free(mrb, ptr); +} + +static struct mrb_data_type mrb_struct_type = { "mrb_struct", rstruct_free }; + +#define RSTRUCT(st) ((struct RStruct*)(DATA_PTR(st))) +#define RSTRUCT_LEN(st) ((int)(RARRAY_LEN(RSTRUCT(st)->values))) +#define RSTRUCT_PTR(st) (RARRAY_PTR(RSTRUCT(st)->values)) static struct RClass * struct_class(mrb_state *mrb) @@ -272,6 +280,7 @@ make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass * k } c = mrb_define_class_under(mrb, klass, RSTRING_PTR(name), klass); } + //MRB_SET_INSTANCE_TT(c, MRB_TT_DATA); nstr = mrb_obj_value(c); mrb_iv_set(mrb, nstr, mrb_intern(mrb, "__members__"), members); @@ -429,10 +438,11 @@ mrb_struct_initialize_withArg(mrb_state *mrb, int argc, mrb_value *argv, mrb_val if (n < argc) { mrb_raise(mrb, E_ARGUMENT_ERROR, "struct size differs"); } - st = RSTRUCT(self); - st->ptr = (mrb_value *)mrb_calloc(mrb, sizeof(mrb_value), n); - st->len = n; - struct_copy(st->ptr, argv, argc); + st = (struct RStruct *) mrb_malloc(mrb, sizeof(struct RStruct)); + DATA_PTR(self) = st; + DATA_TYPE(self) = &mrb_struct_type; + st->values = mrb_ary_new_from_values(mrb, argc, argv); + mrb_iv_set(mrb, self, mrb_intern(mrb, "__values__"), mrb_nil_value()); return self; } From 8ebf9c38e40c39a7ff1a04b49c744371d1872597 Mon Sep 17 00:00:00 2001 From: mattn Date: Fri, 1 Mar 2013 17:37:53 +0900 Subject: [PATCH 6/8] Fixed GC guard --- mrbgems/mruby-struct/src/struct.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mrbgems/mruby-struct/src/struct.c b/mrbgems/mruby-struct/src/struct.c index 847d637ac..3ee76a17e 100644 --- a/mrbgems/mruby-struct/src/struct.c +++ b/mrbgems/mruby-struct/src/struct.c @@ -442,7 +442,7 @@ mrb_struct_initialize_withArg(mrb_state *mrb, int argc, mrb_value *argv, mrb_val DATA_PTR(self) = st; DATA_TYPE(self) = &mrb_struct_type; st->values = mrb_ary_new_from_values(mrb, argc, argv); - mrb_iv_set(mrb, self, mrb_intern(mrb, "__values__"), mrb_nil_value()); + mrb_iv_set(mrb, self, mrb_intern(mrb, "__values__"), st->values); return self; } From cb2de0907a08f985c740f711c274c175217fccb9 Mon Sep 17 00:00:00 2001 From: mattn Date: Fri, 1 Mar 2013 17:42:35 +0900 Subject: [PATCH 7/8] Fix copy values --- mrbgems/mruby-struct/src/struct.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mrbgems/mruby-struct/src/struct.c b/mrbgems/mruby-struct/src/struct.c index 3ee76a17e..c306bc7d9 100644 --- a/mrbgems/mruby-struct/src/struct.c +++ b/mrbgems/mruby-struct/src/struct.c @@ -441,7 +441,8 @@ mrb_struct_initialize_withArg(mrb_state *mrb, int argc, mrb_value *argv, mrb_val st = (struct RStruct *) mrb_malloc(mrb, sizeof(struct RStruct)); DATA_PTR(self) = st; DATA_TYPE(self) = &mrb_struct_type; - st->values = mrb_ary_new_from_values(mrb, argc, argv); + st->values = mrb_ary_new_capa(mrb, n); + struct_copy(RARRAY_PTR(st->values), argv, argc); mrb_iv_set(mrb, self, mrb_intern(mrb, "__values__"), st->values); return self; From 99a6de063cc4c4964074b27ad21553043b468368 Mon Sep 17 00:00:00 2001 From: mattn Date: Fri, 1 Mar 2013 17:45:49 +0900 Subject: [PATCH 8/8] Set nil to uninitialized members --- mrbgems/mruby-struct/src/struct.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mrbgems/mruby-struct/src/struct.c b/mrbgems/mruby-struct/src/struct.c index c306bc7d9..5b7d0ab5d 100644 --- a/mrbgems/mruby-struct/src/struct.c +++ b/mrbgems/mruby-struct/src/struct.c @@ -431,7 +431,7 @@ static mrb_value mrb_struct_initialize_withArg(mrb_state *mrb, int argc, mrb_value *argv, mrb_value self) { struct RClass *klass = mrb_obj_class(mrb, self); - int n; + int i, n; struct RStruct *st; n = num_members(mrb, klass); @@ -442,6 +442,9 @@ mrb_struct_initialize_withArg(mrb_state *mrb, int argc, mrb_value *argv, mrb_val DATA_PTR(self) = st; DATA_TYPE(self) = &mrb_struct_type; st->values = mrb_ary_new_capa(mrb, n); + for (i = argc; i < n; i++) { + mrb_ary_set(mrb, st->values, i, mrb_nil_value()); + } struct_copy(RARRAY_PTR(st->values), argv, argc); mrb_iv_set(mrb, self, mrb_intern(mrb, "__values__"), st->values);