Add AnonymousOmitEmpty type

This commit is contained in:
Masaaki Goshima 2020-08-15 18:17:48 +09:00
parent 025ac2a53b
commit 64cd28839f
4 changed files with 1348 additions and 354 deletions

View File

@ -23,6 +23,8 @@ type headType struct {
AnonymousPtrHead string
OmitEmptyHead string
OmitEmptyPtrHead string
AnonymousOmitEmptyHead string
AnonymousOmitEmptyPtrHead string
}
type fieldType struct {
@ -89,6 +91,8 @@ func (t opType) headToPtrHead() opType {
return op{{ $type.AnonymousPtrHead }}
case op{{ $type.OmitEmptyHead }}:
return op{{ $type.OmitEmptyPtrHead }}
case op{{ $type.AnonymousOmitEmptyHead }}:
return op{{ $type.AnonymousOmitEmptyPtrHead }}
{{- end }}
}
return t
@ -101,6 +105,10 @@ func (t opType) headToAnonymousHead() opType {
return op{{ $type.AnonymousHead }}
case op{{ $type.PtrHead }}:
return op{{ $type.AnonymousPtrHead }}
case op{{ $type.OmitEmptyHead }}:
return op{{ $type.AnonymousOmitEmptyHead }}
case op{{ $type.OmitEmptyPtrHead }}:
return op{{ $type.AnonymousOmitEmptyPtrHead }}
{{- end }}
}
return t
@ -127,6 +135,8 @@ func (t opType) ptrHeadToHead() opType {
return op{{ $type.AnonymousHead }}
case op{{ $type.OmitEmptyPtrHead }}:
return op{{ $type.OmitEmptyHead }}
case op{{ $type.AnonymousOmitEmptyPtrHead }}:
return op{{ $type.AnonymousOmitEmptyHead }}
{{- end }}
}
return t
@ -191,6 +201,8 @@ func (t opType) fieldToOmitEmptyField() opType {
{"StructFieldHead", "StructFieldHeadIndent", "StructField"},
{"StructFieldHeadOmitEmpty", "StructFieldHeadOmitEmptyIndent", "StructField"},
{"StructFieldAnonymousHead", "StructFieldAnonymousHeadIndent", "StructField"},
{"StructFieldAnonymousHeadOmitEmpty", "StructFieldAnonymousHeadOmitEmptyIndent", "StructField"},
{"StructFieldPtrAnonymousHeadOmitEmpty", "StructFieldPtrAnonymousHeadOmitEmptyIndent", "StructField"},
{"StructFieldPtrHead", "StructFieldPtrHeadIndent", "StructField"},
{"StructFieldPtrHeadOmitEmpty", "StructFieldPtrHeadOmitEmptyIndent", "StructField"},
{"StructFieldPtrAnonymousHead", "StructFieldPtrAnonymousHeadIndent", "StructField"},
@ -211,9 +223,11 @@ func (t opType) fieldToOmitEmptyField() opType {
"StructFieldHead",
"StructFieldHeadOmitEmpty",
"StructFieldAnonymousHead",
"StructFieldAnonymousHeadOmitEmpty",
"StructFieldPtrHead",
"StructFieldPtrHeadOmitEmpty",
"StructFieldPtrAnonymousHead",
"StructFieldPtrAnonymousHeadOmitEmpty",
"StructField",
"StructFieldOmitEmpty",
} {
@ -239,6 +253,8 @@ func (t opType) fieldToOmitEmptyField() opType {
AnonymousPtrHead: "StructFieldPtrAnonymousHead",
OmitEmptyHead: "StructFieldHeadOmitEmpty",
OmitEmptyPtrHead: "StructFieldPtrHeadOmitEmpty",
AnonymousOmitEmptyHead: "StructFieldAnonymousHeadOmitEmpty",
AnonymousOmitEmptyPtrHead: "StructFieldPtrAnonymousHeadOmitEmpty",
}
headTypes := []headType{base}
for _, prim := range primitiveTypesUpper {
@ -249,6 +265,8 @@ func (t opType) fieldToOmitEmptyField() opType {
AnonymousPtrHead: fmt.Sprintf("%s%s", base.AnonymousPtrHead, prim),
OmitEmptyHead: fmt.Sprintf("%s%s", base.OmitEmptyHead, prim),
OmitEmptyPtrHead: fmt.Sprintf("%s%s", base.OmitEmptyPtrHead, prim),
AnonymousOmitEmptyHead: fmt.Sprintf("%s%s", base.AnonymousOmitEmptyHead, prim),
AnonymousOmitEmptyPtrHead: fmt.Sprintf("%s%s", base.AnonymousOmitEmptyPtrHead, prim),
})
}
for _, typ := range headTypes {
@ -259,6 +277,8 @@ func (t opType) fieldToOmitEmptyField() opType {
AnonymousPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousPtrHead),
OmitEmptyHead: fmt.Sprintf("%sIndent", typ.OmitEmptyHead),
OmitEmptyPtrHead: fmt.Sprintf("%sIndent", typ.OmitEmptyPtrHead),
AnonymousOmitEmptyHead: fmt.Sprintf("%sIndent", typ.AnonymousOmitEmptyHead),
AnonymousOmitEmptyPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousOmitEmptyPtrHead),
})
}

