From 9863223fbf512d903a1677c861e4beb4f8feda4d Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Tue, 28 May 1996 18:07:32 -0300 Subject: first version of vararg facility (plus new function "call"). --- inout.c | 63 +++++++++++++++++++++++++--- inout.h | 3 +- lex.c | 10 ++++- lua.stx | 81 ++++++++++++++++++++++-------------- opcode.c | 140 ++++++++++++++++++++++++++++++++++++++++----------------------- opcode.h | 32 ++++----------- table.c | 3 +- 7 files changed, 217 insertions(+), 115 deletions(-) diff --git a/inout.c b/inout.c index 294d4137..9850974e 100644 --- a/inout.c +++ b/inout.c @@ -5,7 +5,7 @@ ** Also provides some predefined lua functions. */ -char *rcs_inout="$Id: inout.c,v 2.35 1996/03/19 16:50:24 roberto Exp roberto $"; +char *rcs_inout="$Id: inout.c,v 2.36 1996/03/19 22:28:37 roberto Exp roberto $"; #include @@ -93,6 +93,17 @@ void lua_closestring (void) { } + +static void check_arg (int cond, char *func) +{ + if (!cond) + { + char buff[100]; + sprintf(buff, "incorrect argument to function `%s'", func); + lua_error(buff); + } +} + /* ** Internal function: do a string @@ -230,8 +241,7 @@ void luaI_setglobal (void) { lua_Object name = lua_getparam(1); lua_Object value = lua_getparam(2); - if (!lua_isstring(name)) - lua_error("incorrect argument to function `setglobal'"); + check_arg(lua_isstring(name), "setglobal"); lua_pushobject(value); lua_storeglobal(lua_getstring(name)); lua_pushobject(value); /* return given value */ @@ -240,7 +250,50 @@ void luaI_setglobal (void) void luaI_getglobal (void) { lua_Object name = lua_getparam(1); - if (!lua_isstring(name)) - lua_error("incorrect argument to function `getglobal'"); + check_arg(lua_isstring(name), "getglobal"); lua_pushobject(lua_getglobal(lua_getstring(name))); } + +#define MAXPARAMS 256 +void luaI_call (void) +{ + lua_Object f = lua_getparam(1); + lua_Object arg = lua_getparam(2); + lua_Object temp, params[MAXPARAMS]; + int narg, i; + check_arg(lua_istable(arg), "call"); + check_arg(lua_isfunction(f), "call"); + /* narg = arg.n */ + lua_pushobject(arg); + lua_pushstring("n"); + temp = lua_getsubscript(); + narg = lua_isnumber(temp) ? lua_getnumber(temp) : MAXPARAMS+1; + /* read arg[1...n] */ + for (i=0; i=MAXPARAMS) + lua_error("argument list too long in function `call'"); + lua_pushobject(arg); + lua_pushnumber(i+1); + params[i] = lua_getsubscript(); + if (narg == MAXPARAMS+1 && lua_isnil(params[i])) + { + narg = i; + break; + } + } + /* push parameters and do the call */ + for (i=0; i @@ -280,7 +280,13 @@ int luaY_lex (void) if (current == '.') { save_and_next(); - return CONC; + if (current == '.') + { + save_and_next(); + return DOTS; /* ... */ + } + else + return CONC; /* .. */ } else if (!isdigit(current)) return '.'; /* current is a digit: goes through to number */ diff --git a/lua.stx b/lua.stx index 5df83550..5982a5a7 100644 --- a/lua.stx +++ b/lua.stx @@ -1,9 +1,10 @@ %{ -char *rcs_luastx = "$Id: lua.stx,v 3.35 1996/03/08 12:02:37 roberto Exp roberto $"; +char *rcs_luastx = "$Id: lua.stx,v 3.36 1996/03/21 16:31:32 roberto Exp roberto $"; #include #include +#include #include "luadebug.h" #include "mem.h" @@ -67,49 +68,45 @@ static void yyerror (char *s) lua_error (msg); } +static void check_space (int i) +{ + if (pc+i>maxcurr-1) /* 1 byte free to code HALT of main code */ + maxcurr = growvector(&basepc, maxcurr, Byte, codeEM, MAX_INT); +} + static void code_byte (Byte c) { - if (pc>maxcurr-2) /* 1 byte free to code HALT of main code */ - maxcurr = growvector(&basepc, maxcurr, Byte, codeEM, MAX_INT); + check_space(1); basepc[pc++] = c; } static void code_word (Word n) { - CodeWord code; - code.w = n; - code_byte(code.m.c1); - code_byte(code.m.c2); + check_space(sizeof(Word)); + memcpy(basepc+pc, &n, sizeof(Word)); + pc += sizeof(Word); } -static void code_float (float n) +static void code_float (real n) { - CodeFloat code; - code.f = n; - code_byte(code.m.c1); - code_byte(code.m.c2); - code_byte(code.m.c3); - code_byte(code.m.c4); + check_space(sizeof(real)); + memcpy(basepc+pc, &n, sizeof(real)); + pc += sizeof(real); } static void code_code (TFunc *tf) { - CodeCode code; - code.tf = tf; - code_byte(code.m.c1); - code_byte(code.m.c2); - code_byte(code.m.c3); - code_byte(code.m.c4); + check_space(sizeof(TFunc *)); + memcpy(basepc+pc, &tf, sizeof(TFunc *)); + pc += sizeof(TFunc *); } static void code_word_at (Byte *p, int n) { - CodeWord code; - if ((Word)n != n) - yyerror("block too big"); - code.w = (Word)n; - *p++ = code.m.c1; - *p++ = code.m.c2; + Word w = n; + if (w != n) + yyerror("block too big"); + memcpy(p, &w, sizeof(Word)); } static void push_field (Word name) @@ -322,6 +319,19 @@ static void adjust_mult_assign (int vars, Long exps, int temps) lua_codeadjust(temps); } +static int close_parlist (int dots) +{ + if (!dots) + lua_codeadjust(0); + else + { + code_byte(VARARGS); + code_byte(nlocalvar); + add_localvar(luaI_createfixedstring("arg")); + } + return lua_linenumber; +} + static void storesinglevar (Long v) { if (v > 0) /* global var */ @@ -426,6 +436,7 @@ void lua_parse (TFunc *tf) %token RETURN %token LOCAL %token FUNCTION +%token DOTS %token NUMBER %token STRING %token NAME @@ -440,7 +451,7 @@ void lua_parse (TFunc *tf) %type fieldlist, localdeclist, decinit %type ffieldlist, ffieldlist1, semicolonpart %type lfieldlist, lfieldlist1 -%type parlist +%type parlist, parlist1, par %type var, singlevar, funcname %type body @@ -674,13 +685,21 @@ exprlist1 : expr { if ($1 != 0) $$ = $1; else $$ = -1; } } ; -parlist : /* empty */ { lua_codeadjust(0); $$ = lua_linenumber; } - | parlist1 { lua_codeadjust(0); $$ = lua_linenumber; } +parlist : /* empty */ { $$ = close_parlist(0); } + | parlist1 { $$ = close_parlist($1); } ; -parlist1 : NAME { add_localvar($1); } - | parlist1 ',' NAME { add_localvar($3); } +parlist1 : par { $$ = $1; } + | parlist1 ',' par + { + if ($1) + lua_error("invalid parameter list"); + $$ = $3; + } ; + +par : NAME { add_localvar($1); $$ = 0; } + | DOTS { $$ = 1; } fieldlist : lfieldlist { flush_list($1/FIELDS_PER_FLUSH, $1%FIELDS_PER_FLUSH); } diff --git a/opcode.c b/opcode.c index 13d476f4..237be758 100644 --- a/opcode.c +++ b/opcode.c @@ -3,7 +3,7 @@ ** TecCGraf - PUC-Rio */ -char *rcs_opcode="$Id: opcode.c,v 3.67 1996/04/22 18:00:37 roberto Exp roberto $"; +char *rcs_opcode="$Id: opcode.c,v 3.68 1996/04/25 14:10:00 roberto Exp roberto $"; #include #include @@ -117,7 +117,7 @@ static void growstack (void) */ static char *lua_strconc (char *l, char *r) { - int nl = strlen(l); + size_t nl = strlen(l); char *buffer = luaI_buffer(nl+strlen(r)+1); strcpy(buffer, l); strcpy(buffer+nl, r); @@ -886,6 +886,40 @@ static void comparison (lua_Type tag_less, lua_Type tag_equal, } +void luaI_packarg (Object *firstelem, Object *arg) +{ + int nvararg = (firstelem != NULL) ? top-firstelem : 0; + int i; + if (nvararg < 0) nvararg = 0; + avalue(arg) = lua_createarray(nvararg+1); /* +1 for field 'n' */ + tag(arg) = LUA_T_ARRAY; + for (i=0; itag = LUA_T_FUNCTION; - top->value.tf = code.tf; + top->value.tf = f; incr_top; } break; @@ -960,9 +994,9 @@ static StkId lua_execute (Byte *pc, StkId base) case PUSHGLOBAL: { - CodeWord code; - get_word(code,pc); - getglobal(code.w); + Word w; + get_word(w,pc); + getglobal(w); } break; @@ -973,9 +1007,9 @@ static StkId lua_execute (Byte *pc, StkId base) case PUSHSELF: { Object receiver = *(top-1); - CodeWord code; - get_word(code,pc); - tag(top) = LUA_T_STRING; tsvalue(top) = lua_constant[code.w]; + Word w; + get_word(w,pc); + tag(top) = LUA_T_STRING; tsvalue(top) = lua_constant[w]; incr_top; pushsubscript(); *top = receiver; @@ -994,9 +1028,9 @@ static StkId lua_execute (Byte *pc, StkId base) case STOREGLOBAL: { - CodeWord code; - get_word(code,pc); - s_object(code.w) = *(--top); + Word w; + get_word(w,pc); + s_object(w) = *(--top); } break; @@ -1050,9 +1084,9 @@ static StkId lua_execute (Byte *pc, StkId base) Object *arr = top-n-1; while (n) { - CodeWord code; - get_word(code,pc); - tag(top) = LUA_T_STRING; tsvalue(top) = lua_constant[code.w]; + Word w; + get_word(w,pc); + tag(top) = LUA_T_STRING; tsvalue(top) = lua_constant[w]; *(lua_hashdefine (avalue(arr), top)) = *(top-1); top--; n--; @@ -1068,11 +1102,15 @@ static StkId lua_execute (Byte *pc, StkId base) adjust_top(base + *(pc++)); break; + case VARARGS: + adjust_varargs(base + *(pc++)); + break; + case CREATEARRAY: { - CodeWord size; + Word size; get_word(size,pc); - avalue(top) = lua_createarray(size.w); + avalue(top) = lua_createarray(size); tag(top) = LUA_T_ARRAY; incr_top; } @@ -1195,51 +1233,51 @@ static StkId lua_execute (Byte *pc, StkId base) case ONTJMP: { - CodeWord code; - get_word(code,pc); - if (tag(top-1) != LUA_T_NIL) pc += code.w; + Word w; + get_word(w,pc); + if (tag(top-1) != LUA_T_NIL) pc += w; } break; case ONFJMP: { - CodeWord code; - get_word(code,pc); - if (tag(top-1) == LUA_T_NIL) pc += code.w; + Word w; + get_word(w,pc); + if (tag(top-1) == LUA_T_NIL) pc += w; } break; case JMP: { - CodeWord code; - get_word(code,pc); - pc += code.w; + Word w; + get_word(w,pc); + pc += w; } break; case UPJMP: { - CodeWord code; - get_word(code,pc); - pc -= code.w; + Word w; + get_word(w,pc); + pc -= w; } break; case IFFJMP: { - CodeWord code; - get_word(code,pc); + Word w; + get_word(w,pc); top--; - if (tag(top) == LUA_T_NIL) pc += code.w; + if (tag(top) == LUA_T_NIL) pc += w; } break; case IFFUPJMP: { - CodeWord code; - get_word(code,pc); + Word w; + get_word(w,pc); top--; - if (tag(top) == LUA_T_NIL) pc -= code.w; + if (tag(top) == LUA_T_NIL) pc -= w; } break; @@ -1262,8 +1300,8 @@ static StkId lua_execute (Byte *pc, StkId base) case SETLINE: { - CodeWord code; - get_word(code,pc); + Word line; + get_word(line,pc); if ((stack+base-1)->tag != LUA_T_LINE) { /* open space for LINE value */ @@ -1271,9 +1309,9 @@ static StkId lua_execute (Byte *pc, StkId base) base++; (stack+base-1)->tag = LUA_T_LINE; } - (stack+base-1)->value.i = code.w; + (stack+base-1)->value.i = line; if (lua_linehook) - lineHook (code.w); + lineHook (line); break; } diff --git a/opcode.h b/opcode.h index 9b404a83..85ec1cb8 100644 --- a/opcode.h +++ b/opcode.h @@ -1,6 +1,6 @@ /* ** TeCGraf - PUC-Rio -** $Id: opcode.h,v 3.19 1996/03/06 13:11:23 roberto Exp $ +** $Id: opcode.h,v 3.20 1996/03/15 13:13:13 roberto Exp roberto $ */ #ifndef opcode_h @@ -65,7 +65,8 @@ typedef enum CALLFUNC, RETCODE0, RETCODE, - SETLINE + SETLINE, + VARARGS } OpCode; #define MULT_RET 255 @@ -107,28 +108,10 @@ typedef struct Object #define s_fvalue(i) (fvalue(&s_object(i))) #define s_uvalue(i) (uvalue(&s_object(i))) -typedef union -{ - struct {Byte c1; Byte c2;} m; - Word w; -} CodeWord; -#define get_word(code,pc) {code.m.c1 = *pc++; code.m.c2 = *pc++;} - -typedef union -{ - struct {Byte c1; Byte c2; Byte c3; Byte c4;} m; - float f; -} CodeFloat; -#define get_float(code,pc) {code.m.c1 = *pc++; code.m.c2 = *pc++;\ - code.m.c3 = *pc++; code.m.c4 = *pc++;} - -typedef union -{ - struct {Byte c1; Byte c2; Byte c3; Byte c4;} m; - TFunc *tf; -} CodeCode; -#define get_code(code,pc) {code.m.c1 = *pc++; code.m.c2 = *pc++;\ - code.m.c3 = *pc++; code.m.c4 = *pc++;} +#define get_word(code,pc) {memcpy(&code, pc, sizeof(Word)); pc+=sizeof(Word);} +#define get_float(code,pc){memcpy(&code, pc, sizeof(real)); pc+=sizeof(real);} +#define get_code(code,pc) {memcpy(&code, pc, sizeof(TFunc *)); \ + pc+=sizeof(TFunc *);} /* Exported functions */ @@ -139,5 +122,6 @@ Object *luaI_Address (lua_Object o); void luaI_pushobject (Object *o); void luaI_gcFB (Object *o); int luaI_dorun (TFunc *tf); +void luaI_packarg (Object *firstelem, Object *arg); #endif diff --git a/table.c b/table.c index 56f7fb82..c16924cc 100644 --- a/table.c +++ b/table.c @@ -3,7 +3,7 @@ ** Module to control static tables */ -char *rcs_table="$Id: table.c,v 2.53 1996/04/29 18:53:53 roberto Exp roberto $"; +char *rcs_table="$Id: table.c,v 2.54 1996/05/06 14:29:35 roberto Exp roberto $"; #include "mem.h" #include "opcode.h" @@ -39,6 +39,7 @@ static struct { lua_CFunction func; } int_funcs[] = { {"assert", luaI_assert}, + {"call", luaI_call}, {"dofile", lua_internaldofile}, {"dostring", lua_internaldostring}, {"error", luaI_error}, -- cgit v1.2.3-55-g6feb