github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/lang/methods.go (about)

     1  package lang
     2  
     3  import (
     4  	"fmt"
     5  	"sync"
     6  
     7  	"github.com/lmorg/murex/debug"
     8  	"github.com/lmorg/murex/lang/stdio"
     9  	"github.com/lmorg/murex/lang/types"
    10  )
    11  
    12  type methods struct {
    13  	mutex sync.Mutex
    14  	dt    map[string][]string
    15  }
    16  
    17  func newMethods() *methods {
    18  	m := new(methods)
    19  	m.dt = make(map[string][]string)
    20  	return m
    21  }
    22  
    23  func (m *methods) Exists(cmd, dataType string) bool {
    24  	m.mutex.Lock()
    25  	i := m.exists(cmd, dataType)
    26  	m.mutex.Unlock()
    27  	return i != -1
    28  }
    29  
    30  func (m *methods) exists(cmd, dataType string) int {
    31  	cmds := m.dt[dataType]
    32  
    33  	for i := range cmds {
    34  		if cmds[i] == cmd {
    35  			return i
    36  		}
    37  	}
    38  
    39  	return -1
    40  }
    41  
    42  // Define creates a record of a new method
    43  func (m *methods) Define(cmd, dataType string) {
    44  	m.mutex.Lock()
    45  
    46  	cmds := m.dt[dataType]
    47  
    48  	if m.exists(cmd, dataType) != -1 {
    49  		m.mutex.Unlock()
    50  		debug.Log("method define", cmd, dataType, "exists")
    51  		return
    52  	}
    53  
    54  	m.dt[dataType] = append(cmds, cmd)
    55  	m.mutex.Unlock()
    56  }
    57  
    58  // Degroup takes the commands assigned to group types and sorts them back into individual types
    59  func (m *methods) Degroup() error {
    60  	for group := range m.dt {
    61  		if group[0] == '@' && group != types.Any {
    62  			gs, err := groups(group)
    63  			if err != nil {
    64  				return err
    65  			}
    66  			m.degroup(group, gs)
    67  		}
    68  	}
    69  	return nil
    70  }
    71  
    72  func (m *methods) degroup(group string, dataTypes []string) {
    73  	cmds := m.Get(group)
    74  	for i := range dataTypes {
    75  		for j := range cmds {
    76  			m.Define(cmds[j], dataTypes[i])
    77  		}
    78  	}
    79  	m.mutex.Lock()
    80  	delete(m.dt, group)
    81  	m.mutex.Unlock()
    82  }
    83  
    84  func groups(group string) ([]string, error) {
    85  	switch group {
    86  	case types.Text:
    87  		return types.GroupText, nil
    88  
    89  	case types.Math:
    90  		return types.GroupMath, nil
    91  
    92  	case types.Marshal:
    93  		return DumpUnmarshaller(), nil
    94  
    95  	case types.Unmarshal:
    96  		return DumpMarshaller(), nil
    97  
    98  	case types.ReadArray:
    99  		return stdio.DumpReadArray(), nil
   100  
   101  	case types.ReadArrayWithType:
   102  		return stdio.DumpReadArrayWithType(), nil
   103  
   104  	case types.WriteArray:
   105  		return stdio.DumpWriteArray(), nil
   106  
   107  	case types.ReadMap:
   108  		return stdio.DumpMap(), nil
   109  
   110  	case types.ReadIndex:
   111  		return DumpIndex(), nil
   112  
   113  	case types.ReadNotIndex:
   114  		return DumpNotIndex(), nil
   115  
   116  	default:
   117  		return nil, fmt.Errorf("group name doesn't have a programmed list of data types: %s", group)
   118  	}
   119  }
   120  
   121  // Get returns all the methods for a murex data type
   122  func (m *methods) Get(dataType string) (cmds []string) {
   123  	m.mutex.Lock()
   124  	cmds = m.get(dataType)
   125  	m.mutex.Unlock()
   126  	return
   127  }
   128  
   129  func (m *methods) get(dataType string) []string {
   130  	cmds := m.dt[dataType]
   131  
   132  	if cmds == nil {
   133  		return []string{}
   134  	}
   135  
   136  	s := make([]string, len(cmds))
   137  	copy(s, cmds)
   138  
   139  	return s
   140  }
   141  
   142  // Types returns all the data types supported by a command
   143  func (m *methods) Types(cmd string) (dataTypes []string) {
   144  	dump := m.Dump()
   145  
   146  	for dt := range dump {
   147  		if dt == types.Any {
   148  			continue
   149  		}
   150  
   151  		for i := range dump[dt] {
   152  			if dump[dt][i] == cmd {
   153  				dataTypes = append(dataTypes, dt)
   154  			}
   155  		}
   156  	}
   157  
   158  	return
   159  }
   160  
   161  // Dump returns all methods for `runtime`
   162  func (m *methods) Dump() map[string][]string {
   163  	m.mutex.Lock()
   164  
   165  	dump := make(map[string][]string)
   166  
   167  	for dt := range m.dt {
   168  		dump[dt] = m.get(dt)
   169  	}
   170  
   171  	m.mutex.Unlock()
   172  	return dump
   173  }