back to upavalues as extra arguments for C closures; this way it's

trivial to make currying.
This commit is contained in:
Roberto Ierusalimschy 1998-01-07 14:26:48 -02:00
parent e04c2b9aa8
commit 26679b1a48
6 changed files with 45 additions and 41 deletions

11
lapi.c
View File

@ -1,5 +1,5 @@
/* /*
** $Id: lapi.c,v 1.16 1997/12/22 17:52:20 roberto Exp roberto $ ** $Id: lapi.c,v 1.17 1998/01/02 17:46:32 roberto Exp roberto $
** Lua API ** Lua API
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -124,15 +124,6 @@ lua_Object lua_lua2C (int number)
} }
lua_Object lua_upvalue (int n)
{
TObject *f = L->stack.stack+L->Cstack.lua2C-1;
if (ttype(f) != LUA_T_CLMARK || n <= 0 || n > clvalue(f)->nelems)
return LUA_NOOBJECT;
return put_luaObject(&clvalue(f)->consts[n]);
}
int lua_callfunction (lua_Object function) int lua_callfunction (lua_Object function)
{ {
if (function == LUA_NOOBJECT) if (function == LUA_NOOBJECT)

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lbuiltin.c,v 1.20 1997/12/30 17:57:45 roberto Exp roberto $ ** $Id: lbuiltin.c,v 1.21 1998/01/02 17:46:32 roberto Exp roberto $
** Built-in functions ** Built-in functions
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -441,7 +441,6 @@ static void testC (void)
case 'r': { int n=getnum(s); reg[n]=lua_getref(locks[getnum(s)]); break; } case 'r': { int n=getnum(s); reg[n]=lua_getref(locks[getnum(s)]); break; }
case 'u': lua_unref(locks[getnum(s)]); break; case 'u': lua_unref(locks[getnum(s)]); break;
case 'p': { int n = getnum(s); reg[n] = lua_getparam(getnum(s)); break; } case 'p': { int n = getnum(s); reg[n] = lua_getparam(getnum(s)); break; }
case 'U': { int n = getnum(s); reg[n] = lua_upvalue(getnum(s)); break; }
case '=': lua_setglobal(getname(s)); break; case '=': lua_setglobal(getname(s)); break;
case 's': lua_pushstring(getname(s)); break; case 's': lua_pushstring(getname(s)); break;
case 'o': lua_pushobject(reg[getnum(s)]); break; case 'o': lua_pushobject(reg[getnum(s)]); break;

19
ldo.c
View File

@ -1,5 +1,5 @@
/* /*
** $Id: ldo.c,v 1.19 1997/12/23 12:50:49 roberto Exp roberto $ ** $Id: ldo.c,v 1.20 1997/12/26 18:38:16 roberto Exp roberto $
** Stack and Call structure of Lua ** Stack and Call structure of Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -157,6 +157,21 @@ static StkId callC (lua_CFunction f, StkId base)
} }
static StkId callCclosure (struct Closure *cl, lua_CFunction f, StkId base)
{
TObject *pbase;
int nup = cl->nelems; /* number of upvalues */
luaD_checkstack(nup);
pbase = L->stack.stack+base; /* care: previous call may change this */
/* open space for upvalues as extra arguments */
luaO_memup(pbase+nup, pbase, (L->stack.top-pbase)*sizeof(TObject));
/* copy upvalues into stack */
memcpy(pbase, cl->consts+1, nup*sizeof(TObject));
L->stack.top += nup;
return callC(f, base);
}
void luaD_callTM (TObject *f, int nParams, int nResults) void luaD_callTM (TObject *f, int nParams, int nResults)
{ {
luaD_openstack(nParams); luaD_openstack(nParams);
@ -190,7 +205,7 @@ void luaD_call (StkId base, int nResults)
TObject *proto = &(c->consts[0]); TObject *proto = &(c->consts[0]);
ttype(func) = LUA_T_CLMARK; ttype(func) = LUA_T_CLMARK;
firstResult = (ttype(proto) == LUA_T_CPROTO) ? firstResult = (ttype(proto) == LUA_T_CPROTO) ?
callC(fvalue(proto), base) : callCclosure(c, fvalue(proto), base) :
luaV_execute(c, tfvalue(proto), base); luaV_execute(c, tfvalue(proto), base);
break; break;
} }

