Add IO class.

With io.write(), can start writing tests now.
This commit is contained in:
Bob Nystrom
2013-10-27 22:45:40 -07:00
parent ca445412b8
commit 95fb0863d9
7 changed files with 228 additions and 45 deletions
+2 -2
View File
@@ -268,8 +268,8 @@ int defineName(Compiler* compiler)
}
int symbol = addSymbol(symbols,
compiler->parser->source + compiler->parser->previous.start,
compiler->parser->previous.end - compiler->parser->previous.start);
compiler->parser->source + compiler->parser->previous.start,
compiler->parser->previous.end - compiler->parser->previous.start);
if (symbol == -1)
{
+1 -3
View File
@@ -30,9 +30,7 @@ int main(int argc, const char * argv[])
if (block)
{
Value value = interpret(vm, block);
printValue(value);
printf("\n");
interpret(vm, block);
}
freeVM(vm);
+29 -10
View File
@@ -1,3 +1,4 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -6,14 +7,21 @@
#define PRIMITIVE(cls, name, prim) \
{ \
int symbol = ensureSymbol(&vm->symbols, name, strlen(name)); \
vm->cls##Class->methods[symbol].type = METHOD_PRIMITIVE; \
vm->cls##Class->methods[symbol].primitive = primitive_##cls##_##prim; \
cls->methods[symbol].type = METHOD_PRIMITIVE; \
cls->methods[symbol].primitive = primitive_##prim; \
}
#define DEF_PRIMITIVE(cls, prim) \
static Value primitive_##cls##_##prim(Value* args, int numArgs)
#define DEF_PRIMITIVE(prim) \
static Value primitive_##prim(Value* args, int numArgs)
DEF_PRIMITIVE(num, abs)
#define GLOBAL(cls, name) \
{ \
ObjInstance* obj = makeInstance(cls); \
int symbol = addSymbol(&vm->globalSymbols, name, strlen(name)); \
vm->globals[symbol] = (Value)obj; \
}
DEF_PRIMITIVE(num_abs)
{
double value = ((ObjNum*)args[0])->value;
if (value < 0) value = -value;
@@ -21,7 +29,7 @@ DEF_PRIMITIVE(num, abs)
return (Value)makeNum(value);
}
DEF_PRIMITIVE(string, contains)
DEF_PRIMITIVE(string_contains)
{
const char* string = ((ObjString*)args[0])->value;
// TODO(bob): Check type of arg first!
@@ -31,16 +39,27 @@ DEF_PRIMITIVE(string, contains)
return (Value)makeNum(strstr(string, search) != NULL);
}
DEF_PRIMITIVE(string, count)
DEF_PRIMITIVE(string_count)
{
double count = strlen(((ObjString*)args[0])->value);
return (Value)makeNum(count);
}
DEF_PRIMITIVE(io_write)
{
printValue(args[1]);
printf("\n");
return args[1];
}
void registerPrimitives(VM* vm)
{
PRIMITIVE(num, "abs", abs);
PRIMITIVE(string, "contains ", contains);
PRIMITIVE(string, "count", count);
PRIMITIVE(vm->numClass, "abs", num_abs);
PRIMITIVE(vm->stringClass, "contains ", string_contains);
PRIMITIVE(vm->stringClass, "count", string_count);
ObjClass* ioClass = makeClass();
PRIMITIVE(ioClass, "write ", io_write);
GLOBAL(ioClass, "io");
}
+2 -30
View File
@@ -200,9 +200,6 @@ Value interpret(VM* vm, ObjBlock* block)
int constant = frame->block->bytecode[frame->ip++];
Value value = frame->block->constants[constant];
fiber.stack[fiber.stackSize++] = value;
printf("load constant ");
printValue(value);
printf(" to %d\n", fiber.stackSize - 1);
break;
}
@@ -213,13 +210,11 @@ Value interpret(VM* vm, ObjBlock* block)
// Define a "new" method on the metaclass.
// TODO(bob): Can this be inherited?
int newSymbol = ensureSymbol(&vm->symbols, "new", strlen("new"));
printf("define new %d\n", newSymbol);
classObj->metaclass->methods[newSymbol].type = METHOD_PRIMITIVE;
classObj->metaclass->methods[newSymbol].primitive =
primitive_metaclass_new;
push(&fiber, (Value)classObj);
printf("push class at %d\n", fiber.stackSize - 1);
break;
}
@@ -232,10 +227,6 @@ Value interpret(VM* vm, ObjBlock* block)
ObjBlock* body = (ObjBlock*)frame->block->constants[constant];
classObj->methods[symbol].type = METHOD_BLOCK;
classObj->methods[symbol].block = body;
printf("define method %d using constant %d on ", symbol, constant);
printValue((Value)classObj);
printf("\n");
break;
}
@@ -243,14 +234,12 @@ Value interpret(VM* vm, ObjBlock* block)
{
int local = frame->block->bytecode[frame->ip++];
push(&fiber, fiber.stack[frame->locals + local]);
printf("load local %d to %d\n", local, fiber.stackSize - 1);
break;
}
case CODE_STORE_LOCAL:
{
int local = frame->block->bytecode[frame->ip++];
printf("store local %d from %d\n", local, fiber.stackSize - 1);
fiber.stack[frame->locals + local] = fiber.stack[fiber.stackSize - 1];
break;
}
@@ -259,25 +248,21 @@ Value interpret(VM* vm, ObjBlock* block)
{
int global = frame->block->bytecode[frame->ip++];
push(&fiber, vm->globals[global]);
printf("load global %d to %d\n", global, fiber.stackSize - 1);
break;
}
case CODE_STORE_GLOBAL:
{
int global = frame->block->bytecode[frame->ip++];
printf("store global %d from %d\n", global, fiber.stackSize - 1);
vm->globals[global] = fiber.stack[fiber.stackSize - 1];
break;
}
case CODE_DUP:
push(&fiber, fiber.stack[fiber.stackSize - 1]);
printf("dup %d\n", fiber.stackSize - 1);
break;
case CODE_POP:
printf("pop %d\n", fiber.stackSize - 1);
pop(&fiber);
break;
@@ -323,10 +308,6 @@ Value interpret(VM* vm, ObjBlock* block)
break;
}
printf("call %d on ", symbol);
printValue(receiver);
printf("\n");
Method* method = &classObj->methods[symbol];
switch (method->type)
{
@@ -363,19 +344,10 @@ Value interpret(VM* vm, ObjBlock* block)
fiber.numFrames--;
// If we are returning from the top-level block, just return the value.
if (fiber.numFrames == 0)
{
printf("done with result ");
printValue(result);
printf("\n");
return result;
}
if (fiber.numFrames == 0) return result;
// Store the result of the block in the first slot, which is where the
// caller expects it.
printf("return and store result ");
printValue(result);
printf(" in %d\n", frame->locals);
fiber.stack[frame->locals] = result;
// Discard the stack slots for the locals.
@@ -391,7 +363,7 @@ void printValue(Value value)
switch (value->type)
{
case OBJ_NUM:
printf("%f", ((ObjNum*)value)->value);
printf("%g", ((ObjNum*)value)->value);
break;
case OBJ_STRING: