|
6 | 6 |
|
7 | 7 | "github.com/expr-lang/expr/ast" |
8 | 8 | "github.com/expr-lang/expr/builtin" |
| 9 | + "github.com/expr-lang/expr/checker" |
9 | 10 | "github.com/expr-lang/expr/conf" |
10 | 11 | "github.com/expr-lang/expr/file" |
11 | 12 | "github.com/expr-lang/expr/parser" |
@@ -34,6 +35,7 @@ func Compile(tree *parser.Tree, config *conf.Config) (program *Program, err erro |
34 | 35 | if config != nil { |
35 | 36 | c.mapEnv = config.MapEnv |
36 | 37 | c.cast = config.Expect |
| 38 | + c.types = config.Types |
37 | 39 | } |
38 | 40 |
|
39 | 41 | c.compile(tree.Node) |
@@ -75,6 +77,7 @@ type compiler struct { |
75 | 77 | nodes []ast.Node |
76 | 78 | chains [][]int |
77 | 79 | arguments []int |
| 80 | + types conf.TypesTable |
78 | 81 | } |
79 | 82 |
|
80 | 83 | type scope struct { |
@@ -254,15 +257,15 @@ func (c *compiler) IdentifierNode(node *ast.IdentifierNode) { |
254 | 257 | } |
255 | 258 | if c.mapEnv { |
256 | 259 | c.emit(OpLoadFast, c.addConstant(node.Value)) |
257 | | - } else if len(node.FieldIndex) > 0 { |
| 260 | + } else if ok, index, name := checker.FieldIndex(c.types, node); ok { |
258 | 261 | c.emit(OpLoadField, c.addConstant(&runtime.Field{ |
259 | | - Index: node.FieldIndex, |
260 | | - Path: []string{node.Value}, |
| 262 | + Index: index, |
| 263 | + Path: []string{name}, |
261 | 264 | })) |
262 | | - } else if node.Method { |
| 265 | + } else if ok, index, name := checker.MethodIndex(c.types, node); ok { |
263 | 266 | c.emit(OpLoadMethod, c.addConstant(&runtime.Method{ |
264 | | - Name: node.Value, |
265 | | - Index: node.MethodIndex, |
| 267 | + Name: name, |
| 268 | + Index: index, |
266 | 269 | })) |
267 | 270 | } else { |
268 | 271 | c.emit(OpLoadConst, c.addConstant(node.Value)) |
@@ -559,36 +562,43 @@ func (c *compiler) ChainNode(node *ast.ChainNode) { |
559 | 562 | } |
560 | 563 |
|
561 | 564 | func (c *compiler) MemberNode(node *ast.MemberNode) { |
562 | | - if node.Method { |
| 565 | + if ok, index, name := checker.MethodIndex(c.types, node); ok { |
563 | 566 | c.compile(node.Node) |
564 | 567 | c.emit(OpMethod, c.addConstant(&runtime.Method{ |
565 | | - Name: node.Name, |
566 | | - Index: node.MethodIndex, |
| 568 | + Name: name, |
| 569 | + Index: index, |
567 | 570 | })) |
568 | 571 | return |
569 | 572 | } |
570 | 573 | op := OpFetch |
571 | | - index := node.FieldIndex |
572 | | - path := []string{node.Name} |
573 | 574 | base := node.Node |
574 | | - if len(node.FieldIndex) > 0 { |
| 575 | + |
| 576 | + ok, index, nodeName := checker.FieldIndex(c.types, node) |
| 577 | + path := []string{nodeName} |
| 578 | + |
| 579 | + if ok { |
575 | 580 | op = OpFetchField |
576 | 581 | for !node.Optional { |
577 | | - ident, ok := base.(*ast.IdentifierNode) |
578 | | - if ok && len(ident.FieldIndex) > 0 { |
579 | | - index = append(ident.FieldIndex, index...) |
580 | | - path = append([]string{ident.Value}, path...) |
581 | | - c.emitLocation(ident.Location(), OpLoadField, c.addConstant( |
582 | | - &runtime.Field{Index: index, Path: path}, |
583 | | - )) |
584 | | - return |
| 582 | + if ident, isIdent := base.(*ast.IdentifierNode); isIdent { |
| 583 | + if ok, identIndex, name := checker.FieldIndex(c.types, ident); ok { |
| 584 | + index = append(identIndex, index...) |
| 585 | + path = append([]string{name}, path...) |
| 586 | + c.emitLocation(ident.Location(), OpLoadField, c.addConstant( |
| 587 | + &runtime.Field{Index: index, Path: path}, |
| 588 | + )) |
| 589 | + return |
| 590 | + } |
585 | 591 | } |
586 | | - member, ok := base.(*ast.MemberNode) |
587 | | - if ok && len(member.FieldIndex) > 0 { |
588 | | - index = append(member.FieldIndex, index...) |
589 | | - path = append([]string{member.Name}, path...) |
590 | | - node = member |
591 | | - base = member.Node |
| 592 | + |
| 593 | + if member, isMember := base.(*ast.MemberNode); isMember { |
| 594 | + if ok, memberIndex, name := checker.FieldIndex(c.types, member); ok { |
| 595 | + index = append(memberIndex, index...) |
| 596 | + path = append([]string{name}, path...) |
| 597 | + node = member |
| 598 | + base = member.Node |
| 599 | + } else { |
| 600 | + break |
| 601 | + } |
592 | 602 | } else { |
593 | 603 | break |
594 | 604 | } |
|
0 commit comments