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 }