-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmodular.go
190 lines (185 loc) · 5 KB
/
modular.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
package glu
import (
"errors"
"fmt"
lua "github.com/yuin/gopher-lua"
"strings"
)
// Modular shared methods make it a Modular
type Modular interface {
//TopLevel dose this Mod is top level,means should not be submodule
TopLevel() bool
//PreLoad load as global Mod
PreLoad(l *lua.LState)
//PreloadSubModule use for submodule loading, Should NOT invoke manually
PreloadSubModule(l *lua.LState, t *lua.LTable)
//GetName the unique name (if is a Top Level Modular)
GetName() string
//GetHelp Modular HelpCache info
GetHelp() string
}
type Prepare interface {
prepare()
}
var (
//HelpKey the module HelpCache key
HelpKey = "?"
//HelpFunc the help function name
HelpFunc = "help"
//HelpPrompt the prompt for no value supply for HelpCache
HelpPrompt = "show Help with those key word: "
HelpChunk = `chunk(code,name string)(Chunk?,string?) ==> pre compile string into bytecode`
HelpHelp = HelpFunc + `(topic string?)string? => fetch Help of topic,'?' show topics,without topic show loadable modules`
HelpTopic = `?,chunk`
EagerHelpPrepare = false
)
func helpFuncReg(fun map[string]funcInfo, helps map[string]string, mh *strings.Builder, mod string) {
if len(fun) > 0 {
for s, info := range fun {
if info.Help != "" {
helps[s] = fmt.Sprintf("%s.%s %s", mod, s, info.Help)
mh.WriteString(fmt.Sprintf("%s.%s %s\n", mod, s, info.Help))
info.Help = ""
} else {
mh.WriteString(fmt.Sprintf("%s.%s\n", mod, s))
}
}
}
}
func helpFieldReg(fun map[string]fieldInfo, helps map[string]string, mh *strings.Builder, mod string) {
if len(fun) > 0 {
for s, info := range fun {
if info.Help != "" {
helps[s] = fmt.Sprintf("%s.%s %s", mod, s, info.Help)
mh.WriteString(fmt.Sprintf("%s.%s %s\n", mod, s, info.Help))
info.Help = ""
} else {
mh.WriteString(fmt.Sprintf("%s.%s\n", mod, s))
}
}
}
}
func helpMethodReg(fun map[string]funcInfo, helps map[string]string, mh *strings.Builder, mod string) {
if len(fun) > 0 {
for s, info := range fun {
if info.Help != "" {
helps[s] = fmt.Sprintf("%s:%s %s", mod, s, info.Help)
mh.WriteString(fmt.Sprintf("%s:%s %s\n", mod, s, info.Help))
info.Help = ""
} else {
mh.WriteString(fmt.Sprintf("%s:%s\n", mod, s))
}
}
}
}
func helpSubModReg(fun []Modular, helps map[string]string, mh *strings.Builder, mod string) {
if len(fun) > 0 {
for _, info := range fun {
s := info.GetName()
if info.GetHelp() != "" {
helps[s] = fmt.Sprintf("%s.%s %s", mod, s, info.GetHelp())
mh.WriteString(fmt.Sprintf("%s.%s %s\n", mod, s, info.GetHelp()))
} else {
mh.WriteString(fmt.Sprintf("%s.%s\n", mod, s))
}
}
}
}
func helpOperatorReg(operators map[Operate]funcInfo, hasMethods bool, helps map[string]string, mh *strings.Builder, mod string) {
if len(operators) > 0 {
for op, info := range operators {
var sym string
var name string
switch op {
case OPERATE_ADD:
name = "__add"
sym = "+"
case OPERATE_SUB:
name = "__sub"
sym = "-"
case OPERATE_MUL:
name = "__mul"
sym = "*"
case OPERATE_DIV:
name = "__div"
sym = "/"
case OPERATE_UNM:
name = "__unm"
sym = "-"
case OPERATE_MOD:
name = "__mod"
sym = "%"
case OPERATE_POW:
name = "__pow"
sym = "^"
case OPERATE_CONCAT:
name = "__concat"
sym = ".."
case OPERATE_EQ:
name = "__eq"
sym = "=="
case OPERATE_LT:
name = "__lt"
sym = "<"
case OPERATE_LE:
name = "__le"
sym = "<="
case OPERATE_LEN:
name = "__len"
sym = "#"
case OPERATE_NEWINDEX:
name = "__newindex"
sym = "[]="
case OPERATE_TOSTRING:
name = "__tostring"
sym = "tostring"
case OPERATE_CALL:
name = "__call"
sym = "()"
case OPERATE_INDEX:
if hasMethods {
panic(ErrIndexOverrideWithMethods)
}
name = "__index"
sym = "[]"
default:
panic(fmt.Errorf("unsupported operators of %d", op))
}
if info.Help != "" {
helps[name] = fmt.Sprintf("metatable %s:%s %s\n", mod, sym, info.Help)
mh.WriteString(fmt.Sprintf("metatable %s:%s %s\n", mod, sym, info.Help))
info.Help = ""
} else {
mh.WriteString(fmt.Sprintf("metatable %s:%s\n", mod, sym))
}
}
}
}
func helpCtorReg[T any](ctor func(*lua.LState) (v T), ctor2 string, help map[string]string, mh *strings.Builder, name string) {
if ctor != nil {
if ctor2 != "" {
help["new"] = fmt.Sprintf("%s.new %s", name, ctor2)
}
mh.WriteString(fmt.Sprintf("%s.new %s\n", name, ctor2))
}
}
func helpFn(help map[string]string) lua.LGFunction {
key := make([]string, 0, len(help))
for s := range help {
key = append(key, s)
}
keys := HelpPrompt + strings.Join(key, ",")
return func(s *lua.LState) int {
if s.GetTop() == 0 {
s.Push(lua.LString(keys))
} else {
s.Push(lua.LString(help[s.ToString(1)]))
}
return 1
}
}
var (
ErrAlreadyExists = errors.New("element already exists")
ErrIndexOverrideWithMethods = errors.New("element both have methods and index overrides")
ErrIsTop = errors.New("element is top module")
)