1package ast 2 3import ( 4 "fmt" 5 "reflect" 6) 7 8// LiteralNode represents a single literal value, such as "foo" or 9// 42 or 3.14159. Based on the Type, the Value can be safely cast. 10type LiteralNode struct { 11 Value interface{} 12 Typex Type 13 Posx Pos 14} 15 16// NewLiteralNode returns a new literal node representing the given 17// literal Go value, which must correspond to one of the primitive types 18// supported by HIL. Lists and maps cannot currently be constructed via 19// this function. 20// 21// If an inappropriately-typed value is provided, this function will 22// return an error. The main intended use of this function is to produce 23// "synthetic" literals from constants in code, where the value type is 24// well known at compile time. To easily store these in global variables, 25// see also MustNewLiteralNode. 26func NewLiteralNode(value interface{}, pos Pos) (*LiteralNode, error) { 27 goType := reflect.TypeOf(value) 28 var hilType Type 29 30 switch goType.Kind() { 31 case reflect.Bool: 32 hilType = TypeBool 33 case reflect.Int: 34 hilType = TypeInt 35 case reflect.Float64: 36 hilType = TypeFloat 37 case reflect.String: 38 hilType = TypeString 39 default: 40 return nil, fmt.Errorf("unsupported literal node type: %T", value) 41 } 42 43 return &LiteralNode{ 44 Value: value, 45 Typex: hilType, 46 Posx: pos, 47 }, nil 48} 49 50// MustNewLiteralNode wraps NewLiteralNode and panics if an error is 51// returned, thus allowing valid literal nodes to be easily assigned to 52// global variables. 53func MustNewLiteralNode(value interface{}, pos Pos) *LiteralNode { 54 node, err := NewLiteralNode(value, pos) 55 if err != nil { 56 panic(err) 57 } 58 return node 59} 60 61func (n *LiteralNode) Accept(v Visitor) Node { 62 return v(n) 63} 64 65func (n *LiteralNode) Pos() Pos { 66 return n.Posx 67} 68 69func (n *LiteralNode) GoString() string { 70 return fmt.Sprintf("*%#v", *n) 71} 72 73func (n *LiteralNode) String() string { 74 return fmt.Sprintf("Literal(%s, %v)", n.Typex, n.Value) 75} 76 77func (n *LiteralNode) Type(Scope) (Type, error) { 78 return n.Typex, nil 79} 80 81// IsUnknown returns true either if the node's value is itself unknown 82// of if it is a collection containing any unknown elements, deeply. 83func (n *LiteralNode) IsUnknown() bool { 84 return IsUnknown(Variable{ 85 Type: n.Typex, 86 Value: n.Value, 87 }) 88} 89