(node *Node)
| 18 | } |
| 19 | |
| 20 | func (c *constExpr) Visit(node *Node) { |
| 21 | defer func() { |
| 22 | if r := recover(); r != nil { |
| 23 | msg := fmt.Sprintf("%v", r) |
| 24 | // Make message more actual, it's a runtime error, but at compile step. |
| 25 | msg = strings.Replace(msg, "runtime error:", "compile error:", 1) |
| 26 | c.err = &file.Error{ |
| 27 | Location: (*node).Location(), |
| 28 | Message: msg, |
| 29 | } |
| 30 | } |
| 31 | }() |
| 32 | |
| 33 | if call, ok := (*node).(*CallNode); ok { |
| 34 | if name, ok := call.Callee.(*IdentifierNode); ok { |
| 35 | fn, ok := c.fns[name.Value] |
| 36 | if ok { |
| 37 | in := make([]reflect.Value, len(call.Arguments)) |
| 38 | for i := 0; i < len(call.Arguments); i++ { |
| 39 | arg := call.Arguments[i] |
| 40 | var param any |
| 41 | |
| 42 | switch a := arg.(type) { |
| 43 | case *NilNode: |
| 44 | param = nil |
| 45 | case *IntegerNode: |
| 46 | param = a.Value |
| 47 | case *FloatNode: |
| 48 | param = a.Value |
| 49 | case *BoolNode: |
| 50 | param = a.Value |
| 51 | case *StringNode: |
| 52 | param = a.Value |
| 53 | case *ConstantNode: |
| 54 | param = a.Value |
| 55 | |
| 56 | default: |
| 57 | return // Const expr optimization not applicable. |
| 58 | } |
| 59 | |
| 60 | if param == nil && reflect.TypeOf(param) == nil { |
| 61 | // In case of nil value and nil type use this hack, |
| 62 | // otherwise reflect.Call will panic on zero value. |
| 63 | in[i] = reflect.ValueOf(¶m).Elem() |
| 64 | } else { |
| 65 | in[i] = reflect.ValueOf(param) |
| 66 | } |
| 67 | } |
| 68 | |
| 69 | out := fn.Call(in) |
| 70 | value := out[0].Interface() |
| 71 | if len(out) == 2 && out[1].Type() == errorType && !out[1].IsNil() { |
| 72 | c.err = out[1].Interface().(error) |
| 73 | return |
| 74 | } |
| 75 | constNode := &ConstantNode{Value: value} |
| 76 | patchWithType(node, constNode) |
| 77 | c.applied = true |
nothing calls this directly
no test coverage detected