Allow empty argument list methods.

- Compile them as calls and definitions.
- Use them for call(), clear(), run(), try(), and yield().
- Update the docs.
This commit is contained in:
Bob Nystrom
2015-02-26 23:08:36 -08:00
parent 1aaa8cff52
commit 96ceaa528b
94 changed files with 291 additions and 224 deletions
+14 -6
View File
@@ -1550,6 +1550,10 @@ static void parameterList(Compiler* compiler, Signature* signature,
if (!match(compiler, startToken)) return;
signature->type = SIG_METHOD;
// Allow empty parameter lists for methods.
if (endToken == TOKEN_RIGHT_PAREN && match(compiler, endToken)) return;
finishParameterList(compiler, signature, endToken);
}
@@ -1679,8 +1683,12 @@ static void methodCall(Compiler* compiler, Code instruction,
if (match(compiler, TOKEN_LEFT_PAREN))
{
signature.type = SIG_METHOD;
// TODO: Allow an empty argument list.
finishArgumentList(compiler, &signature);
// Allow empty an argument list.
if (peek(compiler) != TOKEN_RIGHT_PAREN)
{
finishArgumentList(compiler, &signature);
}
consume(compiler, TOKEN_RIGHT_PAREN, "Expect ')' after arguments.");
}
@@ -1773,7 +1781,7 @@ static void list(Compiler* compiler, bool allowAssignment)
emitShortArg(compiler, CODE_LOAD_MODULE_VAR, listClassSymbol);
// Instantiate a new list.
callMethod(compiler, 0, " instantiate", 12);
callMethod(compiler, 0, "<instantiate>", 13);
// Compile the list elements. Each one compiles to a ".add()" call.
if (peek(compiler) != TOKEN_RIGHT_BRACKET)
@@ -1809,7 +1817,7 @@ static void map(Compiler* compiler, bool allowAssignment)
emitShortArg(compiler, CODE_LOAD_MODULE_VAR, mapClassSymbol);
// Instantiate a new map.
callMethod(compiler, 0, " instantiate", 12);
callMethod(compiler, 0, "<instantiate>", 13);
// Compile the map elements. Each one is compiled to just invoke the
// subscript setter on the map.
@@ -2202,7 +2210,7 @@ static void new_(Compiler* compiler, bool allowAssignment)
}
// The leading space in the name is to ensure users can't call it directly.
callMethod(compiler, 0, " instantiate", 12);
callMethod(compiler, 0, "<instantiate>", 13);
// Invoke the constructor on the new instance.
methodCall(compiler, CODE_CALL_0, "new", 3);
@@ -2477,7 +2485,7 @@ void parsePrecedence(Compiler* compiler, bool allowAssignment,
if (prefix == NULL)
{
error(compiler, "Unexpected token for expression.");
error(compiler, "Expected expression.");
return;
}
+13 -15
View File
@@ -1393,7 +1393,7 @@ void wrenInitializeCore(WrenVM* vm)
NATIVE(vm->objectClass, "new", object_new);
NATIVE(vm->objectClass, "toString", object_toString);
NATIVE(vm->objectClass, "type", object_type);
NATIVE(vm->objectClass, " instantiate", object_instantiate);
NATIVE(vm->objectClass, "<instantiate>", object_instantiate);
// Now we can define Class, which is a subclass of Object, but Object's
// metaclass.
@@ -1406,7 +1406,7 @@ void wrenInitializeCore(WrenVM* vm)
// Define the methods specific to Class after wiring up its superclass to
// prevent the inherited ones from overwriting them.
NATIVE(vm->classClass, " instantiate", class_instantiate);
NATIVE(vm->classClass, "<instantiate>", class_instantiate);
NATIVE(vm->classClass, "name", class_name);
// The core class diagram ends up looking like this, where single lines point
@@ -1436,26 +1436,26 @@ void wrenInitializeCore(WrenVM* vm)
// TODO: Make fibers inherit Sequence and be iterable.
vm->fiberClass = defineClass(vm, "Fiber");
NATIVE(vm->fiberClass->obj.classObj, " instantiate", fiber_instantiate);
NATIVE(vm->fiberClass->obj.classObj, "<instantiate>", fiber_instantiate);
NATIVE(vm->fiberClass->obj.classObj, "new(_)", fiber_new);
NATIVE(vm->fiberClass->obj.classObj, "abort(_)", fiber_abort);
NATIVE(vm->fiberClass->obj.classObj, "yield", fiber_yield);
NATIVE(vm->fiberClass->obj.classObj, "yield()", fiber_yield);
NATIVE(vm->fiberClass->obj.classObj, "yield(_)", fiber_yield1);
NATIVE(vm->fiberClass, "call", fiber_call);
NATIVE(vm->fiberClass, "call()", fiber_call);
NATIVE(vm->fiberClass, "call(_)", fiber_call1);
NATIVE(vm->fiberClass, "error", fiber_error);
NATIVE(vm->fiberClass, "isDone", fiber_isDone);
NATIVE(vm->fiberClass, "run", fiber_run);
NATIVE(vm->fiberClass, "run()", fiber_run);
NATIVE(vm->fiberClass, "run(_)", fiber_run1);
NATIVE(vm->fiberClass, "try", fiber_try);
NATIVE(vm->fiberClass, "try()", fiber_try);
vm->fnClass = defineClass(vm, "Fn");
NATIVE(vm->fnClass->obj.classObj, " instantiate", fn_instantiate);
NATIVE(vm->fnClass->obj.classObj, "<instantiate>", fn_instantiate);
NATIVE(vm->fnClass->obj.classObj, "new(_)", fn_new);
NATIVE(vm->fnClass, "arity", fn_arity);
NATIVE(vm->fnClass, "call", fn_call0);
NATIVE(vm->fnClass, "call()", fn_call0);
NATIVE(vm->fnClass, "call(_)", fn_call1);
NATIVE(vm->fnClass, "call(_,_)", fn_call2);
NATIVE(vm->fnClass, "call(_,_,_)", fn_call3);
@@ -1527,12 +1527,11 @@ void wrenInitializeCore(WrenVM* vm)
NATIVE(vm->stringClass, "toString", string_toString);
vm->listClass = AS_CLASS(wrenFindVariable(vm, "List"));
NATIVE(vm->listClass->obj.classObj, " instantiate", list_instantiate);
NATIVE(vm->listClass->obj.classObj, "<instantiate>", list_instantiate);
NATIVE(vm->listClass, "[_]", list_subscript);
NATIVE(vm->listClass, "[_]=(_)", list_subscriptSetter);
NATIVE(vm->listClass, "add(_)", list_add);
// TODO: Make ().
NATIVE(vm->listClass, "clear", list_clear);
NATIVE(vm->listClass, "clear()", list_clear);
NATIVE(vm->listClass, "count", list_count);
NATIVE(vm->listClass, "insert(_,_)", list_insert);
NATIVE(vm->listClass, "iterate(_)", list_iterate);
@@ -1540,11 +1539,10 @@ void wrenInitializeCore(WrenVM* vm)
NATIVE(vm->listClass, "removeAt(_)", list_removeAt);
vm->mapClass = AS_CLASS(wrenFindVariable(vm, "Map"));
NATIVE(vm->mapClass->obj.classObj, " instantiate", map_instantiate);
NATIVE(vm->mapClass->obj.classObj, "<instantiate>", map_instantiate);
NATIVE(vm->mapClass, "[_]", map_subscript);
NATIVE(vm->mapClass, "[_]=(_)", map_subscriptSetter);
// TODO: Make ().
NATIVE(vm->mapClass, "clear", map_clear);
NATIVE(vm->mapClass, "clear()", map_clear);
NATIVE(vm->mapClass, "containsKey(_)", map_containsKey);
NATIVE(vm->mapClass, "count", map_count);
NATIVE(vm->mapClass, "remove(_)", map_remove);