{"id":492,"date":"2021-12-03T12:35:59","date_gmt":"2021-12-03T04:35:59","guid":{"rendered":"https:\/\/www.ccagml.com\/?p=492"},"modified":"2021-12-03T12:35:59","modified_gmt":"2021-12-03T04:35:59","slug":"lua%e4%bb%8emain%e5%bc%80%e5%a7%8b%e4%b9%8b%e5%88%a4%e6%96%ad%e5%ad%97%e7%ac%a6%e4%b8%b2%e7%9b%b8%e7%ad%89","status":"publish","type":"post","link":"https:\/\/www.ccagml.com\/?p=492","title":{"rendered":"lua\u4ecemain\u5f00\u59cb\u4e4b\u5224\u65ad\u5b57\u7b26\u4e32\u76f8\u7b49"},"content":{"rendered":"<h1>\u4ece\u4e00\u4e2a\u7b80\u5355\u7684\u4f8b\u5b50\u5f00\u59cb<\/h1>\n<pre><code class=\"line-numbers\">    -- test\/hello.gafq\n    a = (\"aaa\" == \"aaa\")\n<\/code><\/pre>\n<p>\u4ece\u8fd9\u4e2a\u4f8b\u5b50,\u6211\u4eec\u77e5\u9053a\u7684\u7ed3\u679c\u662ftrue<\/p>\n<h1>lua\u662f\u5982\u4f55\u5224\u65ad\u5b57\u7b26\u4e32\u76f8\u7b49\u7684\u5462?\u5e26\u7740\u8fd9\u4e2a\u95ee\u9898\u6211\u4eec\u6765\u770b\u4ee3\u7801<\/h1>\n<h2>1. \u9996\u5148\u662fmain\u5165\u53e3,\u521b\u5efa\u4e00\u4e2a\u865a\u62df\u673a,\u5e76\u4fdd\u5b58\u53c2\u6570&#8221;.\/test\/hello.gafq &#8220;<\/h2>\n<pre><code class=\"line-numbers\">\/\/ gafq.c\n\nint main(int argc, char **argv)\n{\n    ...\n    ...\n    gafq_State *L = gafq_open(); \/\/ \u521b\u5efa\u4e00\u4e2alua\u865a\u62df\u673a\n    ...\n    s.argv = argv; \/\/ \u4fdd\u5b58\u53c2\u6570\n    ...\n    status = gafq_cpcall(L, &amp;pmain, &amp;s); \/\/ \u6267\u884c\u8c03\u7528\n    ...\n    ...\n}\n<\/code><\/pre>\n<h2>2. \u4ecemain\u6765\u4e86\u4e4b\u540e\u4f1a\u8d70\u5230pmain\u65b9\u6cd5,\u5176\u4e2d\u7684handle_script\u4f1a\u6267\u884c\u811a\u672c<\/h2>\n<pre><code class=\"line-numbers\">\/\/gafq.c\nstatic int pmain(gafq_State *L)\n{\n    ...\n    s-&gt;status = handle_script(L, argv, script); \/\/ \u8fd9\u91cc\u6267\u884c\u6587\u4ef6\u5185\u5bb9\n\n}\n<\/code><\/pre>\n<h2>3. \u4ecepmain\u8fc7\u6765\u7684\u6267\u884c,\u8fd9\u91cc\u505a\u4e86\u52a0\u8f7d\u811a\u672c test\/hello.gafq \u548c\u6267\u884c\u811a\u672c\u5185\u5bb9<\/h2>\n<pre><code class=\"line-numbers\">\/\/gafq.c\nstatic int handle_script(gafq_State *L, char **argv, int n)\n{\n    ...\n    status = gafqL_loadfile(L, fname);\n    ...\n    status = docall(L, narg, 0); \/\/ \u8fd9\u8fb9\u6267\u884c\u4e86\u6587\u4ef6\u597d\u50cf\n    ...\n}\n<\/code><\/pre>\n<h2>4. handle_script\u770b\u4e24\u6b65\u64cd\u4f5c,\u7b2c\u4e00\u6b65\u5904\u7406\u52a0\u8f7d\u7684\u6587\u4ef6gafqL_loadfile<\/h2>\n<pre><code class=\"line-numbers\">\/\/gauxlib.c\nGAFQLIB_API int gafqL_loadfile(gafq_State *L, const char *filename)\n{\n    ...\n    lf.f = fopen(filename, \"r\");\n    ...\n    \/\/ \u8fd9\u91cc\u4f1a\u52a0\u8f7d\u4e24\u79cd\u6587\u4ef6,\u53ef\u80fd\u662f\u6587\u672c,\u4e5f\u53ef\u80fd\u662f\u4e8c\u8fdb\u5236,\u4e8c\u8fdb\u5236\u901a\u8fc7\u5224\u65ad\u7b2c\u4e00\u4f4d\u4e0e\u9b54\u6570\u662f\u5426\u76f8\u7b49\n    if (c == GAFQ_SIGNATURE[0] &amp;&amp; filename) \/\/ \u9b54\u6570\u76f8\u7b49,\u662fgafq\u7684\u4e8c\u8fdb\u5236\u6587\u4ef6\n    ...\n    \/\/ \u5904\u7406\u52a0\u8f7d\u7684\u5185\u5bb9,\u6839\u636e\u4e0a\u4e00\u6b65\u7684\u662f\u5426\u4e8c\u8fdb\u5236,\u9009\u62e9\u4e0d\u540c\u7684\u8c03\u7528\u6765\u89e3\u6790\u5185\u5bb9\u5bf9\u5e94\u8fd9\u4e24\u4e2a\u65b9\u6cd5gafqU_undump : gafqY_parser\n    status = gafq_load(L, getF, &amp;lf, gafq_tostring(L, -1));\n    ...\n    ...\n}\n<\/code><\/pre>\n<h2>5. \u89e3\u91ca\u6587\u4ef6\u5185\u5bb9,\u8fd9\u91cc\u6211\u4eec\u4f1a\u505a\u8bcd\u6cd5\u5206\u6790,\u5c06\u6587\u672c\u5185\u5bb9\u505a\u6210TOKEN,\u8fd8\u4f1a\u521b\u5efa\u5b57\u7b26\u4e32<\/h2>\n<pre><code class=\"line-numbers\">\/\/gparser.c\nProto *gafqY_parser(gafq_State *L, ZIO *z, Mbuffer *buff, const char *name)\n{\n    struct LexState lexstate; \/\/\u8bcd\u6cd5\u5206\u6790\u7684\u7ed3\u6784\u4f53\n    ...\n    gafqX_setinput(L, &amp;lexstate, z, gafqS_new(L, name));\n    gafqX_next(&amp;lexstate); \/\/ \u8bfb\u53d6\u7b2c\u4e00\u4e2atoken\n    ...\n}\n\n<\/code><\/pre>\n<h2>6. \u4ece5\u8fc7\u6765,\u5148\u770b\u7b2c\u4e00\u6b65lua\u662f\u627e\u5230\u4e00\u4e2a\u5b57\u7b26\u4e32\u5bf9\u8c61,\u5982\u679c\u6709\u5c31\u8fd4\u56de,\u5982\u679c\u4e48\u6709\u5c31\u521b\u5efa<\/h2>\n<pre><code class=\"line-numbers\">TString *gafqS_newlstr(gafq_State *L, const char *str, size_t l)\n{\n    GCObject *o;\n    unsigned int h = cast(unsigned int, l); \/* seed *\/\n    size_t step = (l &gt;&gt; 5) + 1;             \/\/ \u5982\u679c\u5b57\u7b26\u4e32\u592a\u957f\u53ea\u54c8\u5e0c\u4e00\u90e8\u5206\n    size_t l1;\n    for (l1 = l; l1 &gt;= step; l1 -= step) \/\/ \u8ba1\u7b97\u54c8\u5e0c\n        h = h ^ ((h &lt;&lt; 5) + (h &gt;&gt; 2) + cast(unsigned char, str[l1 - 1]));\n    for (o = G(L)-&gt;strt.hash[lmod(h, G(L)-&gt;strt.size)]; o != NULL; o = o-&gt;gch.next)\n    {   \/\/ \u6839\u636e\u524d\u9762\u8ba1\u7b97\u7684\u54c8\u5e0c,\u4ece\u5168\u5c40\u7684\u5b57\u7b26\u4e32\u6c60\u5b50\u4e2d\u53d6\u51fa\u5b57\u7b26\u4e32\u5bf9\u8c61.\u5982\u679c\u6709\u627e\u5230\u54c8\u5e0c\u503c\u4e00\u6837,\u957f\u5ea6\u4e00\u6837,\u5e76\u4e14\u6bd4\u8f83\u662f\u4e00\u6837\u7684,\u5c31\u8fd4\u56de\u90a3\u4e2a\u5bf9\u8c61,\u5982\u679c\u6ca1\u627e\u5230\u5c31\u521b\u5efa\u4e2a\u65b0\u7684\n        TString *ts = rawgco2ts(o);\n        if (ts-&gt;tsv.len == l &amp;&amp; (memcmp(str, getstr(ts), l) == 0))\n        {\n            \/* string may be dead *\/\n            if (isdead(G(L), o))\n                changewhite(o);\n            return ts;\n        }\n    }\n    return newlstr(L, str, l, h); \/* not found *\/\n}\n\n<\/code><\/pre>\n<h2>7. \u7b2c6\u6b65\u5982\u679c\u5728\u5168\u5c40\u7684strt\u4e2d\u7684hash\u6ca1\u627e\u5230\u5b57\u7b26\u4e32\u4f1a\u521b\u5efa\u65b0\u7684\u5b57\u7b26\u4e32,\u7136\u540e\u653e\u5165\u5168\u5c40\u7684strt \u4e2d hash<\/h2>\n<pre><code class=\"line-numbers\">\/\/ gstring.c\nstatic TString *newlstr(gafq_State *L, const char *str, size_t l, unsigned int h)\n{\n    TString *ts;\n    stringtable *tb;\n    if (l + 1 &gt; (MAX_SIZET - sizeof(TString)) \/ sizeof(char))\n        gafqM_toobig(L);\n    ts = cast(TString *, gafqM_malloc(L, (l + 1) * sizeof(char) + sizeof(TString)));\n    ts-&gt;tsv.len = l;\n    ts-&gt;tsv.hash = h;\n    ts-&gt;tsv.marked = gafqC_white(G(L));\n    ts-&gt;tsv.tt = GAFQ_TSTRING;\n    ts-&gt;tsv.reserved = 0;\n    memcpy(ts + 1, str, l * sizeof(char));\n    ((char *)(ts + 1))[l] = '\\0'; \/* ending 0 *\/\n    tb = &amp;G(L)-&gt;strt;\n    h = lmod(h, tb-&gt;size);\n    ts-&gt;tsv.next = tb-&gt;hash[h]; \/* chain new entry *\/\n    tb-&gt;hash[h] = obj2gco(ts);\n    tb-&gt;nuse++;\n    if (tb-&gt;nuse &gt; cast(lu_int32, tb-&gt;size) &amp;&amp; tb-&gt;size &lt;= MAX_INT \/ 2)\n        gafqS_resize(L, tb-&gt;size * 2); \/* too crowded *\/\n    return ts;\n}\n\n<\/code><\/pre>\n<h2>8. \u56de\u5230\u7b2c\u4e94\u6b65\u4e2d\u7684<\/h2>\n<pre><code class=\"line-numbers\">\/\/gparser.c\nProto *gafqY_parser(gafq_State *L, ZIO *z, Mbuffer *buff, const char *name)\n{\n    struct LexState lexstate; \/\/\u8bcd\u6cd5\u5206\u6790\u7684\u7ed3\u6784\u4f53\n    ...\n    gafqX_setinput(L, &amp;lexstate, z, gafqS_new(L, name));\n    gafqX_next(&amp;lexstate); \/\/ \u8bfb\u53d6\u7b2c\u4e00\u4e2atoken \u8fd9\u91cc\u662f\u8bcd\u6cd5\u5206\u6790\u8bfb\u53d6\u7b2c\u4e00\u4e2atoken\n    \/\/ \u5728\u6211\u4eec\u7684\u4f8b\u5b50\u4e2d a = (\"aaa\" == \"aaa\"), \u8bfb\u51faa,\u8fd4\u56de\u8fd9\u4e2a\u662f\u4e00\u4e2a\u53d8\u91cf\u540dTK_NAME,\u5b9e\u73b0\u8fc7\u7a0b\u770b\u7b2c9\u6b65\n    ...\n}\n<\/code><\/pre>\n<h2>9. \u5728\u7b2c\u516b\u6b65\u4e2d,\u6211\u4eec\u8bfb\u53d6token\u5224\u65ada\u662f\u4e00\u4e2a\u53d8\u91cf,\u4ed6\u7684token\u662fTK_NAME<\/h2>\n<pre><code class=\"line-numbers\">\/\/ glex.c\nstatic int glex(LexState *ls, SemInfo *seminfo)\n{\n    gafqZ_resetbuffer(ls-&gt;buff);\n    for (;;)\n    {\n        switch (ls-&gt;current)\n        {\n            ...\n        default:\n        {\n            if (isalpha(ls-&gt;current) || ls-&gt;current == '_')\n            {\n                \/* identifier or reserved word *\/\n                TString *ts;\n                do\n                {\n                    save_and_next(ls);\n                } while (isalnum(ls-&gt;current) || ls-&gt;current == '_');\n                ts = gafqX_newstring(ls, gafqZ_buffer(ls-&gt;buff), gafqZ_bufflen(ls-&gt;buff));\n                \/\/ \u5224\u65ad\u8fd9\u4e2a\u5b57\u7b26\u662f\u4e00\u4e2a\u5173\u952e\u5b57\u4f8b\u5982 and,do,local \u8fd8\u662f\u4e00\u4e2a\u53d8\u91cf\u540d\n                if (ts-&gt;tsv.reserved &gt; 0)\n                    return ts-&gt;tsv.reserved - 1 + FIRST_RESERVED;\n                else\n                {\n                    seminfo-&gt;ts = ts;\n                    return TK_NAME;\n                }\n            }\n            ...\n        }\n        }\n    }\n}\n\n<\/code><\/pre>\n<h2>10. \u8bfb\u53d6\u5230\u7b2c\u4e00\u4e2atoken\u540e\u7ee7\u7eed\u7b2c5\u6b65\u7684\u4ee3\u7801<\/h2>\n<pre><code class=\"line-numbers\">\/\/gparser.c\nProto *gafqY_parser(gafq_State *L, ZIO *z, Mbuffer *buff, const char *name)\n{\n    struct LexState lexstate; \/\/\u8bcd\u6cd5\u5206\u6790\u7684\u7ed3\u6784\u4f53\n    ...\n    gafqX_setinput(L, &amp;lexstate, z, gafqS_new(L, name));\n    gafqX_next(&amp;lexstate); \/\/ \u8bfb\u53d6\u7b2c\u4e00\u4e2atoken \u8fd9\u91cc\u662f\u8bcd\u6cd5\u5206\u6790\u8bfb\u53d6\u7b2c\u4e00\u4e2atoken\n    \/\/ \u5728\u6211\u4eec\u7684\u4f8b\u5b50\u4e2d a = (\"aaa\" == \"aaa\"), \u8bfb\u51faa,\u8fd4\u56de\u8fd9\u4e2a\u662f\u4e00\u4e2a\u53d8\u91cf\u540dTK_NAME,\u5b9e\u73b0\u8fc7\u7a0b\u770b\u7b2c9\u6b65\n    chunk(&amp;lexstate);\n    ...\n}\n<\/code><\/pre>\n<h2>11. \u65b0\u7684chunk<\/h2>\n<pre><code class=\"line-numbers\">\/\/gparser.c\n\/\/ \u8fd9\u91cc\u662f\u89e3\u6790\u4ee3\u7801\u5757?\nstatic void chunk(LexState *ls)\n{\n    while (!islast &amp;&amp; !block_follow(ls-&gt;t.token))\n    {\n        islast = statement(ls); \/\/ \u8fd9\u91cc\u4f1a\u6839\u636e\u524d\u9762\u8bfb\u53d6\u7684\u7b2c\u4e00\u4e2atoken\u89e3\u6790\u662f\n        ...\n    }\n}\n\n\/\/ 11.1 \u89e3\u6790\u4ee3\u7801\u5757,\u5728\u6211\u4eec\u7684\u4e0a\u4e00\u6b65\u5f97\u5230a\u7684token\u662f\u4e2a\u53d8\u91cf\u540d, \u90a3\u4e48\u5728\u8fd9\u91cc\u8ba4\u4e3a\u4ed6\u63a5\u4e0b\u53bb\u5e94\u8be5\u662f\u4ec0\u4e48\u4e1c\u897f?\n\/\/ \u4f8b\u5982 a = (\"aaa\" == \"bbb\")\n\/\/ \u8c03\u7528\u65b9\u6cd5 a = function_name()\n\/\/ a.a \u53d6\u503c\n\/\/ a[] \u53d6\u503c\n\/\/ a:a \u51fd\u6570\nstatic int statement(LexState *ls)\n{\n    switch (ls-&gt;t.token)\n    {\n    ...\n    default:\n    {\n        exprstat(ls);\n        return 0; \/* to avoid warnings *\/\n    }\n    }\n}\n\n\/\/11.2\nstatic void exprstat(LexState *ls)\n{\n    primaryexp(ls, &amp;v.v);\n}\n\/11.3\nstatic void primaryexp(LexState *ls, expdesc *v)\n{\n    \/* primaryexp -&gt;\n          prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } *\/\n    FuncState *fs = ls-&gt;fs;\n    prefixexp(ls, v);\n}\n\n\/\/11.4\u73b0\u5728\u662fTK_NAME\nstatic void prefixexp(LexState *ls, expdesc *v)\n{\n    \/* prefixexp -&gt; NAME | '(' expr ')' *\/\n    switch (ls-&gt;t.token)\n    {\n    case TK_NAME:\n    {\n        singlevar(ls, v);\n        return;\n    }\n\n    }\n}\n\/\/11.5\nstatic void primaryexp(LexState *ls, expdesc *v)\n{\n    \/* primaryexp -&gt;\n          prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } *\/\n    FuncState *fs = ls-&gt;fs;\n    prefixexp(ls, v);\n    for (;;)\n    {\n        switch (ls-&gt;t.token)\n        {\n        ...\n        default:\n            return;\n        ...\n        }\n    }\n}\n\n\/\/11.6\nstatic void exprstat(LexState *ls)\n{\n    primaryexp(ls, &amp;v.v);\n    assignment(ls, &amp;v, 1);\n}\n\n\/\/11.7 \u4eceexprstat\u6765, \u8fd9\u91cc\u662f\u8ba1\u7b97\u53d8\u91cf\u8d4b\u503c\u8868\u8fbe\u5f0f\nstatic void assignment(LexState *ls, struct LHS_assign *lh, int nvars)\n{\n    ...\n    if (testnext(ls, ','))\n    {\n        ...\n    }\n    else\n    { \/* assignment -&gt; `=' explist1 *\/\n        int nexps;\n        checknext(ls, '='); \/\/ \u68c0\u67e5a\u540e\u9762\u662f\u4e0d\u662f\u6709=\u53f7\n        nexps = explist1(ls, &amp;e);\n        ...\n    }\n    ...\n}\n\n\/\/11.8\u89e3\u6790\u53c2\u6570\u5217\u8868?\nstatic int explist1(LexState *ls, expdesc *v)\n{\n    \/* explist1 -&gt; expr { `,' expr } *\/\n    int n = 1; \/* at least one expression *\/\n    expr(ls, v);\n    while (testnext(ls, ','))\n    {\n        gafqK_exp2nextreg(ls-&gt;fs, v);\n        expr(ls, v);\n        n++;\n    }\n    return n;\n}\n\n\/\/11.9\n\u5728explist1\u4e2d\u8c03\u7528expr \u76f8\u5f53\u4e8e\u8c03\u7528\u4e86 subexpr \u65b9\u6cd5\n** subexpr -&gt; (\u5b50\u8868\u8fbe\u5f0f | \u4e00\u5143\u8fd0\u7b97\u7b26\u548c\u5b50\u8868\u8fbe\u5f0f) { \u4e8c\u5143\u8fd0\u7b97\u7b26\u548c\u5b50\u8868\u8fbe\u5f0f }\n** where `binop' is any binary operator with a priority higher than `limit'\nstatic BinOpr subexpr(LexState *ls, expdesc *v, unsigned int limit)\n{\n    BinOpr op;\n    UnOpr uop;\n    enterlevel(ls);\n    uop = getunopr(ls-&gt;t.token);\n    if (uop != OPR_NOUNOPR)\n    {\n        ...\n    }\n    else\n        simpleexp(ls, v);\n}\n\n\/\/11.10\nstatic void simpleexp(LexState *ls, expdesc *v)\n{\n    \/\/ \u8fd9\u65f6\u5019\u89e3\u6790\u5230 ls-&gt;t.token = '('\n    switch (ls-&gt;t.token)\n    {\n    default:\n    {\n        primaryexp(ls, v);\n        return;\n    }\n    }\n    gafqX_next(ls);\n}\n\n\/\/11.11\u8fd9\u8fb9\u5904\u7406 ls-&gt;t.token == '(' \u4e4b\u540e\u7684\u89e3\u6790\nstatic void primaryexp(LexState *ls, expdesc *v)\n{\n    prefixexp(ls, v);\n}\n\n\/\/11.12\nstatic void prefixexp(LexState *ls, expdesc *v)\n{\n    \/* prefixexp -&gt; NAME | '(' expr ')' *\/\n    switch (ls-&gt;t.token)\n    {\n    case '(':\n    {\n        \/\/ \u5339\u914d\u5230\u65f6(,\u5f00\u59cb\u505a\u4e0b\u4e00\u6b65\u89e3\u6790\n        gafqX_next(ls); \/\/ \u8fd9\u91cc\u505a\u4e86\u53d6\u4e0b\u4e00\u6b65token, \u5728\u6211\u4eec\u7684\u4f8b\u5b50\u540e(\u4e4b\u540e\u662f\u5b57\u7b26\u4e32 \"aaa\"\n        expr(ls, v);\n\n    }\n    }\n}\n\n\/\/11.13 \u524d\u9762\u6211\u4eec\u9047\u5230token = '('\u4e4b\u540e\u89e3\u6790\u4e0b\u4e00\u5c42\u53c8\u662fsubexpr\nstatic BinOpr subexpr(LexState *ls, expdesc *v, unsigned int limit)\n{\n    BinOpr op;\n    UnOpr uop;\n    enterlevel(ls);\n    uop = getunopr(ls-&gt;t.token); \/\/ \u524d\u9762\u505a\u4e86gafqX_next,\u8fd9\u91cctoken\u53d8\u6210\u4e86286\u65e2TK_STRING\n    if (uop != OPR_NOUNOPR)\n    {\n        ...\n    }\n    else\n        simpleexp(ls, v); \/\/ \u8fd9\u91cc\u505a\u4e86\u521b\u5efa\"aaa\"\u5b57\u7b26\u4e32,\u7136\u540e\u53c8\u53d6\u4e0b\u4e00\u4e2atoken\n    op = getbinopr(ls-&gt;t.token); \u8fd9\u65f6\u5019token\u53d8\u6210\u4e86280 \"==\" \u65e2 TK_EQ\n    while (op != OPR_NOBINOPR &amp;&amp; priority[op].left &gt; limit)\n    {\n        expdesc v2;\n        BinOpr nextop;\n        gafqX_next(ls); \/\/ \u8fd9\u91cc\u53c8\u53d6\u4e86\u4e0b\u4e00\u4e2atoken, a = (\"aaa\" == \"aaa\")\u8fd9\u65f6\u5019token\u53d8\u6210\u4e0b\u4e00\u4e2a\u5b57\u7b26\u4e32\"aaa\"\n        gafqK_infix(ls-&gt;fs, op, v);\n        \/* read sub-expression with higher priority *\/\n        nextop = subexpr(ls, &amp;v2, priority[op].right);\n}\n\n\/\/11.14 \u7531\u4e8e\u524d\u9762 == \u540e\u53d6\u5230\u4e86\u5b57\u7b26\u4e32\"aaa\"\u53c8\u9012\u5f52\u8fdb\u4e86\u8fd9\u4e2a\u51fd\u6570\nstatic BinOpr subexpr(LexState *ls, expdesc *v, unsigned int limit)\n{\n    BinOpr op;\n    UnOpr uop;\n    enterlevel(ls);\n    uop = getunopr(ls-&gt;t.token);\n    if (uop != OPR_NOUNOPR)\n    {\n        ...\n    }\n    else\n        simpleexp(ls, v);\n    \/* expand while operators have priorities higher than `limit' *\/\n    op = getbinopr(ls-&gt;t.token);\n    \/\/ \u6700\u540e\u4e00\u4e2aaaa\u540e\u8fd9\u884c\u5c31\u6ca1\u6709\u8868\u8fbe\u5f0f\u4e86\n}\n\n\/\/11.15 \u89e3\u6790\u5b8c\u540e \u6211\u4eec\u53c8\u56de\u5230\u4e8611.12\u5339\u914d\u5230'('\u7684\u5730\u65b9\u7ee7\u7eed\u5f80\u4e0b\u5224\u65ad\nstatic void prefixexp(LexState *ls, expdesc *v)\n{\n    \/* prefixexp -&gt; NAME | '(' expr ')' *\/\n    switch (ls-&gt;t.token)\n    {\n    case '(':\n    {\n        int line = ls-&gt;linenumber;\n        gafqX_next(ls);\n        expr(ls, v);\n        check_match(ls, ')', '(', line); \/\/ \u662f\u4e0d\u662f\u62ec\u53f7\u5339\u914d\n        return;\n    }\n}\n\n\/\/11.16\u4ece11.15\u8fd4\u56de\u540e\u56de\u5230\u4e86\u539f\u672c11.11\u7684\u5730\u65b9\nstatic void primaryexp(LexState *ls, expdesc *v)\n{\n    prefixexp(ls, v);\n     for (;;)\n    {\n        switch (ls-&gt;t.token) \/\/ \u4ee5\u4e3a\u6211\u4eec\u7684\u4f8b\u5b50\u4ee3\u7801\u5c311\u884c,\u524d\u9762\u89e3\u6790\u5b8c\u4e86\u4e4b\u540e,\u5df2\u7ecf\u7ed3\u675f\u4e86,\u8fd9\u91cc\u7684token\u53d8\u6210287,\u65e2 TK_EOS\n        {\n        default:\n            return;\n        }\n    }\n}\n\n\/\/11.17 \u4ece11.11\u4e00\u76f4\u8fd4\u56de\u523011.7\u7684\u5730\u65b9\nstatic void assignment(LexState *ls, struct LHS_assign *lh, int nvars)\n{\n        \/\/ \u6211\u4eec\u4ece11.7-11.17\u505a\u4e86\u89e3\u6790,\u628a\u6211\u4eec\u4e00\u884c\u7684\u4ee3\u7801 a = (\"aaa\" == \"aaa\")\u89e3\u6790\u5b8c\u6210, \u8fd9\u65f6\u5019nexps = 1\n        nexps = explist1(ls, &amp;e);\n        if (nexps != nvars)\n        {\n            adjust_assign(ls, nvars, nexps, &amp;e);\n            if (nexps &gt; nvars)\n                ls-&gt;fs-&gt;freereg -= nexps - nvars; \/* remove extra values *\/\n        }\n        else\n        {\n            gafqK_setoneret(ls-&gt;fs, &amp;e); \/* close last expression *\/\n            gafqK_storevar(ls-&gt;fs, &amp;lh-&gt;v, &amp;e);\n            return; \/* avoid default *\/\n        }\n    }\n    init_exp(&amp;e, VNONRELOC, ls-&gt;fs-&gt;freereg - 1); \/* default assignment *\/\n    gafqK_storevar(ls-&gt;fs, &amp;lh-&gt;v, &amp;e);\n}\n\n\n<\/code><\/pre>\n<h2>12. \u89e3\u6790\u6587\u672c\u7684\u90e8\u5206\u5148\u544a\u4e00\u6bb5\u843d,\u63a5\u4e0b\u6765\u770b\u5982\u4f55\u6267\u884c,\u56de\u5230\u7b2c4\u6b65\u7684handle_script\u4e2d<\/h2>\n<pre><code class=\"line-numbers\">\/\/gafq.c\nstatic int handle_script(gafq_State *L, char **argv, int n)\n{\n    ...\n    status = gafqL_loadfile(L, fname); \/\/ \u89e3\u6790\u6587\u672c\u5185\u5bb9,\u5728\u524d\u9762\u89e3\u6790\u7684*gafqY_parser\u4e2d \u4e2d,\u6211\u4eec\u5f04\u51fa\u4e86struct FuncState funcstate;,\u8fd9\u91cc\u8981\u6267\u884c\u8fd9\u4e2a\u51fd\u6570\n    ...\n    status = docall(L, narg, 0); \/\/ \u8fd9\u8fb9\u6267\u884c\u4e86\u6587\u4ef6\u597d\u50cf\n}\n\n<\/code><\/pre>\n<h2>13. \u5728\u4e0a\u4e00\u6b65,\u6211\u4eec\u505a\u51fa\u7684funcstate,\u4e8e\u662fdocall\u4f1a\u8c03\u7528\u6267\u884clua\u7684\u65b9\u6cd5<\/h2>\n<pre><code class=\"line-numbers\">gdo.c\n\/\/ \u666e\u901a\u8c03\u7528\u51fd\u6570\nvoid gafqD_call(gafq_State *L, StkId func, int nResults)\n{\n    ...\n    if (gafqD_precall(L, func, nResults) == PCRGAFQ) \/\/ \u5982\u679c\u662f\u4e2alua\u7684\u51fd\u6570,\u4f1a\u6267\u884c\u4e0b\u9762\u8fd9\u4e00\u4e2a\u65b9\u6cd5\n        gafqV_execute(L, 1);                       \n    ...\n}\n\n<\/code><\/pre>\n<h2>14. \u6267\u884c\u521a\u521a11\u89e3\u6790\u51fa\u6587\u672c\u7684\u5185\u5bb9<\/h2>\n<pre><code class=\"line-numbers\">void gafqV_execute(gafq_State *L, int nexeccalls)\n{\n    ...\n    pc = L-&gt;savedpc;\n    ...\n    for (;;)\n    {\n        \/\/\u53d6\u51fa\u5f53\u524d\u6307\u4ee4\n        const Instruction i = *pc++;\n        StkId ra;\n        ...\n        ra = RA(i); \/\/ \u53d6\u51fa\u6267\u884c\u7684A\u5bc4\u5b58\u5668\n        ...\n        \/\/ \u8fd9\u91cc\u7684i\u4e3a 2,160,083,031\n        \/\/ \u5bf9\u5e94\u4e8c\u8fdb\u5236 1000 0000 1100 0000 0100 0000 0101 0111\n        switch (GET_OPCODE(i))\n        {\n            \/\/ \u8ba1\u7b97\u76f8\u7b49\n            case OP_EQ:\n            {\n                \/\/\u6761\u4ef6\u6210\u7acb\u5c31\u6267\u884c\uff0c\u5426\u5219\u5c31\u8df3\u8f6cequalobj\u662f\u7c7b\u578b\u6bd4\u8f83\uff0c\u76f8\u540c\u7c7b\u578b\u7528gafqV_equalval\n                TValue *rb = RKB(i);\n                TValue *rc = RKC(i);\n                Protect(if (equalobj(L, rb, rc) == GETARG_A(i)) dojump(L, pc, GETARG_sBx(*pc));) pc++;\n                continue;\n            }\n\n        }\n    }\n}\n\n<\/code><\/pre>\n<h2>15.\u572814\u4e2d\u8fd0\u7528\u5230\u4e86\u4e09\u4e2a\u5b8f<\/h2>\n<pre><code class=\"line-numbers\">\u7b2c\u4e00\u4e2a\u5b8fGET_OPCODE(i)\n    #define GET_OPCODE(i) (cast(OpCode, ((i) &gt;&gt; POS_OP) &amp; MASK1(SIZE_OP, 0)))\n    cast\u5f3a\u5236\u7c7b\u578b\u8f6c\u6362,\u628a\u540e\u9762\u7684\u503c\u8f6c\u6210\u524d\u9762\u7684\u7c7b\u578b\n    OpCode \u662fenum\u5e38\u91cf\n    MASK1(n, p) \u521b\u5efa\u5728p\u4f4d\u7f6e\u5f00\u59cb\u521b\u5efan\u4e2a\u4e3a1\u7684bit\n    #define SIZE_OP 6  \/\/ \u64cd\u4f5c\u7801\u5927\u5c0f\u5360\u75286\u4e2a\u6bd4\u7279\n    MASK1(SIZE_OP, 0) = \u4e8c\u8fdb\u52360000000000000000111111 = \u5341\u8fdb\u5236\u768463\n    \u8fd9\u91cc\u7684i\u4e3a 2,160,083,031\n    \u5bf9\u5e94\u4e8c\u8fdb\u5236 1000 0000 1100 0000 0100 0000 0101 0111\n    #define POS_OP 0                  \/\/ \u64cd\u4f5c\u7801\u5f00\u59cb\n    010111 &amp; 111111 = 23 \u65e2OP_EQ\n\n\u7b2c\u4e8c\u4e2a\u5b8fRKB(i)\n#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, ISK(GETARG_B(i)) ? k + INDEXK(GETARG_B(i)) : base + GETARG_B(i))\n\n    \u8fd9\u91cc\u7684i\u4e3a 2,160,083,031\n    B         C          A       \u64cd\u4f5c\u7801EQ\n    100000001 100000001 00000001  010111\n\n    check_exp(c,e) \u68c0\u67e5c \u662f\u4e0d\u662ftrue, \u7136\u540e\u4f1a\u8fd4\u56dee?\n    #define getBMode(m) (cast(enum OpArgMask, (gafqP_opmodes[m] &gt;&gt; 4) &amp; 3)) \/\/ \u64cd\u4f5c\u6570B\u7684\u4f7f\u7528\u6a21\u5f0f\n    cast\u5f3a\u5236\u7c7b\u578b\u8f6c\u6362,\u628a\u540e\u9762\u7684\u503c\u8f6c\u6210\u524d\u9762\u7684\u7c7b\u578b\n    OpArgMask \u662f enum\u5e38\u91cf\n    gafqP_opmodes \u662f\u4e00\u4e2a\u6574\u6570\u6307\u4ee4\u8868,OP_EQ\u7684\u6574\u6570\u662fopmode(1, 0, 3, 3, 0)\n    #define opmode(t, a, b, c, m) (((1) &lt;&lt; 7) | ((0) &lt;&lt; 6) | ((3) &lt;&lt; 4) | ((3) &lt;&lt; 2) | (0))\n                                   (1000 0000) | (0)        | (0011 0000) | (0000 1100) | 0\n    \u8fd9\u91cc\u6211\u4eec\u5f97\u5230OP_EQ \u5728gafqP_opmodes[23] \u7684\u64cd\u4f5c\u6307\u4ee4\u662f\u4e8c\u8fdb\u5236 10111100 \u4e3a\u5341\u8fdb\u5236\u7684188\n    \u6240\u4ee5 (gafqP_opmodes[m] &gt;&gt; 4) &amp; 3) = ((188 &gt;&gt; 4) &amp; 3)  = 3,\u8f6c\u6210OpArgMask\u5e38\u91cf\u4e3a OpArgK\n    \u8fd9\u91cc\u5b8c\u6210\u4e86\u5b8fRKB(i)\u7684\u524d\u534a\u90e8 getBMode(GET_OPCODE(i)) == OpArgK \u662ftrue\n    \u63a5\u4e0b\u6765\u770b\u540e\u534a\u90e8\n    ISK(GETARG_B(i)) ? k + INDEXK(GETARG_B(i)) : base + GETARG_B(i)\n    \u8fd9\u91cc\u770b\u51fa\u662f\u4e00\u4e2a\u4e09\u5143\u8868\u8fbe\u5f0f\n    #define GETARG_B(i) (cast(int, ((i) &gt;&gt; POS_B) &amp; MASK1(SIZE_B, 0)))\n    POS_B = (6(op\u64cd\u4f5c\u7801\u4f4d\u6570) + 8(A\u64cd\u4f5c\u7801\u4f4d\u6570) ) + 9(C\u64cd\u4f5c\u7801\u4f4d\u6570) = 23\n    SIZE_B = 9\n    \u5f97\u5230B\u64cd\u4f5c\u7801\u662f 100000001\n    #define BITRK (1 &lt;&lt; (SIZE_B - 1)) 1\u8868\u793a\u5728\u5e38\u91cf\u4f4d\u7f6e, 0\u8868\u793a\u5728\u5bc4\u5b58\u5668*\/\n    #define ISK(x) ((x)&amp;BITRK)     \/* \u770b\u662f\u5b58\u5728\u5e38\u91cf\u8fd8\u662f\u5bc4\u5b58\u5668 *\/\n    \u6211\u4eec\u7684B\u64cd\u4f5c\u7801\u662f 100000001 \u6700\u9ad8\u4f4d\u662f1,\u8868\u793a\u5728\u5e38\u91cf\u4f4d\u7f6e,\u6267\u884c k + INDEXK(GETARG_B(i))\n    #define INDEXK(r) ((int)(r) &amp; ~BITRK) \/\/ \u83b7\u53d6\u5e38\u91cf\u7684\u7d22\u5f15\n    \u6211\u4eec\u7684 B\u64cd\u4f5c\u7801\u53bb\u6389\u6700\u9ad8\u4f4d\u5c31\u662f 00000001\n    \u8fd9\u91cc\u7684k\u662f\n    Proto\u4e2d\u7684 TValue *k;\u51fd\u6570\u4f7f\u7528\u7684\u5e38\u6570\n\n\u7b2c\u4e09\u4e2a\u5b8fRKC\u539f\u7406\u7c7b\u4f3cRKB\n<\/code><\/pre>\n<h2>16. \u7ecf\u8fc715\u7684\u5206\u6790,\u6211\u4eec\u56de\u523014\u6b65\u4e2d,\u6211\u4eec\u83b7\u5f97\u4e86\u4e24\u4e2a\u5b57\u7b26\u4e32\u5bf9\u8c61,\u8fdb\u5165\u4e86\u6211\u4eec\u95ee\u9898\u7684\u5173\u952e\u5904,\u5b57\u7b26\u4e32\u662f\u5982\u4f55\u6bd4\u8f83\u7684<\/h2>\n<pre><code class=\"line-numbers\">\/\/gvm.c\n\/\/ \u8ba1\u7b97\u76f8\u7b49\n    case OP_EQ:\n    {                       \u5728\u6211\u4eec\u7684\u4f8b\u5b50\u4e2d \"aaa\" == \"bbb\"\n    TValue *rb = RKB(i);    \/\/ \u83b7\u5f97\u4e86b\u64cd\u4f5c\u7b26\u7684\u5b57\u7b26\u4e32\u5bf9\u8c61\n    TValue *rc = RKC(i);    \/\/ \u83b7\u5f97\u4e86c\u64cd\u4f5c\u7b26\u7684\u5b57\u7b26\u4e32\u5bf9\u8c61\n    Protect(if (equalobj(L, rb, rc) == GETARG_A(i)) dojump(L, pc, GETARG_sBx(*pc));) pc++;\n    }\n\n<\/code><\/pre>\n<h2>17. lua\u5f00\u59cb\u6bd4\u8f83\u4e24\u4e2a\u5bf9\u8c61rb,\u548crc<\/h2>\n<pre><code class=\"line-numbers\">#define equalobj(L, o1, o2) (ttype(o1) == ttype(o2) &amp;&amp; gafqV_equalval(L, o1, o2))\nlua\u4f1a\u5148\u6bd4\u8f83\u7c7b\u578b,\u5728\u6bd4\u8f83\u6570\u636e,\u6211\u4eec\u7684\u4f8b\u5b50,\u7c7b\u578b\u90fd\u662f\u5b57\u7b26\u4e32\u662f\u4e00\u6837\u7684\nint gafqV_equalval(gafq_State *L, const TValue *t1, const TValue *t2)\n{\n    const TValue *tm;\n    gafq_assert(ttype(t1) == ttype(t2));\n    switch (ttype(t1))\n    {\n    '''\n    '''\n    -- \u56e0\u4e3a\u6211\u4eec\u7684\u4f8b\u5b50\u662f\u5b57\u7b26\u4e32,\u6240\u4ee5\u8fdb\u5165\u7684default\u7684\u5206\u652f\n    default:\n        return gcvalue(t1) == gcvalue(t2);\n    }\n}\n\n    #define gcvalue(o) check_exp(iscollectable(o), (o)-&gt;value.gc)\n    -- \u4ece\u8fd9\u4e2a\u5b8f\u6211\u4eec\u53ef\u4ee5\u770b\u51fa,\u5f53\u6211\u4eec\u5728\u6bd4\u8f83\u5b57\u7b26\u4e32\u7684\u65f6\u5019,\u5224\u65ad\u662f\u4e0d\u662f\u540c\u4e00\u4e2agc\u5bf9\u8c61\n    typedef union\n    {\n        GCObject *gc; \/\/ \u95f4\u63a5\u5f15\u7528\n        void *p;\n        gafq_Number n;\n        int b;\n    } Value;\n    \/\/ \u6240\u6709\u53ef\u56de\u6536\u7684\u5bf9\u8c61\n    union GCObject\n    {\n        GCheader gch;\n        union TString ts;\n        union Udata u;\n        union Closure cl;\n        struct Table h;\n        struct Proto p;\n        struct UpVal uv;\n        struct gafq_State th; \/* thread *\/\n    };\n<\/code><\/pre>\n<h2>18. \u81f3\u6b64\u6211\u4eec\u77e5\u9053\u4e86,lua\u4f1a\u5c06\u5b57\u7b26\u4e32\u5b58\u5728\u5168\u5c40\u7684strt\u4e2d,\u6bd4\u8f83\u7684\u65f6\u5019\u662f\u6bd4\u8f83\u662f\u4e0d\u662f\u540c\u4e00\u4e2agc\u5bf9\u8c61<\/h2>\n","protected":false},"excerpt":{"rendered":"<p>\u4ece\u4e00\u4e2a\u7b80\u5355\u7684\u4f8b\u5b50\u5f00\u59cb &#8212; test\/hello.gafq a = (&#8220;aaa&#8221; == &#8220;aaa&#8221;) \u4ece\u8fd9\u4e2a\u4f8b<a href=\"https:\/\/www.ccagml.com\/?p=492\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">lua\u4ecemain\u5f00\u59cb\u4e4b\u5224\u65ad\u5b57\u7b26\u4e32\u76f8\u7b49<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[32],"tags":[],"_links":{"self":[{"href":"https:\/\/www.ccagml.com\/index.php?rest_route=\/wp\/v2\/posts\/492"}],"collection":[{"href":"https:\/\/www.ccagml.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ccagml.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ccagml.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ccagml.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=492"}],"version-history":[{"count":2,"href":"https:\/\/www.ccagml.com\/index.php?rest_route=\/wp\/v2\/posts\/492\/revisions"}],"predecessor-version":[{"id":494,"href":"https:\/\/www.ccagml.com\/index.php?rest_route=\/wp\/v2\/posts\/492\/revisions\/494"}],"wp:attachment":[{"href":"https:\/\/www.ccagml.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=492"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ccagml.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=492"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ccagml.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=492"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}