github.com/MontFerret/ferret@v0.18.0/pkg/compiler/scope.go (about)

     1  package compiler
     2  
     3  import (
     4  	"github.com/MontFerret/ferret/pkg/runtime/core"
     5  )
     6  
     7  type (
     8  	globalScope struct {
     9  		params map[string]struct{}
    10  	}
    11  
    12  	scope struct {
    13  		global *globalScope
    14  		parent *scope
    15  		name   string
    16  		vars   map[string]struct{}
    17  	}
    18  )
    19  
    20  func newGlobalScope() *globalScope {
    21  	return &globalScope{
    22  		params: map[string]struct{}{},
    23  	}
    24  }
    25  
    26  func newRootScope(global *globalScope) *scope {
    27  	return &scope{
    28  		global: global,
    29  		vars:   make(map[string]struct{}),
    30  		name:   "root",
    31  	}
    32  }
    33  
    34  func newScope(parent *scope, name string) *scope {
    35  	s := newRootScope(parent.global)
    36  	s.parent = parent
    37  	s.name = name
    38  
    39  	return s
    40  }
    41  
    42  func (s *scope) Name() string {
    43  	if s.name != "" {
    44  		return s.name
    45  	}
    46  
    47  	if s.parent != nil {
    48  		return s.parent.Name()
    49  	}
    50  
    51  	return ""
    52  }
    53  
    54  func (s *scope) AddParam(name string) {
    55  	s.global.params[name] = struct{}{}
    56  }
    57  
    58  func (s *scope) HasVariable(name string) bool {
    59  	_, exists := s.vars[name]
    60  
    61  	if exists {
    62  		return true
    63  	}
    64  
    65  	if s.parent != nil {
    66  		return s.parent.HasVariable(name)
    67  	}
    68  
    69  	return false
    70  }
    71  
    72  func (s *scope) SetVariable(name string) error {
    73  	if name == core.IgnorableVariable {
    74  		return nil
    75  	}
    76  
    77  	_, exists := s.vars[name]
    78  
    79  	if exists {
    80  		return core.Error(ErrVariableNotUnique, name)
    81  	}
    82  
    83  	// TODO: add type detection
    84  	s.vars[name] = struct{}{}
    85  
    86  	return nil
    87  }
    88  
    89  func (s *scope) RemoveVariable(name string) error {
    90  	_, exists := s.vars[name]
    91  
    92  	if !exists {
    93  		return core.Error(ErrVariableNotFound, name)
    94  	}
    95  
    96  	delete(s.vars, name)
    97  
    98  	return nil
    99  }
   100  
   101  func (s *scope) ClearVariables() {
   102  	s.vars = make(map[string]struct{})
   103  }
   104  
   105  func (s *scope) Fork(name string) *scope {
   106  	return newScope(s, name)
   107  }