Merge pull request #181 from Nan-Zhang/support-integer
Support parsing int64 number in Blueprint file
diff --git a/parser/ast.go b/parser/ast.go
index 52462f7..7f94efb 100644
--- a/parser/ast.go
+++ b/parser/ast.go
@@ -161,6 +161,7 @@
const (
BoolType Type = iota + 1
StringType
+ Int64Type
ListType
MapType
)
@@ -171,6 +172,8 @@
return "bool"
case StringType:
return "string"
+ case Int64Type:
+ return "int64"
case ListType:
return "list"
case MapType:
@@ -350,6 +353,31 @@
return StringType
}
+type Int64 struct {
+ LiteralPos scanner.Position
+ Value int64
+}
+
+func (x *Int64) Pos() scanner.Position { return x.LiteralPos }
+func (x *Int64) End() scanner.Position { return x.LiteralPos }
+
+func (x *Int64) Copy() Expression {
+ ret := *x
+ return &ret
+}
+
+func (x *Int64) Eval() Expression {
+ return x
+}
+
+func (x *Int64) String() string {
+ return fmt.Sprintf("%q@%s", x.Value, x.LiteralPos)
+}
+
+func (x *Int64) Type() Type {
+ return Int64Type
+}
+
type Bool struct {
LiteralPos scanner.Position
Value bool
diff --git a/parser/parser.go b/parser/parser.go
index de4e8e2..728afbe 100644
--- a/parser/parser.go
+++ b/parser/parser.go
@@ -114,7 +114,7 @@
p.scanner.Error = func(sc *scanner.Scanner, msg string) {
p.errorf(msg)
}
- p.scanner.Mode = scanner.ScanIdents | scanner.ScanStrings |
+ p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanStrings |
scanner.ScanRawStrings | scanner.ScanComments
p.next()
return p
@@ -330,6 +330,9 @@
switch p.tok {
case '+':
return p.parseOperator(value)
+ case '-':
+ p.errorf("subtraction not supported: %s", p.scanner.String())
+ return value
default:
return value
}
@@ -355,6 +358,8 @@
switch v := value.(type) {
case *String:
v.Value += e2.(*String).Value
+ case *Int64:
+ v.Value += e2.(*Int64).Value
case *List:
v.Values = append(v.Values, e2.(*List).Values...)
case *Map:
@@ -441,6 +446,8 @@
switch p.tok {
case scanner.Ident:
return p.parseVariable()
+ case '-', scanner.Int: // Integer might have '-' sign ahead ('+' is only treated as operator now)
+ return p.parseIntValue()
case scanner.String:
return p.parseStringValue()
case '[':
@@ -500,6 +507,32 @@
return value
}
+func (p *parser) parseIntValue() *Int64 {
+ var str string
+ literalPos := p.scanner.Position
+ if p.tok == '-' {
+ str += string(p.tok)
+ p.accept(p.tok)
+ if p.tok != scanner.Int {
+ p.errorf("expected int; found %s", scanner.TokenString(p.tok))
+ return nil
+ }
+ }
+ str += p.scanner.TokenText()
+ i, err := strconv.ParseInt(str, 10, 64)
+ if err != nil {
+ p.errorf("couldn't parse int: %s", err)
+ return nil
+ }
+
+ value := &Int64{
+ LiteralPos: literalPos,
+ Value: i,
+ }
+ p.accept(scanner.Int)
+ return value
+}
+
func (p *parser) parseListValue() *List {
lBracePos := p.scanner.Position
if !p.accept('[') {
diff --git a/parser/parser_test.go b/parser/parser_test.go
index bde67e5..d740184 100644
--- a/parser/parser_test.go
+++ b/parser/parser_test.go
@@ -110,6 +110,35 @@
{`
foo {
+ num: 4,
+ }
+ `,
+ []Definition{
+ &Module{
+ Type: "foo",
+ TypePos: mkpos(3, 2, 3),
+ Map: Map{
+ LBracePos: mkpos(7, 2, 7),
+ RBracePos: mkpos(22, 4, 3),
+ Properties: []*Property{
+ {
+ Name: "num",
+ NamePos: mkpos(12, 3, 4),
+ ColonPos: mkpos(15, 3, 7),
+ Value: &Int64{
+ LiteralPos: mkpos(17, 3, 9),
+ Value: 4,
+ },
+ },
+ },
+ },
+ },
+ },
+ nil,
+ },
+
+ {`
+ foo {
stuff: ["asdf", "jkl;", "qwert",
"uiop", "bnm,"]
}
@@ -164,7 +193,8 @@
foo {
stuff: {
isGood: true,
- name: "bar"
+ name: "bar",
+ num: 36,
}
}
`,
@@ -174,7 +204,7 @@
TypePos: mkpos(3, 2, 3),
Map: Map{
LBracePos: mkpos(7, 2, 7),
- RBracePos: mkpos(62, 7, 3),
+ RBracePos: mkpos(76, 8, 3),
Properties: []*Property{
{
Name: "stuff",
@@ -182,7 +212,7 @@
ColonPos: mkpos(17, 3, 9),
Value: &Map{
LBracePos: mkpos(19, 3, 11),
- RBracePos: mkpos(58, 6, 4),
+ RBracePos: mkpos(72, 7, 4),
Properties: []*Property{
{
Name: "isGood",
@@ -202,6 +232,15 @@
Value: "bar",
},
},
+ {
+ Name: "num",
+ NamePos: mkpos(60, 6, 5),
+ ColonPos: mkpos(63, 6, 8),
+ Value: &Int64{
+ LiteralPos: mkpos(65, 6, 10),
+ Value: 36,
+ },
+ },
},
},
},
@@ -279,10 +318,12 @@
{`
foo {
name: "abc",
+ num: 4,
}
bar {
name: "def",
+ num: -5,
}
`,
[]Definition{
@@ -291,7 +332,7 @@
TypePos: mkpos(3, 2, 3),
Map: Map{
LBracePos: mkpos(7, 2, 7),
- RBracePos: mkpos(27, 4, 3),
+ RBracePos: mkpos(38, 5, 3),
Properties: []*Property{
{
Name: "name",
@@ -302,31 +343,50 @@
Value: "abc",
},
},
+ {
+ Name: "num",
+ NamePos: mkpos(28, 4, 4),
+ ColonPos: mkpos(31, 4, 7),
+ Value: &Int64{
+ LiteralPos: mkpos(33, 4, 9),
+ Value: 4,
+ },
+ },
},
},
},
&Module{
Type: "bar",
- TypePos: mkpos(32, 6, 3),
+ TypePos: mkpos(43, 7, 3),
Map: Map{
- LBracePos: mkpos(36, 6, 7),
- RBracePos: mkpos(56, 8, 3),
+ LBracePos: mkpos(47, 7, 7),
+ RBracePos: mkpos(79, 10, 3),
Properties: []*Property{
{
Name: "name",
- NamePos: mkpos(41, 7, 4),
- ColonPos: mkpos(45, 7, 8),
+ NamePos: mkpos(52, 8, 4),
+ ColonPos: mkpos(56, 8, 8),
Value: &String{
- LiteralPos: mkpos(47, 7, 10),
+ LiteralPos: mkpos(58, 8, 10),
Value: "def",
},
},
+ {
+ Name: "num",
+ NamePos: mkpos(68, 9, 4),
+ ColonPos: mkpos(71, 9, 7),
+ Value: &Int64{
+ LiteralPos: mkpos(73, 9, 9),
+ Value: -5,
+ },
+ },
},
},
},
},
nil,
},
+
{`
foo = "stuff"
bar = foo
@@ -557,6 +617,317 @@
},
nil,
},
+
+ {`
+ baz = -4 + -5 + 6
+ `,
+ []Definition{
+ &Assignment{
+ Name: "baz",
+ NamePos: mkpos(3, 2, 3),
+ EqualsPos: mkpos(7, 2, 7),
+ Value: &Operator{
+ OperatorPos: mkpos(12, 2, 12),
+ Operator: '+',
+ Value: &Int64{
+ LiteralPos: mkpos(9, 2, 9),
+ Value: -3,
+ },
+ Args: [2]Expression{
+ &Int64{
+ LiteralPos: mkpos(9, 2, 9),
+ Value: -4,
+ },
+ &Operator{
+ OperatorPos: mkpos(17, 2, 17),
+ Operator: '+',
+ Value: &Int64{
+ LiteralPos: mkpos(14, 2, 14),
+ Value: 1,
+ },
+ Args: [2]Expression{
+ &Int64{
+ LiteralPos: mkpos(14, 2, 14),
+ Value: -5,
+ },
+ &Int64{
+ LiteralPos: mkpos(19, 2, 19),
+ Value: 6,
+ },
+ },
+ },
+ },
+ },
+ OrigValue: &Operator{
+ OperatorPos: mkpos(12, 2, 12),
+ Operator: '+',
+ Value: &Int64{
+ LiteralPos: mkpos(9, 2, 9),
+ Value: -3,
+ },
+ Args: [2]Expression{
+ &Int64{
+ LiteralPos: mkpos(9, 2, 9),
+ Value: -4,
+ },
+ &Operator{
+ OperatorPos: mkpos(17, 2, 17),
+ Operator: '+',
+ Value: &Int64{
+ LiteralPos: mkpos(14, 2, 14),
+ Value: 1,
+ },
+ Args: [2]Expression{
+ &Int64{
+ LiteralPos: mkpos(14, 2, 14),
+ Value: -5,
+ },
+ &Int64{
+ LiteralPos: mkpos(19, 2, 19),
+ Value: 6,
+ },
+ },
+ },
+ },
+ },
+ Assigner: "=",
+ Referenced: false,
+ },
+ },
+ nil,
+ },
+
+ {`
+ foo = 1000000
+ bar = foo
+ baz = foo + bar
+ boo = baz
+ boo += foo
+ `,
+ []Definition{
+ &Assignment{
+ Name: "foo",
+ NamePos: mkpos(3, 2, 3),
+ EqualsPos: mkpos(7, 2, 7),
+ Value: &Int64{
+ LiteralPos: mkpos(9, 2, 9),
+ Value: 1000000,
+ },
+ OrigValue: &Int64{
+ LiteralPos: mkpos(9, 2, 9),
+ Value: 1000000,
+ },
+ Assigner: "=",
+ Referenced: true,
+ },
+ &Assignment{
+ Name: "bar",
+ NamePos: mkpos(19, 3, 3),
+ EqualsPos: mkpos(23, 3, 7),
+ Value: &Variable{
+ Name: "foo",
+ NamePos: mkpos(25, 3, 9),
+ Value: &Int64{
+ LiteralPos: mkpos(9, 2, 9),
+ Value: 1000000,
+ },
+ },
+ OrigValue: &Variable{
+ Name: "foo",
+ NamePos: mkpos(25, 3, 9),
+ Value: &Int64{
+ LiteralPos: mkpos(9, 2, 9),
+ Value: 1000000,
+ },
+ },
+ Assigner: "=",
+ Referenced: true,
+ },
+ &Assignment{
+ Name: "baz",
+ NamePos: mkpos(31, 4, 3),
+ EqualsPos: mkpos(35, 4, 7),
+ Value: &Operator{
+ OperatorPos: mkpos(41, 4, 13),
+ Operator: '+',
+ Value: &Int64{
+ LiteralPos: mkpos(9, 2, 9),
+ Value: 2000000,
+ },
+ Args: [2]Expression{
+ &Variable{
+ Name: "foo",
+ NamePos: mkpos(37, 4, 9),
+ Value: &Int64{
+ LiteralPos: mkpos(9, 2, 9),
+ Value: 1000000,
+ },
+ },
+ &Variable{
+ Name: "bar",
+ NamePos: mkpos(43, 4, 15),
+ Value: &Variable{
+ Name: "foo",
+ NamePos: mkpos(25, 3, 9),
+ Value: &Int64{
+ LiteralPos: mkpos(9, 2, 9),
+ Value: 1000000,
+ },
+ },
+ },
+ },
+ },
+ OrigValue: &Operator{
+ OperatorPos: mkpos(41, 4, 13),
+ Operator: '+',
+ Value: &Int64{
+ LiteralPos: mkpos(9, 2, 9),
+ Value: 2000000,
+ },
+ Args: [2]Expression{
+ &Variable{
+ Name: "foo",
+ NamePos: mkpos(37, 4, 9),
+ Value: &Int64{
+ LiteralPos: mkpos(9, 2, 9),
+ Value: 1000000,
+ },
+ },
+ &Variable{
+ Name: "bar",
+ NamePos: mkpos(43, 4, 15),
+ Value: &Variable{
+ Name: "foo",
+ NamePos: mkpos(25, 3, 9),
+ Value: &Int64{
+ LiteralPos: mkpos(9, 2, 9),
+ Value: 1000000,
+ },
+ },
+ },
+ },
+ },
+ Assigner: "=",
+ Referenced: true,
+ },
+ &Assignment{
+ Name: "boo",
+ NamePos: mkpos(49, 5, 3),
+ EqualsPos: mkpos(53, 5, 7),
+ Value: &Operator{
+ Args: [2]Expression{
+ &Variable{
+ Name: "baz",
+ NamePos: mkpos(55, 5, 9),
+ Value: &Operator{
+ OperatorPos: mkpos(41, 4, 13),
+ Operator: '+',
+ Value: &Int64{
+ LiteralPos: mkpos(9, 2, 9),
+ Value: 2000000,
+ },
+ Args: [2]Expression{
+ &Variable{
+ Name: "foo",
+ NamePos: mkpos(37, 4, 9),
+ Value: &Int64{
+ LiteralPos: mkpos(9, 2, 9),
+ Value: 1000000,
+ },
+ },
+ &Variable{
+ Name: "bar",
+ NamePos: mkpos(43, 4, 15),
+ Value: &Variable{
+ Name: "foo",
+ NamePos: mkpos(25, 3, 9),
+ Value: &Int64{
+ LiteralPos: mkpos(9, 2, 9),
+ Value: 1000000,
+ },
+ },
+ },
+ },
+ },
+ },
+ &Variable{
+ Name: "foo",
+ NamePos: mkpos(68, 6, 10),
+ Value: &Int64{
+ LiteralPos: mkpos(9, 2, 9),
+ Value: 1000000,
+ },
+ },
+ },
+ OperatorPos: mkpos(66, 6, 8),
+ Operator: '+',
+ Value: &Int64{
+ LiteralPos: mkpos(9, 2, 9),
+ Value: 3000000,
+ },
+ },
+ OrigValue: &Variable{
+ Name: "baz",
+ NamePos: mkpos(55, 5, 9),
+ Value: &Operator{
+ OperatorPos: mkpos(41, 4, 13),
+ Operator: '+',
+ Value: &Int64{
+ LiteralPos: mkpos(9, 2, 9),
+ Value: 2000000,
+ },
+ Args: [2]Expression{
+ &Variable{
+ Name: "foo",
+ NamePos: mkpos(37, 4, 9),
+ Value: &Int64{
+ LiteralPos: mkpos(9, 2, 9),
+ Value: 1000000,
+ },
+ },
+ &Variable{
+ Name: "bar",
+ NamePos: mkpos(43, 4, 15),
+ Value: &Variable{
+ Name: "foo",
+ NamePos: mkpos(25, 3, 9),
+ Value: &Int64{
+ LiteralPos: mkpos(9, 2, 9),
+ Value: 1000000,
+ },
+ },
+ },
+ },
+ },
+ },
+ Assigner: "=",
+ },
+ &Assignment{
+ Name: "boo",
+ NamePos: mkpos(61, 6, 3),
+ EqualsPos: mkpos(66, 6, 8),
+ Value: &Variable{
+ Name: "foo",
+ NamePos: mkpos(68, 6, 10),
+ Value: &Int64{
+ LiteralPos: mkpos(9, 2, 9),
+ Value: 1000000,
+ },
+ },
+ OrigValue: &Variable{
+ Name: "foo",
+ NamePos: mkpos(68, 6, 10),
+ Value: &Int64{
+ LiteralPos: mkpos(9, 2, 9),
+ Value: 1000000,
+ },
+ },
+ Assigner: "+=",
+ },
+ },
+ nil,
+ },
+
{`
// comment1
// comment2
diff --git a/parser/printer.go b/parser/printer.go
index 56349fa..d3aad4a 100644
--- a/parser/printer.go
+++ b/parser/printer.go
@@ -123,6 +123,8 @@
s = "false"
}
p.printToken(s, v.LiteralPos)
+ case *Int64:
+ p.printToken(strconv.FormatInt(v.Value, 10), v.LiteralPos)
case *String:
p.printToken(strconv.Quote(v.Value), v.LiteralPos)
case *List:
diff --git a/parser/printer_test.go b/parser/printer_test.go
index 6c5b646..a223fab 100644
--- a/parser/printer_test.go
+++ b/parser/printer_test.go
@@ -33,11 +33,12 @@
},
{
input: `
-foo{name= "abc",}
+foo{name= "abc",num= 4,}
`,
output: `
foo {
name: "abc",
+ num: 4,
}
`,
},
@@ -108,7 +109,8 @@
foo {
stuff: {
isGood: true,
- name: "bar"
+ name: "bar",
+ num: 4,
}
}
`,
@@ -117,6 +119,7 @@
stuff: {
isGood: true,
name: "bar",
+ num: 4,
},
}
`,
@@ -141,19 +144,23 @@
input: `
foo {
name: "abc",
+ num: 4,
}
bar {
name: "def",
+ num: 5,
}
`,
output: `
foo {
name: "abc",
+ num: 4,
}
bar {
name: "def",
+ num: 5,
}
`,
},
@@ -173,6 +180,20 @@
},
{
input: `
+foo = 100
+bar = foo
+baz = foo + bar
+baz += foo
+`,
+ output: `
+foo = 100
+bar = foo
+baz = foo + bar
+baz += foo
+`,
+ },
+ {
+ input: `
//test
test /* test */ {
srcs: [
diff --git a/proptools/clone.go b/proptools/clone.go
index 4cc1103..9948b9a 100644
--- a/proptools/clone.go
+++ b/proptools/clone.go
@@ -114,7 +114,7 @@
origDstFieldValue.Set(newValue)
}
}
- case reflect.Bool, reflect.String:
+ case reflect.Bool, reflect.Int64, reflect.String:
newValue := reflect.New(srcFieldValue.Type())
newValue.Elem().Set(srcFieldValue)
origDstFieldValue.Set(newValue)
@@ -167,7 +167,7 @@
break
}
ZeroProperties(fieldValue.Elem())
- case reflect.Bool, reflect.String:
+ case reflect.Bool, reflect.Int64, reflect.String:
fieldValue.Set(reflect.Zero(fieldValue.Type()))
default:
panic(fmt.Errorf("can't zero field %q: points to a %s",
@@ -237,7 +237,7 @@
} else {
dstFieldValue.Set(newValue)
}
- case reflect.Bool, reflect.String:
+ case reflect.Bool, reflect.Int64, reflect.String:
// Nothing
default:
panic(fmt.Errorf("can't clone empty field %q: points to a %s",
diff --git a/proptools/clone_test.go b/proptools/clone_test.go
index 0679c12..b6f1bf6 100644
--- a/proptools/clone_test.go
+++ b/proptools/clone_test.go
@@ -91,6 +91,15 @@
},
},
{
+ // Clone pointer to int64
+ in: &struct{ S *int64 }{
+ S: Int64Ptr(5),
+ },
+ out: &struct{ S *int64 }{
+ S: Int64Ptr(5),
+ },
+ },
+ {
// Clone struct
in: &struct{ S struct{ S string } }{
S: struct{ S string }{
@@ -189,10 +198,12 @@
}{
EmbeddedStruct: EmbeddedStruct{
S: "string1",
+ I: Int64Ptr(55),
},
Nested: struct{ EmbeddedStruct }{
EmbeddedStruct: EmbeddedStruct{
S: "string2",
+ I: Int64Ptr(5),
},
},
},
@@ -202,10 +213,12 @@
}{
EmbeddedStruct: EmbeddedStruct{
S: "string1",
+ I: Int64Ptr(55),
},
Nested: struct{ EmbeddedStruct }{
EmbeddedStruct: EmbeddedStruct{
S: "string2",
+ I: Int64Ptr(5),
},
},
},
@@ -241,7 +254,10 @@
},
}
-type EmbeddedStruct struct{ S string }
+type EmbeddedStruct struct {
+ S string
+ I *int64
+}
type EmbeddedInterface interface{}
func TestCloneProperties(t *testing.T) {
@@ -309,6 +325,14 @@
out: &struct{ B1, B2 *bool }{},
},
{
+ // Clone pointer to int64
+ in: &struct{ B1, B2 *int64 }{
+ B1: Int64Ptr(5),
+ B2: Int64Ptr(4),
+ },
+ out: &struct{ B1, B2 *int64 }{},
+ },
+ {
// Clone pointer to string
in: &struct{ S *string }{
S: StringPtr("string1"),
diff --git a/proptools/extend.go b/proptools/extend.go
index 16f48c3..1f323cf 100644
--- a/proptools/extend.go
+++ b/proptools/extend.go
@@ -346,7 +346,7 @@
dstFieldValue.Type(), srcFieldValue.Type())
}
switch ptrKind := srcFieldValue.Type().Elem().Kind(); ptrKind {
- case reflect.Bool, reflect.String, reflect.Struct:
+ case reflect.Bool, reflect.Int64, reflect.String, reflect.Struct:
// Nothing
default:
return extendPropertyErrorf(propertyName, "pointer is a %s", ptrKind)
@@ -448,6 +448,17 @@
// For append, replace the original value.
dstFieldValue.Set(reflect.ValueOf(BoolPtr(srcFieldValue.Elem().Bool())))
}
+ case reflect.Int64:
+ if prepend {
+ if dstFieldValue.IsNil() {
+ // Int() returns Int64
+ dstFieldValue.Set(reflect.ValueOf(Int64Ptr(srcFieldValue.Elem().Int())))
+ }
+ } else {
+ // For append, replace the original value.
+ // Int() returns Int64
+ dstFieldValue.Set(reflect.ValueOf(Int64Ptr(srcFieldValue.Elem().Int())))
+ }
case reflect.String:
if prepend {
if dstFieldValue.IsNil() {
diff --git a/proptools/extend_test.go b/proptools/extend_test.go
index 0070d7e..66adabb 100644
--- a/proptools/extend_test.go
+++ b/proptools/extend_test.go
@@ -177,6 +177,58 @@
prepend: true,
},
{
+ // Append pointer to integer
+ in1: &struct{ I1, I2, I3, I4, I5, I6, I7, I8, I9 *int64 }{
+ I1: Int64Ptr(55),
+ I2: Int64Ptr(-3),
+ I3: nil,
+ I4: Int64Ptr(100),
+ I5: Int64Ptr(33),
+ I6: nil,
+ I7: Int64Ptr(77),
+ I8: Int64Ptr(0),
+ I9: nil,
+ },
+ in2: &struct{ I1, I2, I3, I4, I5, I6, I7, I8, I9 *int64 }{
+ I1: nil,
+ I2: nil,
+ I3: nil,
+ I4: Int64Ptr(1),
+ I5: Int64Ptr(-2),
+ I6: Int64Ptr(8),
+ I7: Int64Ptr(9),
+ I8: Int64Ptr(10),
+ I9: Int64Ptr(11),
+ },
+ out: &struct{ I1, I2, I3, I4, I5, I6, I7, I8, I9 *int64 }{
+ I1: Int64Ptr(55),
+ I2: Int64Ptr(-3),
+ I3: nil,
+ I4: Int64Ptr(1),
+ I5: Int64Ptr(-2),
+ I6: Int64Ptr(8),
+ I7: Int64Ptr(9),
+ I8: Int64Ptr(10),
+ I9: Int64Ptr(11),
+ },
+ },
+ {
+ // Prepend pointer to integer
+ in1: &struct{ I1, I2, I3 *int64 }{
+ I1: Int64Ptr(55),
+ I3: nil,
+ },
+ in2: &struct{ I1, I2, I3 *int64 }{
+ I2: Int64Ptr(33),
+ },
+ out: &struct{ I1, I2, I3 *int64 }{
+ I1: Int64Ptr(55),
+ I2: Int64Ptr(33),
+ I3: nil,
+ },
+ prepend: true,
+ },
+ {
// Append pointer to strings
in1: &struct{ S1, S2, S3, S4 *string }{
S1: StringPtr("string1"),
@@ -383,6 +435,18 @@
},
},
{
+ // Unexported field
+ in1: &struct{ i *int64 }{
+ i: Int64Ptr(33),
+ },
+ in2: &struct{ i *int64 }{
+ i: Int64Ptr(5),
+ },
+ out: &struct{ i *int64 }{
+ i: Int64Ptr(33),
+ },
+ },
+ {
// Empty struct
in1: &struct{}{},
in2: &struct{}{},
@@ -420,10 +484,12 @@
}{
EmbeddedStruct: EmbeddedStruct{
S: "string1",
+ I: Int64Ptr(55),
},
Nested: struct{ EmbeddedStruct }{
EmbeddedStruct: EmbeddedStruct{
S: "string2",
+ I: Int64Ptr(-4),
},
},
},
@@ -433,10 +499,12 @@
}{
EmbeddedStruct: EmbeddedStruct{
S: "string3",
+ I: Int64Ptr(66),
},
Nested: struct{ EmbeddedStruct }{
EmbeddedStruct: EmbeddedStruct{
S: "string4",
+ I: Int64Ptr(-8),
},
},
},
@@ -446,10 +514,12 @@
}{
EmbeddedStruct: EmbeddedStruct{
S: "string1string3",
+ I: Int64Ptr(66),
},
Nested: struct{ EmbeddedStruct }{
EmbeddedStruct: EmbeddedStruct{
S: "string2string4",
+ I: Int64Ptr(-8),
},
},
},
@@ -460,12 +530,20 @@
EmbeddedInterface
Nested struct{ EmbeddedInterface }
}{
- EmbeddedInterface: &struct{ S string }{
+ EmbeddedInterface: &struct {
+ S string
+ I *int64
+ }{
S: "string1",
+ I: Int64Ptr(-8),
},
Nested: struct{ EmbeddedInterface }{
- EmbeddedInterface: &struct{ S string }{
+ EmbeddedInterface: &struct {
+ S string
+ I *int64
+ }{
S: "string2",
+ I: Int64Ptr(55),
},
},
},
@@ -473,12 +551,20 @@
EmbeddedInterface
Nested struct{ EmbeddedInterface }
}{
- EmbeddedInterface: &struct{ S string }{
+ EmbeddedInterface: &struct {
+ S string
+ I *int64
+ }{
S: "string3",
+ I: Int64Ptr(6),
},
Nested: struct{ EmbeddedInterface }{
- EmbeddedInterface: &struct{ S string }{
+ EmbeddedInterface: &struct {
+ S string
+ I *int64
+ }{
S: "string4",
+ I: Int64Ptr(6),
},
},
},
@@ -486,12 +572,20 @@
EmbeddedInterface
Nested struct{ EmbeddedInterface }
}{
- EmbeddedInterface: &struct{ S string }{
+ EmbeddedInterface: &struct {
+ S string
+ I *int64
+ }{
S: "string1string3",
+ I: Int64Ptr(6),
},
Nested: struct{ EmbeddedInterface }{
- EmbeddedInterface: &struct{ S string }{
+ EmbeddedInterface: &struct {
+ S string
+ I *int64
+ }{
S: "string2string4",
+ I: Int64Ptr(6),
},
},
},
@@ -626,6 +720,19 @@
err: extendPropertyErrorf("i", "unsupported kind int"),
},
{
+ // Unsupported kind
+ in1: &struct{ I int64 }{
+ I: 1,
+ },
+ in2: &struct{ I int64 }{
+ I: 2,
+ },
+ out: &struct{ I int64 }{
+ I: 1,
+ },
+ err: extendPropertyErrorf("i", "unsupported kind int64"),
+ },
+ {
// Interface nilitude mismatch
in1: &struct{ S interface{} }{
S: nil,
@@ -785,6 +892,24 @@
},
},
{
+ // Filter mutated
+ in1: &struct {
+ S *int64 `blueprint:"mutated"`
+ }{
+ S: Int64Ptr(4),
+ },
+ in2: &struct {
+ S *int64 `blueprint:"mutated"`
+ }{
+ S: Int64Ptr(5),
+ },
+ out: &struct {
+ S *int64 `blueprint:"mutated"`
+ }{
+ S: Int64Ptr(4),
+ },
+ },
+ {
// Filter error
in1: &struct{ S string }{
S: "string1",
diff --git a/proptools/proptools.go b/proptools/proptools.go
index 690d384..e071b3c 100644
--- a/proptools/proptools.go
+++ b/proptools/proptools.go
@@ -55,6 +55,12 @@
return &b
}
+// Int64Ptr returns a pointer to a new int64 containing the given value.
+func Int64Ptr(i int64) *int64 {
+ b := int64(i)
+ return &(b)
+}
+
// StringPtr returns a pointer to a new string containing the given value.
func StringPtr(s string) *string {
return &s
diff --git a/unpack.go b/unpack.go
index 4591f1a..cd165da 100644
--- a/unpack.go
+++ b/unpack.go
@@ -186,7 +186,7 @@
origFieldValue.Set(fieldValue)
}
fieldValue = fieldValue.Elem()
- case reflect.Bool, reflect.String:
+ case reflect.Bool, reflect.Int64, reflect.String:
// Nothing
default:
panic(fmt.Errorf("field %s contains a pointer to %s", propertyName, ptrKind))
@@ -303,6 +303,14 @@
}
value = reflect.ValueOf(b.Value)
+ case reflect.Int64:
+ b, ok := property.Value.Eval().(*parser.Int64)
+ if !ok {
+ return value, fmt.Errorf("%s: can't assign %s value to int64 property %q",
+ property.Value.Pos(), property.Value.Type(), property.Name)
+ }
+ value = reflect.ValueOf(b.Value)
+
case reflect.String:
s, ok := property.Value.Eval().(*parser.String)
if !ok {