OSDN Git Service

Merge pull request #41 from Bytom/dev
[bytom/vapor.git] / equity / compiler / ast.go
1 package compiler
2
3 import (
4         "encoding/hex"
5         "fmt"
6         "strconv"
7         "strings"
8
9         chainjson "github.com/vapor/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 // IfBody describes a if ... else ... struct
94 type IfStatmentBody struct {
95         // if statements body
96         trueBody []statement
97
98         // else statements body
99         falseBody []statement
100 }
101
102 type statement interface {
103         countVarRefs(map[string]int)
104 }
105
106 type defineStatement struct {
107         variable *Param
108         expr     expression
109 }
110
111 func (s defineStatement) countVarRefs(counts map[string]int) {
112         s.expr.countVarRefs(counts)
113 }
114
115 type assignStatement struct {
116         variable *Param
117         expr     expression
118 }
119
120 func (s assignStatement) countVarRefs(counts map[string]int) {
121         s.expr.countVarRefs(counts)
122 }
123
124 type ifStatement struct {
125         condition expression
126         body      *IfStatmentBody
127 }
128
129 func (s ifStatement) countVarRefs(counts map[string]int) {
130         s.condition.countVarRefs(counts)
131 }
132
133 type verifyStatement struct {
134         expr expression
135 }
136
137 func (s verifyStatement) countVarRefs(counts map[string]int) {
138         s.expr.countVarRefs(counts)
139 }
140
141 type lockStatement struct {
142         lockedAmount expression
143         lockedAsset  expression
144         program      expression
145
146         // Added as a decoration, used by CHECKOUTPUT
147         index int64
148 }
149
150 func (s lockStatement) countVarRefs(counts map[string]int) {
151         s.lockedAmount.countVarRefs(counts)
152         s.lockedAsset.countVarRefs(counts)
153         s.program.countVarRefs(counts)
154 }
155
156 type unlockStatement struct {
157         unlockedAmount expression
158         unlockedAsset  expression
159 }
160
161 func (s unlockStatement) countVarRefs(counts map[string]int) {
162         s.unlockedAmount.countVarRefs(counts)
163         s.unlockedAsset.countVarRefs(counts)
164 }
165
166 type expression interface {
167         String() string
168         typ(*environ) typeDesc
169         countVarRefs(map[string]int)
170 }
171
172 type binaryExpr struct {
173         left, right expression
174         op          *binaryOp
175 }
176
177 func (e binaryExpr) String() string {
178         return fmt.Sprintf("(%s %s %s)", e.left, e.op.op, e.right)
179 }
180
181 func (e binaryExpr) typ(*environ) typeDesc {
182         return e.op.result
183 }
184
185 func (e binaryExpr) countVarRefs(counts map[string]int) {
186         e.left.countVarRefs(counts)
187         e.right.countVarRefs(counts)
188 }
189
190 type unaryExpr struct {
191         op   *unaryOp
192         expr expression
193 }
194
195 func (e unaryExpr) String() string {
196         return fmt.Sprintf("%s%s", e.op.op, e.expr)
197 }
198
199 func (e unaryExpr) typ(*environ) typeDesc {
200         return e.op.result
201 }
202
203 func (e unaryExpr) countVarRefs(counts map[string]int) {
204         e.expr.countVarRefs(counts)
205 }
206
207 type callExpr struct {
208         fn   expression
209         args []expression
210 }
211
212 func (e callExpr) String() string {
213         var argStrs []string
214         for _, a := range e.args {
215                 argStrs = append(argStrs, a.String())
216         }
217         return fmt.Sprintf("%s(%s)", e.fn, strings.Join(argStrs, ", "))
218 }
219
220 func (e callExpr) typ(env *environ) typeDesc {
221         if b := referencedBuiltin(e.fn); b != nil {
222                 switch b.name {
223                 case "sha3":
224                         if len(e.args) == 1 {
225                                 switch e.args[0].typ(env) {
226                                 case strType:
227                                         return sha3StrType
228                                 case pubkeyType:
229                                         return sha3PubkeyType
230                                 }
231                         }
232
233                 case "sha256":
234                         if len(e.args) == 1 {
235                                 switch e.args[0].typ(env) {
236                                 case strType:
237                                         return sha256StrType
238                                 case pubkeyType:
239                                         return sha256PubkeyType
240                                 }
241                         }
242                 }
243
244                 return b.result
245         }
246         if e.fn.typ(env) == predType {
247                 return boolType
248         }
249         if e.fn.typ(env) == contractType {
250                 return progType
251         }
252         return nilType
253 }
254
255 func (e callExpr) countVarRefs(counts map[string]int) {
256         e.fn.countVarRefs(counts)
257         for _, a := range e.args {
258                 a.countVarRefs(counts)
259         }
260 }
261
262 type varRef string
263
264 func (v varRef) String() string {
265         return string(v)
266 }
267
268 func (e varRef) typ(env *environ) typeDesc {
269         if entry := env.lookup(string(e)); entry != nil {
270                 return entry.t
271         }
272         return nilType
273 }
274
275 func (e varRef) countVarRefs(counts map[string]int) {
276         counts[string(e)]++
277 }
278
279 type bytesLiteral []byte
280
281 func (e bytesLiteral) String() string {
282         return "0x" + hex.EncodeToString([]byte(e))
283 }
284
285 func (bytesLiteral) typ(*environ) typeDesc {
286         return "String"
287 }
288
289 func (bytesLiteral) countVarRefs(map[string]int) {}
290
291 type integerLiteral int64
292
293 func (e integerLiteral) String() string {
294         return strconv.FormatInt(int64(e), 10)
295 }
296
297 func (integerLiteral) typ(*environ) typeDesc {
298         return "Integer"
299 }
300
301 func (integerLiteral) countVarRefs(map[string]int) {}
302
303 type booleanLiteral bool
304
305 func (e booleanLiteral) String() string {
306         if e {
307                 return "true"
308         }
309         return "false"
310 }
311
312 func (booleanLiteral) typ(*environ) typeDesc {
313         return "Boolean"
314 }
315
316 func (booleanLiteral) countVarRefs(map[string]int) {}
317
318 type listExpr []expression
319
320 func (e listExpr) String() string {
321         var elts []string
322         for _, elt := range e {
323                 elts = append(elts, elt.String())
324         }
325         return fmt.Sprintf("[%s]", strings.Join(elts, ", "))
326 }
327
328 func (listExpr) typ(*environ) typeDesc {
329         return "List"
330 }
331
332 func (e listExpr) countVarRefs(counts map[string]int) {
333         for _, elt := range e {
334                 elt.countVarRefs(counts)
335         }
336 }