New: dictionary literals in Objective-J 2.0.

This commit is contained in:
Alexander Ljungberg
2013-02-25 14:24:29 +00:00
parent a736bb4e93
commit 5200f945fe
5 changed files with 106 additions and 3 deletions
+29
View File
@@ -774,6 +774,35 @@ Identifier: function(node, st, c) {
}
}
},
DictionaryLiteral: function(node, st, c) {
CONCAT(st.compiler.jsBuffer, st.compiler.source.substring(st.compiler.lastPos, node.start));
st.compiler.lastPos = node.start;
if (!node.keys.length) {
CONCAT(st.compiler.jsBuffer, "objj_msgSend(objj_msgSend(CPDictionary, \"alloc\"), \"init\")");
} else {
CONCAT(st.compiler.jsBuffer, "objj_msgSend(objj_msgSend(CPDictionary, \"alloc\"), \"initWithObjectsAndKeys:\"");
for (var i = 0; i < node.keys.length; i++) {
var key = node.keys[i],
value = node.values[i];
CONCAT(st.compiler.jsBuffer, ", ");
st.compiler.lastPos = value.start;
c(value, st, "Expression");
CONCAT(st.compiler.jsBuffer, st.compiler.source.substring(st.compiler.lastPos, value.end));
CONCAT(st.compiler.jsBuffer, ", ");
st.compiler.lastPos = key.start;
c(key, st, "Expression");
CONCAT(st.compiler.jsBuffer, st.compiler.source.substring(st.compiler.lastPos, key.end));
}
CONCAT(st.compiler.jsBuffer, ")");
}
st.compiler.lastPos = node.end;
},
SelectorLiteralExpression: function(node, st, c) {
CONCAT(st.compiler.jsBuffer, st.compiler.source.substring(st.compiler.lastPos, node.start));
CONCAT(st.compiler.jsBuffer, "sel_getUid(\"");
+33
View File
@@ -273,6 +273,7 @@ if (!exports.acorn) {
var _implementation = {keyword: "implementation"}, _outlet = {keyword: "outlet"}, _accessors = {keyword: "accessors"};
var _end = {keyword: "end"}, _import = {keyword: "import", afterImport: true};
var _action = {keyword: "action"}, _selector = {keyword: "selector"}, _class = {keyword: "class"}, _global = {keyword: "global"};
var _dictionaryLiteral = {keyword: "{"};
// Objective-J keywords
@@ -660,6 +661,9 @@ if (!exports.acorn) {
var next = input.charCodeAt(++tokPos);
if (next === 34 || next === 39) // Read string if "'" or '"'
return readString(next);
if (next === 123) // Read dictionary literal if "{"
return finishToken(_dictionaryLiteral);
var word = readWord1(),
token = objJAtKeywordTypes[word];
if (!token) raise(tokStart, "Unrecognized Objective-J keyword '@" + word + "'");
@@ -1878,6 +1882,15 @@ if (!exports.acorn) {
node.elements = parseExprList(_bracketR, firstExpr, true, true);
return finishNode(node, "ArrayExpression");
case _dictionaryLiteral:
var node = startNode();
next();
var r = parseDictionary();
node.keys = r[0];
node.values = r[1];
return finishNode(node, "DictionaryLiteral");
case _braceL:
return parseObj();
@@ -2088,6 +2101,26 @@ if (!exports.acorn) {
return elts;
}
// Parses a comma-separated list of <key>:<value> pairs and returns them as
// [arrayOfKeyExpressions, arrayOfValueExpressions].
function parseDictionary() {
expect(_braceL, "Expected '{' before dictionary");
var keys = [], values = [], first = true;
while (!eat(_braceR)) {
if (!first) {
expect(_comma, "Expected ',' between expressions");
if (options.allowTrailingCommas && eat(_braceR)) break;
}
keys.push(parseExpression(true, true));
expect(_colon, "Expected ':' between dictionary key and value");
values.push(parseExpression(true, true));
first = false;
}
return [keys, values];
}
// Parse the next token as an identifier. If `liberal` is true (used
// when parsing properties), it will also convert keywords into
// identifiers.
+9 -1
View File
@@ -155,6 +155,14 @@ if (!exports.acorn) {
if (elt) c(elt, st, "Expression");
}
};
exports.DictionaryLiteral = function(node, st, c) {
for (var i = 0; i < node.keys.length; i++) {
var key = node.keys[i];
c(key, st, "Expression");
var value = node.values[i];
c(value, st, "Expression");
}
};
exports.ObjectExpression = function(node, st, c) {
for (var i = 0; i < node.properties.length; ++i)
c(node.properties[i].value, st, "Expression");
@@ -195,7 +203,7 @@ if (!exports.acorn) {
c(node.body[i], st, "Statement");
}
}
exports.ImportStatement = ignore;
exports.IvarDeclaration = ignore;
+34 -1
View File
@@ -1,5 +1,7 @@
@import <Foundation/CPDictionary.j>
@import <OJUnit/OJTestCase.j>
@implementation CPDictionaryTest : OJTestCase
{
CPDictionary string_dict;
@@ -403,9 +405,40 @@
{
var dict = [[CPDictionary alloc] initWithObjectsAndKeys:@"Value1", @"Key1", nil, @"Key2", @"Value3", @"Key3"];
[self assert:2 equals:[dict count]];
[self assert:2 equals:[dict count]];
[self assert:@"Value1" equals:[dict objectForKey:@"Key1"]];
[self assert:nil equals:[dict objectForKey:@"Key2"]]; // No key/value pair
[self assert:@"Value3" equals:[dict objectForKey:@"Key3"]];
}
- (void)testDictionaryLiteral
{
var dict = @{
@"Key1": @"Value1",
@"Key2": [CPNull null],
@"Key3": 2
};
[self assert:3 equals:[dict count]];
[self assert:@"Value1" equals:[dict objectForKey:@"Key1"]];
[self assert:[CPNull null] same:[dict objectForKey:@"Key2"]];
[self assert:2 equals:[dict objectForKey:@"Key3"]];
}
- (void)testDictionaryLiteralExpressions
{
var aKey = @"aKey",
aValue = 5,
dict = @{
@"Key" + 1: @"Value" + 1,
@"Key2": NO ? 1 : 2,
aKey: aValue, // trailing comma is allowed
};
[self assert:3 equals:[dict count]];
[self assert:@"Value1" equals:[dict objectForKey:@"Key1"]];
[self assert:2 equals:[dict objectForKey:@"Key2"]];
[self assert:5 equals:[dict objectForKey:@"aKey"]];
}
@end
+1 -1
View File
@@ -20,7 +20,7 @@
{
var dict = new CFMutableDictionary();
[self assert:0 equals:dict.countOfValue(@"123")];
dict.setValueForKey(@"abc", @"123");
[self assert:1 equals:dict.countOfValue(@"123")];