Skip to content

Commit

Permalink
refactor literals
Browse files Browse the repository at this point in the history
  • Loading branch information
neelance committed Mar 19, 2017
1 parent 2e1fef0 commit f7d9ff4
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 62 deletions.
54 changes: 31 additions & 23 deletions internal/common/values.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package common

import (
"strconv"
"text/scanner"

"github.com/neelance/graphql-go/errors"
Expand All @@ -24,10 +25,6 @@ type ValueWithLoc struct {
Loc *errors.Location
}

type Variable string

type EnumValue string

func ParseInputValue(l *lexer.Lexer) *InputValue {
p := &InputValue{}
p.Desc = l.DescComment()
Expand Down Expand Up @@ -70,16 +67,9 @@ func parseValue(l *lexer.Lexer, constOnly bool) interface{} {
l.SyntaxError("variable not allowed")
panic("unreachable")
}
l.ConsumeToken('$')
return Variable(l.ConsumeIdent())
case scanner.Int:
return l.ConsumeInt()
case scanner.Float:
return l.ConsumeFloat()
case scanner.String:
return l.ConsumeString()
case scanner.Ident:
return parseIdent(l)
return l.ConsumeVariable()
case scanner.Int, scanner.Float, scanner.String, scanner.Ident:
return l.ConsumeLiteral()
case '[':
l.ConsumeToken('[')
var list []interface{}
Expand All @@ -104,15 +94,33 @@ func parseValue(l *lexer.Lexer, constOnly bool) interface{} {
}
}

func parseIdent(l *lexer.Lexer) interface{} {
switch ident := l.ConsumeIdent(); ident {
case "true":
return true
case "false":
return false
case "null":
return nil
func UnmarshalLiteral(lit *lexer.Literal) interface{} {
switch lit.Type {
case scanner.Int, scanner.Float:
value, err := strconv.ParseFloat(lit.Text, 64)
if err != nil {
panic(err)
}
return value

case scanner.String:
value, err := strconv.Unquote(lit.Text)
if err != nil {
panic(err)
}
return value

case scanner.Ident:
switch lit.Text {
case "true":
return true
case "false":
return false
default:
return lit.Text
}

default:
return EnumValue(ident)
panic("invalid literal")
}
}
9 changes: 5 additions & 4 deletions internal/exec/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (

"github.com/neelance/graphql-go/errors"
"github.com/neelance/graphql-go/internal/common"
"github.com/neelance/graphql-go/internal/lexer"
"github.com/neelance/graphql-go/internal/query"
"github.com/neelance/graphql-go/internal/schema"
)
Expand Down Expand Up @@ -348,7 +349,7 @@ func (r *request) handlePanic() {
}

func (r *request) resolveVar(value interface{}) interface{} {
if v, ok := value.(common.Variable); ok {
if v, ok := value.(lexer.Variable); ok {
value = r.vars[string(v)]
}
return value
Expand Down Expand Up @@ -541,7 +542,7 @@ func (e *objectExec) execField(ctx context.Context, r *request, f *query.Field,
addResult(f.Alias, introspectSchema(ctx, r, f.SelSet))

case "__type":
p := valuePacker{valueType: stringType}
p := valuePacker{valueType: reflect.TypeOf("")}
v, err := p.pack(r, r.resolveVar(f.Arguments["name"].Value))
if err != nil {
r.addError(errors.Errorf("%s", err))
Expand Down Expand Up @@ -660,7 +661,7 @@ type typeAssertExec struct {

func skipByDirective(r *request, d map[string]common.DirectiveArgs) bool {
if args, ok := d["skip"]; ok {
p := valuePacker{valueType: boolType}
p := valuePacker{valueType: reflect.TypeOf(false)}
v, err := p.pack(r, r.resolveVar(args["if"].Value))
if err != nil {
r.addError(errors.Errorf("%s", err))
Expand All @@ -671,7 +672,7 @@ func skipByDirective(r *request, d map[string]common.DirectiveArgs) bool {
}

if args, ok := d["include"]; ok {
p := valuePacker{valueType: boolType}
p := valuePacker{valueType: reflect.TypeOf(false)}
v, err := p.pack(r, r.resolveVar(args["if"].Value))
if err != nil {
r.addError(errors.Errorf("%s", err))
Expand Down
27 changes: 12 additions & 15 deletions internal/exec/packer.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/neelance/graphql-go/errors"
"github.com/neelance/graphql-go/internal/common"
"github.com/neelance/graphql-go/internal/lexer"
"github.com/neelance/graphql-go/internal/schema"
)

Expand Down Expand Up @@ -237,6 +238,10 @@ func (p *valuePacker) pack(r *request, value interface{}) (reflect.Value, error)
return reflect.Value{}, errors.Errorf("got null for non-null")
}

if lit, ok := value.(*lexer.Literal); ok {
value = common.UnmarshalLiteral(lit)
}

coerced, err := unmarshalInput(p.valueType, value)
if err != nil {
return reflect.Value{}, fmt.Errorf("could not unmarshal %#v (%T) into %s: %s", value, value, p.valueType, err)
Expand All @@ -253,6 +258,10 @@ func (p *unmarshalerPacker) pack(r *request, value interface{}) (reflect.Value,
return reflect.Value{}, errors.Errorf("got null for non-null")
}

if lit, ok := value.(*lexer.Literal); ok {
value = common.UnmarshalLiteral(lit)
}

v := reflect.New(p.valueType)
if err := v.Interface().(Unmarshaler).UnmarshalGraphQL(value); err != nil {
return reflect.Value{}, err
Expand All @@ -265,18 +274,13 @@ type Unmarshaler interface {
UnmarshalGraphQL(input interface{}) error
}

var int32Type = reflect.TypeOf(int32(0))
var float64Type = reflect.TypeOf(float64(0))
var stringType = reflect.TypeOf("")
var boolType = reflect.TypeOf(false)

func unmarshalInput(typ reflect.Type, input interface{}) (interface{}, error) {
if reflect.TypeOf(input) == typ {
return input, nil
}

switch typ {
case int32Type:
switch typ.Kind() {
case reflect.Int32:
switch input := input.(type) {
case int:
if input < math.MinInt32 || input > math.MaxInt32 {
Expand All @@ -291,21 +295,14 @@ func unmarshalInput(typ reflect.Type, input interface{}) (interface{}, error) {
return coerced, nil
}

case float64Type:
case reflect.Float64:
switch input := input.(type) {
case int32:
return float64(input), nil
case int:
return float64(input), nil
}

case stringType:
switch input := input.(type) {
case common.EnumValue:
return string(input), nil
}
}

panic("incompatible type")
return nil, fmt.Errorf("incompatible type")
}
35 changes: 17 additions & 18 deletions internal/lexer/lexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package lexer

import (
"fmt"
"strconv"
"text/scanner"

"github.com/neelance/graphql-go/errors"
Expand All @@ -16,6 +15,13 @@ type Lexer struct {
descComment string
}

type Literal struct {
Type rune
Text string
}

type Variable string

func New(sc *scanner.Scanner) *Lexer {
l := &Lexer{sc: sc}
l.Consume()
Expand Down Expand Up @@ -81,25 +87,18 @@ func (l *Lexer) ConsumeKeyword(keyword string) {
l.Consume()
}

func (l *Lexer) ConsumeInt() int {
text := l.sc.TokenText()
l.ConsumeToken(scanner.Int)
value, _ := strconv.Atoi(text)
return value
}

func (l *Lexer) ConsumeFloat() float64 {
text := l.sc.TokenText()
l.ConsumeToken(scanner.Float)
value, _ := strconv.ParseFloat(text, 64)
return value
func (l *Lexer) ConsumeVariable() Variable {
l.ConsumeToken('$')
return Variable(l.ConsumeIdent())
}

func (l *Lexer) ConsumeString() string {
text := l.sc.TokenText()
l.ConsumeToken(scanner.String)
value, _ := strconv.Unquote(text)
return value
func (l *Lexer) ConsumeLiteral() interface{} {
lit := &Literal{Type: l.next, Text: l.sc.TokenText()}
l.Consume()
if lit.Type == scanner.Ident && lit.Text == "null" {
return nil
}
return lit
}

func (l *Lexer) ConsumeToken(expected rune) {
Expand Down
5 changes: 3 additions & 2 deletions introspection/introspection.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"sort"

"github.com/neelance/graphql-go/internal/common"
"github.com/neelance/graphql-go/internal/lexer"
"github.com/neelance/graphql-go/internal/schema"
)

Expand Down Expand Up @@ -232,7 +233,7 @@ func (r *Field) DeprecationReason() *string {
if !ok {
return nil
}
reason := args["reason"].Value.(string)
reason := common.UnmarshalLiteral(args["reason"].Value.(*lexer.Literal)).(string)
return &reason
}

Expand Down Expand Up @@ -292,7 +293,7 @@ func (r *EnumValue) DeprecationReason() *string {
if !ok {
return nil
}
reason := args["reason"].Value.(string)
reason := common.UnmarshalLiteral(args["reason"].Value.(*lexer.Literal)).(string)
return &reason
}

Expand Down

0 comments on commit f7d9ff4

Please sign in to comment.