Skip to content

Infinite recursion in macro expansion crashes compiler #1740

Description

@cgay

The following macro and macro call cause a segmentation fault in the compiler.

(Also available here: https://play.opendylan.org/shared/e3ade7dbb9f0d071)

define traced macro enum-definer
    { define enum ?enum-name:name () ?clauses:* end }
 => { ?@defconst{ 1 ; ?clauses }
      define constant "$" ## ?enum-name ## "-names" = vector(?@pretty-names{ ?clauses });
      define constant "$" ## ?enum-name ## "-values" = vector(?@constant-names{ ?clauses }); }

 defconst:
    { ?default:expression } => { }

    // Rewrite foo; => foo = default ("foo");
    { ?default:expression ; ?:name ; ?more:* }
 => { ?@defconst{ ?default ; ?name = ?default (?"name") ; ?more } }

    // Rewrite foo = 1; => foo = 1 ("foo");
    { ?default:expression ; ?:name = ?value:expression ; ?more:* }
 => { ?@defconst{ ?default ; ?name = ?value (?"name") ; ?more } }

    // Rewrite foo ("Foo"); => foo = default ("Foo");
    { ?default:expression ; ?:name (?pretty-name:expression) ; ?more:* }
 => { ?@defconst{ ?default ; ?name = ?default (?pretty-name) ; ?more } }

    // Fully specified case
    { ?default:expression ; ?:name = ?value:expression (?pretty-name:expression) ; ?more:* }
 => { define constant ?name :: <int> = ?value;
      ?@defconst{ ?default ; ?more } }

 constant-names:
    { } => {}
    { ?:name ?junk:* ; ...} => { ?name , ... }

 pretty-names:
    { ?:name = ?:expression { ?pretty-name:expression } ; ... } => { ?pretty-name , ... }
    { ?:name { ?pretty-name:expression } ; ... }                => { ?pretty-name , ... }
    { ?:name = ?:expression ; ... }                             => { ?"name" , ... }
    { ?:name ; ... }                                            => { ?"name" , ... }
    {} => {}
end macro;

define enum color ()
  $color-red;                 // defines $color-red   :: <int> = 1 with name "red"
  $color-green = 20;          // defines $color-green :: <int> = 20 with name "green"
  $color-blue {"Blue"};       // defines $color-blue  :: <int> = 21 with name "Blue"
  $color-cyan = 30 {"Cyan"};  // defines $color-cyan  :: <int> = 30 with name "Cyan"
end;

The sharp eye will notice that I hadn't fixed all the template rules to use { } around the color name yet. Finishing that work (as is done here) prevents the crash.

I'm sure this isn't a minimal test case. I'll try to whittle it down a bit when I get a chance.

I don't yet understand why { } work and ( ) don't, but I did note that when using ( ) in the pretty-names aux rule set the clause $color-cyan = 30 ("Cyan"); was matching { ?:name = ?:expression ; ... } for some reason. I assume that's the same reason for the infinite recursion in the defconst rules as well.

Backtrace from segfault:

dylan-bt
  frame #14   list                                                         0x000001089cd433 libdylan.dylib at list.dylan:37
  frame #15   append-sequence                                              0x0000010a20c7b9 libdfmc-reader.dylib at parser-support.dylan:13
  frame #16   call-parser-action                                           0x0000010943916a libparser-run-time.dylib at dispatch.dylan:305
  frame #17   run-parser                                                   0x00000109439108 libparser-run-time.dylib at dispatch.dylan:395
  frame #18   re-read-fragments                                            0x0000010a20eb9f libdfmc-reader.dylib at interface.dylan:65
  frame #19   parse-constraint                                             0x0000010a36f144 libdfmc-macro-expander.dylib at constraint-parsing.dylan:55
  frame #20   match-expression-constraint                                  0x0000010a37354c libdfmc-macro-expander.dylib at pattern-back-end.dylan:333
  frame #21   Kanonymous_of_generate_functionF225I                         0x0000010a38b8ed libdfmc-macro-expander.dylib at pattern-to-function.dylan:415
  frame #22   Kanonymous_of_generate_pattern_element_functionF308I         0x0000010a38be1b libdfmc-macro-expander.dylib at pattern-to-function.dylan:228
  frame #23   Kanonymous_of_generate_pattern_element_functionF308I         0x0000010a38be82 libdfmc-macro-expander.dylib at pattern-to-function.dylan:229
  frame #24   Kanonymous_of_generate_pattern_element_functionF308I         0x0000010a38be82 libdfmc-macro-expander.dylib at pattern-to-function.dylan:229
  frame #25   Kanonymous_of_generate_structure_parts_functionF322I         0x0000010a38bfba libdfmc-macro-expander.dylib at pattern-to-function.dylan:207
  frame #26   Kanonymous_of_generate_structure_parts_functionF322I         0x0000010a38bfea libdfmc-macro-expander.dylib at pattern-to-function.dylan:209
  frame #27   Kanonymous_of_generate_rule_functionF323I                    0x0000010a38a09d libdfmc-macro-expander.dylib at pattern-to-function.dylan:105
  frame #28   call-list-with-collecting                                    0x0000010a389b0c libdfmc-macro-expander.dylib at pattern-to-function.dylan:570
  frame #29   Kanonymous_of_generate_template_functionF60I                 0x0000010a3894a5 libdfmc-macro-expander.dylib at template-function.dylan:24
  frame #30   call-list-with-collecting                                    0x0000010a389b0c libdfmc-macro-expander.dylib at pattern-to-function.dylan:570
  frame #31   Kanonymous_of_generate_template_functionF60I                 0x0000010a3894a5 libdfmc-macro-expander.dylib at template-function.dylan:24
  frame #32   call-list-with-collecting                                    0x0000010a389b0c libdfmc-macro-expander.dylib at pattern-to-function.dylan:570
  frame #33   Kanonymous_of_generate_template_functionF60I                 0x0000010a3894a5 libdfmc-macro-expander.dylib at template-function.dylan:24
  frame #34   call-list-with-collecting                                    0x0000010a389b0c libdfmc-macro-expander.dylib at pattern-to-function.dylan:570
...etc...

[edit: fixed dead playground links]

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions