rtype-legacy-native 0.0.2
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 +7 -0
- data/Gemfile +3 -0
- data/LICENSE +9 -0
- data/README.md +449 -0
- data/Rakefile +12 -0
- data/benchmark/benchmark.rb +104 -0
- data/ext/rtype/legacy/c/extconf.rb +3 -0
- data/ext/rtype/legacy/c/rtype_legacy.c +144 -0
- data/ext/rtype/legacy/c/rtype_legacy.h +6 -0
- data/spec/rtype_legacy_spec.rb +825 -0
- data/spec/spec_helper.rb +13 -0
- metadata +114 -0
@@ -0,0 +1,144 @@
|
|
1
|
+
#include "rtype_legacy.h"
|
2
|
+
|
3
|
+
VALUE rb_mRtype, rb_mRtypeLegacy, 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, id_key;
|
5
|
+
|
6
|
+
VALUE
|
7
|
+
rb_rtype_valid(VALUE self, VALUE expected, VALUE value) {
|
8
|
+
long i;
|
9
|
+
VALUE e_keys;
|
10
|
+
VALUE v_keys;
|
11
|
+
|
12
|
+
switch(TYPE(expected)) {
|
13
|
+
case T_MODULE:
|
14
|
+
case T_CLASS:
|
15
|
+
return rb_obj_is_kind_of(value, expected) ? Qtrue : Qfalse;
|
16
|
+
case T_SYMBOL:
|
17
|
+
return rb_respond_to(value, rb_to_id(expected)) ? Qtrue : Qfalse;
|
18
|
+
case T_REGEXP:
|
19
|
+
return rb_reg_match( expected, rb_funcall(value, id_to_s, 0) ) != Qnil ? Qtrue : Qfalse;
|
20
|
+
case T_HASH:
|
21
|
+
if( !RB_TYPE_P(value, T_HASH) ) {
|
22
|
+
return Qfalse;
|
23
|
+
}
|
24
|
+
e_keys = rb_funcall(expected, id_keys, 0);
|
25
|
+
v_keys = rb_funcall(value, id_keys, 0);
|
26
|
+
if( !RTEST(rb_funcall(e_keys, id_eqeq, 1, v_keys)) ) {
|
27
|
+
return Qfalse;
|
28
|
+
}
|
29
|
+
|
30
|
+
for(i = 0; i < RARRAY_LEN(e_keys); i++) {
|
31
|
+
VALUE e_k = rb_ary_entry(e_keys, i);
|
32
|
+
VALUE e_v = rb_hash_aref(expected, e_k);
|
33
|
+
if(rb_rtype_valid(self, e_v, rb_hash_aref(value, e_k)) == Qfalse) {
|
34
|
+
return Qfalse;
|
35
|
+
}
|
36
|
+
}
|
37
|
+
return Qtrue;
|
38
|
+
case T_ARRAY:
|
39
|
+
for(i = 0; i < RARRAY_LEN(expected); i++) {
|
40
|
+
VALUE e = rb_ary_entry(expected, i);
|
41
|
+
VALUE valid = rb_rtype_valid(self, e, value);
|
42
|
+
if(valid == Qtrue) {
|
43
|
+
return Qtrue;
|
44
|
+
}
|
45
|
+
}
|
46
|
+
return Qfalse;
|
47
|
+
case T_TRUE:
|
48
|
+
return RTEST(value) ? Qtrue : Qfalse;
|
49
|
+
case T_FALSE:
|
50
|
+
return !RTEST(value) ? Qtrue : Qfalse;
|
51
|
+
case T_NIL:
|
52
|
+
return value == Qnil;
|
53
|
+
default:
|
54
|
+
if(rb_obj_is_kind_of(expected, rb_cRange)) {
|
55
|
+
return rb_funcall(expected, id_include, 1, value);
|
56
|
+
}
|
57
|
+
else if(rb_obj_is_kind_of(expected, rb_cProc)) {
|
58
|
+
return RTEST(rb_funcall(expected, id_call, 1, value)) ? Qtrue : Qfalse;
|
59
|
+
}
|
60
|
+
else if( RTEST(rb_obj_is_kind_of(expected, rb_cRtypeBehaviorBase)) ) {
|
61
|
+
return rb_funcall(expected, id_valid, 1, value);
|
62
|
+
}
|
63
|
+
else {
|
64
|
+
VALUE str = rb_any_to_s(expected);
|
65
|
+
rb_raise(rb_eRtypeTypeSignatureError, "Invalid type signature: Unknown type behavior %s", StringValueCStr(str));
|
66
|
+
return Qfalse;
|
67
|
+
}
|
68
|
+
}
|
69
|
+
}
|
70
|
+
|
71
|
+
VALUE
|
72
|
+
rb_rtype_assert_arguments_type(VALUE self, VALUE expected_args, VALUE args) {
|
73
|
+
// 'for' loop initial declarations are only allowed in c99 mode
|
74
|
+
long i;
|
75
|
+
long e_len = RARRAY_LEN(expected_args);
|
76
|
+
for(i = 0; i < RARRAY_LEN(args); i++) {
|
77
|
+
VALUE e, v;
|
78
|
+
if(i >= e_len) {
|
79
|
+
break;
|
80
|
+
}
|
81
|
+
e = rb_ary_entry(expected_args, i);
|
82
|
+
v = rb_ary_entry(args, i);
|
83
|
+
if( !RTEST(rb_rtype_valid(self, e, v)) ) {
|
84
|
+
VALUE msg = rb_funcall(rb_mRtype, rb_intern("arg_type_error_message"), 3, LONG2FIX(i), e, v);
|
85
|
+
rb_raise(rb_eRtypeArgumentTypeError, "%s", StringValueCStr(msg));
|
86
|
+
}
|
87
|
+
}
|
88
|
+
return Qnil;
|
89
|
+
}
|
90
|
+
|
91
|
+
/*
|
92
|
+
static int
|
93
|
+
kwargs_do_each(VALUE key, VALUE val, VALUE in) {
|
94
|
+
if( RTEST(rb_funcall(in, id_key, 1, key)) ) {
|
95
|
+
VALUE expected = rb_hash_aref(in, key);
|
96
|
+
if( !RTEST(rb_rtype_valid((VALUE) NULL, expected, val)) ) {
|
97
|
+
VALUE msg = rb_funcall(rb_mRtype, rb_intern("kwarg_type_error_message"), 3, key, expected, val);
|
98
|
+
rb_raise(rb_eRtypeArgumentTypeError, "%s", StringValueCStr(msg));
|
99
|
+
}
|
100
|
+
}
|
101
|
+
return ST_CONTINUE;
|
102
|
+
}
|
103
|
+
|
104
|
+
VALUE
|
105
|
+
rb_rtype_assert_arguments_type_with_keywords(VALUE self, VALUE expected_args, VALUE args, VALUE expected_kwargs, VALUE kwargs) {
|
106
|
+
rb_rtype_assert_arguments_type(self, expected_args, args);
|
107
|
+
rb_hash_foreach(kwargs, kwargs_do_each, expected_kwargs);
|
108
|
+
return Qnil;
|
109
|
+
}
|
110
|
+
*/
|
111
|
+
|
112
|
+
VALUE
|
113
|
+
rb_rtype_assert_return_type(VALUE self, VALUE expected, VALUE result) {
|
114
|
+
if( !RTEST(rb_rtype_valid(self, expected, result)) ) {
|
115
|
+
VALUE msg = rb_funcall(rb_mRtype, rb_intern("type_error_message"), 2, expected, result);
|
116
|
+
rb_raise(rb_eRtypeReturnTypeError, "for return:\n%s", StringValueCStr(msg));
|
117
|
+
}
|
118
|
+
return Qnil;
|
119
|
+
}
|
120
|
+
|
121
|
+
void Init_rtype_legacy_native(void) {
|
122
|
+
rb_mRtype = rb_define_module("Rtype");
|
123
|
+
rb_mRtypeLegacy = rb_define_module_under(rb_mRtype, "Legacy");
|
124
|
+
rb_mRtypeBehavior = rb_define_module_under(rb_mRtype, "Behavior");
|
125
|
+
rb_cRtypeBehaviorBase = rb_define_class_under(rb_mRtypeBehavior, "Base", rb_cObject);
|
126
|
+
rb_eRtypeArgumentTypeError = rb_define_class_under(rb_mRtype, "ArgumentTypeError", rb_eArgError);
|
127
|
+
rb_eRtypeTypeSignatureError = rb_define_class_under(rb_mRtype, "TypeSignatureError", rb_eArgError);
|
128
|
+
rb_eRtypeReturnTypeError = rb_define_class_under(rb_mRtype, "ReturnTypeError", rb_eStandardError);
|
129
|
+
|
130
|
+
rb_define_const(rb_mRtypeLegacy, "NATIVE_EXT_VERSION", rb_str_new2(RTYPE_NATIVE_EXT_VERSION));
|
131
|
+
|
132
|
+
id_to_s = rb_intern("to_s");
|
133
|
+
id_keys = rb_intern("keys");
|
134
|
+
id_eqeq = rb_intern("==");
|
135
|
+
id_include = rb_intern("include?");
|
136
|
+
id_valid = rb_intern("valid?");
|
137
|
+
id_call = rb_intern("call");
|
138
|
+
id_key = rb_intern("key?");
|
139
|
+
|
140
|
+
rb_define_method(rb_mRtype, "valid?", rb_rtype_valid, 2);
|
141
|
+
rb_define_method(rb_mRtype, "assert_arguments_type", rb_rtype_assert_arguments_type, 2);
|
142
|
+
// rb_define_method(rb_mRtype, "assert_arguments_type_with_keywords", rb_rtype_assert_arguments_type_with_keywords, 4);
|
143
|
+
rb_define_method(rb_mRtype, "assert_return_type", rb_rtype_assert_return_type, 2);
|
144
|
+
}
|