Adding upstream version 0.10.5.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
104c0c203d
commit
e733edafba
141 changed files with 102352 additions and 0 deletions
752
internal/encoder/opcode.go
Normal file
752
internal/encoder/opcode.go
Normal file
|
@ -0,0 +1,752 @@
|
|||
package encoder
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"sort"
|
||||
"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
|
||||
NonEmptyInterfaceFlags OpFlags = 1 << 9
|
||||
)
|
||||
|
||||
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
|
||||
Jmp *CompiledCode // for recursive call
|
||||
FieldQuery *FieldQuery // field query for Interface / MarshalJSON / MarshalText
|
||||
ElemIdx uint32 // offset to access array/slice elem
|
||||
Length uint32 // offset to access slice length or array length
|
||||
Indent uint32 // indent number
|
||||
Size uint32 // array/slice elem size
|
||||
DisplayIdx uint32 // opcode index
|
||||
DisplayKey string // key text to display
|
||||
}
|
||||
|
||||
func (c *Opcode) Validate() error {
|
||||
var prevIdx uint32
|
||||
for code := c; !code.IsEnd(); {
|
||||
if prevIdx != 0 {
|
||||
if code.DisplayIdx != prevIdx+1 {
|
||||
return fmt.Errorf(
|
||||
"invalid index. previous display index is %d but next is %d. dump = %s",
|
||||
prevIdx, code.DisplayIdx, c.Dump(),
|
||||
)
|
||||
}
|
||||
}
|
||||
prevIdx = code.DisplayIdx
|
||||
code = code.IterNext()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Opcode) IterNext() *Opcode {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
switch c.Op.CodeType() {
|
||||
case CodeArrayElem, CodeSliceElem, CodeMapKey:
|
||||
return c.End
|
||||
default:
|
||||
return c.Next
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Opcode) IsEnd() bool {
|
||||
if c == nil {
|
||||
return true
|
||||
}
|
||||
return c.Op == OpEnd || c.Op == OpInterfaceEnd || c.Op == OpRecursiveEnd
|
||||
}
|
||||
|
||||
func (c *Opcode) MaxIdx() uint32 {
|
||||
max := uint32(0)
|
||||
for _, value := range []uint32{
|
||||
c.Idx,
|
||||
c.ElemIdx,
|
||||
c.Length,
|
||||
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, typ *runtime.Type, op OpType) *Opcode {
|
||||
return newOpCodeWithNext(ctx, typ, op, newEndOp(ctx, typ))
|
||||
}
|
||||
|
||||
func opcodeOffset(idx int) uint32 {
|
||||
return uint32(idx) * uintptrSize
|
||||
}
|
||||
|
||||
func getCodeAddrByIdx(head *Opcode, idx uint32) *Opcode {
|
||||
addr := uintptr(unsafe.Pointer(head)) + uintptr(idx)*unsafe.Sizeof(Opcode{})
|
||||
return *(**Opcode)(unsafe.Pointer(&addr))
|
||||
}
|
||||
|
||||
func copyOpcode(code *Opcode) *Opcode {
|
||||
codeNum := ToEndCode(code).DisplayIdx + 1
|
||||
codeSlice := make([]Opcode, codeNum)
|
||||
head := (*Opcode)((*runtime.SliceHeader)(unsafe.Pointer(&codeSlice)).Data)
|
||||
ptr := head
|
||||
c := code
|
||||
for {
|
||||
*ptr = 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,
|
||||
FieldQuery: c.FieldQuery,
|
||||
DisplayIdx: c.DisplayIdx,
|
||||
DisplayKey: c.DisplayKey,
|
||||
ElemIdx: c.ElemIdx,
|
||||
Length: c.Length,
|
||||
Size: c.Size,
|
||||
Indent: c.Indent,
|
||||
Jmp: c.Jmp,
|
||||
}
|
||||
if c.End != nil {
|
||||
ptr.End = getCodeAddrByIdx(head, c.End.DisplayIdx)
|
||||
}
|
||||
if c.NextField != nil {
|
||||
ptr.NextField = getCodeAddrByIdx(head, c.NextField.DisplayIdx)
|
||||
}
|
||||
if c.Next != nil {
|
||||
ptr.Next = getCodeAddrByIdx(head, c.Next.DisplayIdx)
|
||||
}
|
||||
if c.IsEnd() {
|
||||
break
|
||||
}
|
||||
ptr = getCodeAddrByIdx(head, c.DisplayIdx+1)
|
||||
c = c.IterNext()
|
||||
}
|
||||
return head
|
||||
}
|
||||
|
||||
func setTotalLengthToInterfaceOp(code *Opcode) {
|
||||
for c := code; !c.IsEnd(); {
|
||||
if c.Op == OpInterface || c.Op == OpInterfacePtr {
|
||||
c.Length = uint32(code.TotalLength())
|
||||
}
|
||||
c = c.IterNext()
|
||||
}
|
||||
}
|
||||
|
||||
func ToEndCode(code *Opcode) *Opcode {
|
||||
c := code
|
||||
for !c.IsEnd() {
|
||||
c = c.IterNext()
|
||||
}
|
||||
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, typ *runtime.Type, op OpType, next *Opcode) *Opcode {
|
||||
return &Opcode{
|
||||
Op: op,
|
||||
Idx: opcodeOffset(ctx.ptrIndex),
|
||||
Next: next,
|
||||
Type: typ,
|
||||
DisplayIdx: ctx.opcodeIndex,
|
||||
Indent: ctx.indent,
|
||||
}
|
||||
}
|
||||
|
||||
func newEndOp(ctx *compileContext, typ *runtime.Type) *Opcode {
|
||||
return newOpCodeWithNext(ctx, typ, OpEnd, nil)
|
||||
}
|
||||
|
||||
func (c *Opcode) TotalLength() int {
|
||||
var idx int
|
||||
code := c
|
||||
for !code.IsEnd() {
|
||||
maxIdx := int(code.MaxIdx() / uintptrSize)
|
||||
if idx < maxIdx {
|
||||
idx = maxIdx
|
||||
}
|
||||
if code.Op == OpRecursiveEnd {
|
||||
break
|
||||
}
|
||||
code = code.IterNext()
|
||||
}
|
||||
maxIdx := int(code.MaxIdx() / uintptrSize)
|
||||
if idx < maxIdx {
|
||||
idx = maxIdx
|
||||
}
|
||||
return idx + 1
|
||||
}
|
||||
|
||||
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(
|
||||
`[%03d]%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(
|
||||
`[%03d]%s%s ([idx:%d])`,
|
||||
code.DisplayIdx,
|
||||
strings.Repeat("-", int(code.Indent)),
|
||||
code.Op,
|
||||
code.Idx/uintptrSize,
|
||||
)
|
||||
}
|
||||
|
||||
func (c *Opcode) dumpMapEnd(code *Opcode) string {
|
||||
return fmt.Sprintf(
|
||||
`[%03d]%s%s ([idx:%d])`,
|
||||
code.DisplayIdx,
|
||||
strings.Repeat("-", int(code.Indent)),
|
||||
code.Op,
|
||||
code.Idx/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(
|
||||
`[%03d]%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(
|
||||
`[%03d]%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(
|
||||
`[%03d]%s%s ([idx:%d])`,
|
||||
code.DisplayIdx,
|
||||
strings.Repeat("-", int(code.Indent)),
|
||||
code.Op,
|
||||
code.Idx/uintptrSize,
|
||||
)
|
||||
}
|
||||
|
||||
func (c *Opcode) dumpValue(code *Opcode) string {
|
||||
return fmt.Sprintf(
|
||||
`[%03d]%s%s ([idx:%d])`,
|
||||
code.DisplayIdx,
|
||||
strings.Repeat("-", int(code.Indent)),
|
||||
code.Op,
|
||||
code.Idx/uintptrSize,
|
||||
)
|
||||
}
|
||||
|
||||
func (c *Opcode) Dump() string {
|
||||
codes := []string{}
|
||||
for code := c; !code.IsEnd(); {
|
||||
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(
|
||||
"[%03d]%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 (c *Opcode) DumpDOT() string {
|
||||
type edge struct {
|
||||
from, to *Opcode
|
||||
label string
|
||||
weight int
|
||||
}
|
||||
var edges []edge
|
||||
|
||||
b := &bytes.Buffer{}
|
||||
fmt.Fprintf(b, "digraph \"%p\" {\n", c.Type)
|
||||
fmt.Fprintln(b, "mclimit=1.5;\nrankdir=TD;\nordering=out;\nnode[shape=box];")
|
||||
for code := c; !code.IsEnd(); {
|
||||
label := code.Op.String()
|
||||
fmt.Fprintf(b, "\"%p\" [label=%q];\n", code, label)
|
||||
if p := code.Next; p != nil {
|
||||
edges = append(edges, edge{
|
||||
from: code,
|
||||
to: p,
|
||||
label: "Next",
|
||||
weight: 10,
|
||||
})
|
||||
}
|
||||
if p := code.NextField; p != nil {
|
||||
edges = append(edges, edge{
|
||||
from: code,
|
||||
to: p,
|
||||
label: "NextField",
|
||||
weight: 2,
|
||||
})
|
||||
}
|
||||
if p := code.End; p != nil {
|
||||
edges = append(edges, edge{
|
||||
from: code,
|
||||
to: p,
|
||||
label: "End",
|
||||
weight: 1,
|
||||
})
|
||||
}
|
||||
if p := code.Jmp; p != nil {
|
||||
edges = append(edges, edge{
|
||||
from: code,
|
||||
to: p.Code,
|
||||
label: "Jmp",
|
||||
weight: 1,
|
||||
})
|
||||
}
|
||||
|
||||
switch code.Op.CodeType() {
|
||||
case CodeSliceHead:
|
||||
code = code.Next
|
||||
case CodeMapHead:
|
||||
code = code.Next
|
||||
case CodeArrayElem, CodeSliceElem:
|
||||
code = code.End
|
||||
case CodeMapKey:
|
||||
code = code.End
|
||||
case CodeMapValue:
|
||||
code = code.Next
|
||||
case CodeMapEnd:
|
||||
code = code.Next
|
||||
case CodeStructField:
|
||||
code = code.Next
|
||||
case CodeStructEnd:
|
||||
code = code.Next
|
||||
default:
|
||||
code = code.Next
|
||||
}
|
||||
if code.IsEnd() {
|
||||
fmt.Fprintf(b, "\"%p\" [label=%q];\n", code, code.Op.String())
|
||||
}
|
||||
}
|
||||
sort.Slice(edges, func(i, j int) bool {
|
||||
return edges[i].to.DisplayIdx < edges[j].to.DisplayIdx
|
||||
})
|
||||
for _, e := range edges {
|
||||
fmt.Fprintf(b, "\"%p\" -> \"%p\" [label=%q][weight=%d];\n", e.from, e.to, e.label, e.weight)
|
||||
}
|
||||
fmt.Fprint(b, "}")
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func newSliceHeaderCode(ctx *compileContext, typ *runtime.Type) *Opcode {
|
||||
idx := opcodeOffset(ctx.ptrIndex)
|
||||
ctx.incPtrIndex()
|
||||
elemIdx := opcodeOffset(ctx.ptrIndex)
|
||||
ctx.incPtrIndex()
|
||||
length := opcodeOffset(ctx.ptrIndex)
|
||||
return &Opcode{
|
||||
Op: OpSlice,
|
||||
Type: typ,
|
||||
Idx: idx,
|
||||
DisplayIdx: ctx.opcodeIndex,
|
||||
ElemIdx: elemIdx,
|
||||
Length: length,
|
||||
Indent: ctx.indent,
|
||||
}
|
||||
}
|
||||
|
||||
func newSliceElemCode(ctx *compileContext, typ *runtime.Type, head *Opcode, size uintptr) *Opcode {
|
||||
return &Opcode{
|
||||
Op: OpSliceElem,
|
||||
Type: typ,
|
||||
Idx: head.Idx,
|
||||
DisplayIdx: ctx.opcodeIndex,
|
||||
ElemIdx: head.ElemIdx,
|
||||
Length: head.Length,
|
||||
Indent: ctx.indent,
|
||||
Size: uint32(size),
|
||||
}
|
||||
}
|
||||
|
||||
func newArrayHeaderCode(ctx *compileContext, typ *runtime.Type, alen int) *Opcode {
|
||||
idx := opcodeOffset(ctx.ptrIndex)
|
||||
ctx.incPtrIndex()
|
||||
elemIdx := opcodeOffset(ctx.ptrIndex)
|
||||
return &Opcode{
|
||||
Op: OpArray,
|
||||
Type: typ,
|
||||
Idx: idx,
|
||||
DisplayIdx: ctx.opcodeIndex,
|
||||
ElemIdx: elemIdx,
|
||||
Indent: ctx.indent,
|
||||
Length: uint32(alen),
|
||||
}
|
||||
}
|
||||
|
||||
func newArrayElemCode(ctx *compileContext, typ *runtime.Type, head *Opcode, length int, size uintptr) *Opcode {
|
||||
return &Opcode{
|
||||
Op: OpArrayElem,
|
||||
Type: typ,
|
||||
Idx: head.Idx,
|
||||
DisplayIdx: ctx.opcodeIndex,
|
||||
ElemIdx: head.ElemIdx,
|
||||
Length: uint32(length),
|
||||
Indent: ctx.indent,
|
||||
Size: uint32(size),
|
||||
}
|
||||
}
|
||||
|
||||
func newMapHeaderCode(ctx *compileContext, typ *runtime.Type) *Opcode {
|
||||
idx := opcodeOffset(ctx.ptrIndex)
|
||||
ctx.incPtrIndex()
|
||||
return &Opcode{
|
||||
Op: OpMap,
|
||||
Type: typ,
|
||||
Idx: idx,
|
||||
DisplayIdx: ctx.opcodeIndex,
|
||||
Indent: ctx.indent,
|
||||
}
|
||||
}
|
||||
|
||||
func newMapKeyCode(ctx *compileContext, typ *runtime.Type, head *Opcode) *Opcode {
|
||||
return &Opcode{
|
||||
Op: OpMapKey,
|
||||
Type: typ,
|
||||
Idx: head.Idx,
|
||||
DisplayIdx: ctx.opcodeIndex,
|
||||
Indent: ctx.indent,
|
||||
}
|
||||
}
|
||||
|
||||
func newMapValueCode(ctx *compileContext, typ *runtime.Type, head *Opcode) *Opcode {
|
||||
return &Opcode{
|
||||
Op: OpMapValue,
|
||||
Type: typ,
|
||||
Idx: head.Idx,
|
||||
DisplayIdx: ctx.opcodeIndex,
|
||||
Indent: ctx.indent,
|
||||
}
|
||||
}
|
||||
|
||||
func newMapEndCode(ctx *compileContext, typ *runtime.Type, head *Opcode) *Opcode {
|
||||
return &Opcode{
|
||||
Op: OpMapEnd,
|
||||
Type: typ,
|
||||
Idx: head.Idx,
|
||||
DisplayIdx: ctx.opcodeIndex,
|
||||
Indent: ctx.indent,
|
||||
Next: newEndOp(ctx, typ),
|
||||
}
|
||||
}
|
||||
|
||||
func newRecursiveCode(ctx *compileContext, typ *runtime.Type, jmp *CompiledCode) *Opcode {
|
||||
return &Opcode{
|
||||
Op: OpRecursive,
|
||||
Type: typ,
|
||||
Idx: opcodeOffset(ctx.ptrIndex),
|
||||
Next: newEndOp(ctx, typ),
|
||||
DisplayIdx: ctx.opcodeIndex,
|
||||
Indent: ctx.indent,
|
||||
Jmp: jmp,
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue