feat: enforce MAX_LOCALS limit of 256 in declareVariable and add test cases for boundary conditions

Add a compile-time check in declareVariable() that emits an error when the number of simultaneous local variables reaches MAX_LOCALS (256), replacing the previous placeholder TODO. The limit is derived from the bytecode encoding constraint where CODE_LOAD_LOCAL and CODE_STORE_LOCAL use a single argument byte. Also move the MAX_LOCALS definition from a TODO comment to a proper #define, increasing the value from 255 to 256. Include four new test files: many_locals.wren (exactly 256 simultaneous locals), many_nonsimultaneous_locals.wren (more than 256 locals across nested scopes), too_many_locals.wren (257 simultaneous locals triggering the error), and too_many_locals_nested.wren (exceeding the limit across nested blocks).
This commit is contained in:
Bob Nystrom
2013-12-01 02:51:27 +00:00
parent 4240e46e05
commit d9ed245dd4
5 changed files with 1325 additions and 5 deletions
+16 -5
View File
@@ -21,6 +21,15 @@
// `CODE_CALL_XX` instructions assume a certain maximum number.
#define MAX_PARAMETERS (16)
// The maximum number of local (i.e. non-global) variables that can be declared
// in a single function, method, or chunk of top level code. This is the
// maximum number of variables in scope at one time, and spans block scopes.
//
// Note that this limitation is also explicit in the bytecode. Since
// [CODE_LOAD_LOCAL] and [CODE_STORE_LOCAL] use a single argument byte to
// identify the local, only 256 can be in scope at one time.
#define MAX_LOCALS (256)
typedef enum
{
TOKEN_LEFT_PAREN,
@@ -123,9 +132,6 @@ typedef struct
int currentStringLength;
} Parser;
// TODO(bob): Move and doc.
#define MAX_LOCALS (255)
typedef struct
{
// The name of the local variable. This points directly into the original
@@ -692,13 +698,18 @@ static int declareVariable(Compiler* compiler)
}
}
if (compiler->numLocals == MAX_LOCALS)
{
error(compiler, "Cannot declare more than %d variables in one scope.",
MAX_LOCALS);
return -1;
}
// Define a new local variable in the current scope.
Local* local = &compiler->locals[compiler->numLocals];
local->name = name;
local->length = length;
local->depth = compiler->scopeDepth;
// TODO(bob): Check for too many.
return compiler->numLocals++;
}