-
Notifications
You must be signed in to change notification settings - Fork 3
Add MethodDefinition#signatures to Ruby API #697
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
b32b692
3203c85
8379cc7
d7681eb
a8f4c85
7d9657a
555cbed
d625d55
a2aedb6
4066306
783402a
d8520b7
3762ce3
b73cb99
f5e6d8e
cc54708
9fb0de4
fe2e52d
9a0fbad
7f41cb3
e9942f7
c5c9d07
4d495ef
fce9732
536102e
4494f5c
aeeebb3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| #include "signature.h" | ||
| #include "location.h" | ||
|
|
||
| VALUE cSignature; | ||
| VALUE cParameter; | ||
| VALUE cPositionalParameter; | ||
| VALUE cOptionalPositionalParameter; | ||
| VALUE cRestPositionalParameter; | ||
| VALUE cPostParameter; | ||
| VALUE cKeywordParameter; | ||
| VALUE cOptionalKeywordParameter; | ||
| VALUE cRestKeywordParameter; | ||
| VALUE cForwardParameter; | ||
| VALUE cBlockParameter; | ||
|
|
||
| static VALUE parameter_class_for_kind(ParameterKind kind) { | ||
| switch (kind) { | ||
| case ParameterKind_RequiredPositional: return cPositionalParameter; | ||
| case ParameterKind_OptionalPositional: return cOptionalPositionalParameter; | ||
| case ParameterKind_RestPositional: return cRestPositionalParameter; | ||
| case ParameterKind_Post: return cPostParameter; | ||
| case ParameterKind_RequiredKeyword: return cKeywordParameter; | ||
| case ParameterKind_OptionalKeyword: return cOptionalKeywordParameter; | ||
| case ParameterKind_RestKeyword: return cRestKeywordParameter; | ||
| case ParameterKind_Forward: return cForwardParameter; | ||
| case ParameterKind_Block: return cBlockParameter; | ||
| default: rb_raise(rb_eRuntimeError, "Unknown ParameterKind: %d", kind); | ||
| } | ||
| } | ||
|
|
||
| VALUE rdxi_signatures_to_ruby(SignatureArray *arr) { | ||
| VALUE signatures = rb_ary_new_capa((long)arr->len); | ||
|
|
||
| for (size_t i = 0; i < arr->len; i++) { | ||
| SignatureEntry sig_entry = arr->items[i]; | ||
|
|
||
| VALUE parameters = rb_ary_new_capa((long)sig_entry.parameters_len); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For a follow-up PR, potential performance optimization: Parameter-less functions are pretty common. We might see some nice memory gains if we reuse the same empty array between them all. |
||
| for (size_t j = 0; j < sig_entry.parameters_len; j++) { | ||
| ParameterEntry param_entry = sig_entry.parameters[j]; | ||
|
|
||
| VALUE param_class = parameter_class_for_kind(param_entry.kind); | ||
| VALUE name_sym = rb_str_intern(rb_utf8_str_new_cstr(param_entry.name)); | ||
| VALUE location = rdxi_build_location_value(param_entry.location); | ||
| VALUE param_argv[] = {name_sym, location}; | ||
| VALUE param = rb_class_new_instance(2, param_argv, param_class); | ||
|
|
||
| rb_ary_push(parameters, param); | ||
| } | ||
|
|
||
| VALUE signature = rb_class_new_instance(1, ¶meters, cSignature); | ||
|
|
||
| rb_ary_push(signatures, signature); | ||
| } | ||
|
|
||
| rdx_definition_signatures_free(arr); | ||
| return signatures; | ||
| } | ||
|
|
||
| void rdxi_initialize_signature(VALUE mRubydex) { | ||
| cSignature = rb_define_class_under(mRubydex, "Signature", rb_cObject); | ||
|
|
||
| cParameter = rb_define_class_under(cSignature, "Parameter", rb_cObject); | ||
| cPositionalParameter = rb_define_class_under(cSignature, "PositionalParameter", cParameter); | ||
| cOptionalPositionalParameter = rb_define_class_under(cSignature, "OptionalPositionalParameter", cParameter); | ||
| cRestPositionalParameter = rb_define_class_under(cSignature, "RestPositionalParameter", cParameter); | ||
| cPostParameter = rb_define_class_under(cSignature, "PostParameter", cParameter); | ||
| cKeywordParameter = rb_define_class_under(cSignature, "KeywordParameter", cParameter); | ||
| cOptionalKeywordParameter = rb_define_class_under(cSignature, "OptionalKeywordParameter", cParameter); | ||
| cRestKeywordParameter = rb_define_class_under(cSignature, "RestKeywordParameter", cParameter); | ||
| cForwardParameter = rb_define_class_under(cSignature, "ForwardParameter", cParameter); | ||
|
soutaro marked this conversation as resolved.
|
||
| cBlockParameter = rb_define_class_under(cSignature, "BlockParameter", cParameter); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| #ifndef RUBYDEX_SIGNATURE_H | ||
| #define RUBYDEX_SIGNATURE_H | ||
|
|
||
| #include "ruby.h" | ||
| #include "rustbindings.h" | ||
|
|
||
| extern VALUE cSignature; | ||
| extern VALUE cParameter; | ||
| extern VALUE cPositionalParameter; | ||
| extern VALUE cOptionalPositionalParameter; | ||
| extern VALUE cRestPositionalParameter; | ||
| extern VALUE cPostParameter; | ||
| extern VALUE cKeywordParameter; | ||
| extern VALUE cOptionalKeywordParameter; | ||
| extern VALUE cRestKeywordParameter; | ||
| extern VALUE cForwardParameter; | ||
| extern VALUE cBlockParameter; | ||
|
|
||
| // Convert a SignatureArray into a Ruby array of Rubydex::Signature objects. | ||
| // The SignatureArray is freed after conversion. | ||
| VALUE rdxi_signatures_to_ruby(SignatureArray *arr); | ||
|
|
||
| void rdxi_initialize_signature(VALUE mRubydex); | ||
|
|
||
| #endif // RUBYDEX_SIGNATURE_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| module Rubydex | ||
| class Signature | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (Not for this PR, but in a follow-up) In my experience, having all the parameters in a single array ends up making callers need to do lots of filtering (e.g. to find just positional args, just keyword args, pull out the block param, etc.). As the need arises, I would encourage adding convenience methods like |
||
| class Parameter | ||
| #: Symbol | ||
| attr_reader :name | ||
|
|
||
| #: Location | ||
| attr_reader :location | ||
|
|
||
| #: (Symbol, Location) -> void | ||
| def initialize(name, location) | ||
| @name = name | ||
| @location = location | ||
| end | ||
| end | ||
|
|
||
| #: Array[Parameter] | ||
| attr_reader :parameters | ||
|
|
||
| #: (Array[Parameter]) -> void | ||
| def initialize(parameters) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No return value? |
||
| @parameters = parameters | ||
| end | ||
| end | ||
| end | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.