Lua4.0 lua_dofile,lua_dostring

這兩個函數的定義都位於 ldo.c 中,看看這兩個函數都作了什麼事兒?函數

先來看一下 lua_dofile 執行文件編碼

LUA_API int lua_dofile (lua_State *L, const char *filename) {
  int status = parse_file(L, filename);
  if (status == 0)  /* parse OK? */
    status = lua_call(L, 0, LUA_MULTRET);  /* call main */
  return status;
}

先解析文件,若是解析無誤,則調用。lua

由函數名字及下面的調用咱們能夠猜出,parse_file 應該是作的語法解析。spa

static int parse_file (lua_State *L, const char *filename) {
  ZIO z;
  int status;
  int bin;  /* flag for file mode */
  int c;    /* look ahead char */
  FILE *f = (filename == NULL) ? stdin : fopen(filename, "r");
  if (f == NULL) return LUA_ERRFILE;  /* unable to open file */
  c = fgetc(f);
  ungetc(c, f);
  bin = (c == ID_CHUNK);
  if (bin && f != stdin) {
    f = freopen(filename, "rb", f);  /* set binary mode */
    if (f == NULL) return LUA_ERRFILE;  /* unable to reopen file */
  }
  lua_pushstring(L, "@");
  lua_pushstring(L, (filename == NULL) ? "(stdin)" : filename);
  lua_concat(L, 2);
  c = lua_gettop(L);
  filename = lua_tostring(L, c);  /* filename = '@'..filename */
  luaZ_Fopen(&z, f, filename);
  status = protectedparser(L, &z, bin);
  lua_remove(L, c);  /* remove `filename' from the stack */
  if (f != stdin)
    fclose(f);
  return status;
}

先根據文件名來判斷輸入的是什麼?設計

若是文件名爲空,則從標準輸入讀取。code

不然從文件名讀取。orm

取得文件的第一個字符,若是是 ID_CHUNK 的話,表示文件是一個已經編譯好的 Lua 字節碼文件。rem

bin 標誌位就是用來標識這個文件是否爲 Lua 字節碼文件。字符串

後面對 filename 進行編碼,前面添加 '@' 符號。get

luaZ_Fopen 打開緩衝區。

protectedparser 解析。


先不看 protectedparser 裏作什麼了。

先看下 lua_dostring,由於最後也是調到了 protectedparser 身上。

LUA_API int lua_dostring (lua_State *L, const char *str) {
  return lua_dobuffer(L, str, strlen(str), str);
}

lua_dostring 內部調用 lua_dobuffer 來實現。

能夠看出這裏調用 lua_dobuffer 時 str 即當 buff 參數,又當 name 參數。

LUA_API int lua_dobuffer (lua_State *L, const char *buff, size_t size, const char *name) {
  int status = parse_buffer(L, buff, size, name);
  if (status == 0)  /* parse OK? */
    status = lua_call(L, 0, LUA_MULTRET);  /* call main */
  return status;
}

一樣,和文件類型,也是先語法解析。

解析無誤,則調用。

static int parse_buffer (lua_State *L, const char *buff, size_t size,
                         const char *name) {
  ZIO z;
  if (!name) name = "?";
  luaZ_mopen(&z, buff, size, name);
  return protectedparser(L, &z, buff[0]==ID_CHUNK);
}

能夠看到,在解析字符串 buffer 時,最後也是調到了 protectedparser 身上。


到 protectedparser 時,因爲緩衝區 ZIO 的做用,已經沒有文件或者字符串的區別了。

很不錯的設計思想!


這時候,再來看看 protectedparser 。

static int protectedparser (lua_State *L, ZIO *z, int bin) {
  struct ParserS p;
  unsigned long old_blocks;
  int status;
  p.z = z; p.bin = bin;
  /* before parsing, give a (good) chance to GC */
  if (L->nblocks/8 >= L->GCthreshold/10)
    luaC_collectgarbage(L);
  old_blocks = L->nblocks;
  status = luaD_runprotected(L, f_parser, &p);
  if (status == 0) {
    /* add new memory to threshold (as it probably will stay) */
    L->GCthreshold += (L->nblocks - old_blocks);
  }
  else if (status == LUA_ERRRUN)  /* an error occurred: correct error code */
    status = LUA_ERRSYNTAX;
  return status;
}

能夠看到它裏面調用了 f_parser 。

static void f_parser (lua_State *L, void *ud) {
  struct ParserS *p = (struct ParserS *)ud;
  Proto *tf = p->bin ? luaU_undump(L, p->z) : luaY_parser(L, p->z);
  luaV_Lclosure(L, tf, 0);
}

f_parser 裏調用 luaY_parser 來作具體的語法解析。

若是已是字節碼的文件,就不用語法解析了,直接 luaU_undump 字節碼就好。


到這裏,就差 lua_call 的執行了。

LUA_API int lua_call (lua_State *L, int nargs, int nresults) {
  StkId func = L->top - (nargs+1);  /* function to be called */
  struct CallS c;
  int status;
  c.func = func; c.nresults = nresults;
  status = luaD_runprotected(L, f_call, &c);
  if (status != 0)  /* an error occurred? */
    L->top = func;  /* remove parameters from the stack */
  return status;
}

lua_call 裏調用 f_call

static void f_call (lua_State *L, void *ud) {
  struct CallS *c = (struct CallS *)ud;
  luaD_call(L, c->func, c->nresults);
}

f_call 裏調用 luaD_call。

而後是 luaV_execute(L, cl, func+1));

這個就是虛擬機執行字節碼指令了。

luaV_execute 就是個大大的 switch case,不貼代碼了。

翻了下以前的博客,最先的時候有一個虛擬機執行的分析。

這裏就再也不重複一次這種體力勞動了。

力氣應該花在更有意義的地方!

----------------------------------------

到目前爲止的問題:

無!

----------------------------------------

相關文章
相關標籤/搜索