EXPRESSION *anonymousVar(enum e_sc storage_class, TYPE *tp) { static int anonct = 1; char buf[256]; SYMBOL *rv = (SYMBOL *)Alloc(sizeof(SYMBOL)); // if ((storage_class == sc_localstatic || storage_class == sc_auto) && !theCurrentFunc) // { // storage_class = sc_static; // insertInitSym(rv); // } if (tp->size == 0 && isstructured(tp)) tp = basetype(tp)->sp->tp; rv->storage_class = storage_class; rv->tp = tp; rv->anonymous = TRUE; rv->allocate = !anonymousNotAlloc; rv->assigned = TRUE; rv->used = TRUE; if (theCurrentFunc) rv->value.i = theCurrentFunc->value.i; sprintf(buf,"$anontemp%d", anonct++); rv->name = litlate(buf); tp->size = basetype(tp)->size; if (theCurrentFunc && !inDefaultParam) InsertSymbol(rv, storage_class, FALSE, FALSE); SetLinkerNames(rv, lk_none); return varNode(storage_class == sc_auto || storage_class == sc_parameter ? en_auto : storage_class == sc_localstatic ? en_label : en_global, rv); }
void insertOverload(SYMBOL *in, HASHTABLE *table) { if (cparams.prm_extwarning) if (in->storage_class == sc_parameter || in->storage_class == sc_auto || in->storage_class == sc_register) { SYMBOL *sp; if ((sp = gsearch(in->name)) != NULL) preverror(ERR_VARIABLE_OBSCURES_VARIABLE_AT_HIGHER_SCOPE, in->name, sp->declfile, sp->declline); } if (AddOverloadName(in, table)) { #ifdef CPREPROCESSOR pperrorstr(ERR_DUPLICATE_IDENTIFIER, in->name); #else SetLinkerNames(in, lk_cdecl); preverrorsym(ERR_DUPLICATE_IDENTIFIER, in, in->declfile, in->declline); #endif } }
LEXEME *expression_lambda(LEXEME *lex, SYMBOL *funcsp, TYPE *atp, TYPE **tp, EXPRESSION **exp, int flags) { LAMBDA *self; SYMBOL *vpl, *ths; HASHREC *hrl; TYPE *ltp; STRUCTSYM ssl; if (funcsp) funcsp->noinline = TRUE; IncGlobalFlag(); self = Alloc(sizeof(LAMBDA)); ltp = Alloc(sizeof(TYPE)); ltp->type = bt_struct; ltp->syms = CreateHashTable(1); ltp->tags = CreateHashTable(1); ltp->size = 0; self->captured = CreateHashTable(1); self->oldSyms = localNameSpace->syms; self->oldTags = localNameSpace->tags; self->index = lambdaIndex; self->captureMode = cmNone; self->isMutable = FALSE; self->captureThis = FALSE; self->cls = makeID(sc_type, ltp, NULL, LambdaName()); ltp->sp = self->cls; SetLinkerNames(self->cls, lk_cdecl); self->cls->islambda = TRUE; self->cls->structAlign = getAlign(sc_global, &stdpointer); self->func = makeID(sc_member, ltp, NULL, "$internalFunc"); self->func->parentClass = self->cls; self->functp = &stdauto; self->enclosingFunc = theCurrentFunc; if (lambdas) lambdas->prev = self; self->next = lambdas; lambdas = self; localNameSpace->syms = CreateHashTable(1); localNameSpace->tags = CreateHashTable(1); if (lambdas->next) { self->lthis = lambdas->next->lthis; } else if (funcsp && funcsp->parentClass) { self->lthis = ((SYMBOL *)funcsp->tp->syms->table[0]->p); } lex = getsym(); // past [ if (funcsp) { // can have a capture list; if (MATCHKW(lex, assign)) { lex = getsym(); if (MATCHKW(lex, comma) || MATCHKW(lex, closebr)) { self->captureMode = cmValue; skip(&lex, comma); } else { lex = backupsym(); } } else if (MATCHKW(lex, and)) { lex = getsym(); if (MATCHKW(lex, comma) || MATCHKW(lex, closebr)) { self->captureMode = cmRef; skip(&lex, comma); } else { lex = backupsym(); } } if (!MATCHKW(lex, comma) && !MATCHKW(lex, closebr)) { do { enum e_cm localMode = self->captureMode; if (MATCHKW(lex, comma)) skip(&lex, comma); if (MATCHKW(lex, kw_this)) { lex = getsym(); if (localMode == cmValue || !self->lthis) { error(ERR_CANNOT_CAPTURE_THIS); } else { if (self->captureThis) { error(ERR_CAPTURE_ITEM_LISTED_MULTIPLE_TIMES); } self->captureThis = TRUE; lambda_capture(NULL, cmThis, TRUE); } continue; } else if (MATCHKW(lex, and)) { if (localMode == cmRef) { error(ERR_INVALID_LAMBDA_CAPTURE_MODE); } localMode = cmRef; lex = getsym(); } else { if (localMode == cmValue) { error(ERR_INVALID_LAMBDA_CAPTURE_MODE); } localMode = cmValue; } if (ISID(lex)) { SYMBOL *sp = search(lex->value.s.a, localNameSpace->syms); LAMBDA *current = lambdas; while (current && !sp) { sp = search(lex->value.s.a, current->oldSyms); current = current->next; } lex = getsym(); if (sp) { if (sp->packed) { if (!MATCHKW(lex, ellipse)) error(ERR_PACK_SPECIFIER_REQUIRED_HERE); else lex = getsym(); } if (sp->packed) { int n; TEMPLATEPARAMLIST * templateParam = sp->tp->templateParam->p->byPack.pack; HASHREC *hr; for (n=0; templateParam; templateParam = templateParam->next, n++); hr = funcsp->tp->syms->table[0]; while (hr && ((SYMBOL *)hr->p) != sp) hr = hr->next; while (hr && n) { lambda_capture((SYMBOL *)hr->p, localMode, TRUE); hr = hr->next; n--; } } else { lambda_capture(sp, localMode, TRUE); } } else errorstr(ERR_UNDEFINED_IDENTIFIER, lex->value.s.a); } else { error(ERR_INVALID_LAMBDA_CAPTURE_MODE); } } while (MATCHKW(lex, comma)); } needkw(&lex, closebr); } else { if (!MATCHKW(lex, closebr)) { error(ERR_LAMBDA_CANNOT_CAPTURE); } else { lex = getsym(); } } if (MATCHKW(lex, openpa)) { TYPE *tpx = &stdvoid; HASHREC *hr; lex = getFunctionParams(lex, NULL, &self->func, &tpx, FALSE, sc_auto); self->funcargs = self->func->tp->syms->table[0]; hr = self->func->tp->syms->table[0]; while (hr) { SYMBOL *sym = (SYMBOL *)hr->p; if (sym->init) { error(ERR_CANNOT_DEFAULT_PARAMETERS_WITH_LAMBDA); } hr = hr->next; } if (MATCHKW(lex, kw_mutable)) { HASHREC *hr = self->captured->table[0]; while (hr) { LAMBDASP *lsp = (LAMBDASP *)hr->p; if (lsp->sym->lambdaMode == cmValue) { lsp->sym->tp = basetype(lsp->sym->tp); } hr = hr->next; } self->isMutable = TRUE; lex = getsym(); } ParseAttributeSpecifiers(&lex, funcsp, TRUE); if (MATCHKW(lex, pointsto)) { lex = getsym(); lex = get_type_id(lex, &self->functp, funcsp, sc_cast, FALSE, TRUE); } } else { TYPE *tp1 = Alloc(sizeof(TYPE)); SYMBOL *spi; tp1->type = bt_func; tp1->size = getSize(bt_pointer); tp1->btp = &stdvoid; tp1->sp = self->func; self->func->tp = tp1; spi = makeID(sc_parameter, tp1, NULL, AnonymousName()); spi->anonymous = TRUE; spi->tp = Alloc(sizeof(TYPE)); spi->tp->type = bt_void; insert(spi, localNameSpace->syms); SetLinkerNames(spi, lk_cpp); self->func->tp->syms = localNameSpace->syms; self->funcargs = self->func->tp->syms->table[0]; self->func->tp->syms->table[0] = NULL; } vpl = makeID(sc_parameter, &stdpointer, NULL, AnonymousName()); vpl->assigned = vpl->used = TRUE; SetLinkerNames(vpl, lk_cdecl); hrl = Alloc(sizeof(HASHREC)); hrl->p = (struct _hrintern_ *)vpl; hrl->next = lambdas->func->tp->syms->table[0]; lambdas->func->tp->syms->table[0] = hrl; vpl = makeID(sc_parameter, &stdpointer, NULL, AnonymousName()); vpl->assigned = vpl->used = TRUE; SetLinkerNames(vpl, lk_cdecl); hrl = Alloc(sizeof(HASHREC)); hrl->p = (struct _hrintern_ *)vpl; hrl->next = lambdas->func->tp->syms->table[0]; lambdas->func->tp->syms->table[0] = hrl; SetLinkerNames(lambdas->func, lk_cdecl); injectThisPtr(lambdas->func, basetype(lambdas->func->tp)->syms); lambdas->func->tp->btp = self->functp; lambdas->func->linkage = lk_virtual; lambdas->func->isInline = TRUE; ssl.str = self->cls; ssl.tmpl = NULL; addStructureDeclaration(&ssl); ths = makeID(sc_member, &stdpointer, NULL, "$this"); lambda_insert(ths, lambdas); if (MATCHKW(lex, begin)) { lex = body(lex, self->func); } else { error(ERR_LAMBDA_FUNCTION_BODY_EXPECTED); } dropStructureDeclaration(); localNameSpace->syms = self->oldSyms; localNameSpace->tags = self->oldTags; inferType(); finishClass(); *exp = createLambda(0); *tp = lambdas->cls->tp; lambdas = lambdas->next; if (lambdas) lambdas->prev = NULL; DecGlobalFlag(); return lex; }
static EXPRESSION *createLambda(BOOLEAN noinline) { EXPRESSION *rv = NULL, **cur = &rv; HASHREC *hr; EXPRESSION *clsThs, *parentThs; SYMBOL *cls = makeID(lambdas->enclosingFunc ? sc_auto : sc_localstatic, lambdas->cls->tp, NULL, AnonymousName()); SetLinkerNames(cls, lk_cdecl); cls->allocate = TRUE; if (lambdas->enclosingFunc) { insert(cls, localNameSpace->syms); clsThs = varNode(en_auto, cls); // this ptr } else { insert(cls, globalNameSpace->syms); // well if we could put this as an auto in the init func that would be good but there is no way to do that here... clsThs = varNode(en_label, cls); // this ptr cls->label = nextLabel++; insertInitSym(cls); } { INITIALIZER *init = NULL; EXPRESSION *exp = clsThs; callDestructor(cls, NULL, &exp, NULL, TRUE, FALSE, FALSE); initInsert(&init, cls->tp, exp, 0, TRUE); if (cls->storage_class != sc_auto) { insertDynamicDestructor(cls, init); } else { cls->dest = init; } } parentThs = varNode(en_auto, (SYMBOL *)basetype(lambdas->func->tp)->syms->table[0]->p); // this ptr hr = lambdas->cls->tp->syms->table[0]; while (hr) { SYMBOL *sp = (SYMBOL *)hr->p; EXPRESSION *en = NULL, *en1 = NULL; if (!strcmp(sp->name, "$self")) { en1 = clsThs; en = varNode(en_label, sp); deref(&stdpointer, &en); en = exprNode(en_assign, en, en1); } else if (!strcmp(sp->name, "$parent")) { en1 = parentThs; // get parent from function call deref(&stdpointer, &en1); en = exprNode(en_add, clsThs, intNode(en_c_i, sp->offset)) ; deref(&stdpointer, &en); en = exprNode(en_assign, en, en1); } else if (!strcmp(sp->name, "$this")) { if (!lambdas->next || !lambdas->captureThis) { en1 = parentThs; // get parent from function call } else { SYMBOL *parent = search("$parent", lambdas->cls->tp->syms); en1 = varNode(en_auto, cls); deref(&stdpointer, &en1); en1 = exprNode(en_add, en1, intNode(en_c_i, parent->offset)); } deref(&stdpointer, &en1); en = exprNode(en_add, clsThs, intNode(en_c_i, sp->offset)) ; deref(&stdpointer, &en); en = exprNode(en_assign, en, en1); } else if (sp->lambdaMode) { LAMBDASP *lsp = (LAMBDASP *)search(sp->name, lambdas->captured); if (lsp) { en1 = exprNode(en_add, clsThs, intNode(en_c_i, sp->offset)); if (sp->lambdaMode == cmRef) { SYMBOL *capture = lsp->parent; deref(&stdpointer, &en1); if (capture->lambdaMode) { en = parentThs; deref(&stdpointer, &en); en = exprNode(en_add, en, intNode(en_c_i, capture->offset)); } else // must be an sc_auto { en = varNode(en_auto, capture); } if (isref(capture->tp)) { deref(&stdpointer, &en); } en = exprNode(en_assign, en1, en); } else // cmValue { SYMBOL *capture = lsp->parent; TYPE *ctp = capture->tp; if (capture->lambdaMode) { en = parentThs; deref(&stdpointer, &en); en = exprNode(en_add, en, intNode(en_c_i, capture->offset)); } else // must be an sc_auto { en = varNode(en_auto, capture); } if (isref(ctp)) { ctp = basetype(ctp)->btp; deref(&stdpointer, &en); } if (isstructured(ctp)) { FUNCTIONCALL *params = (FUNCTIONCALL *)Alloc(sizeof(FUNCTIONCALL)); params->arguments = (INITLIST *)Alloc(sizeof(INITLIST)); params->arguments->tp = ctp; params->arguments->exp = en; if (!callConstructor(&ctp, &en1, params, FALSE, NULL, TRUE, FALSE, TRUE, FALSE, FALSE)) errorsym(ERR_NO_APPROPRIATE_CONSTRUCTOR, lsp->sym); en = en1; } else { deref(ctp, &en1); deref(ctp, &en); en = exprNode(en_assign, en1, en); } } } else { diag("createLambda: no capture var"); } } if (en) { *cur = exprNode(en_void, en, NULL); cur = &(*cur)->right; } hr = hr->next; } *cur = clsThs; // this expression will be used in copy constructors, or discarded if unneeded return rv; }