forked from Mirror/wren
Get rid of separate CODE_SUBCLASS instruction.
Just pushes null to indicate "inherits from Object". Unifies a bit of code.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,5 +1,6 @@
|
||||
# Intermediate files directory.
|
||||
build/
|
||||
build_xcode/
|
||||
|
||||
# Built applications.
|
||||
wren
|
||||
|
||||
@ -2047,8 +2047,6 @@ static int getNumArguments(const uint8_t* bytecode, const Value* constants,
|
||||
case CODE_CLOSE_UPVALUE:
|
||||
case CODE_RETURN:
|
||||
case CODE_NEW:
|
||||
case CODE_CLASS:
|
||||
case CODE_SUBCLASS:
|
||||
case CODE_END:
|
||||
return 0;
|
||||
|
||||
@ -2063,6 +2061,7 @@ static int getNumArguments(const uint8_t* bytecode, const Value* constants,
|
||||
case CODE_LOAD_FIELD:
|
||||
case CODE_STORE_FIELD:
|
||||
case CODE_LIST:
|
||||
case CODE_CLASS:
|
||||
return 1;
|
||||
|
||||
case CODE_CONSTANT:
|
||||
@ -2422,14 +2421,15 @@ static void classDefinition(Compiler* compiler)
|
||||
if (match(compiler, TOKEN_IS))
|
||||
{
|
||||
parsePrecedence(compiler, false, PREC_CALL);
|
||||
emit(compiler, CODE_SUBCLASS);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create the empty class.
|
||||
emit(compiler, CODE_CLASS);
|
||||
emit(compiler, CODE_NULL);
|
||||
}
|
||||
|
||||
emit(compiler, CODE_CLASS);
|
||||
|
||||
// Store a placeholder for the number of fields argument. We don't know
|
||||
// the value until we've compiled all the methods to see which fields are
|
||||
// used.
|
||||
|
||||
200
src/wren_debug.c
200
src/wren_debug.c
@ -26,8 +26,12 @@ void wrenDebugPrintStackTrace(WrenVM* vm, ObjFiber* fiber)
|
||||
}
|
||||
}
|
||||
|
||||
static void printLine(ObjFn* fn, int i, int* lastLine)
|
||||
static int debugPrintInstruction(WrenVM* vm, ObjFn* fn, int i, int* lastLine)
|
||||
{
|
||||
int start = i;
|
||||
uint8_t* bytecode = fn->bytecode;
|
||||
Code code = bytecode[i];
|
||||
|
||||
int line = fn->debug->sourceLines[i];
|
||||
if (lastLine == NULL || *lastLine != line)
|
||||
{
|
||||
@ -38,32 +42,24 @@ static void printLine(ObjFn* fn, int i, int* lastLine)
|
||||
{
|
||||
printf(" ");
|
||||
}
|
||||
}
|
||||
|
||||
static int debugPrintInstruction(WrenVM* vm, ObjFn* fn, int i, int* lastLine)
|
||||
{
|
||||
int start = i;
|
||||
uint8_t* bytecode = fn->bytecode;
|
||||
Code code = bytecode[i++];
|
||||
printf(" %04d ", i++);
|
||||
|
||||
printLine(fn, i, lastLine);
|
||||
printf(" %04d ", i);
|
||||
#define READ_BYTE() (bytecode[i++])
|
||||
#define READ_SHORT() (i += 2, (bytecode[i - 2] << 8) | bytecode[i - 1])
|
||||
|
||||
#define PRINT_ARG \
|
||||
printLine(fn, i, lastLine); printf(" %04d ", ++i); printf
|
||||
#define BYTE_INSTRUCTION(name) \
|
||||
printf("%-16s %5d\n", name, READ_BYTE()); \
|
||||
break; \
|
||||
|
||||
// TODO: Come up with a cleaner way of displaying 16-bit args.
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case CODE_CONSTANT:
|
||||
{
|
||||
int constant = (bytecode[i] << 8) | bytecode[i + 1];
|
||||
printf("CONSTANT '");
|
||||
int constant = READ_SHORT();
|
||||
printf("%-16s %5d '", "CONSTANT", constant);
|
||||
wrenPrintValue(fn->constants[constant]);
|
||||
printf("'\n");
|
||||
PRINT_ARG("constant %d\n", constant);
|
||||
PRINT_ARG("\n");
|
||||
break;
|
||||
}
|
||||
|
||||
@ -71,85 +67,31 @@ static int debugPrintInstruction(WrenVM* vm, ObjFn* fn, int i, int* lastLine)
|
||||
case CODE_FALSE: printf("FALSE\n"); break;
|
||||
case CODE_TRUE: printf("TRUE\n"); break;
|
||||
|
||||
case CODE_LOAD_LOCAL:
|
||||
{
|
||||
int local = bytecode[i];
|
||||
printf("LOAD_LOCAL %d\n", local);
|
||||
PRINT_ARG("local %d\n", local);
|
||||
break;
|
||||
}
|
||||
|
||||
case CODE_STORE_LOCAL:
|
||||
{
|
||||
int local = bytecode[i];
|
||||
printf("STORE_LOCAL %d\n", local);
|
||||
PRINT_ARG("local %d\n", local);
|
||||
break;
|
||||
}
|
||||
|
||||
case CODE_LOAD_UPVALUE:
|
||||
{
|
||||
int upvalue = bytecode[i];
|
||||
printf("LOAD_UPVALUE %d\n", upvalue);
|
||||
PRINT_ARG("upvalue %d\n", upvalue);
|
||||
break;
|
||||
}
|
||||
|
||||
case CODE_STORE_UPVALUE:
|
||||
{
|
||||
int upvalue = bytecode[i];
|
||||
printf("STORE_UPVALUE %d\n", upvalue);
|
||||
PRINT_ARG("upvalue %d\n", upvalue);
|
||||
break;
|
||||
}
|
||||
case CODE_LOAD_LOCAL: BYTE_INSTRUCTION("LOAD_LOCAL");
|
||||
case CODE_STORE_LOCAL: BYTE_INSTRUCTION("STORE_LOCAL");
|
||||
case CODE_LOAD_UPVALUE: BYTE_INSTRUCTION("LOAD_UPVALUE");
|
||||
case CODE_STORE_UPVALUE: BYTE_INSTRUCTION("STORE_UPVALUE");
|
||||
|
||||
case CODE_LOAD_GLOBAL:
|
||||
{
|
||||
int global = bytecode[i];
|
||||
printf("LOAD_GLOBAL \"%s\"\n", vm->globalSymbols.names.data[global]);
|
||||
PRINT_ARG("global %d\n", global);
|
||||
int global = READ_BYTE();
|
||||
printf("%-16s %5d '%s'\n", "LOAD_GLOBAL", global,
|
||||
vm->globalSymbols.names.data[global]);
|
||||
break;
|
||||
}
|
||||
|
||||
case CODE_STORE_GLOBAL:
|
||||
{
|
||||
int global = bytecode[i];
|
||||
printf("STORE_GLOBAL \"%s\"\n", vm->globalSymbols.names.data[global]);
|
||||
PRINT_ARG("global %d\n", global);
|
||||
int global = READ_BYTE();
|
||||
printf("%-16s %5d '%s'\n", "STORE_GLOBAL", global,
|
||||
vm->globalSymbols.names.data[global]);
|
||||
break;
|
||||
}
|
||||
|
||||
case CODE_LOAD_FIELD_THIS:
|
||||
{
|
||||
int field = bytecode[i];
|
||||
printf("LOAD_FIELD_THIS %d\n", field);
|
||||
PRINT_ARG("field %d\n", field);
|
||||
break;
|
||||
}
|
||||
|
||||
case CODE_STORE_FIELD_THIS:
|
||||
{
|
||||
int field = bytecode[i];
|
||||
printf("STORE_FIELD_THIS %d\n", field);
|
||||
PRINT_ARG("field %d\n", field);
|
||||
break;
|
||||
}
|
||||
|
||||
case CODE_LOAD_FIELD:
|
||||
{
|
||||
int field = bytecode[i];
|
||||
printf("LOAD_FIELD %d\n", field);
|
||||
PRINT_ARG("field %d\n", field);
|
||||
break;
|
||||
}
|
||||
|
||||
case CODE_STORE_FIELD:
|
||||
{
|
||||
int field = bytecode[i];
|
||||
printf("STORE_FIELD %d\n", field);
|
||||
PRINT_ARG("field %d\n", field);
|
||||
break;
|
||||
}
|
||||
case CODE_LOAD_FIELD_THIS: BYTE_INSTRUCTION("LOAD_FIELD_THIS");
|
||||
case CODE_STORE_FIELD_THIS: BYTE_INSTRUCTION("STORE_FIELD_THIS");
|
||||
case CODE_LOAD_FIELD: BYTE_INSTRUCTION("LOAD_FIELD");
|
||||
case CODE_STORE_FIELD: BYTE_INSTRUCTION("STORE_FIELD");
|
||||
|
||||
case CODE_POP: printf("POP\n"); break;
|
||||
|
||||
@ -172,10 +114,9 @@ static int debugPrintInstruction(WrenVM* vm, ObjFn* fn, int i, int* lastLine)
|
||||
case CODE_CALL_16:
|
||||
{
|
||||
int numArgs = bytecode[i - 1] - CODE_CALL_0;
|
||||
int symbol = (bytecode[i] << 8) | bytecode[i + 1];
|
||||
printf("CALL_%d \"%s\"\n", numArgs, vm->methods.names.data[symbol]);
|
||||
PRINT_ARG("symbol %d\n", symbol);
|
||||
PRINT_ARG("\n");
|
||||
int symbol = READ_SHORT();
|
||||
printf("CALL_%-11d %5d '%s'\n", numArgs, symbol,
|
||||
vm->methods.names.data[symbol]);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -198,50 +139,44 @@ static int debugPrintInstruction(WrenVM* vm, ObjFn* fn, int i, int* lastLine)
|
||||
case CODE_SUPER_16:
|
||||
{
|
||||
int numArgs = bytecode[i - 1] - CODE_SUPER_0;
|
||||
int symbol = (bytecode[i] << 8) | bytecode[i + 1];
|
||||
printf("SUPER_%d \"%s\"\n", numArgs, vm->methods.names.data[symbol]);
|
||||
PRINT_ARG("symbol %d\n", symbol);
|
||||
PRINT_ARG("\n");
|
||||
int symbol = READ_SHORT();
|
||||
printf("SUPER_%-10d %5d '%s'\n", numArgs, symbol,
|
||||
vm->methods.names.data[symbol]);
|
||||
break;
|
||||
}
|
||||
|
||||
case CODE_JUMP:
|
||||
{
|
||||
int offset = bytecode[i];
|
||||
printf("JUMP %d\n", offset);
|
||||
PRINT_ARG("offset %d\n", offset);
|
||||
int offset = READ_SHORT();
|
||||
printf("%-16s %5d to %d\n", "JUMP", offset, i + offset);
|
||||
break;
|
||||
}
|
||||
|
||||
case CODE_LOOP:
|
||||
{
|
||||
int offset = bytecode[i];
|
||||
printf("LOOP %d\n", offset);
|
||||
PRINT_ARG("offset -%d\n", offset);
|
||||
int offset = READ_SHORT();
|
||||
printf("%-16s %5d to %d\n", "LOOP", offset, i - offset);
|
||||
break;
|
||||
}
|
||||
|
||||
case CODE_JUMP_IF:
|
||||
{
|
||||
int offset = bytecode[i];
|
||||
printf("JUMP_IF %d\n", offset);
|
||||
PRINT_ARG("offset %d\n", offset);
|
||||
int offset = READ_SHORT();
|
||||
printf("%-16s %5d to %d\n", "JUMP_IF", offset, i + offset);
|
||||
break;
|
||||
}
|
||||
|
||||
case CODE_AND:
|
||||
{
|
||||
int offset = bytecode[i];
|
||||
printf("AND %d\n", offset);
|
||||
PRINT_ARG("offset %d\n", offset);
|
||||
int offset = READ_SHORT();
|
||||
printf("%-16s %5d to %d\n", "AND", offset, i + offset);
|
||||
break;
|
||||
}
|
||||
|
||||
case CODE_OR:
|
||||
{
|
||||
int offset = bytecode[i];
|
||||
printf("OR %d\n", offset);
|
||||
PRINT_ARG("offset %d\n", offset);
|
||||
int offset = READ_SHORT();
|
||||
printf("%-16s %5d to %d\n", "OR", offset, i + offset);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -252,62 +187,49 @@ static int debugPrintInstruction(WrenVM* vm, ObjFn* fn, int i, int* lastLine)
|
||||
|
||||
case CODE_LIST:
|
||||
{
|
||||
int count = bytecode[i];
|
||||
printf("LIST\n");
|
||||
PRINT_ARG("count %d\n", count);
|
||||
int length = READ_BYTE();
|
||||
printf("%-16s %5d length\n", "LIST", length);
|
||||
break;
|
||||
}
|
||||
|
||||
case CODE_CLOSURE:
|
||||
{
|
||||
int constant = (bytecode[i] << 8) | bytecode[i + 1];
|
||||
printf("CLOSURE ");
|
||||
int constant = READ_SHORT();
|
||||
printf("%-16s %5d ", "CLOSURE", constant);
|
||||
wrenPrintValue(fn->constants[constant]);
|
||||
printf("\n");
|
||||
PRINT_ARG("constant %d\n", constant);
|
||||
PRINT_ARG("\n");
|
||||
printf(" ");
|
||||
ObjFn* loadedFn = AS_FN(fn->constants[constant]);
|
||||
for (int j = 0; j < loadedFn->numUpvalues; j++)
|
||||
{
|
||||
int isLocal = bytecode[i];
|
||||
PRINT_ARG("upvalue %d isLocal %d\n", j, isLocal);
|
||||
int index = bytecode[i];
|
||||
PRINT_ARG("upvalue %d index %d\n", j, index);
|
||||
int isLocal = READ_BYTE();
|
||||
int index = READ_BYTE();
|
||||
if (j > 0) printf(", ");
|
||||
printf("%s %d", isLocal ? "local" : "upvalue", index);
|
||||
}
|
||||
printf("\n");
|
||||
break;
|
||||
}
|
||||
|
||||
case CODE_CLASS:
|
||||
{
|
||||
int numFields = bytecode[i];
|
||||
printf("CLASS\n");
|
||||
PRINT_ARG("num fields %d\n", numFields);
|
||||
break;
|
||||
}
|
||||
|
||||
case CODE_SUBCLASS:
|
||||
{
|
||||
int numFields = bytecode[i];
|
||||
printf("SUBCLASS\n");
|
||||
PRINT_ARG("num fields %d\n", numFields);
|
||||
int numFields = READ_BYTE();
|
||||
printf("%-16s %5d fields\n", "CLASS", numFields);
|
||||
break;
|
||||
}
|
||||
|
||||
case CODE_METHOD_INSTANCE:
|
||||
{
|
||||
int symbol = (bytecode[i] << 8) | bytecode[i + 1];
|
||||
printf("METHOD_INSTANCE \"%s\"\n", vm->methods.names.data[symbol]);
|
||||
PRINT_ARG("symbol %d\n", symbol);
|
||||
PRINT_ARG("\n");
|
||||
int symbol = READ_SHORT();
|
||||
printf("%-16s %5d '%s'\n", "METHOD_INSTANCE", symbol,
|
||||
vm->methods.names.data[symbol]);
|
||||
break;
|
||||
}
|
||||
|
||||
case CODE_METHOD_STATIC:
|
||||
{
|
||||
int symbol = (bytecode[i] << 8) | bytecode[i + 1];
|
||||
printf("METHOD_STATIC \"%s\"\n", vm->methods.names.data[symbol]);
|
||||
PRINT_ARG("symbol %d\n", symbol);
|
||||
PRINT_ARG("\n");
|
||||
int symbol = READ_SHORT();
|
||||
printf("%-16s %5d '%s'\n", "METHOD_STATIC", symbol,
|
||||
vm->methods.names.data[symbol]);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@ -476,7 +476,6 @@ static bool runInterpreter(WrenVM* vm)
|
||||
&&code_LIST,
|
||||
&&code_CLOSURE,
|
||||
&&code_CLASS,
|
||||
&&code_SUBCLASS,
|
||||
&&code_METHOD_INSTANCE,
|
||||
&&code_METHOD_STATIC,
|
||||
&&code_END
|
||||
@ -971,22 +970,20 @@ static bool runInterpreter(WrenVM* vm)
|
||||
}
|
||||
|
||||
CASE_CODE(CLASS):
|
||||
CASE_CODE(SUBCLASS):
|
||||
{
|
||||
bool isSubclass = instruction == CODE_SUBCLASS;
|
||||
int numFields = READ_BYTE();
|
||||
|
||||
ObjClass* superclass;
|
||||
if (isSubclass)
|
||||
{
|
||||
// TODO: Handle the superclass not being a class object!
|
||||
superclass = AS_CLASS(PEEK());
|
||||
}
|
||||
else
|
||||
if (IS_NULL(PEEK()))
|
||||
{
|
||||
// Implicit Object superclass.
|
||||
superclass = vm->objectClass;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Handle the superclass not being a class object!
|
||||
superclass = AS_CLASS(PEEK());
|
||||
}
|
||||
|
||||
ObjClass* classObj = wrenNewClass(vm, superclass, numFields);
|
||||
|
||||
@ -1001,7 +998,7 @@ static bool runInterpreter(WrenVM* vm)
|
||||
|
||||
// Don't pop the superclass off the stack until the subclass is done
|
||||
// being created, to make sure it doesn't get collected.
|
||||
if (isSubclass) POP();
|
||||
POP();
|
||||
|
||||
PUSH(OBJ_VAL(classObj));
|
||||
DISPATCH();
|
||||
|
||||
@ -151,9 +151,6 @@ typedef enum
|
||||
// Define a new empty class and push it.
|
||||
CODE_CLASS,
|
||||
|
||||
// Pop a superclass off the stack, then push a new class that extends it.
|
||||
CODE_SUBCLASS,
|
||||
|
||||
// Define a method for symbol [arg]. The class receiving the method is popped
|
||||
// off the stack, then the function defining the body is popped.
|
||||
CODE_METHOD_INSTANCE,
|
||||
@ -162,7 +159,7 @@ typedef enum
|
||||
// the method is popped off the stack, then the function defining the body is
|
||||
// popped.
|
||||
CODE_METHOD_STATIC,
|
||||
|
||||
|
||||
// This pseudo-instruction indicates the end of the bytecode. It should
|
||||
// always be preceded by a `CODE_RETURN`, so is never actually executed.
|
||||
CODE_END
|
||||
|
||||
Reference in New Issue
Block a user