View File

@ -1,5 +1,5 @@
/* /*
** $Id: liolib.c,v 1.12 1997/12/18 19:11:43 roberto Exp roberto $ ** $Id: liolib.c,v 1.13 1997/12/26 18:38:16 roberto Exp roberto $
** Standard I/O (and system) library ** Standard I/O (and system) library
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -34,6 +34,8 @@
#define CLOSEDTAG 2 #define CLOSEDTAG 2
#define IOTAG 1 #define IOTAG 1
#define FIRSTARG 3 /* 1st and 2nd are upvalues */
#define FINPUT "_INPUT" #define FINPUT "_INPUT"
#define FOUTPUT "_OUTPUT" #define FOUTPUT "_OUTPUT"
@ -49,7 +51,7 @@ int pclose();
static int gettag (int i) static int gettag (int i)
{ {
return lua_getnumber(lua_upvalue(i)); return lua_getnumber(lua_getparam(i));
} }
@ -124,7 +126,7 @@ static void setreturn (FILE *f, char *name)
static void io_readfrom (void) static void io_readfrom (void)
{ {
FILE *current; FILE *current;
lua_Object f = lua_getparam(1); lua_Object f = lua_getparam(FIRSTARG);
if (f == LUA_NOOBJECT) { if (f == LUA_NOOBJECT) {
closefile(FINPUT); closefile(FINPUT);
current = stdin; current = stdin;
@ -132,7 +134,7 @@ static void io_readfrom (void)
else if (lua_tag(f) == gettag(IOTAG)) else if (lua_tag(f) == gettag(IOTAG))
current = lua_getuserdata(f); current = lua_getuserdata(f);
else { else {
char *s = luaL_check_string(1); char *s = luaL_check_string(FIRSTARG);
current = (*s == '|') ? popen(s+1, "r") : fopen(s, "r"); current = (*s == '|') ? popen(s+1, "r") : fopen(s, "r");
if (current == NULL) { if (current == NULL) {
pushresult(0); pushresult(0);
@ -146,7 +148,7 @@ static void io_readfrom (void)
static void io_writeto (void) static void io_writeto (void)
{ {
FILE *current; FILE *current;
lua_Object f = lua_getparam(1); lua_Object f = lua_getparam(FIRSTARG);
if (f == LUA_NOOBJECT) { if (f == LUA_NOOBJECT) {
closefile(FOUTPUT); closefile(FOUTPUT);
current = stdout; current = stdout;
@ -154,7 +156,7 @@ static void io_writeto (void)
else if (lua_tag(f) == gettag(IOTAG)) else if (lua_tag(f) == gettag(IOTAG))
current = lua_getuserdata(f); current = lua_getuserdata(f);
else { else {
char *s = luaL_check_string(1); char *s = luaL_check_string(FIRSTARG);
current = (*s == '|') ? popen(s+1,"w") : fopen(s,"w"); current = (*s == '|') ? popen(s+1,"w") : fopen(s,"w");
if (current == NULL) { if (current == NULL) {
pushresult(0); pushresult(0);
@ -167,7 +169,7 @@ static void io_writeto (void)
static void io_appendto (void) static void io_appendto (void)
{ {
char *s = luaL_check_string(1); char *s = luaL_check_string(FIRSTARG);
FILE *fp = fopen (s, "a"); FILE *fp = fopen (s, "a");
if (fp != NULL) if (fp != NULL)
setreturn(fp, FOUTPUT); setreturn(fp, FOUTPUT);
@ -180,7 +182,7 @@ static void io_appendto (void)
static void io_read (void) static void io_read (void)
{ {
int arg = 1; int arg = FIRSTARG;
FILE *f = getfileparam(FINPUT, &arg); FILE *f = getfileparam(FINPUT, &arg);
char *buff; char *buff;
char *p = luaL_opt_string(arg, "[^\n]*{\n}"); char *p = luaL_opt_string(arg, "[^\n]*{\n}");
@ -232,7 +234,7 @@ static void io_read (void)
static void io_write (void) static void io_write (void)
{ {
int arg = 1; int arg = FIRSTARG;
FILE *f = getfileparam(FOUTPUT, &arg); FILE *f = getfileparam(FOUTPUT, &arg);
int status = 1; int status = 1;
char *s; char *s;

3
lua.h
View File

@ -1,5 +1,5 @@
/* /*
** $Id: lua.h,v 1.12 1997/12/18 18:32:39 roberto Exp roberto $ ** $Id: lua.h,v 1.13 1998/01/02 17:46:32 roberto Exp roberto $
** Lua - An Extensible Extension Language ** Lua - An Extensible Extension Language
** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil ** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil
** e-mail: lua@tecgraf.puc-rio.br ** e-mail: lua@tecgraf.puc-rio.br
@ -77,7 +77,6 @@ void lua_beginblock (void);
void lua_endblock (void); void lua_endblock (void);
lua_Object lua_lua2C (int number); lua_Object lua_lua2C (int number);
lua_Object lua_upvalue (int n);
#define lua_getparam(_) lua_lua2C(_) #define lua_getparam(_) lua_lua2C(_)
#define lua_getresult(_) lua_lua2C(_) #define lua_getresult(_) lua_lua2C(_)

View File

@ -1,4 +1,4 @@
% $Id: manual.tex,v 1.1 1998/01/02 18:34:00 roberto Exp roberto $ % $Id: manual.tex,v 1.2 1998/01/06 19:17:31 roberto Exp roberto $
\documentstyle[fullpage,11pt,bnf]{article} \documentstyle[fullpage,11pt,bnf]{article}
@ -38,7 +38,7 @@ Waldemar Celes
\tecgraf\ --- Computer Science Department --- PUC-Rio \tecgraf\ --- Computer Science Department --- PUC-Rio
} }
\date{\small \verb$Date: 1998/01/02 18:34:00 $} \date{\small \verb$Date: 1998/01/06 19:17:31 $}
\maketitle \maketitle
@ -1647,7 +1647,8 @@ many results.
When a C function is created, When a C function is created,
it is possible to associate some \emph{upvalues} to it; it is possible to associate some \emph{upvalues} to it;
then these values can be accessed by the function whenever it is called. then these values are passed to the function whenever it is called,
as common arguments.
To associate upvalues to a function, To associate upvalues to a function,
first these values must be pushed on C2lua. first these values must be pushed on C2lua.
Then the function: Then the function:
@ -1660,14 +1661,11 @@ with the argument \verb|n| telling how many upvalues must be
associated with the function associated with the function
(notice that the macro \verb|lua_pushcfunction| is defined as (notice that the macro \verb|lua_pushcfunction| is defined as
\verb|lua_pushCclosure| with \verb|n| set to 0). \verb|lua_pushCclosure| with \verb|n| set to 0).
Any time the function \verb|fn| is called, Then, any time the function is called,
it can access those upvalues using: these upvalues are inserted as the first arguments to the function,
\Deffunc{lua_upvalue} before the actual arguments provided in the call.
\begin{verbatim}
lua_Object lua_upvalue (int n);
\end{verbatim}
For some examples, see files \verb|lstrlib.c|, For some examples of C functions, see files \verb|lstrlib.c|,
\verb|liolib.c| and \verb|lmathlib.c| in Lua distribution. \verb|liolib.c| and \verb|lmathlib.c| in Lua distribution.
\subsection{References to Lua Objects} \subsection{References to Lua Objects}
@ -2080,7 +2078,7 @@ If \verb|i| is absent, then it is assumed to be 1.
\subsubsection*{\ff \T{format (formatstring, e1, e2, \ldots)}}\Deffunc{format} \subsubsection*{\ff \T{format (formatstring, e1, e2, \ldots)}}\Deffunc{format}
\label{format} \label{format}
This function returns a formated version of its variable number of arguments This function returns a formatted version of its variable number of arguments
following the description given in its first argument (which must be a string). following the description given in its first argument (which must be a string).
The format string follows the same rules as the \verb|printf| family of The format string follows the same rules as the \verb|printf| family of
standard C functions. standard C functions.
@ -2112,7 +2110,7 @@ decimal digit in the range [1,9],
giving the position of the argument in the argument list. giving the position of the argument in the argument list.
For instance, the call \verb|format("%2$d -> %1$03d", 1, 34)| will For instance, the call \verb|format("%2$d -> %1$03d", 1, 34)| will
result in \verb|"34 -> 001"|. result in \verb|"34 -> 001"|.
The same argument can be used in more than one convertion. The same argument can be used in more than one conversion.
The options \verb|c|, \verb|d|, \verb|E|, \verb|e|, \verb|f|, The options \verb|c|, \verb|d|, \verb|E|, \verb|e|, \verb|f|,
\verb|g|, \verb|G|, \verb|i|, \verb|o|, \verb|u|, \verb|X|, and \verb|x| all \verb|g|, \verb|G|, \verb|i|, \verb|o|, \verb|u|, \verb|X|, and \verb|x| all
@ -2506,7 +2504,7 @@ It returns an error code, which is system-dependent.
\subsubsection*{\ff \T{setlocale (locale [, category])}}\Deffunc{setlocale} \subsubsection*{\ff \T{setlocale (locale [, category])}}\Deffunc{setlocale}
This function is an interface to the ANSI C function \verb|setlocale|. This function is an interface to the ANSI C function \verb|setlocale|.
\verb|locale| is a string specifing a locale; \verb|locale| is a string specifying a locale;
\verb|category| is a number describing which category to change: \verb|category| is a number describing which category to change:
0 is \verb|LC_ALL|, 1 is \verb|LC_COLLATE|, 2 is \verb|LC_CTYPE|, 0 is \verb|LC_ALL|, 1 is \verb|LC_COLLATE|, 2 is \verb|LC_CTYPE|,
3 is \verb|LC_MONETARY|, 4 is \verb|LC_NUMERIC|, and 5 is \verb|LC_TIME|; 3 is \verb|LC_MONETARY|, 4 is \verb|LC_NUMERIC|, and 5 is \verb|LC_TIME|;
@ -2659,7 +2657,7 @@ This program can be called with any sequence of the following arguments:
\item[\T{-e stat}] executes \verb|stat| as a Lua chunk. \item[\T{-e stat}] executes \verb|stat| as a Lua chunk.
\item[\T{-i}] runs interactively, \item[\T{-i}] runs interactively,
accepting commands from standard input until an \verb|EOF|. accepting commands from standard input until an \verb|EOF|.
Each line entered is immediatly executed. Each line entered is immediately executed.
\item[\T{-q}] same as \T{-i}, but without a prompt (quiet mode). \item[\T{-q}] same as \T{-i}, but without a prompt (quiet mode).
\item[\T{-}] executes \verb|stdin| as a file. \item[\T{-}] executes \verb|stdin| as a file.
\item[\T{var=value}] sets global \verb|var| with string \verb|value|. \item[\T{var=value}] sets global \verb|var| with string \verb|value|.
@ -2711,7 +2709,7 @@ Here is a list of all these incompatibilities.
\begin{itemize} \begin{itemize}
\item To support for multiple contexts, \item To support for multiple contexts,
the whole library must be explicitly openen before used. the whole library must be explicitly opened before used.
However, all standard libraries check whether Lua is already opened, However, all standard libraries check whether Lua is already opened,
so any program that opens at least one standard library before using so any program that opens at least one standard library before using
Lua API does not need to be corrected. Lua API does not need to be corrected.
@ -2727,7 +2725,7 @@ Closures make this feature irrelevant.
\item The syntax for function declaration is now more restricted; \item The syntax for function declaration is now more restricted;
for instance, the old syntax \verb|function f[exp] (x) ... end| is not for instance, the old syntax \verb|function f[exp] (x) ... end| is not
accepted in 3.1. accepted in 3.1.
Progams should use an explicit assignment instead, like this: Programs should use an explicit assignment instead, like this:
\verb|f[exp] = function (x) ... end|. \verb|f[exp] = function (x) ... end|.
\item Old pre-compiled code is obsolete, and must be re-compiled. \item Old pre-compiled code is obsolete, and must be re-compiled.