aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/vektah/gqlparser/ast
diff options
context:
space:
mode:
authorMichael Muré <batolettre@gmail.com>2018-09-14 12:40:31 +0200
committerMichael Muré <batolettre@gmail.com>2018-09-14 12:41:59 +0200
commitb478cd1bcb4756b20f7f4b15fcf81f23e1a60a02 (patch)
tree8ce232dcab3dd00708f8ba66c334472457e5980d /vendor/github.com/vektah/gqlparser/ast
parenta3fc9abb921f5ce7084d6ab7473442d0b72b1d78 (diff)
downloadgit-bug-b478cd1bcb4756b20f7f4b15fcf81f23e1a60a02.tar.gz
graphql: update gqlgen to 0.5.1
fix #6
Diffstat (limited to 'vendor/github.com/vektah/gqlparser/ast')
-rw-r--r--vendor/github.com/vektah/gqlparser/ast/argmap.go37
-rw-r--r--vendor/github.com/vektah/gqlparser/ast/collections.go138
-rw-r--r--vendor/github.com/vektah/gqlparser/ast/definition.go92
-rw-r--r--vendor/github.com/vektah/gqlparser/ast/directive.go42
-rw-r--r--vendor/github.com/vektah/gqlparser/ast/document.go65
-rw-r--r--vendor/github.com/vektah/gqlparser/ast/dumper.go159
-rw-r--r--vendor/github.com/vektah/gqlparser/ast/fragment.go38
-rw-r--r--vendor/github.com/vektah/gqlparser/ast/operation.go29
-rw-r--r--vendor/github.com/vektah/gqlparser/ast/selection.go39
-rw-r--r--vendor/github.com/vektah/gqlparser/ast/source.go14
-rw-r--r--vendor/github.com/vektah/gqlparser/ast/type.go68
-rw-r--r--vendor/github.com/vektah/gqlparser/ast/value.go120
12 files changed, 841 insertions, 0 deletions
diff --git a/vendor/github.com/vektah/gqlparser/ast/argmap.go b/vendor/github.com/vektah/gqlparser/ast/argmap.go
new file mode 100644
index 00000000..43f6a3d6
--- /dev/null
+++ b/vendor/github.com/vektah/gqlparser/ast/argmap.go
@@ -0,0 +1,37 @@
+package ast
+
+func arg2map(defs ArgumentDefinitionList, args ArgumentList, vars map[string]interface{}) map[string]interface{} {
+ result := map[string]interface{}{}
+ var err error
+
+ for _, argDef := range defs {
+ var val interface{}
+ var hasValue bool
+
+ if argValue := args.ForName(argDef.Name); argValue != nil {
+ if argValue.Value.Kind == Variable {
+ val, hasValue = vars[argValue.Value.Raw]
+ } else {
+ val, err = argValue.Value.Value(vars)
+ if err != nil {
+ panic(err)
+ }
+ hasValue = true
+ }
+ }
+
+ if !hasValue && argDef.DefaultValue != nil {
+ val, err = argDef.DefaultValue.Value(vars)
+ if err != nil {
+ panic(err)
+ }
+ hasValue = true
+ }
+
+ if hasValue {
+ result[argDef.Name] = val
+ }
+ }
+
+ return result
+}
diff --git a/vendor/github.com/vektah/gqlparser/ast/collections.go b/vendor/github.com/vektah/gqlparser/ast/collections.go
new file mode 100644
index 00000000..6bf67297
--- /dev/null
+++ b/vendor/github.com/vektah/gqlparser/ast/collections.go
@@ -0,0 +1,138 @@
+package ast
+
+type FieldList []*FieldDefinition
+
+func (l FieldList) ForName(name string) *FieldDefinition {
+ for _, it := range l {
+ if it.Name == name {
+ return it
+ }
+ }
+ return nil
+}
+
+type EnumValueList []*EnumValueDefinition
+
+func (l EnumValueList) ForName(name string) *EnumValueDefinition {
+ for _, it := range l {
+ if it.Name == name {
+ return it
+ }
+ }
+ return nil
+}
+
+type DirectiveList []*Directive
+
+func (l DirectiveList) ForName(name string) *Directive {
+ for _, it := range l {
+ if it.Name == name {
+ return it
+ }
+ }
+ return nil
+}
+
+type OperationList []*OperationDefinition
+
+func (l OperationList) ForName(name string) *OperationDefinition {
+ if name == "" && len(l) == 1 {
+ return l[0]
+ }
+ for _, it := range l {
+ if it.Name == name {
+ return it
+ }
+ }
+ return nil
+}
+
+type FragmentDefinitionList []*FragmentDefinition
+
+func (l FragmentDefinitionList) ForName(name string) *FragmentDefinition {
+ for _, it := range l {
+ if it.Name == name {
+ return it
+ }
+ }
+ return nil
+}
+
+type VariableDefinitionList []*VariableDefinition
+
+func (l VariableDefinitionList) ForName(name string) *VariableDefinition {
+ for _, it := range l {
+ if it.Variable == name {
+ return it
+ }
+ }
+ return nil
+}
+
+type ArgumentList []*Argument
+
+func (l ArgumentList) ForName(name string) *Argument {
+ for _, it := range l {
+ if it.Name == name {
+ return it
+ }
+ }
+ return nil
+}
+
+type ArgumentDefinitionList []*ArgumentDefinition
+
+func (l ArgumentDefinitionList) ForName(name string) *ArgumentDefinition {
+ for _, it := range l {
+ if it.Name == name {
+ return it
+ }
+ }
+ return nil
+}
+
+type SchemaDefinitionList []*SchemaDefinition
+
+type DirectiveDefinitionList []*DirectiveDefinition
+
+func (l DirectiveDefinitionList) ForName(name string) *DirectiveDefinition {
+ for _, it := range l {
+ if it.Name == name {
+ return it
+ }
+ }
+ return nil
+}
+
+type DefinitionList []*Definition
+
+func (l DefinitionList) ForName(name string) *Definition {
+ for _, it := range l {
+ if it.Name == name {
+ return it
+ }
+ }
+ return nil
+}
+
+type OperationTypeDefinitionList []*OperationTypeDefinition
+
+func (l OperationTypeDefinitionList) ForType(name string) *OperationTypeDefinition {
+ for _, it := range l {
+ if it.Type == name {
+ return it
+ }
+ }
+ return nil
+}
+
+type ChildValueList []*ChildValue
+
+func (v ChildValueList) ForName(name string) *Value {
+ for _, f := range v {
+ if f.Name == name {
+ return f.Value
+ }
+ }
+ return nil
+}
diff --git a/vendor/github.com/vektah/gqlparser/ast/definition.go b/vendor/github.com/vektah/gqlparser/ast/definition.go
new file mode 100644
index 00000000..74f4ece5
--- /dev/null
+++ b/vendor/github.com/vektah/gqlparser/ast/definition.go
@@ -0,0 +1,92 @@
+package ast
+
+type DefinitionKind string
+
+const (
+ Scalar DefinitionKind = "SCALAR"
+ Object DefinitionKind = "OBJECT"
+ Interface DefinitionKind = "INTERFACE"
+ Union DefinitionKind = "UNION"
+ Enum DefinitionKind = "ENUM"
+ InputObject DefinitionKind = "INPUT_OBJECT"
+)
+
+// ObjectDefinition is the core type definition object, it includes all of the definable types
+// but does *not* cover schema or directives.
+//
+// @vektah: Javascript implementation has different types for all of these, but they are
+// more similar than different and don't define any behaviour. I think this style of
+// "some hot" struct works better, at least for go.
+//
+// Type extensions are also represented by this same struct.
+type Definition struct {
+ Kind DefinitionKind
+ Description string
+ Name string
+ Directives DirectiveList
+ Interfaces []string // object and input object
+ Fields FieldList // object and input object
+ Types []string // union
+ EnumValues EnumValueList // enum
+
+ Position *Position `dump:"-"`
+}
+
+func (d *Definition) IsLeafType() bool {
+ return d.Kind == Enum || d.Kind == Scalar
+}
+
+func (d *Definition) IsAbstractType() bool {
+ return d.Kind == Interface || d.Kind == Union
+}
+
+func (d *Definition) IsCompositeType() bool {
+ return d.Kind == Object || d.Kind == Interface || d.Kind == Union
+}
+
+func (d *Definition) IsInputType() bool {
+ return d.Kind == Scalar || d.Kind == Enum || d.Kind == InputObject
+}
+
+func (d *Definition) OneOf(types ...string) bool {
+ for _, t := range types {
+ if d.Name == t {
+ return true
+ }
+ }
+ return false
+}
+
+type FieldDefinition struct {
+ Description string
+ Name string
+ Arguments ArgumentDefinitionList // only for objects
+ DefaultValue *Value // only for input objects
+ Type *Type
+ Directives DirectiveList
+ Position *Position `dump:"-"`
+}
+
+type ArgumentDefinition struct {
+ Description string
+ Name string
+ DefaultValue *Value
+ Type *Type
+ Directives DirectiveList
+ Position *Position `dump:"-"`
+}
+
+type EnumValueDefinition struct {
+ Description string
+ Name string
+ Directives DirectiveList
+ Position *Position `dump:"-"`
+}
+
+type DirectiveDefinition struct {
+ Description string
+ Name string
+ Arguments ArgumentDefinitionList
+ Locations []DirectiveLocation
+ Position *Position `dump:"-"`
+}
diff --git a/vendor/github.com/vektah/gqlparser/ast/directive.go b/vendor/github.com/vektah/gqlparser/ast/directive.go
new file mode 100644
index 00000000..9b07c92a
--- /dev/null
+++ b/vendor/github.com/vektah/gqlparser/ast/directive.go
@@ -0,0 +1,42 @@
+package ast
+
+type DirectiveLocation string
+
+const (
+ // Executable
+ LocationQuery DirectiveLocation = `QUERY`
+ LocationMutation DirectiveLocation = `MUTATION`
+ LocationSubscription DirectiveLocation = `SUBSCRIPTION`
+ LocationField DirectiveLocation = `FIELD`
+ LocationFragmentDefinition DirectiveLocation = `FRAGMENT_DEFINITION`
+ LocationFragmentSpread DirectiveLocation = `FRAGMENT_SPREAD`
+ LocationInlineFragment DirectiveLocation = `INLINE_FRAGMENT`
+
+ // Type System
+ LocationSchema DirectiveLocation = `SCHEMA`
+ LocationScalar DirectiveLocation = `SCALAR`
+ LocationObject DirectiveLocation = `OBJECT`
+ LocationFieldDefinition DirectiveLocation = `FIELD_DEFINITION`
+ LocationArgumentDefinition DirectiveLocation = `ARGUMENT_DEFINITION`
+ LocationInterface DirectiveLocation = `INTERFACE`
+ LocationUnion DirectiveLocation = `UNION`
+ LocationEnum DirectiveLocation = `ENUM`
+ LocationEnumValue DirectiveLocation = `ENUM_VALUE`
+ LocationInputObject DirectiveLocation = `INPUT_OBJECT`
+ LocationInputFieldDefinition DirectiveLocation = `INPUT_FIELD_DEFINITION`
+)
+
+type Directive struct {
+ Name string
+ Arguments ArgumentList
+ Position *Position `dump:"-"`
+
+ // Requires validation
+ ParentDefinition *Definition
+ Definition *DirectiveDefinition
+ Location DirectiveLocation
+}
+
+func (d *Directive) ArgumentMap(vars map[string]interface{}) map[string]interface{} {
+ return arg2map(d.Definition.Arguments, d.Arguments, vars)
+}
diff --git a/vendor/github.com/vektah/gqlparser/ast/document.go b/vendor/github.com/vektah/gqlparser/ast/document.go
new file mode 100644
index 00000000..b7657d62
--- /dev/null
+++ b/vendor/github.com/vektah/gqlparser/ast/document.go
@@ -0,0 +1,65 @@
+package ast
+
+type QueryDocument struct {
+ Operations OperationList
+ Fragments FragmentDefinitionList
+ Position *Position `dump:"-"`
+}
+
+type SchemaDocument struct {
+ Schema SchemaDefinitionList
+ SchemaExtension SchemaDefinitionList
+ Directives DirectiveDefinitionList
+ Definitions DefinitionList
+ Extensions DefinitionList
+ Position *Position `dump:"-"`
+}
+
+func (d *SchemaDocument) Merge(other *SchemaDocument) {
+ d.Schema = append(d.Schema, other.Schema...)
+ d.SchemaExtension = append(d.SchemaExtension, other.SchemaExtension...)
+ d.Directives = append(d.Directives, other.Directives...)
+ d.Definitions = append(d.Definitions, other.Definitions...)
+ d.Extensions = append(d.Extensions, other.Extensions...)
+}
+
+type Schema struct {
+ Query *Definition
+ Mutation *Definition
+ Subscription *Definition
+
+ Types map[string]*Definition
+ Directives map[string]*DirectiveDefinition
+
+ PossibleTypes map[string][]*Definition
+}
+
+func (s *Schema) AddPossibleType(name string, def *Definition) {
+ s.PossibleTypes[name] = append(s.PossibleTypes[name], def)
+}
+
+// GetPossibleTypes will enumerate all the definitions for a given interface or union
+func (s *Schema) GetPossibleTypes(def *Definition) []*Definition {
+ if def.Kind == Union {
+ var defs []*Definition
+ for _, t := range def.Types {
+ defs = append(defs, s.Types[t])
+ }
+ return defs
+ }
+
+ return s.PossibleTypes[def.Name]
+}
+
+type SchemaDefinition struct {
+ Description string
+ Directives DirectiveList
+ OperationTypes OperationTypeDefinitionList
+ Position *Position `dump:"-"`
+}
+
+type OperationTypeDefinition struct {
+ Operation Operation
+ Type string
+ Position *Position `dump:"-"`
+}
diff --git a/vendor/github.com/vektah/gqlparser/ast/dumper.go b/vendor/github.com/vektah/gqlparser/ast/dumper.go
new file mode 100644
index 00000000..dbb7a7ef
--- /dev/null
+++ b/vendor/github.com/vektah/gqlparser/ast/dumper.go
@@ -0,0 +1,159 @@
+package ast
+
+import (
+ "bytes"
+ "fmt"
+ "reflect"
+ "strconv"
+ "strings"
+)
+
+// Dump turns ast into a stable string format for assertions in tests
+func Dump(i interface{}) string {
+ v := reflect.ValueOf(i)
+
+ d := dumper{Buffer: &bytes.Buffer{}}
+ d.dump(v)
+
+ return d.String()
+}
+
+type dumper struct {
+ *bytes.Buffer
+ indent int
+}
+
+type Dumpable interface {
+ Dump() string
+}
+
+func (d *dumper) dump(v reflect.Value) {
+ if dumpable, isDumpable := v.Interface().(Dumpable); isDumpable {
+ d.WriteString(dumpable.Dump())
+ return
+ }
+ switch v.Kind() {
+ case reflect.Bool:
+ if v.Bool() {
+ d.WriteString("true")
+ } else {
+ d.WriteString("false")
+ }
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ d.WriteString(fmt.Sprintf("%d", v.Int()))
+
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ d.WriteString(fmt.Sprintf("%d", v.Uint()))
+
+ case reflect.Float32, reflect.Float64:
+ d.WriteString(fmt.Sprintf("%.2f", v.Float()))
+
+ case reflect.String:
+ if v.Type().Name() != "string" {
+ d.WriteString(v.Type().Name() + "(" + strconv.Quote(v.String()) + ")")
+ } else {
+ d.WriteString(strconv.Quote(v.String()))
+ }
+
+ case reflect.Array, reflect.Slice:
+ d.dumpArray(v)
+
+ case reflect.Interface, reflect.Ptr:
+ d.dumpPtr(v)
+
+ case reflect.Struct:
+ d.dumpStruct(v)
+
+ default:
+ panic(fmt.Errorf("unsupported kind: %s\n buf: %s", v.Kind().String(), d.String()))
+ }
+}
+
+func (d *dumper) writeIndent() {
+ d.Buffer.WriteString(strings.Repeat(" ", d.indent))
+}
+
+func (d *dumper) nl() {
+ d.Buffer.WriteByte('\n')
+ d.writeIndent()
+}
+
+func typeName(t reflect.Type) string {
+ if t.Kind() == reflect.Ptr {
+ return typeName(t.Elem())
+ }
+ return t.Name()
+}
+
+func (d *dumper) dumpArray(v reflect.Value) {
+ d.WriteString("[" + typeName(v.Type().Elem()) + "]")
+
+ for i := 0; i < v.Len(); i++ {
+ d.nl()
+ d.WriteString("- ")
+ d.indent++
+ d.dump(v.Index(i))
+ d.indent--
+ }
+}
+
+func (d *dumper) dumpStruct(v reflect.Value) {
+ d.WriteString("<" + v.Type().Name() + ">")
+ d.indent++
+
+ typ := v.Type()
+ for i := 0; i < v.NumField(); i++ {
+ f := v.Field(i)
+ if typ.Field(i).Tag.Get("dump") == "-" {
+ continue
+ }
+
+ if isZero(f) {
+ continue
+ }
+ d.nl()
+ d.WriteString(typ.Field(i).Name)
+ d.WriteString(": ")
+ d.dump(v.Field(i))
+ }
+
+ d.indent--
+}
+
+func isZero(v reflect.Value) bool {
+ switch v.Kind() {
+ case reflect.Ptr, reflect.Interface:
+ return v.IsNil()
+ case reflect.Func, reflect.Map:
+ return v.IsNil()
+
+ case reflect.Array, reflect.Slice:
+ if v.IsNil() {
+ return true
+ }
+ z := true
+ for i := 0; i < v.Len(); i++ {
+ z = z && isZero(v.Index(i))
+ }
+ return z
+ case reflect.Struct:
+ z := true
+ for i := 0; i < v.NumField(); i++ {
+ z = z && isZero(v.Field(i))
+ }
+ return z
+ case reflect.String:
+ return v.String() == ""
+ }
+
+ // Compare other types directly:
+ return reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()))
+}
+
+func (d *dumper) dumpPtr(v reflect.Value) {
+ if v.IsNil() {
+ d.WriteString("nil")
+ return
+ }
+ d.dump(v.Elem())
+}
diff --git a/vendor/github.com/vektah/gqlparser/ast/fragment.go b/vendor/github.com/vektah/gqlparser/ast/fragment.go
new file mode 100644
index 00000000..57ab56c7
--- /dev/null
+++ b/vendor/github.com/vektah/gqlparser/ast/fragment.go
@@ -0,0 +1,38 @@
+package ast
+
+type FragmentSpread struct {
+ Name string
+ Directives DirectiveList
+
+ // Require validation
+ ObjectDefinition *Definition
+ Definition *FragmentDefinition
+
+ Position *Position `dump:"-"`
+}
+
+type InlineFragment struct {
+ TypeCondition string
+ Directives DirectiveList
+ SelectionSet SelectionSet
+
+ // Require validation
+ ObjectDefinition *Definition
+
+ Position *Position `dump:"-"`
+}
+
+type FragmentDefinition struct {
+ Name string
+ // Note: fragment variable definitions are experimental and may be changed
+ // or removed in the future.
+ VariableDefinition VariableDefinitionList
+ TypeCondition string
+ Directives DirectiveList
+ SelectionSet SelectionSet
+
+ // Require validation
+ Definition *Definition
+
+ Position *Position `dump:"-"`
+}
diff --git a/vendor/github.com/vektah/gqlparser/ast/operation.go b/vendor/github.com/vektah/gqlparser/ast/operation.go
new file mode 100644
index 00000000..03e916a0
--- /dev/null
+++ b/vendor/github.com/vektah/gqlparser/ast/operation.go
@@ -0,0 +1,29 @@
+package ast
+
+type Operation string
+
+const (
+ Query Operation = "query"
+ Mutation Operation = "mutation"
+ Subscription Operation = "subscription"
+)
+
+type OperationDefinition struct {
+ Operation Operation
+ Name string
+ VariableDefinitions VariableDefinitionList
+ Directives DirectiveList
+ SelectionSet SelectionSet
+ Position *Position `dump:"-"`
+}
+
+type VariableDefinition struct {
+ Variable string
+ Type *Type
+ DefaultValue *Value
+ Position *Position `dump:"-"`
+
+ // Requires validation
+ Definition *Definition
+ Used bool `dump:"-"`
+}
diff --git a/vendor/github.com/vektah/gqlparser/ast/selection.go b/vendor/github.com/vektah/gqlparser/ast/selection.go
new file mode 100644
index 00000000..159db844
--- /dev/null
+++ b/vendor/github.com/vektah/gqlparser/ast/selection.go
@@ -0,0 +1,39 @@
+package ast
+
+type SelectionSet []Selection
+
+type Selection interface {
+ isSelection()
+ GetPosition() *Position
+}
+
+func (*Field) isSelection() {}
+func (*FragmentSpread) isSelection() {}
+func (*InlineFragment) isSelection() {}
+
+func (s *Field) GetPosition() *Position { return s.Position }
+func (s *FragmentSpread) GetPosition() *Position { return s.Position }
+func (s *InlineFragment) GetPosition() *Position { return s.Position }
+
+type Field struct {
+ Alias string
+ Name string
+ Arguments ArgumentList
+ Directives DirectiveList
+ SelectionSet SelectionSet
+ Position *Position `dump:"-"`
+
+ // Require validation
+ Definition *FieldDefinition
+ ObjectDefinition *Definition
+}
+
+type Argument struct {
+ Name string
+ Value *Value
+ Position *Position `dump:"-"`
+}
+
+func (f *Field) ArgumentMap(vars map[string]interface{}) map[string]interface{} {
+ return arg2map(f.Definition.Arguments, f.Arguments, vars)
+}
diff --git a/vendor/github.com/vektah/gqlparser/ast/source.go b/vendor/github.com/vektah/gqlparser/ast/source.go
new file mode 100644
index 00000000..9d44dd9c
--- /dev/null
+++ b/vendor/github.com/vektah/gqlparser/ast/source.go
@@ -0,0 +1,14 @@
+package ast
+
+type Source struct {
+ Name string
+ Input string
+}
+
+type Position struct {
+ Start int // The starting position, in runes, of this token in the input.
+ End int // The end position, in runes, of this token in the input.
+ Line int // The line number at the start of this item.
+ Column int // The line number at the start of this item.
+ Src *Source // The source document this token belongs to
+}
diff --git a/vendor/github.com/vektah/gqlparser/ast/type.go b/vendor/github.com/vektah/gqlparser/ast/type.go
new file mode 100644
index 00000000..9577fdb4
--- /dev/null
+++ b/vendor/github.com/vektah/gqlparser/ast/type.go
@@ -0,0 +1,68 @@
+package ast
+
+func NonNullNamedType(named string, pos *Position) *Type {
+ return &Type{NamedType: named, NonNull: true, Position: pos}
+}
+
+func NamedType(named string, pos *Position) *Type {
+ return &Type{NamedType: named, NonNull: false, Position: pos}
+}
+
+func NonNullListType(elem *Type, pos *Position) *Type {
+ return &Type{Elem: elem, NonNull: true, Position: pos}
+}
+
+func ListType(elem *Type, pos *Position) *Type {
+ return &Type{Elem: elem, NonNull: false, Position: pos}
+}
+
+type Type struct {
+ NamedType string
+ Elem *Type
+ NonNull bool
+ Position *Position `dump:"-"`
+}
+
+func (t *Type) Name() string {
+ if t.NamedType != "" {
+ return t.NamedType
+ }
+
+ return t.Elem.Name()
+}
+
+func (t *Type) String() string {
+ nn := ""
+ if t.NonNull {
+ nn = "!"
+ }
+ if t.NamedType != "" {
+ return t.NamedType + nn
+ }
+
+ return "[" + t.Elem.String() + "]" + nn
+}
+
+func (t *Type) IsCompatible(other *Type) bool {
+ if t.NamedType != other.NamedType {
+ return false
+ }
+
+ if t.Elem != nil && other.Elem == nil {
+ return false
+ }
+
+ if t.Elem != nil && !t.Elem.IsCompatible(other.Elem) {
+ return false
+ }
+
+ if other.NonNull {
+ return t.NonNull
+ }
+
+ return true
+}
+
+func (v *Type) Dump() string {
+ return v.String()
+}
diff --git a/vendor/github.com/vektah/gqlparser/ast/value.go b/vendor/github.com/vektah/gqlparser/ast/value.go
new file mode 100644
index 00000000..3168b266
--- /dev/null
+++ b/vendor/github.com/vektah/gqlparser/ast/value.go
@@ -0,0 +1,120 @@
+package ast
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+)
+
+type ValueKind int
+
+const (
+ Variable ValueKind = iota
+ IntValue
+ FloatValue
+ StringValue
+ BlockValue
+ BooleanValue
+ NullValue
+ EnumValue
+ ListValue
+ ObjectValue
+)
+
+type Value struct {
+ Raw string
+ Children ChildValueList
+ Kind ValueKind
+ Position *Position `dump:"-"`
+
+ // Require validation
+ Definition *Definition
+ VariableDefinition *VariableDefinition
+ ExpectedType *Type
+}
+
+type ChildValue struct {
+ Name string
+ Value *Value
+ Position *Position `dump:"-"`
+}
+
+func (v *Value) Value(vars map[string]interface{}) (interface{}, error) {
+ if v == nil {
+ return nil, nil
+ }
+ switch v.Kind {
+ case Variable:
+ if value, ok := vars[v.Raw]; ok {
+ return value, nil
+ }
+ if v.VariableDefinition != nil && v.VariableDefinition.DefaultValue != nil {
+ return v.VariableDefinition.DefaultValue.Value(vars)
+ }
+ return nil, nil
+ case IntValue:
+ return strconv.ParseInt(v.Raw, 10, 64)
+ case FloatValue:
+ return strconv.ParseFloat(v.Raw, 64)
+ case StringValue, BlockValue, EnumValue:
+ return v.Raw, nil
+ case BooleanValue:
+ return strconv.ParseBool(v.Raw)
+ case NullValue:
+ return nil, nil
+ case ListValue:
+ var val []interface{}
+ for _, elem := range v.Children {
+ elemVal, err := elem.Value.Value(vars)
+ if err != nil {
+ return val, err
+ }
+ val = append(val, elemVal)
+ }
+ return val, nil
+ case ObjectValue:
+ val := map[string]interface{}{}
+ for _, elem := range v.Children {
+ elemVal, err := elem.Value.Value(vars)
+ if err != nil {
+ return val, err
+ }
+ val[elem.Name] = elemVal
+ }
+ return val, nil
+ default:
+ panic(fmt.Errorf("unknown value kind %d", v.Kind))
+ }
+}
+
+func (v *Value) String() string {
+ if v == nil {
+ return "<nil>"
+ }
+ switch v.Kind {
+ case Variable:
+ return "$" + v.Raw
+ case IntValue, FloatValue, EnumValue, BooleanValue, NullValue:
+ return v.Raw
+ case StringValue, BlockValue:
+ return strconv.Quote(v.Raw)
+ case ListValue:
+ var val []string
+ for _, elem := range v.Children {
+ val = append(val, elem.Value.String())
+ }
+ return "[" + strings.Join(val, ",") + "]"
+ case ObjectValue:
+ var val []string
+ for _, elem := range v.Children {
+ val = append(val, strconv.Quote(elem.Name)+":"+elem.Value.String())
+ }
+ return "{" + strings.Join(val, ",") + "}"
+ default:
+ panic(fmt.Errorf("unknown value kind %d", v.Kind))
+ }
+}
+
+func (v *Value) Dump() string {
+ return v.String()
+}