OSDN Git Service

Hulk did something
[bytom/vapor.git] / equity / compiler / ast.go
diff --git a/equity/compiler/ast.go b/equity/compiler/ast.go
new file mode 100644 (file)
index 0000000..85db64e
--- /dev/null
@@ -0,0 +1,336 @@
+package compiler
+
+import (
+       "encoding/hex"
+       "fmt"
+       "strconv"
+       "strings"
+
+       chainjson "github.com/vapor/encoding/json"
+)
+
+// Contract is a compiled Equity contract.
+type Contract struct {
+       // Name is the contract name.
+       Name string `json:"name"`
+
+       // Params is the list of contract parameters.
+       Params []*Param `json:"params,omitempty"`
+
+       // Clauses is the list of contract clauses.
+       Clauses []*Clause `json:"clauses"`
+
+       // Value is the name of the value locked by the contract.
+       Value ValueInfo `json:"value"`
+
+       // Body is the optimized bytecode of the contract body. This is not
+       // a complete program!  Use instantiate to turn this (plus some
+       // arguments) into a program.
+       Body chainjson.HexBytes `json:"body_bytecode"`
+
+       // Opcodes is the human-readable string of opcodes corresponding to
+       // Body.
+       Opcodes string `json:"body_opcodes,omitempty"`
+
+       // Recursive tells whether this contract calls itself.  (This is
+       // used to select between two possible instantiation options.)
+       Recursive bool `json:"recursive"`
+
+       // Pre-optimized list of instruction steps, with stack snapshots.
+       Steps []Step `json:"-"`
+}
+
+// Param is a contract or clause parameter.
+type Param struct {
+       // Name is the parameter name.
+       Name string `json:"name"`
+
+       // Type is the declared parameter type.
+       Type typeDesc `json:"type"`
+
+       // InferredType, if available, is a more-specific type than Type,
+       // inferred from the logic of the contract.
+       InferredType typeDesc `json:"inferred_type,omitempty"`
+}
+
+// Clause is a compiled contract clause.
+type Clause struct {
+       // Name is the clause name.
+       Name string `json:"name"`
+
+       // Params is the list of clause parameters.
+       Params []*Param `json:"params,omitempty"`
+
+       statements []statement
+
+       // BlockHeight is the list of expressions passed to greater()/less() in this
+       // clause.
+       BlockHeight []string `json:"blockheight,omitempty"`
+
+       // HashCalls is the list of hash functions and their arguments used
+       // in this clause.
+       HashCalls []HashCall `json:"hash_calls,omitempty"`
+
+       // Values is the list of values unlocked or relocked in this clause.
+       Values []ValueInfo `json:"values"`
+
+       // Contracts is the list of contracts called by this clause.
+       Contracts []string `json:"contracts,omitempty"`
+}
+
+// HashCall describes a call to a hash function.
+type HashCall struct {
+       // HashType is "sha3" or "sha256".
+       HashType string `json:"hash_type"`
+
+       // Arg is the expression passed to the hash function.
+       Arg string `json:"arg"`
+
+       // ArgType is the type of Arg.
+       ArgType string `json:"arg_type"`
+}
+
+// IfBody describes a if ... else ... struct
+type IfStatmentBody struct {
+       // if statements body
+       trueBody []statement
+
+       // else statements body
+       falseBody []statement
+}
+
+type statement interface {
+       countVarRefs(map[string]int)
+}
+
+type defineStatement struct {
+       variable *Param
+       expr     expression
+}
+
+func (s defineStatement) countVarRefs(counts map[string]int) {
+       s.expr.countVarRefs(counts)
+}
+
+type assignStatement struct {
+       variable *Param
+       expr     expression
+}
+
+func (s assignStatement) countVarRefs(counts map[string]int) {
+       s.expr.countVarRefs(counts)
+}
+
+type ifStatement struct {
+       condition expression
+       body      *IfStatmentBody
+}
+
+func (s ifStatement) countVarRefs(counts map[string]int) {
+       s.condition.countVarRefs(counts)
+}
+
+type verifyStatement struct {
+       expr expression
+}
+
+func (s verifyStatement) countVarRefs(counts map[string]int) {
+       s.expr.countVarRefs(counts)
+}
+
+type lockStatement struct {
+       lockedAmount expression
+       lockedAsset  expression
+       program      expression
+
+       // Added as a decoration, used by CHECKOUTPUT
+       index int64
+}
+
+func (s lockStatement) countVarRefs(counts map[string]int) {
+       s.lockedAmount.countVarRefs(counts)
+       s.lockedAsset.countVarRefs(counts)
+       s.program.countVarRefs(counts)
+}
+
+type unlockStatement struct {
+       unlockedAmount expression
+       unlockedAsset  expression
+}
+
+func (s unlockStatement) countVarRefs(counts map[string]int) {
+       s.unlockedAmount.countVarRefs(counts)
+       s.unlockedAsset.countVarRefs(counts)
+}
+
+type expression interface {
+       String() string
+       typ(*environ) typeDesc
+       countVarRefs(map[string]int)
+}
+
+type binaryExpr struct {
+       left, right expression
+       op          *binaryOp
+}
+
+func (e binaryExpr) String() string {
+       return fmt.Sprintf("(%s %s %s)", e.left, e.op.op, e.right)
+}
+
+func (e binaryExpr) typ(*environ) typeDesc {
+       return e.op.result
+}
+
+func (e binaryExpr) countVarRefs(counts map[string]int) {
+       e.left.countVarRefs(counts)
+       e.right.countVarRefs(counts)
+}
+
+type unaryExpr struct {
+       op   *unaryOp
+       expr expression
+}
+
+func (e unaryExpr) String() string {
+       return fmt.Sprintf("%s%s", e.op.op, e.expr)
+}
+
+func (e unaryExpr) typ(*environ) typeDesc {
+       return e.op.result
+}
+
+func (e unaryExpr) countVarRefs(counts map[string]int) {
+       e.expr.countVarRefs(counts)
+}
+
+type callExpr struct {
+       fn   expression
+       args []expression
+}
+
+func (e callExpr) String() string {
+       var argStrs []string
+       for _, a := range e.args {
+               argStrs = append(argStrs, a.String())
+       }
+       return fmt.Sprintf("%s(%s)", e.fn, strings.Join(argStrs, ", "))
+}
+
+func (e callExpr) typ(env *environ) typeDesc {
+       if b := referencedBuiltin(e.fn); b != nil {
+               switch b.name {
+               case "sha3":
+                       if len(e.args) == 1 {
+                               switch e.args[0].typ(env) {
+                               case strType:
+                                       return sha3StrType
+                               case pubkeyType:
+                                       return sha3PubkeyType
+                               }
+                       }
+
+               case "sha256":
+                       if len(e.args) == 1 {
+                               switch e.args[0].typ(env) {
+                               case strType:
+                                       return sha256StrType
+                               case pubkeyType:
+                                       return sha256PubkeyType
+                               }
+                       }
+               }
+
+               return b.result
+       }
+       if e.fn.typ(env) == predType {
+               return boolType
+       }
+       if e.fn.typ(env) == contractType {
+               return progType
+       }
+       return nilType
+}
+
+func (e callExpr) countVarRefs(counts map[string]int) {
+       e.fn.countVarRefs(counts)
+       for _, a := range e.args {
+               a.countVarRefs(counts)
+       }
+}
+
+type varRef string
+
+func (v varRef) String() string {
+       return string(v)
+}
+
+func (e varRef) typ(env *environ) typeDesc {
+       if entry := env.lookup(string(e)); entry != nil {
+               return entry.t
+       }
+       return nilType
+}
+
+func (e varRef) countVarRefs(counts map[string]int) {
+       counts[string(e)]++
+}
+
+type bytesLiteral []byte
+
+func (e bytesLiteral) String() string {
+       return "0x" + hex.EncodeToString([]byte(e))
+}
+
+func (bytesLiteral) typ(*environ) typeDesc {
+       return "String"
+}
+
+func (bytesLiteral) countVarRefs(map[string]int) {}
+
+type integerLiteral int64
+
+func (e integerLiteral) String() string {
+       return strconv.FormatInt(int64(e), 10)
+}
+
+func (integerLiteral) typ(*environ) typeDesc {
+       return "Integer"
+}
+
+func (integerLiteral) countVarRefs(map[string]int) {}
+
+type booleanLiteral bool
+
+func (e booleanLiteral) String() string {
+       if e {
+               return "true"
+       }
+       return "false"
+}
+
+func (booleanLiteral) typ(*environ) typeDesc {
+       return "Boolean"
+}
+
+func (booleanLiteral) countVarRefs(map[string]int) {}
+
+type listExpr []expression
+
+func (e listExpr) String() string {
+       var elts []string
+       for _, elt := range e {
+               elts = append(elts, elt.String())
+       }
+       return fmt.Sprintf("[%s]", strings.Join(elts, ", "))
+}
+
+func (listExpr) typ(*environ) typeDesc {
+       return "List"
+}
+
+func (e listExpr) countVarRefs(counts map[string]int) {
+       for _, elt := range e {
+               elt.countVarRefs(counts)
+       }
+}