Procházet zdrojové kódy

Added EnumKindName() for rtti enums + sample usage to print node kind names during type checking (#1305)

Sample trace output:

```
checking tuple pattern (v1: T1, v2: T2), expecting (T1:! ImplicitAs(U1), T2:! ImplicitAs(U2))
checking binding pattern v1: T1, expecting T1:! ImplicitAs(U1)
checking expression pattern T1
checking identifier expression T1
```
pk19604014 před 3 roky
rodič
revize
035afdccff

+ 5 - 3
explorer/ast/BUILD

@@ -16,7 +16,7 @@ cc_library(
 
 cc_library(
     name = "ast_node",
-    srcs = ["ast_node.cpp"],
+    srcs = ["ast_node.cpp", "ast_rtti.cpp",],
     hdrs = [
         "ast_node.h",
         "ast_rtti.h",
@@ -30,9 +30,11 @@ cc_library(
 genrule(
     name = "ast_rtti",
     srcs = ["ast_rtti.txt"],
-    outs = ["ast_rtti.h"],
+    outs = ["ast_rtti.h", "ast_rtti.cpp"],
     cmd = "./$(location //explorer:gen_rtti)" +
-          " $(location ast_rtti.txt) > \"$@\"",
+          " $(location ast_rtti.txt)" +
+          " $(location ast_rtti.h) $(location ast_rtti.cpp)" +
+          " $(rootpath ast_rtti.h)",
     tools = ["//explorer:gen_rtti"],
 )
 

+ 36 - 0
explorer/gen_rtti.py

@@ -181,6 +181,10 @@ _LINE_PATTERN = r"""(?P<prefix> \w*) \s*
 
 def main() -> None:
     input_filename = sys.argv[1]
+    header_filename = sys.argv[2]
+    cpp_filename = sys.argv[3]
+    relative_header = sys.argv[4]
+
     with open(input_filename) as file:
         lines = file.readlines()
 
@@ -226,11 +230,15 @@ def main() -> None:
         if node.kind == Class.Kind.ROOT:
             node.Finalize()
 
+    header_file = open(header_filename, "w")
+    sys.stdout = header_file
+
     print(f"// Generated from {input_filename} by explorer/gen_rtti.py\n")
     trans_table = str.maketrans({"/": "_", ".": "_"})
     guard_macro = input_filename.upper().translate(trans_table) + "_"
     print(f"#ifndef {guard_macro}")
     print(f"#define {guard_macro}")
+    print("\n#include <string_view>")
     print("\nnamespace Carbon {\n")
 
     for node in classes.values():
@@ -242,6 +250,8 @@ def main() -> None:
                 print(f"  {node.Root().leaves[id].name} = {id},")
             print("};\n")
 
+            print(f"std::string_view {node.name}KindName({node.name}Kind k);\n")
+
         if node.kind in [Class.Kind.ABSTRACT, Class.Kind.CONCRETE]:
             print(
                 f"inline bool InheritsFrom{node.name}({node.Root().name}Kind"
@@ -273,6 +283,32 @@ def main() -> None:
     print("}  // namespace Carbon\n")
     print(f"#endif  // {guard_macro}")
 
+    header_file.close()
+
+    cpp_file = open(cpp_filename, "w")
+    sys.stdout = cpp_file
+
+    print(f"// Generated from {input_filename} by explorer/gen_rtti.py\n")
+    print(f'#include "{relative_header}"')
+    print("\nnamespace Carbon {\n")
+    for node in classes.values():
+        if node.kind != Class.Kind.CONCRETE:
+            assert node.id_range is not None
+            ids = range(node.id_range[0], node.id_range[1])
+            print(f"std::string_view {node.name}KindName({node.name}Kind k) {{")
+            print("  switch(k) {")
+            for id in ids:
+                name = node.Root().leaves[id].name
+                desc = " ".join(
+                    w.lower() for w in re.sub(r"([A-Z])", r" \1", name).split()
+                )
+                print(f'    case {node.name}Kind::{name}: return "{desc}";')
+            print("  }")
+            print("}\n")
+
+    print("}  // namespace Carbon\n")
+    cpp_file.close()
+
 
 if __name__ == "__main__":
     main()

+ 8 - 3
explorer/interpreter/type_checker.cpp

@@ -994,7 +994,8 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
                                const ImplScope& impl_scope)
     -> ErrorOr<Success> {
   if (trace_stream_) {
-    **trace_stream_ << "checking expression " << *e;
+    **trace_stream_ << "checking " << ExpressionKindName(e->kind()) << " "
+                    << *e;
     **trace_stream_ << "\nconstants: ";
     PrintConstants(**trace_stream_);
     **trace_stream_ << "\n";
@@ -1793,7 +1794,7 @@ auto TypeChecker::TypeCheckPattern(
     ImplScope& impl_scope, ValueCategory enclosing_value_category)
     -> ErrorOr<Success> {
   if (trace_stream_) {
-    **trace_stream_ << "checking pattern " << *p;
+    **trace_stream_ << "checking " << PatternKindName(p->kind()) << " " << *p;
     if (expected) {
       **trace_stream_ << ", expecting " << **expected;
     }
@@ -1986,7 +1987,8 @@ auto TypeChecker::TypeCheckStmt(Nonnull<Statement*> s,
                                 const ImplScope& impl_scope)
     -> ErrorOr<Success> {
   if (trace_stream_) {
-    **trace_stream_ << "checking statement " << *s << "\n";
+    **trace_stream_ << "checking " << StatementKindName(s->kind()) << " " << *s
+                    << "\n";
   }
   switch (s->kind()) {
     case StatementKind::Match: {
@@ -2723,6 +2725,9 @@ auto TypeChecker::TypeCheck(AST& ast) -> ErrorOr<Success> {
 auto TypeChecker::TypeCheckDeclaration(Nonnull<Declaration*> d,
                                        const ImplScope& impl_scope)
     -> ErrorOr<Success> {
+  if (trace_stream_) {
+    **trace_stream_ << "checking " << DeclarationKindName(d->kind()) << "\n";
+  }
   switch (d->kind()) {
     case DeclarationKind::InterfaceDeclaration: {
       CARBON_RETURN_IF_ERROR(TypeCheckInterfaceDeclaration(

+ 1 - 1
explorer/testdata/basic_syntax/trace.carbon

@@ -12,7 +12,7 @@
 // CHECK: ********** source program **********
 // CHECK: fn Print (format_str: String) {
 // CHECK: ********** type checking **********
-// CHECK: checking pattern (format_str: String)
+// CHECK: checking tuple pattern (format_str: String)
 // CHECK: ********** type checking complete **********
 // CHECK: fn Print (format_str: String) {
 // CHECK: ********** starting execution **********