@@ -15,11 +15,11 @@ import (
15
15
)
16
16
17
17
func Compile (tree * parser.Tree , config * conf.Config ) (program * Program , err error ) {
18
- // defer func() {
19
- // if r := recover(); r != nil {
20
- // err = fmt.Errorf("%v", r)
21
- // }
22
- // }()
18
+ defer func () {
19
+ if r := recover (); r != nil {
20
+ err = fmt .Errorf ("%v" , r )
21
+ }
22
+ }()
23
23
24
24
c := & compiler {
25
25
index : make (map [interface {}]uint16 ),
@@ -74,6 +74,14 @@ func (c *compiler) emit(op byte, b ...byte) int {
74
74
return current
75
75
}
76
76
77
+ func (c * compiler ) emitLoc (node ast.Node , op byte , b ... byte ) int {
78
+ c .bytecode = append (c .bytecode , op )
79
+ current := len (c .bytecode )
80
+ c .bytecode = append (c .bytecode , b ... )
81
+ c .locations [current - 1 ] = node .Location ()
82
+ return current
83
+ }
84
+
77
85
func (c * compiler ) emitPush (value interface {}) int {
78
86
return c .emit (OpPush , c .makeConstant (value )... )
79
87
}
@@ -418,21 +426,53 @@ func (c *compiler) ChainNode(node *ast.ChainNode) {
418
426
}
419
427
420
428
func (c * compiler ) MemberNode (node * ast.MemberNode ) {
421
- c .compile (node .Node )
429
+ op := OpFetch
430
+ original := node
431
+ index := node .Index
432
+ path := node .Name
433
+ base := node .Node
434
+ if len (node .Index ) > 0 {
435
+ op = OpFetchField
436
+ for ! node .Optional {
437
+ ident , ok := base .(* ast.IdentifierNode )
438
+ if ok && len (ident .Index ) > 0 {
439
+ if ident .Deref {
440
+ panic ("IdentifierNode should not be dereferenced" )
441
+ }
442
+ index = append (ident .Index , index ... )
443
+ path = ident .Value + "." + path
444
+ op = OpFetchEnvField
445
+ goto emit
446
+ }
447
+ member , ok := base .(* ast.MemberNode )
448
+ if ok && len (member .Index ) > 0 {
449
+ if member .Deref {
450
+ panic ("MemberNode should not be dereferenced" )
451
+ }
452
+ index = append (member .Index , index ... )
453
+ path = member .Name + "." + path
454
+ node = member
455
+ base = member .Node
456
+ } else {
457
+ break
458
+ }
459
+ }
460
+ }
461
+
462
+ c .compile (base )
422
463
if node .Optional {
423
464
ph := c .emit (OpJumpIfNil , c .placeholder ()... )
424
465
c .chains [len (c .chains )- 1 ] = append (c .chains [len (c .chains )- 1 ], ph )
425
466
}
426
- if len (node .Index ) > 0 {
427
- c .emit (OpFetchField , c .makeConstant (& runtime.Field {
428
- Index : node .Index ,
429
- Path : node .Name ,
430
- })... )
431
- } else {
467
+
468
+ emit:
469
+ if op == OpFetch {
432
470
c .compile (node .Property )
433
471
c .emit (OpFetch )
472
+ } else {
473
+ c .emitLoc (node , op , c .makeConstant (& runtime.Field {Index : index , Path : path })... )
434
474
}
435
- if node .Deref {
475
+ if original .Deref {
436
476
c .emit (OpDeref )
437
477
}
438
478
}
0 commit comments