No more default constructors.

Fixes #296.
This commit is contained in:
Bob Nystrom
2015-09-01 08:16:04 -07:00
parent 36f3059e48
commit 2e83f056c1
86 changed files with 248 additions and 133 deletions
+2 -30
View File
@@ -2964,7 +2964,7 @@ static void defineMethod(Compiler* compiler, int classSlot, bool isStatic,
// Returns `true` if it compiled successfully, or `false` if the method couldn't
// be parsed.
static bool method(Compiler* compiler, ClassCompiler* classCompiler,
int classSlot, bool* hasConstructor)
int classSlot)
{
// TODO: What about foreign constructors?
bool isForeign = match(compiler, TOKEN_FOREIGN);
@@ -3030,31 +3030,11 @@ static bool method(Compiler* compiler, ClassCompiler* classCompiler,
createConstructor(compiler, &signature, methodSymbol);
defineMethod(compiler, classSlot, true, constructorSymbol);
// We don't need a default constructor anymore.
*hasConstructor = true;
}
return true;
}
// Defines a default "new()" constructor on the current class.
//
// It just invokes "init new()" on the instance. If a base class defines that,
// it will get invoked. Otherwise, it falls to the default one in Object which
// does nothing.
static void createDefaultConstructor(Compiler* compiler, int classSlot)
{
Signature signature = { "new", 3, SIG_INITIALIZER, 0 };
int initializerSymbol = signatureSymbol(compiler, &signature);
signature.type = SIG_METHOD;
int constructorSymbol = signatureSymbol(compiler, &signature);
createConstructor(compiler, &signature, initializerSymbol);
defineMethod(compiler, classSlot, true, constructorSymbol);
}
// Compiles a class definition. Assumes the "class" token has already been
// consumed (along with a possibly preceding "foreign" token).
static void classDefinition(Compiler* compiler, bool isForeign)
@@ -3117,11 +3097,9 @@ static void classDefinition(Compiler* compiler, bool isForeign)
consume(compiler, TOKEN_LEFT_BRACE, "Expect '{' after class declaration.");
matchLine(compiler);
bool hasConstructor = false;
while (!match(compiler, TOKEN_RIGHT_BRACE))
{
if (!method(compiler, &classCompiler, slot, &hasConstructor)) break;
if (!method(compiler, &classCompiler, slot)) break;
// Don't require a newline after the last definition.
if (match(compiler, TOKEN_RIGHT_BRACE)) break;
@@ -3129,12 +3107,6 @@ static void classDefinition(Compiler* compiler, bool isForeign)
consumeLine(compiler, "Expect newline after definition in class.");
}
// If no constructor was defined, create a default new() one.
if (!hasConstructor)
{
createDefaultConstructor(compiler, slot);
}
// Update the class with the number of fields.
if (!isForeign)
{
+6 -12
View File
@@ -213,16 +213,6 @@ static const char* coreLibSource =
"\n"
"class Range is Sequence {}\n";
// A simple primitive that just returns "this". Used in a few different places:
//
// * The default new() initializer on Object needs no initialization so just
// uses this.
// * String's toString method obviously can use this.
DEF_PRIMITIVE(return_this)
{
RETURN_VAL(args[0]);
}
DEF_PRIMITIVE(bool_not)
{
RETURN_BOOL(!AS_BOOL(args[0]));
@@ -1258,6 +1248,11 @@ DEF_PRIMITIVE(string_subscript)
RETURN_ERROR("Subscript ranges for strings are not implemented yet.");
}
DEF_PRIMITIVE(string_toString)
{
RETURN_VAL(args[0]);
}
// Creates either the Object or Class class in the core library with [name].
static ObjClass* defineClass(WrenVM* vm, ObjModule* module, const char* name)
{
@@ -1282,7 +1277,6 @@ void wrenInitializeCore(WrenVM* vm)
PRIMITIVE(vm->objectClass, "!", object_not);
PRIMITIVE(vm->objectClass, "==(_)", object_eqeq);
PRIMITIVE(vm->objectClass, "!=(_)", object_bangeq);
PRIMITIVE(vm->objectClass, "init new()", return_this);
PRIMITIVE(vm->objectClass, "is(_)", object_is);
PRIMITIVE(vm->objectClass, "toString", object_toString);
PRIMITIVE(vm->objectClass, "type", object_type);
@@ -1436,7 +1430,7 @@ void wrenInitializeCore(WrenVM* vm)
PRIMITIVE(vm->stringClass, "iterateByte_(_)", string_iterateByte);
PRIMITIVE(vm->stringClass, "iteratorValue(_)", string_iteratorValue);
PRIMITIVE(vm->stringClass, "startsWith(_)", string_startsWith);
PRIMITIVE(vm->stringClass, "toString", return_this);
PRIMITIVE(vm->stringClass, "toString", string_toString);
vm->listClass = AS_CLASS(wrenFindVariable(vm, coreModule, "List"));
PRIMITIVE(vm->listClass->obj.classObj, "new()", list_new);