diff --git a/internal/core/export/adt.go b/internal/core/export/adt.go index 4cbb49fc13d..9691763f2b5 100644 --- a/internal/core/export/adt.go +++ b/internal/core/export/adt.go @@ -179,51 +179,7 @@ func (e *exporter) adt(expr adt.Expr, conjuncts []adt.Conjunct) ast.Expr { return ident case *adt.LetReference: - // TODO: Handle references that went out of scope. In case of aliases - // this means they may need to be reproduced locally. Most of these - // issues can be avoided by either fully expanding a configuration - // (export) or not at all (def). - // - i := len(e.stack) - 1 - int(x.UpCount) - 1 - if i < 0 { - i = 0 - } - f := &(e.stack[i]) - let := f.let[x.X] - if let == nil { - if f.let == nil { - f.let = map[adt.Expr]*ast.LetClause{} - } - label := e.uniqueLetIdent(x.Label, x.X) - - name := label.IdentString(e.ctx) - - // A let may be added multiple times to the same scope as a result - // of how merging works. If that happens here it must be one - // originating from the same expression, and it is safe to drop. - for _, elt := range f.scope.Elts { - if a, ok := elt.(*ast.LetClause); ok { - if a.Ident.Name == name { - let = a - break - } - } - } - - if let == nil { - let = &ast.LetClause{ - Ident: e.ident(label), - Expr: e.expr(x.X), - } - f.scope.Elts = append(f.scope.Elts, let) - } - - f.let[x.X] = let - } - ident := ast.NewIdent(let.Ident.Name) - ident.Node = let - ident.Scope = f.scope - return ident + return e.resolveLet(x) case *adt.SelectorExpr: return &ast.SelectorExpr{ diff --git a/internal/core/export/export.go b/internal/core/export/export.go index 6c88b5bf440..c98f4d72aee 100644 --- a/internal/core/export/export.go +++ b/internal/core/export/export.go @@ -217,7 +217,7 @@ type exporter struct { index adt.StringIndexer rand *rand.Rand - // For resolving up references. + // For resolving references. stack []frame inDefinition int // for close() wrapping. @@ -231,6 +231,7 @@ type exporter struct { usedFeature map[adt.Feature]adt.Expr labelAlias map[adt.Expr]adt.Feature valueAlias map[*ast.Alias]*ast.Alias + letAlias map[*ast.LetClause]*ast.LetClause usedHidden map[string]bool } @@ -307,15 +308,76 @@ func setFieldAlias(f *ast.Field, name string) { } } -// uniqueLetIdent returns a name for a let identifier that uniquely identifies -// the given expression. If the preferred name is already taken, a new globally -// unique name of the form base_X ... base_XXXXXXXXXXXXXX is generated. -// -// It prefers short extensions over large ones, while ensuring the likelihood of -// fast termination is high. There are at least two digits to make it visually -// clearer this concerns a generated number. -// -func (e exporter) uniqueLetIdent(f adt.Feature, x adt.Expr) adt.Feature { +func (e *exporter) markLets(n ast.Node) { + switch v := n.(type) { + case *ast.StructLit: + e.markLetDecls(v.Elts) + case *ast.File: + e.markLetDecls(v.Decls) + } +} + +func (e *exporter) markLetDecls(decls []ast.Decl) { + for _, d := range decls { + if let, ok := d.(*ast.LetClause); ok { + e.markLetAlias(let) + } + } +} + +// markLetAlias inserts an uninitialized let clause into the current scope. +// It gets initialized upon first usage. +func (e *exporter) markLetAlias(x *ast.LetClause) { + // The created let clause is initialized upon first usage, and removed + // later if never referenced. + let := &ast.LetClause{} + + if e.letAlias == nil { + e.letAlias = make(map[*ast.LetClause]*ast.LetClause) + } + e.letAlias[x] = let + + scope := e.top().scope + scope.Elts = append(scope.Elts, let) +} + +// In value mode, lets are only used if there wasn't an error. +func filterUnusedLets(s *ast.StructLit) { + k := 0 + for i, d := range s.Elts { + if let, ok := d.(*ast.LetClause); ok && let.Expr == nil { + continue + } + s.Elts[k] = s.Elts[i] + k++ + } + s.Elts = s.Elts[:k] +} + +// resolveLet actually parses the let expression. +// If there was no recorded let expression, it expands the expression in place. +func (e *exporter) resolveLet(x *adt.LetReference) ast.Expr { + letClause, _ := x.Src.Node.(*ast.LetClause) + let := e.letAlias[letClause] + + switch { + case let == nil: + return e.expr(x.X) + + case let.Expr == nil: + label := e.uniqueLetIdent(x.Label, x.X) + + let.Ident = e.ident(label) + let.Expr = e.expr(x.X) + } + + ident := ast.NewIdent(let.Ident.Name) + ident.Node = let + // TODO: set scope? + return ident +} + +func (e *exporter) uniqueLetIdent(f adt.Feature, x adt.Expr) adt.Feature { if e.usedFeature[f] == x { return f } @@ -325,7 +387,7 @@ func (e exporter) uniqueLetIdent(f adt.Feature, x adt.Expr) adt.Feature { return f } -func (e exporter) uniqueAlias(name string) string { +func (e *exporter) uniqueAlias(name string) string { f := adt.MakeIdentLabel(e.ctx, name, "") if _, ok := e.usedFeature[f]; !ok { @@ -337,29 +399,46 @@ func (e exporter) uniqueAlias(name string) string { return name } -func (e exporter) uniqueFeature(base string) (f adt.Feature, name string) { +// uniqueFeature returns a name for an identifier that uniquely identifies +// the given expression. If the preferred name is already taken, a new globally +// unique name of the form base_X ... base_XXXXXXXXXXXXXX is generated. +// +// It prefers short extensions over large ones, while ensuring the likelihood of +// fast termination is high. There are at least two digits to make it visually +// clearer this concerns a generated number. +// +func (e *exporter) uniqueFeature(base string) (f adt.Feature, name string) { if e.rand == nil { e.rand = rand.New(rand.NewSource(808)) } + // Try the first few numbers in sequence. + for i := 1; i < 5; i++ { + name := fmt.Sprintf("%s_%01X", base, i) + f := adt.MakeIdentLabel(e.ctx, name, "") + if _, ok := e.usedFeature[f]; !ok { + e.usedFeature[f] = nil + return f, name + } + } + const mask = 0xff_ffff_ffff_ffff // max bits; stay clear of int64 overflow const shift = 4 // rate of growth + digits := 1 for n := int64(0x10); ; n = int64(mask&((n< 0 + for _, c := range a { e.top().upCount = c.up x := c.c.Expr() @@ -133,8 +138,6 @@ func (x *exporter) mergeValues(label adt.Feature, src *adt.Vertex, a []conjunct, } } - s := x.top().scope - for _, a := range e.attrs { s.Elts = append(s.Elts, a) } @@ -184,7 +187,7 @@ func (x *exporter) mergeValues(label adt.Feature, src *adt.Vertex, a []conjunct, } else { x = e.embed[0] } - if len(e.attrs) == 0 { + if len(e.attrs) == 0 && !hasAlias { return x } if st, ok := x.(*ast.StructLit); ok { diff --git a/internal/core/export/testdata/alias.txtar b/internal/core/export/testdata/alias.txtar index fb688e68051..1098d246cc9 100644 --- a/internal/core/export/testdata/alias.txtar +++ b/internal/core/export/testdata/alias.txtar @@ -67,12 +67,12 @@ fieldAlias: { } cross: { baz: 3 - X_85="d-2": { + X_2="d-2": { E=[D="cue"]: { C="foo\(baz)": { name: "xx" foo: C.name - bar: X_85 + bar: X_2 baz: D qux: E } @@ -84,8 +84,8 @@ valueAlias: { merge: { // Merge fields, rename alias to avoid conflict. // TODO: merged values can still be simplified. - value: X_BA={ - #value: X_BA.b & X_BA.b + value: X_3={ + #value: X_3.b & X_3.b b: 2 v: { X: 3 @@ -95,8 +95,8 @@ valueAlias: { selfRef: { struct: { a: { - b: X_57C8={ - #foo: X_57C8.b + b: X_4={ + #foo: X_4.b b: 2 } } @@ -110,7 +110,7 @@ valueAlias: { // an issue exclusive to value aliases, and falls within the // range of what is acceptable for now. // TODO: solve this issue. - a: X_35B7E=or(X_35B7E) + a: X_8=or(X_8) } pattern: { // this triggers the verbatim "adt" path. Note that there diff --git a/internal/core/export/testdata/let.txtar b/internal/core/export/testdata/let.txtar index 65b1e39c7b1..c581f766b21 100644 --- a/internal/core/export/testdata/let.txtar +++ b/internal/core/export/testdata/let.txtar @@ -31,8 +31,73 @@ for cfg in cfgs { } } +-- for.cue -- +comprehension: { + for cfg in [{a: "one"}] { + let filepath = "kind-\(cfg.name)" + "\(filepath)": { + patches: cfg + } + } +} + +-- scope.cue -- +scoped: { + _args: required: 1 + direct: { + let Args = _args + a: Args.required + } + embed1: { + let Args = _args + a: {Args.required} + } + embed2: { + let Args = _args + a: {{Args.required}} + } + list: { + let Args = _args + a: [Args.required] + } + listStruct: { + let Args = _args + a: [{a: Args.required}] + } + listEmbed: { + let Args = _args + a: [{Args.required}] + } +} + + +-- incomplete.cue -- +incomplete: a: { + x: "a \(run.a) z" + run: { + a: string + } +} +incomplete: b: { + let A = run.a + x: "a \(A) z" + run: { + a: string + } +} +incomplete: c: { + let A = run.a + x: "a \(A) z" + run: { + a: "foo" + } +} + -- out/definition -- +let X = 1 + 1 +let Y = x +let Y_1 = x { cfgs: [ for crd in ["one", "two"] { metadata: { @@ -48,12 +113,72 @@ for cfg in cfgs { } } } -let X = 1 + 1 #Foo: X x: "foo" -let Y = x -let Y_1 = x +comprehension: { + for cfg in [{ + a: "one" + }] { + let filepath_1 = "kind-\(cfg.name)" + "\(filepath_1)": { + patches: cfg + } + } +} +scoped: { + _args: { + required: 1 + } + direct: { + let Args = _args + a: Args.required + } + embed1: { + let Args_1 = _args + a: Args_1.required + } + embed2: { + let Args_2 = _args + a: Args_2.required + } + list: { + let Args_3 = _args + a: [Args_3.required] + } + listStruct: { + let Args_4 = _args + a: [{ + a: Args_4.required + }] + } + listEmbed: { + let Args_8 = _args + a: [Args_8.required] + } +} y: Y & Y_1 +incomplete: { + a: { + x: "a \(run.a) z" + run: { + a: string + } + } + b: { + let A = run.a + x: "a \(A) z" + run: { + a: string + } + } + c: { + let A_1 = run.a + x: "a \(A_1) z" + run: { + a: "foo" + } + } +} -- out/doc -- [] [#Foo] @@ -66,6 +191,39 @@ y: Y & Y_1 [cfgs 1] [cfgs 1 metadata] [cfgs 1 metadata name] +[comprehension] +[scoped] +[scoped _args] +[scoped _args required] +[scoped direct] +[scoped direct a] +[scoped embed1] +[scoped embed1 a] +[scoped embed2] +[scoped embed2 a] +[scoped list] +[scoped list a] +[scoped list a 0] +[scoped listStruct] +[scoped listStruct a] +[scoped listStruct a 0] +[scoped listStruct a 0 a] +[scoped listEmbed] +[scoped listEmbed a] +[scoped listEmbed a 0] +[incomplete] +[incomplete a] +[incomplete a x] +[incomplete a run] +[incomplete a run a] +[incomplete b] +[incomplete b x] +[incomplete b run] +[incomplete b run a] +[incomplete c] +[incomplete c x] +[incomplete c run] +[incomplete c run a] [files] -- out/value -- == Simplified @@ -80,17 +238,69 @@ y: Y & Y_1 name: "two" } }] - let filepath = "kind-\(cfg.name)" + comprehension: { + for cfg in [{ + a: "one" + }] { + let filepath_1 = "kind-\(cfg.name)" + "\(filepath_1)": { + patches: cfg + } + } + } + scoped: { + direct: { + a: 1 + } + embed1: { + a: 1 + } + embed2: { + a: 1 + } + list: { + a: [1] + } + listStruct: { + a: [{ + a: 1 + }] + } + listEmbed: { + a: [1] + } + } files: { - "\(filepath)": { + "\("kind-\(cfg.name)")": { patches: cfg } } & { - "\(filepath)": { + "\("kind-\(cfg.name)")": { patches: cfg } } y: "foo" + incomplete: { + a: { + x: "a \(run.a) z" + run: { + a: string + } + } + b: { + let A = run.a + x: "a \(A) z" + run: { + a: string + } + } + c: { + x: "a foo z" + run: { + a: "foo" + } + } + } } == Raw { @@ -105,17 +315,72 @@ y: Y & Y_1 name: "two" } }] - let filepath = "kind-\(cfg.name)" + comprehension: { + for cfg in [{ + a: "one" + }] { + let filepath_1 = "kind-\(cfg.name)" + "\(filepath_1)": { + patches: cfg + } + } + } + scoped: { + _args: { + required: 1 + } + direct: { + a: 1 + } + embed1: { + a: 1 + } + embed2: { + a: 1 + } + list: { + a: [1] + } + listStruct: { + a: [{ + a: 1 + }] + } + listEmbed: { + a: [1] + } + } files: { - "\(filepath)": { + "\("kind-\(cfg.name)")": { patches: cfg } } & { - "\(filepath)": { + "\("kind-\(cfg.name)")": { patches: cfg } } y: "foo" + incomplete: { + a: { + x: "a \(run.a) z" + run: { + a: string + } + } + b: { + let A = run.a + x: "a \(A) z" + run: { + a: string + } + } + c: { + x: "a foo z" + run: { + a: "foo" + } + } + } } == Final { @@ -129,8 +394,51 @@ y: Y & Y_1 name: "two" } }] + comprehension: _|_ // invalid interpolation: invalid interpolation: comprehension: undefined field: name + scoped: { + direct: { + a: 1 + } + embed1: { + a: 1 + } + embed2: { + a: 1 + } + list: { + a: [1] + } + listStruct: { + a: [{ + a: 1 + }] + } + listEmbed: { + a: [1] + } + } files: _|_ // invalid interpolation: invalid interpolation: files: undefined field: name (and 3 more errors) y: "foo" + incomplete: { + a: { + x: _|_ // invalid interpolation: incomplete.a.x: non-concrete value string (type string) + run: { + a: string + } + } + b: { + x: _|_ // invalid interpolation: incomplete.b.x: non-concrete value string (type string) + run: { + a: string + } + } + c: { + x: "a foo z" + run: { + a: "foo" + } + } + } } == All { @@ -145,17 +453,72 @@ y: Y & Y_1 name: "two" } }] - let filepath = "kind-\(cfg.name)" + comprehension: { + for cfg in [{ + a: "one" + }] { + let filepath_1 = "kind-\(cfg.name)" + "\(filepath_1)": { + patches: cfg + } + } + } + scoped: { + _args: { + required: 1 + } + direct: { + a: 1 + } + embed1: { + a: 1 + } + embed2: { + a: 1 + } + list: { + a: [1] + } + listStruct: { + a: [{ + a: 1 + }] + } + listEmbed: { + a: [1] + } + } files: { - "\(filepath)": { + "\("kind-\(cfg.name)")": { patches: cfg } } & { - "\(filepath)": { + "\("kind-\(cfg.name)")": { patches: cfg } } y: "foo" + incomplete: { + a: { + x: "a \(run.a) z" + run: { + a: string + } + } + b: { + let A = run.a + x: "a \(A) z" + run: { + a: string + } + } + c: { + x: "a foo z" + run: { + a: "foo" + } + } + } } == Eval { @@ -170,15 +533,67 @@ y: Y & Y_1 name: "two" } }] - let filepath = "kind-\(cfg.name)" + comprehension: { + for cfg in [{ + a: "one" + }] { + let filepath_1 = "kind-\(cfg.name)" + "\(filepath_1)": { + patches: cfg + } + } + } + scoped: { + direct: { + a: 1 + } + embed1: { + a: 1 + } + embed2: { + a: 1 + } + list: { + a: [1] + } + listStruct: { + a: [{ + a: 1 + }] + } + listEmbed: { + a: [1] + } + } files: { - "\(filepath)": { + "\("kind-\(cfg.name)")": { patches: cfg } } & { - "\(filepath)": { + "\("kind-\(cfg.name)")": { patches: cfg } } y: "foo" + incomplete: { + a: { + x: "a \(run.a) z" + run: { + a: string + } + } + b: { + let A = run.a + x: "a \(A) z" + run: { + a: string + } + } + c: { + x: "a foo z" + run: { + a: "foo" + } + } + } } diff --git a/internal/core/export/value.go b/internal/core/export/value.go index 9018af8e874..a5efc7f2e74 100644 --- a/internal/core/export/value.go +++ b/internal/core/export/value.go @@ -349,6 +349,13 @@ func (e *exporter) structComposite(v *adt.Vertex, attrs []*ast.Attribute) ast.Ex e.popFrame(saved) }() + for _, c := range v.Conjuncts { + e.markLets(c.Expr().Source()) + } + if len(s.Elts) > 0 { + defer filterUnusedLets(s) + } + showRegular := false switch x := v.BaseValue.(type) { case *adt.StructMarker: diff --git a/internal/filetypes/types.go b/internal/filetypes/types.go index 2093cd0cd8a..b4cd55aeec2 100644 --- a/internal/filetypes/types.go +++ b/internal/filetypes/types.go @@ -41,5 +41,5 @@ func cuegenMake(name string, x interface{}) cue.Value { return v } -// Data size: 1713 bytes. -var cuegenInstanceData = []byte("\x01\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xacX\u074f\u0736\x11\x97\xce.P\x11i\u07da\xb7\x02c\x19\b\u0483\xabE\x1e\x8c\x18\v\x1c\f'\xb6\v\xbf4E\x91>\x05\xc1\x81+\x8dv\xd9H\xa4JR\xc9\x1dr\xfb\xd06M\xfbW{\x8b!\xa9o\xdd\xd9\xd7\xfa^nw~\x9c\xe1\xccp>\xf7W\xa7\u007f\x9f\xc5g\xa7\xffD\xf1\xe9\x1fQ\xf4\xf9\xe9\xef\x0f\xe2\xf8#!\x8d\xe52\u01d7\xdcr\xa2\xc7\x0f\xe2\x87\u007fV\xca\xc6gQ\xfc\xf0O\xdc\x1e\u23e2\xf8\x17\xafE\x85&>\xfd\x1cE\xd1oO\xff:\x8b\xe3_\u007f\xf3m\xdebV\x8a*p\xfe\x1c\u0167\x9f\xa2\xe8\xd3\xd3?\x1f\xc4\xf1/\a\xfaOQ|\x16?\xfc#\xaf\x91\x04=tD\x16E\xd1\u06cf3\xd2$\x8e\xcf\xe28\xb1\xd7\r\x9a,o1~\xfb\xf1o\x1a\x9e\u007f\xc7\xf7\b\xbbVT\x05c\x9b\r\xbc\x00\xba\x1fr\xa55\x9aF\xc9\u0080U\xc0\xe1\x0f\xca\x1f\xca\b\xce\xd8c\xfa\xb7\x85\x1fYB\xd7K^\xe3\x16\u009f\xb1Z\xc8=KP\xe6\xaa\x10r\xdf\x03\x8f_\x05\nK\x84\xb4\xa8\x1b\x8d\x96[\xa1\xe4\xf3-<~3\xa1\xb0\xa4T\xba~\u07b3\x12\xf7k\xa5k\x96X\xbe7\xcf\xdd\xc5\xc97\xfe\xa6o\xb7\xfd\x95GvtF\xbc\u0112\xb7\x95\x05a\xc0\x1e\x10HEh\r\x16P*\r\xc6\x16B\x02\x97\x05}R\xad\xcd\xe0\xeb\x03\x82Ak\x85\xdc\x1b(\xb0AY\x90\x14%\a\xeeZ\x15du\x10\xbc\x05g?|2u\xc0y\xfa\xfb\x14n:m\x8e#\u007f\xbe\x91\xa5\x82\x02K!\xd1\xc0A\xfd\x00\u070b\x15\x06\x9c\x9b\xb0p\n\xf5n\xc1\"\xb8\x98\x18\x9d\xb5\xee\x1bK\nn\xf9\xe0\x95s\xab[\x84\x1b(ye\x90%\x1aK\xd4(s4\xdb%\x98_\xe7\x95\aV8\x9dj\x82\xa0A\xb0X7\x15\xb7h\x80kt\x0f \xe95\xac\x82\x1dB+E)\x90\xde\x05\xb8u\xc1\xa0\x95\xb2\xa0J\xb0\aaHH\xaed)\xf6\xad\xbf!c\xee\x02\xf7^B6\xad\xf5q:D\r}\x1b\xe5\xc5y\x9a\xb7H\x11sI\xf4,\xcbX\x92\x1cY\x92Th\xe1\n.\xfc\xf1\xb1;f\xaf\x96L\xfc2\aI\xd2(\x86\xae\xd8p\xb5\t\xaa\xe4-E-\xa5\x9a\xc9L~\xc0\x9a\ae\x88\x17\xaf,J\xe3C\u009dN\xb3\xbf\x1a%\xd3\xf0m\x96\xc3d\ro\xad\xea\xcd9z\x96k^W\xf7e\xb9\x1f\u01d1\xf2>\xc1+\x8a\xaew:\xdcYp\x8b\xc7/?[\xf3y\xf0\xea\xf9\xaa\xcf\xe7\xe0\xdc\u75df\xbd\xc3\xeb\x94\u03c3\u03cf,Qmc\xbb\xc0\xf1Z={\xfa\xe1\xd5z\xf6\xf4\xbez\xe1\xf7T\t\xfe\xf7p\xbe\xfc\xe2\u01477\xe3\x8b\x17\xef0\xa3\x14\x94\xf6c;\n,\xff/3\x9e~\xfe\xe5\xb3\x0f\x9e\x9aN\xea=\xf3\xb3\xebu\xaf\xba4\x85\x9a7\u01b7\x95!u\xa9\x90\x85\xc2\xe8\xa1FSA\xb4\x82\xea\xe0,\xc3\xd3t\xdco/Y\x92\u0498\xd0\x13\xa9\xf3\x12\x81\r\x85`\xa0\x13\xa1\x03\xaa\x80\xf4@EHU\fLSD\u078a\x84\xe21H#\x02\xebK\xc4\n`\xaf\xec\x14\xb0xe\t\u062b\xc1:\a\xec\x15\x91\x1b\xad\xac\x1a\xeb\xeb\bN\x12^\xd9\x0e\xed%M\xd1\xddH\xe7\x01e\t5\x97\xaf^~\xb5\x052\xc4\xe0\u07de8R\x9au\f=\xd3N\xc8f\a\x9b\r\xec\x84\xe4\xfa\xba\xd9\xf5CC7*\x81\x90\x85\xc8}\u007f\xf2\x0fH\xd1\xc0\xadkr\x1a\x1b\x8d\x06%\r.\xc0\xe9i\xf7\x9a\xd7\x19\xeb\a\xad-<\xbaHS/R\xc2t\u0102\x02-\xeaz4\x91\xe4\xa8-\x17\xb2\x93\x03\xe6\xa0\u06aa\xa0>8\x99K6\x1bx\xad4t\xc3\xec\x13p\xb5\xa2\xe6\u05f3\x93\xc0\xa9'\x9b\\\x8b\x9d\xd7\xcfG\xf0\x13\xf8\xe1 \xf2\x03\bk\xb0*]\x0f\xe5\x92Xs%\xbfGm}\xf3\xe5\xf0\xe5_^\x05\x8e\x8c\u0366\xc3~\xe0s3\xe18h\x03\xbdt\xc3\xe9dx\uc1b0\xd9\u0216\x96J\xf9h\xf6#\xa7\xe7J\xfd\xc5ix\x0ez+\x9f]\xb9\xaak\x1a\xd4*!\u0453\xadZ\xe6\x15\x01.\xa3\xbc\x18\x9f\xcc^z/\x99Rx\xafys\x98\xa0\x8e\xe2\xc1\x82\xef'P\xc1\xf7\x1d`\xf9\f\xb1A\xa0\xab\x17?\xb2q5s\xc5\u0301d\xe5\x02\r\xa6\a\xb8Z\xc5+\u007f\x80Rl\x81\xbb\fu\xb0\v\xfe\x05\xee3\xc8\x1d\xe83dqhH5:\u84a5\xd9\xd1l\xecfv\x14\xf6\x80\x9a\x1c\xdd\xe5BH\x17\xe8D<\x015\xc1Y\xd2\xec\xb6p>\xbd\xc5\xff\xa5]\xa6\xa5l9\\\xa4t?\xdc\xc0\x1a\u38cb\xbbY\x1d9X\xb9j`\xda?\x98\xd3cx4/v\xc1\xe3\u0277r\xed\x17n\f\x06\xd26q\x9bqI\x1f\x99IRqw\u035e\x9c\x1ez#\xb1~\x10\xa9\xdd>\x16\xe4\xd2\xc8\xe6\xf1\x05\xbb\x9b\xe6V.\x9cLj!:\xc7\u0674\x104\x1cx\x1fq\xaaA\xc9\x1bq\x8b\xac\x80\xbe\x87 _\x1f\\\x83\xee\u05fb\u0428\xa9@\xf3\xaa\xf2`\x06o,\x14\n\rHeA\u023cj\v\xf4\u06e5\xd25\xbcy\x991w\xce)\xe4v[\xda\xe2/\xfa\x05\xb7\xaf_N{j\u0517k\xd5\x05z-\x83+\xe0\x06R7\x03\xb9O]u\x99\xad]\xf31k\xba\xbc\xcdg\x97\xe9\xaa8G\xa7K\xe3\xa7\x13\xf8w\xf0\u025c\u0092\xd9J9\x977].\xe7\xe8t\xa5\x9c\xa1G\xaa\xf3\xb2\x9bZ\xc7C\xd4\xc2_\xc1G\x8b\xfb\u05ad\x1a\xe4/\n\xf8\xf0\x00\xde\xd7\xe4u*\xdc\xfe\xbf\xcb\xdd\xd9\nO:/|\xbe\xee\xeb;\xb5\x99\xf9q\xdd\u007f\xeb~\x1b\xec\x99\xf4\x1c\x939\x1bF\xb6=\xba\x18B\xa8\xfb9a\xcc<\xeeK\xb4B\xec\xe7~yt\x11\xda\xd8T\xdbN\xad\xc9\xef\x17\xbd]\xe3\xdf-V\rX\xf5K\xaf\u05d1M\xa7\xea\xbeGvI0X0t\xc8a\t\x9ae\x8bO\x12\xb8\xe9\xdem\xbc\x02tz\x8c'\xffA\xf8\xd0>\xa7\u039d\xa8Ai\xe8%O;\xf2\xaa>\xfd\xc1\xa1\u7b1e\x1bt\x18\xb7\x9aw\x1c\xb5\xaa\xbe\xeb\xee\xe1\u0a25\xcfr\xec\xbd\u0180\x89\xf4[f\x82\xd1\v\xccm\xa1F\u007f\x97\x98q\xcf^\x932\xb4\xbc\x99\xf2\vC\x8fl\xda'\xeeQ\xab\xdd2\xe5\x9b\xe0\xf4\x96yW\xbb\u0541w\xf6\xaf\xf7\xe6Zu\xd6<\x9a\x8e,\x8a\xfe\x1b\x00\x00\xff\xff\x8e\xf7,\xe9\xbe\x16\x00\x00") +// Data size: 1708 bytes. +var cuegenInstanceData = []byte("\x01\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xc4X\xddo\xe4\xb6\x11\x97|W\xa0R\xd3>\xe6\xad\xc0\x9c\xae\bR\xe3*#\x1f@\x81\x05\x8cC\u047b+\xee\xa5)\x8a\xf4)\b\f\xae4\xdae#\x91*I%6\xe2}h\x9b\xa6\xfd\xab\xb3\u0150\x94(je\xfb\f\xa4\xa8_\xbc;?\xcepf8\x9f\xfb\xf3\xe3\xbf\xcf\u04b3\xe3\u007f\x92\xf4\xf8\x8f$\xf9\xed\xf1\xefO\xd2\xf4=.\xb4a\xa2\xc2W\xcc0\xa2\xa7O\u04a7\u007f\x96\u04a4gI\xfa\xf4O\xcc\xec\xd3\xf7\x92\xf4'ox\x8b:=~\x9f$\xc9/\x8f\xff:K\xd3_|\xf1e5`\xd9\xf0\xd6s~\x9f\xa4\xc7\xef\x92\xe4\xc3\xe3?\x9f\xa4\xe9O\x03\xfd\xbb$=K\x9f\xfe\x91uH\x82\x9eZb\x9e$\xc9\x0f\xef\xff\x8a4I\u04f34\xcd\xccM\x8f\xba\xac\x06L\u007fx\xffg=\xab\xbeb;\x84\xed\xc0\xdb:\xcf/.\xe0w@\xf7C%\x95B\xddKQk0\x12\x18\xfcA\xbaC%\xc1e\xfe\x9c\xfem\xe0\xdb<\xa3\xeb\x05\xebp\x03\xfeO\x1b\xc5\xc5.\xcfPT\xb2\xe6b7\x01\xcf_{J\x9eqaP\xf5\n\r3\\\x8a\x97\x1bx\xfe6\xa2\xe4Y#U\xf7rb%\xee7Ruyf\xd8N\xbf\xb4\x17g_\xb8\x9b\xbe\xdcLW\x1e\xf2\x835\xe2\x156lh\rp\rf\x8f@*\u00a0\xb1\x86F*\u0426\xe6\x02\x98\xa8\xe9\x93\x1cL\t\x9f\xef\x114\x1a\xc3\xc5NC\x8d=\x8a\x9a\xa4H\x11\xb8;Y\x93\xd5^\xf0\x06\xac\xfd\xf0A\xec\x80\xf3\xe27\x05\u070e\xda\x1cf\xfe|+\x1a\t56\\\xa0\x86\xbd\xfc\x06\x98\x13\xcb5X7am\x15\x9a\u0702\xb5w11Zk\xed\xb7<\xab\x99a\xc1+\xe7F\r\b\xb7\u0430Vc\x9e)lP\xa1\xa8PoN\xc1\xea\xa6j\x1d\xb0\xc2iU\xe3\xe4y:\xb1\x95\xb2\xcd3\xd9\xd3w\xd6:\x16G\xab\xa4\xd0F1.L8\xf7\x15b\xef\xfd\xa27\x9e\xc6E%\xbb\xbeEc\xc3\xc2\u04fa^*3j\xe0h\xda(d\u0768\x94\xa3\u0572\xd2\xc1DGc\xc6(\xbe\x1d\x8c3\xc0\u049c{\xe9]4=\x1e=\x9c\xd3\xc1>r\xcd\x1b\xeb\v\x03\xb2G\u015c%\xeet\x99_\\\x10\xeb\xe7{\xd4\b\x06\xbb\xbee\x0650\x85\xf6\x01\x04\xbd\x86\x91\xb0E\x18\x04o8\u04bb\x0036\x18\x94\x94\x06d\x03f\xcf5\t\xa9\xa4h\xf8np7\x94\xb9\xbd\xc0\xbe\x17\x17\xfd`\\\x9c\xb6h\xe0\x1a.\xed\xe7\u023a\xc5#d\x91\x99K\xf0\x90gY\x88?++d\xd8yQ\rH\xb1wE\xf4\xb2,G\x86\x10C\xd7y`\xd0^@5P\xd4R\xaa\xe9RW{\xec\x98\x17A\xbcxmPh\x17\x12\xf6tQ\xfeUKQ\xf8o\x8b\x1c&\x1d\xd8`\xe4\xa4\xc4\xc1\xb1\u0730\xae},\xcb\xe38\x0e\x94\xf7\x19^St\xcd\x1c~\xf5\u045a\u02fdS\xcfW]\xbe\x04\x1fp\xb9\xf5\xc6\xfd>\xbf\xfa\xe8\x01\xafS>\a\x9f\x1f\xf2L\x0e\xbd\x89\x02\xe7\xea\xe3\x1f\u01ce\xb9V\x1f?V+\xfc\x9a\xea@\xd0\xe9\x93\xff\xb5o\x1f\x0e\xe7\xabO\x1e0\xa2\xe1\x94\xf2s+jl\xe6F|\xfa\xff\xcf\u026bO\x1f\x99\x95c\x87{=&'t\xac\u05ee\x99\x84\x84\xa5\xf2\xe5\u02e1\x83zEe\xd0p\xaa~\x8b\xbc.\x8ay\x97\xbd\u02b3\x82\x86\x83\x89H\xfd\x96\byH\xff@'\xc2\b\xb4\x1e\x99\x80\x96\x90\xb6\x0eL1\"\xeeD|\xc9\b\u0488\x90O\x85a\x050\xd7&\x06\f^\x1b\x02v2Xg\x81\x9d$r\xaf\xa4\x91s}-\xc1J\xc2k3\xa2\x93\xa4\x18\xdd\xcet\x0eh\x9eQK\xf9\xec\xd5g\x1b C4\xfe\xed\x85%\x15\xe5\xc801m\xb9\xe8\xb7pq\x01[.\x98\xba\xe9\xb7\u04e80\x0eH\xc0E\xcd+\u05d5\xdc\x03R40c[\x9b\xc2^\xa1FA\xe3\n0z\u069db]\x99O\xe3\xd5\x06\x9e]\x16\x85\x13) \x1e\xac\xa0F\x83\xaa\x9b\xcd!\x15*\u00f8\x18\xe5\x80\xde\u02e1\xad\xa9\xfbE\xd3\xc8\xc5\x05\xbc\x91\n\xc6\x11\xf6\x05\xd8\x1a\u0471\x9b\xc5I`\u0509u\xa5\xf8\xd6\xe9\xe7\"\xf8\x05|\xb3\xe7\xd5\x1e\xb8\xd1\xd86\xb6s2A\xac\x95\x14_\xa32\xae\xe52\xf8\xfd_^{\x8e2_\u0304\u04d8g'\xc1y\xd0zzcG\xd2hd\x1cG\xaf\u0160V4R\xbahv\x83\xa6\xe3*\xdc\u0145\u007f\x0ez+\x97]\x95\xec:\x1a\xcfZ.\u0411\x8d<\xcd+\x02lF91.\x99\x9d\xf4I2\xa5\xf0N\xb1~\x1f\xa1\x96\xe2\xc0\x9a\xed\"\xa8f\xbb\x110l\x81\x18/\xd0\u058bo\xf3y\xed\xb1\xa5\u01c2d\xe5\t\xeaM\xf7p\xbb\x8a\xb7\xee\x00\xa5\xd8\tn3\xd4\xc26\xf8Op\x97A\xf6\xc0\x94!'\x87B\xaa\xd1A\x9b,\xfd\x96&b;\xa9#7{T\xe4\xe81\x17|\xba\xc0(\xe2\x05\xc8\b\u03f3~\xbb\x81\xf3\xf8\x16\xf7W\x8c\x99V\xe4\xa7#EA\xf7\xc3-\xac1>\xbb\xbc\x9f\u0552\xbd\x95\xab\x06\x16\u04c3Y=\u00a39\xb1'<\x8e|'\xd7\xee\u010d\xde@\xda!\xee2.\x9b\"3\xcbZf\xaf\u0651\xd3}W$\xd6\x1fE\uae05y\xb94\xa89\xfc\x84\xdd\xcep+\x17F3\x95\x8f\xcey6\x9d\b\n\a\xdeE\x9c\xecQ\xb0\x9e\xdf!\u02e3\xef \xc8\xd5\a\u06e0\xa7\xa5\xce7j*\u042cm\x1dX\xc2[\x03\xb5D\rB\x1a\xe0\xa2j\x87\x1a\xddN)U\ao_\x95\xb9=g\x15\xb2\x1b-\xed\xee\x97\xd3Z;\xd5/\xab=5\uaaf5\xea\x02\x93\x96\xde\x15p\v\x85\x9d~\uc9f1\xba,\x96\xad\xe5@\x16\xafl\xcbI'^\x10\x97h\xbc*~\x18\xc1\xbf\x86\x0f\x96\x94<[,\x92Ky\xf1J\xb9D\xe3Er\x81\x1e\xa8\u038bqZ\x9d\x0fQ'\xfe\xf2>:\xb9o\u076a \xff\xa4\x80\x87\ap\xbe&\xafS\xe1v\xffm\xee.\x16w\xd2\xf9\xc4\xe7\ubfbeW\x9b\x85\x1f\xd7\xfd\xb7\xee\xb7`O\xd4stim\x98\xd9\xf6\xec2\x84\xd0\xf8#\u009cy\u0797hu\xd8-\xfd\xf2\xec\u04b7\xb1X\xdbQ\xad\xe8W\x8b\u026e\xf9\xaf\x15\xab\x06\xac\xfae\xd2\xeb\x90\xc7S\xf5\xd4#\xc7$\b\x16\x84\x0e\x19\x96\x9fE\xb6\xb8$\x81\xdb\xf1\xdd\xe6\v\u00e8\xc7|O\b\xc2C\xfb\x8c\x9d\x1b\xa9Ai\xe8$\xc7\x1dyU\x9f\xe9`\xe89\xab\xe7\x82\x0e\xf3V\xf3\xc0Q#\xbb\xfb\xee\x0e\ag-}\x91c\xef4\x06D\xd2\xef\x98\tf/\xb0\xb4\x85\x1a\xfd}b\xe6={MJhy\v\xe5O\f=\xe4q\x9fxD\xad\xb6\u02d4k\x82\xf1-\u02eev\xa7\x03\xef\xed_\xef\u0335\xea\xace4\x1d\xf2$\xf9o\x00\x00\x00\xff\xff\x85i\xbeS\xb4\x16\x00\x00")