From 3fe283c53edc2a98d0164d893a4a667245da8e78 Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Tue, 21 Jan 2014 05:53:40 -0800 Subject: [PATCH] Implement full unsigned/signed/long/short syntax. --- Cycript.l.in | 2 ++ Cycript.yy.in | 75 ++++++++++++++++++++++++++------------ Decode.cpp | 44 +++++++++++------------ Execute.cpp | 78 +++++++++++++++++++++++++++++++++++++++- Output.cpp | 26 +++++++++++++- Parser.hpp | 99 ++++++++++++++++++++++++++++++++++++++++++++++++--- Replace.cpp | 28 +++++++++++++-- 7 files changed, 298 insertions(+), 54 deletions(-) diff --git a/Cycript.l.in b/Cycript.l.in index 40316ae..44d36f3 100644 --- a/Cycript.l.in +++ b/Cycript.l.in @@ -260,6 +260,8 @@ XMLName {XMLNameStart}{XMLNamePart}* @begin C "typedef" L C I(identifier, Identifier("typedef"), tk::Typedef, hi::Meta); +"unsigned" L C I(identifier, Identifier("unsigned"), tk::Unsigned, hi::Meta); +"signed" L C I(identifier, Identifier("signed"), tk::Signed, hi::Meta); @end @begin ObjectiveC diff --git a/Cycript.yy.in b/Cycript.yy.in index 5a35dd7..c8a1862 100644 --- a/Cycript.yy.in +++ b/Cycript.yy.in @@ -79,6 +79,7 @@ typedef struct { CYProperty *property_; CYPropertyName *propertyName_; CYRubyProc *rubyProc_; + CYTypeSpecifier *specifier_; CYStatement *statement_; CYString *string_; CYThis *this_; @@ -234,6 +235,8 @@ int cylex(YYSTYPE *, cy::location *, void *); @begin C %token Typedef "typedef" +%token Unsigned "unsigned" +%token Signed "signed" @end @begin ObjectiveC @@ -406,6 +409,7 @@ int cylex(YYSTYPE *, cy::location *, void *); %type FunctionExpression %type Identifier %type IdentifierOpt +%type IdentifierType %type IdentifierName %type IfStatement %type Initialiser @@ -486,6 +490,8 @@ int cylex(YYSTYPE *, cy::location *, void *); %type ClassProtocolsOpt %type EncodedType %type FunctionedType +%type IntegerType +%type IntegerTypeOpt %type MessageExpression %type MessageParameter %type MessageParameters @@ -495,7 +501,7 @@ int cylex(YYSTYPE *, cy::location *, void *); %type ModifiedType %type Module %type PrefixedType -%type PrimitiveType +%type PrimitiveType %type SelectorCall_ %type SelectorCall %type SelectorExpression_ @@ -656,15 +662,9 @@ WordOpt | { $$ = NULL; } ; -Identifier +IdentifierType : Identifier_ { $$ = $1; } -@begin C - | "typedef" { $$ = $1; } - | "YES" { $$ = $1; } - | "NO" { $$ = $1; } -@end - | "implements" { $$ = $1; } | "interface" { $$ = $1; } | "package" { $$ = $1; } @@ -676,19 +676,14 @@ Identifier | "abstract" { $$ = $1; } | "boolean" { $$ = $1; } | "byte" { $$ = $1; } - | "char" { $$ = $1; } | "double" { $$ = $1; } | "final" { $$ = $1; } | "float" { $$ = $1; } | "goto" { $$ = $1; } - | "int" { $$ = $1; } - | "long" { $$ = $1; } | "native" { $$ = $1; } - | "short" { $$ = $1; } | "synchronized" { $$ = $1; } | "throws" { $$ = $1; } | "transient" { $$ = $1; } - | "volatile" { $$ = $1; } // XXX: currently I only have this as Word // | "let" { $$ = $1; } @@ -699,6 +694,22 @@ Identifier | "of" { $$ = $1; } ; +Identifier + : IdentifierType + | "char" { $$ = $1; } + | "int" { $$ = $1; } + | "long" { $$ = $1; } + | "short" { $$ = $1; } + | "volatile" { $$ = $1; } +@begin C + | "typedef" { $$ = $1; } + | "unsigned" { $$ = $1; } + | "signed" { $$ = $1; } + | "YES" { $$ = $1; } + | "NO" { $$ = $1; } +@end + ; + IdentifierOpt : Identifier { $$ = $1; } | { $$ = NULL; } @@ -1390,7 +1401,7 @@ TypeParenthetical ; TypeSignifier - : Identifier { $$ = CYNew CYTypedIdentifier($1); } + : IdentifierType { $$ = CYNew CYTypedIdentifier($1); } | TypeParenthetical { $$ = $1; } ; @@ -1416,24 +1427,42 @@ PrefixedType ; TypeQualifierLeft - : "const" TypeQualifierLeft { $$ = $2; CYSetLast($$) = CYNew CYTypeConstant(); } - /* XXX: | "volatile" TypeQualifierLeft { $$ = $2; CYSetLast($$) = CYNew CYTypeVolatile(); } */ - | { $$ = NULL; } + : { $$ = NULL; } + | "const" TypeQualifierLeft { $$ = $2; CYSetLast($$) = CYNew CYTypeConstant(); } + | "volatile" TypeQualifierLeft { $$ = $2; CYSetLast($$) = CYNew CYTypeVolatile(); } ; TypeQualifierRight - : "const" TypeQualifierRight { $$ = $2; $$->modifier_ = CYNew CYTypeConstant($$->modifier_); } - | PrefixedType { $$ = $1; } + : PrefixedType { $$ = $1; } | SuffixedType { $$ = $1; } + | "const" TypeQualifierRight { $$ = $2; $$->modifier_ = CYNew CYTypeConstant($$->modifier_); } + | "volatile" TypeQualifierRight { $$ = $2; $$->modifier_ = CYNew CYTypeVolatile($$->modifier_); } + ; + +IntegerType + : "int" { $$ = CYNew CYTypeVariable("int"); } + | "unsigned" IntegerTypeOpt { $$ = CYNew CYTypeUnsigned($2); } + | "signed" IntegerTypeOpt { $$ = CYNew CYTypeSigned($2); } + | "long" IntegerTypeOpt { $$ = CYNew CYTypeLong($2); } + | "short" IntegerTypeOpt { $$ = CYNew CYTypeShort($2); } + ; + +IntegerTypeOpt + : IntegerType { $$ = $1; } + | ; PrimitiveType - : Variable { $$ = $1; } - | "void" { $$ = CYNew cy::Syntax::New(CYNew CYVariable(CYNew CYIdentifier("Type")), CYNew CYArgument(CYNew CYString("v"))); } + : IdentifierType { $$ = CYNew CYTypeVariable($1); } + | IntegerType { $$ = $1; } + | "void" { $$ = CYNew CYTypeVoid(); } + | "char" { $$ = CYNew CYTypeVariable("char"); } + | "signed" "char" { $$ = CYNew CYTypeSigned(CYNew CYTypeVariable("char")); } + | "unsigned" "char" { $$ = CYNew CYTypeUnsigned(CYNew CYTypeVariable("char")); } ; TypedIdentifier - : TypeQualifierLeft PrimitiveType TypeQualifierRight { $$ = $3; $$->type_ = $2; CYSetLast($1) = $$->modifier_; $$->modifier_ = $1; } + : TypeQualifierLeft PrimitiveType TypeQualifierRight { $$ = $3; $$->specifier_ = $2; CYSetLast($1) = $$->modifier_; $$->modifier_ = $1; } ; EncodedType @@ -1626,7 +1655,7 @@ PrimaryExpression /* }}} */ /* Cycript (Objective-C): Block Expressions {{{ */ ModifiedType - : TypeQualifierLeft PrimitiveType { $$ = CYNew CYTypedIdentifier(); $$->type_ = $2; $$->modifier_ = $1; } + : TypeQualifierLeft PrimitiveType { $$ = CYNew CYTypedIdentifier(); $$->specifier_ = $2; $$->modifier_ = $1; } | ModifiedType "*" { $$ = $1; $$->modifier_ = CYNew CYTypePointerTo($$->modifier_); } ; diff --git a/Decode.cpp b/Decode.cpp index 9cb165c..e31b469 100644 --- a/Decode.cpp +++ b/Decode.cpp @@ -34,10 +34,10 @@ CYTypedIdentifier *Decode_(CYPool &pool, struct sig::Type *type) { return Decode(pool, type->data.signature.elements[0].type)->Modify($ CYTypeFunctionWith(parameter)); } break; - case sig::typename_P: return $ CYTypedIdentifier($V("Class")); + case sig::typename_P: return $ CYTypedIdentifier($ CYTypeVariable("Class")); case sig::union_P: _assert(false); break; - case sig::string_P: return $ CYTypedIdentifier($V("char"), $ CYTypePointerTo()); - case sig::selector_P: return $ CYTypedIdentifier($V("SEL")); + case sig::string_P: return $ CYTypedIdentifier($ CYTypeVariable("char"), $ CYTypePointerTo()); + case sig::selector_P: return $ CYTypedIdentifier($ CYTypeVariable("SEL")); case sig::block_P: { _assert(type->data.signature.count != 0); @@ -49,44 +49,42 @@ CYTypedIdentifier *Decode_(CYPool &pool, struct sig::Type *type) { case sig::object_P: { if (type->name == NULL) - return $ CYTypedIdentifier($V("id")); + return $ CYTypedIdentifier($ CYTypeVariable("id")); else - return $ CYTypedIdentifier($V(type->name), $ CYTypePointerTo()); + return $ CYTypedIdentifier($ CYTypeVariable(type->name), $ CYTypePointerTo()); } break; - case sig::boolean_P: return $ CYTypedIdentifier($V("bool")); - case sig::uchar_P: return $ CYTypedIdentifier($V("uchar")); - case sig::uint_P: return $ CYTypedIdentifier($V("uint")); - case sig::ulong_P: return $ CYTypedIdentifier($V("ulong")); - case sig::ulonglong_P: return $ CYTypedIdentifier($V("ulonglong")); - case sig::ushort_P: return $ CYTypedIdentifier($V("ushort")); + case sig::boolean_P: return $ CYTypedIdentifier($ CYTypeVariable("bool")); + case sig::uchar_P: return $ CYTypedIdentifier($ CYTypeUnsigned($ CYTypeVariable("char"))); + case sig::uint_P: return $ CYTypedIdentifier($ CYTypeUnsigned($ CYTypeVariable("int"))); + case sig::ulong_P: return $ CYTypedIdentifier($ CYTypeUnsigned($ CYTypeLong($ CYTypeVariable("int")))); + case sig::ulonglong_P: return $ CYTypedIdentifier($ CYTypeUnsigned($ CYTypeLong($ CYTypeLong($ CYTypeVariable("int"))))); + case sig::ushort_P: return $ CYTypedIdentifier($ CYTypeUnsigned($ CYTypeShort($ CYTypeVariable("int")))); case sig::array_P: return Decode(pool, type->data.data.type)->Modify($ CYTypeArrayOf($D(type->data.data.size))); - // XXX: once again, the issue of void here is incorrect case sig::pointer_P: { CYTypedIdentifier *typed; if (type->data.data.type == NULL) - typed = $ CYTypedIdentifier($V("void")); + typed = $ CYTypedIdentifier($ CYTypeVoid()); else typed = Decode(pool, type->data.data.type); return typed->Modify($ CYTypePointerTo()); } break; case sig::bit_P: _assert(false); break; - case sig::char_P: return $ CYTypedIdentifier($V("char")); - case sig::double_P: return $ CYTypedIdentifier($V("double")); - case sig::float_P: return $ CYTypedIdentifier($V("float")); - case sig::int_P: return $ CYTypedIdentifier($V("int")); - case sig::long_P: return $ CYTypedIdentifier($V("long")); - case sig::longlong_P: return $ CYTypedIdentifier($V("longlong")); - case sig::short_P: return $ CYTypedIdentifier($V("short")); + case sig::char_P: return $ CYTypedIdentifier($ CYTypeVariable("char")); + case sig::double_P: return $ CYTypedIdentifier($ CYTypeVariable("double")); + case sig::float_P: return $ CYTypedIdentifier($ CYTypeVariable("float")); + case sig::int_P: return $ CYTypedIdentifier($ CYTypeVariable("int")); + case sig::long_P: return $ CYTypedIdentifier($ CYTypeLong($ CYTypeVariable("int"))); + case sig::longlong_P: return $ CYTypedIdentifier($ CYTypeLong($ CYTypeLong($ CYTypeVariable("int")))); + case sig::short_P: return $ CYTypedIdentifier($ CYTypeShort($ CYTypeVariable("int"))); - // XXX: this happens to work, but is totally wrong - case sig::void_P: return $ CYTypedIdentifier($V("void")); + case sig::void_P: return $ CYTypedIdentifier($ CYTypeVoid()); case sig::struct_P: { _assert(type->name != NULL); - return $ CYTypedIdentifier($V(type->name)); + return $ CYTypedIdentifier($ CYTypeVariable(type->name)); } break; } diff --git a/Execute.cpp b/Execute.cpp index 898cd14..5baca2a 100644 --- a/Execute.cpp +++ b/Execute.cpp @@ -1146,6 +1146,78 @@ static JSValueRef Type_callAsFunction_constant(JSContextRef context, JSObjectRef return CYMakeType(context, &type); } CYCatch(NULL) } +static JSValueRef Type_callAsFunction_long(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { + if (count != 0) + throw CYJSError(context, "incorrect number of arguments to Type.long"); + Type_privateData *internal(reinterpret_cast(JSObjectGetPrivate(_this))); + + sig::Type type(*internal->type_); + + switch (type.primitive) { + case sig::short_P: type.primitive = sig::int_P; break; + case sig::int_P: type.primitive = sig::long_P; break; + case sig::long_P: type.primitive = sig::longlong_P; break; + default: throw CYJSError(context, "invalid type argument to Type.long"); + } + + return CYMakeType(context, &type); +} CYCatch(NULL) } + +static JSValueRef Type_callAsFunction_short(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { + if (count != 0) + throw CYJSError(context, "incorrect number of arguments to Type.short"); + Type_privateData *internal(reinterpret_cast(JSObjectGetPrivate(_this))); + + sig::Type type(*internal->type_); + + switch (type.primitive) { + case sig::int_P: type.primitive = sig::short_P; break; + case sig::long_P: type.primitive = sig::int_P; break; + case sig::longlong_P: type.primitive = sig::long_P; break; + default: throw CYJSError(context, "invalid type argument to Type.short"); + } + + return CYMakeType(context, &type); +} CYCatch(NULL) } + +static JSValueRef Type_callAsFunction_signed(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { + if (count != 0) + throw CYJSError(context, "incorrect number of arguments to Type.signed"); + Type_privateData *internal(reinterpret_cast(JSObjectGetPrivate(_this))); + + sig::Type type(*internal->type_); + + switch (type.primitive) { + case sig::char_P: case sig::uchar_P: type.primitive = sig::char_P; break; + case sig::short_P: case sig::ushort_P: type.primitive = sig::short_P; break; + case sig::int_P: case sig::uint_P: type.primitive = sig::int_P; break; + case sig::long_P: case sig::ulong_P: type.primitive = sig::long_P; break; + case sig::longlong_P: case sig::ulonglong_P: type.primitive = sig::longlong_P; break; + default: throw CYJSError(context, "invalid type argument to Type.signed"); + } + + return CYMakeType(context, &type); +} CYCatch(NULL) } + +static JSValueRef Type_callAsFunction_unsigned(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { CYTry { + if (count != 0) + throw CYJSError(context, "incorrect number of arguments to Type.unsigned"); + Type_privateData *internal(reinterpret_cast(JSObjectGetPrivate(_this))); + + sig::Type type(*internal->type_); + + switch (type.primitive) { + case sig::char_P: case sig::uchar_P: type.primitive = sig::uchar_P; break; + case sig::short_P: case sig::ushort_P: type.primitive = sig::ushort_P; break; + case sig::int_P: case sig::uint_P: type.primitive = sig::uint_P; break; + case sig::long_P: case sig::ulong_P: type.primitive = sig::ulong_P; break; + case sig::longlong_P: case sig::ulonglong_P: type.primitive = sig::ulonglong_P; break; + default: throw CYJSError(context, "invalid type argument to Type.unsigned"); + } + + return CYMakeType(context, &type); +} CYCatch(NULL) } + static JSValueRef Type_callAsFunction_functionWith(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { return Type_callAsFunction_$With(context, object, _this, count, arguments, sig::function_P, exception); } @@ -1355,16 +1427,20 @@ static JSStaticValue Type_staticValues[4] = { {NULL, NULL, NULL, 0} }; -static JSStaticFunction Type_staticFunctions[10] = { +static JSStaticFunction Type_staticFunctions[14] = { {"arrayOf", &Type_callAsFunction_arrayOf, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"blockWith", &Type_callAsFunction_blockWith, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"constant", &Type_callAsFunction_constant, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"functionWith", &Type_callAsFunction_functionWith, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {"long", &Type_callAsFunction_long, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"pointerTo", &Type_callAsFunction_pointerTo, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {"short", &Type_callAsFunction_short, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {"signed", &Type_callAsFunction_signed, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"withName", &Type_callAsFunction_withName, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"toCYON", &Type_callAsFunction_toCYON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"toJSON", &Type_callAsFunction_toJSON, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {"toString", &Type_callAsFunction_toString, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, + {"unsigned", &Type_callAsFunction_unsigned, kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {NULL, NULL, 0} }; diff --git a/Output.cpp b/Output.cpp index 51134c7..42d1854 100644 --- a/Output.cpp +++ b/Output.cpp @@ -523,7 +523,7 @@ void CYTypeModifier::Output(CYOutput &out, int precedence, CYIdentifier *identif } void CYTypedIdentifier::Output(CYOutput &out) const { - type_->Output(out, 0, CYNoFlags); + specifier_->Output(out); modifier_->Output(out, 0, identifier_); } @@ -748,6 +748,30 @@ void Try::Output(CYOutput &out, CYFlags flags) const { } } +void CYTypeLong::Output(CYOutput &out) const { + out << "long" << specifier_; +} + +void CYTypeShort::Output(CYOutput &out) const { + out << "short" << specifier_; +} + +void CYTypeSigned::Output(CYOutput &out) const { + out << "signed" << specifier_; +} + +void CYTypeUnsigned::Output(CYOutput &out) const { + out << "unsigned" << specifier_; +} + +void CYTypeVariable::Output(CYOutput &out) const { + out << *name_; +} + +void CYTypeVoid::Output(CYOutput &out) const { + out << "void"; +} + void CYVar::Output(CYOutput &out, CYFlags flags) const { out << "var"; declarations_->Output(out, flags); diff --git a/Parser.hpp b/Parser.hpp index 59e657f..d9530df 100644 --- a/Parser.hpp +++ b/Parser.hpp @@ -1606,6 +1606,97 @@ struct CYFinally : virtual void Output(CYOutput &out) const; }; +struct CYTypeSpecifier : + CYThing +{ + virtual CYExpression *Replace(CYContext &context) = 0; +}; + +struct CYTypeVoid : + CYTypeSpecifier +{ + CYTypeVoid() { + } + + virtual CYExpression *Replace(CYContext &context); + virtual void Output(CYOutput &out) const; +}; + +struct CYTypeVariable : + CYTypeSpecifier +{ + CYIdentifier *name_; + + CYTypeVariable(CYIdentifier *name) : + name_(name) + { + } + + CYTypeVariable(const char *name) : + name_(new($pool) CYIdentifier(name)) + { + } + + virtual CYExpression *Replace(CYContext &context); + virtual void Output(CYOutput &out) const; +}; + +struct CYTypeUnsigned : + CYTypeSpecifier +{ + CYTypeSpecifier *specifier_; + + CYTypeUnsigned(CYTypeSpecifier *specifier) : + specifier_(specifier) + { + } + + virtual CYExpression *Replace(CYContext &context); + virtual void Output(CYOutput &out) const; +}; + +struct CYTypeSigned : + CYTypeSpecifier +{ + CYTypeSpecifier *specifier_; + + CYTypeSigned(CYTypeSpecifier *specifier) : + specifier_(specifier) + { + } + + virtual CYExpression *Replace(CYContext &context); + virtual void Output(CYOutput &out) const; +}; + +struct CYTypeLong : + CYTypeSpecifier +{ + CYTypeSpecifier *specifier_; + + CYTypeLong(CYTypeSpecifier *specifier) : + specifier_(specifier) + { + } + + virtual CYExpression *Replace(CYContext &context); + virtual void Output(CYOutput &out) const; +}; + +struct CYTypeShort : + CYTypeSpecifier +{ + CYTypeSpecifier *specifier_; + + CYTypeShort(CYTypeSpecifier *specifier) : + specifier_(specifier) + { + } + + virtual CYExpression *Replace(CYContext &context); + virtual void Output(CYOutput &out) const; +}; + struct CYTypeModifier : CYNext { @@ -1687,19 +1778,19 @@ struct CYTypedIdentifier : CYThing { CYIdentifier *identifier_; - CYExpression *type_; + CYTypeSpecifier *specifier_; CYTypeModifier *modifier_; CYTypedIdentifier(CYIdentifier *identifier = NULL) : identifier_(identifier), - type_(NULL), + specifier_(NULL), modifier_(NULL) { } - CYTypedIdentifier(CYExpression *type, CYTypeModifier *modifier = NULL) : + CYTypedIdentifier(CYTypeSpecifier *specifier, CYTypeModifier *modifier = NULL) : identifier_(NULL), - type_(type), + specifier_(specifier), modifier_(modifier) { } diff --git a/Replace.cpp b/Replace.cpp index f577919..ce01303 100644 --- a/Replace.cpp +++ b/Replace.cpp @@ -906,16 +906,40 @@ CYExpression *CYTypeFunctionWith::Replace_(CYContext &context, CYExpression *typ return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("functionWith")), parameters_->Argument(context))); } +CYExpression *CYTypeLong::Replace(CYContext &context) { + return $ CYCall($ CYDirectMember(specifier_->Replace(context), $ CYString("long"))); +} + CYExpression *CYTypePointerTo::Replace_(CYContext &context, CYExpression *type) { return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("pointerTo")))); } +CYExpression *CYTypeShort::Replace(CYContext &context) { + return $ CYCall($ CYDirectMember(specifier_->Replace(context), $ CYString("short"))); +} + +CYExpression *CYTypeSigned::Replace(CYContext &context) { + return $ CYCall($ CYDirectMember(specifier_->Replace(context), $ CYString("signed"))); +} + +CYExpression *CYTypeUnsigned::Replace(CYContext &context) { + return $ CYCall($ CYDirectMember(specifier_->Replace(context), $ CYString("unsigned"))); +} + +CYExpression *CYTypeVariable::Replace(CYContext &context) { + return $V(name_); +} + +CYExpression *CYTypeVoid::Replace(CYContext &context) { + return $N1($V("Type"), $ CYString("v")); +} + CYExpression *CYTypeVolatile::Replace_(CYContext &context, CYExpression *type) { return next_->Replace(context, $ CYCall($ CYDirectMember(type, $ CYString("volatile")))); } CYExpression *CYTypedIdentifier::Replace(CYContext &context) { - return modifier_->Replace(context, type_); + return modifier_->Replace(context, specifier_->Replace(context)); } CYArgument *CYTypedParameter::Argument(CYContext &context) { $T(NULL) @@ -927,7 +951,7 @@ CYFunctionParameter *CYTypedParameter::Parameters(CYContext &context) { $T(NULL) } CYExpression *CYTypedParameter::TypeSignature(CYContext &context, CYExpression *prefix) { $T(prefix) - return next_->TypeSignature(context, $ CYAdd(prefix, typed_->type_->Replace(context))); + return next_->TypeSignature(context, $ CYAdd(prefix, typed_->specifier_->Replace(context))); } CYStatement *CYVar::Replace(CYContext &context) { -- 2.45.2