Skip to content

Cyclic importsΒ #28

@moleike

Description

@moleike

Cyclic imports are valid and well defined:

$ cat a.jsonnet 
{
  a:: 'a',
  c: (import 'b.jsonnet').b,
}
$ cat b.jsonnet 
{
  b:: (import 'a.jsonnet').a,
}
$ /google/data/ro/teams/jsonnet/jsonnet a.jsonnet 
{
   "c": "a"
}

So are imports on self:

$ cat a.jsonnet 
{
  a:: 'a',
  c: (import 'a.jsonnet').a,
}
$ jsonnet a.jsonnet 
{
   "c": "a"
}

The problem in the code snippet in the description is that the object in "main.jsonnet" is recursively defined in a way where the recursion doesn't have a terminating condition (i.e. bottomless). It's equivalent to:

local a = a + {};
a

Which produces similar results:

$ jsonnet main.jsonnet 
RUNTIME ERROR: max stack frames exceeded.
        main.jsonnet:1:11       thunk <a>
        main.jsonnet:1:11       thunk <a>
        main.jsonnet:1:11       thunk <a>
        main.jsonnet:1:11       thunk <a>
        main.jsonnet:1:11       thunk <a>
        main.jsonnet:1:11       thunk <a>
        main.jsonnet:1:11       thunk <a>
        main.jsonnet:1:11       thunk <a>
        main.jsonnet:1:11       thunk <a>
        main.jsonnet:1:11       thunk <a>
        ...

But there are plenty of valid ways to define a variable or set of varibles recursively that do bottom out. For example:

{
 x: {
   a: 1,
   y: $.y,
 },
 y: {
   x: $.x,
   a: 1,
 },
}.x.y.x.y.x.y.x.a
{
  a: 1,
  b: 1,
  fib: self {
    a: super.b,
    b: super.a + super.b,
  },
}.fib.fib.fib.fib.fib.a

Are both valid, terminating programs.

Originally posted by @mikedanese in google/go-jsonnet#353 (comment)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions