-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcode.go
More file actions
executable file
·122 lines (103 loc) · 2.14 KB
/
code.go
File metadata and controls
executable file
·122 lines (103 loc) · 2.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package wax
import (
"bytes"
"github.com/pkg/errors"
)
/*
code ::= size:u32 code:func => code (if size = ||func||)
func ::= (t*)*:vec(locals) e:expr => concat((t*)*),e* (if |concat((t*)*)| < 2^32)
locals ::= n:u32 t:valtype => tn
Here, code ranges over pairs (valtype*,expr).
The meta function concat((t*)*) concatenates all sequences ti* in (t*)*.
*/
type Code struct {
Size uint32
Code Func
}
func ParseCode(ber *BinaryEncodingReader) (*Code, error) {
// Read size
size64, _, err := ber.ReadVaruint()
if err != nil {
return nil, err
}
size := uint32(size64)
buf := make([]byte, size)
n, err := ber.Read(buf)
if err != nil {
return nil, err
}
if uint32(n) != size {
return nil, errors.New("insufficient data")
}
cr := NewBinaryEncodingReader(bytes.NewReader(buf))
fc, err := parseFuncInCodeSection(cr)
if err != nil {
return nil, err
}
f := Func{
Type: 0, // This must be retrieved from 'function section' later
Locals: concatLocals(fc.t),
Body: fc.e,
}
return &Code{
Size: size,
Code: f,
}, nil
}
type funcInCodeSection struct {
t []locals
e Expr
}
func parseFuncInCodeSection(ber *BinaryEncodingReader) (*funcInCodeSection, error) {
t, err := parseLocals(ber)
if err != nil {
return nil, err
}
e, err := ParseExpr(ber)
if err != nil {
return nil, err
}
return &funcInCodeSection{
t: t,
e: *e,
}, nil
}
type locals struct {
n uint32
t ValType
}
func parseLocals(ber *BinaryEncodingReader) ([]locals, error) {
// Read size of vector
size64, _, err := ber.ReadVaruint()
if err != nil {
return nil, err
}
size := uint32(size64)
result := make([]locals, 0, size)
for i := uint32(0); i < size; i++ {
// Read n
n64, _, err := ber.ReadVaruint()
if err != nil {
return nil, err
}
n := uint32(n64)
t, _, err := ParseValType(ber)
if err != nil {
return nil, err
}
result = append(result, locals{
n: n,
t: *t,
})
}
return result, nil
}
func concatLocals(ls []locals) []ValType {
result := make([]ValType, 0)
for _, l := range ls {
for i := uint32(0); i < l.n; i++ {
result = append(result, l.t)
}
}
return result
}