github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/equity/compiler/environ.go (about)

     1  package compiler
     2  
     3  import "fmt"
     4  
     5  // name-binding environment
     6  type environ struct {
     7  	entries map[string]*envEntry
     8  	parent  *environ
     9  }
    10  
    11  type envEntry struct {
    12  	t typeDesc
    13  	r role
    14  	c *Contract // if t == contractType
    15  }
    16  
    17  type role int
    18  
    19  const (
    20  	roleKeyword role = 1 + iota
    21  	roleBuiltin
    22  	roleContract
    23  	roleContractParam
    24  	roleContractValue
    25  	roleClause
    26  	roleClauseParam
    27  	roleClauseValue
    28  	roleClauseVariable
    29  )
    30  
    31  var roleDesc = map[role]string{
    32  	roleKeyword:        "keyword",
    33  	roleBuiltin:        "built-in function",
    34  	roleContract:       "contract",
    35  	roleContractParam:  "contract parameter",
    36  	roleContractValue:  "contract value",
    37  	roleClause:         "clause",
    38  	roleClauseParam:    "clause parameter",
    39  	roleClauseValue:    "clause value",
    40  	roleClauseVariable: "clause variable",
    41  }
    42  
    43  func newEnviron(parent *environ) *environ {
    44  	return &environ{
    45  		entries: make(map[string]*envEntry),
    46  		parent:  parent,
    47  	}
    48  }
    49  
    50  func (e *environ) add(name string, t typeDesc, r role) error {
    51  	if entry := e.lookup(name); entry != nil {
    52  		return fmt.Errorf("%s \"%s\" conflicts with %s", roleDesc[r], name, roleDesc[entry.r])
    53  	}
    54  	e.entries[name] = &envEntry{t: t, r: r}
    55  	return nil
    56  }
    57  
    58  func (e *environ) addContract(contract *Contract) error {
    59  	if entry := e.lookup(contract.Name); entry != nil {
    60  		return fmt.Errorf("%s \"%s\" conflicts with %s", roleDesc[roleContract], contract.Name, roleDesc[entry.r])
    61  	}
    62  	e.entries[contract.Name] = &envEntry{t: contractType, r: roleContract, c: contract}
    63  	return nil
    64  }
    65  
    66  func (e environ) lookup(name string) *envEntry {
    67  	if res, ok := e.entries[name]; ok {
    68  		return res
    69  	}
    70  	if e.parent != nil {
    71  		return e.parent.lookup(name)
    72  	}
    73  	return nil
    74  }