aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/goccy/go-json/internal/encoder/opcode.go
diff options
context:
space:
mode:
authorLunny Xiao <xiaolunwen@gmail.com>2021-08-13 07:11:42 +0800
committerGitHub <noreply@github.com>2021-08-13 01:11:42 +0200
commit7224cfc578c1ff9f6b52ad13d18d3ca37d7f8186 (patch)
tree763e29950bed8c31caba1dc2b943da87e6810202 /vendor/github.com/goccy/go-json/internal/encoder/opcode.go
parent5fbccad906f803c63e758ad3a168714430c9d1a9 (diff)
downloadgitea-7224cfc578c1ff9f6b52ad13d18d3ca37d7f8186.tar.gz
gitea-7224cfc578c1ff9f6b52ad13d18d3ca37d7f8186.zip
Upgrade xorm to v1.2.2 (#16663)
* Upgrade xorm to v1.2.2 * Change the Engine interface to match xorm v1.2.2
Diffstat (limited to 'vendor/github.com/goccy/go-json/internal/encoder/opcode.go')
-rw-r--r--vendor/github.com/goccy/go-json/internal/encoder/opcode.go766
1 files changed, 766 insertions, 0 deletions
diff --git a/vendor/github.com/goccy/go-json/internal/encoder/opcode.go b/vendor/github.com/goccy/go-json/internal/encoder/opcode.go
new file mode 100644
index 0000000000..c23a90b2e1
--- /dev/null
+++ b/vendor/github.com/goccy/go-json/internal/encoder/opcode.go
@@ -0,0 +1,766 @@
+package encoder
+
+import (
+ "fmt"
+ "strings"
+ "unsafe"
+
+ "github.com/goccy/go-json/internal/runtime"
+)
+
+const uintptrSize = 4 << (^uintptr(0) >> 63)
+
+type OpFlags uint16
+
+const (
+ AnonymousHeadFlags OpFlags = 1 << 0
+ AnonymousKeyFlags OpFlags = 1 << 1
+ IndirectFlags OpFlags = 1 << 2
+ IsTaggedKeyFlags OpFlags = 1 << 3
+ NilCheckFlags OpFlags = 1 << 4
+ AddrForMarshalerFlags OpFlags = 1 << 5
+ IsNextOpPtrTypeFlags OpFlags = 1 << 6
+ IsNilableTypeFlags OpFlags = 1 << 7
+ MarshalerContextFlags OpFlags = 1 << 8
+)
+
+type Opcode struct {
+ Op OpType // operation type
+ Idx uint32 // offset to access ptr
+ Next *Opcode // next opcode
+ End *Opcode // array/slice/struct/map end
+ NextField *Opcode // next struct field
+ Key string // struct field key
+ Offset uint32 // offset size from struct header
+ PtrNum uint8 // pointer number: e.g. double pointer is 2.
+ NumBitSize uint8
+ Flags OpFlags
+
+ Type *runtime.Type // go type
+ PrevField *Opcode // prev struct field
+ Jmp *CompiledCode // for recursive call
+ ElemIdx uint32 // offset to access array/slice/map elem
+ Length uint32 // offset to access slice/map length or array length
+ MapIter uint32 // offset to access map iterator
+ MapPos uint32 // offset to access position list for sorted map
+ Indent uint32 // indent number
+ Size uint32 // array/slice elem size
+ DisplayIdx uint32 // opcode index
+ DisplayKey string // key text to display
+}
+
+func (c *Opcode) MaxIdx() uint32 {
+ max := uint32(0)
+ for _, value := range []uint32{
+ c.Idx,
+ c.ElemIdx,
+ c.Length,
+ c.MapIter,
+ c.MapPos,
+ c.Size,
+ } {
+ if max < value {
+ max = value
+ }
+ }
+ return max
+}
+
+func (c *Opcode) ToHeaderType(isString bool) OpType {
+ switch c.Op {
+ case OpInt:
+ if isString {
+ return OpStructHeadIntString
+ }
+ return OpStructHeadInt
+ case OpIntPtr:
+ if isString {
+ return OpStructHeadIntPtrString
+ }
+ return OpStructHeadIntPtr
+ case OpUint:
+ if isString {
+ return OpStructHeadUintString
+ }
+ return OpStructHeadUint
+ case OpUintPtr:
+ if isString {
+ return OpStructHeadUintPtrString
+ }
+ return OpStructHeadUintPtr
+ case OpFloat32:
+ if isString {
+ return OpStructHeadFloat32String
+ }
+ return OpStructHeadFloat32
+ case OpFloat32Ptr:
+ if isString {
+ return OpStructHeadFloat32PtrString
+ }
+ return OpStructHeadFloat32Ptr
+ case OpFloat64:
+ if isString {
+ return OpStructHeadFloat64String
+ }
+ return OpStructHeadFloat64
+ case OpFloat64Ptr:
+ if isString {
+ return OpStructHeadFloat64PtrString
+ }
+ return OpStructHeadFloat64Ptr
+ case OpString:
+ if isString {
+ return OpStructHeadStringString
+ }
+ return OpStructHeadString
+ case OpStringPtr:
+ if isString {
+ return OpStructHeadStringPtrString
+ }
+ return OpStructHeadStringPtr
+ case OpNumber:
+ if isString {
+ return OpStructHeadNumberString
+ }
+ return OpStructHeadNumber
+ case OpNumberPtr:
+ if isString {
+ return OpStructHeadNumberPtrString
+ }
+ return OpStructHeadNumberPtr
+ case OpBool:
+ if isString {
+ return OpStructHeadBoolString
+ }
+ return OpStructHeadBool
+ case OpBoolPtr:
+ if isString {
+ return OpStructHeadBoolPtrString
+ }
+ return OpStructHeadBoolPtr
+ case OpBytes:
+ return OpStructHeadBytes
+ case OpBytesPtr:
+ return OpStructHeadBytesPtr
+ case OpMap:
+ return OpStructHeadMap
+ case OpMapPtr:
+ c.Op = OpMap
+ return OpStructHeadMapPtr
+ case OpArray:
+ return OpStructHeadArray
+ case OpArrayPtr:
+ c.Op = OpArray
+ return OpStructHeadArrayPtr
+ case OpSlice:
+ return OpStructHeadSlice
+ case OpSlicePtr:
+ c.Op = OpSlice
+ return OpStructHeadSlicePtr
+ case OpMarshalJSON:
+ return OpStructHeadMarshalJSON
+ case OpMarshalJSONPtr:
+ return OpStructHeadMarshalJSONPtr
+ case OpMarshalText:
+ return OpStructHeadMarshalText
+ case OpMarshalTextPtr:
+ return OpStructHeadMarshalTextPtr
+ }
+ return OpStructHead
+}
+
+func (c *Opcode) ToFieldType(isString bool) OpType {
+ switch c.Op {
+ case OpInt:
+ if isString {
+ return OpStructFieldIntString
+ }
+ return OpStructFieldInt
+ case OpIntPtr:
+ if isString {
+ return OpStructFieldIntPtrString
+ }
+ return OpStructFieldIntPtr
+ case OpUint:
+ if isString {
+ return OpStructFieldUintString
+ }
+ return OpStructFieldUint
+ case OpUintPtr:
+ if isString {
+ return OpStructFieldUintPtrString
+ }
+ return OpStructFieldUintPtr
+ case OpFloat32:
+ if isString {
+ return OpStructFieldFloat32String
+ }
+ return OpStructFieldFloat32
+ case OpFloat32Ptr:
+ if isString {
+ return OpStructFieldFloat32PtrString
+ }
+ return OpStructFieldFloat32Ptr
+ case OpFloat64:
+ if isString {
+ return OpStructFieldFloat64String
+ }
+ return OpStructFieldFloat64
+ case OpFloat64Ptr:
+ if isString {
+ return OpStructFieldFloat64PtrString
+ }
+ return OpStructFieldFloat64Ptr
+ case OpString:
+ if isString {
+ return OpStructFieldStringString
+ }
+ return OpStructFieldString
+ case OpStringPtr:
+ if isString {
+ return OpStructFieldStringPtrString
+ }
+ return OpStructFieldStringPtr
+ case OpNumber:
+ if isString {
+ return OpStructFieldNumberString
+ }
+ return OpStructFieldNumber
+ case OpNumberPtr:
+ if isString {
+ return OpStructFieldNumberPtrString
+ }
+ return OpStructFieldNumberPtr
+ case OpBool:
+ if isString {
+ return OpStructFieldBoolString
+ }
+ return OpStructFieldBool
+ case OpBoolPtr:
+ if isString {
+ return OpStructFieldBoolPtrString
+ }
+ return OpStructFieldBoolPtr
+ case OpBytes:
+ return OpStructFieldBytes
+ case OpBytesPtr:
+ return OpStructFieldBytesPtr
+ case OpMap:
+ return OpStructFieldMap
+ case OpMapPtr:
+ c.Op = OpMap
+ return OpStructFieldMapPtr
+ case OpArray:
+ return OpStructFieldArray
+ case OpArrayPtr:
+ c.Op = OpArray
+ return OpStructFieldArrayPtr
+ case OpSlice:
+ return OpStructFieldSlice
+ case OpSlicePtr:
+ c.Op = OpSlice
+ return OpStructFieldSlicePtr
+ case OpMarshalJSON:
+ return OpStructFieldMarshalJSON
+ case OpMarshalJSONPtr:
+ return OpStructFieldMarshalJSONPtr
+ case OpMarshalText:
+ return OpStructFieldMarshalText
+ case OpMarshalTextPtr:
+ return OpStructFieldMarshalTextPtr
+ }
+ return OpStructField
+}
+
+func newOpCode(ctx *compileContext, op OpType) *Opcode {
+ return newOpCodeWithNext(ctx, op, newEndOp(ctx))
+}
+
+func opcodeOffset(idx int) uint32 {
+ return uint32(idx) * uintptrSize
+}
+
+func copyOpcode(code *Opcode) *Opcode {
+ codeMap := map[uintptr]*Opcode{}
+ return code.copy(codeMap)
+}
+
+func setTotalLengthToInterfaceOp(code *Opcode) {
+ c := code
+ for c.Op != OpEnd && c.Op != OpInterfaceEnd {
+ if c.Op == OpInterface {
+ c.Length = uint32(code.TotalLength())
+ }
+ switch c.Op.CodeType() {
+ case CodeArrayElem, CodeSliceElem, CodeMapKey:
+ c = c.End
+ default:
+ c = c.Next
+ }
+ }
+}
+
+func ToEndCode(code *Opcode) *Opcode {
+ c := code
+ for c.Op != OpEnd && c.Op != OpInterfaceEnd {
+ switch c.Op.CodeType() {
+ case CodeArrayElem, CodeSliceElem, CodeMapKey:
+ c = c.End
+ default:
+ c = c.Next
+ }
+ }
+ return c
+}
+
+func copyToInterfaceOpcode(code *Opcode) *Opcode {
+ copied := copyOpcode(code)
+ c := copied
+ c = ToEndCode(c)
+ c.Idx += uintptrSize
+ c.ElemIdx = c.Idx + uintptrSize
+ c.Length = c.Idx + 2*uintptrSize
+ c.Op = OpInterfaceEnd
+ return copied
+}
+
+func newOpCodeWithNext(ctx *compileContext, op OpType, next *Opcode) *Opcode {
+ return &Opcode{
+ Op: op,
+ Idx: opcodeOffset(ctx.ptrIndex),
+ Next: next,
+ Type: ctx.typ,
+ DisplayIdx: ctx.opcodeIndex,
+ Indent: ctx.indent,
+ }
+}
+
+func newEndOp(ctx *compileContext) *Opcode {
+ return newOpCodeWithNext(ctx, OpEnd, nil)
+}
+
+func (c *Opcode) copy(codeMap map[uintptr]*Opcode) *Opcode {
+ if c == nil {
+ return nil
+ }
+ addr := uintptr(unsafe.Pointer(c))
+ if code, exists := codeMap[addr]; exists {
+ return code
+ }
+ copied := &Opcode{
+ Op: c.Op,
+ Key: c.Key,
+ PtrNum: c.PtrNum,
+ NumBitSize: c.NumBitSize,
+ Flags: c.Flags,
+ Idx: c.Idx,
+ Offset: c.Offset,
+ Type: c.Type,
+ DisplayIdx: c.DisplayIdx,
+ DisplayKey: c.DisplayKey,
+ ElemIdx: c.ElemIdx,
+ Length: c.Length,
+ MapIter: c.MapIter,
+ MapPos: c.MapPos,
+ Size: c.Size,
+ Indent: c.Indent,
+ }
+ codeMap[addr] = copied
+ copied.End = c.End.copy(codeMap)
+ copied.PrevField = c.PrevField.copy(codeMap)
+ copied.NextField = c.NextField.copy(codeMap)
+ copied.Next = c.Next.copy(codeMap)
+ copied.Jmp = c.Jmp
+ return copied
+}
+
+func (c *Opcode) BeforeLastCode() *Opcode {
+ code := c
+ for {
+ var nextCode *Opcode
+ switch code.Op.CodeType() {
+ case CodeArrayElem, CodeSliceElem, CodeMapKey:
+ nextCode = code.End
+ default:
+ nextCode = code.Next
+ }
+ if nextCode.Op == OpEnd {
+ return code
+ }
+ code = nextCode
+ }
+}
+
+func (c *Opcode) TotalLength() int {
+ var idx int
+ code := c
+ for code.Op != OpEnd && code.Op != OpInterfaceEnd {
+ maxIdx := int(code.MaxIdx() / uintptrSize)
+ if idx < maxIdx {
+ idx = maxIdx
+ }
+ if code.Op == OpRecursiveEnd {
+ break
+ }
+ switch code.Op.CodeType() {
+ case CodeArrayElem, CodeSliceElem, CodeMapKey:
+ code = code.End
+ default:
+ code = code.Next
+ }
+ }
+ maxIdx := int(code.MaxIdx() / uintptrSize)
+ if idx < maxIdx {
+ idx = maxIdx
+ }
+ return idx + 1
+}
+
+func (c *Opcode) decOpcodeIndex() {
+ for code := c; code.Op != OpEnd; {
+ code.DisplayIdx--
+ if code.Idx > 0 {
+ code.Idx -= uintptrSize
+ }
+ if code.ElemIdx > 0 {
+ code.ElemIdx -= uintptrSize
+ }
+ if code.MapIter > 0 {
+ code.MapIter -= uintptrSize
+ }
+ if code.Length > 0 && code.Op.CodeType() != CodeArrayHead && code.Op.CodeType() != CodeArrayElem {
+ code.Length -= uintptrSize
+ }
+ switch code.Op.CodeType() {
+ case CodeArrayElem, CodeSliceElem, CodeMapKey:
+ code = code.End
+ default:
+ code = code.Next
+ }
+ }
+}
+
+func (c *Opcode) decIndent() {
+ for code := c; code.Op != OpEnd; {
+ code.Indent--
+ switch code.Op.CodeType() {
+ case CodeArrayElem, CodeSliceElem, CodeMapKey:
+ code = code.End
+ default:
+ code = code.Next
+ }
+ }
+}
+
+func (c *Opcode) dumpHead(code *Opcode) string {
+ var length uint32
+ if code.Op.CodeType() == CodeArrayHead {
+ length = code.Length
+ } else {
+ length = code.Length / uintptrSize
+ }
+ return fmt.Sprintf(
+ `[%d]%s%s ([idx:%d][elemIdx:%d][length:%d])`,
+ code.DisplayIdx,
+ strings.Repeat("-", int(code.Indent)),
+ code.Op,
+ code.Idx/uintptrSize,
+ code.ElemIdx/uintptrSize,
+ length,
+ )
+}
+
+func (c *Opcode) dumpMapHead(code *Opcode) string {
+ return fmt.Sprintf(
+ `[%d]%s%s ([idx:%d][elemIdx:%d][length:%d][mapIter:%d])`,
+ code.DisplayIdx,
+ strings.Repeat("-", int(code.Indent)),
+ code.Op,
+ code.Idx/uintptrSize,
+ code.ElemIdx/uintptrSize,
+ code.Length/uintptrSize,
+ code.MapIter/uintptrSize,
+ )
+}
+
+func (c *Opcode) dumpMapEnd(code *Opcode) string {
+ return fmt.Sprintf(
+ `[%d]%s%s ([idx:%d][mapPos:%d][length:%d])`,
+ code.DisplayIdx,
+ strings.Repeat("-", int(code.Indent)),
+ code.Op,
+ code.Idx/uintptrSize,
+ code.MapPos/uintptrSize,
+ code.Length/uintptrSize,
+ )
+}
+
+func (c *Opcode) dumpElem(code *Opcode) string {
+ var length uint32
+ if code.Op.CodeType() == CodeArrayElem {
+ length = code.Length
+ } else {
+ length = code.Length / uintptrSize
+ }
+ return fmt.Sprintf(
+ `[%d]%s%s ([idx:%d][elemIdx:%d][length:%d][size:%d])`,
+ code.DisplayIdx,
+ strings.Repeat("-", int(code.Indent)),
+ code.Op,
+ code.Idx/uintptrSize,
+ code.ElemIdx/uintptrSize,
+ length,
+ code.Size,
+ )
+}
+
+func (c *Opcode) dumpField(code *Opcode) string {
+ return fmt.Sprintf(
+ `[%d]%s%s ([idx:%d][key:%s][offset:%d])`,
+ code.DisplayIdx,
+ strings.Repeat("-", int(code.Indent)),
+ code.Op,
+ code.Idx/uintptrSize,
+ code.DisplayKey,
+ code.Offset,
+ )
+}
+
+func (c *Opcode) dumpKey(code *Opcode) string {
+ return fmt.Sprintf(
+ `[%d]%s%s ([idx:%d][elemIdx:%d][length:%d][mapIter:%d])`,
+ code.DisplayIdx,
+ strings.Repeat("-", int(code.Indent)),
+ code.Op,
+ code.Idx/uintptrSize,
+ code.ElemIdx/uintptrSize,
+ code.Length/uintptrSize,
+ code.MapIter/uintptrSize,
+ )
+}
+
+func (c *Opcode) dumpValue(code *Opcode) string {
+ return fmt.Sprintf(
+ `[%d]%s%s ([idx:%d][mapIter:%d])`,
+ code.DisplayIdx,
+ strings.Repeat("-", int(code.Indent)),
+ code.Op,
+ code.Idx/uintptrSize,
+ code.MapIter/uintptrSize,
+ )
+}
+
+func (c *Opcode) Dump() string {
+ codes := []string{}
+ for code := c; code.Op != OpEnd && code.Op != OpInterfaceEnd; {
+ switch code.Op.CodeType() {
+ case CodeSliceHead:
+ codes = append(codes, c.dumpHead(code))
+ code = code.Next
+ case CodeMapHead:
+ codes = append(codes, c.dumpMapHead(code))
+ code = code.Next
+ case CodeArrayElem, CodeSliceElem:
+ codes = append(codes, c.dumpElem(code))
+ code = code.End
+ case CodeMapKey:
+ codes = append(codes, c.dumpKey(code))
+ code = code.End
+ case CodeMapValue:
+ codes = append(codes, c.dumpValue(code))
+ code = code.Next
+ case CodeMapEnd:
+ codes = append(codes, c.dumpMapEnd(code))
+ code = code.Next
+ case CodeStructField:
+ codes = append(codes, c.dumpField(code))
+ code = code.Next
+ case CodeStructEnd:
+ codes = append(codes, c.dumpField(code))
+ code = code.Next
+ default:
+ codes = append(codes, fmt.Sprintf(
+ "[%d]%s%s ([idx:%d])",
+ code.DisplayIdx,
+ strings.Repeat("-", int(code.Indent)),
+ code.Op,
+ code.Idx/uintptrSize,
+ ))
+ code = code.Next
+ }
+ }
+ return strings.Join(codes, "\n")
+}
+
+func prevField(code *Opcode, removedFields map[*Opcode]struct{}) *Opcode {
+ if _, exists := removedFields[code]; exists {
+ return prevField(code.PrevField, removedFields)
+ }
+ return code
+}
+
+func nextField(code *Opcode, removedFields map[*Opcode]struct{}) *Opcode {
+ if _, exists := removedFields[code]; exists {
+ return nextField(code.NextField, removedFields)
+ }
+ return code
+}
+
+func linkPrevToNextField(cur *Opcode, removedFields map[*Opcode]struct{}) {
+ prev := prevField(cur.PrevField, removedFields)
+ prev.NextField = nextField(cur.NextField, removedFields)
+ code := prev
+ fcode := cur
+ for {
+ var nextCode *Opcode
+ switch code.Op.CodeType() {
+ case CodeArrayElem, CodeSliceElem, CodeMapKey:
+ nextCode = code.End
+ default:
+ nextCode = code.Next
+ }
+ if nextCode == fcode {
+ code.Next = fcode.Next
+ break
+ } else if nextCode.Op == OpEnd {
+ break
+ }
+ code = nextCode
+ }
+}
+
+func newSliceHeaderCode(ctx *compileContext) *Opcode {
+ idx := opcodeOffset(ctx.ptrIndex)
+ ctx.incPtrIndex()
+ elemIdx := opcodeOffset(ctx.ptrIndex)
+ ctx.incPtrIndex()
+ length := opcodeOffset(ctx.ptrIndex)
+ return &Opcode{
+ Op: OpSlice,
+ Idx: idx,
+ DisplayIdx: ctx.opcodeIndex,
+ ElemIdx: elemIdx,
+ Length: length,
+ Indent: ctx.indent,
+ }
+}
+
+func newSliceElemCode(ctx *compileContext, head *Opcode, size uintptr) *Opcode {
+ return &Opcode{
+ Op: OpSliceElem,
+ Idx: head.Idx,
+ DisplayIdx: ctx.opcodeIndex,
+ ElemIdx: head.ElemIdx,
+ Length: head.Length,
+ Indent: ctx.indent,
+ Size: uint32(size),
+ }
+}
+
+func newArrayHeaderCode(ctx *compileContext, alen int) *Opcode {
+ idx := opcodeOffset(ctx.ptrIndex)
+ ctx.incPtrIndex()
+ elemIdx := opcodeOffset(ctx.ptrIndex)
+ return &Opcode{
+ Op: OpArray,
+ Idx: idx,
+ DisplayIdx: ctx.opcodeIndex,
+ ElemIdx: elemIdx,
+ Indent: ctx.indent,
+ Length: uint32(alen),
+ }
+}
+
+func newArrayElemCode(ctx *compileContext, head *Opcode, length int, size uintptr) *Opcode {
+ return &Opcode{
+ Op: OpArrayElem,
+ Idx: head.Idx,
+ DisplayIdx: ctx.opcodeIndex,
+ ElemIdx: head.ElemIdx,
+ Length: uint32(length),
+ Indent: ctx.indent,
+ Size: uint32(size),
+ }
+}
+
+func newMapHeaderCode(ctx *compileContext) *Opcode {
+ idx := opcodeOffset(ctx.ptrIndex)
+ ctx.incPtrIndex()
+ elemIdx := opcodeOffset(ctx.ptrIndex)
+ ctx.incPtrIndex()
+ length := opcodeOffset(ctx.ptrIndex)
+ ctx.incPtrIndex()
+ mapIter := opcodeOffset(ctx.ptrIndex)
+ return &Opcode{
+ Op: OpMap,
+ Idx: idx,
+ Type: ctx.typ,
+ DisplayIdx: ctx.opcodeIndex,
+ ElemIdx: elemIdx,
+ Length: length,
+ MapIter: mapIter,
+ Indent: ctx.indent,
+ }
+}
+
+func newMapKeyCode(ctx *compileContext, head *Opcode) *Opcode {
+ return &Opcode{
+ Op: OpMapKey,
+ Idx: opcodeOffset(ctx.ptrIndex),
+ DisplayIdx: ctx.opcodeIndex,
+ ElemIdx: head.ElemIdx,
+ Length: head.Length,
+ MapIter: head.MapIter,
+ Indent: ctx.indent,
+ }
+}
+
+func newMapValueCode(ctx *compileContext, head *Opcode) *Opcode {
+ return &Opcode{
+ Op: OpMapValue,
+ Idx: opcodeOffset(ctx.ptrIndex),
+ DisplayIdx: ctx.opcodeIndex,
+ ElemIdx: head.ElemIdx,
+ Length: head.Length,
+ MapIter: head.MapIter,
+ Indent: ctx.indent,
+ }
+}
+
+func newMapEndCode(ctx *compileContext, head *Opcode) *Opcode {
+ mapPos := opcodeOffset(ctx.ptrIndex)
+ ctx.incPtrIndex()
+ idx := opcodeOffset(ctx.ptrIndex)
+ return &Opcode{
+ Op: OpMapEnd,
+ Idx: idx,
+ Next: newEndOp(ctx),
+ DisplayIdx: ctx.opcodeIndex,
+ Length: head.Length,
+ MapPos: mapPos,
+ Indent: ctx.indent,
+ }
+}
+
+func newInterfaceCode(ctx *compileContext) *Opcode {
+ return &Opcode{
+ Op: OpInterface,
+ Idx: opcodeOffset(ctx.ptrIndex),
+ Next: newEndOp(ctx),
+ Type: ctx.typ,
+ DisplayIdx: ctx.opcodeIndex,
+ Indent: ctx.indent,
+ }
+}
+
+func newRecursiveCode(ctx *compileContext, jmp *CompiledCode) *Opcode {
+ return &Opcode{
+ Op: OpRecursive,
+ Idx: opcodeOffset(ctx.ptrIndex),
+ Next: newEndOp(ctx),
+ Type: ctx.typ,
+ DisplayIdx: ctx.opcodeIndex,
+ Indent: ctx.indent,
+ Jmp: jmp,
+ }
+}