OSDN Git Service

modify unit test for check_test (#4)
[bytom/equity.git] / compiler / ast.go
1 package compiler
2
3 import (
4         "encoding/hex"
5         "fmt"
6         "strconv"
7         "strings"
8
9         chainjson "github.com/bytom/encoding/json"
10 )
11
12 // Contract is a compiled Equity contract.
13 type Contract struct {
14         // Name is the contract name.
15         Name string `json:"name"`
16
17         // Params is the list of contract parameters.
18         Params []*Param `json:"params,omitempty"`
19
20         // Clauses is the list of contract clauses.
21         Clauses []*Clause `json:"clauses"`
22
23         // Value is the name of the value locked by the contract.
24         Value ValueInfo `json:"value"`
25
26         // Body is the optimized bytecode of the contract body. This is not
27         // a complete program!  Use instantiate to turn this (plus some
28         // arguments) into a program.
29         Body chainjson.HexBytes `json:"body_bytecode"`
30
31         // Opcodes is the human-readable string of opcodes corresponding to
32         // Body.
33         Opcodes string `json:"body_opcodes,omitempty"`
34
35         // Recursive tells whether this contract calls itself.  (This is
36         // used to select between two possible instantiation options.)
37         Recursive bool `json:"recursive"`
38
39         // Pre-optimized list of instruction steps, with stack snapshots.
40         Steps []Step `json:"-"`
41 }
42
43 // Param is a contract or clause parameter.
44 type Param struct {
45         // Name is the parameter name.
46         Name string `json:"name"`
47
48         // Type is the declared parameter type.
49         Type typeDesc `json:"type"`
50
51         // InferredType, if available, is a more-specific type than Type,
52         // inferred from the logic of the contract.
53         InferredType typeDesc `json:"inferred_type,omitempty"`
54 }
55
56 // Clause is a compiled contract clause.
57 type Clause struct {
58         // Name is the clause name.
59         Name string `json:"name"`
60
61         // Params is the list of clause parameters.
62         Params []*Param `json:"params,omitempty"`
63
64         statements []statement
65
66         // BlockHeight is the list of expressions passed to greater()/less() in this
67         // clause.
68         BlockHeight []string `json:"blockheight,omitempty"`
69
70         // HashCalls is the list of hash functions and their arguments used
71         // in this clause.
72         HashCalls []HashCall `json:"hash_calls,omitempty"`
73
74         // Values is the list of values unlocked or relocked in this clause.
75         Values []ValueInfo `json:"values"`
76
77         // Contracts is the list of contracts called by this clause.
78         Contracts []string `json:"contracts,omitempty"`
79 }
80
81 // HashCall describes a call to a hash function.
82 type HashCall struct {
83         // HashType is "sha3" or "sha256".
84         HashType string `json:"hash_type"`
85
86         // Arg is the expression passed to the hash function.
87         Arg string `json:"arg"`
88
89         // ArgType is the type of Arg.
90         ArgType string `json:"arg_type"`
91 }
92
93 // ClauseReq describes a payment requirement of a clause (one of the
94 // things after the "requires" keyword).
95 type ClauseReq struct {
96         Name string `json:"name"`
97
98         assetExpr, amountExpr expression
99
100         // Asset is the expression describing the required asset.
101         Asset string `json:"asset"`
102
103         // Amount is the expression describing the required amount.
104         Amount string `json:"amount"`
105 }
106
107 type statement interface {
108         countVarRefs(map[string]int)
109 }
110
111 type verifyStatement struct {
112         expr expression
113 }
114
115 func (s verifyStatement) countVarRefs(counts map[string]int) {
116         s.expr.countVarRefs(counts)
117 }
118
119 type lockStatement struct {
120         lockedAmount expression
121         lockedAsset  expression
122         program      expression
123
124         // Added as a decoration, used by CHECKOUTPUT
125         index int64
126 }
127
128 func (s lockStatement) countVarRefs(counts map[string]int) {
129         s.lockedAmount.countVarRefs(counts)
130         s.lockedAsset.countVarRefs(counts)
131         s.program.countVarRefs(counts)
132 }
133
134 type unlockStatement struct {
135         unlockedAmount expression
136         unlockedAsset  expression
137 }
138
139 func (s unlockStatement) countVarRefs(counts map[string]int) {
140         s.unlockedAmount.countVarRefs(counts)
141         s.unlockedAsset.countVarRefs(counts)
142 }
143
144 type expression interface {
145         String() string
146         typ(*environ) typeDesc
147         countVarRefs(map[string]int)
148 }
149
150 type binaryExpr struct {
151         left, right expression
152         op          *binaryOp
153 }
154
155 func (e binaryExpr) String() string {
156         return fmt.Sprintf("(%s %s %s)", e.left, e.op.op, e.right)
157 }
158
159 func (e binaryExpr) typ(*environ) typeDesc {
160         return e.op.result
161 }
162
163 func (e binaryExpr) countVarRefs(counts map[string]int) {
164         e.left.countVarRefs(counts)
165         e.right.countVarRefs(counts)
166 }
167
168 type unaryExpr struct {
169         op   *unaryOp
170         expr expression
171 }
172
173 func (e unaryExpr) String() string {
174         return fmt.Sprintf("%s%s", e.op.op, e.expr)
175 }
176
177 func (e unaryExpr) typ(*environ) typeDesc {
178         return e.op.result
179 }
180
181 func (e unaryExpr) countVarRefs(counts map[string]int) {
182         e.expr.countVarRefs(counts)
183 }
184
185 type callExpr struct {
186         fn   expression
187         args []expression
188 }
189
190 func (e callExpr) String() string {
191         var argStrs []string
192         for _, a := range e.args {
193                 argStrs = append(argStrs, a.String())
194         }
195         return fmt.Sprintf("%s(%s)", e.fn, strings.Join(argStrs, ", "))
196 }
197
198 func (e callExpr) typ(env *environ) typeDesc {
199         if b := referencedBuiltin(e.fn); b != nil {
200                 switch b.name {
201                 case "sha3":
202                         if len(e.args) == 1 {
203                                 switch e.args[0].typ(env) {
204                                 case strType:
205                                         return sha3StrType
206                                 case pubkeyType:
207                                         return sha3PubkeyType
208                                 }
209                         }
210
211                 case "sha256":
212                         if len(e.args) == 1 {
213                                 switch e.args[0].typ(env) {
214                                 case strType:
215                                         return sha256StrType
216                                 case pubkeyType:
217                                         return sha256PubkeyType
218                                 }
219                         }
220                 }
221
222                 return b.result
223         }
224         if e.fn.typ(env) == predType {
225                 return boolType
226         }
227         if e.fn.typ(env) == contractType {
228                 return progType
229         }
230         return nilType
231 }
232
233 func (e callExpr) countVarRefs(counts map[string]int) {
234         e.fn.countVarRefs(counts)
235         for _, a := range e.args {
236                 a.countVarRefs(counts)
237         }
238 }
239
240 type varRef string
241
242 func (v varRef) String() string {
243         return string(v)
244 }
245
246 func (e varRef) typ(env *environ) typeDesc {
247         if entry := env.lookup(string(e)); entry != nil {
248                 return entry.t
249         }
250         return nilType
251 }
252
253 func (e varRef) countVarRefs(counts map[string]int) {
254         counts[string(e)]++
255 }
256
257 type bytesLiteral []byte
258
259 func (e bytesLiteral) String() string {
260         return "0x" + hex.EncodeToString([]byte(e))
261 }
262
263 func (bytesLiteral) typ(*environ) typeDesc {
264         return "String"
265 }
266
267 func (bytesLiteral) countVarRefs(map[string]int) {}
268
269 type integerLiteral int64
270
271 func (e integerLiteral) String() string {
272         return strconv.FormatInt(int64(e), 10)
273 }
274
275 func (integerLiteral) typ(*environ) typeDesc {
276         return "Integer"
277 }
278
279 func (integerLiteral) countVarRefs(map[string]int) {}
280
281 type booleanLiteral bool
282
283 func (e booleanLiteral) String() string {
284         if e {
285                 return "true"
286         }
287         return "false"
288 }
289
290 func (booleanLiteral) typ(*environ) typeDesc {
291         return "Boolean"
292 }
293
294 func (booleanLiteral) countVarRefs(map[string]int) {}
295
296 type listExpr []expression
297
298 func (e listExpr) String() string {
299         var elts []string
300         for _, elt := range e {
301                 elts = append(elts, elt.String())
302         }
303         return fmt.Sprintf("[%s]", strings.Join(elts, ", "))
304 }
305
306 func (listExpr) typ(*environ) typeDesc {
307         return "List"
308 }
309
310 func (e listExpr) countVarRefs(counts map[string]int) {
311         for _, elt := range e {
312                 elt.countVarRefs(counts)
313         }
314 }