From aff6313e59a3a6f6c74998f0ba62f4a8e63eed59 Mon Sep 17 00:00:00 2001 From: asterite Date: Tue, 16 Jan 2018 09:12:02 -0300 Subject: [PATCH] Compiler: add more locations --- spec/compiler/codegen/debug_spec.cr | 22 ++++++++++ src/compiler/crystal/codegen/asm.cr | 4 +- src/compiler/crystal/codegen/call.cr | 2 +- src/compiler/crystal/codegen/codegen.cr | 40 +++++++++++-------- src/compiler/crystal/codegen/exception.cr | 2 +- src/compiler/crystal/codegen/primitives.cr | 2 +- src/compiler/crystal/macros/interpreter.cr | 2 +- src/compiler/crystal/semantic/ast.cr | 1 + src/compiler/crystal/semantic/call.cr | 2 +- .../crystal/semantic/default_arguments.cr | 20 +++++----- .../crystal/semantic/literal_expander.cr | 38 +++++++++--------- src/compiler/crystal/semantic/main_visitor.cr | 12 +++--- src/compiler/crystal/semantic/new.cr | 5 +-- src/compiler/crystal/semantic/normalizer.cr | 4 +- .../crystal/semantic/top_level_visitor.cr | 5 +++ src/compiler/crystal/syntax/parser.cr | 19 ++++++--- src/compiler/crystal/tools/context.cr | 1 + 17 files changed, 112 insertions(+), 69 deletions(-) diff --git a/spec/compiler/codegen/debug_spec.cr b/spec/compiler/codegen/debug_spec.cr index f4e619466a56..b8ba64f5401b 100644 --- a/spec/compiler/codegen/debug_spec.cr +++ b/spec/compiler/codegen/debug_spec.cr @@ -128,4 +128,26 @@ describe "Code gen: debug" do A ), debug: Crystal::Debug::All) end + + it "has debug info in closure inside if (#5593)" do + codegen(%( + require "prelude" + + def foo + if true && true + yield 1 + end + end + + def bar(&block) + block + end + + foo do |i| + bar do + i + end + end + ), debug: Crystal::Debug::All) + end end diff --git a/src/compiler/crystal/codegen/asm.cr b/src/compiler/crystal/codegen/asm.cr index 1229e426ea88..729a6b8a0fc1 100644 --- a/src/compiler/crystal/codegen/asm.cr +++ b/src/compiler/crystal/codegen/asm.cr @@ -19,7 +19,7 @@ class Crystal::CodeGenVisitor constraints << "," unless constraints.empty? inputs.each_with_index do |input, i| - input.exp.accept self + accept input.exp input_types << llvm_type(input.exp.type) input_values << @last constraints << "," if i > 0 @@ -45,7 +45,7 @@ class Crystal::CodeGenVisitor asm_value = call value, input_values if ptrof - ptrof.accept self + accept ptrof store asm_value, @last end diff --git a/src/compiler/crystal/codegen/call.cr b/src/compiler/crystal/codegen/call.cr index 4627b89c9e0d..8277ae58c212 100644 --- a/src/compiler/crystal/codegen/call.cr +++ b/src/compiler/crystal/codegen/call.cr @@ -293,7 +293,7 @@ class Crystal::CodeGenVisitor end def codegen_call_with_block_as_fun_literal(node, fun_literal, self_type, call_args) - fun_literal.accept self + accept fun_literal call_args.push @last target_def = node.target_def diff --git a/src/compiler/crystal/codegen/codegen.cr b/src/compiler/crystal/codegen/codegen.cr index ea51484396e9..25287dad1723 100644 --- a/src/compiler/crystal/codegen/codegen.cr +++ b/src/compiler/crystal/codegen/codegen.cr @@ -62,7 +62,7 @@ module Crystal def codegen(node, single_module = false, debug = Debug::Default) visitor = CodeGenVisitor.new self, node, single_module: single_module, debug: debug - node.accept visitor + visitor.accept node visitor.process_finished_hooks visitor.finish @@ -381,7 +381,7 @@ module Crystal emit_vars_debug_info(vars) if @debug.variables? end - node.node.accept self + accept node.node @last = llvm_nil end @@ -450,7 +450,7 @@ module Crystal type = node.type.as(TupleInstanceType) @last = allocate_tuple(type) do |tuple_type, i| exp = node.elements[i] - exp.accept self + accept exp {exp.type, @last} end end @@ -462,7 +462,7 @@ module Crystal type = node.type.as(NamedTupleInstanceType) struct_type = alloca llvm_type(type) node.entries.each do |entry| - entry.value.accept self + accept entry.value index = type.name_index(entry.key).not_nil! assign aggregate_index(struct_type, index), type.entries[index].type, entry.value.type, @last end @@ -490,7 +490,7 @@ module Crystal const = node_exp.target_const.not_nil! read_const_pointer(const) when ReadInstanceVar - node_exp.obj.accept self + accept node_exp.obj instance_var_ptr (node_exp.obj.type), node_exp.name, @last when Call # lib external var @@ -637,7 +637,9 @@ module Crystal end def visit(node : ClassDef) - node.hook_expansions.try &.each &.accept self + node.hook_expansions.try &.each do |hook| + accept hook + end accept node.body @last = llvm_nil false @@ -651,7 +653,7 @@ module Crystal def visit(node : LibDef) @in_lib = true - node.body.accept self + accept node.body @in_lib = false @last = llvm_nil false @@ -665,7 +667,7 @@ module Crystal def visit(node : EnumDef) node.members.each do |member| if member.is_a?(Assign) - member.accept self + accept member end end @@ -704,14 +706,18 @@ module Crystal end def visit(node : Include) - node.hook_expansions.try &.each &.accept self + node.hook_expansions.try &.each do |hook| + accept hook + end @last = llvm_nil false end def visit(node : Extend) - node.hook_expansions.try &.each &.accept self + node.hook_expansions.try &.each do |hook| + accept hook + end @last = llvm_nil false @@ -719,8 +725,8 @@ module Crystal def visit(node : If) if node.truthy? - node.cond.accept self - node.then.accept self + accept node.cond + accept node.then if @needs_value && (node_type = node.type?) && (then_type = node.then.type?) @last = upcast(@last, node_type, then_type) end @@ -728,8 +734,8 @@ module Crystal end if node.falsey? - node.cond.accept self - node.else.accept self + accept node.cond + accept node.else if @needs_value && (node_type = node.type?) && (else_type = node.else.type?) @last = upcast(@last, node_type, else_type) end @@ -1306,7 +1312,9 @@ module Crystal end def visit(node : Def) - node.hook_expansions.try &.each &.accept self + node.hook_expansions.try &.each do |hook| + accept hook + end @last = llvm_nil false @@ -1826,7 +1834,7 @@ module Crystal context.vars["self"] = LLVMVar.new(type_ptr, real_type) alloca_vars init.meta_vars - init.value.accept self + accept init.value ivar_ptr = instance_var_ptr real_type, init.name, type_ptr assign ivar_ptr, ivar.type, init.value.type, @last diff --git a/src/compiler/crystal/codegen/exception.cr b/src/compiler/crystal/codegen/exception.cr index f2ea4d9a733d..ca1eb6ef3bf6 100644 --- a/src/compiler/crystal/codegen/exception.cr +++ b/src/compiler/crystal/codegen/exception.cr @@ -205,7 +205,7 @@ class Crystal::CodeGenVisitor next unless target_ensure with_context(exception_handler.context) do - target_ensure.accept self + accept target_ensure end end end diff --git a/src/compiler/crystal/codegen/primitives.cr b/src/compiler/crystal/codegen/primitives.cr index 1a19251538ce..ff87cf55230f 100644 --- a/src/compiler/crystal/codegen/primitives.cr +++ b/src/compiler/crystal/codegen/primitives.cr @@ -504,7 +504,7 @@ class Crystal::CodeGenVisitor if (extra = node.extra) existing_value = context.vars["value"]? context.vars["value"] = LLVMVar.new(call_arg, node.type, true) - request_value { extra.accept self } + request_value { accept extra } call_arg = @last context.vars["value"] = existing_value if existing_value end diff --git a/src/compiler/crystal/macros/interpreter.cr b/src/compiler/crystal/macros/interpreter.cr index cbe7964ec763..ae26d9cbc566 100644 --- a/src/compiler/crystal/macros/interpreter.cr +++ b/src/compiler/crystal/macros/interpreter.cr @@ -149,7 +149,7 @@ module Crystal @last.to_s(str) end end - end) + end).at(node) false end diff --git a/src/compiler/crystal/semantic/ast.cr b/src/compiler/crystal/semantic/ast.cr index ede0132fa192..ff06e9670d9a 100644 --- a/src/compiler/crystal/semantic/ast.cr +++ b/src/compiler/crystal/semantic/ast.cr @@ -195,6 +195,7 @@ module Crystal a_def.always_inline = always_inline? a_def.returns_twice = returns_twice? a_def.naked = naked? + a_def.new = new? a_def end diff --git a/src/compiler/crystal/semantic/call.cr b/src/compiler/crystal/semantic/call.cr index 9308b8f6772b..8baa5516b139 100644 --- a/src/compiler/crystal/semantic/call.cr +++ b/src/compiler/crystal/semantic/call.cr @@ -799,7 +799,7 @@ class Crystal::Call wrong_number_of "block arguments", block.args.size, fun_args.size end - a_def = Def.new("->", fun_args, block.body) + a_def = Def.new("->", fun_args, block.body).at(block) a_def.captured_block = true fun_literal = ProcLiteral.new(a_def).at(self) diff --git a/src/compiler/crystal/semantic/default_arguments.cr b/src/compiler/crystal/semantic/default_arguments.cr index 00d7908ab241..a04c1602fb6d 100644 --- a/src/compiler/crystal/semantic/default_arguments.cr +++ b/src/compiler/crystal/semantic/default_arguments.cr @@ -87,14 +87,13 @@ class Crystal::Def new_name = name end - expansion = Def.new(new_name, new_args, nil, receiver.clone, block_arg.clone, return_type.clone, macro_def?, yields) + expansion = Def.new(new_name, new_args, nil, receiver.clone, block_arg.clone, return_type.clone, macro_def?, yields).at(self) expansion.args.each { |arg| arg.default_value = nil } expansion.calls_super = calls_super? expansion.calls_initialize = calls_initialize? expansion.calls_previous_def = calls_previous_def? expansion.uses_block_arg = uses_block_arg? expansion.yields = yields - expansion.location = location expansion.raises = raises? expansion.free_vars = free_vars if owner = self.owner? @@ -122,10 +121,10 @@ class Crystal::Def if default_value.is_a?(MagicConstant) expansion.args.push arg.clone else - new_body << Assign.new(Var.new(arg.name), default_value) + new_body << Assign.new(Var.new(arg.name).at(arg), default_value).at(arg) if restriction = arg.restriction - new_body << TypeRestriction.new(Var.new(arg.name), restriction).at(arg) + new_body << TypeRestriction.new(Var.new(arg.name).at(arg), restriction).at(arg) end end end @@ -135,10 +134,11 @@ class Crystal::Def if splat_names && splat_index tuple_args = [] of ASTNode splat_size.times do |i| - tuple_args << Var.new(splat_names[i]) + tuple_args << Var.new(splat_names[i]).at(self) end - tuple = TupleLiteral.new(tuple_args).at(args[splat_index]) - new_body << Assign.new(Var.new(args[splat_index].name), tuple) + splat_arg = args[splat_index] + tuple = TupleLiteral.new(tuple_args).at(splat_arg) + new_body << Assign.new(Var.new(splat_arg.name).at(splat_arg), tuple).at(splat_arg) end # Double splat argument @@ -151,7 +151,7 @@ class Crystal::Def named_tuple_entries << NamedTupleLiteral::Entry.new(named_arg, Var.new(named_arg)) end named_tuple = NamedTupleLiteral.new(named_tuple_entries).at(double_splat) - new_body << Assign.new(Var.new(double_splat.name), named_tuple) + new_body << Assign.new(Var.new(double_splat.name).at(double_splat), named_tuple).at(double_splat) end new_body.push body @@ -182,8 +182,8 @@ class Crystal::Def new_args.push Var.new(arg.name) expansion.args.push arg.clone else - body << Assign.new(Var.new(arg.name), default_value.clone) - new_args.push Var.new(arg.name) + body << Assign.new(Var.new(arg.name).at(arg), default_value.clone).at(arg) + new_args.push Var.new(arg.name).at(arg) end end end diff --git a/src/compiler/crystal/semantic/literal_expander.cr b/src/compiler/crystal/semantic/literal_expander.cr index f06f49e91a8d..ed5404ec86a9 100644 --- a/src/compiler/crystal/semantic/literal_expander.cr +++ b/src/compiler/crystal/semantic/literal_expander.cr @@ -185,10 +185,10 @@ module Crystal @program.global_vars[global_name] = global_var - first_assign = Assign.new(Var.new(temp_name), Global.new(global_name)) - regex = regex_new_call(node, StringLiteral.new(string)) - second_assign = Assign.new(Global.new(global_name), regex) - If.new(first_assign, Var.new(temp_name), second_assign) + first_assign = Assign.new(Var.new(temp_name).at(node), Global.new(global_name).at(node)).at(node) + regex = regex_new_call(node, StringLiteral.new(string).at(node)) + second_assign = Assign.new(Global.new(global_name).at(node), regex).at(node) + If.new(first_assign, Var.new(temp_name).at(node), second_assign).at(node) else regex_new_call(node, node_value) end @@ -211,16 +211,16 @@ module Crystal left = node.left.single_expression new_node = if left.is_a?(Var) || (left.is_a?(IsA) && left.obj.is_a?(Var)) - If.new(left, node.right, left.clone) + If.new(left, node.right, left.clone).at(node) elsif left.is_a?(Assign) && left.target.is_a?(Var) - If.new(left, node.right, left.target.clone) + If.new(left, node.right, left.target.clone).at(node) elsif left.is_a?(Not) && left.exp.is_a?(Var) - If.new(left, node.right, left.clone) + If.new(left, node.right, left.clone).at(node) elsif left.is_a?(Not) && ((left_exp = left.exp).is_a?(IsA) && left_exp.obj.is_a?(Var)) - If.new(left, node.right, left.clone) + If.new(left, node.right, left.clone).at(node) else temp_var = new_temp_var - If.new(Assign.new(temp_var.clone, left), node.right, temp_var.clone) + If.new(Assign.new(temp_var.clone, left).at(node), node.right, temp_var.clone).at(node) end new_node.and = true new_node.location = node.location @@ -244,16 +244,16 @@ module Crystal left = node.left.single_expression new_node = if left.is_a?(Var) || (left.is_a?(IsA) && left.obj.is_a?(Var)) - If.new(left, left.clone, node.right) + If.new(left, left.clone, node.right).at(node) elsif left.is_a?(Assign) && left.target.is_a?(Var) - If.new(left, left.target.clone, node.right) + If.new(left, left.target.clone, node.right).at(node) elsif left.is_a?(Not) && left.exp.is_a?(Var) - If.new(left, left.clone, node.right) + If.new(left, left.clone, node.right).at(node) elsif left.is_a?(Not) && ((left_exp = left.exp).is_a?(IsA) && left_exp.obj.is_a?(Var)) - If.new(left, left.clone, node.right) + If.new(left, left.clone, node.right).at(node) else temp_var = new_temp_var - If.new(Assign.new(temp_var.clone, left), temp_var.clone, node.right) + If.new(Assign.new(temp_var.clone, left).at(node), temp_var.clone, node.right).at(node) end new_node.or = true new_node.location = node.location @@ -390,7 +390,7 @@ module Crystal assigns << cond else temp_var = new_temp_var - assigns << Assign.new(temp_var.clone, cond) + assigns << Assign.new(temp_var.clone, cond).at(node_cond) end temp_var end @@ -411,7 +411,7 @@ module Crystal sub_comp = case_when_comparison(rh, lh).at(cond) if comp - comp = And.new(comp, sub_comp) + comp = And.new(comp, sub_comp).at(comp) else comp = sub_comp end @@ -427,7 +427,7 @@ module Crystal next unless comp if final_comp - final_comp = Or.new(final_comp, comp) + final_comp = Or.new(final_comp, comp).at(final_comp) else final_comp = comp end @@ -435,7 +435,7 @@ module Crystal final_comp ||= BoolLiteral.new(true) - wh_if = If.new(final_comp, wh.body) + wh_if = If.new(final_comp, wh.body).at(final_comp) if a_if a_if.else = wh_if else @@ -451,7 +451,7 @@ module Crystal final_if = final_if.not_nil! final_exp = if assigns && !assigns.empty? assigns << final_if - Expressions.new(assigns) + Expressions.new(assigns).at(node) else final_if end diff --git a/src/compiler/crystal/semantic/main_visitor.cr b/src/compiler/crystal/semantic/main_visitor.cr index a2dc89f5220d..b3deb7523403 100644 --- a/src/compiler/crystal/semantic/main_visitor.cr +++ b/src/compiler/crystal/semantic/main_visitor.cr @@ -1507,8 +1507,8 @@ module Crystal expected_return_type = proc_type.return_type expected_return_type = @program.nil if expected_return_type.void? - proc_def = Def.new("->", proc_args, block.body) - proc_literal = ProcLiteral.new(proc_def).at(node.location) + proc_def = Def.new("->", proc_args, block.body).at(node) + proc_literal = ProcLiteral.new(proc_def).at(node) proc_literal.expected_return_type = expected_return_type proc_literal.force_nil = true if expected_return_type.nil_type? proc_literal.accept self @@ -1536,11 +1536,11 @@ module Crystal new_call = Call.new(node.obj, "new").at(node.location) - new_assign = Assign.new(Var.new(temp_name), new_call) + new_assign = Assign.new(Var.new(temp_name).at(node), new_call).at(node) exps << new_assign named_args.each do |named_arg| - assign_call = Call.new(Var.new(temp_name), "#{named_arg.name}=", named_arg.value) + assign_call = Call.new(Var.new(temp_name).at(named_arg), "#{named_arg.name}=", named_arg.value).at(named_arg) if loc = named_arg.location assign_call.location = loc assign_call.name_column_number = loc.column_number @@ -1548,9 +1548,9 @@ module Crystal exps << assign_call end - exps << Var.new(temp_name) + exps << Var.new(temp_name).at(node) - expanded = Expressions.new(exps) + expanded = Expressions.new(exps).at(node) expanded.accept self node.bind_to expanded diff --git a/src/compiler/crystal/semantic/new.cr b/src/compiler/crystal/semantic/new.cr index fa83c5f3e834..72f30e1f87d6 100644 --- a/src/compiler/crystal/semantic/new.cr +++ b/src/compiler/crystal/semantic/new.cr @@ -126,13 +126,12 @@ module Crystal def expand_new_signature_from_initialize(instance_type) def_args = args.clone - new_def = Def.new("new", def_args, Nop.new) + new_def = Def.new("new", def_args, Nop.new).at(self) new_def.splat_index = splat_index new_def.double_splat = double_splat.clone new_def.yields = yields new_def.visibility = Visibility::Private if visibility.private? new_def.new = true - new_def.location = location new_def.doc = doc new_def.free_vars = free_vars @@ -275,7 +274,7 @@ module Crystal name = "new" end - expansion = Def.new(name, def_args, Nop.new, splat_index: splat_index) + expansion = Def.new(name, def_args, Nop.new, splat_index: splat_index).at(self) expansion.yields = yields expansion.visibility = Visibility::Private if visibility.private? if uses_block_arg? diff --git a/src/compiler/crystal/semantic/normalizer.cr b/src/compiler/crystal/semantic/normalizer.cr index 357fe7be9004..7f85554b3fb1 100644 --- a/src/compiler/crystal/semantic/normalizer.cr +++ b/src/compiler/crystal/semantic/normalizer.cr @@ -82,11 +82,11 @@ module Crystal right = Call.new(middle.clone, node.name, node.args).at(middle) else temp_var = program.new_temp_var - temp_assign = Assign.new(temp_var.clone, middle) + temp_assign = Assign.new(temp_var.clone, middle).at(middle) left = Call.new(obj.obj, obj.name, temp_assign).at(obj.obj) right = Call.new(temp_var.clone, node.name, node.args).at(node) end - node = And.new(left, right) + node = And.new(left, right).at(left) node = node.transform self else node = super diff --git a/src/compiler/crystal/semantic/top_level_visitor.cr b/src/compiler/crystal/semantic/top_level_visitor.cr index 541db128a265..80ff1b7ba43d 100644 --- a/src/compiler/crystal/semantic/top_level_visitor.cr +++ b/src/compiler/crystal/semantic/top_level_visitor.cr @@ -433,6 +433,11 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor type.struct = true type.extern = true type.extern_union = node.union? + + if location = node.location + type.add_location(location) + end + current_type.types[node.name] = type end diff --git a/src/compiler/crystal/syntax/parser.cr b/src/compiler/crystal/syntax/parser.cr index d272f949da74..c2aa4facd6cc 100644 --- a/src/compiler/crystal/syntax/parser.cr +++ b/src/compiler/crystal/syntax/parser.cr @@ -1632,6 +1632,8 @@ module Crystal end def parse_fun_literal + location = @token.location + next_token_skip_space_or_newline unless @token.type == :"{" || @token.type == :"(" || @token.keyword?(:do) @@ -1677,7 +1679,8 @@ module Crystal pop_def - ProcLiteral.new(Def.new("->", args, body)).at_end(end_location) + a_def = Def.new("->", args, body).at(location).at_end(end_location) + ProcLiteral.new(a_def).at(location).at_end(end_location) end def check_not_pipe_before_proc_literal_body @@ -1782,7 +1785,7 @@ module Crystal def parse_delimiter(want_skip_space = true) if @token.type == :STRING - return node_and_next_token StringLiteral.new(@token.value.to_s) + return node_and_next_token StringLiteral.new(@token.value.to_s).at(@token.location) end location = @token.location @@ -3007,6 +3010,8 @@ module Crystal end def parse_macro_if(start_line, start_column, macro_state, check_end = true) + location = @token.location + next_token_skip_space @in_macro_expression = true @@ -3014,7 +3019,7 @@ module Crystal @in_macro_expression = false if @token.type != :"%}" && check_end - an_if = parse_if_after_condition cond, true + an_if = parse_if_after_condition cond, location, true return MacroExpression.new(an_if, output: false).at_end(token_end_location) end @@ -3590,14 +3595,16 @@ module Crystal end def parse_if(check_end = true) + location = @token.location + slash_is_regex! next_token_skip_space_or_newline cond = parse_op_assign_no_control allow_suffix: false - parse_if_after_condition cond, check_end + parse_if_after_condition cond, location, check_end end - def parse_if_after_condition(cond, check_end) + def parse_if_after_condition(cond, location, check_end) slash_is_regex! skip_statement_end @@ -3621,7 +3628,7 @@ module Crystal next_token_skip_space end - If.new(cond, a_then, a_else).at_end(end_location) + If.new(cond, a_then, a_else).at(location).at_end(end_location) end def parse_unless diff --git a/src/compiler/crystal/tools/context.cr b/src/compiler/crystal/tools/context.cr index 935bcd3129fb..4587ec9b2142 100644 --- a/src/compiler/crystal/tools/context.cr +++ b/src/compiler/crystal/tools/context.cr @@ -124,6 +124,7 @@ module Crystal return unless loc = typed_def.location return unless loc.filename == typed_def.end_location.try &.filename return unless contains_target typed_def + return if typed_def.new? # Skip autogenerated 'new' methods @context = HashStringType.new