github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/equity/compiler/ast.go (about) 1 package compiler 2 3 import ( 4 "encoding/hex" 5 "fmt" 6 "strconv" 7 "strings" 8 9 chainjson "github.com/bytom/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 // 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 }