case sig::void_P: return $ CYTypedIdentifier($ CYTypeVoid());
case sig::struct_P: {
- _assert(type->name != NULL);
- return $ CYTypedIdentifier($ CYTypeVariable(type->name));
+ CYTypeStructField *fields(NULL);
+ for (size_t i(type->data.signature.count); i != 0; --i) {
+ sig::Element &element(type->data.signature.elements[i - 1]);
+ CYTypedIdentifier *typed(Decode(pool, element.type));
+ if (element.name != NULL)
+ typed->identifier_ = $I(element.name);
+ fields = $ CYTypeStructField(typed, fields);
+ }
+ CYIdentifier *name(type->name == NULL ? NULL : $I(type->name));
+ return $ CYTypedIdentifier($ CYTypeStruct(name, fields));
} break;
}
} CYCatch(NULL) }
static JSObjectRef Type_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
- if (count != 1)
- throw CYJSError(context, "incorrect number of arguments to Type constructor");
CYPool pool;
- const char *type(CYPoolCString(pool, context, arguments[0]));
- return CYMakeType(context, type);
+
+ if (false) {
+ } else if (count == 1) {
+ const char *type(CYPoolCString(pool, context, arguments[0]));
+ return CYMakeType(context, type);
+ } else if (count == 2) {
+ JSObjectRef types(CYCastJSObject(context, arguments[0]));
+ size_t count(CYArrayLength(context, types));
+
+ JSObjectRef names(CYCastJSObject(context, arguments[1]));
+
+ sig::Type type;
+ type.name = NULL;
+ type.flags = 0;
+
+ type.primitive = sig::struct_P;
+ type.data.signature.elements = new(pool) sig::Element[count];
+ type.data.signature.count = count;
+
+ for (size_t i(0); i != count; ++i) {
+ sig::Element &element(type.data.signature.elements[i]);
+ element.offset = _not(size_t);
+
+ JSValueRef name(CYArrayGet(context, names, i));
+ if (JSValueIsUndefined(context, name))
+ element.name = NULL;
+ else
+ element.name = CYPoolCString(pool, context, name);
+
+ JSObjectRef object(CYCastJSObject(context, CYArrayGet(context, types, i)));
+ _assert(JSValueIsObjectOfClass(context, object, Type_privateData::Class_));
+ Type_privateData *internal(reinterpret_cast<Type_privateData *>(JSObjectGetPrivate(object)));
+ element.type = internal->type_;
+ }
+
+ return CYMakeType(context, &type);
+ } else {
+ throw CYJSError(context, "incorrect number of arguments to Type constructor");
+ }
} CYCatch(NULL) }
static JSValueRef Type_callAsFunction_$With(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], sig::Primitive primitive, JSValueRef *exception) { CYTry {
#ifndef CYCRIPT_LIST_HPP
#define CYCRIPT_LIST_HPP
+#include "Exception.hpp"
+
template <typename Type_>
struct CYNext {
Type_ *next_;
Type_ *first_;
Type_ *last_;
- CYList(Type_ *first = NULL) :
+ CYList() :
+ first_(NULL),
+ last_(NULL)
+ {
+ }
+
+ CYList(Type_ *first) :
first_(first),
last_(CYGetLast(first))
{
}
+ CYList(Type_ *first, Type_ *last) :
+ first_(first),
+ last_(last)
+ {
+ }
+
operator Type_ *() const {
return first_;
}
if (first_ == NULL) {
first_ = next;
last_ = next;
- } else for (;; last_ = last_->next_)
- if (last_->next_ == NULL) {
- last_->next_ = next;
- last_ = next;
- break;
- }
+ } else {
+ _assert(last_->next_ == NULL);
+ last_->next_ = next;
+ last_ = next;
+ }
return *this;
}
out << "signed" << specifier_;
}
+void CYTypeStruct::Output(CYOutput &out) const {
+ out << "struct" << ' ';
+ if (name_ != NULL)
+ out << *name_ << ' ';
+ out << '{' << '\n';
+ ++out.indent_;
+ CYForEach (field, fields_) {
+ out << '\t' << *field->typed_;
+ out.Terminate();
+ out << '\n';
+ }
+ --out.indent_;
+ out << '}';
+}
+
void CYTypeUnsigned::Output(CYOutput &out) const {
out << "unsigned" << specifier_;
}
%union { CYWord *word_; }
@begin C
+%union { CYTypeStructField *structField_; }
%union { CYTypeModifier *modifier_; }
%union { CYTypeSpecifier *specifier_; }
%union { CYTypedIdentifier *typedIdentifier_; }
%token _typedef_ "typedef"
%token _unsigned_ "unsigned"
%token _signed_ "signed"
+%token _struct_ "struct"
%token _extern_ "extern"
@end
%type <identifier_> IdentifierNoOf
%type <identifier_> IdentifierType
%type <identifier_> IdentifierTypeNoOf
+%type <identifier_> IdentifierTypeOpt
%type <word_> IdentifierName
%type <variable_> IdentifierReference
%type <statement_> IfStatement
%type <specifier_> IntegerTypeOpt
%type <typedIdentifier_> PrefixedType
%type <specifier_> PrimitiveType
+%type <structField_> StructFieldListOpt
%type <typedIdentifier_> SuffixedType
%type <typedIdentifier_> TypeSignifier
%type <modifier_> TypeQualifierLeft
| "of" { $$ = CYNew CYIdentifier("of"); }
;
+IdentifierTypeOpt
+ : IdentifierType[pass] { $$ = $pass; }
+ | { $$ = NULL; }
+ ;
+
IdentifierNoOf
: IdentifierTypeNoOf
| "char" { $$ = CYNew CYIdentifier("char"); }
| "volatile" { $$ = CYNew CYIdentifier("volatile"); }
@begin C
| "signed" { $$ = CYNew CYIdentifier("signed"); }
+ | "struct" { $$ = CYNew CYIdentifier("struct"); }
| "unsigned" { $$ = CYNew CYIdentifier("unsigned"); }
@end
@begin ObjectiveC
| { $$ = CYNew CYTypeVariable("int"); }
;
+StructFieldListOpt
+ : TypedIdentifierMaybe[typed] ";" StructFieldListOpt[next] { $$ = CYNew CYTypeStructField($typed, $next); }
+ | { $$ = NULL; }
+ ;
+
PrimitiveType
: IdentifierType[name] { $$ = CYNew CYTypeVariable($name); }
| IntegerType[pass] { $$ = $pass; }
| "char" { $$ = CYNew CYTypeVariable("char"); }
| "signed" "char" { $$ = CYNew CYTypeSigned(CYNew CYTypeVariable("char")); }
| "unsigned" "char" { $$ = CYNew CYTypeUnsigned(CYNew CYTypeVariable("char")); }
+ | "struct" IdentifierTypeOpt[name] "{" StructFieldListOpt[fields] "}" { $$ = CYNew CYTypeStruct($name, $fields); }
;
TypedIdentifierMaybe
return $ CYCall($ CYDirectMember(specifier_->Replace(context), $ CYString("signed")));
}
+CYTarget *CYTypeStruct::Replace(CYContext &context) {
+ CYList<CYElementValue> types;
+ CYList<CYElementValue> names;
+
+ CYForEach (field, fields_) {
+ CYTypedIdentifier *typed(field->typed_);
+ types->*$ CYElementValue(typed->Replace(context));
+
+ CYExpression *name;
+ if (typed->identifier_ == NULL)
+ name = NULL;
+ else
+ name = $S(typed->identifier_->Word());
+ names->*$ CYElementValue(name);
+ }
+
+ CYTarget *target($N2($V("Type"), $ CYArray(types), $ CYArray(names)));
+ if (name_ != NULL)
+ target = $C1($M(target, $S("withName")), $S(name_->Word()));
+ return target;
+}
+
CYTarget *CYTypeUnsigned::Replace(CYContext &context) {
return $ CYCall($ CYDirectMember(specifier_->Replace(context), $ CYString("unsigned")));
}
@begin C
"extern" L F(tk::_extern_, hi::Type);
"signed" L F(tk::_signed_, hi::Type);
+"struct" L F(tk::_struct_, hi::Meta);
"typedef" L F(tk::_typedef_, hi::Meta);
"unsigned" L F(tk::_unsigned_, hi::Type);
@end
{
CYExpression *value_;
- CYElementValue(CYExpression *value, CYElement *next) :
+ CYElementValue(CYExpression *value, CYElement *next = NULL) :
CYNext<CYElement>(next),
value_(value)
{
virtual CYTypeFunctionWith *Function() { return this; }
};
+struct CYTypeStructField :
+ CYNext<CYTypeStructField>
+{
+ CYTypedIdentifier *typed_;
+
+ CYTypeStructField(CYTypedIdentifier *typed, CYTypeStructField *next = NULL) :
+ CYNext<CYTypeStructField>(next),
+ typed_(typed)
+ {
+ }
+};
+
+struct CYTypeStruct :
+ CYTypeSpecifier
+{
+ CYIdentifier *name_;
+ CYTypeStructField *fields_;
+
+ CYTypeStruct(CYIdentifier *name, CYTypeStructField *fields) :
+ name_(name),
+ fields_(fields)
+ {
+ }
+
+ virtual CYTarget *Replace(CYContext &context);
+ virtual void Output(CYOutput &out) const;
+};
+
namespace cy {
namespace Syntax {