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: