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.
*/
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>
@ -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<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_setglobal (void);
void luaI_getglobal (void);
void luaI_call (void);
#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>
@ -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 */

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 <stdlib.h>
#include <string.h>
#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 <vFloat> NUMBER
%token <vWord> STRING
%token <pTStr> NAME
@ -440,7 +451,7 @@ void lua_parse (TFunc *tf)
%type <vInt> fieldlist, localdeclist, decinit
%type <vInt> ffieldlist, ffieldlist1, semicolonpart
%type <vInt> lfieldlist, lfieldlist1
%type <vInt> parlist
%type <vInt> parlist, parlist1, par
%type <vLong> var, singlevar, funcname
%type <pFunc> 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); }

140
opcode.c
View File

@ -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 <setjmp.h>
#include <stdio.h>
@ -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; 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
@ -914,38 +948,38 @@ static StkId lua_execute (Byte *pc, StkId base)
case PUSHWORD:
{
CodeWord code;
get_word(code,pc);
tag(top) = LUA_T_NUMBER; nvalue(top) = code.w;
Word w;
get_word(w,pc);
tag(top) = LUA_T_NUMBER; nvalue(top) = w;
incr_top;
}
break;
case PUSHFLOAT:
{
CodeFloat code;
get_float(code,pc);
tag(top) = LUA_T_NUMBER; nvalue(top) = code.f;
real num;
get_float(num,pc);
tag(top) = LUA_T_NUMBER; nvalue(top) = num;
incr_top;
}
break;
case PUSHSTRING:
{
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;
}
break;
case PUSHFUNCTION:
{
CodeCode code;
get_code(code,pc);
luaI_insertfunction(code.tf); /* may take part in GC */
TFunc *f;
get_code(f,pc);
luaI_insertfunction(f); /* may take part in GC */
top->tag = 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;
}

View File

@ -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

View File

@ -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},