]> git.saurik.com Git - cycript.git/commitdiff
Finally provide totally legit support for structs.
authorJay Freeman (saurik) <saurik@saurik.com>
Sat, 19 Dec 2015 05:57:13 +0000 (21:57 -0800)
committerJay Freeman (saurik) <saurik@saurik.com>
Sat, 19 Dec 2015 05:57:13 +0000 (21:57 -0800)
Decode.cpp
Execute.cpp
List.hpp
Output.cpp
Parser.ypp.in
Replace.cpp
Scanner.lpp.in
Syntax.hpp

index 95f68ef4fdd0bf535e64d02bbca83816c4c936f8..e7ea5f9e3acdc834abea915d54d287948de83440 100644 (file)
@@ -88,8 +88,16 @@ CYTypedIdentifier *Decode_(CYPool &pool, struct sig::Type *type) {
         case sig::void_P: return $ CYTypedIdentifier($ CYTypeVoid());
 
         case sig::struct_P: {
         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;
     }
 
         } break;
     }
 
index bb337ba79a62728221794fd128f157563bcd7739..b45007667854b9f0680e846984aeb6a5f3004c0f 100644 (file)
@@ -1175,11 +1175,46 @@ static JSObjectRef Pointer_new(JSContextRef context, JSObjectRef object, size_t
 } CYCatch(NULL) }
 
 static JSObjectRef Type_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry {
 } 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;
     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 {
 } 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 {
index 4caa5361e35db6eceb83f1232c23e078f3b7c7ab..010f7ae21175dcde47ea4094dfaea09576c618ed 100644 (file)
--- a/List.hpp
+++ b/List.hpp
@@ -22,6 +22,8 @@
 #ifndef CYCRIPT_LIST_HPP
 #define CYCRIPT_LIST_HPP
 
 #ifndef CYCRIPT_LIST_HPP
 #define CYCRIPT_LIST_HPP
 
+#include "Exception.hpp"
+
 template <typename Type_>
 struct CYNext {
     Type_ *next_;
 template <typename Type_>
 struct CYNext {
     Type_ *next_;
@@ -68,12 +70,24 @@ struct CYList {
     Type_ *first_;
     Type_ *last_;
 
     Type_ *first_;
     Type_ *last_;
 
-    CYList(Type_ *first = NULL) :
+    CYList() :
+        first_(NULL),
+        last_(NULL)
+    {
+    }
+
+    CYList(Type_ *first) :
         first_(first),
         last_(CYGetLast(first))
     {
     }
 
         first_(first),
         last_(CYGetLast(first))
     {
     }
 
+    CYList(Type_ *first, Type_ *last) :
+        first_(first),
+        last_(last)
+    {
+    }
+
     operator Type_ *() const {
         return first_;
     }
     operator Type_ *() const {
         return first_;
     }
@@ -87,12 +101,11 @@ struct CYList {
             if (first_ == NULL) {
                 first_ = next;
                 last_ = next;
             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;
     }
 
         return *this;
     }
 
index cbd853f836f00b6a1521c638010c3c0310e65242..6610ff20ac4ddc9b8b6d98af3e946e30bf4eab88 100644 (file)
@@ -920,6 +920,21 @@ void CYTypeSigned::Output(CYOutput &out) const {
     out << "signed" << specifier_;
 }
 
     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_;
 }
 void CYTypeUnsigned::Output(CYOutput &out) const {
     out << "unsigned" << specifier_;
 }
index f73ccd168b9758b9d83a630351a260d02799c764..17b42e584e475f01f50eeff3b712babcfec09a95 100644 (file)
@@ -80,6 +80,7 @@
 %union { CYWord *word_; }
 
 @begin C
 %union { CYWord *word_; }
 
 @begin C
+%union { CYTypeStructField *structField_; }
 %union { CYTypeModifier *modifier_; }
 %union { CYTypeSpecifier *specifier_; }
 %union { CYTypedIdentifier *typedIdentifier_; }
 %union { CYTypeModifier *modifier_; }
 %union { CYTypeSpecifier *specifier_; }
 %union { CYTypedIdentifier *typedIdentifier_; }
@@ -330,6 +331,7 @@ type; })
 %token _typedef_ "typedef"
 %token _unsigned_ "unsigned"
 %token _signed_ "signed"
 %token _typedef_ "typedef"
 %token _unsigned_ "unsigned"
 %token _signed_ "signed"
+%token _struct_ "struct"
 %token _extern_ "extern"
 @end
 
 %token _extern_ "extern"
 @end
 
@@ -543,6 +545,7 @@ type; })
 %type <identifier_> IdentifierNoOf
 %type <identifier_> IdentifierType
 %type <identifier_> IdentifierTypeNoOf
 %type <identifier_> IdentifierNoOf
 %type <identifier_> IdentifierType
 %type <identifier_> IdentifierTypeNoOf
+%type <identifier_> IdentifierTypeOpt
 %type <word_> IdentifierName
 %type <variable_> IdentifierReference
 %type <statement_> IfStatement
 %type <word_> IdentifierName
 %type <variable_> IdentifierReference
 %type <statement_> IfStatement
