forked from Mirror/wren
Better error message on too many inherited fields.
This commit is contained in:
@ -158,13 +158,13 @@ nav {
|
||||
}
|
||||
|
||||
h2 {
|
||||
font: normal 24px $header;
|
||||
font: normal 30px $header;
|
||||
margin: 24px 0 0 0;
|
||||
color: $blue;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font: normal 20px $header;
|
||||
font: normal 24px $header;
|
||||
margin: 24px 0 0 0;
|
||||
color: $blue;
|
||||
}
|
||||
|
||||
@ -62,28 +62,32 @@
|
||||
// The maximum number of globals that may be defined at one time. This
|
||||
// limitation comes from the 16 bits used for the arguments to
|
||||
// `CODE_LOAD_GLOBAL` and `CODE_STORE_GLOBAL`.
|
||||
#define MAX_GLOBALS (65536)
|
||||
#define MAX_GLOBALS 65536
|
||||
|
||||
// The maximum number of arguments that can be passed to a method. Note that
|
||||
// this limitation is hardcoded in other places in the VM, in particular, the
|
||||
// `CODE_CALL_XX` instructions assume a certain maximum number.
|
||||
#define MAX_PARAMETERS (16)
|
||||
#define MAX_PARAMETERS 16
|
||||
|
||||
// The maximum name of a method, not including the signature. This is an
|
||||
// arbitrary but enforced maximum just so we know how long the method name
|
||||
// strings need to be in the parser.
|
||||
#define MAX_METHOD_NAME (64)
|
||||
#define MAX_METHOD_NAME 64
|
||||
|
||||
// The maximum length of a method signature. This includes the name, and the
|
||||
// extra spaces added to handle arity, and another byte to terminate the string.
|
||||
#define MAX_METHOD_SIGNATURE (MAX_METHOD_NAME + MAX_PARAMETERS + 1)
|
||||
|
||||
// The maximum length of an identifier. The only real reason for this limitation
|
||||
// is so that error messages mentioning variables can be stack allocated.
|
||||
#define MAX_VARIABLE_NAME 64
|
||||
|
||||
// The maximum number of fields a class can have, including inherited fields.
|
||||
// This is explicit in the bytecode since `CODE_CLASS` and `CODE_SUBCLASS` take
|
||||
// a single byte for the number of fields. Note that it's 255 and not 256
|
||||
// because creating a class takes the *number* of fields, not the *highest
|
||||
// field index*.
|
||||
#define MAX_FIELDS (255)
|
||||
#define MAX_FIELDS 255
|
||||
|
||||
// Assertions are used to validate program invariants. They indicate things the
|
||||
// program expects to be true about its internal state during execution. If an
|
||||
|
||||
@ -943,6 +943,12 @@ static int declareVariable(Compiler* compiler)
|
||||
{
|
||||
Token* token = &compiler->parser->previous;
|
||||
|
||||
if (token->length > MAX_VARIABLE_NAME)
|
||||
{
|
||||
error(compiler, "Variable name cannot be longer than %d characters.",
|
||||
MAX_VARIABLE_NAME);
|
||||
}
|
||||
|
||||
// Top-level global scope.
|
||||
if (compiler->scopeDepth == -1)
|
||||
{
|
||||
|
||||
@ -950,20 +950,20 @@ static bool runInterpreter(WrenVM* vm)
|
||||
}
|
||||
|
||||
int numFields = READ_BYTE();
|
||||
|
||||
ObjClass* classObj = wrenNewClass(vm, superclass, numFields, name);
|
||||
|
||||
// Now that we know the total number of fields, make sure we don't
|
||||
// overflow.
|
||||
if (superclass->numFields + numFields > MAX_FIELDS)
|
||||
{
|
||||
// TODO: Include class name in message. Mention inheritance.
|
||||
char message[80];
|
||||
snprintf(message, 80,
|
||||
"A class may not have more than %d fields, including inherited "
|
||||
"ones.", MAX_FIELDS);
|
||||
char message[70 + MAX_VARIABLE_NAME];
|
||||
snprintf(message, 70 + MAX_VARIABLE_NAME,
|
||||
"Class '%s' may not have more than %d fields, including inherited "
|
||||
"ones.", name->value, MAX_FIELDS);
|
||||
RUNTIME_ERROR(message);
|
||||
}
|
||||
|
||||
|
||||
// Don't pop the superclass and name off the stack until the subclass is
|
||||
// done being created, to make sure it doesn't get collected.
|
||||
DROP();
|
||||
|
||||
2
test/limit/long_variable_name.wren
Normal file
2
test/limit/long_variable_name.wren
Normal file
@ -0,0 +1,2 @@
|
||||
var i234567890i234567890i234567890i234567890i234567890i234 = "value"
|
||||
class c234567890c234567890c234567890c234567890c234567890c234567890c234 {}
|
||||
@ -136,7 +136,7 @@ class Foo {
|
||||
}
|
||||
}
|
||||
|
||||
class Bar is Foo { // expect runtime error: A class may not have more than 255 fields, including inherited ones.
|
||||
class Bar is Foo {
|
||||
new {
|
||||
super
|
||||
_field129 = 129
|
||||
@ -266,15 +266,16 @@ class Bar is Foo { // expect runtime error: A class may not have more than 255 f
|
||||
_field253 = 253
|
||||
_field254 = 254
|
||||
_field255 = 255
|
||||
_field256 = 256
|
||||
}
|
||||
|
||||
bar {
|
||||
IO.print(_field129)
|
||||
IO.print(_field256)
|
||||
IO.print(_field255)
|
||||
}
|
||||
}
|
||||
|
||||
var bar = new Bar
|
||||
bar.foo
|
||||
bar.bar
|
||||
bar.foo // expect: 1
|
||||
// expect: 128
|
||||
bar.bar // expect: 129
|
||||
// expect: 255
|
||||
|
||||
@ -136,7 +136,7 @@ class Foo {
|
||||
}
|
||||
}
|
||||
|
||||
class Bar is Foo {
|
||||
class Bar is Foo { // expect runtime error: Class 'Bar' may not have more than 255 fields, including inherited ones.
|
||||
new {
|
||||
super
|
||||
_field129 = 129
|
||||
@ -266,16 +266,15 @@ class Bar is Foo {
|
||||
_field253 = 253
|
||||
_field254 = 254
|
||||
_field255 = 255
|
||||
_field256 = 256
|
||||
}
|
||||
|
||||
bar {
|
||||
IO.print(_field129)
|
||||
IO.print(_field255)
|
||||
IO.print(_field256)
|
||||
}
|
||||
}
|
||||
|
||||
var bar = new Bar
|
||||
bar.foo // expect: 1
|
||||
// expect: 128
|
||||
bar.bar // expect: 129
|
||||
// expect: 255
|
||||
bar.foo
|
||||
bar.bar
|
||||
|
||||
2
test/limit/variable_name_too_long.wren
Normal file
2
test/limit/variable_name_too_long.wren
Normal file
@ -0,0 +1,2 @@
|
||||
var i234567890i234567890i234567890i234567890i234567890i2345 = "value" // expect error
|
||||
class c234567890c234567890c234567890c234567890c234567890c234567890c2345 {} // expect error
|
||||
Reference in New Issue
Block a user