Skip to content

Commit

Permalink
Implement parser
Browse files Browse the repository at this point in the history
  • Loading branch information
soutaro committed Apr 22, 2024
1 parent cb0af1d commit 15c8c03
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 16 deletions.
2 changes: 2 additions & 0 deletions ext/rbs_extension/constants.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ VALUE RBS_Types_ClassInstance;
VALUE RBS_Types_ClassSingleton;
VALUE RBS_Types_Function_Param;
VALUE RBS_Types_Function;
VALUE RBS_Types_UntypedFunction;
VALUE RBS_Types_Interface;
VALUE RBS_Types_Intersection;
VALUE RBS_Types_Literal;
Expand Down Expand Up @@ -138,6 +139,7 @@ void rbs__init_constants(void) {
IMPORT_CONSTANT(RBS_Types_ClassInstance, RBS_Types, "ClassInstance");
IMPORT_CONSTANT(RBS_Types_ClassSingleton, RBS_Types, "ClassSingleton");
IMPORT_CONSTANT(RBS_Types_Function, RBS_Types, "Function");
IMPORT_CONSTANT(RBS_Types_UntypedFunction, RBS_Types, "UntypedFunction");
IMPORT_CONSTANT(RBS_Types_Function_Param, RBS_Types_Function, "Param");
IMPORT_CONSTANT(RBS_Types_Interface, RBS_Types, "Interface");
IMPORT_CONSTANT(RBS_Types_Intersection, RBS_Types, "Intersection");
Expand Down
1 change: 1 addition & 0 deletions ext/rbs_extension/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ extern VALUE RBS_Types_ClassInstance;
extern VALUE RBS_Types_ClassSingleton;
extern VALUE RBS_Types_Function_Param;
extern VALUE RBS_Types_Function;
extern VALUE RBS_Types_UntypedFunction;
extern VALUE RBS_Types_Interface;
extern VALUE RBS_Types_Intersection;
extern VALUE RBS_Types_Literal;
Expand Down
49 changes: 33 additions & 16 deletions ext/rbs_extension/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ typedef struct {
VALUE rest_keywords;
} method_params;

static bool rbs_is_untyped_params(method_params *params) {
return NIL_P(params->required_positionals);
}

// /**
// * Returns RBS::Location object of `current_token` of a parser state.
// *
Expand Down Expand Up @@ -362,6 +366,7 @@ static bool is_keyword(parserstate *state) {

/*
params ::= {} `)`
| {} `?` `)` -- Untyped function params (assign params.required = nil)
| <required_params> `)`
| <required_params> `,` `)`
Expand Down Expand Up @@ -389,6 +394,11 @@ static bool is_keyword(parserstate *state) {
| {} `**` <function_param>
*/
static void parse_params(parserstate *state, method_params *params) {
if (state->next_token.type == pQUESTION && state->next_token2.type == pRPAREN) {
params->required_positionals = Qnil;
parser_advance(state);
return;
}
if (state->next_token.type == pRPAREN) {
return;
}
Expand Down Expand Up @@ -641,8 +651,11 @@ static void parse_function(parserstate *state, VALUE *function, VALUE *block, VA
parser_advance_assert(state, pARROW);
VALUE block_return_type = parse_optional(state);

*block = rbs_block(
rbs_function(
VALUE block_function = Qnil;
if (rbs_is_untyped_params(&block_params)) {
block_function = rbs_untyped_function(block_return_type);
} else {
block_function = rbs_function(
block_params.required_positionals,
block_params.optional_positionals,
block_params.rest_positionals,
Expand All @@ -651,27 +664,31 @@ static void parse_function(parserstate *state, VALUE *function, VALUE *block, VA
block_params.optional_keywords,
block_params.rest_keywords,
block_return_type
),
required,
block_self_type
);
);
}

*block = rbs_block(block_function, required, block_self_type);

parser_advance_assert(state, pRBRACE);
}

parser_advance_assert(state, pARROW);
VALUE type = parse_optional(state);

*function = rbs_function(
params.required_positionals,
params.optional_positionals,
params.rest_positionals,
params.trailing_positionals,
params.required_keywords,
params.optional_keywords,
params.rest_keywords,
type
);
if (rbs_is_untyped_params(&params)) {
*function = rbs_untyped_function(type);
} else {
*function = rbs_function(
params.required_positionals,
params.optional_positionals,
params.rest_positionals,
params.trailing_positionals,
params.required_keywords,
params.optional_keywords,
params.rest_keywords,
type
);
}
}

/*
Expand Down
11 changes: 11 additions & 0 deletions ext/rbs_extension/ruby_objs.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,17 @@ VALUE rbs_function_param(VALUE type, VALUE name, VALUE location) {
);
}

VALUE rbs_untyped_function(VALUE return_type) {
VALUE args = rb_hash_new();
rb_hash_aset(args, ID2SYM(rb_intern("return_type")), return_type);

return CLASS_NEW_INSTANCE(
RBS_Types_UntypedFunction,
1,
&args
);
}

VALUE rbs_function(
VALUE required_positional_params,
VALUE optional_positional_params,
Expand Down
1 change: 1 addition & 0 deletions ext/rbs_extension/ruby_objs.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ VALUE rbs_class_instance(VALUE typename, VALUE type_args, VALUE location);
VALUE rbs_class_singleton(VALUE typename, VALUE location);
VALUE rbs_function_param(VALUE type, VALUE name, VALUE location);
VALUE rbs_function(VALUE required_positional_params, VALUE optional_positional_params, VALUE rest_positional_params, VALUE trailing_positional_params, VALUE required_keywords, VALUE optional_keywords, VALUE rest_keywords, VALUE return_type);
VALUE rbs_untyped_function(VALUE return_type);
VALUE rbs_interface(VALUE typename, VALUE type_args, VALUE location);
VALUE rbs_intersection(VALUE types, VALUE location);
VALUE rbs_literal(VALUE literal, VALUE location);
Expand Down
9 changes: 9 additions & 0 deletions test/rbs/parser_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -751,4 +751,13 @@ def test_parse_require_eof
RBS::Parser.parse_method_type("() -> void () -> void", range: 0..., require_eof: true)
end
end

def test_proc__untyped_function
code = buffer("^(?) { (?) -> void } -> Integer")

type = RBS::Parser.parse_type(code, range: 0...)

assert_instance_of RBS::Types::UntypedFunction, type.type
assert_instance_of RBS::Types::UntypedFunction, type.block.type
end
end

0 comments on commit 15c8c03

Please sign in to comment.