baselib.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. package lua
  2. import (
  3. "fmt"
  4. "io"
  5. "os"
  6. "runtime"
  7. "strconv"
  8. "strings"
  9. )
  10. /* basic functions {{{ */
  11. func OpenBase(L *LState) int {
  12. global := L.Get(GlobalsIndex).(*LTable)
  13. L.SetGlobal("_G", global)
  14. L.SetGlobal("_VERSION", LString(LuaVersion))
  15. L.SetGlobal("_GOPHER_LUA_VERSION", LString(PackageName+" "+PackageVersion))
  16. basemod := L.RegisterModule("_G", baseFuncs)
  17. global.RawSetString("ipairs", L.NewClosure(baseIpairs, L.NewFunction(ipairsaux)))
  18. global.RawSetString("pairs", L.NewClosure(basePairs, L.NewFunction(pairsaux)))
  19. L.Push(basemod)
  20. return 1
  21. }
  22. var baseFuncs = map[string]LGFunction{
  23. "assert": baseAssert,
  24. "collectgarbage": baseCollectGarbage,
  25. "dofile": baseDoFile,
  26. "error": baseError,
  27. "getfenv": baseGetFEnv,
  28. "getmetatable": baseGetMetatable,
  29. "load": baseLoad,
  30. "loadfile": baseLoadFile,
  31. "loadstring": baseLoadString,
  32. "next": baseNext,
  33. "pcall": basePCall,
  34. "print": basePrint,
  35. "rawequal": baseRawEqual,
  36. "rawget": baseRawGet,
  37. "rawset": baseRawSet,
  38. "select": baseSelect,
  39. "_printregs": base_PrintRegs,
  40. "setfenv": baseSetFEnv,
  41. "setmetatable": baseSetMetatable,
  42. "tonumber": baseToNumber,
  43. "tostring": baseToString,
  44. "type": baseType,
  45. "unpack": baseUnpack,
  46. "xpcall": baseXPCall,
  47. // loadlib
  48. "module": loModule,
  49. "require": loRequire,
  50. // hidden features
  51. "newproxy": baseNewProxy,
  52. }
  53. func baseAssert(L *LState) int {
  54. if !L.ToBool(1) {
  55. L.RaiseError(L.OptString(2, "assertion failed!"))
  56. return 0
  57. }
  58. return L.GetTop()
  59. }
  60. func baseCollectGarbage(L *LState) int {
  61. runtime.GC()
  62. return 0
  63. }
  64. func baseDoFile(L *LState) int {
  65. src := L.ToString(1)
  66. top := L.GetTop()
  67. fn, err := L.LoadFile(src)
  68. if err != nil {
  69. L.Push(LString(err.Error()))
  70. L.Panic(L)
  71. }
  72. L.Push(fn)
  73. L.Call(0, MultRet)
  74. return L.GetTop() - top
  75. }
  76. func baseError(L *LState) int {
  77. obj := L.CheckAny(1)
  78. level := L.OptInt(2, 1)
  79. L.Error(obj, level)
  80. return 0
  81. }
  82. func baseGetFEnv(L *LState) int {
  83. var value LValue
  84. if L.GetTop() == 0 {
  85. value = LNumber(1)
  86. } else {
  87. value = L.Get(1)
  88. }
  89. if fn, ok := value.(*LFunction); ok {
  90. if !fn.IsG {
  91. L.Push(fn.Env)
  92. } else {
  93. L.Push(L.G.Global)
  94. }
  95. return 1
  96. }
  97. if number, ok := value.(LNumber); ok {
  98. level := int(float64(number))
  99. if level <= 0 {
  100. L.Push(L.Env)
  101. } else {
  102. cf := L.currentFrame
  103. for i := 0; i < level && cf != nil; i++ {
  104. cf = cf.Parent
  105. }
  106. if cf == nil || cf.Fn.IsG {
  107. L.Push(L.G.Global)
  108. } else {
  109. L.Push(cf.Fn.Env)
  110. }
  111. }
  112. return 1
  113. }
  114. L.Push(L.G.Global)
  115. return 1
  116. }
  117. func baseGetMetatable(L *LState) int {
  118. L.Push(L.GetMetatable(L.CheckAny(1)))
  119. return 1
  120. }
  121. func ipairsaux(L *LState) int {
  122. tb := L.CheckTable(1)
  123. i := L.CheckInt(2)
  124. i++
  125. v := tb.RawGetInt(i)
  126. if v == LNil {
  127. return 0
  128. } else {
  129. L.Pop(1)
  130. L.Push(LNumber(i))
  131. L.Push(LNumber(i))
  132. L.Push(v)
  133. return 2
  134. }
  135. }
  136. func baseIpairs(L *LState) int {
  137. tb := L.CheckTable(1)
  138. L.Push(L.Get(UpvalueIndex(1)))
  139. L.Push(tb)
  140. L.Push(LNumber(0))
  141. return 3
  142. }
  143. func loadaux(L *LState, reader io.Reader, chunkname string) int {
  144. if fn, err := L.Load(reader, chunkname); err != nil {
  145. L.Push(LNil)
  146. L.Push(LString(err.Error()))
  147. return 2
  148. } else {
  149. L.Push(fn)
  150. return 1
  151. }
  152. }
  153. func baseLoad(L *LState) int {
  154. fn := L.CheckFunction(1)
  155. chunkname := L.OptString(2, "?")
  156. top := L.GetTop()
  157. buf := []string{}
  158. for {
  159. L.SetTop(top)
  160. L.Push(fn)
  161. L.Call(0, 1)
  162. ret := L.reg.Pop()
  163. if ret == LNil {
  164. break
  165. } else if LVCanConvToString(ret) {
  166. str := ret.String()
  167. if len(str) > 0 {
  168. buf = append(buf, string(str))
  169. } else {
  170. break
  171. }
  172. } else {
  173. L.Push(LNil)
  174. L.Push(LString("reader function must return a string"))
  175. return 2
  176. }
  177. }
  178. return loadaux(L, strings.NewReader(strings.Join(buf, "")), chunkname)
  179. }
  180. func baseLoadFile(L *LState) int {
  181. var reader io.Reader
  182. var chunkname string
  183. var err error
  184. if L.GetTop() < 1 {
  185. reader = os.Stdin
  186. chunkname = "<stdin>"
  187. } else {
  188. chunkname = L.CheckString(1)
  189. reader, err = os.Open(chunkname)
  190. if err != nil {
  191. L.Push(LNil)
  192. L.Push(LString(fmt.Sprintf("can not open file: %v", chunkname)))
  193. return 2
  194. }
  195. defer reader.(*os.File).Close()
  196. }
  197. return loadaux(L, reader, chunkname)
  198. }
  199. func baseLoadString(L *LState) int {
  200. return loadaux(L, strings.NewReader(L.CheckString(1)), L.OptString(2, "<string>"))
  201. }
  202. func baseNext(L *LState) int {
  203. tb := L.CheckTable(1)
  204. index := LNil
  205. if L.GetTop() >= 2 {
  206. index = L.Get(2)
  207. }
  208. key, value := tb.Next(index)
  209. if key == LNil {
  210. L.Push(LNil)
  211. return 1
  212. }
  213. L.Push(key)
  214. L.Push(value)
  215. return 2
  216. }
  217. func pairsaux(L *LState) int {
  218. tb := L.CheckTable(1)
  219. key, value := tb.Next(L.Get(2))
  220. if key == LNil {
  221. return 0
  222. } else {
  223. L.Pop(1)
  224. L.Push(key)
  225. L.Push(key)
  226. L.Push(value)
  227. return 2
  228. }
  229. }
  230. func basePairs(L *LState) int {
  231. tb := L.CheckTable(1)
  232. L.Push(L.Get(UpvalueIndex(1)))
  233. L.Push(tb)
  234. L.Push(LNil)
  235. return 3
  236. }
  237. func basePCall(L *LState) int {
  238. L.CheckAny(1)
  239. v := L.Get(1)
  240. if v.Type() != LTFunction && L.GetMetaField(v, "__call").Type() != LTFunction {
  241. L.Push(LFalse)
  242. L.Push(LString("attempt to call a " + v.Type().String() + " value"))
  243. return 2
  244. }
  245. nargs := L.GetTop() - 1
  246. if err := L.PCall(nargs, MultRet, nil); err != nil {
  247. L.Push(LFalse)
  248. if aerr, ok := err.(*ApiError); ok {
  249. L.Push(aerr.Object)
  250. } else {
  251. L.Push(LString(err.Error()))
  252. }
  253. return 2
  254. } else {
  255. L.Insert(LTrue, 1)
  256. return L.GetTop()
  257. }
  258. }
  259. func basePrint(L *LState) int {
  260. top := L.GetTop()
  261. for i := 1; i <= top; i++ {
  262. fmt.Print(L.ToStringMeta(L.Get(i)).String())
  263. if i != top {
  264. fmt.Print("\t")
  265. }
  266. }
  267. fmt.Println("")
  268. return 0
  269. }
  270. func base_PrintRegs(L *LState) int {
  271. L.printReg()
  272. return 0
  273. }
  274. func baseRawEqual(L *LState) int {
  275. if L.CheckAny(1) == L.CheckAny(2) {
  276. L.Push(LTrue)
  277. } else {
  278. L.Push(LFalse)
  279. }
  280. return 1
  281. }
  282. func baseRawGet(L *LState) int {
  283. L.Push(L.RawGet(L.CheckTable(1), L.CheckAny(2)))
  284. return 1
  285. }
  286. func baseRawSet(L *LState) int {
  287. L.RawSet(L.CheckTable(1), L.CheckAny(2), L.CheckAny(3))
  288. return 0
  289. }
  290. func baseSelect(L *LState) int {
  291. L.CheckTypes(1, LTNumber, LTString)
  292. switch lv := L.Get(1).(type) {
  293. case LNumber:
  294. idx := int(lv)
  295. num := L.GetTop()
  296. if idx < 0 {
  297. idx = num + idx
  298. } else if idx > num {
  299. idx = num
  300. }
  301. if 1 > idx {
  302. L.ArgError(1, "index out of range")
  303. }
  304. return num - idx
  305. case LString:
  306. if string(lv) != "#" {
  307. L.ArgError(1, "invalid string '"+string(lv)+"'")
  308. }
  309. L.Push(LNumber(L.GetTop() - 1))
  310. return 1
  311. }
  312. return 0
  313. }
  314. func baseSetFEnv(L *LState) int {
  315. var value LValue
  316. if L.GetTop() == 0 {
  317. value = LNumber(1)
  318. } else {
  319. value = L.Get(1)
  320. }
  321. env := L.CheckTable(2)
  322. if fn, ok := value.(*LFunction); ok {
  323. if fn.IsG {
  324. L.RaiseError("cannot change the environment of given object")
  325. } else {
  326. fn.Env = env
  327. L.Push(fn)
  328. return 1
  329. }
  330. }
  331. if number, ok := value.(LNumber); ok {
  332. level := int(float64(number))
  333. if level <= 0 {
  334. L.Env = env
  335. return 0
  336. }
  337. cf := L.currentFrame
  338. for i := 0; i < level && cf != nil; i++ {
  339. cf = cf.Parent
  340. }
  341. if cf == nil || cf.Fn.IsG {
  342. L.RaiseError("cannot change the environment of given object")
  343. } else {
  344. cf.Fn.Env = env
  345. L.Push(cf.Fn)
  346. return 1
  347. }
  348. }
  349. L.RaiseError("cannot change the environment of given object")
  350. return 0
  351. }
  352. func baseSetMetatable(L *LState) int {
  353. L.CheckTypes(2, LTNil, LTTable)
  354. obj := L.Get(1)
  355. if obj == LNil {
  356. L.RaiseError("cannot set metatable to a nil object.")
  357. }
  358. mt := L.Get(2)
  359. if m := L.metatable(obj, true); m != LNil {
  360. if tb, ok := m.(*LTable); ok && tb.RawGetString("__metatable") != LNil {
  361. L.RaiseError("cannot change a protected metatable")
  362. }
  363. }
  364. L.SetMetatable(obj, mt)
  365. L.SetTop(1)
  366. return 1
  367. }
  368. func baseToNumber(L *LState) int {
  369. base := L.OptInt(2, 10)
  370. noBase := L.Get(2) == LNil
  371. switch lv := L.CheckAny(1).(type) {
  372. case LNumber:
  373. L.Push(lv)
  374. case LString:
  375. str := strings.Trim(string(lv), " \n\t")
  376. if strings.Index(str, ".") > -1 {
  377. if v, err := strconv.ParseFloat(str, LNumberBit); err != nil {
  378. L.Push(LNil)
  379. } else {
  380. L.Push(LNumber(v))
  381. }
  382. } else {
  383. if noBase && strings.HasPrefix(strings.ToLower(str), "0x") {
  384. base, str = 16, str[2:] // Hex number
  385. }
  386. if v, err := strconv.ParseInt(str, base, LNumberBit); err != nil {
  387. L.Push(LNil)
  388. } else {
  389. L.Push(LNumber(v))
  390. }
  391. }
  392. default:
  393. L.Push(LNil)
  394. }
  395. return 1
  396. }
  397. func baseToString(L *LState) int {
  398. v1 := L.CheckAny(1)
  399. L.Push(L.ToStringMeta(v1))
  400. return 1
  401. }
  402. func baseType(L *LState) int {
  403. L.Push(LString(L.CheckAny(1).Type().String()))
  404. return 1
  405. }
  406. func baseUnpack(L *LState) int {
  407. tb := L.CheckTable(1)
  408. start := L.OptInt(2, 1)
  409. end := L.OptInt(3, tb.Len())
  410. for i := start; i <= end; i++ {
  411. L.Push(tb.RawGetInt(i))
  412. }
  413. ret := end - start + 1
  414. if ret < 0 {
  415. return 0
  416. }
  417. return ret
  418. }
  419. func baseXPCall(L *LState) int {
  420. fn := L.CheckFunction(1)
  421. errfunc := L.CheckFunction(2)
  422. top := L.GetTop()
  423. L.Push(fn)
  424. if err := L.PCall(0, MultRet, errfunc); err != nil {
  425. L.Push(LFalse)
  426. if aerr, ok := err.(*ApiError); ok {
  427. L.Push(aerr.Object)
  428. } else {
  429. L.Push(LString(err.Error()))
  430. }
  431. return 2
  432. } else {
  433. L.Insert(LTrue, top+1)
  434. return L.GetTop() - top
  435. }
  436. }
  437. /* }}} */
  438. /* load lib {{{ */
  439. func loModule(L *LState) int {
  440. name := L.CheckString(1)
  441. loaded := L.GetField(L.Get(RegistryIndex), "_LOADED")
  442. tb := L.GetField(loaded, name)
  443. if _, ok := tb.(*LTable); !ok {
  444. tb = L.FindTable(L.Get(GlobalsIndex).(*LTable), name, 1)
  445. if tb == LNil {
  446. L.RaiseError("name conflict for module: %v", name)
  447. }
  448. L.SetField(loaded, name, tb)
  449. }
  450. if L.GetField(tb, "_NAME") == LNil {
  451. L.SetField(tb, "_M", tb)
  452. L.SetField(tb, "_NAME", LString(name))
  453. names := strings.Split(name, ".")
  454. pname := ""
  455. if len(names) > 1 {
  456. pname = strings.Join(names[:len(names)-1], ".") + "."
  457. }
  458. L.SetField(tb, "_PACKAGE", LString(pname))
  459. }
  460. caller := L.currentFrame.Parent
  461. if caller == nil {
  462. L.RaiseError("no calling stack.")
  463. } else if caller.Fn.IsG {
  464. L.RaiseError("module() can not be called from GFunctions.")
  465. }
  466. L.SetFEnv(caller.Fn, tb)
  467. top := L.GetTop()
  468. for i := 2; i <= top; i++ {
  469. L.Push(L.Get(i))
  470. L.Push(tb)
  471. L.Call(1, 0)
  472. }
  473. L.Push(tb)
  474. return 1
  475. }
  476. var loopdetection = &LUserData{}
  477. func loRequire(L *LState) int {
  478. name := L.CheckString(1)
  479. loaded := L.GetField(L.Get(RegistryIndex), "_LOADED")
  480. lv := L.GetField(loaded, name)
  481. if LVAsBool(lv) {
  482. if lv == loopdetection {
  483. L.RaiseError("loop or previous error loading module: %s", name)
  484. }
  485. L.Push(lv)
  486. return 1
  487. }
  488. loaders, ok := L.GetField(L.Get(RegistryIndex), "_LOADERS").(*LTable)
  489. if !ok {
  490. L.RaiseError("package.loaders must be a table")
  491. }
  492. messages := []string{}
  493. var modasfunc LValue
  494. for i := 1; ; i++ {
  495. loader := L.RawGetInt(loaders, i)
  496. if loader == LNil {
  497. L.RaiseError("module %s not found:\n\t%s, ", name, strings.Join(messages, "\n\t"))
  498. }
  499. L.Push(loader)
  500. L.Push(LString(name))
  501. L.Call(1, 1)
  502. ret := L.reg.Pop()
  503. switch retv := ret.(type) {
  504. case *LFunction:
  505. modasfunc = retv
  506. goto loopbreak
  507. case LString:
  508. messages = append(messages, string(retv))
  509. }
  510. }
  511. loopbreak:
  512. L.SetField(loaded, name, loopdetection)
  513. L.Push(modasfunc)
  514. L.Push(LString(name))
  515. L.Call(1, 1)
  516. ret := L.reg.Pop()
  517. modv := L.GetField(loaded, name)
  518. if ret != LNil && modv == loopdetection {
  519. L.SetField(loaded, name, ret)
  520. L.Push(ret)
  521. } else if modv == loopdetection {
  522. L.SetField(loaded, name, LTrue)
  523. L.Push(LTrue)
  524. } else {
  525. L.Push(modv)
  526. }
  527. return 1
  528. }
  529. /* }}} */
  530. /* hidden features {{{ */
  531. func baseNewProxy(L *LState) int {
  532. ud := L.NewUserData()
  533. L.SetTop(1)
  534. if L.Get(1) == LTrue {
  535. L.SetMetatable(ud, L.NewTable())
  536. } else if d, ok := L.Get(1).(*LUserData); ok {
  537. L.SetMetatable(ud, L.GetMetatable(d))
  538. }
  539. L.Push(ud)
  540. return 1
  541. }
  542. /* }}} */
  543. //