2022-12-29 12:32:55 +00:00
|
|
|
#include "compiler/CObjCModern.h"
|
|
|
|
#include "compiler/CError.h"
|
|
|
|
#include "compiler/CExpr.h"
|
|
|
|
#include "compiler/CObjC.h"
|
|
|
|
#include "compiler/CPrep.h"
|
|
|
|
#include "compiler/CPrepTokenizer.h"
|
|
|
|
#include "compiler/CompilerTools.h"
|
|
|
|
#include "compiler/objc.h"
|
|
|
|
#include "compiler/objects.h"
|
|
|
|
#include "compiler/scopes.h"
|
|
|
|
|
|
|
|
static ObjCNamedArg *CObjC_GetKeywordArgList(HashNameNode *name, Boolean *isSingleArg) {
|
|
|
|
ObjCNamedArg *first;
|
|
|
|
ObjCNamedArg *arg;
|
|
|
|
char *start;
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
start = name->name;
|
|
|
|
first = NULL;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
for (p = start; *p != '_'; p++) {
|
|
|
|
if (*p == 0) {
|
|
|
|
if (!first) {
|
|
|
|
first = lalloc(sizeof(ObjCNamedArg));
|
|
|
|
memclrw(first, sizeof(ObjCNamedArg));
|
|
|
|
|
|
|
|
first->name = name;
|
|
|
|
|
|
|
|
*isSingleArg = 1;
|
|
|
|
return first;
|
|
|
|
}
|
|
|
|
|
|
|
|
arg->next = lalloc(sizeof(ObjCNamedArg));
|
|
|
|
arg = arg->next;
|
|
|
|
|
|
|
|
arg->next = NULL;
|
|
|
|
arg->name = GetHashNameNode(start);
|
|
|
|
arg->expr = NULL;
|
|
|
|
|
|
|
|
*isSingleArg = 0;
|
|
|
|
return first;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (first) {
|
|
|
|
arg->next = lalloc(sizeof(ObjCNamedArg));
|
|
|
|
arg = arg->next;
|
|
|
|
} else {
|
|
|
|
arg = lalloc(sizeof(ObjCNamedArg));
|
|
|
|
first = arg;
|
|
|
|
}
|
|
|
|
|
|
|
|
*p = 0;
|
|
|
|
arg->next = NULL;
|
|
|
|
arg->name = GetHashNameNode(start);
|
|
|
|
arg->expr = NULL;
|
|
|
|
*p = '_';
|
|
|
|
|
|
|
|
if (*(++p) == 0) {
|
|
|
|
*isSingleArg = 0;
|
|
|
|
return first;
|
|
|
|
}
|
|
|
|
|
|
|
|
start = p;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static ENode *CObjC_ModernSendMessage(TypeClass *tclass, ENode *expr, HashNameNode *name, Boolean isSuper) {
|
|
|
|
ENode *callexpr;
|
|
|
|
ObjCNamedArg *args;
|
|
|
|
ObjCNamedArg *arg;
|
|
|
|
ENodeList *unnamedArgs;
|
|
|
|
Boolean isSingleArg;
|
|
|
|
|
|
|
|
CError_ASSERT(92, ENODE_IS(expr, EINDIRECT));
|
|
|
|
expr = expr->data.monadic;
|
|
|
|
|
|
|
|
args = CObjC_GetKeywordArgList(name, &isSingleArg);
|
|
|
|
|
|
|
|
if ((tk = lex()) == ')') {
|
|
|
|
if (!isSingleArg) {
|
|
|
|
CError_Error(CErrorStr162);
|
|
|
|
return nullnode();
|
|
|
|
}
|
|
|
|
|
|
|
|
callexpr = CObjC_MakeSendMsgExpr(expr, tclass, args, NULL, 1, isSuper);
|
|
|
|
tk = lex();
|
|
|
|
return callexpr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isSingleArg) {
|
|
|
|
CError_Error(CErrorStr162);
|
|
|
|
return nullnode();
|
|
|
|
}
|
|
|
|
|
|
|
|
unnamedArgs = NULL;
|
|
|
|
arg = args;
|
|
|
|
while (1) {
|
|
|
|
arg->expr = assignment_expression();
|
|
|
|
|
|
|
|
if (tk == ')') {
|
|
|
|
if (arg->next) {
|
|
|
|
CError_Error(CErrorStr162);
|
|
|
|
return nullnode();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tk != ',') {
|
|
|
|
CError_Error(CErrorStr141);
|
|
|
|
return nullnode();
|
|
|
|
}
|
|
|
|
|
|
|
|
tk = lex();
|
|
|
|
arg = arg->next;
|
|
|
|
|
|
|
|
if (!arg) {
|
|
|
|
unnamedArgs = CExpr_ScanExpressionList(0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
callexpr = CObjC_MakeSendMsgExpr(expr, tclass, args, unnamedArgs, 1, isSuper);
|
|
|
|
tk = lex();
|
|
|
|
return callexpr;
|
|
|
|
}
|
|
|
|
|
|
|
|
ENode *CObjC_CheckModernSendMessage(TypeClass *tclass, ENode *expr) {
|
|
|
|
HashNameNode *name;
|
|
|
|
SInt32 state;
|
|
|
|
|
|
|
|
CPrep_TokenStreamGetState(&state);
|
|
|
|
|
|
|
|
tk = lex();
|
|
|
|
CObjC_TranslateSelectorToken();
|
|
|
|
if (tk == TK_IDENTIFIER) {
|
|
|
|
if (!strcmp(tkidentifier->name, "super")) {
|
|
|
|
if (lex() == TK_COLON_COLON) {
|
|
|
|
tk = lex();
|
|
|
|
CObjC_TranslateSelectorToken();
|
|
|
|
|
|
|
|
name = tkidentifier;
|
|
|
|
if (tk == TK_IDENTIFIER && lex() == '(')
|
|
|
|
return CObjC_ModernSendMessage(tclass, expr, name, 1);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
name = tkidentifier;
|
|
|
|
if (lex() == '(')
|
|
|
|
return CObjC_ModernSendMessage(tclass, expr, name, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CPrep_TokenStreamSetState(&state);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ENode *CObjC_New(TypeClass *tclass) {
|
|
|
|
ObjCNamedArg *arg;
|
|
|
|
ENode *objexpr;
|
|
|
|
|
|
|
|
arg = lalloc(sizeof(ObjCNamedArg));
|
|
|
|
memclrw(arg, sizeof(ObjCNamedArg));
|
|
|
|
|
|
|
|
arg->name = GetHashNameNode("alloc");
|
|
|
|
|
|
|
|
objexpr = create_objectrefnode(tclass->objcinfo->classobject);
|
|
|
|
|
|
|
|
return CObjC_MakeSendMsgExpr(objexpr, tclass, arg, NULL, 1, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
ENode *CObjC_Delete(TypeClass *tclass, ENode *objexpr) {
|
|
|
|
ObjCNamedArg *arg;
|
|
|
|
|
|
|
|
arg = lalloc(sizeof(ObjCNamedArg));
|
|
|
|
memclrw(arg, sizeof(ObjCNamedArg));
|
|
|
|
|
|
|
|
arg->name = GetHashNameNode("dealloc");
|
|
|
|
|
|
|
|
return CObjC_MakeSendMsgExpr(objexpr, tclass, arg, NULL, 0, 0);
|
|
|
|
}
|