~sircmpwn/go-bare

69fc441aab5ffa208b371d757d948541b04077df — Drew DeVault a month ago 6702ee2
Implement explicit union tag specification
2 files changed, 50 insertions(+), 10 deletions(-)

M schema/parser.go
M schema/parser_test.go
M schema/parser.go => schema/parser.go +22 -9
@@ 426,26 426,39 @@ func parseUnionType(scanner *Scanner) (Type, error) {
		if err != nil {
			return nil, err
		}
		subt := UnionSubtype{

		tok, err = scanner.Next()
		if err != nil {
			return nil, err
		}
		if tok.Token == TEQUAL {
			tok, err := scanner.Next()
			if err != nil {
				return nil, err
			}
			if tok.Token != TINTEGER {
				return nil, &ErrUnexpectedToken{tok, "integer"}
			}
			tag, _ = strconv.ParseUint(tok.Value, 10, 64)
		} else {
			scanner.PushBack(tok)
		}

		types = append(types, UnionSubtype{
			subtype: ty,
			tag:     tag,
		}
		})
		tag++

		tok, err := scanner.Next()
		tok, err = scanner.Next()
		if err != nil {
			return nil, err
		}

		if tok.Token == TPIPE {
			types = append(types, subt)
			continue
		} else if tok.Token == TRPAREN {
			types = append(types, subt)
			break
		} else if tok.Token == TEQUAL {
			// TODO: explicit tag values
			types = append(types, subt)
			return nil, &ErrUnexpectedToken{tok, "TODO"}
		} else {
			return nil, &ErrUnexpectedToken{tok, "'|' or ')'"}
		}

M schema/parser_test.go => schema/parser_test.go +28 -1
@@ 178,9 178,10 @@ func TestParseStruct(t *testing.T) {
func TestParseUnion(t *testing.T) {
	types, err := Parse(strings.NewReader(`
		type MyUnion (i8 | i16 | i32 | i64)
		type MyUnion42 (i8 = 42 | i16 | i32 | i64)
	`))
	assert.NoError(t, err)
	assert.Len(t, types, 1)
	assert.Len(t, types, 2)

	ty := types[0]
	assert.IsType(t, new(UserDefinedType), ty)


@@ 207,6 208,32 @@ func TestParseUnion(t *testing.T) {
	o = ut.Types()[3]
	assert.Equal(t, I64, o.Type().Kind())
	assert.Equal(t, uint64(3), o.Tag())

	ty = types[1]
	assert.IsType(t, new(UserDefinedType), ty)
	udt = ty.(*UserDefinedType)
	assert.Equal(t, "MyUnion42", udt.Name())

	assert.IsType(t, new(UnionType), udt.Type())
	ut = udt.Type().(*UnionType)
	assert.Equal(t, Union, ut.Kind())
	assert.Len(t, ut.Types(), 4)

	o = ut.Types()[0]
	assert.Equal(t, I8, o.Type().Kind())
	assert.Equal(t, uint64(42), o.Tag())

	o = ut.Types()[1]
	assert.Equal(t, I16, o.Type().Kind())
	assert.Equal(t, uint64(43), o.Tag())

	o = ut.Types()[2]
	assert.Equal(t, I32, o.Type().Kind())
	assert.Equal(t, uint64(44), o.Tag())

	o = ut.Types()[3]
	assert.Equal(t, I64, o.Type().Kind())
	assert.Equal(t, uint64(45), o.Tag())
}

func TestParseNamedType(t *testing.T) {