_assert(false);
}
-void Pointer::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const {
- *reinterpret_cast<void **>(data) = CYCastPointer<void *>(context, value);
-}
-
-void Array::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const {
- uint8_t *base(reinterpret_cast<uint8_t *>(data));
- JSObjectRef aggregate(JSValueIsObject(context, value) ? (JSObjectRef) value : NULL);
- for (size_t index(0); index != size; ++index) {
- ffi_type *field(ffi->elements[index]);
-
+static void CYArrayCopy(CYPool *pool, JSContextRef context, uint8_t *base, size_t length, const sig::Type &type, ffi_type *ffi, JSValueRef value, JSObjectRef object) {
+ for (size_t index(0); index != length; ++index) {
JSValueRef rhs;
- if (aggregate == NULL)
+ if (object == NULL)
rhs = value;
else {
- rhs = CYGetProperty(context, aggregate, index);
+ rhs = CYGetProperty(context, object, index);
if (JSValueIsUndefined(context, rhs))
throw CYJSError(context, "unable to extract array value");
}
- type.PoolFFI(pool, context, field, base, rhs);
- base += field->size;
+ type.PoolFFI(pool, context, ffi, base, rhs);
+ base += ffi->size;
}
}
+void Pointer::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const {
+ bool guess(false);
+ *reinterpret_cast<void **>(data) = CYCastPointer<void *>(context, value, &guess);
+ if (!guess || pool == NULL || !JSValueIsObject(context, value))
+ return;
+ JSObjectRef object(CYCastJSObject(context, value));
+ if (CYHasProperty(context, object, length_s)) {
+ size_t length(CYArrayLength(context, object));
+ ffi_type *element(type.GetFFI(*pool));
+ size_t size(element->size * length);
+ uint8_t *base(pool->malloc<uint8_t>(size, element->alignment));
+ CYArrayCopy(pool, context, base, length, type, element, value, object);
+ *reinterpret_cast<void **>(data) = base;
+ }
+}
+
+void Array::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const {
+ if (size == 0)
+ return;
+ uint8_t *base(reinterpret_cast<uint8_t *>(data));
+ JSObjectRef object(JSValueIsObject(context, value) ? (JSObjectRef) value : NULL);
+ CYArrayCopy(pool, context, base, size, type, ffi->elements[0], value, object);
+}
+
void Aggregate::PoolFFI(CYPool *pool, JSContextRef context, ffi_type *ffi, void *data, JSValueRef value) const {
_assert(!overlap);
value_->Output(out, Precedence(), CYRight(flags));
}
+void CYObjCArray::Output(CYOutput &out, CYFlags flags) const {
+ out << '@' << '[' << elements_ << ']';
+}
+
+void CYObjCDictionary::Output(CYOutput &out, CYFlags flags) const {
+ out << '@' << '{' << '}';
+}
+
void CYObjCBlock::Output(CYOutput &out, CYFlags flags) const {
out << '^' << ' ' << *typed_ << ' ' << '(';
return $C1($M($V("Instance"), $S("box")), value_);
}
+CYTarget *CYObjCArray::Replace(CYContext &context) {
+ size_t count(0);
+ CYForEach (element, elements_)
+ ++count;
+ return $ CYSendDirect($V("NSArray"), $C_($ CYWord("arrayWithObjects"), $ CYArray(elements_), $C_($ CYWord("count"), $D(count))));
+}
+
+CYTarget *CYObjCDictionary::Replace(CYContext &context) {
+ CYList<CYElement> keys;
+ CYList<CYElement> values;
+ size_t count(0);
+
+ CYForEach (pair, pairs_) {
+ keys->*$ CYElementValue(pair->key_);
+ values->*$ CYElementValue(pair->value_);
+ ++count;
+ }
+
+ return $ CYSendDirect($V("NSDictionary"), $C_($ CYWord("dictionaryWithObjects"), $ CYArray(values), $C_($ CYWord("forKeys"), $ CYArray(keys), $C_($ CYWord("count"), $D(count)))));
+}
+
CYTarget *CYObjCBlock::Replace(CYContext &context) {
return $C1($ CYTypeExpression(($ CYTypedIdentifier(*typed_))->Modify($ CYTypeBlockWith(parameters_))), $ CYFunctionExpression(NULL, parameters_->Parameters(context), code_));
}
virtual void Output(CYOutput &out, CYFlags flags) const;
};
+struct CYObjCArray :
+ CYTarget
+{
+ CYElement *elements_;
+
+ CYObjCArray(CYElement *elements = NULL) :
+ elements_(elements)
+ {
+ }
+
+ CYPrecedence(0)
+
+ virtual CYTarget *Replace(CYContext &context);
+ virtual void Output(CYOutput &out, CYFlags flags) const;
+};
+
+struct CYObjCKeyValue :
+ CYNext<CYObjCKeyValue>
+{
+ CYExpression *key_;
+ CYExpression *value_;
+
+ CYObjCKeyValue(CYExpression *key, CYExpression *value, CYObjCKeyValue *next) :
+ CYNext<CYObjCKeyValue>(next),
+ key_(key),
+ value_(value)
+ {
+ }
+};
+
+struct CYObjCDictionary :
+ CYTarget
+{
+ CYObjCKeyValue *pairs_;
+
+ CYObjCDictionary(CYObjCKeyValue *pairs) :
+ pairs_(pairs)
+ {
+ }
+
+ CYPrecedence(0)
+
+ virtual CYTarget *Replace(CYContext &context);
+ virtual void Output(CYOutput &out, CYFlags flags) const;
+};
+
struct CYSelectorPart :
CYNext<CYSelectorPart>,
CYThing
@end
@begin ObjectiveC
+%union { CYObjCKeyValue *keyValue_; }
%union { CYImplementationField *implementationField_; }
%union { CYMessage *message_; }
%union { CYMessageParameter *messageParameter_; }
%type <argument_> ArgumentListOpt
%type <argument_> Arguments
%type <target_> ArrayComprehension
+%type <element_> ArrayElement
%type <literal_> ArrayLiteral
%type <expression_> ArrowFunction
%type <functionParameter_> ArrowParameters
%type <expression_> AssignmentExpression
-%type <expression_> AssignmentExpressionOpt
%type <identifier_> BindingIdentifier
%type <identifier_> BindingIdentifierOpt
%type <bindings_> BindingList_
%type <statement_> Declaration_
%type <statement_> Declaration
%type <clause_> DefaultClause
+%type <element_> ElementList_
%type <element_> ElementList
%type <element_> ElementListOpt
%type <statement_> ElseStatementOpt
%type <protocol_> ClassProtocolsOpt
%type <implementationField_> ImplementationFieldListOpt
%type <statement_> ImplementationStatement
+%type <keyValue_> KeyValuePairList_
+%type <keyValue_> KeyValuePairList
+%type <keyValue_> KeyValuePairListOpt
%type <target_> MessageExpression
%type <messageParameter_> MessageParameter
%type <messageParameter_> MessageParameters
: "[" ElementListOpt[elements] "]" { $$ = CYNew CYArray($elements); }
;
-ElementList
- : AssignmentExpressionOpt[value] "," ElementListOpt[next] { $$ = CYNew CYElementValue($value, $next); }
+ArrayElement
+ : AssignmentExpression[value] { $$ = CYNew CYElementValue($value); }
| LexOf "..." AssignmentExpression[values] { $$ = CYNew CYElementSpread($values); }
- | AssignmentExpression[value] { $$ = CYNew CYElementValue($value, NULL); }
+ ;
+
+ElementList_
+ : "," ElementListOpt[elements] { $$ = $elements; }
+ | { $$ = NULL; }
+ ;
+
+ElementList
+ : ArrayElement[element] ElementList_[next] { $$ = $element; $$->SetNext($next); }
+ | LexOf "," ElementListOpt[next] { $$ = CYNew CYElementValue(NULL, $next); }
;
ElementListOpt
| ArrowFunction[pass] { $$ = $pass; }
| LexOf LeftHandSideAssignment[assignment] AssignmentExpression[rhs] { $assignment->SetRight($rhs); $$ = $assignment; }
;
-
-AssignmentExpressionOpt
- : AssignmentExpression[pass] { $$ = $pass; }
- | LexOf { $$ = NULL; }
- ;
/* }}} */
/* 12.15 Comma Operator ( , ) {{{ */
Expression
| BooleanLiteral[pass] { $$ = $pass; }
| NumericLiteral[pass] { $$ = $pass; }
| StringLiteral[pass] { $$ = $pass; }
- | ArrayLiteral[pass] { $$ = $pass; }
- | ObjectLiteral[pass] { $$ = $pass; }
| CoverParenthesizedExpressionAndArrowParameterList[pass] { $$ = $pass; }
| "YES" { $$ = CYNew CYTrue(); }
| "NO" { $$ = CYNew CYFalse(); }
;
+KeyValuePairList_
+ : "," KeyValuePairListOpt[next] { $$ = $next; }
+ | { $$ = NULL; }
+
+KeyValuePairList
+ : AssignmentExpression[key] ":" AssignmentExpression[value] KeyValuePairList_[next] { $$ = CYNew CYObjCKeyValue($key, $value, $next); }
+ ;
+
+KeyValuePairListOpt
+ : KeyValuePairList[pass] { $$ = $pass; }
+ | LexOf { $$ = NULL; }
+ ;
+
PrimaryExpression
: "@" BoxableExpression[expression] { $$ = CYNew CYBox($expression); }
+ | "@" "[" ElementListOpt[elements] "]" { $$ = CYNew CYObjCArray($elements); }
+ | "@" "{" KeyValuePairListOpt[pairs] "}" { $$ = CYNew CYObjCDictionary($pairs); }
+
| "@YES" { $$ = CYNew CYBox(CYNew CYTrue()); }
| "@NO" { $$ = CYNew CYBox(CYNew CYFalse()); }
| "@true" { $$ = CYNew CYBox(CYNew CYTrue()); }
}
CYTarget *CYArray::Replace(CYContext &context) {
- if (elements_ != NULL)
- elements_->Replace(context);
+ CYForEach (element, elements_)
+ element->Replace(context);
return this;
}
void CYElementValue::Replace(CYContext &context) {
context.Replace(value_);
- if (next_ != NULL)
- next_->Replace(context);
}
CYForInitializer *CYEmpty::Replace(CYContext &context) {
};
struct CYElement :
+ CYNext<CYElement>,
CYThing
{
+ CYElement(CYElement *next) :
+ CYNext<CYElement>(next)
+ {
+ }
+
virtual bool Elision() const = 0;
virtual void Replace(CYContext &context) = 0;
};
struct CYElementValue :
- CYNext<CYElement>,
CYElement
{
CYExpression *value_;
CYElementValue(CYExpression *value, CYElement *next = NULL) :
- CYNext<CYElement>(next),
+ CYElement(next),
value_(value)
{
}
{
CYExpression *value_;
- CYElementSpread(CYExpression *value) :
+ CYElementSpread(CYExpression *value, CYElement *next = NULL) :
+ CYElement(next),
value_(value)
{
}