Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 282914b

Browse files
committed
Added error checking for numeric constants; added local/global variable
optimization.
1 parent 572fd57 commit 282914b

1 file changed

Lines changed: 112 additions & 4 deletions

File tree

Python/compile.c

Lines changed: 112 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
4141

4242
#include <ctype.h>
4343

44+
extern int errno;
45+
4446
#define OFF(x) offsetof(codeobject, x)
4547

4648
static struct memberlist code_memberlist[] = {
@@ -349,14 +351,28 @@ parsenumber(s)
349351
char *s;
350352
{
351353
extern long strtol();
352-
extern double atof();
354+
extern double strtod();
353355
char *end = s;
354356
long x;
357+
double xx;
358+
errno = 0;
355359
x = strtol(s, &end, 0);
356-
if (*end == '\0')
360+
if (*end == '\0') {
361+
if (errno != 0) {
362+
err_setstr(RuntimeError, "integer constant too large");
363+
return NULL;
364+
}
357365
return newintobject(x);
358-
if (*end == '.' || *end == 'e' || *end == 'E')
359-
return newfloatobject(atof(s));
366+
}
367+
errno = 0;
368+
xx = strtod(s, &end);
369+
if (*end == '\0') {
370+
if (errno != 0) {
371+
err_setstr(RuntimeError, "float constant too large");
372+
return NULL;
373+
}
374+
return newfloatobject(xx);
375+
}
360376
err_setstr(RuntimeError, "bad number syntax");
361377
return NULL;
362378
}
@@ -1752,6 +1768,96 @@ compile_node(c, n)
17521768
}
17531769
}
17541770

1771+
/* Optimization for local and global variables.
1772+
1773+
Attempt to replace all LOAD_NAME instructions that refer to a local
1774+
variable with LOAD_LOCAL instructions, and all that refer to a global
1775+
variable with LOAD_GLOBAL instructions.
1776+
1777+
To find all local variables, we check all STORE_NAME and IMPORT_FROM
1778+
instructions. This yields all local variables, including arguments,
1779+
function definitions, class definitions and import statements.
1780+
1781+
There is one leak: 'from foo import *' introduces local variables
1782+
that we can't know while compiling. If this is the case, LOAD_GLOBAL
1783+
instructions are not generated -- LOAD_NAME is left in place for
1784+
globals, since it first checks for globals (LOAD_LOCAL is still used
1785+
for recognized locals, since it doesn't hurt).
1786+
1787+
This optimization means that using the same name as a global and
1788+
as a local variable within the same scope is now illegal, which
1789+
is a change to the language! Also using eval() to introduce new
1790+
local variables won't work. But both were bad practice at best.
1791+
1792+
The optimization doesn't save much: basically, it saves one
1793+
unsuccessful dictionary lookup per global (or built-in) variable
1794+
reference. On the (slow!) Mac Plus, with 4 local variables,
1795+
this saving was measured to be about 0.18 ms. We might save more
1796+
by using a different data structure to hold local variables, like
1797+
an array indexed by variable number.
1798+
1799+
NB: this modifies the string object co->co_code!
1800+
*/
1801+
1802+
static void
1803+
optimizer(co)
1804+
codeobject *co;
1805+
{
1806+
char *next_instr, *cur_instr;
1807+
object *locals;
1808+
int opcode;
1809+
int oparg;
1810+
object *name;
1811+
int star_used;
1812+
1813+
#define NEXTOP() (*next_instr++)
1814+
#define NEXTARG() (next_instr += 2, (next_instr[-1]<<8) + next_instr[-2])
1815+
#define GETITEM(v, i) (getlistitem((v), (i)))
1816+
#define GETNAMEOBJ(i) (GETITEM(co->co_names, (i)))
1817+
1818+
locals = newdictobject();
1819+
if (locals == NULL) {
1820+
err_clear();
1821+
return; /* For now, this is OK */
1822+
}
1823+
1824+
next_instr = GETSTRINGVALUE(co->co_code);
1825+
for (;;) {
1826+
opcode = NEXTOP();
1827+
if (opcode == STOP_CODE)
1828+
break;
1829+
if (HAS_ARG(opcode))
1830+
oparg = NEXTARG();
1831+
if (opcode == STORE_NAME || opcode == IMPORT_FROM) {
1832+
name = GETNAMEOBJ(oparg);
1833+
if (dict2insert(locals, name, None) != 0) {
1834+
DECREF(locals);
1835+
return; /* Sorry */
1836+
}
1837+
}
1838+
}
1839+
1840+
star_used = (dictlookup(locals, "*") != NULL);
1841+
next_instr = GETSTRINGVALUE(co->co_code);
1842+
for (;;) {
1843+
cur_instr = next_instr;
1844+
opcode = NEXTOP();
1845+
if (opcode == STOP_CODE)
1846+
break;
1847+
if (HAS_ARG(opcode))
1848+
oparg = NEXTARG();
1849+
if (opcode == LOAD_NAME) {
1850+
name = GETNAMEOBJ(oparg);
1851+
if (dictlookup(locals, getstringvalue(name)) != NULL)
1852+
*cur_instr = LOAD_LOCAL;
1853+
else if (!star_used)
1854+
*cur_instr = LOAD_GLOBAL;
1855+
}
1856+
}
1857+
1858+
DECREF(locals);
1859+
}
1860+
17551861
codeobject *
17561862
compile(n, filename)
17571863
node *n;
@@ -1768,5 +1874,7 @@ compile(n, filename)
17681874
else
17691875
co = NULL;
17701876
com_free(&sc);
1877+
if (co != NULL)
1878+
optimizer(co);
17711879
return co;
17721880
}

0 commit comments

Comments
 (0)