summaryrefslogtreecommitdiff
path: root/vendor/github.com/hashicorp/hil/ast/literal.go
blob: da6014fee2ba954fd286ffb2b75c4ed460b29d77 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package ast

import (
	"fmt"
	"reflect"
)

// LiteralNode represents a single literal value, such as "foo" or
// 42 or 3.14159. Based on the Type, the Value can be safely cast.
type LiteralNode struct {
	Value interface{}
	Typex Type
	Posx  Pos
}

// NewLiteralNode returns a new literal node representing the given
// literal Go value, which must correspond to one of the primitive types
// supported by HIL. Lists and maps cannot currently be constructed via
// this function.
//
// If an inappropriately-typed value is provided, this function will
// return an error. The main intended use of this function is to produce
// "synthetic" literals from constants in code, where the value type is
// well known at compile time. To easily store these in global variables,
// see also MustNewLiteralNode.
func NewLiteralNode(value interface{}, pos Pos) (*LiteralNode, error) {
	goType := reflect.TypeOf(value)
	var hilType Type

	switch goType.Kind() {
	case reflect.Bool:
		hilType = TypeBool
	case reflect.Int:
		hilType = TypeInt
	case reflect.Float64:
		hilType = TypeFloat
	case reflect.String:
		hilType = TypeString
	default:
		return nil, fmt.Errorf("unsupported literal node type: %T", value)
	}

	return &LiteralNode{
		Value: value,
		Typex: hilType,
		Posx:  pos,
	}, nil
}

// MustNewLiteralNode wraps NewLiteralNode and panics if an error is
// returned, thus allowing valid literal nodes to be easily assigned to
// global variables.
func MustNewLiteralNode(value interface{}, pos Pos) *LiteralNode {
	node, err := NewLiteralNode(value, pos)
	if err != nil {
		panic(err)
	}
	return node
}

func (n *LiteralNode) Accept(v Visitor) Node {
	return v(n)
}

func (n *LiteralNode) Pos() Pos {
	return n.Posx
}

func (n *LiteralNode) GoString() string {
	return fmt.Sprintf("*%#v", *n)
}

func (n *LiteralNode) String() string {
	return fmt.Sprintf("Literal(%s, %v)", n.Typex, n.Value)
}

func (n *LiteralNode) Type(Scope) (Type, error) {
	return n.Typex, nil
}

// IsUnknown returns true either if the node's value is itself unknown
// of if it is a collection containing any unknown elements, deeply.
func (n *LiteralNode) IsUnknown() bool {
	return IsUnknown(Variable{
		Type:  n.Typex,
		Value: n.Value,
	})
}