rtype-native 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +2 -2
- data/LICENSE +8 -8
- data/README.md +567 -567
- data/Rakefile +11 -11
- data/benchmark/benchmark.rb +191 -191
- data/ext/rtype/c/extconf.rb +2 -2
- data/ext/rtype/c/rtype.c +148 -148
- data/ext/rtype/c/rtype.h +4 -4
- data/spec/rtype_spec.rb +822 -822
- data/spec/spec_helper.rb +4 -4
- metadata +6 -5
data/ext/rtype/c/rtype.c
CHANGED
@@ -1,149 +1,149 @@
|
|
1
|
-
#include "rtype.h"
|
2
|
-
|
3
|
-
VALUE rb_mRtype, rb_mRtypeBehavior, rb_cRtypeBehaviorBase, rb_eRtypeArgumentTypeError, rb_eRtypeTypeSignatureError, rb_eRtypeReturnTypeError;
|
4
|
-
static ID id_to_s, id_keys, id_eqeq, id_include, id_valid, id_call;
|
5
|
-
|
6
|
-
VALUE
|
7
|
-
rb_rtype_valid(VALUE self, VALUE expected, VALUE value) {
|
8
|
-
switch(TYPE(expected)) {
|
9
|
-
case T_MODULE:
|
10
|
-
case T_CLASS:
|
11
|
-
return rb_obj_is_kind_of(value, expected) ? Qtrue : Qfalse;
|
12
|
-
case T_SYMBOL:
|
13
|
-
return rb_respond_to(value, rb_to_id(expected)) ? Qtrue : Qfalse;
|
14
|
-
case T_REGEXP:
|
15
|
-
return rb_reg_match( expected, rb_funcall(value, id_to_s, 0) ) != Qnil ? Qtrue : Qfalse;
|
16
|
-
case T_HASH:
|
17
|
-
if( !RB_TYPE_P(value, T_HASH) ) {
|
18
|
-
return Qfalse;
|
19
|
-
}
|
20
|
-
VALUE e_keys = rb_funcall(expected, id_keys, 0);
|
21
|
-
VALUE v_keys = rb_funcall(value, id_keys, 0);
|
22
|
-
if( !RTEST(rb_funcall(e_keys, id_eqeq, 1, v_keys)) ) {
|
23
|
-
return Qfalse;
|
24
|
-
}
|
25
|
-
|
26
|
-
long i;
|
27
|
-
for(i = 0; i < RARRAY_LEN(e_keys); i++) {
|
28
|
-
VALUE e_k = rb_ary_entry(e_keys, i);
|
29
|
-
VALUE e_v = rb_hash_aref(expected, e_k);
|
30
|
-
if(rb_rtype_valid(self, e_v, rb_hash_aref(value, e_k)) == Qfalse) {
|
31
|
-
return Qfalse;
|
32
|
-
}
|
33
|
-
}
|
34
|
-
return Qtrue;
|
35
|
-
case T_ARRAY:
|
36
|
-
if( !RB_TYPE_P(value, T_ARRAY) ) {
|
37
|
-
return Qfalse;
|
38
|
-
}
|
39
|
-
else if( RARRAY_LEN(expected) != RARRAY_LEN(value) ) {
|
40
|
-
return Qfalse;
|
41
|
-
}
|
42
|
-
else {
|
43
|
-
// 'for' loop initial declarations are only allowed in c99 mode
|
44
|
-
long i;
|
45
|
-
for(i = 0; i < RARRAY_LEN(expected); i++) {
|
46
|
-
VALUE e = rb_ary_entry(expected, i);
|
47
|
-
VALUE v = rb_ary_entry(value, i);
|
48
|
-
VALUE valid = rb_rtype_valid(self, e, v);
|
49
|
-
if(valid == Qfalse) {
|
50
|
-
return Qfalse;
|
51
|
-
}
|
52
|
-
}
|
53
|
-
return Qtrue;
|
54
|
-
}
|
55
|
-
case T_TRUE:
|
56
|
-
return RTEST(value) ? Qtrue : Qfalse;
|
57
|
-
case T_FALSE:
|
58
|
-
return !RTEST(value) ? Qtrue : Qfalse;
|
59
|
-
default:
|
60
|
-
if(rb_obj_is_kind_of(expected, rb_cRange)) {
|
61
|
-
return rb_funcall(expected, id_include, 1, value);
|
62
|
-
}
|
63
|
-
else if(rb_obj_is_kind_of(expected, rb_cProc)) {
|
64
|
-
return RTEST(rb_funcall(expected, id_call, 1, value)) ? Qtrue : Qfalse;
|
65
|
-
}
|
66
|
-
else if( RTEST(rb_obj_is_kind_of(expected, rb_cRtypeBehaviorBase)) ) {
|
67
|
-
return rb_funcall(expected, id_valid, 1, value);
|
68
|
-
}
|
69
|
-
else {
|
70
|
-
VALUE str = rb_any_to_s(expected);
|
71
|
-
rb_raise(rb_eRtypeTypeSignatureError, "Invalid type signature: Unknown type behavior %s", StringValueCStr(str));
|
72
|
-
return Qfalse;
|
73
|
-
}
|
74
|
-
}
|
75
|
-
}
|
76
|
-
|
77
|
-
VALUE
|
78
|
-
rb_rtype_assert_arguments_type(VALUE self, VALUE expected_args, VALUE args) {
|
79
|
-
// 'for' loop initial declarations are only allowed in c99 mode
|
80
|
-
long i;
|
81
|
-
for(i = 0; i < RARRAY_LEN(args); i++) {
|
82
|
-
VALUE e = rb_ary_entry(expected_args, i);
|
83
|
-
VALUE v = rb_ary_entry(args, i);
|
84
|
-
if(e != Qnil) {
|
85
|
-
if( !RTEST(rb_rtype_valid(self, e, v)) ) {
|
86
|
-
VALUE msg = rb_funcall(rb_mRtype, rb_intern("arg_type_error_message"), 3, LONG2FIX(i), e, v);
|
87
|
-
rb_raise(rb_eRtypeArgumentTypeError, "%s", StringValueCStr(msg));
|
88
|
-
}
|
89
|
-
}
|
90
|
-
}
|
91
|
-
return Qnil;
|
92
|
-
}
|
93
|
-
|
94
|
-
static int
|
95
|
-
kwargs_do_each(VALUE key, VALUE val, VALUE in) {
|
96
|
-
VALUE expected = rb_hash_aref(in, key);
|
97
|
-
if(expected != Qnil) {
|
98
|
-
if( !RTEST(rb_rtype_valid((VALUE) NULL, expected, val)) ) {
|
99
|
-
VALUE msg = rb_funcall(rb_mRtype, rb_intern("kwarg_type_error_message"), 3, key, expected, val);
|
100
|
-
rb_raise(rb_eRtypeArgumentTypeError, "%s", StringValueCStr(msg));
|
101
|
-
}
|
102
|
-
}
|
103
|
-
return ST_CONTINUE;
|
104
|
-
}
|
105
|
-
|
106
|
-
VALUE
|
107
|
-
rb_rtype_assert_arguments_type_with_keywords(VALUE self, VALUE expected_args, VALUE args, VALUE expected_kwargs, VALUE kwargs) {
|
108
|
-
rb_rtype_assert_arguments_type(self, expected_args, args);
|
109
|
-
rb_hash_foreach(kwargs, kwargs_do_each, expected_kwargs);
|
110
|
-
return Qnil;
|
111
|
-
}
|
112
|
-
|
113
|
-
VALUE
|
114
|
-
rb_rtype_assert_return_type(VALUE self, VALUE expected, VALUE result) {
|
115
|
-
if(expected == Qnil) {
|
116
|
-
if(result != Qnil) {
|
117
|
-
VALUE msg = rb_funcall(rb_mRtype, rb_intern("type_error_message"), 2, expected, result);
|
118
|
-
rb_raise(rb_eRtypeReturnTypeError, "for return:\n%s", StringValueCStr(msg));
|
119
|
-
}
|
120
|
-
}
|
121
|
-
else {
|
122
|
-
if( !RTEST(rb_rtype_valid(self, expected, result)) ) {
|
123
|
-
VALUE msg = rb_funcall(rb_mRtype, rb_intern("type_error_message"), 2, expected, result);
|
124
|
-
rb_raise(rb_eRtypeReturnTypeError, "for return:\n%s", StringValueCStr(msg));
|
125
|
-
}
|
126
|
-
}
|
127
|
-
return Qnil;
|
128
|
-
}
|
129
|
-
|
130
|
-
void Init_rtype_native(void) {
|
131
|
-
rb_mRtype = rb_define_module("Rtype");
|
132
|
-
rb_mRtypeBehavior = rb_define_module_under(rb_mRtype, "Behavior");
|
133
|
-
rb_cRtypeBehaviorBase = rb_define_class_under(rb_mRtypeBehavior, "Base", rb_cObject);
|
134
|
-
rb_eRtypeArgumentTypeError = rb_define_class_under(rb_mRtype, "ArgumentTypeError", rb_eArgError);
|
135
|
-
rb_eRtypeTypeSignatureError = rb_define_class_under(rb_mRtype, "TypeSignatureError", rb_eArgError);
|
136
|
-
rb_eRtypeReturnTypeError = rb_define_class_under(rb_mRtype, "ReturnTypeError", rb_eStandardError);
|
137
|
-
|
138
|
-
id_to_s = rb_intern("to_s");
|
139
|
-
id_keys = rb_intern("keys");
|
140
|
-
id_eqeq = rb_intern("==");
|
141
|
-
id_include = rb_intern("include?");
|
142
|
-
id_valid = rb_intern("valid?");
|
143
|
-
id_call = rb_intern("call");
|
144
|
-
|
145
|
-
rb_define_method(rb_mRtype, "valid?", rb_rtype_valid, 2);
|
146
|
-
rb_define_method(rb_mRtype, "assert_arguments_type", rb_rtype_assert_arguments_type, 2);
|
147
|
-
rb_define_method(rb_mRtype, "assert_arguments_type_with_keywords", rb_rtype_assert_arguments_type_with_keywords, 4);
|
148
|
-
rb_define_method(rb_mRtype, "assert_return_type", rb_rtype_assert_return_type, 2);
|
1
|
+
#include "rtype.h"
|
2
|
+
|
3
|
+
VALUE rb_mRtype, rb_mRtypeBehavior, rb_cRtypeBehaviorBase, rb_eRtypeArgumentTypeError, rb_eRtypeTypeSignatureError, rb_eRtypeReturnTypeError;
|
4
|
+
static ID id_to_s, id_keys, id_eqeq, id_include, id_valid, id_call;
|
5
|
+
|
6
|
+
VALUE
|
7
|
+
rb_rtype_valid(VALUE self, VALUE expected, VALUE value) {
|
8
|
+
switch(TYPE(expected)) {
|
9
|
+
case T_MODULE:
|
10
|
+
case T_CLASS:
|
11
|
+
return rb_obj_is_kind_of(value, expected) ? Qtrue : Qfalse;
|
12
|
+
case T_SYMBOL:
|
13
|
+
return rb_respond_to(value, rb_to_id(expected)) ? Qtrue : Qfalse;
|
14
|
+
case T_REGEXP:
|
15
|
+
return rb_reg_match( expected, rb_funcall(value, id_to_s, 0) ) != Qnil ? Qtrue : Qfalse;
|
16
|
+
case T_HASH:
|
17
|
+
if( !RB_TYPE_P(value, T_HASH) ) {
|
18
|
+
return Qfalse;
|
19
|
+
}
|
20
|
+
VALUE e_keys = rb_funcall(expected, id_keys, 0);
|
21
|
+
VALUE v_keys = rb_funcall(value, id_keys, 0);
|
22
|
+
if( !RTEST(rb_funcall(e_keys, id_eqeq, 1, v_keys)) ) {
|
23
|
+
return Qfalse;
|
24
|
+
}
|
25
|
+
|
26
|
+
long i;
|
27
|
+
for(i = 0; i < RARRAY_LEN(e_keys); i++) {
|
28
|
+
VALUE e_k = rb_ary_entry(e_keys, i);
|
29
|
+
VALUE e_v = rb_hash_aref(expected, e_k);
|
30
|
+
if(rb_rtype_valid(self, e_v, rb_hash_aref(value, e_k)) == Qfalse) {
|
31
|
+
return Qfalse;
|
32
|
+
}
|
33
|
+
}
|
34
|
+
return Qtrue;
|
35
|
+
case T_ARRAY:
|
36
|
+
if( !RB_TYPE_P(value, T_ARRAY) ) {
|
37
|
+
return Qfalse;
|
38
|
+
}
|
39
|
+
else if( RARRAY_LEN(expected) != RARRAY_LEN(value) ) {
|
40
|
+
return Qfalse;
|
41
|
+
}
|
42
|
+
else {
|
43
|
+
// 'for' loop initial declarations are only allowed in c99 mode
|
44
|
+
long i;
|
45
|
+
for(i = 0; i < RARRAY_LEN(expected); i++) {
|
46
|
+
VALUE e = rb_ary_entry(expected, i);
|
47
|
+
VALUE v = rb_ary_entry(value, i);
|
48
|
+
VALUE valid = rb_rtype_valid(self, e, v);
|
49
|
+
if(valid == Qfalse) {
|
50
|
+
return Qfalse;
|
51
|
+
}
|
52
|
+
}
|
53
|
+
return Qtrue;
|
54
|
+
}
|
55
|
+
case T_TRUE:
|
56
|
+
return RTEST(value) ? Qtrue : Qfalse;
|
57
|
+
case T_FALSE:
|
58
|
+
return !RTEST(value) ? Qtrue : Qfalse;
|
59
|
+
default:
|
60
|
+
if(rb_obj_is_kind_of(expected, rb_cRange)) {
|
61
|
+
return rb_funcall(expected, id_include, 1, value);
|
62
|
+
}
|
63
|
+
else if(rb_obj_is_kind_of(expected, rb_cProc)) {
|
64
|
+
return RTEST(rb_funcall(expected, id_call, 1, value)) ? Qtrue : Qfalse;
|
65
|
+
}
|
66
|
+
else if( RTEST(rb_obj_is_kind_of(expected, rb_cRtypeBehaviorBase)) ) {
|
67
|
+
return rb_funcall(expected, id_valid, 1, value);
|
68
|
+
}
|
69
|
+
else {
|
70
|
+
VALUE str = rb_any_to_s(expected);
|
71
|
+
rb_raise(rb_eRtypeTypeSignatureError, "Invalid type signature: Unknown type behavior %s", StringValueCStr(str));
|
72
|
+
return Qfalse;
|
73
|
+
}
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
VALUE
|
78
|
+
rb_rtype_assert_arguments_type(VALUE self, VALUE expected_args, VALUE args) {
|
79
|
+
// 'for' loop initial declarations are only allowed in c99 mode
|
80
|
+
long i;
|
81
|
+
for(i = 0; i < RARRAY_LEN(args); i++) {
|
82
|
+
VALUE e = rb_ary_entry(expected_args, i);
|
83
|
+
VALUE v = rb_ary_entry(args, i);
|
84
|
+
if(e != Qnil) {
|
85
|
+
if( !RTEST(rb_rtype_valid(self, e, v)) ) {
|
86
|
+
VALUE msg = rb_funcall(rb_mRtype, rb_intern("arg_type_error_message"), 3, LONG2FIX(i), e, v);
|
87
|
+
rb_raise(rb_eRtypeArgumentTypeError, "%s", StringValueCStr(msg));
|
88
|
+
}
|
89
|
+
}
|
90
|
+
}
|
91
|
+
return Qnil;
|
92
|
+
}
|
93
|
+
|
94
|
+
static int
|
95
|
+
kwargs_do_each(VALUE key, VALUE val, VALUE in) {
|
96
|
+
VALUE expected = rb_hash_aref(in, key);
|
97
|
+
if(expected != Qnil) {
|
98
|
+
if( !RTEST(rb_rtype_valid((VALUE) NULL, expected, val)) ) {
|
99
|
+
VALUE msg = rb_funcall(rb_mRtype, rb_intern("kwarg_type_error_message"), 3, key, expected, val);
|
100
|
+
rb_raise(rb_eRtypeArgumentTypeError, "%s", StringValueCStr(msg));
|
101
|
+
}
|
102
|
+
}
|
103
|
+
return ST_CONTINUE;
|
104
|
+
}
|
105
|
+
|
106
|
+
VALUE
|
107
|
+
rb_rtype_assert_arguments_type_with_keywords(VALUE self, VALUE expected_args, VALUE args, VALUE expected_kwargs, VALUE kwargs) {
|
108
|
+
rb_rtype_assert_arguments_type(self, expected_args, args);
|
109
|
+
rb_hash_foreach(kwargs, kwargs_do_each, expected_kwargs);
|
110
|
+
return Qnil;
|
111
|
+
}
|
112
|
+
|
113
|
+
VALUE
|
114
|
+
rb_rtype_assert_return_type(VALUE self, VALUE expected, VALUE result) {
|
115
|
+
if(expected == Qnil) {
|
116
|
+
if(result != Qnil) {
|
117
|
+
VALUE msg = rb_funcall(rb_mRtype, rb_intern("type_error_message"), 2, expected, result);
|
118
|
+
rb_raise(rb_eRtypeReturnTypeError, "for return:\n%s", StringValueCStr(msg));
|
119
|
+
}
|
120
|
+
}
|
121
|
+
else {
|
122
|
+
if( !RTEST(rb_rtype_valid(self, expected, result)) ) {
|
123
|
+
VALUE msg = rb_funcall(rb_mRtype, rb_intern("type_error_message"), 2, expected, result);
|
124
|
+
rb_raise(rb_eRtypeReturnTypeError, "for return:\n%s", StringValueCStr(msg));
|
125
|
+
}
|
126
|
+
}
|
127
|
+
return Qnil;
|
128
|
+
}
|
129
|
+
|
130
|
+
void Init_rtype_native(void) {
|
131
|
+
rb_mRtype = rb_define_module("Rtype");
|
132
|
+
rb_mRtypeBehavior = rb_define_module_under(rb_mRtype, "Behavior");
|
133
|
+
rb_cRtypeBehaviorBase = rb_define_class_under(rb_mRtypeBehavior, "Base", rb_cObject);
|
134
|
+
rb_eRtypeArgumentTypeError = rb_define_class_under(rb_mRtype, "ArgumentTypeError", rb_eArgError);
|
135
|
+
rb_eRtypeTypeSignatureError = rb_define_class_under(rb_mRtype, "TypeSignatureError", rb_eArgError);
|
136
|
+
rb_eRtypeReturnTypeError = rb_define_class_under(rb_mRtype, "ReturnTypeError", rb_eStandardError);
|
137
|
+
|
138
|
+
id_to_s = rb_intern("to_s");
|
139
|
+
id_keys = rb_intern("keys");
|
140
|
+
id_eqeq = rb_intern("==");
|
141
|
+
id_include = rb_intern("include?");
|
142
|
+
id_valid = rb_intern("valid?");
|
143
|
+
id_call = rb_intern("call");
|
144
|
+
|
145
|
+
rb_define_method(rb_mRtype, "valid?", rb_rtype_valid, 2);
|
146
|
+
rb_define_method(rb_mRtype, "assert_arguments_type", rb_rtype_assert_arguments_type, 2);
|
147
|
+
rb_define_method(rb_mRtype, "assert_arguments_type_with_keywords", rb_rtype_assert_arguments_type_with_keywords, 4);
|
148
|
+
rb_define_method(rb_mRtype, "assert_return_type", rb_rtype_assert_return_type, 2);
|
149
149
|
}
|
data/ext/rtype/c/rtype.h
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
#ifndef RTYPE_H
|
2
|
-
#define RTYPE_H
|
3
|
-
#include "ruby.h"
|
4
|
-
#include <string.h>
|
1
|
+
#ifndef RTYPE_H
|
2
|
+
#define RTYPE_H
|
3
|
+
#include "ruby.h"
|
4
|
+
#include <string.h>
|
5
5
|
#endif
|