Map literals!

This commit is contained in:
Bob Nystrom
2015-01-24 23:21:50 -08:00
parent abe80e6d4b
commit e740a4c95a
12 changed files with 83 additions and 20 deletions
+54 -2
View File
@@ -1315,7 +1315,8 @@ typedef enum
PREC_TERM, // + -
PREC_FACTOR, // * / %
PREC_UNARY, // unary - ! ~
PREC_CALL // . () []
PREC_CALL, // . () []
PREC_PRIMARY
} Precedence;
typedef void (*GrammarFn)(Compiler*, bool allowAssignment);
@@ -1574,12 +1575,14 @@ static void loadThis(Compiler* compiler)
}
}
// A parenthesized expression.
static void grouping(Compiler* compiler, bool allowAssignment)
{
expression(compiler);
consume(compiler, TOKEN_RIGHT_PAREN, "Expect ')' after expression.");
}
// A list literal.
static void list(Compiler* compiler, bool allowAssignment)
{
// Compile the list elements.
@@ -1603,6 +1606,54 @@ static void list(Compiler* compiler, bool allowAssignment)
emitByteArg(compiler, CODE_LIST, numElements);
}
// A map literal.
static void map(Compiler* compiler, bool allowAssignment)
{
// TODO: Do we want to do the same thing for list literals and remove the
// bytecodes for them?
// Load the Map class.
int mapClassSymbol = wrenSymbolTableFind(&compiler->parser->vm->globalNames,
"Map", 3);
ASSERT(mapClassSymbol != -1, "Should have already defined 'Map' global.");
emitShortArg(compiler, CODE_LOAD_GLOBAL, mapClassSymbol);
// Instantiate a new map.
emitShortArg(compiler, CODE_CALL_0,
methodSymbol(compiler, " instantiate", 12));
int subscriptSetSymbol = methodSymbol(compiler, "[ ]=", 4);
// Compile the map elements. Each one is compiled to just invoke the
// subscript setter on the map.
if (peek(compiler) != TOKEN_RIGHT_BRACE)
{
do
{
ignoreNewlines(compiler);
// Push a copy of the map since the subscript call will consume it.
emit(compiler, CODE_DUP);
// The key.
parsePrecedence(compiler, false, PREC_PRIMARY);
consume(compiler, TOKEN_COLON, "Expect ':' after map key.");
// The value.
expression(compiler);
emitShortArg(compiler, CODE_CALL_2, subscriptSetSymbol);
// Discard the result of the setter call.
emit(compiler, CODE_POP);
} while (match(compiler, TOKEN_COMMA));
}
// Allow newlines before the closing '}'.
ignoreNewlines(compiler);
consume(compiler, TOKEN_RIGHT_BRACE, "Expect '}' after map entries.");
}
// Unary operators like `-foo`.
static void unaryOp(Compiler* compiler, bool allowAssignment)
{
@@ -2174,7 +2225,7 @@ GrammarRule rules[] =
/* TOKEN_RIGHT_PAREN */ UNUSED,
/* TOKEN_LEFT_BRACKET */ { list, subscript, subscriptSignature, PREC_CALL, NULL },
/* TOKEN_RIGHT_BRACKET */ UNUSED,
/* TOKEN_LEFT_BRACE */ UNUSED,
/* TOKEN_LEFT_BRACE */ PREFIX(map),
/* TOKEN_RIGHT_BRACE */ UNUSED,
/* TOKEN_COLON */ UNUSED,
/* TOKEN_DOT */ INFIX(PREC_CALL, call),
@@ -2297,6 +2348,7 @@ static int getNumArguments(const uint8_t* bytecode, const Value* constants,
case CODE_FALSE:
case CODE_TRUE:
case CODE_POP:
case CODE_DUP:
case CODE_IS:
case CODE_CLOSE_UPVALUE:
case CODE_RETURN:
+1
View File
@@ -110,6 +110,7 @@ static int debugPrintInstruction(WrenVM* vm, ObjFn* fn, int i, int* lastLine)
case CODE_STORE_FIELD: BYTE_INSTRUCTION("STORE_FIELD");
case CODE_POP: printf("POP\n"); break;
case CODE_DUP: printf("DUP\n"); break;
case CODE_CALL_0:
case CODE_CALL_1:
+3
View File
@@ -450,6 +450,7 @@ static bool runInterpreter(WrenVM* vm)
&&code_LOAD_FIELD,
&&code_STORE_FIELD,
&&code_POP,
&&code_DUP,
&&code_CALL_0,
&&code_CALL_1,
&&code_CALL_2,
@@ -559,6 +560,8 @@ static bool runInterpreter(WrenVM* vm)
}
CASE_CODE(POP): DROP(); DISPATCH();
CASE_CODE(DUP): PUSH(PEEK()); DISPATCH();
CASE_CODE(NULL): PUSH(NULL_VAL); DISPATCH();
CASE_CODE(FALSE): PUSH(FALSE_VAL); DISPATCH();
CASE_CODE(TRUE): PUSH(TRUE_VAL); DISPATCH();
+3
View File
@@ -77,6 +77,9 @@ typedef enum
// Pop and discard the top of stack.
CODE_POP,
// Push a copy of the value currently on the top of the stack.
CODE_DUP,
// Invoke the method with symbol [arg]. The number indicates the number of
// arguments (not including the receiver).
CODE_CALL_0,