From 6d8a0ad15d801a6ca4e34328ae67c7ed34f2e3ca Mon Sep 17 00:00:00 2001 From: yuyi Date: Tue, 14 Jun 2022 15:50:20 +0800 Subject: [PATCH] ast, checker, cgen: sort consts with call expr (fix #14748) (#14755) --- vlib/v/ast/table.v | 94 ++++++++++++++++++++++- vlib/v/checker/fn.v | 10 +++ vlib/v/gen/c/cgen.v | 44 +---------- vlib/v/tests/const_call_expr_order_test.v | 18 +++++ 4 files changed, 122 insertions(+), 44 deletions(-) create mode 100644 vlib/v/tests/const_call_expr_order_test.v diff --git a/vlib/v/ast/table.v b/vlib/v/ast/table.v index 32c8e6b217..0b2806c671 100644 --- a/vlib/v/ast/table.v +++ b/vlib/v/ast/table.v @@ -117,9 +117,10 @@ pub mut: source_fn voidptr // set in the checker, while processing fn declarations usages int generic_names []string - attrs []Attr // all fn attributes - is_conditional bool // true for `[if abc]fn(){}` - ctdefine_idx int // the index of the attribute, containing the compile time define [if mytag] + dep_names []string // globals or consts dependent names + attrs []Attr // all fn attributes + is_conditional bool // true for `[if abc]fn(){}` + ctdefine_idx int // the index of the attribute, containing the compile time define [if mytag] } fn (f &Fn) method_equals(o &Fn) bool { @@ -2155,3 +2156,90 @@ pub fn (t &Table) is_comptime_type(x Type, y ComptimeType) bool { } } } + +pub fn (t &Table) dependent_names_in_expr(expr Expr) []string { + mut names := []string{} + match expr { + Ident { + if expr.kind in [.global, .constant] { + names << util.no_dots(expr.name) + } + } + ArrayInit { + for elem_expr in expr.exprs { + names << t.dependent_names_in_expr(elem_expr) + } + } + StructInit { + for field in expr.fields { + names << t.dependent_names_in_expr(field.expr) + } + } + InfixExpr { + names << t.dependent_names_in_expr(expr.left) + names << t.dependent_names_in_expr(expr.right) + } + PostfixExpr { + names << t.dependent_names_in_expr(expr.expr) + } + PrefixExpr { + names << t.dependent_names_in_expr(expr.right) + } + CallExpr { + for arg in expr.args { + names << t.dependent_names_in_expr(arg.expr) + } + if func := t.find_fn(expr.name) { + names << func.dep_names + } + } + IfExpr { + for branch in expr.branches { + names << t.dependent_names_in_expr(branch.cond) + for stmt in branch.stmts { + names << t.dependent_names_in_stmt(stmt) + } + } + } + MatchExpr { + names << t.dependent_names_in_expr(expr.cond) + for branch in expr.branches { + for stmt in branch.stmts { + names << t.dependent_names_in_stmt(stmt) + } + } + } + else {} + } + return names +} + +pub fn (t &Table) dependent_names_in_stmt(stmt Stmt) []string { + mut names := []string{} + match stmt { + AssignStmt { + for expr in stmt.left { + names << t.dependent_names_in_expr(expr) + } + for expr in stmt.right { + names << t.dependent_names_in_expr(expr) + } + } + ExprStmt { + names << t.dependent_names_in_expr(stmt.expr) + } + ForInStmt { + names << t.dependent_names_in_expr(stmt.cond) + for stmt_ in stmt.stmts { + names << t.dependent_names_in_stmt(stmt_) + } + } + Return { + for expr in stmt.exprs { + names << t.dependent_names_in_expr(expr) + } + } + else {} + } + return names +} diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index 788d39eee9..d26b760f87 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -334,6 +334,16 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) { } } node.source_file = c.file + + if c.table.known_fn(node.name) { + mut dep_names := []string{} + for stmt in node.stmts { + dep_names << c.table.dependent_names_in_stmt(stmt) + } + if dep_names.len > 0 { + c.table.fns[node.name].dep_names = dep_names + } + } } // check_same_type_ignoring_pointers util function to check if the Types are the same, including all diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index e4d04b7ed0..bca1f8e279 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -4359,44 +4359,6 @@ fn (mut g Gen) return_stmt(node ast.Return) { } } -fn (mut g Gen) dependent_var_names(expr ast.Expr) []string { - mut vars := []string{} - match expr { - ast.Ident { - if expr.kind in [.global, .constant] { - vars << util.no_dots(expr.name) - } - } - ast.ArrayInit { - for elem_expr in expr.exprs { - vars << g.dependent_var_names(elem_expr) - } - } - ast.StructInit { - for field in expr.fields { - vars << g.dependent_var_names(field.expr) - } - } - ast.InfixExpr { - vars << g.dependent_var_names(expr.left) - vars << g.dependent_var_names(expr.right) - } - ast.PostfixExpr { - vars << g.dependent_var_names(expr.expr) - } - ast.PrefixExpr { - vars << g.dependent_var_names(expr.right) - } - ast.CallExpr { - for arg in expr.args { - vars << g.dependent_var_names(arg.expr) - } - } - else {} - } - return vars -} - fn (mut g Gen) const_decl(node ast.ConstDecl) { g.inside_const = true defer { @@ -4427,7 +4389,7 @@ fn (mut g Gen) const_decl(node ast.ConstDecl) { g.global_const_defs[util.no_dots(field.name)] = GlobalConstDef{ mod: field.mod def: '$styp $const_name = $val; // fixed array const' - dep_names: g.dependent_var_names(field_expr) + dep_names: g.table.dependent_names_in_expr(field_expr) // line: field.pos.line_nr } } else { @@ -4658,7 +4620,7 @@ fn (mut g Gen) const_decl_init_later(line_nr int, mod string, name string, expr mod: mod def: '$styp $cname; // inited later' init: init.str() - dep_names: g.dependent_var_names(expr) + dep_names: g.table.dependent_names_in_expr(expr) order: order line: line } @@ -4765,7 +4727,7 @@ fn (mut g Gen) global_decl(node ast.GlobalDecl) { mod: node.mod def: def_builder.str() init: init - dep_names: g.dependent_var_names(field.expr) + dep_names: g.table.dependent_names_in_expr(field.expr) // line: node.pos.line_nr } } diff --git a/vlib/v/tests/const_call_expr_order_test.v b/vlib/v/tests/const_call_expr_order_test.v new file mode 100644 index 0000000000..5e39b846d4 --- /dev/null +++ b/vlib/v/tests/const_call_expr_order_test.v @@ -0,0 +1,18 @@ +import os + +const ( + shdc_exe_name = 'sokol-shdc.exe' + tool_name = os.file_name(os.executable()) + cache_dir = os.join_path(os.cache_dir(), 'v', tool_name) + shdc = shdc_exe() +) + +fn test_const_call_expr_order() { + dump(cache_dir) + dump(shdc) + assert true +} + +fn shdc_exe() string { + return os.join_path(cache_dir, shdc_exe_name) +}