mirror of
https://github.com/wren-lang/wren.git
synced 2026-01-10 21:58:48 +01:00
Make blocks callable.
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
{
|
||||
123
|
||||
var a = {
|
||||
var b = 234
|
||||
3
|
||||
b
|
||||
}
|
||||
var a = 123
|
||||
var b = 345
|
||||
a
|
||||
a.call
|
||||
|
||||
@ -110,8 +110,15 @@ static void consume(Compiler* compiler, TokenType expected);
|
||||
static void advance(Parser* parser);
|
||||
|
||||
// Tokens:
|
||||
|
||||
// Lex the next token in the source file and store it in parser.current. Omits
|
||||
// newlines that aren't meaningful.
|
||||
static void readNextToken(Parser* parser);
|
||||
|
||||
// Lex the next token and store it in parser.current. Does not do any newline
|
||||
// filtering.
|
||||
static void readRawToken(Parser* parser);
|
||||
|
||||
static void readName(Parser* parser);
|
||||
static void readNumber(Parser* parser);
|
||||
static void readString(Parser* parser);
|
||||
|
||||
11
src/main.c
11
src/main.c
@ -27,9 +27,14 @@ int main(int argc, const char * argv[])
|
||||
char* source = readFile(argv[1], &length);
|
||||
VM* vm = newVM();
|
||||
ObjBlock* block = compile(vm, source, length);
|
||||
Value value = interpret(vm, block);
|
||||
printValue(value);
|
||||
printf("\n");
|
||||
|
||||
if (block)
|
||||
{
|
||||
Value value = interpret(vm, block);
|
||||
printValue(value);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
freeVM(vm);
|
||||
free(source);
|
||||
|
||||
|
||||
48
src/vm.c
48
src/vm.c
@ -4,6 +4,13 @@
|
||||
|
||||
#include "vm.h"
|
||||
|
||||
#define PRIMITIVE(cls, prim) \
|
||||
{ \
|
||||
int symbol = ensureSymbol(&vm->symbols, #prim, strlen(#prim)); \
|
||||
vm->cls##Class->methods[symbol].type = METHOD_PRIMITIVE; \
|
||||
vm->cls##Class->methods[symbol].primitive = primitive_##cls##_##prim; \
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// Index of the current (really next-to-be-executed) instruction in the
|
||||
@ -29,17 +36,26 @@ typedef struct
|
||||
static void callBlock(Fiber* fiber, ObjBlock* block, int firstLocal);
|
||||
static void push(Fiber* fiber, Value value);
|
||||
static Value pop(Fiber* fiber);
|
||||
static Value primitiveNumAbs(Value number);
|
||||
static Value primitive_num_abs(Value block);
|
||||
|
||||
VM* newVM()
|
||||
{
|
||||
VM* vm = malloc(sizeof(VM));
|
||||
initSymbolTable(&vm->symbols);
|
||||
|
||||
vm->blockClass = makeClass();
|
||||
|
||||
// The call method is special: neither a primitive nor a user-defined one.
|
||||
// This is because it mucks with the fiber itself.
|
||||
{
|
||||
int symbol = ensureSymbol(&vm->symbols, "call", strlen("call"));
|
||||
vm->blockClass->methods[symbol].type = METHOD_CALL;
|
||||
}
|
||||
|
||||
vm->classClass = makeClass();
|
||||
|
||||
vm->numClass = makeClass();
|
||||
int symbol = ensureSymbol(&vm->symbols, "abs", 3);
|
||||
vm->numClass->methods[symbol].type = METHOD_PRIMITIVE;
|
||||
vm->numClass->methods[symbol].primitive = primitiveNumAbs;
|
||||
PRIMITIVE(num, abs);
|
||||
|
||||
return vm;
|
||||
}
|
||||
@ -198,7 +214,22 @@ Value interpret(VM* vm, ObjBlock* block)
|
||||
int symbol = frame->block->bytecode[frame->ip++];
|
||||
|
||||
// TODO(bob): Support classes for other object types.
|
||||
ObjClass* classObj = vm->numClass;
|
||||
ObjClass* classObj;
|
||||
switch (receiver->type)
|
||||
{
|
||||
case OBJ_BLOCK:
|
||||
classObj = vm->blockClass;
|
||||
break;
|
||||
|
||||
case OBJ_CLASS:
|
||||
classObj = vm->classClass;
|
||||
break;
|
||||
|
||||
case OBJ_NUM:
|
||||
classObj = vm->numClass;
|
||||
break;
|
||||
}
|
||||
|
||||
Method* method = &classObj->methods[symbol];
|
||||
switch (method->type)
|
||||
{
|
||||
@ -208,6 +239,11 @@ Value interpret(VM* vm, ObjBlock* block)
|
||||
exit(1);
|
||||
break;
|
||||
|
||||
case METHOD_CALL:
|
||||
// TODO(bob): Should pass in correct index for locals.
|
||||
callBlock(&fiber, (ObjBlock*)receiver, fiber.stackSize);
|
||||
break;
|
||||
|
||||
case METHOD_PRIMITIVE:
|
||||
push(&fiber, method->primitive(receiver));
|
||||
break;
|
||||
@ -282,7 +318,7 @@ Value pop(Fiber* fiber)
|
||||
return fiber->stack[--fiber->stackSize];
|
||||
}
|
||||
|
||||
Value primitiveNumAbs(Value number)
|
||||
Value primitive_num_abs(Value number)
|
||||
{
|
||||
double value = ((ObjNum*)number)->value;
|
||||
if (value < 0) value = -value;
|
||||
|
||||
4
src/vm.h
4
src/vm.h
@ -46,6 +46,7 @@ typedef Value (*Primitive)(Value receiver);
|
||||
typedef enum
|
||||
{
|
||||
METHOD_NONE,
|
||||
METHOD_CALL,
|
||||
METHOD_PRIMITIVE,
|
||||
METHOD_BLOCK
|
||||
} MethodType;
|
||||
@ -105,6 +106,9 @@ typedef struct
|
||||
typedef struct
|
||||
{
|
||||
SymbolTable symbols;
|
||||
|
||||
ObjClass* blockClass;
|
||||
ObjClass* classClass;
|
||||
ObjClass* numClass;
|
||||
} VM;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user