misc/liblua/lparser.c
author koda
Sat, 09 Mar 2013 00:57:09 +0100
changeset 8702 a28966180a29
parent 2812 0a24853de796
child 10017 de822cd3df3a
permissions -rw-r--r--
have fpc work in the right directory instead of passing the full path of the main module (avoids having full paths in debug build backtraces for the first module only)
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2812
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
     1
/*
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
     2
** $Id: lparser.c,v 2.42.1.3 2007/12/28 15:32:23 roberto Exp $
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
     3
** Lua Parser
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
     4
** See Copyright Notice in lua.h
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
     5
*/
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
     6
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
     7
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
     8
#include <string.h>
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
     9
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    10
#define lparser_c
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    11
#define LUA_CORE
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    12
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    13
#include "lua.h"
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    14
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    15
#include "lcode.h"
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    16
#include "ldebug.h"
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    17
#include "ldo.h"
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    18
#include "lfunc.h"
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    19
#include "llex.h"
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    20
#include "lmem.h"
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    21
#include "lobject.h"
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    22
#include "lopcodes.h"
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    23
#include "lparser.h"
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    24
#include "lstate.h"
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    25
#include "lstring.h"
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    26
#include "ltable.h"
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    27
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    28
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    29
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    30
#define hasmultret(k)		((k) == VCALL || (k) == VVARARG)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    31
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    32
#define getlocvar(fs, i)	((fs)->f->locvars[(fs)->actvar[i]])
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    33
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    34
#define luaY_checklimit(fs,v,l,m)	if ((v)>(l)) errorlimit(fs,l,m)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    35
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    36
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    37
/*
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    38
** nodes for block list (list of active blocks)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    39
*/
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    40
typedef struct BlockCnt {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    41
  struct BlockCnt *previous;  /* chain */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    42
  int breaklist;  /* list of jumps out of this loop */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    43
  lu_byte nactvar;  /* # active locals outside the breakable structure */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    44
  lu_byte upval;  /* true if some variable in the block is an upvalue */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    45
  lu_byte isbreakable;  /* true if `block' is a loop */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    46
} BlockCnt;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    47
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    48
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    49
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    50
/*
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    51
** prototypes for recursive non-terminal functions
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    52
*/
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    53
static void chunk (LexState *ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    54
static void expr (LexState *ls, expdesc *v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    55
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    56
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    57
static void anchor_token (LexState *ls) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    58
  if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    59
    TString *ts = ls->t.seminfo.ts;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    60
    luaX_newstring(ls, getstr(ts), ts->tsv.len);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    61
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    62
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    63
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    64
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    65
static void error_expected (LexState *ls, int token) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    66
  luaX_syntaxerror(ls,
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    67
      luaO_pushfstring(ls->L, LUA_QS " expected", luaX_token2str(ls, token)));
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    68
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    69
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    70
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    71
static void errorlimit (FuncState *fs, int limit, const char *what) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    72
  const char *msg = (fs->f->linedefined == 0) ?
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    73
    luaO_pushfstring(fs->L, "main function has more than %d %s", limit, what) :
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    74
    luaO_pushfstring(fs->L, "function at line %d has more than %d %s",
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    75
                            fs->f->linedefined, limit, what);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    76
  luaX_lexerror(fs->ls, msg, 0);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    77
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    78
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    79
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    80
static int testnext (LexState *ls, int c) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    81
  if (ls->t.token == c) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    82
    luaX_next(ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    83
    return 1;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    84
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    85
  else return 0;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    86
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    87
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    88
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    89
static void check (LexState *ls, int c) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    90
  if (ls->t.token != c)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    91
    error_expected(ls, c);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    92
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    93
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    94
static void checknext (LexState *ls, int c) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    95
  check(ls, c);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    96
  luaX_next(ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    97
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    98
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
    99
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   100
#define check_condition(ls,c,msg)	{ if (!(c)) luaX_syntaxerror(ls, msg); }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   101
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   102
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   103
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   104
static void check_match (LexState *ls, int what, int who, int where) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   105
  if (!testnext(ls, what)) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   106
    if (where == ls->linenumber)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   107
      error_expected(ls, what);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   108
    else {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   109
      luaX_syntaxerror(ls, luaO_pushfstring(ls->L,
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   110
             LUA_QS " expected (to close " LUA_QS " at line %d)",
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   111
              luaX_token2str(ls, what), luaX_token2str(ls, who), where));
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   112
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   113
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   114
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   115
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   116
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   117
static TString *str_checkname (LexState *ls) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   118
  TString *ts;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   119
  check(ls, TK_NAME);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   120
  ts = ls->t.seminfo.ts;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   121
  luaX_next(ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   122
  return ts;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   123
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   124
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   125
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   126
static void init_exp (expdesc *e, expkind k, int i) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   127
  e->f = e->t = NO_JUMP;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   128
  e->k = k;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   129
  e->u.s.info = i;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   130
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   131
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   132
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   133
static void codestring (LexState *ls, expdesc *e, TString *s) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   134
  init_exp(e, VK, luaK_stringK(ls->fs, s));
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   135
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   136
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   137
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   138
static void checkname(LexState *ls, expdesc *e) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   139
  codestring(ls, e, str_checkname(ls));
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   140
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   141
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   142
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   143
static int registerlocalvar (LexState *ls, TString *varname) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   144
  FuncState *fs = ls->fs;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   145
  Proto *f = fs->f;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   146
  int oldsize = f->sizelocvars;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   147
  luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars,
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   148
                  LocVar, SHRT_MAX, "too many local variables");
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   149
  while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   150
  f->locvars[fs->nlocvars].varname = varname;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   151
  luaC_objbarrier(ls->L, f, varname);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   152
  return fs->nlocvars++;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   153
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   154
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   155
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   156
#define new_localvarliteral(ls,v,n) \
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   157
  new_localvar(ls, luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char))-1), n)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   158
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   159
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   160
static void new_localvar (LexState *ls, TString *name, int n) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   161
  FuncState *fs = ls->fs;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   162
  luaY_checklimit(fs, fs->nactvar+n+1, LUAI_MAXVARS, "local variables");
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   163
  fs->actvar[fs->nactvar+n] = cast(unsigned short, registerlocalvar(ls, name));
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   164
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   165
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   166
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   167
static void adjustlocalvars (LexState *ls, int nvars) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   168
  FuncState *fs = ls->fs;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   169
  fs->nactvar = cast_byte(fs->nactvar + nvars);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   170
  for (; nvars; nvars--) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   171
    getlocvar(fs, fs->nactvar - nvars).startpc = fs->pc;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   172
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   173
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   174
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   175
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   176
static void removevars (LexState *ls, int tolevel) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   177
  FuncState *fs = ls->fs;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   178
  while (fs->nactvar > tolevel)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   179
    getlocvar(fs, --fs->nactvar).endpc = fs->pc;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   180
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   181
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   182
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   183
static int indexupvalue (FuncState *fs, TString *name, expdesc *v) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   184
  int i;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   185
  Proto *f = fs->f;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   186
  int oldsize = f->sizeupvalues;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   187
  for (i=0; i<f->nups; i++) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   188
    if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->u.s.info) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   189
      lua_assert(f->upvalues[i] == name);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   190
      return i;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   191
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   192
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   193
  /* new one */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   194
  luaY_checklimit(fs, f->nups + 1, LUAI_MAXUPVALUES, "upvalues");
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   195
  luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues,
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   196
                  TString *, MAX_INT, "");
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   197
  while (oldsize < f->sizeupvalues) f->upvalues[oldsize++] = NULL;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   198
  f->upvalues[f->nups] = name;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   199
  luaC_objbarrier(fs->L, f, name);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   200
  lua_assert(v->k == VLOCAL || v->k == VUPVAL);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   201
  fs->upvalues[f->nups].k = cast_byte(v->k);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   202
  fs->upvalues[f->nups].info = cast_byte(v->u.s.info);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   203
  return f->nups++;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   204
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   205
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   206
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   207
static int searchvar (FuncState *fs, TString *n) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   208
  int i;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   209
  for (i=fs->nactvar-1; i >= 0; i--) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   210
    if (n == getlocvar(fs, i).varname)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   211
      return i;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   212
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   213
  return -1;  /* not found */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   214
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   215
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   216
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   217
static void markupval (FuncState *fs, int level) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   218
  BlockCnt *bl = fs->bl;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   219
  while (bl && bl->nactvar > level) bl = bl->previous;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   220
  if (bl) bl->upval = 1;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   221
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   222
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   223
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   224
static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   225
  if (fs == NULL) {  /* no more levels? */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   226
    init_exp(var, VGLOBAL, NO_REG);  /* default is global variable */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   227
    return VGLOBAL;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   228
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   229
  else {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   230
    int v = searchvar(fs, n);  /* look up at current level */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   231
    if (v >= 0) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   232
      init_exp(var, VLOCAL, v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   233
      if (!base)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   234
        markupval(fs, v);  /* local will be used as an upval */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   235
      return VLOCAL;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   236
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   237
    else {  /* not found at current level; try upper one */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   238
      if (singlevaraux(fs->prev, n, var, 0) == VGLOBAL)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   239
        return VGLOBAL;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   240
      var->u.s.info = indexupvalue(fs, n, var);  /* else was LOCAL or UPVAL */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   241
      var->k = VUPVAL;  /* upvalue in this level */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   242
      return VUPVAL;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   243
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   244
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   245
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   246
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   247
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   248
static void singlevar (LexState *ls, expdesc *var) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   249
  TString *varname = str_checkname(ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   250
  FuncState *fs = ls->fs;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   251
  if (singlevaraux(fs, varname, var, 1) == VGLOBAL)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   252
    var->u.s.info = luaK_stringK(fs, varname);  /* info points to global name */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   253
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   254
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   255
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   256
static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   257
  FuncState *fs = ls->fs;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   258
  int extra = nvars - nexps;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   259
  if (hasmultret(e->k)) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   260
    extra++;  /* includes call itself */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   261
    if (extra < 0) extra = 0;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   262
    luaK_setreturns(fs, e, extra);  /* last exp. provides the difference */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   263
    if (extra > 1) luaK_reserveregs(fs, extra-1);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   264
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   265
  else {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   266
    if (e->k != VVOID) luaK_exp2nextreg(fs, e);  /* close last expression */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   267
    if (extra > 0) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   268
      int reg = fs->freereg;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   269
      luaK_reserveregs(fs, extra);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   270
      luaK_nil(fs, reg, extra);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   271
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   272
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   273
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   274
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   275
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   276
static void enterlevel (LexState *ls) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   277
  if (++ls->L->nCcalls > LUAI_MAXCCALLS)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   278
	luaX_lexerror(ls, "chunk has too many syntax levels", 0);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   279
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   280
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   281
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   282
#define leavelevel(ls)	((ls)->L->nCcalls--)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   283
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   284
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   285
static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   286
  bl->breaklist = NO_JUMP;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   287
  bl->isbreakable = isbreakable;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   288
  bl->nactvar = fs->nactvar;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   289
  bl->upval = 0;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   290
  bl->previous = fs->bl;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   291
  fs->bl = bl;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   292
  lua_assert(fs->freereg == fs->nactvar);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   293
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   294
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   295
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   296
static void leaveblock (FuncState *fs) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   297
  BlockCnt *bl = fs->bl;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   298
  fs->bl = bl->previous;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   299
  removevars(fs->ls, bl->nactvar);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   300
  if (bl->upval)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   301
    luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   302
  /* a block either controls scope or breaks (never both) */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   303
  lua_assert(!bl->isbreakable || !bl->upval);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   304
  lua_assert(bl->nactvar == fs->nactvar);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   305
  fs->freereg = fs->nactvar;  /* free registers */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   306
  luaK_patchtohere(fs, bl->breaklist);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   307
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   308
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   309
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   310
static void pushclosure (LexState *ls, FuncState *func, expdesc *v) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   311
  FuncState *fs = ls->fs;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   312
  Proto *f = fs->f;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   313
  int oldsize = f->sizep;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   314
  int i;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   315
  luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *,
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   316
                  MAXARG_Bx, "constant table overflow");
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   317
  while (oldsize < f->sizep) f->p[oldsize++] = NULL;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   318
  f->p[fs->np++] = func->f;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   319
  luaC_objbarrier(ls->L, f, func->f);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   320
  init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1));
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   321
  for (i=0; i<func->f->nups; i++) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   322
    OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   323
    luaK_codeABC(fs, o, 0, func->upvalues[i].info, 0);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   324
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   325
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   326
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   327
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   328
static void open_func (LexState *ls, FuncState *fs) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   329
  lua_State *L = ls->L;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   330
  Proto *f = luaF_newproto(L);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   331
  fs->f = f;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   332
  fs->prev = ls->fs;  /* linked list of funcstates */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   333
  fs->ls = ls;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   334
  fs->L = L;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   335
  ls->fs = fs;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   336
  fs->pc = 0;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   337
  fs->lasttarget = -1;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   338
  fs->jpc = NO_JUMP;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   339
  fs->freereg = 0;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   340
  fs->nk = 0;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   341
  fs->np = 0;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   342
  fs->nlocvars = 0;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   343
  fs->nactvar = 0;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   344
  fs->bl = NULL;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   345
  f->source = ls->source;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   346
  f->maxstacksize = 2;  /* registers 0/1 are always valid */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   347
  fs->h = luaH_new(L, 0, 0);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   348
  /* anchor table of constants and prototype (to avoid being collected) */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   349
  sethvalue2s(L, L->top, fs->h);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   350
  incr_top(L);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   351
  setptvalue2s(L, L->top, f);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   352
  incr_top(L);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   353
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   354
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   355
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   356
static void close_func (LexState *ls) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   357
  lua_State *L = ls->L;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   358
  FuncState *fs = ls->fs;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   359
  Proto *f = fs->f;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   360
  removevars(ls, 0);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   361
  luaK_ret(fs, 0, 0);  /* final return */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   362
  luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   363
  f->sizecode = fs->pc;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   364
  luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   365
  f->sizelineinfo = fs->pc;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   366
  luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   367
  f->sizek = fs->nk;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   368
  luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   369
  f->sizep = fs->np;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   370
  luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   371
  f->sizelocvars = fs->nlocvars;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   372
  luaM_reallocvector(L, f->upvalues, f->sizeupvalues, f->nups, TString *);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   373
  f->sizeupvalues = f->nups;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   374
  lua_assert(luaG_checkcode(f));
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   375
  lua_assert(fs->bl == NULL);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   376
  ls->fs = fs->prev;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   377
  L->top -= 2;  /* remove table and prototype from the stack */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   378
  /* last token read was anchored in defunct function; must reanchor it */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   379
  if (fs) anchor_token(ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   380
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   381
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   382
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   383
Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   384
  struct LexState lexstate;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   385
  struct FuncState funcstate;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   386
  lexstate.buff = buff;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   387
  luaX_setinput(L, &lexstate, z, luaS_new(L, name));
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   388
  open_func(&lexstate, &funcstate);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   389
  funcstate.f->is_vararg = VARARG_ISVARARG;  /* main func. is always vararg */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   390
  luaX_next(&lexstate);  /* read first token */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   391
  chunk(&lexstate);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   392
  check(&lexstate, TK_EOS);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   393
  close_func(&lexstate);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   394
  lua_assert(funcstate.prev == NULL);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   395
  lua_assert(funcstate.f->nups == 0);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   396
  lua_assert(lexstate.fs == NULL);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   397
  return funcstate.f;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   398
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   399
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   400
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   401
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   402
/*============================================================*/
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   403
/* GRAMMAR RULES */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   404
/*============================================================*/
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   405
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   406
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   407
static void field (LexState *ls, expdesc *v) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   408
  /* field -> ['.' | ':'] NAME */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   409
  FuncState *fs = ls->fs;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   410
  expdesc key;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   411
  luaK_exp2anyreg(fs, v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   412
  luaX_next(ls);  /* skip the dot or colon */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   413
  checkname(ls, &key);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   414
  luaK_indexed(fs, v, &key);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   415
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   416
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   417
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   418
static void yindex (LexState *ls, expdesc *v) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   419
  /* index -> '[' expr ']' */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   420
  luaX_next(ls);  /* skip the '[' */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   421
  expr(ls, v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   422
  luaK_exp2val(ls->fs, v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   423
  checknext(ls, ']');
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   424
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   425
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   426
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   427
/*
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   428
** {======================================================================
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   429
** Rules for Constructors
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   430
** =======================================================================
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   431
*/
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   432
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   433
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   434
struct ConsControl {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   435
  expdesc v;  /* last list item read */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   436
  expdesc *t;  /* table descriptor */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   437
  int nh;  /* total number of `record' elements */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   438
  int na;  /* total number of array elements */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   439
  int tostore;  /* number of array elements pending to be stored */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   440
};
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   441
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   442
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   443
static void recfield (LexState *ls, struct ConsControl *cc) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   444
  /* recfield -> (NAME | `['exp1`]') = exp1 */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   445
  FuncState *fs = ls->fs;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   446
  int reg = ls->fs->freereg;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   447
  expdesc key, val;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   448
  int rkkey;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   449
  if (ls->t.token == TK_NAME) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   450
    luaY_checklimit(fs, cc->nh, MAX_INT, "items in a constructor");
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   451
    checkname(ls, &key);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   452
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   453
  else  /* ls->t.token == '[' */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   454
    yindex(ls, &key);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   455
  cc->nh++;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   456
  checknext(ls, '=');
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   457
  rkkey = luaK_exp2RK(fs, &key);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   458
  expr(ls, &val);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   459
  luaK_codeABC(fs, OP_SETTABLE, cc->t->u.s.info, rkkey, luaK_exp2RK(fs, &val));
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   460
  fs->freereg = reg;  /* free registers */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   461
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   462
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   463
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   464
static void closelistfield (FuncState *fs, struct ConsControl *cc) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   465
  if (cc->v.k == VVOID) return;  /* there is no list item */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   466
  luaK_exp2nextreg(fs, &cc->v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   467
  cc->v.k = VVOID;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   468
  if (cc->tostore == LFIELDS_PER_FLUSH) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   469
    luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore);  /* flush */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   470
    cc->tostore = 0;  /* no more items pending */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   471
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   472
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   473
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   474
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   475
static void lastlistfield (FuncState *fs, struct ConsControl *cc) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   476
  if (cc->tostore == 0) return;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   477
  if (hasmultret(cc->v.k)) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   478
    luaK_setmultret(fs, &cc->v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   479
    luaK_setlist(fs, cc->t->u.s.info, cc->na, LUA_MULTRET);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   480
    cc->na--;  /* do not count last expression (unknown number of elements) */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   481
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   482
  else {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   483
    if (cc->v.k != VVOID)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   484
      luaK_exp2nextreg(fs, &cc->v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   485
    luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   486
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   487
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   488
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   489
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   490
static void listfield (LexState *ls, struct ConsControl *cc) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   491
  expr(ls, &cc->v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   492
  luaY_checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor");
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   493
  cc->na++;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   494
  cc->tostore++;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   495
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   496
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   497
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   498
static void constructor (LexState *ls, expdesc *t) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   499
  /* constructor -> ?? */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   500
  FuncState *fs = ls->fs;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   501
  int line = ls->linenumber;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   502
  int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   503
  struct ConsControl cc;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   504
  cc.na = cc.nh = cc.tostore = 0;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   505
  cc.t = t;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   506
  init_exp(t, VRELOCABLE, pc);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   507
  init_exp(&cc.v, VVOID, 0);  /* no value (yet) */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   508
  luaK_exp2nextreg(ls->fs, t);  /* fix it at stack top (for gc) */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   509
  checknext(ls, '{');
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   510
  do {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   511
    lua_assert(cc.v.k == VVOID || cc.tostore > 0);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   512
    if (ls->t.token == '}') break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   513
    closelistfield(fs, &cc);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   514
    switch(ls->t.token) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   515
      case TK_NAME: {  /* may be listfields or recfields */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   516
        luaX_lookahead(ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   517
        if (ls->lookahead.token != '=')  /* expression? */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   518
          listfield(ls, &cc);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   519
        else
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   520
          recfield(ls, &cc);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   521
        break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   522
      }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   523
      case '[': {  /* constructor_item -> recfield */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   524
        recfield(ls, &cc);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   525
        break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   526
      }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   527
      default: {  /* constructor_part -> listfield */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   528
        listfield(ls, &cc);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   529
        break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   530
      }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   531
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   532
  } while (testnext(ls, ',') || testnext(ls, ';'));
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   533
  check_match(ls, '}', '{', line);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   534
  lastlistfield(fs, &cc);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   535
  SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   536
  SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh));  /* set initial table size */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   537
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   538
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   539
/* }====================================================================== */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   540
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   541
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   542
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   543
static void parlist (LexState *ls) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   544
  /* parlist -> [ param { `,' param } ] */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   545
  FuncState *fs = ls->fs;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   546
  Proto *f = fs->f;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   547
  int nparams = 0;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   548
  f->is_vararg = 0;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   549
  if (ls->t.token != ')') {  /* is `parlist' not empty? */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   550
    do {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   551
      switch (ls->t.token) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   552
        case TK_NAME: {  /* param -> NAME */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   553
          new_localvar(ls, str_checkname(ls), nparams++);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   554
          break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   555
        }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   556
        case TK_DOTS: {  /* param -> `...' */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   557
          luaX_next(ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   558
#if defined(LUA_COMPAT_VARARG)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   559
          /* use `arg' as default name */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   560
          new_localvarliteral(ls, "arg", nparams++);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   561
          f->is_vararg = VARARG_HASARG | VARARG_NEEDSARG;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   562
#endif
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   563
          f->is_vararg |= VARARG_ISVARARG;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   564
          break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   565
        }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   566
        default: luaX_syntaxerror(ls, "<name> or " LUA_QL("...") " expected");
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   567
      }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   568
    } while (!f->is_vararg && testnext(ls, ','));
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   569
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   570
  adjustlocalvars(ls, nparams);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   571
  f->numparams = cast_byte(fs->nactvar - (f->is_vararg & VARARG_HASARG));
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   572
  luaK_reserveregs(fs, fs->nactvar);  /* reserve register for parameters */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   573
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   574
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   575
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   576
static void body (LexState *ls, expdesc *e, int needself, int line) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   577
  /* body ->  `(' parlist `)' chunk END */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   578
  FuncState new_fs;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   579
  open_func(ls, &new_fs);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   580
  new_fs.f->linedefined = line;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   581
  checknext(ls, '(');
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   582
  if (needself) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   583
    new_localvarliteral(ls, "self", 0);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   584
    adjustlocalvars(ls, 1);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   585
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   586
  parlist(ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   587
  checknext(ls, ')');
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   588
  chunk(ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   589
  new_fs.f->lastlinedefined = ls->linenumber;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   590
  check_match(ls, TK_END, TK_FUNCTION, line);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   591
  close_func(ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   592
  pushclosure(ls, &new_fs, e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   593
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   594
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   595
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   596
static int explist1 (LexState *ls, expdesc *v) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   597
  /* explist1 -> expr { `,' expr } */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   598
  int n = 1;  /* at least one expression */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   599
  expr(ls, v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   600
  while (testnext(ls, ',')) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   601
    luaK_exp2nextreg(ls->fs, v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   602
    expr(ls, v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   603
    n++;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   604
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   605
  return n;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   606
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   607
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   608
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   609
static void funcargs (LexState *ls, expdesc *f) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   610
  FuncState *fs = ls->fs;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   611
  expdesc args;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   612
  int base, nparams;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   613
  int line = ls->linenumber;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   614
  switch (ls->t.token) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   615
    case '(': {  /* funcargs -> `(' [ explist1 ] `)' */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   616
      if (line != ls->lastline)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   617
        luaX_syntaxerror(ls,"ambiguous syntax (function call x new statement)");
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   618
      luaX_next(ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   619
      if (ls->t.token == ')')  /* arg list is empty? */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   620
        args.k = VVOID;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   621
      else {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   622
        explist1(ls, &args);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   623
        luaK_setmultret(fs, &args);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   624
      }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   625
      check_match(ls, ')', '(', line);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   626
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   627
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   628
    case '{': {  /* funcargs -> constructor */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   629
      constructor(ls, &args);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   630
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   631
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   632
    case TK_STRING: {  /* funcargs -> STRING */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   633
      codestring(ls, &args, ls->t.seminfo.ts);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   634
      luaX_next(ls);  /* must use `seminfo' before `next' */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   635
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   636
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   637
    default: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   638
      luaX_syntaxerror(ls, "function arguments expected");
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   639
      return;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   640
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   641
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   642
  lua_assert(f->k == VNONRELOC);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   643
  base = f->u.s.info;  /* base register for call */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   644
  if (hasmultret(args.k))
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   645
    nparams = LUA_MULTRET;  /* open call */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   646
  else {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   647
    if (args.k != VVOID)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   648
      luaK_exp2nextreg(fs, &args);  /* close last argument */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   649
    nparams = fs->freereg - (base+1);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   650
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   651
  init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2));
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   652
  luaK_fixline(fs, line);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   653
  fs->freereg = base+1;  /* call remove function and arguments and leaves
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   654
                            (unless changed) one result */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   655
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   656
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   657
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   658
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   659
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   660
/*
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   661
** {======================================================================
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   662
** Expression parsing
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   663
** =======================================================================
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   664
*/
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   665
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   666
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   667
static void prefixexp (LexState *ls, expdesc *v) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   668
  /* prefixexp -> NAME | '(' expr ')' */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   669
  switch (ls->t.token) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   670
    case '(': {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   671
      int line = ls->linenumber;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   672
      luaX_next(ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   673
      expr(ls, v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   674
      check_match(ls, ')', '(', line);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   675
      luaK_dischargevars(ls->fs, v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   676
      return;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   677
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   678
    case TK_NAME: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   679
      singlevar(ls, v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   680
      return;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   681
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   682
    default: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   683
      luaX_syntaxerror(ls, "unexpected symbol");
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   684
      return;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   685
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   686
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   687
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   688
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   689
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   690
static void primaryexp (LexState *ls, expdesc *v) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   691
  /* primaryexp ->
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   692
        prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   693
  FuncState *fs = ls->fs;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   694
  prefixexp(ls, v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   695
  for (;;) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   696
    switch (ls->t.token) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   697
      case '.': {  /* field */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   698
        field(ls, v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   699
        break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   700
      }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   701
      case '[': {  /* `[' exp1 `]' */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   702
        expdesc key;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   703
        luaK_exp2anyreg(fs, v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   704
        yindex(ls, &key);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   705
        luaK_indexed(fs, v, &key);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   706
        break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   707
      }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   708
      case ':': {  /* `:' NAME funcargs */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   709
        expdesc key;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   710
        luaX_next(ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   711
        checkname(ls, &key);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   712
        luaK_self(fs, v, &key);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   713
        funcargs(ls, v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   714
        break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   715
      }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   716
      case '(': case TK_STRING: case '{': {  /* funcargs */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   717
        luaK_exp2nextreg(fs, v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   718
        funcargs(ls, v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   719
        break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   720
      }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   721
      default: return;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   722
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   723
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   724
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   725
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   726
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   727
static void simpleexp (LexState *ls, expdesc *v) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   728
  /* simpleexp -> NUMBER | STRING | NIL | true | false | ... |
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   729
                  constructor | FUNCTION body | primaryexp */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   730
  switch (ls->t.token) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   731
    case TK_NUMBER: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   732
      init_exp(v, VKNUM, 0);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   733
      v->u.nval = ls->t.seminfo.r;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   734
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   735
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   736
    case TK_STRING: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   737
      codestring(ls, v, ls->t.seminfo.ts);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   738
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   739
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   740
    case TK_NIL: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   741
      init_exp(v, VNIL, 0);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   742
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   743
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   744
    case TK_TRUE: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   745
      init_exp(v, VTRUE, 0);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   746
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   747
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   748
    case TK_FALSE: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   749
      init_exp(v, VFALSE, 0);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   750
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   751
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   752
    case TK_DOTS: {  /* vararg */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   753
      FuncState *fs = ls->fs;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   754
      check_condition(ls, fs->f->is_vararg,
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   755
                      "cannot use " LUA_QL("...") " outside a vararg function");
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   756
      fs->f->is_vararg &= ~VARARG_NEEDSARG;  /* don't need 'arg' */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   757
      init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0));
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   758
      break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   759
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   760
    case '{': {  /* constructor */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   761
      constructor(ls, v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   762
      return;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   763
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   764
    case TK_FUNCTION: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   765
      luaX_next(ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   766
      body(ls, v, 0, ls->linenumber);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   767
      return;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   768
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   769
    default: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   770
      primaryexp(ls, v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   771
      return;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   772
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   773
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   774
  luaX_next(ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   775
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   776
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   777
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   778
static UnOpr getunopr (int op) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   779
  switch (op) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   780
    case TK_NOT: return OPR_NOT;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   781
    case '-': return OPR_MINUS;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   782
    case '#': return OPR_LEN;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   783
    default: return OPR_NOUNOPR;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   784
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   785
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   786
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   787
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   788
static BinOpr getbinopr (int op) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   789
  switch (op) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   790
    case '+': return OPR_ADD;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   791
    case '-': return OPR_SUB;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   792
    case '*': return OPR_MUL;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   793
    case '/': return OPR_DIV;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   794
    case '%': return OPR_MOD;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   795
    case '^': return OPR_POW;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   796
    case TK_CONCAT: return OPR_CONCAT;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   797
    case TK_NE: return OPR_NE;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   798
    case TK_EQ: return OPR_EQ;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   799
    case '<': return OPR_LT;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   800
    case TK_LE: return OPR_LE;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   801
    case '>': return OPR_GT;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   802
    case TK_GE: return OPR_GE;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   803
    case TK_AND: return OPR_AND;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   804
    case TK_OR: return OPR_OR;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   805
    default: return OPR_NOBINOPR;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   806
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   807
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   808
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   809
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   810
static const struct {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   811
  lu_byte left;  /* left priority for each binary operator */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   812
  lu_byte right; /* right priority */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   813
} priority[] = {  /* ORDER OPR */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   814
   {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7},  /* `+' `-' `/' `%' */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   815
   {10, 9}, {5, 4},                 /* power and concat (right associative) */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   816
   {3, 3}, {3, 3},                  /* equality and inequality */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   817
   {3, 3}, {3, 3}, {3, 3}, {3, 3},  /* order */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   818
   {2, 2}, {1, 1}                   /* logical (and/or) */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   819
};
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   820
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   821
#define UNARY_PRIORITY	8  /* priority for unary operators */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   822
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   823
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   824
/*
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   825
** subexpr -> (simpleexp | unop subexpr) { binop subexpr }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   826
** where `binop' is any binary operator with a priority higher than `limit'
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   827
*/
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   828
static BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   829
  BinOpr op;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   830
  UnOpr uop;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   831
  enterlevel(ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   832
  uop = getunopr(ls->t.token);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   833
  if (uop != OPR_NOUNOPR) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   834
    luaX_next(ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   835
    subexpr(ls, v, UNARY_PRIORITY);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   836
    luaK_prefix(ls->fs, uop, v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   837
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   838
  else simpleexp(ls, v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   839
  /* expand while operators have priorities higher than `limit' */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   840
  op = getbinopr(ls->t.token);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   841
  while (op != OPR_NOBINOPR && priority[op].left > limit) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   842
    expdesc v2;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   843
    BinOpr nextop;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   844
    luaX_next(ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   845
    luaK_infix(ls->fs, op, v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   846
    /* read sub-expression with higher priority */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   847
    nextop = subexpr(ls, &v2, priority[op].right);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   848
    luaK_posfix(ls->fs, op, v, &v2);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   849
    op = nextop;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   850
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   851
  leavelevel(ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   852
  return op;  /* return first untreated operator */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   853
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   854
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   855
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   856
static void expr (LexState *ls, expdesc *v) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   857
  subexpr(ls, v, 0);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   858
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   859
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   860
/* }==================================================================== */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   861
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   862
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   863
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   864
/*
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   865
** {======================================================================
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   866
** Rules for Statements
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   867
** =======================================================================
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   868
*/
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   869
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   870
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   871
static int block_follow (int token) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   872
  switch (token) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   873
    case TK_ELSE: case TK_ELSEIF: case TK_END:
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   874
    case TK_UNTIL: case TK_EOS:
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   875
      return 1;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   876
    default: return 0;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   877
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   878
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   879
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   880
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   881
static void block (LexState *ls) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   882
  /* block -> chunk */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   883
  FuncState *fs = ls->fs;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   884
  BlockCnt bl;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   885
  enterblock(fs, &bl, 0);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   886
  chunk(ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   887
  lua_assert(bl.breaklist == NO_JUMP);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   888
  leaveblock(fs);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   889
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   890
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   891
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   892
/*
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   893
** structure to chain all variables in the left-hand side of an
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   894
** assignment
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   895
*/
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   896
struct LHS_assign {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   897
  struct LHS_assign *prev;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   898
  expdesc v;  /* variable (global, local, upvalue, or indexed) */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   899
};
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   900
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   901
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   902
/*
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   903
** check whether, in an assignment to a local variable, the local variable
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   904
** is needed in a previous assignment (to a table). If so, save original
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   905
** local value in a safe place and use this safe copy in the previous
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   906
** assignment.
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   907
*/
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   908
static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   909
  FuncState *fs = ls->fs;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   910
  int extra = fs->freereg;  /* eventual position to save local variable */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   911
  int conflict = 0;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   912
  for (; lh; lh = lh->prev) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   913
    if (lh->v.k == VINDEXED) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   914
      if (lh->v.u.s.info == v->u.s.info) {  /* conflict? */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   915
        conflict = 1;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   916
        lh->v.u.s.info = extra;  /* previous assignment will use safe copy */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   917
      }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   918
      if (lh->v.u.s.aux == v->u.s.info) {  /* conflict? */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   919
        conflict = 1;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   920
        lh->v.u.s.aux = extra;  /* previous assignment will use safe copy */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   921
      }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   922
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   923
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   924
  if (conflict) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   925
    luaK_codeABC(fs, OP_MOVE, fs->freereg, v->u.s.info, 0);  /* make copy */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   926
    luaK_reserveregs(fs, 1);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   927
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   928
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   929
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   930
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   931
static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   932
  expdesc e;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   933
  check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED,
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   934
                      "syntax error");
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   935
  if (testnext(ls, ',')) {  /* assignment -> `,' primaryexp assignment */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   936
    struct LHS_assign nv;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   937
    nv.prev = lh;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   938
    primaryexp(ls, &nv.v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   939
    if (nv.v.k == VLOCAL)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   940
      check_conflict(ls, lh, &nv.v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   941
    luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls,
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   942
                    "variables in assignment");
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   943
    assignment(ls, &nv, nvars+1);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   944
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   945
  else {  /* assignment -> `=' explist1 */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   946
    int nexps;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   947
    checknext(ls, '=');
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   948
    nexps = explist1(ls, &e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   949
    if (nexps != nvars) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   950
      adjust_assign(ls, nvars, nexps, &e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   951
      if (nexps > nvars)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   952
        ls->fs->freereg -= nexps - nvars;  /* remove extra values */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   953
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   954
    else {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   955
      luaK_setoneret(ls->fs, &e);  /* close last expression */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   956
      luaK_storevar(ls->fs, &lh->v, &e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   957
      return;  /* avoid default */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   958
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   959
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   960
  init_exp(&e, VNONRELOC, ls->fs->freereg-1);  /* default assignment */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   961
  luaK_storevar(ls->fs, &lh->v, &e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   962
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   963
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   964
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   965
static int cond (LexState *ls) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   966
  /* cond -> exp */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   967
  expdesc v;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   968
  expr(ls, &v);  /* read condition */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   969
  if (v.k == VNIL) v.k = VFALSE;  /* `falses' are all equal here */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   970
  luaK_goiftrue(ls->fs, &v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   971
  return v.f;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   972
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   973
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   974
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   975
static void breakstat (LexState *ls) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   976
  FuncState *fs = ls->fs;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   977
  BlockCnt *bl = fs->bl;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   978
  int upval = 0;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   979
  while (bl && !bl->isbreakable) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   980
    upval |= bl->upval;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   981
    bl = bl->previous;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   982
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   983
  if (!bl)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   984
    luaX_syntaxerror(ls, "no loop to break");
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   985
  if (upval)
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   986
    luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   987
  luaK_concat(fs, &bl->breaklist, luaK_jump(fs));
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   988
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   989
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   990
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   991
static void whilestat (LexState *ls, int line) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   992
  /* whilestat -> WHILE cond DO block END */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   993
  FuncState *fs = ls->fs;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   994
  int whileinit;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   995
  int condexit;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   996
  BlockCnt bl;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   997
  luaX_next(ls);  /* skip WHILE */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   998
  whileinit = luaK_getlabel(fs);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
   999
  condexit = cond(ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1000
  enterblock(fs, &bl, 1);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1001
  checknext(ls, TK_DO);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1002
  block(ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1003
  luaK_patchlist(fs, luaK_jump(fs), whileinit);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1004
  check_match(ls, TK_END, TK_WHILE, line);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1005
  leaveblock(fs);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1006
  luaK_patchtohere(fs, condexit);  /* false conditions finish the loop */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1007
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1008
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1009
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1010
static void repeatstat (LexState *ls, int line) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1011
  /* repeatstat -> REPEAT block UNTIL cond */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1012
  int condexit;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1013
  FuncState *fs = ls->fs;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1014
  int repeat_init = luaK_getlabel(fs);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1015
  BlockCnt bl1, bl2;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1016
  enterblock(fs, &bl1, 1);  /* loop block */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1017
  enterblock(fs, &bl2, 0);  /* scope block */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1018
  luaX_next(ls);  /* skip REPEAT */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1019
  chunk(ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1020
  check_match(ls, TK_UNTIL, TK_REPEAT, line);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1021
  condexit = cond(ls);  /* read condition (inside scope block) */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1022
  if (!bl2.upval) {  /* no upvalues? */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1023
    leaveblock(fs);  /* finish scope */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1024
    luaK_patchlist(ls->fs, condexit, repeat_init);  /* close the loop */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1025
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1026
  else {  /* complete semantics when there are upvalues */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1027
    breakstat(ls);  /* if condition then break */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1028
    luaK_patchtohere(ls->fs, condexit);  /* else... */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1029
    leaveblock(fs);  /* finish scope... */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1030
    luaK_patchlist(ls->fs, luaK_jump(fs), repeat_init);  /* and repeat */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1031
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1032
  leaveblock(fs);  /* finish loop */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1033
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1034
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1035
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1036
static int exp1 (LexState *ls) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1037
  expdesc e;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1038
  int k;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1039
  expr(ls, &e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1040
  k = e.k;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1041
  luaK_exp2nextreg(ls->fs, &e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1042
  return k;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1043
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1044
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1045
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1046
static void forbody (LexState *ls, int base, int line, int nvars, int isnum) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1047
  /* forbody -> DO block */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1048
  BlockCnt bl;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1049
  FuncState *fs = ls->fs;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1050
  int prep, endfor;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1051
  adjustlocalvars(ls, 3);  /* control variables */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1052
  checknext(ls, TK_DO);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1053
  prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1054
  enterblock(fs, &bl, 0);  /* scope for declared variables */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1055
  adjustlocalvars(ls, nvars);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1056
  luaK_reserveregs(fs, nvars);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1057
  block(ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1058
  leaveblock(fs);  /* end of scope for declared variables */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1059
  luaK_patchtohere(fs, prep);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1060
  endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) :
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1061
                     luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1062
  luaK_fixline(fs, line);  /* pretend that `OP_FOR' starts the loop */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1063
  luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1064
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1065
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1066
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1067
static void fornum (LexState *ls, TString *varname, int line) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1068
  /* fornum -> NAME = exp1,exp1[,exp1] forbody */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1069
  FuncState *fs = ls->fs;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1070
  int base = fs->freereg;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1071
  new_localvarliteral(ls, "(for index)", 0);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1072
  new_localvarliteral(ls, "(for limit)", 1);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1073
  new_localvarliteral(ls, "(for step)", 2);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1074
  new_localvar(ls, varname, 3);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1075
  checknext(ls, '=');
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1076
  exp1(ls);  /* initial value */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1077
  checknext(ls, ',');
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1078
  exp1(ls);  /* limit */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1079
  if (testnext(ls, ','))
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1080
    exp1(ls);  /* optional step */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1081
  else {  /* default step = 1 */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1082
    luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1));
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1083
    luaK_reserveregs(fs, 1);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1084
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1085
  forbody(ls, base, line, 1, 1);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1086
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1087
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1088
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1089
static void forlist (LexState *ls, TString *indexname) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1090
  /* forlist -> NAME {,NAME} IN explist1 forbody */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1091
  FuncState *fs = ls->fs;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1092
  expdesc e;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1093
  int nvars = 0;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1094
  int line;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1095
  int base = fs->freereg;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1096
  /* create control variables */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1097
  new_localvarliteral(ls, "(for generator)", nvars++);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1098
  new_localvarliteral(ls, "(for state)", nvars++);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1099
  new_localvarliteral(ls, "(for control)", nvars++);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1100
  /* create declared variables */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1101
  new_localvar(ls, indexname, nvars++);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1102
  while (testnext(ls, ','))
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1103
    new_localvar(ls, str_checkname(ls), nvars++);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1104
  checknext(ls, TK_IN);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1105
  line = ls->linenumber;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1106
  adjust_assign(ls, 3, explist1(ls, &e), &e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1107
  luaK_checkstack(fs, 3);  /* extra space to call generator */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1108
  forbody(ls, base, line, nvars - 3, 0);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1109
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1110
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1111
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1112
static void forstat (LexState *ls, int line) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1113
  /* forstat -> FOR (fornum | forlist) END */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1114
  FuncState *fs = ls->fs;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1115
  TString *varname;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1116
  BlockCnt bl;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1117
  enterblock(fs, &bl, 1);  /* scope for loop and control variables */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1118
  luaX_next(ls);  /* skip `for' */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1119
  varname = str_checkname(ls);  /* first variable name */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1120
  switch (ls->t.token) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1121
    case '=': fornum(ls, varname, line); break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1122
    case ',': case TK_IN: forlist(ls, varname); break;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1123
    default: luaX_syntaxerror(ls, LUA_QL("=") " or " LUA_QL("in") " expected");
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1124
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1125
  check_match(ls, TK_END, TK_FOR, line);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1126
  leaveblock(fs);  /* loop scope (`break' jumps to this point) */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1127
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1128
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1129
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1130
static int test_then_block (LexState *ls) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1131
  /* test_then_block -> [IF | ELSEIF] cond THEN block */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1132
  int condexit;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1133
  luaX_next(ls);  /* skip IF or ELSEIF */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1134
  condexit = cond(ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1135
  checknext(ls, TK_THEN);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1136
  block(ls);  /* `then' part */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1137
  return condexit;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1138
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1139
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1140
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1141
static void ifstat (LexState *ls, int line) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1142
  /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1143
  FuncState *fs = ls->fs;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1144
  int flist;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1145
  int escapelist = NO_JUMP;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1146
  flist = test_then_block(ls);  /* IF cond THEN block */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1147
  while (ls->t.token == TK_ELSEIF) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1148
    luaK_concat(fs, &escapelist, luaK_jump(fs));
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1149
    luaK_patchtohere(fs, flist);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1150
    flist = test_then_block(ls);  /* ELSEIF cond THEN block */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1151
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1152
  if (ls->t.token == TK_ELSE) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1153
    luaK_concat(fs, &escapelist, luaK_jump(fs));
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1154
    luaK_patchtohere(fs, flist);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1155
    luaX_next(ls);  /* skip ELSE (after patch, for correct line info) */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1156
    block(ls);  /* `else' part */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1157
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1158
  else
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1159
    luaK_concat(fs, &escapelist, flist);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1160
  luaK_patchtohere(fs, escapelist);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1161
  check_match(ls, TK_END, TK_IF, line);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1162
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1163
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1164
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1165
static void localfunc (LexState *ls) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1166
  expdesc v, b;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1167
  FuncState *fs = ls->fs;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1168
  new_localvar(ls, str_checkname(ls), 0);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1169
  init_exp(&v, VLOCAL, fs->freereg);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1170
  luaK_reserveregs(fs, 1);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1171
  adjustlocalvars(ls, 1);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1172
  body(ls, &b, 0, ls->linenumber);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1173
  luaK_storevar(fs, &v, &b);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1174
  /* debug information will only see the variable after this point! */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1175
  getlocvar(fs, fs->nactvar - 1).startpc = fs->pc;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1176
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1177
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1178
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1179
static void localstat (LexState *ls) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1180
  /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1181
  int nvars = 0;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1182
  int nexps;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1183
  expdesc e;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1184
  do {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1185
    new_localvar(ls, str_checkname(ls), nvars++);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1186
  } while (testnext(ls, ','));
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1187
  if (testnext(ls, '='))
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1188
    nexps = explist1(ls, &e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1189
  else {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1190
    e.k = VVOID;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1191
    nexps = 0;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1192
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1193
  adjust_assign(ls, nvars, nexps, &e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1194
  adjustlocalvars(ls, nvars);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1195
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1196
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1197
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1198
static int funcname (LexState *ls, expdesc *v) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1199
  /* funcname -> NAME {field} [`:' NAME] */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1200
  int needself = 0;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1201
  singlevar(ls, v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1202
  while (ls->t.token == '.')
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1203
    field(ls, v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1204
  if (ls->t.token == ':') {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1205
    needself = 1;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1206
    field(ls, v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1207
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1208
  return needself;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1209
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1210
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1211
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1212
static void funcstat (LexState *ls, int line) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1213
  /* funcstat -> FUNCTION funcname body */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1214
  int needself;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1215
  expdesc v, b;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1216
  luaX_next(ls);  /* skip FUNCTION */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1217
  needself = funcname(ls, &v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1218
  body(ls, &b, needself, line);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1219
  luaK_storevar(ls->fs, &v, &b);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1220
  luaK_fixline(ls->fs, line);  /* definition `happens' in the first line */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1221
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1222
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1223
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1224
static void exprstat (LexState *ls) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1225
  /* stat -> func | assignment */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1226
  FuncState *fs = ls->fs;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1227
  struct LHS_assign v;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1228
  primaryexp(ls, &v.v);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1229
  if (v.v.k == VCALL)  /* stat -> func */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1230
    SETARG_C(getcode(fs, &v.v), 1);  /* call statement uses no results */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1231
  else {  /* stat -> assignment */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1232
    v.prev = NULL;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1233
    assignment(ls, &v, 1);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1234
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1235
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1236
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1237
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1238
static void retstat (LexState *ls) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1239
  /* stat -> RETURN explist */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1240
  FuncState *fs = ls->fs;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1241
  expdesc e;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1242
  int first, nret;  /* registers with returned values */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1243
  luaX_next(ls);  /* skip RETURN */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1244
  if (block_follow(ls->t.token) || ls->t.token == ';')
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1245
    first = nret = 0;  /* return no values */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1246
  else {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1247
    nret = explist1(ls, &e);  /* optional return values */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1248
    if (hasmultret(e.k)) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1249
      luaK_setmultret(fs, &e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1250
      if (e.k == VCALL && nret == 1) {  /* tail call? */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1251
        SET_OPCODE(getcode(fs,&e), OP_TAILCALL);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1252
        lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1253
      }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1254
      first = fs->nactvar;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1255
      nret = LUA_MULTRET;  /* return all values */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1256
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1257
    else {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1258
      if (nret == 1)  /* only one single value? */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1259
        first = luaK_exp2anyreg(fs, &e);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1260
      else {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1261
        luaK_exp2nextreg(fs, &e);  /* values must go to the `stack' */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1262
        first = fs->nactvar;  /* return all `active' values */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1263
        lua_assert(nret == fs->freereg - first);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1264
      }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1265
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1266
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1267
  luaK_ret(fs, first, nret);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1268
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1269
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1270
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1271
static int statement (LexState *ls) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1272
  int line = ls->linenumber;  /* may be needed for error messages */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1273
  switch (ls->t.token) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1274
    case TK_IF: {  /* stat -> ifstat */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1275
      ifstat(ls, line);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1276
      return 0;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1277
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1278
    case TK_WHILE: {  /* stat -> whilestat */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1279
      whilestat(ls, line);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1280
      return 0;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1281
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1282
    case TK_DO: {  /* stat -> DO block END */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1283
      luaX_next(ls);  /* skip DO */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1284
      block(ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1285
      check_match(ls, TK_END, TK_DO, line);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1286
      return 0;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1287
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1288
    case TK_FOR: {  /* stat -> forstat */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1289
      forstat(ls, line);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1290
      return 0;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1291
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1292
    case TK_REPEAT: {  /* stat -> repeatstat */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1293
      repeatstat(ls, line);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1294
      return 0;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1295
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1296
    case TK_FUNCTION: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1297
      funcstat(ls, line);  /* stat -> funcstat */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1298
      return 0;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1299
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1300
    case TK_LOCAL: {  /* stat -> localstat */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1301
      luaX_next(ls);  /* skip LOCAL */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1302
      if (testnext(ls, TK_FUNCTION))  /* local function? */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1303
        localfunc(ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1304
      else
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1305
        localstat(ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1306
      return 0;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1307
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1308
    case TK_RETURN: {  /* stat -> retstat */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1309
      retstat(ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1310
      return 1;  /* must be last statement */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1311
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1312
    case TK_BREAK: {  /* stat -> breakstat */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1313
      luaX_next(ls);  /* skip BREAK */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1314
      breakstat(ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1315
      return 1;  /* must be last statement */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1316
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1317
    default: {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1318
      exprstat(ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1319
      return 0;  /* to avoid warnings */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1320
    }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1321
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1322
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1323
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1324
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1325
static void chunk (LexState *ls) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1326
  /* chunk -> { stat [`;'] } */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1327
  int islast = 0;
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1328
  enterlevel(ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1329
  while (!islast && !block_follow(ls->t.token)) {
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1330
    islast = statement(ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1331
    testnext(ls, ';');
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1332
    lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg &&
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1333
               ls->fs->freereg >= ls->fs->nactvar);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1334
    ls->fs->freereg = ls->fs->nactvar;  /* free registers */
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1335
  }
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1336
  leavelevel(ls);
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1337
}
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1338
0a24853de796 add liblua to sources for macosx
koda
parents:
diff changeset
  1339
/* }====================================================================== */