1
0
mirror of https://github.com/lua/lua.git synced 2025-01-14 05:43:00 +08:00

first version of vararg facility (plus new function "call").

This commit is contained in:
Roberto Ierusalimschy 1996-05-28 18:07:32 -03:00
parent 9a1948e67d
commit 9863223fbf
7 changed files with 217 additions and 115 deletions

63
inout.c
View File

@ -5,7 +5,7 @@
** Also provides some predefined lua functions. ** 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 <stdio.h> #include <stdio.h>
@ -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 ** Internal function: do a string
@ -230,8 +241,7 @@ void luaI_setglobal (void)
{ {
lua_Object name = lua_getparam(1); lua_Object name = lua_getparam(1);
lua_Object value = lua_getparam(2); lua_Object value = lua_getparam(2);
if (!lua_isstring(name)) check_arg(lua_isstring(name), "setglobal");
lua_error("incorrect argument to function `setglobal'");
lua_pushobject(value); lua_pushobject(value);
lua_storeglobal(lua_getstring(name)); lua_storeglobal(lua_getstring(name));
lua_pushobject(value); /* return given value */ lua_pushobject(value); /* return given value */
@ -240,7 +250,50 @@ void luaI_setglobal (void)
void luaI_getglobal (void) void luaI_getglobal (void)
{ {
lua_Object name = lua_getparam(1); lua_Object name = lua_getparam(1);
if (!lua_isstring(name)) check_arg(lua_isstring(name), "getglobal");
lua_error("incorrect argument to function `getglobal'");
lua_pushobject(lua_getglobal(lua_getstring(name))); 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<narg; i++)
{
if (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<narg; i++)
lua_pushobject(params[i]);
if (lua_callfunction(f))
{ /* error */
lua_error(NULL);
}
else
{ /* push results */
Object r;
arg = lua_getresult(1);
luaI_packarg((arg == LUA_NOOBJECT)?NULL:luaI_Address(arg), &r);
luaI_pushobject(&r);
}
}

View File

@ -1,5 +1,5 @@
/* /*
** $Id: inout.h,v 1.14 1996/03/15 13:13:13 roberto Exp roberto $ ** $Id: inout.h,v 1.15 1996/03/15 18:21:58 roberto Exp roberto $
*/ */
@ -29,5 +29,6 @@ void luaI_error (void);
void luaI_assert (void); void luaI_assert (void);
void luaI_setglobal (void); void luaI_setglobal (void);
void luaI_getglobal (void); void luaI_getglobal (void);
void luaI_call (void);
#endif #endif

10
lex.c
View File

@ -1,4 +1,4 @@
char *rcs_lex = "$Id: lex.c,v 2.31 1996/03/19 16:50:24 roberto Exp roberto $"; char *rcs_lex = "$Id: lex.c,v 2.32 1996/03/21 16:33:47 roberto Exp roberto $";
#include <ctype.h> #include <ctype.h>
@ -280,7 +280,13 @@ int luaY_lex (void)
if (current == '.') if (current == '.')
{ {
save_and_next(); save_and_next();
return CONC; if (current == '.')
{
save_and_next();
return DOTS; /* ... */
}
else
return CONC; /* .. */
} }
else if (!isdigit(current)) return '.'; else if (!isdigit(current)) return '.';
/* current is a digit: goes through to number */ /* current is a digit: goes through to number */

81
lua.stx
View File

@ -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 <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include "luadebug.h" #include "luadebug.h"
#include "mem.h" #include "mem.h"
@ -67,49 +68,45 @@ static void yyerror (char *s)
lua_error (msg); 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) static void code_byte (Byte c)
{ {
if (pc>maxcurr-2) /* 1 byte free to code HALT of main code */ check_space(1);
maxcurr = growvector(&basepc, maxcurr, Byte, codeEM, MAX_INT);
basepc[pc++] = c; basepc[pc++] = c;
} }
static void code_word (Word n) static void code_word (Word n)
{ {
CodeWord code; check_space(sizeof(Word));
code.w = n; memcpy(basepc+pc, &n, sizeof(Word));
code_byte(code.m.c1); pc += sizeof(Word);
code_byte(code.m.c2);
} }
static void code_float (float n) static void code_float (real n)
{ {
CodeFloat code; check_space(sizeof(real));
code.f = n; memcpy(basepc+pc, &n, sizeof(real));
code_byte(code.m.c1); pc += sizeof(real);
code_byte(code.m.c2);
code_byte(code.m.c3);
code_byte(code.m.c4);
} }
static void code_code (TFunc *tf) static void code_code (TFunc *tf)
{ {
CodeCode code; check_space(sizeof(TFunc *));
code.tf = tf; memcpy(basepc+pc, &tf, sizeof(TFunc *));
code_byte(code.m.c1); pc += sizeof(TFunc *);
code_byte(code.m.c2);
code_byte(code.m.c3);
code_byte(code.m.c4);
} }
static void code_word_at (Byte *p, int n) static void code_word_at (Byte *p, int n)
{ {
CodeWord code; Word w = n;
if ((Word)n != n) if (w != n)
yyerror("block too big"); yyerror("block too big");
code.w = (Word)n; memcpy(p, &w, sizeof(Word));
*p++ = code.m.c1;
*p++ = code.m.c2;
} }
static void push_field (Word name) static void push_field (Word name)
@ -322,6 +319,19 @@ static void adjust_mult_assign (int vars, Long exps, int temps)
lua_codeadjust(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) static void storesinglevar (Long v)
{ {
if (v > 0) /* global var */ if (v > 0) /* global var */
@ -426,6 +436,7 @@ void lua_parse (TFunc *tf)
%token RETURN %token RETURN
%token LOCAL %token LOCAL
%token FUNCTION %token FUNCTION
%token DOTS
%token <vFloat> NUMBER %token <vFloat> NUMBER
%token <vWord> STRING %token <vWord> STRING
%token <pTStr> NAME %token <pTStr> NAME
@ -440,7 +451,7 @@ void lua_parse (TFunc *tf)
%type <vInt> fieldlist, localdeclist, decinit %type <vInt> fieldlist, localdeclist, decinit
%type <vInt> ffieldlist, ffieldlist1, semicolonpart %type <vInt> ffieldlist, ffieldlist1, semicolonpart
%type <vInt> lfieldlist, lfieldlist1 %type <vInt> lfieldlist, lfieldlist1
%type <vInt> parlist %type <vInt> parlist, parlist1, par
%type <vLong> var, singlevar, funcname %type <vLong> var, singlevar, funcname
%type <pFunc> body %type <pFunc> body
@ -674,13 +685,21 @@ exprlist1 : expr { if ($1 != 0) $$ = $1; else $$ = -1; }
} }
; ;
parlist : /* empty */ { lua_codeadjust(0); $$ = lua_linenumber; } parlist : /* empty */ { $$ = close_parlist(0); }
| parlist1 { lua_codeadjust(0); $$ = lua_linenumber; } | parlist1 { $$ = close_parlist($1); }
; ;
parlist1 : NAME { add_localvar($1); } parlist1 : par { $$ = $1; }
| parlist1 ',' NAME { add_localvar($3); } | parlist1 ',' par
{
if ($1)
lua_error("invalid parameter list");
$$ = $3;
}
; ;
par : NAME { add_localvar($1); $$ = 0; }
| DOTS { $$ = 1; }
fieldlist : lfieldlist fieldlist : lfieldlist
{ flush_list($1/FIELDS_PER_FLUSH, $1%FIELDS_PER_FLUSH); } { flush_list($1/FIELDS_PER_FLUSH, $1%FIELDS_PER_FLUSH); }

140
opcode.c
View File

@ -3,7 +3,7 @@
** TecCGraf - PUC-Rio ** 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 <setjmp.h> #include <setjmp.h>
#include <stdio.h> #include <stdio.h>
@ -117,7 +117,7 @@ static void growstack (void)
*/ */
static char *lua_strconc (char *l, char *r) 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); char *buffer = luaI_buffer(nl+strlen(r)+1);
strcpy(buffer, l); strcpy(buffer, l);
strcpy(buffer+nl, r); 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; i<nvararg; i++)
{
Object index;
tag(&index) = LUA_T_NUMBER;
nvalue(&index) = i+1;
*(lua_hashdefine(avalue(arg), &index)) = *(firstelem+i);
}
/* store counter in field "n" */
{
Object index, extra;
tag(&index) = LUA_T_STRING;
tsvalue(&index) = lua_createstring("n");
tag(&extra) = LUA_T_NUMBER;
nvalue(&extra) = nvararg;
*(lua_hashdefine(avalue(arg), &index)) = extra;
}
}
static void adjust_varargs (StkId first_extra_arg)
{
Object arg;
luaI_packarg(stack+first_extra_arg, &arg);
adjust_top(first_extra_arg);
*top = arg; incr_top;
}
/* /*
** Execute the given opcode, until a RET. Parameters are between ** Execute the given opcode, until a RET. Parameters are between
@ -914,38 +948,38 @@ static StkId lua_execute (Byte *pc, StkId base)
case PUSHWORD: case PUSHWORD:
{ {
CodeWord code; Word w;
get_word(code,pc); get_word(w,pc);
tag(top) = LUA_T_NUMBER; nvalue(top) = code.w; tag(top) = LUA_T_NUMBER; nvalue(top) = w;
incr_top; incr_top;
} }
break; break;
case PUSHFLOAT: case PUSHFLOAT:
{ {
CodeFloat code; real num;
get_float(code,pc); get_float(num,pc);
tag(top) = LUA_T_NUMBER; nvalue(top) = code.f; tag(top) = LUA_T_NUMBER; nvalue(top) = num;
incr_top; incr_top;
} }
break; break;
case PUSHSTRING: case PUSHSTRING:
{ {
CodeWord code; Word w;
get_word(code,pc); get_word(w,pc);
tag(top) = LUA_T_STRING; tsvalue(top) = lua_constant[code.w]; tag(top) = LUA_T_STRING; tsvalue(top) = lua_constant[w];
incr_top; incr_top;
} }
break; break;
case PUSHFUNCTION: case PUSHFUNCTION:
{ {
CodeCode code; TFunc *f;
get_code(code,pc); get_code(f,pc);
luaI_insertfunction(code.tf); /* may take part in GC */ luaI_insertfunction(f); /* may take part in GC */
top->tag = LUA_T_FUNCTION; top->tag = LUA_T_FUNCTION;
top->value.tf = code.tf; top->value.tf = f;
incr_top; incr_top;
} }
break; break;
@ -960,9 +994,9 @@ static StkId lua_execute (Byte *pc, StkId base)
case PUSHGLOBAL: case PUSHGLOBAL:
{ {
CodeWord code; Word w;
get_word(code,pc); get_word(w,pc);
getglobal(code.w); getglobal(w);
} }
break; break;
@ -973,9 +1007,9 @@ static StkId lua_execute (Byte *pc, StkId base)
case PUSHSELF: case PUSHSELF:
{ {
Object receiver = *(top-1); Object receiver = *(top-1);
CodeWord code; Word w;
get_word(code,pc); get_word(w,pc);
tag(top) = LUA_T_STRING; tsvalue(top) = lua_constant[code.w]; tag(top) = LUA_T_STRING; tsvalue(top) = lua_constant[w];
incr_top; incr_top;
pushsubscript(); pushsubscript();
*top = receiver; *top = receiver;
@ -994,9 +1028,9 @@ static StkId lua_execute (Byte *pc, StkId base)
case STOREGLOBAL: case STOREGLOBAL:
{ {
CodeWord code; Word w;
get_word(code,pc); get_word(w,pc);
s_object(code.w) = *(--top); s_object(w) = *(--top);
} }
break; break;
@ -1050,9 +1084,9 @@ static StkId lua_execute (Byte *pc, StkId base)
Object *arr = top-n-1; Object *arr = top-n-1;
while (n) while (n)
{ {
CodeWord code; Word w;
get_word(code,pc); get_word(w,pc);
tag(top) = LUA_T_STRING; tsvalue(top) = lua_constant[code.w]; tag(top) = LUA_T_STRING; tsvalue(top) = lua_constant[w];
*(lua_hashdefine (avalue(arr), top)) = *(top-1); *(lua_hashdefine (avalue(arr), top)) = *(top-1);
top--; top--;
n--; n--;
@ -1068,11 +1102,15 @@ static StkId lua_execute (Byte *pc, StkId base)
adjust_top(base + *(pc++)); adjust_top(base + *(pc++));
break; break;
case VARARGS:
adjust_varargs(base + *(pc++));
break;
case CREATEARRAY: case CREATEARRAY:
{ {
CodeWord size; Word size;
get_word(size,pc); get_word(size,pc);
avalue(top) = lua_createarray(size.w); avalue(top) = lua_createarray(size);
tag(top) = LUA_T_ARRAY; tag(top) = LUA_T_ARRAY;
incr_top; incr_top;
} }
@ -1195,51 +1233,51 @@ static StkId lua_execute (Byte *pc, StkId base)
case ONTJMP: case ONTJMP:
{ {
CodeWord code; Word w;
get_word(code,pc); get_word(w,pc);
if (tag(top-1) != LUA_T_NIL) pc += code.w; if (tag(top-1) != LUA_T_NIL) pc += w;
} }
break; break;
case ONFJMP: case ONFJMP:
{ {
CodeWord code; Word w;
get_word(code,pc); get_word(w,pc);
if (tag(top-1) == LUA_T_NIL) pc += code.w; if (tag(top-1) == LUA_T_NIL) pc += w;
} }
break; break;
case JMP: case JMP:
{ {
CodeWord code; Word w;
get_word(code,pc); get_word(w,pc);
pc += code.w; pc += w;
} }
break; break;
case UPJMP: case UPJMP:
{ {
CodeWord code; Word w;
get_word(code,pc); get_word(w,pc);
pc -= code.w; pc -= w;
} }
break; break;
case IFFJMP: case IFFJMP:
{ {
CodeWord code; Word w;
get_word(code,pc); get_word(w,pc);
top--; top--;
if (tag(top) == LUA_T_NIL) pc += code.w; if (tag(top) == LUA_T_NIL) pc += w;
} }
break; break;
case IFFUPJMP: case IFFUPJMP:
{ {
CodeWord code; Word w;
get_word(code,pc); get_word(w,pc);
top--; top--;
if (tag(top) == LUA_T_NIL) pc -= code.w; if (tag(top) == LUA_T_NIL) pc -= w;
} }
break; break;
@ -1262,8 +1300,8 @@ static StkId lua_execute (Byte *pc, StkId base)
case SETLINE: case SETLINE:
{ {
CodeWord code; Word line;
get_word(code,pc); get_word(line,pc);
if ((stack+base-1)->tag != LUA_T_LINE) if ((stack+base-1)->tag != LUA_T_LINE)
{ {
/* open space for LINE value */ /* open space for LINE value */
@ -1271,9 +1309,9 @@ static StkId lua_execute (Byte *pc, StkId base)
base++; base++;
(stack+base-1)->tag = LUA_T_LINE; (stack+base-1)->tag = LUA_T_LINE;
} }
(stack+base-1)->value.i = code.w; (stack+base-1)->value.i = line;
if (lua_linehook) if (lua_linehook)
lineHook (code.w); lineHook (line);
break; break;
} }

View File

@ -1,6 +1,6 @@
/* /*
** TeCGraf - PUC-Rio ** 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 #ifndef opcode_h
@ -65,7 +65,8 @@ typedef enum
CALLFUNC, CALLFUNC,
RETCODE0, RETCODE0,
RETCODE, RETCODE,
SETLINE SETLINE,
VARARGS
} OpCode; } OpCode;
#define MULT_RET 255 #define MULT_RET 255
@ -107,28 +108,10 @@ typedef struct Object
#define s_fvalue(i) (fvalue(&s_object(i))) #define s_fvalue(i) (fvalue(&s_object(i)))
#define s_uvalue(i) (uvalue(&s_object(i))) #define s_uvalue(i) (uvalue(&s_object(i)))
typedef union #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);}
struct {Byte c1; Byte c2;} m; #define get_code(code,pc) {memcpy(&code, pc, sizeof(TFunc *)); \
Word w; pc+=sizeof(TFunc *);}
} 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++;}
/* Exported functions */ /* Exported functions */
@ -139,5 +122,6 @@ Object *luaI_Address (lua_Object o);
void luaI_pushobject (Object *o); void luaI_pushobject (Object *o);
void luaI_gcFB (Object *o); void luaI_gcFB (Object *o);
int luaI_dorun (TFunc *tf); int luaI_dorun (TFunc *tf);
void luaI_packarg (Object *firstelem, Object *arg);
#endif #endif

View File

@ -3,7 +3,7 @@
** Module to control static tables ** 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 "mem.h"
#include "opcode.h" #include "opcode.h"
@ -39,6 +39,7 @@ static struct {
lua_CFunction func; lua_CFunction func;
} int_funcs[] = { } int_funcs[] = {
{"assert", luaI_assert}, {"assert", luaI_assert},
{"call", luaI_call},
{"dofile", lua_internaldofile}, {"dofile", lua_internaldofile},
{"dostring", lua_internaldostring}, {"dostring", lua_internaldostring},
{"error", luaI_error}, {"error", luaI_error},