1package ast
2
3import (
4 "fmt"
5 "strconv"
6 "strings"
7)
8
9type ValueKind int
10
11const (
12 Variable ValueKind = iota
13 IntValue
14 FloatValue
15 StringValue
16 BlockValue
17 BooleanValue
18 NullValue
19 EnumValue
20 ListValue
21 ObjectValue
22)
23
24type Value struct {
25 Raw string
26 Children ChildValueList
27 Kind ValueKind
28 Position *Position `dump:"-"`
29
30 // Require validation
31 Definition *Definition
32 VariableDefinition *VariableDefinition
33 ExpectedType *Type
34}
35
36type ChildValue struct {
37 Name string
38 Value *Value
39 Position *Position `dump:"-"`
40}
41
42func (v *Value) Value(vars map[string]interface{}) (interface{}, error) {
43 if v == nil {
44 return nil, nil
45 }
46 switch v.Kind {
47 case Variable:
48 if value, ok := vars[v.Raw]; ok {
49 return value, nil
50 }
51 if v.VariableDefinition != nil && v.VariableDefinition.DefaultValue != nil {
52 return v.VariableDefinition.DefaultValue.Value(vars)
53 }
54 return nil, nil
55 case IntValue:
56 return strconv.ParseInt(v.Raw, 10, 64)
57 case FloatValue:
58 return strconv.ParseFloat(v.Raw, 64)
59 case StringValue, BlockValue, EnumValue:
60 return v.Raw, nil
61 case BooleanValue:
62 return strconv.ParseBool(v.Raw)
63 case NullValue:
64 return nil, nil
65 case ListValue:
66 var val []interface{}
67 for _, elem := range v.Children {
68 elemVal, err := elem.Value.Value(vars)
69 if err != nil {
70 return val, err
71 }
72 val = append(val, elemVal)
73 }
74 return val, nil
75 case ObjectValue:
76 val := map[string]interface{}{}
77 for _, elem := range v.Children {
78 elemVal, err := elem.Value.Value(vars)
79 if err != nil {
80 return val, err
81 }
82 val[elem.Name] = elemVal
83 }
84 return val, nil
85 default:
86 panic(fmt.Errorf("unknown value kind %d", v.Kind))
87 }
88}
89
90func (v *Value) String() string {
91 if v == nil {
92 return "<nil>"
93 }
94 switch v.Kind {
95 case Variable:
96 return "$" + v.Raw
97 case IntValue, FloatValue, EnumValue, BooleanValue, NullValue:
98 return v.Raw
99 case StringValue, BlockValue:
100 return strconv.Quote(v.Raw)
101 case ListValue:
102 var val []string
103 for _, elem := range v.Children {
104 val = append(val, elem.Value.String())
105 }
106 return "[" + strings.Join(val, ",") + "]"
107 case ObjectValue:
108 var val []string
109 for _, elem := range v.Children {
110 val = append(val, elem.Name+":"+elem.Value.String())
111 }
112 return "{" + strings.Join(val, ",") + "}"
113 default:
114 panic(fmt.Errorf("unknown value kind %d", v.Kind))
115 }
116}
117
118func (v *Value) Dump() string {
119 return v.String()
120}