File diff suppressed because it is too large Load Diff

View File

@ -140,6 +140,13 @@ func Test_Marshal(t *testing.T) {
*T
B string `json:"b"`
}
type T2 struct {
A string `json:"a,omitempty"`
}
type U2 struct {
*T2
B string `json:"b,omitempty"`
}
t.Run("exists field", func(t *testing.T) {
bytes, err := json.Marshal(&U{
T: &T{
@ -149,6 +156,16 @@ func Test_Marshal(t *testing.T) {
})
assertErr(t, err)
assertEq(t, "embedded", `{"a":"aaa","b":"bbb"}`, string(bytes))
t.Run("omitempty", func(t *testing.T) {
bytes, err := json.Marshal(&U2{
T2: &T2{
A: "aaa",
},
B: "bbb",
})
assertErr(t, err)
assertEq(t, "embedded", `{"a":"aaa","b":"bbb"}`, string(bytes))
})
})
t.Run("none field", func(t *testing.T) {
bytes, err := json.Marshal(&U{
@ -156,6 +173,13 @@ func Test_Marshal(t *testing.T) {
})
assertErr(t, err)
assertEq(t, "embedded", `{"b":"bbb"}`, string(bytes))
t.Run("omitempty", func(t *testing.T) {
bytes, err := json.Marshal(&U2{
B: "bbb",
})
assertErr(t, err)
assertEq(t, "embedded", `{"b":"bbb"}`, string(bytes))
})
})
})
t.Run("omitempty", func(t *testing.T) {

View File

@ -1237,19 +1237,38 @@ func (e *Encoder) run(code *opcode) error {
e.encodeNull()
code = field.end.next
} else {
e.encodeIndent(code.indent)
e.encodeByte('{')
p := ptr + field.offset
if p == 0 || *(*uintptr)(unsafe.Pointer(p)) == 0 {
code = field.nextField
} else {
e.encodeIndent(code.indent + 1)
e.encodeBytes(field.key)
code = field.next
code.ptr = p
}
field.nextField.ptr = field.ptr
}
case opStructFieldPtrAnonymousHeadOmitEmpty:
if code.ptr != 0 {
code.ptr = e.ptrToPtr(code.ptr)
}
fallthrough
case opStructFieldAnonymousHeadOmitEmpty:
field := code.toStructFieldCode()
ptr := field.ptr
if ptr == 0 {
code = field.end.next
} else {
p := ptr + field.offset
if p == 0 || *(*uintptr)(unsafe.Pointer(p)) == 0 {
code = field.nextField
} else {
e.encodeBytes(field.key)
code = field.next
code.ptr = p
}
field.nextField.ptr = ptr
}
case opStructFieldPtrHeadOmitEmptyInt:
if code.ptr != 0 {
code.ptr = e.ptrToPtr(code.ptr)
@ -1262,19 +1281,38 @@ func (e *Encoder) run(code *opcode) error {
e.encodeNull()
code = field.end.next
} else {
e.encodeIndent(code.indent)
e.encodeByte('{')
v := e.ptrToInt(ptr + field.offset)
if v == 0 {
code = field.nextField
} else {
e.encodeIndent(code.indent + 1)
e.encodeBytes(field.key)
e.encodeInt(v)
code = field.next
}
field.nextField.ptr = field.ptr
}
case opStructFieldPtrAnonymousHeadOmitEmptyInt:
if code.ptr != 0 {
code.ptr = e.ptrToPtr(code.ptr)
}
fallthrough
case opStructFieldAnonymousHeadOmitEmptyInt:
field := code.toStructFieldCode()
ptr := field.ptr
if ptr == 0 {
code = field.end.next
} else {
v := e.ptrToInt(ptr + field.offset)
if v == 0 {
code = field.nextField
} else {
e.encodeBytes(field.key)
e.encodeInt(v)
code = field.next
}
field.nextField.ptr = ptr
}
case opStructFieldPtrHeadOmitEmptyInt8:
if code.ptr != 0 {
code.ptr = e.ptrToPtr(code.ptr)
@ -1287,18 +1325,37 @@ func (e *Encoder) run(code *opcode) error {
e.encodeNull()
code = field.end.next
} else {
e.encodeIndent(code.indent)
e.encodeByte('{')
v := e.ptrToInt8(ptr + field.offset)
if v == 0 {
code = field.nextField
} else {
e.encodeIndent(code.indent + 1)
e.encodeBytes(field.key)
e.encodeInt8(v)
code = field.next
}
field.nextField.ptr = field.ptr
field.nextField.ptr = ptr
}
case opStructFieldPtrAnonymousHeadOmitEmptyInt8:
if code.ptr != 0 {
code.ptr = e.ptrToPtr(code.ptr)
}
fallthrough
case opStructFieldAnonymousHeadOmitEmptyInt8:
field := code.toStructFieldCode()
ptr := field.ptr
if ptr == 0 {
code = field.end.next
} else {
v := e.ptrToInt8(ptr + field.offset)
if v == 0 {
code = field.nextField
} else {
e.encodeBytes(field.key)
e.encodeInt8(v)
code = field.next
}
field.nextField.ptr = ptr
}
case opStructFieldPtrHeadOmitEmptyInt16:
if code.ptr != 0 {
@ -1312,19 +1369,38 @@ func (e *Encoder) run(code *opcode) error {
e.encodeNull()
code = field.end.next
} else {
e.encodeIndent(code.indent)
e.encodeByte('{')
v := e.ptrToInt16(ptr + field.offset)
if v == 0 {
code = field.nextField
} else {
e.encodeIndent(code.indent + 1)
e.encodeBytes(field.key)
e.encodeInt16(v)
code = field.next
}
field.nextField.ptr = field.ptr
}
case opStructFieldPtrAnonymousHeadOmitEmptyInt16:
if code.ptr != 0 {
code.ptr = e.ptrToPtr(code.ptr)
}
fallthrough
case opStructFieldAnonymousHeadOmitEmptyInt16:
field := code.toStructFieldCode()
ptr := field.ptr
if ptr == 0 {
code = field.end.next
} else {
v := e.ptrToInt16(ptr + field.offset)
if v == 0 {
code = field.nextField
} else {
e.encodeBytes(field.key)
e.encodeInt16(v)
code = field.next
}
field.nextField.ptr = ptr
}
case opStructFieldPtrHeadOmitEmptyInt32:
if code.ptr != 0 {
code.ptr = e.ptrToPtr(code.ptr)
@ -1337,19 +1413,38 @@ func (e *Encoder) run(code *opcode) error {
e.encodeNull()
code = field.end.next
} else {
e.encodeIndent(code.indent)
e.encodeByte('{')
v := e.ptrToInt32(ptr + field.offset)
if v == 0 {
code = field.nextField
} else {
e.encodeIndent(code.indent + 1)
e.encodeBytes(field.key)
e.encodeInt32(v)
code = field.next
}
field.nextField.ptr = field.ptr
}
case opStructFieldPtrAnonymousHeadOmitEmptyInt32:
if code.ptr != 0 {
code.ptr = e.ptrToPtr(code.ptr)
}
fallthrough
case opStructFieldAnonymousHeadOmitEmptyInt32:
field := code.toStructFieldCode()
ptr := field.ptr
if ptr == 0 {
code = field.end.next
} else {
v := e.ptrToInt32(ptr + field.offset)
if v == 0 {
code = field.nextField
} else {
e.encodeBytes(field.key)
e.encodeInt32(v)
code = field.next
}
field.nextField.ptr = ptr
}
case opStructFieldPtrHeadOmitEmptyInt64:
if code.ptr != 0 {
code.ptr = e.ptrToPtr(code.ptr)
@ -1362,18 +1457,37 @@ func (e *Encoder) run(code *opcode) error {
e.encodeNull()
code = field.end.next
} else {
e.encodeIndent(code.indent)
e.encodeByte('{')
v := e.ptrToInt64(ptr + field.offset)
if v == 0 {
code = field.nextField
} else {
e.encodeIndent(code.indent + 1)
e.encodeBytes(field.key)
e.encodeInt64(v)
code = field.next
}
field.nextField.ptr = field.ptr
field.nextField.ptr = ptr
}
case opStructFieldPtrAnonymousHeadOmitEmptyInt64:
if code.ptr != 0 {
code.ptr = e.ptrToPtr(code.ptr)
}
fallthrough
case opStructFieldAnonymousHeadOmitEmptyInt64:
field := code.toStructFieldCode()
ptr := field.ptr
if ptr == 0 {
code = field.end.next
} else {
v := e.ptrToInt64(ptr + field.offset)
if v == 0 {
code = field.nextField
} else {
e.encodeBytes(field.key)
e.encodeInt64(v)
code = field.next
}
field.nextField.ptr = ptr
}
case opStructFieldPtrHeadOmitEmptyUint:
if code.ptr != 0 {
@ -1387,18 +1501,37 @@ func (e *Encoder) run(code *opcode) error {
e.encodeNull()
code = field.end.next
} else {
e.encodeIndent(code.indent)
e.encodeByte('{')
v := e.ptrToUint(ptr + field.offset)
if v == 0 {
code = field.nextField
} else {
e.encodeIndent(code.indent + 1)
e.encodeBytes(field.key)
e.encodeUint(v)
code = field.next
}
field.nextField.ptr = field.ptr
field.nextField.ptr = ptr
}
case opStructFieldPtrAnonymousHeadOmitEmptyUint:
if code.ptr != 0 {
code.ptr = e.ptrToPtr(code.ptr)
}
fallthrough
case opStructFieldAnonymousHeadOmitEmptyUint:
field := code.toStructFieldCode()
ptr := field.ptr
if ptr == 0 {
code = field.end.next
} else {
v := e.ptrToUint(ptr + field.offset)
if v == 0 {
code = field.nextField
} else {
e.encodeBytes(field.key)
e.encodeUint(v)
code = field.next
}
field.nextField.ptr = ptr
}
case opStructFieldPtrHeadOmitEmptyUint8:
if code.ptr != 0 {
@ -1412,18 +1545,37 @@ func (e *Encoder) run(code *opcode) error {
e.encodeNull()
code = field.end.next
} else {
e.encodeIndent(code.indent)
e.encodeByte('{')
v := e.ptrToUint8(ptr + field.offset)
if v == 0 {
code = field.nextField
} else {
e.encodeIndent(code.indent + 1)
e.encodeBytes(field.key)
e.encodeUint8(v)
code = field.next
}
field.nextField.ptr = field.ptr
field.nextField.ptr = ptr
}
case opStructFieldPtrAnonymousHeadOmitEmptyUint8:
if code.ptr != 0 {
code.ptr = e.ptrToPtr(code.ptr)
}
fallthrough
case opStructFieldAnonymousHeadOmitEmptyUint8:
field := code.toStructFieldCode()
ptr := field.ptr
if ptr == 0 {
code = field.end.next
} else {
v := e.ptrToUint8(ptr + field.offset)
if v == 0 {
code = field.nextField
} else {
e.encodeBytes(field.key)
e.encodeUint8(v)
code = field.next
}
field.nextField.ptr = ptr
}
case opStructFieldPtrHeadOmitEmptyUint16:
if code.ptr != 0 {
@ -1437,19 +1589,38 @@ func (e *Encoder) run(code *opcode) error {
e.encodeNull()
code = field.end.next
} else {
e.encodeIndent(code.indent)
e.encodeByte('{')
v := e.ptrToUint16(ptr + field.offset)
if v == 0 {
code = field.nextField
} else {
e.encodeIndent(code.indent + 1)
e.encodeBytes(field.key)
e.encodeUint16(v)
code = field.next
}
field.nextField.ptr = field.ptr
}
case opStructFieldPtrAnonymousHeadOmitEmptyUint16:
if code.ptr != 0 {
code.ptr = e.ptrToPtr(code.ptr)
}
fallthrough
case opStructFieldAnonymousHeadOmitEmptyUint16:
field := code.toStructFieldCode()
ptr := field.ptr
if ptr == 0 {
code = field.end.next
} else {
v := e.ptrToUint16(ptr + field.offset)
if v == 0 {
code = field.nextField
} else {
e.encodeBytes(field.key)
e.encodeUint16(v)
code = field.next
}
field.nextField.ptr = ptr
}
case opStructFieldPtrHeadOmitEmptyUint32:
if code.ptr != 0 {
code.ptr = e.ptrToPtr(code.ptr)
@ -1462,18 +1633,37 @@ func (e *Encoder) run(code *opcode) error {
e.encodeNull()
code = field.end.next
} else {
e.encodeIndent(code.indent)
e.encodeByte('{')
v := e.ptrToUint32(ptr + field.offset)
if v == 0 {
code = field.nextField
} else {
e.encodeIndent(code.indent + 1)
e.encodeBytes(field.key)
e.encodeUint32(v)
code = field.next
}
field.nextField.ptr = field.ptr
field.nextField.ptr = ptr
}
case opStructFieldPtrAnonymousHeadOmitEmptyUint32:
if code.ptr != 0 {
code.ptr = e.ptrToPtr(code.ptr)
}
fallthrough
case opStructFieldAnonymousHeadOmitEmptyUint32:
field := code.toStructFieldCode()
ptr := field.ptr
if ptr == 0 {
code = field.end.next
} else {
v := e.ptrToUint32(ptr + field.offset)
if v == 0 {
code = field.nextField
} else {
e.encodeBytes(field.key)
e.encodeUint32(v)
code = field.next
}
field.nextField.ptr = ptr
}
case opStructFieldPtrHeadOmitEmptyUint64:
if code.ptr != 0 {
@ -1487,19 +1677,38 @@ func (e *Encoder) run(code *opcode) error {
e.encodeNull()
code = field.end.next
} else {
e.encodeIndent(code.indent)
e.encodeByte('{')
v := e.ptrToUint64(ptr + field.offset)
if v == 0 {
code = field.nextField
} else {
e.encodeIndent(code.indent + 1)
e.encodeBytes(field.key)
e.encodeUint64(v)
code = field.next
}
field.nextField.ptr = field.ptr
}
case opStructFieldPtrAnonymousHeadOmitEmptyUint64:
if code.ptr != 0 {
code.ptr = e.ptrToPtr(code.ptr)
}
fallthrough
case opStructFieldAnonymousHeadOmitEmptyUint64:
field := code.toStructFieldCode()
ptr := field.ptr
if ptr == 0 {
code = field.end.next
} else {
v := e.ptrToUint64(ptr + field.offset)
if v == 0 {
code = field.nextField
} else {
e.encodeBytes(field.key)
e.encodeUint64(v)
code = field.next
}
field.nextField.ptr = ptr
}
case opStructFieldPtrHeadOmitEmptyFloat32:
if code.ptr != 0 {
code.ptr = e.ptrToPtr(code.ptr)
@ -1512,18 +1721,37 @@ func (e *Encoder) run(code *opcode) error {
e.encodeNull()
code = field.end.next
} else {
e.encodeIndent(code.indent)
e.encodeByte('{')
v := e.ptrToFloat32(ptr + field.offset)
if v == 0 {
code = field.nextField
} else {
e.encodeIndent(code.indent + 1)
e.encodeBytes(field.key)
e.encodeFloat32(v)
code = field.next
}
field.nextField.ptr = field.ptr
field.nextField.ptr = ptr
}
case opStructFieldPtrAnonymousHeadOmitEmptyFloat32:
if code.ptr != 0 {
code.ptr = e.ptrToPtr(code.ptr)
}
fallthrough
case opStructFieldAnonymousHeadOmitEmptyFloat32:
field := code.toStructFieldCode()
ptr := field.ptr
if ptr == 0 {
code = field.end.next
} else {
v := e.ptrToFloat32(ptr + field.offset)
if v == 0 {
code = field.nextField
} else {
e.encodeBytes(field.key)
e.encodeFloat32(v)
code = field.next
}
field.nextField.ptr = ptr
}
case opStructFieldPtrHeadOmitEmptyFloat64:
if code.ptr != 0 {
@ -1537,7 +1765,6 @@ func (e *Encoder) run(code *opcode) error {
e.encodeNull()
code = field.end.next
} else {
e.encodeIndent(code.indent)
e.encodeByte('{')
v := e.ptrToFloat64(ptr + field.offset)
if v == 0 {
@ -1549,13 +1776,39 @@ func (e *Encoder) run(code *opcode) error {
Str: strconv.FormatFloat(v, 'g', -1, 64),
}
}
e.encodeIndent(code.indent + 1)
e.encodeBytes(field.key)
e.encodeFloat64(v)
code = field.next
}
field.nextField.ptr = field.ptr
}
case opStructFieldPtrAnonymousHeadOmitEmptyFloat64:
if code.ptr != 0 {
code.ptr = e.ptrToPtr(code.ptr)
}
fallthrough
case opStructFieldAnonymousHeadOmitEmptyFloat64:
field := code.toStructFieldCode()
ptr := field.ptr
if ptr == 0 {
code = field.end.next
} else {
v := e.ptrToFloat64(ptr + field.offset)
if v == 0 {
code = field.nextField
} else {
if math.IsInf(v, 0) || math.IsNaN(v) {
return &UnsupportedValueError{
Value: reflect.ValueOf(v),
Str: strconv.FormatFloat(v, 'g', -1, 64),
}
}
e.encodeBytes(field.key)
e.encodeFloat64(v)
code = field.next
}
field.nextField.ptr = ptr
}
case opStructFieldPtrHeadOmitEmptyString:
if code.ptr != 0 {
code.ptr = e.ptrToPtr(code.ptr)
@ -1568,18 +1821,37 @@ func (e *Encoder) run(code *opcode) error {
e.encodeNull()
code = field.end.next
} else {
e.encodeIndent(code.indent)
e.encodeByte('{')
v := e.ptrToString(ptr + field.offset)
if v == "" {
code = field.nextField
} else {
e.encodeIndent(code.indent + 1)
e.encodeBytes(field.key)
e.encodeString(v)
code = field.next
}
field.nextField.ptr = field.ptr
field.nextField.ptr = ptr
}
case opStructFieldPtrAnonymousHeadOmitEmptyString:
if code.ptr != 0 {
code.ptr = e.ptrToPtr(code.ptr)
}
fallthrough
case opStructFieldAnonymousHeadOmitEmptyString:
field := code.toStructFieldCode()
ptr := field.ptr
if ptr == 0 {
code = field.end.next
} else {
v := e.ptrToString(ptr + field.offset)
if v == "" {
code = field.nextField
} else {
e.encodeBytes(field.key)
e.encodeString(v)
code = field.next
}
field.nextField.ptr = ptr
}
case opStructFieldPtrHeadOmitEmptyBool:
if code.ptr != 0 {
@ -1593,20 +1865,38 @@ func (e *Encoder) run(code *opcode) error {
e.encodeNull()
code = field.end.next
} else {
e.encodeIndent(code.indent)
e.encodeByte('{')
v := e.ptrToBool(ptr + field.offset)
if !v {
code = field.nextField
} else {
e.encodeIndent(code.indent + 1)
e.encodeBytes(field.key)
e.encodeBool(v)
code = field.next
}
field.nextField.ptr = field.ptr
field.nextField.ptr = ptr
}
case opStructFieldPtrAnonymousHeadOmitEmptyBool:
if code.ptr != 0 {
code.ptr = e.ptrToPtr(code.ptr)
}
fallthrough
case opStructFieldAnonymousHeadOmitEmptyBool:
field := code.toStructFieldCode()
ptr := field.ptr
if ptr == 0 {
code = field.end.next
} else {
v := e.ptrToBool(ptr + field.offset)
if !v {
code = field.nextField
} else {
e.encodeBytes(field.key)
e.encodeBool(v)
code = field.next
}
field.nextField.ptr = ptr
}
case opStructFieldPtrHeadOmitEmptyIndent:
if code.ptr != 0 {
code.ptr = e.ptrToPtr(code.ptr)