rtype-native 0.5.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
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