@@ -626,6 +629,7 @@ type; })
 %type <specifier_> IntegerTypeOpt
 %type <typedIdentifier_> PrefixedType
 %type <specifier_> PrimitiveType
 %type <specifier_> IntegerTypeOpt
 %type <typedIdentifier_> PrefixedType
 %type <specifier_> PrimitiveType
+%type <structField_> StructFieldListOpt
 %type <typedIdentifier_> SuffixedType
 %type <typedIdentifier_> TypeSignifier
 %type <modifier_> TypeQualifierLeft
 %type <typedIdentifier_> SuffixedType
 %type <typedIdentifier_> TypeSignifier
 %type <modifier_> TypeQualifierLeft
@@ -930,6 +934,11 @@ IdentifierType
     | "of" { $$ = CYNew CYIdentifier("of"); }
     ;
 
     | "of" { $$ = CYNew CYIdentifier("of"); }
     ;
 
+IdentifierTypeOpt
+    : IdentifierType[pass] { $$ = $pass; }
+    | { $$ = NULL; }
+    ;
+
 IdentifierNoOf
     : IdentifierTypeNoOf
     | "char" { $$ = CYNew CYIdentifier("char"); }
 IdentifierNoOf
     : IdentifierTypeNoOf
     | "char" { $$ = CYNew CYIdentifier("char"); }
@@ -940,6 +949,7 @@ IdentifierNoOf
     | "volatile" { $$ = CYNew CYIdentifier("volatile"); }
 @begin C
     | "signed" { $$ = CYNew CYIdentifier("signed"); }
     | "volatile" { $$ = CYNew CYIdentifier("volatile"); }
 @begin C
     | "signed" { $$ = CYNew CYIdentifier("signed"); }
+    | "struct" { $$ = CYNew CYIdentifier("struct"); }
     | "unsigned" { $$ = CYNew CYIdentifier("unsigned"); }
 @end
 @begin ObjectiveC
     | "unsigned" { $$ = CYNew CYIdentifier("unsigned"); }
 @end
 @begin ObjectiveC
@@ -1974,6 +1984,11 @@ IntegerTypeOpt
     | { $$ = CYNew CYTypeVariable("int"); }
     ;
 
     | { $$ = CYNew CYTypeVariable("int"); }
     ;
 
+StructFieldListOpt
+    : TypedIdentifierMaybe[typed] ";" StructFieldListOpt[next] { $$ = CYNew CYTypeStructField($typed, $next); }
+    | { $$ = NULL; }
+    ;
+
 PrimitiveType
     : IdentifierType[name] { $$ = CYNew CYTypeVariable($name); }
     | IntegerType[pass] { $$ = $pass; }
 PrimitiveType
     : IdentifierType[name] { $$ = CYNew CYTypeVariable($name); }
     | IntegerType[pass] { $$ = $pass; }
@@ -1981,6 +1996,7 @@ PrimitiveType
     | "char" { $$ = CYNew CYTypeVariable("char"); }
     | "signed" "char" { $$ = CYNew CYTypeSigned(CYNew CYTypeVariable("char")); }
     | "unsigned" "char" { $$ = CYNew CYTypeUnsigned(CYNew CYTypeVariable("char")); }
     | "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
     ;
 
 TypedIdentifierMaybe
index c812c358e3524344ebda7d1a93296e1203516cc6..307ccecfff8b2c4715791061f06267cda331725b 100644 (file)
@@ -1187,6 +1187,28 @@ CYTarget *CYTypeSigned::Replace(CYContext &context) {
     return $ CYCall($ CYDirectMember(specifier_->Replace(context), $ CYString("signed")));
 }
 
     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")));
 }
 CYTarget *CYTypeUnsigned::Replace(CYContext &context) {
     return $ CYCall($ CYDirectMember(specifier_->Replace(context), $ CYString("unsigned")));
 }
index 518b6b48215f4fac003f5b2b2f568bea742c204f..3459b08655f8c99d2cd7e951a045723d219f7293 100644 (file)
@@ -526,6 +526,7 @@ XMLName {XMLNameStart}{XMLNamePart}*
 @begin C
 "extern"          L F(tk::_extern_, hi::Type);
 "signed"          L F(tk::_signed_, hi::Type);
 @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
 "typedef"         L F(tk::_typedef_, hi::Meta);
 "unsigned"        L F(tk::_unsigned_, hi::Type);
 @end
index 89bca7336c23251c34089bc9e578e3c1fc428991..cb39f405cff53fbdd27da9f67fed5111ab592a9e 100644 (file)
@@ -1090,7 +1090,7 @@ struct CYElementValue :
 {
     CYExpression *value_;
 
 {
     CYExpression *value_;
 
-    CYElementValue(CYExpression *value, CYElement *next) :
+    CYElementValue(CYExpression *value, CYElement *next = NULL) :
         CYNext<CYElement>(next),
         value_(value)
     {
         CYNext<CYElement>(next),
         value_(value)
     {
@@ -2324,6 +2324,34 @@ struct CYTypeFunctionWith :
     virtual CYTypeFunctionWith *Function() { return this; }
 };
 
     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 {
 
 namespace cy {
 namespace Syntax {