Add IO class.
With io.write(), can start writing tests now.
This commit is contained in:
+2
-2
@@ -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
@@ -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
@@ -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");
|
||||
}
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user