-
e := adc.NewEngine()
新建一个引擎,同时`Setup()` 即开创一个 `sync.Pool`内存池
-
func (imp* EngineImp) SetCtx(key string, value interface{}){ imp.ctx.kv[key] = value }
引擎中的属性之一-内存池有个kv(map)属性,把MongoSrcKey = "MongoSrcKey"
加入kv的key中, 数据库db放在kv的value中 -
e.LoadFile("test.adc")
inp := adcInterpreterPool.Get().(*interpreterImp) 加载文件代码块,同时也创建一个 sync.Pool 内存池 `loader.clear = true loader.braceStack = newBytesStack() loader.bracketStack = newBytesStack() loader.parenthesisStack = newBytesStack() loader.braceBuff = make([]byte, 0) loader.bracketBuff = make([]byte, 0) loader.parenthesisBuff = make([]byte, 0) 同时这个interpreterImp 内存池的属性中包含很多buff 和stack 都是[]byte 这一步同时初始化 `
-
loader.fp = f 把文件流放在了interpreterImp 里面的fp属性,然后开始一行行读取文件流
-
按照line读取文件流 -读取文件的每一行 #(35)除外
func readByLine(f string) [][]byte {
r := make([][]byte, 0)
fi, err := os.Open(f)
if err != nil {
return nil
}
defer fi.Close()
br := bufio.NewReader(fi)
for {
l, _, e := br.ReadLine()
if e != nil {
if e == io.EOF {
break
}else {
return nil
}
}
if len(l) == 0 {
continue
}
data := bytes.TrimSpace(l)
if data[0] == commentPrefix {
continue
}
r = append(r, utils.CopyBytes(data))
}
return r
}
- 然后读取每一行的每一个字符,这里是分析标识符 { ( 这些
for k, v := range data {
out.InitRow(k)
for _, ch := range v {
switch ch {
case chBraceStart:
loader.braceStack.push(ch)
loader.appendChToBuf(ch)
case chBracketStart:
loader.bracketStack.push(ch)
loader.appendChToBuf(ch)
case chParenthesisStart:
loader.parenthesisStack.push(ch)
loader.appendChToBuf(ch)
case chBraceEnd:
loader.appendChToBuf(ch)
if loader.braceStack.getLen() == 0 {
return LSSyntaxError
}
loader.braceStack.pop()
if loader.braceStack.getLen() == 0 {
out.AppendData(k, adcData.STypeBrace, utils.CopyBytes(loader.braceBuff))
loader.braceBuff = loader.braceBuff[:0]
}
case chBracketEnd:
loader.appendChToBuf(ch)
if loader.bracketStack.getLen() == 0 {
return LSSyntaxError
}
loader.bracketStack.pop()
if loader.bracketStack.getLen() == 0 {
out.AppendData(k, adcData.STypeBracket, utils.CopyBytes(loader.bracketBuff))
loader.bracketBuff = loader.bracketBuff[:0]
}
case chParenthesisEnd:
loader.appendChToBuf(ch)
if loader.parenthesisStack.getLen() == 0 {
return LSSyntaxError
}
loader.parenthesisStack.pop()
if loader.parenthesisStack.getLen() == 0 {
out.AppendData(k, adcData.STypeParenthesis, utils.CopyBytes(loader.parenthesisBuff))
loader.parenthesisBuff = loader.parenthesisBuff[:0]
}
default:
loader.appendChToBuf(ch)
}
}
if !loader.allRight() {
return LSSyntaxError
}
}
return LSSuccess
}
-
读取规则: 如果是[ 把字符放在 interpreterImp 里面的bracketStack,bracketBuff属性里
如果遇到 ] 则pop出来,
如果是( { [ 则把字符存在stack里面,后面会根据stack的长度来判断,这三个字符分别对应着不同,固定的stack具体是怎么存,怎么弹出来的 没搞明白
-
规则:先执行case,当所有的case都判断完不符合bai条件的时候,才会执行default,无论你的default放在哪
default:
loader.appendChToBuf(ch)
把除了大小括号的字符都存在 了 interpreterImp属性里面的 braceBuff bracketBuff parenthesisBuff
- 引擎的line属性 初始化
imp.lines = make([]*pipeline, len(data.data))
line是个数组 遍历文件流data 数组的每个字符都要
imp.lines = make([]*pipeline, len(data.data))
for k, v := range data.data {
imp.lines[k] = getPipeline()
imp.lines[k].form(imp, v)
}
get一下sync pool里面的东西 不理解,然后进入到form方法
创建line 里面的sts 属性 是[]*stage 创建line里面的temp属性 是[]string
然后根据data里面的 []位置的数据开始遍历 (就是每次截取两个[]中间的数据)
for k, v := range data[adcData.STypeBracket] {
line.sts[k] = getStage()
line.sts[k].form(line, v, data[adcData.STypeParenthesis][k], data[adcData.STypeBrace][k])
}
这个st属性就是存类型的
st.st = stageType(trimData(sd)[0])
st stageType
const (
stSource = 102 //f
stProcess = 112 //p
stTo = 116 //t
)
这个方法是把自定义的方法标签提取出来 ,比如@jkv @mongoTree
st.f, st.fn = formFunction(trimData(vd))
这个是把数据提取粗来,比如[t{@jkv(hello2)}] 里面的hell02
pd := trimData(fd)
然后把数据put到pool里面
- 然后到了run方法,先创建一个string缓存栈
buf := bytes.NewBufferString("")
然后遍历引擎里面的 imp.lines 将遍历的结果跑run的方法 并且把返回的参数加入到buf的缓存区
run方法参数是一个写死的map
tm := map[string]interface{
}{
"data" : "foo"} --lkv
buf.WriteString(v.run(lkv))
- 遍历 line.sts里面的每一个值 然后进行v.run()方法
for k, v := range line.sts {
line.nowSts = k
line.temp[k] = v.run()
}
这里会选择进行哪个函数
result, kv := st.f(temp, args, ctx.kv)
type fHandler func(temp string, args []string, kv map[string]interface{
}) (string, map[string]interface{
})
var fMap = map[string]fHandler{
ftPlaint: functions.Plain,
ftMongo: functions.MongoTree,
ftMongoMulti: functions.MongoTreeMulti,
ftJKV: functions.JKV,
ftJKVMulti: functions.JKVMulti,
ftJKVNow: functions.JKVNow,
ftNow: functions.Now,
}
跑完v.run之后 会把 结果推到sync池里面 putContext(line.ctx)