Skip to content

Possible to use less recursion when parsing? #113

@vpanteleev-sym

Description

@vpanteleev-sym

Currently trying to parse a moderately sized GraphQL schema at compile-time results in:

.../source/graphql/lexer.d(66,15): Error: function `graphql.lexer.Lexer.eatComment` CTFE recursion limit exceeded
.../source/graphql/lexer.d(88,22):        called from here: `this.eatComment()`
.../source/graphql/lexer.d(104,21):        called from here: `this.eatWhitespace()`
.../source/graphql/lexer.d(548,18):        called from here: `this.buildToken()`
.../source/graphql/parser.d(2153,21):        called from here: `this.lex.popFront()`
.../source/graphql/parser.d(2140,33):        called from here: `this.parseListTypeImpl()`
.../source/graphql/parser.d(2108,38):        called from here: `this.parseListType()`
.../source/graphql/parser.d(2081,29):        called from here: `this.parseTypeImpl()`
.../source/graphql/parser.d(3947,33):        called from here: `this.parseType()`
.../source/graphql/parser.d(3861,45):        called from here: `this.parseInputValueDefinitionImpl()`
.../source/graphql/parser.d(3805,60):        called from here: `this.parseInputValueDefinition()`
.../source/graphql/parser.d(3792,46):        called from here: `this.parseInputValueDefinitionsImpl()`
.../source/graphql/parser.d(3801,24):        9 recursive calls to function `parseInputValueDefinitionsImpl`
.../source/graphql/parser.d(3790,24):        recursively called from function `parseInputValueDefinitions`
.../source/graphql/parser.d(5022,67):        called from here: `this.parseInputValueDefinitions()`
.../source/graphql/parser.d(4946,50):        called from here: `this.parseInputObjectTypeDefinitionImpl()`
.../source/graphql/parser.d(2670,71):        called from here: `this.parseInputObjectTypeDefinition()`
.../source/graphql/parser.d(2627,39):        called from here: `this.parseTypeDefinitionImpl()`
.../source/graphql/parser.d(2570,49):        called from here: `this.parseTypeDefinition()`
.../source/graphql/parser.d(2523,45):        called from here: `this.parseTypeSystemDefinitionImpl()`
.../source/graphql/parser.d(142,62):        called from here: `this.parseTypeSystemDefinition()`
.../source/graphql/parser.d(117,35):        called from here: `this.parseDefinitionImpl()`
.../source/graphql/parser.d(82,41):        called from here: `this.parseDefinition()`
.../source/graphql/parser.d(69,36):        called from here: `this.parseDefinitionsImpl()`
.../source/graphql/parser.d(78,14):        479 recursive calls to function `parseDefinitionsImpl`
.../source/graphql/parser.d(67,14):        recursively called from function `parseDefinitions`
.../source/graphql/parser.d(44,44):        called from here: `this.parseDefinitions()`
.../source/graphql/parser.d(31,33):        called from here: `this.parseDocumentImpl()`
.../source/graphql/client/query.d(66,27):        called from here: `p.parseDocument()`
.../source/graphql/client/query.d(69,3):        called from here: `(*function () @system => SchemaDocument(SchemaDefinition(null), null, null, null, null, null).this(d))()`
Error: cannot interpret `__error` at compile time
.../source/graphql/client/query.d(25,13):        called from here: `toD(document, settings)`
.../source/graphql/client/query.d(26,3):        called from here: `(*function () @system => toD(document, settings))()`
.../source/graphql/client/query.d(70,12): Error: template instance `graphql.client.query.GraphQLSchema!(document, GraphQLSettings

It looks like the root of the issue is that parseDefinitions recurses into itself (via parseDefinitionsImpl), so the parsed document size will always be limited by the maximum stack depth.

Looking at the generated code, at least for this case, it doesn't seem like recursion is strictly required, and can be replaced with a loop instead. Perhaps we can detect this situation in Darser and generate different code for it which avoids excessive recursion.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions