diff --git a/spec/compiler/parser/parser_spec.cr b/spec/compiler/parser/parser_spec.cr index d454d213da23..c746c5b38b18 100644 --- a/spec/compiler/parser/parser_spec.cr +++ b/spec/compiler/parser/parser_spec.cr @@ -348,8 +348,8 @@ module Crystal assert_syntax_error "def foo(x, *); 1; end", "named parameters must follow bare *" it_parses "def foo(x, *, y, &); 1; end", Def.new("foo", args: ["x".arg, "".arg, "y".arg], body: 1.int32, splat_index: 1, block_arg: Arg.new(""), yields: 0) - assert_syntax_error "def foo(var = 1 : Int32); end", "the syntax for a parameter with a default value V and type T is `arg : T = V`" - assert_syntax_error "def foo(var = x : Int); end", "the syntax for a parameter with a default value V and type T is `arg : T = V`" + assert_syntax_error "def foo(var = 1 : Int32); end", "the syntax for a parameter with a default value V and type T is `param : T = V`" + assert_syntax_error "def foo(var = x : Int); end", "the syntax for a parameter with a default value V and type T is `param : T = V`" it_parses "def foo(**args)\n1\nend", Def.new("foo", body: 1.int32, double_splat: "args".arg) it_parses "def foo(x, **args)\n1\nend", Def.new("foo", body: 1.int32, args: ["x".arg], double_splat: "args".arg) @@ -1885,8 +1885,9 @@ module Crystal assert_syntax_error "/foo)/", "invalid regex" assert_syntax_error "def =\nend" assert_syntax_error "def foo; A = 1; end", "dynamic constant assignment. Constants can only be declared at the top level or inside other types." - assert_syntax_error "{1, ->{ |x| x } }", %(unexpected token: "|") - assert_syntax_error "{1, ->do\n|x| x\end }", %(unexpected token: "|") + assert_syntax_error "{1, ->{ |x| x } }", "unexpected token: \"|\", proc literals specify their parameters like this: ->(x : Type) { ... }" + assert_syntax_error "{1, ->do\n|x| x\end }", "unexpected token: \"|\", proc literals specify their parameters like this: ->(x : Type) { ... }" + assert_syntax_error "{1, ->{ |_| x } }", "unexpected token: \"|\", proc literals specify their parameters like this: ->(param : Type) { ... }" assert_syntax_error "1 while 3", "trailing `while` is not supported" assert_syntax_error "1 until 3", "trailing `until` is not supported" diff --git a/src/compiler/crystal/syntax/parser.cr b/src/compiler/crystal/syntax/parser.cr index ead4e2c9ed5d..4b3fe8566f3a 100644 --- a/src/compiler/crystal/syntax/parser.cr +++ b/src/compiler/crystal/syntax/parser.cr @@ -1825,17 +1825,17 @@ module Crystal return parse_fun_pointer unless @token.keyword?(:do) end - args = [] of Arg + params = [] of Arg if @token.type.op_lparen? next_token_skip_space_or_newline while !@token.type.op_rparen? param_location = @token.location - arg = parse_fun_literal_arg.at(param_location) - if args.any? &.name.==(arg.name) - raise "duplicated proc literal parameter name: #{arg.name}", param_location + param = parse_fun_literal_param.at(param_location) + if params.any? &.name.==(param.name) + raise "duplicated proc literal parameter name: #{param.name}", param_location end - args << arg + params << param end next_token_skip_space_or_newline end @@ -1851,7 +1851,7 @@ module Crystal end with_lexical_var_scope do - push_vars args + push_vars params end_location = nil @@ -1871,7 +1871,7 @@ module Crystal unexpected_token end - a_def = Def.new("->", args, body, return_type: return_type).at(location).at_end(end_location) + a_def = Def.new("->", params, body, return_type: return_type).at(location).at_end(end_location) ProcLiteral.new(a_def).at(location).at_end(end_location) end end @@ -1888,7 +1888,7 @@ module Crystal next_token_skip_space_or_newline msg << ", ..." if @token.type.op_comma? else - msg << "arg : Type" + msg << "param : Type" end msg << ") { ... }" end @@ -1897,7 +1897,7 @@ module Crystal end end - def parse_fun_literal_arg + def parse_fun_literal_param name = check_ident next_token_skip_space_or_newline @@ -3045,7 +3045,7 @@ module Crystal next_token_skip_space end - args = [] of Arg + params = [] of Arg found_default_value = false found_splat = false @@ -3059,7 +3059,7 @@ module Crystal when .op_lparen? next_token_skip_space_or_newline while !@token.type.op_rparen? - extras = parse_arg(args, + extras = parse_param(params, extra_assigns: nil, parentheses: true, found_default_value: found_default_value, @@ -3074,10 +3074,10 @@ module Crystal found_splat = true end if extras.double_splat - double_splat = args.pop + double_splat = params.pop found_double_splat = double_splat end - if block_arg = extras.block_arg + if block_param = extras.block_arg check :OP_RPAREN break elsif @token.type.op_comma? @@ -3089,8 +3089,8 @@ module Crystal index += 1 end - if splat_index == args.size - 1 && args.last.name.empty? - raise "named parameters must follow bare *", args.last.location.not_nil! + if splat_index == params.size - 1 && params.last.name.empty? + raise "named parameters must follow bare *", params.last.location.not_nil! end next_token @@ -3118,7 +3118,7 @@ module Crystal body, end_location = parse_macro_body(name_location) end - node = Macro.new name, args, body, block_arg, splat_index, double_splat: double_splat + node = Macro.new name, params, body, block_param, splat_index, double_splat: double_splat node.name_location = name_location node.doc = doc node.end_location = end_location @@ -3487,7 +3487,7 @@ module Crystal next_token_skip_space end - args = [] of Arg + params = [] of Arg extra_assigns = [] of ASTNode if @token.type.op_period? @@ -3537,7 +3537,7 @@ module Crystal when .op_lparen? next_token_skip_space_or_newline while !@token.type.op_rparen? - extras = parse_arg(args, + extras = parse_param(params, extra_assigns: extra_assigns, parentheses: true, found_default_value: found_default_value, @@ -3553,11 +3553,11 @@ module Crystal found_splat = true end if extras.double_splat - double_splat = args.pop + double_splat = params.pop found_double_splat = double_splat end - if block_arg = extras.block_arg - compute_block_arg_yields block_arg + if block_param = extras.block_arg + compute_block_arg_yields block_param check :OP_RPAREN found_block = true break @@ -3571,15 +3571,15 @@ module Crystal end if name.ends_with?('=') - if name != "[]=" && (args.size > 1 || found_splat || found_double_splat) + if name != "[]=" && (params.size > 1 || found_splat || found_double_splat) raise "setter method '#{name}' cannot have more than one parameter" elsif found_block raise "setter method '#{name}' cannot have a block" end end - if splat_index == args.size - 1 && args.last.name.empty? - raise "named parameters must follow bare *", args.last.location.not_nil! + if splat_index == params.size - 1 && params.last.name.empty? + raise "named parameters must follow bare *", params.last.location.not_nil! end next_token_skip_space @@ -3650,7 +3650,7 @@ module Crystal @def_nest -= 1 @doc_enabled = !!@wants_doc - node = Def.new name, args, body, receiver, block_arg, return_type, @is_macro_def, @yields, is_abstract, splat_index, double_splat: double_splat, free_vars: free_vars + node = Def.new name, params, body, receiver, block_param, return_type, @is_macro_def, @yields, is_abstract, splat_index, double_splat: double_splat, free_vars: free_vars node.name_location = name_location set_visibility node node.end_location = end_location @@ -3703,10 +3703,10 @@ module Crystal splat : Bool, double_splat : Bool - def parse_arg(args, extra_assigns, parentheses, found_default_value, found_splat, found_double_splat, allow_restrictions) + def parse_param(params, extra_assigns, parentheses, found_default_value, found_splat, found_double_splat, allow_restrictions) annotations = nil - # Parse annotations first since they would be before any actual arg tokens. + # Parse annotations first since they would be before any actual param tokens. # Do this in a loop to account for multiple annotations. while @token.type.op_at_lsquare? (annotations ||= Array(Annotation).new) << parse_annotation @@ -3715,20 +3715,20 @@ module Crystal if @token.type.op_amp? next_token_skip_space_or_newline - block_arg = parse_block_arg(extra_assigns, annotations) + block_param = parse_block_param(extra_assigns, annotations) skip_space_or_newline - # When block_arg.name is empty, this is an anonymous parameter. + # When block_param.name is empty, this is an anonymous parameter. # An anonymous parameter should not conflict other parameters names. - # (In fact `args` may contain anonymous splat parameter. See #9108). + # (In fact `params` may contain anonymous splat parameter. See #9108). # So check is skipped. - unless block_arg.name.empty? - conflict_arg = args.any?(&.name.==(block_arg.name)) - conflict_double_splat = found_double_splat && found_double_splat.name == block_arg.name - if conflict_arg || conflict_double_splat - raise "duplicated def parameter name: #{block_arg.name}", block_arg.location.not_nil! + unless block_param.name.empty? + conflict_param = params.any?(&.name.==(block_param.name)) + conflict_double_splat = found_double_splat && found_double_splat.name == block_param.name + if conflict_param || conflict_double_splat + raise "duplicated def parameter name: #{block_param.name}", block_param.location.not_nil! end end - return ArgExtras.new(block_arg, false, false, false) + return ArgExtras.new(block_param, false, false, false) end if found_double_splat @@ -3737,7 +3737,7 @@ module Crystal splat = false double_splat = false - arg_location = @token.location + param_location = @token.location allow_external_name = true case @token.type @@ -3760,20 +3760,20 @@ module Crystal found_space = false if splat && (@token.type.op_comma? || @token.type.op_rparen?) - arg_name = "" - uses_arg = false + param_name = "" + uses_param = false allow_restrictions = false else - arg_location = @token.location - arg_name, external_name, found_space, uses_arg = parse_arg_name(arg_location, extra_assigns, allow_external_name: allow_external_name) + param_location = @token.location + param_name, external_name, found_space, uses_param = parse_param_name(param_location, extra_assigns, allow_external_name: allow_external_name) - args.each do |arg| - if arg.name == arg_name - raise "duplicated def parameter name: #{arg_name}", arg_location + params.each do |param| + if param.name == param_name + raise "duplicated def parameter name: #{param_name}", param_location end - if arg.external_name == external_name - raise "duplicated def parameter external name: #{external_name}", arg_location + if param.external_name == external_name + raise "duplicated def parameter external name: #{external_name}", param_location end end @@ -3830,37 +3830,37 @@ module Crystal skip_space else if found_default_value && !found_splat && !splat && !double_splat - raise "parameter must have a default value", arg_location + raise "parameter must have a default value", param_location end end unless found_colon if @token.type.symbol? - raise "the syntax for a parameter with a default value V and type T is `arg : T = V`", @token + raise "the syntax for a parameter with a default value V and type T is `param : T = V`", @token end if allow_restrictions && @token.type.op_colon? - raise "the syntax for a parameter with a default value V and type T is `arg : T = V`", @token + raise "the syntax for a parameter with a default value V and type T is `param : T = V`", @token end end - raise "BUG: arg_name is nil" unless arg_name + raise "BUG: param_name is nil" unless param_name - arg = Arg.new(arg_name, default_value, restriction, external_name: external_name, parsed_annotations: annotations).at(arg_location) - args << arg - push_var arg + param = Arg.new(param_name, default_value, restriction, external_name: external_name, parsed_annotations: annotations).at(param_location) + params << param + push_var param ArgExtras.new(nil, !!default_value, splat, !!double_splat) end - def parse_block_arg(extra_assigns, annotations) + def parse_block_param(extra_assigns, annotations) name_location = @token.location if @token.type.op_rparen? || @token.type.newline? || @token.type.op_colon? - arg_name = "" + param_name = "" else - arg_name, external_name, found_space, uses_arg = parse_arg_name(name_location, extra_assigns, allow_external_name: false) - @uses_block_arg = true if uses_arg + param_name, external_name, found_space, uses_param = parse_param_name(name_location, extra_assigns, allow_external_name: false) + @uses_block_arg = true if uses_param end inputs = nil @@ -3874,16 +3874,16 @@ module Crystal type_spec = parse_bare_proc_type end - block_arg = Arg.new(arg_name, restriction: type_spec, parsed_annotations: annotations).at(name_location) + block_param = Arg.new(param_name, restriction: type_spec, parsed_annotations: annotations).at(name_location) - push_var block_arg + push_var block_param - @block_arg_name = block_arg.name + @block_arg_name = block_param.name - block_arg + block_param end - def parse_arg_name(location, extra_assigns, allow_external_name) + def parse_param_name(location, extra_assigns, allow_external_name) do_next_token = true found_string_literal = false invalid_internal_name = nil @@ -3916,17 +3916,17 @@ module Crystal raise "cannot use '#{@token}' as a parameter name", @token end - arg_name = @token.value.to_s - if arg_name == external_name + param_name = @token.value.to_s + if param_name == external_name raise "when specified, external name must be different than internal name", @token end - uses_arg = false + uses_param = false do_next_token = true when .instance_var? # Transform `def foo(@x); end` to `def foo(x); @x = x; end` - arg_name = @token.value.to_s[1..-1] - if arg_name == external_name + param_name = @token.value.to_s[1..-1] + if param_name == external_name raise "when specified, external name must be different than internal name", @token end @@ -3940,40 +3940,40 @@ module Crystal # def method(select __arg0) # @select = __arg0 # end - if !external_name && invalid_internal_name?(arg_name) - arg_name, external_name = temp_arg_name, arg_name + if !external_name && invalid_internal_name?(param_name) + param_name, external_name = temp_arg_name, param_name end ivar = InstanceVar.new(@token.value.to_s).at(location) - var = Var.new(arg_name).at(location) + var = Var.new(param_name).at(location) assign = Assign.new(ivar, var).at(location) if extra_assigns extra_assigns.push assign else raise "can't use @instance_variable here" end - uses_arg = true + uses_param = true do_next_token = true when .class_var? - arg_name = @token.value.to_s[2..-1] - if arg_name == external_name + param_name = @token.value.to_s[2..-1] + if param_name == external_name raise "when specified, external name must be different than internal name", @token end # Same case as :INSTANCE_VAR for things like @select - if !external_name && invalid_internal_name?(arg_name) - arg_name, external_name = temp_arg_name, arg_name + if !external_name && invalid_internal_name?(param_name) + param_name, external_name = temp_arg_name, param_name end cvar = ClassVar.new(@token.value.to_s).at(location) - var = Var.new(arg_name).at(location) + var = Var.new(param_name).at(location) assign = Assign.new(cvar, var).at(location) if extra_assigns extra_assigns.push assign else raise "can't use @@class_var here" end - uses_arg = true + uses_param = true do_next_token = true else if external_name @@ -3983,7 +3983,7 @@ module Crystal if invalid_internal_name raise "cannot use '#{invalid_internal_name}' as a parameter name", invalid_internal_name end - arg_name = external_name + param_name = external_name else unexpected_token end @@ -3996,7 +3996,7 @@ module Crystal skip_space - {arg_name, external_name, found_space, uses_arg} + {param_name, external_name, found_space, uses_param} end def invalid_internal_name?(keyword) @@ -4324,11 +4324,11 @@ module Crystal def parse_block2 location = @token.location - block_args = [] of Var + block_params = [] of Var all_names = [] of String extra_assigns = nil block_body = nil - arg_index = 0 + param_index = 0 splat_index = nil slash_is_regex! @@ -4340,7 +4340,7 @@ module Crystal if splat_index raise "splat block parameter already specified", @token end - splat_index = arg_index + splat_index = param_index next_token end @@ -4350,16 +4350,16 @@ module Crystal raise "cannot use '#{@token}' as a block parameter name", @token end - arg_name = @token.value.to_s + param_name = @token.value.to_s - if all_names.includes?(arg_name) - raise "duplicated block parameter name: #{arg_name}", @token + if all_names.includes?(param_name) + raise "duplicated block parameter name: #{param_name}", @token end - all_names << arg_name + all_names << param_name when .underscore? - arg_name = "_" + param_name = "_" when .op_lparen? - block_arg_name = temp_arg_name + block_param_name = temp_arg_name next_token_skip_space_or_newline @@ -4371,26 +4371,26 @@ module Crystal raise "cannot use '#{@token}' as a block parameter name", @token end - sub_arg_name = @token.value.to_s + sub_param_name = @token.value.to_s - if all_names.includes?(sub_arg_name) - raise "duplicated block parameter name: #{sub_arg_name}", @token + if all_names.includes?(sub_param_name) + raise "duplicated block parameter name: #{sub_param_name}", @token end - all_names << sub_arg_name + all_names << sub_param_name when .underscore? - sub_arg_name = "_" + sub_param_name = "_" else raise "expecting block parameter name, not #{@token.type}", @token end - push_var_name sub_arg_name + push_var_name sub_param_name location = @token.location - unless sub_arg_name == "_" + unless sub_param_name == "_" extra_assigns ||= [] of ASTNode extra_assigns << Assign.new( - Var.new(sub_arg_name).at(location), - Call.new(Var.new(block_arg_name).at(location), "[]", NumberLiteral.new(i)).at(location) + Var.new(sub_param_name).at(location), + Call.new(Var.new(block_param_name).at(location), "[]", NumberLiteral.new(i)).at(location) ).at(location) end @@ -4408,13 +4408,13 @@ module Crystal i += 1 end - arg_name = block_arg_name + param_name = block_param_name else raise "expecting block parameter name, not #{@token.type}", @token end - var = Var.new(arg_name).at(@token.location) - block_args << var + var = Var.new(param_name).at(@token.location) + block_params << var next_token_skip_space_or_newline @@ -4428,7 +4428,7 @@ module Crystal raise "expecting ',' or '|', not #{@token}", @token end - arg_index += 1 + param_index += 1 end next_token_skip_statement_end else @@ -4436,7 +4436,7 @@ module Crystal end with_lexical_var_scope do - push_vars block_args + push_vars block_params block_body = parse_expressions @@ -4452,7 +4452,7 @@ module Crystal end block_body, end_location = yield block_body - Block.new(block_args, block_body, splat_index).at(location).at_end(end_location) + Block.new(block_params, block_body, splat_index).at(location).at_end(end_location) end end @@ -5612,7 +5612,7 @@ module Crystal real_name = name end - args = [] of Arg + params = [] of Arg varargs = false if @token.type.op_lparen? @@ -5626,30 +5626,30 @@ module Crystal end if @token.type.ident? - arg_name = @token.value.to_s - arg_location = @token.location + param_name = @token.value.to_s + param_location = @token.location next_token_skip_space_or_newline check :OP_COLON next_token_skip_space_or_newline - arg_type = parse_bare_proc_type + param_type = parse_bare_proc_type skip_space_or_newline - args.each do |arg| - if arg.name == arg_name - raise "duplicated fun parameter name: #{arg_name}", arg_location + params.each do |param| + if param.name == param_name + raise "duplicated fun parameter name: #{param_name}", param_location end end - args << Arg.new(arg_name, nil, arg_type).at(arg_location) + params << Arg.new(param_name, nil, param_type).at(param_location) - push_var_name arg_name if require_body + push_var_name param_name if require_body else if top_level raise "top-level fun parameter must have a name", @token end - arg_type = parse_union_type - args << Arg.new("", nil, arg_type).at(arg_type.location) + param_type = parse_union_type + params << Arg.new("", nil, param_type).at(param_type.location) end if @token.type.op_comma? @@ -5688,7 +5688,7 @@ module Crystal end_location = token_end_location end - fun_def = FunDef.new name, args, return_type, varargs, body, real_name + fun_def = FunDef.new name, params, return_type, varargs, body, real_name fun_def.doc = doc fun_def.at(location).at_end(end_location) end