SEXP attribute_hidden do_subset2_dflt(SEXP call, SEXP op, SEXP args, SEXP rho) { SEXP ans, dims, dimnames, indx, subs, x; int i, ndims, nsubs; int drop = 1, pok, exact = -1; int named_x; R_xlen_t offset = 0; PROTECT(args); ExtractDropArg(args, &drop); /* Is partial matching ok? When the exact arg is NA, a warning is issued if partial matching occurs. */ exact = ExtractExactArg(args); if (exact == -1) pok = exact; else pok = !exact; x = CAR(args); /* This code was intended for compatibility with S, */ /* but in fact S does not do this. Will anyone notice? */ if (x == R_NilValue) { UNPROTECT(1); /* args */ return x; } /* Get the subscripting and dimensioning information */ /* and check that any array subscripting is compatible. */ subs = CDR(args); if(0 == (nsubs = length(subs))) errorcall(call, _("no index specified")); dims = getAttrib(x, R_DimSymbol); ndims = length(dims); if(nsubs > 1 && nsubs != ndims) errorcall(call, _("incorrect number of subscripts")); /* code to allow classes to extend environment */ if(TYPEOF(x) == S4SXP) { x = R_getS4DataSlot(x, ANYSXP); if(x == R_NilValue) errorcall(call, _("this S4 class is not subsettable")); } PROTECT(x); /* split out ENVSXP for now */ if( TYPEOF(x) == ENVSXP ) { if( nsubs != 1 || !isString(CAR(subs)) || length(CAR(subs)) != 1 ) errorcall(call, _("wrong arguments for subsetting an environment")); ans = findVarInFrame(x, installTrChar(STRING_ELT(CAR(subs), 0))); if( TYPEOF(ans) == PROMSXP ) { PROTECT(ans); ans = eval(ans, R_GlobalEnv); UNPROTECT(1); /* ans */ } else SET_NAMED(ans, 2); UNPROTECT(2); /* args, x */ if(ans == R_UnboundValue) return(R_NilValue); if (NAMED(ans)) SET_NAMED(ans, 2); return ans; } /* back to the regular program */ if (!(isVector(x) || isList(x) || isLanguage(x))) errorcall(call, R_MSG_ob_nonsub, type2char(TYPEOF(x))); named_x = NAMED(x); /* x may change below; save this now. See PR#13411 */ if(nsubs == 1) { /* vector indexing */ SEXP thesub = CAR(subs); int len = length(thesub); if (len > 1) { #ifdef SWITCH_TO_REFCNT if (IS_GETTER_CALL(call)) { /* this is (most likely) a getter call in a complex assighment so we duplicate as needed. The original x should have been duplicated if it might be shared */ if (MAYBE_SHARED(x)) error("getter call used outside of a complex assignment."); x = vectorIndex(x, thesub, 0, len-1, pok, call, TRUE); } else x = vectorIndex(x, thesub, 0, len-1, pok, call, FALSE); #else x = vectorIndex(x, thesub, 0, len-1, pok, call, FALSE); #endif named_x = NAMED(x); UNPROTECT(1); /* x */ PROTECT(x); } SEXP xnames = PROTECT(getAttrib(x, R_NamesSymbol)); offset = get1index(thesub, xnames, xlength(x), pok, len > 1 ? len-1 : -1, call); UNPROTECT(1); /* xnames */ if (offset < 0 || offset >= xlength(x)) { /* a bold attempt to get the same behaviour for $ and [[ */ if (offset < 0 && (isNewList(x) || isExpression(x) || isList(x) || isLanguage(x))) { UNPROTECT(2); /* args, x */ return R_NilValue; } else errorcall(call, R_MSG_subs_o_b); } } else { /* matrix indexing */ /* Here we use the fact that: */ /* CAR(R_NilValue) = R_NilValue */ /* CDR(R_NilValue) = R_NilValue */ int ndn; /* Number of dimnames. Unlikely to be anything but 0 or nsubs, but just in case... */ PROTECT(indx = allocVector(INTSXP, nsubs)); dimnames = getAttrib(x, R_DimNamesSymbol); ndn = length(dimnames); for (i = 0; i < nsubs; i++) { INTEGER(indx)[i] = (int) get1index(CAR(subs), (i < ndn) ? VECTOR_ELT(dimnames, i) : R_NilValue, INTEGER(indx)[i], pok, -1, call); subs = CDR(subs); if (INTEGER(indx)[i] < 0 || INTEGER(indx)[i] >= INTEGER(dims)[i]) errorcall(call, R_MSG_subs_o_b); } offset = 0; for (i = (nsubs - 1); i > 0; i--) offset = (offset + INTEGER(indx)[i]) * INTEGER(dims)[i - 1]; offset += INTEGER(indx)[0]; UNPROTECT(1); /* indx */ } if(isPairList(x)) { #ifdef LONG_VECTOR_SUPPORT if (offset > R_SHORT_LEN_MAX) error("invalid subscript for pairlist"); #endif ans = CAR(nthcdr(x, (int) offset)); if (named_x > NAMED(ans)) SET_NAMED(ans, named_x); } else if(isVectorList(x)) { /* did unconditional duplication before 2.4.0 */ ans = VECTOR_ELT(x, offset); if (named_x > NAMED(ans)) SET_NAMED(ans, named_x); } else { ans = allocVector(TYPEOF(x), 1); switch (TYPEOF(x)) { case LGLSXP: case INTSXP: INTEGER(ans)[0] = INTEGER(x)[offset]; break; case REALSXP: REAL(ans)[0] = REAL(x)[offset]; break; case CPLXSXP: COMPLEX(ans)[0] = COMPLEX(x)[offset]; break; case STRSXP: SET_STRING_ELT(ans, 0, STRING_ELT(x, offset)); break; case RAWSXP: RAW(ans)[0] = RAW(x)[offset]; break; default: UNIMPLEMENTED_TYPE("do_subset2", x); } } UNPROTECT(2); /* args, x */ return ans; }
// push negation as far down as possible, use demorgan's laws // ~(A && B) identical to (~A || ~B), and // ~(A || B) identical to (~A && ~B) // int Semantic::demorgans() { // check if atomic or an expression if (!isExpression()) return(OK); // remove multiple NOTs, // use ~~A <--> A and // use ~~~A <--> ~A rules. // if (removeExtraNots() != OK) return(NOTOK); // check if atomic or an expression. this second check // is required since it is possible that when all extra // negations are removed, only an Atomic is left. // if (!isExpression()) return(OK); // check if we have a negated expression Expression *pe = (Expression *)prep; if (pe->type != Expression::Negation) { // not a negated expression, check left and right if (pe->left != NULL && pe->left->demorgans() != OK) return(NOTOK); if (pe->right != NULL && pe->right->demorgans() != OK) return(NOTOK); return(OK); } // we have a negation, check if rhs is atomic or an expression. Semantic *prs = pe->right; if (!(prs->isExpression())) { // what is negated is NOT an expression, just return. return(OK); } // check if expression is an AND or OR Expression *pre = (Expression *)prs->prep; if (pre->type != Expression::Or && pre->type != Expression::And) { // not a AND or OR expression, check left and right if (pre->left != NULL && pre->left->demorgans() != OK) return(NOTOK); if (pre->right != NULL && pre->right->demorgans() != OK) return(NOTOK); return(OK); } // we have a negated AND or OR expression, apply demorgans laws. Semantic *prels = pre->left; Semantic *prers = pre->right; // create new negation records Semantic *pnegls = new Semantic(Expression::Negation, NULL, prels); MustBeTrue(pnegls != NULL); Semantic *pnegrs = new Semantic(Expression::Negation, NULL, prers); MustBeTrue(pnegrs != NULL); // write over negation record with the new record info pe->left = pnegls; pe->right = pnegrs; switch (pre->type) { case Expression::Or: pe->type = Expression::And; break; case Expression::And: pe->type = Expression::Or; break; default: MustBeTrue(0); break; } // delete old right semantic record pre->left = NULL; pre->right = NULL; delete prs; // check left and right sides if (pe->left != NULL && pe->left->demorgans() != OK) return(NOTOK); if (pe->right != NULL && pe->right->demorgans() != OK) return(NOTOK); // all done return(OK); }
/* Calculate the bounding rectangle for a string. * x and y assumed to be in INCHES. */ void textRect(double x, double y, SEXP text, int i, const pGEcontext gc, double xadj, double yadj, double rot, pGEDevDesc dd, LRect *r) { /* NOTE that we must work in inches for the angles to be correct */ LLocation bl, br, tr, tl; LLocation tbl, tbr, ttr, ttl; LTransform thisLocation, thisRotation, thisJustification; LTransform tempTransform, transform; double w, h; if (isExpression(text)) { SEXP expr = VECTOR_ELT(text, i % LENGTH(text)); w = fromDeviceWidth(GEExpressionWidth(expr, gc, dd), GE_INCHES, dd); h = fromDeviceHeight(GEExpressionHeight(expr, gc, dd), GE_INCHES, dd); } else { const char* string = CHAR(STRING_ELT(text, i % LENGTH(text))); w = fromDeviceWidth(GEStrWidth(string, (gc->fontface == 5) ? CE_SYMBOL : getCharCE(STRING_ELT(text, i % LENGTH(text))), gc, dd), GE_INCHES, dd); h = fromDeviceHeight(GEStrHeight(string, (gc->fontface == 5) ? CE_SYMBOL : getCharCE(STRING_ELT(text, i % LENGTH(text))), gc, dd), GE_INCHES, dd); } location(0, 0, bl); location(w, 0, br); location(w, h, tr); location(0, h, tl); translation(-xadj*w, -yadj*h, thisJustification); translation(x, y, thisLocation); if (rot != 0) rotation(rot, thisRotation); else identity(thisRotation); /* Position relative to origin of rotation THEN rotate. */ multiply(thisJustification, thisRotation, tempTransform); /* Translate to (x, y) */ multiply(tempTransform, thisLocation, transform); trans(bl, transform, tbl); trans(br, transform, tbr); trans(tr, transform, ttr); trans(tl, transform, ttl); rect(locationX(tbl), locationX(tbr), locationX(ttr), locationX(ttl), locationY(tbl), locationY(tbr), locationY(ttr), locationY(ttl), r); /* For debugging, the following prints out an R statement to draw the * bounding box */ /* Rprintf("\ngrid.lines(c(%f, %f, %f, %f, %f), c(%f, %f, %f, %f, %f), default.units=\"inches\")\n", locationX(tbl), locationX(tbr), locationX(ttr), locationX(ttl), locationX(tbl), locationY(tbl), locationY(tbr), locationY(ttr), locationY(ttl), locationY(tbl) ); */ }
// remove existential quantifier by using skolem functions. all skolem // functions must be unique. remember that the skolem function is dependent // on any universal variables that are in scope. // int Semantic::skolemize(List<Symbol> &localscope) { // check if expression or predicate if (isExpression()) { // get expression Expression *pe = (Expression *)prep; // what type is it if (pe->type == Expression::Universal) { // store universal variable localscope.insertAtEnd(Symbol(pe->name, Symbol::UniversalVariable)); // follow right leg, left leg is null MustBeTrue(pe->left == NULL && pe->right != NULL); if (pe->right->skolemize(localscope) != OK) return(NOTOK); // remove universal variable Symbol tmp; localscope.removeAtEnd(tmp); } else if (pe->type == Expression::Existential) { // store existential variable String uname = uniqueName(String("_SK")); localscope.insertAtEnd(Symbol(pe->name, uname, Symbol::ExistentialVariable)); // follow right leg, left leg is null MustBeTrue(pe->left == NULL && pe->right != NULL); if (pe->right->skolemize(localscope) != OK) return(NOTOK); // remove existential variable Symbol tmp; localscope.removeAtEnd(tmp); } else { // follow down other expression operators if (pe->left != NULL && pe->left->skolemize(localscope) != OK) return(NOTOK); if (pe->right != NULL && pe->right->skolemize(localscope) != OK) return(NOTOK); } } else if (isPredicate()) { // get predicate Predicate *pp = (Predicate *)prep; // check for functions if (pp->type == Predicate::Function) { // cycle thru arguments ListIterator<Semantic * > pargsIter(*pp->pargs); for ( ; !pargsIter.done(); pargsIter++) { Semantic *parg = pargsIter(); if (parg != NULL && parg->skolemize(localscope) != OK) return(NOTOK); } } } else if (isArgument()) { // check type of argument Argument *pa = (Argument *)prep; switch (pa->type) { case Argument::Variable: { // check if an existential variable Symbol qvarsym(pa->name); if(localscope.retrieve(qvarsym) != OK) break; if (qvarsym.getType() != Symbol::ExistentialVariable) break; // we have an existential variable String skolemName(qvarsym.getUniqueName()); // need to replace this variable with a // skolem function which is dependent on all // universal variables in scope at this time. // List<Semantic * > *pargs = new List<Semantic * >; MustBeTrue(pargs != NULL); ListIterator<Symbol> scopeIter(localscope); int nargs; for (nargs = 0; !scopeIter.done(); scopeIter++) { // get symbol Symbol uvar = scopeIter(); // check if we found the current // symbol. this marks the end of // dependent variables for the // skolem function. all other // existential variables are skipped. // if (uvar.getType() == Symbol::ExistentialVariable) { if (uvar == Symbol(pa->name)) break; else continue; } // we have a universal variable in // scope // Semantic *parg = new Semantic( Argument::Variable, uvar.getName()); MustBeTrue(parg != NULL); pargs->insertAtEnd(parg); nargs++; } if (nargs == 0) { // skolem constant pa->type = Argument::Constant; pa->name = skolemName; pa->pargs = NULL; pa->argnum = 0; // delete unused argument list delete pargs; } else { // skolem function pa->type = Argument::Function; pa->name = skolemName; pa->pargs = pargs; pa->argnum = nargs; } break; } case Argument::Function: { // we have a function, scan its arguments ListIterator<Semantic *> pargsIter(*pa->pargs); for ( ; !pargsIter.done(); pargsIter++) { Semantic *parg = pargsIter(); if (parg != NULL && parg->skolemize(localscope) != OK) return(NOTOK); } break; } } } else { MustBeTrue(0); } // all done return(OK); }
int Semantic::skolemize() { // check if expression or predicate // if it's a predicate, there is nothing to do // since we are at the beginning of the expression, // and quantifiers are expressions. // if (!isExpression()) return(OK); // list of variables in scope List<Symbol> localscope; // get expression Expression *pe = (Expression *)prep; // what type is it if (pe->type == Expression::Universal) { // store universal variable localscope.insertAtEnd(Symbol(pe->name, Symbol::UniversalVariable)); // follow right leg, left leg is null MustBeTrue(pe->left == NULL && pe->right != NULL); if (pe->right->skolemize(localscope) != OK) return(NOTOK); // remove universal variable Symbol tmp; localscope.removeAtEnd(tmp); } else if (pe->type == Expression::Existential) { // store existential variable String uname = uniqueName(String("_SK")); localscope.insertAtEnd(Symbol(pe->name, uname, Symbol::ExistentialVariable)); // follow right leg, left leg is null MustBeTrue(pe->left == NULL && pe->right != NULL); if (pe->right->skolemize(localscope) != OK) return(NOTOK); // remove existential variable Symbol tmp(pe->name); localscope.removeAtEnd(tmp); } else { // follow down other expression operators if (pe->left != NULL && pe->left->skolemize(localscope) != OK) return(NOTOK); if (pe->right != NULL && pe->right->skolemize(localscope) != OK) return(NOTOK); } // scan one more time to remove existential records return(removeExistentials()); }
Expression *semanticTraits(TraitsExp *e, Scope *sc) { #if LOGSEMANTIC printf("TraitsExp::semantic() %s\n", e->toChars()); #endif if (e->ident != Id::compiles && e->ident != Id::isSame && e->ident != Id::identifier && e->ident != Id::getProtection) { if (!TemplateInstance::semanticTiargs(e->loc, sc, e->args, 1)) return new ErrorExp(); } size_t dim = e->args ? e->args->dim : 0; if (e->ident == Id::isArithmetic) { return isTypeX(e, &isTypeArithmetic); } else if (e->ident == Id::isFloating) { return isTypeX(e, &isTypeFloating); } else if (e->ident == Id::isIntegral) { return isTypeX(e, &isTypeIntegral); } else if (e->ident == Id::isScalar) { return isTypeX(e, &isTypeScalar); } else if (e->ident == Id::isUnsigned) { return isTypeX(e, &isTypeUnsigned); } else if (e->ident == Id::isAssociativeArray) { return isTypeX(e, &isTypeAssociativeArray); } else if (e->ident == Id::isStaticArray) { return isTypeX(e, &isTypeStaticArray); } else if (e->ident == Id::isAbstractClass) { return isTypeX(e, &isTypeAbstractClass); } else if (e->ident == Id::isFinalClass) { return isTypeX(e, &isTypeFinalClass); } else if (e->ident == Id::isPOD) { if (dim != 1) goto Ldimerror; RootObject *o = (*e->args)[0]; Type *t = isType(o); StructDeclaration *sd; if (!t) { e->error("type expected as second argument of __traits %s instead of %s", e->ident->toChars(), o->toChars()); goto Lfalse; } Type *tb = t->baseElemOf(); if (tb->ty == Tstruct && ((sd = (StructDeclaration *)(((TypeStruct *)tb)->sym)) != NULL)) { if (sd->isPOD()) goto Ltrue; else goto Lfalse; } goto Ltrue; } else if (e->ident == Id::isNested) { if (dim != 1) goto Ldimerror; RootObject *o = (*e->args)[0]; Dsymbol *s = getDsymbol(o); AggregateDeclaration *a; FuncDeclaration *f; if (!s) { } else if ((a = s->isAggregateDeclaration()) != NULL) { if (a->isNested()) goto Ltrue; else goto Lfalse; } else if ((f = s->isFuncDeclaration()) != NULL) { if (f->isNested()) goto Ltrue; else goto Lfalse; } e->error("aggregate or function expected instead of '%s'", o->toChars()); goto Lfalse; } else if (e->ident == Id::isAbstractFunction) { return isFuncX(e, &isFuncAbstractFunction); } else if (e->ident == Id::isVirtualFunction) { return isFuncX(e, &isFuncVirtualFunction); } else if (e->ident == Id::isVirtualMethod) { return isFuncX(e, &isFuncVirtualMethod); } else if (e->ident == Id::isFinalFunction) { return isFuncX(e, &isFuncFinalFunction); } else if (e->ident == Id::isOverrideFunction) { return isFuncX(e, &isFuncOverrideFunction); } else if (e->ident == Id::isStaticFunction) { return isFuncX(e, &isFuncStaticFunction); } else if (e->ident == Id::isRef) { return isDeclX(e, &isDeclRef); } else if (e->ident == Id::isOut) { return isDeclX(e, &isDeclOut); } else if (e->ident == Id::isLazy) { return isDeclX(e, &isDeclLazy); } else if (e->ident == Id::identifier) { // Get identifier for symbol as a string literal /* Specify 0 for bit 0 of the flags argument to semanticTiargs() so that * a symbol should not be folded to a constant. * Bit 1 means don't convert Parameter to Type if Parameter has an identifier */ if (!TemplateInstance::semanticTiargs(e->loc, sc, e->args, 2)) return new ErrorExp(); if (dim != 1) goto Ldimerror; RootObject *o = (*e->args)[0]; Parameter *po = isParameter(o); Identifier *id; if (po) { id = po->ident; assert(id); } else { Dsymbol *s = getDsymbol(o); if (!s || !s->ident) { e->error("argument %s has no identifier", o->toChars()); goto Lfalse; } id = s->ident; } StringExp *se = new StringExp(e->loc, id->toChars()); return se->semantic(sc); } else if (e->ident == Id::getProtection) { if (dim != 1) goto Ldimerror; Scope *sc2 = sc->push(); sc2->flags = sc->flags | SCOPEnoaccesscheck; bool ok = TemplateInstance::semanticTiargs(e->loc, sc2, e->args, 1); sc2->pop(); if (!ok) return new ErrorExp(); RootObject *o = (*e->args)[0]; Dsymbol *s = getDsymbol(o); if (!s) { if (!isError(o)) e->error("argument %s has no protection", o->toChars()); goto Lfalse; } if (s->scope) s->semantic(s->scope); PROT protection = s->prot(); const char *protName = Pprotectionnames[protection]; assert(protName); StringExp *se = new StringExp(e->loc, (char *) protName); return se->semantic(sc); } else if (e->ident == Id::parent) { if (dim != 1) goto Ldimerror; RootObject *o = (*e->args)[0]; Dsymbol *s = getDsymbol(o); if (s) { if (FuncDeclaration *fd = s->isFuncDeclaration()) // Bugzilla 8943 s = fd->toAliasFunc(); if (!s->isImport()) // Bugzilla 8922 s = s->toParent(); } if (!s || s->isImport()) { e->error("argument %s has no parent", o->toChars()); goto Lfalse; } if (FuncDeclaration *f = s->isFuncDeclaration()) { if (TemplateDeclaration *td = getFuncTemplateDecl(f)) { if (td->overroot) // if not start of overloaded list of TemplateDeclaration's td = td->overroot; // then get the start Expression *ex = new TemplateExp(e->loc, td, f); ex = ex->semantic(sc); return ex; } if (FuncLiteralDeclaration *fld = f->isFuncLiteralDeclaration()) { // Directly translate to VarExp instead of FuncExp Expression *ex = new VarExp(e->loc, fld, 1); return ex->semantic(sc); } } return (new DsymbolExp(e->loc, s))->semantic(sc); } else if (e->ident == Id::hasMember || e->ident == Id::getMember || e->ident == Id::getOverloads || e->ident == Id::getVirtualMethods || e->ident == Id::getVirtualFunctions) { if (dim != 2) goto Ldimerror; RootObject *o = (*e->args)[0]; Expression *ex = isExpression((*e->args)[1]); if (!ex) { e->error("expression expected as second argument of __traits %s", e->ident->toChars()); goto Lfalse; } ex = ex->ctfeInterpret(); StringExp *se = ex->toStringExp(); if (!se || se->length() == 0) { e->error("string expected as second argument of __traits %s instead of %s", e->ident->toChars(), ex->toChars()); goto Lfalse; } se = se->toUTF8(sc); if (se->sz != 1) { e->error("string must be chars"); goto Lfalse; } Identifier *id = Lexer::idPool((char *)se->string); /* Prefer dsymbol, because it might need some runtime contexts. */ Dsymbol *sym = getDsymbol(o); if (sym) { ex = new DsymbolExp(e->loc, sym); ex = new DotIdExp(e->loc, ex, id); } else if (Type *t = isType(o)) ex = typeDotIdExp(e->loc, t, id); else if (Expression *ex2 = isExpression(o)) ex = new DotIdExp(e->loc, ex2, id); else { e->error("invalid first argument"); goto Lfalse; } if (e->ident == Id::hasMember) { if (sym) { Dsymbol *sm = sym->search(e->loc, id); if (sm) goto Ltrue; } /* Take any errors as meaning it wasn't found */ Scope *sc2 = sc->push(); ex = ex->trySemantic(sc2); sc2->pop(); if (!ex) goto Lfalse; else goto Ltrue; } else if (e->ident == Id::getMember) { ex = ex->semantic(sc); return ex; } else if (e->ident == Id::getVirtualFunctions || e->ident == Id::getVirtualMethods || e->ident == Id::getOverloads) { unsigned errors = global.errors; Expression *eorig = ex; ex = ex->semantic(sc); if (errors < global.errors) e->error("%s cannot be resolved", eorig->toChars()); /* Create tuple of functions of ex */ //ex->print(); Expressions *exps = new Expressions(); FuncDeclaration *f; if (ex->op == TOKvar) { VarExp *ve = (VarExp *)ex; f = ve->var->isFuncDeclaration(); ex = NULL; } else if (ex->op == TOKdotvar) { DotVarExp *dve = (DotVarExp *)ex; f = dve->var->isFuncDeclaration(); if (dve->e1->op == TOKdottype || dve->e1->op == TOKthis) ex = NULL; else ex = dve->e1; } else f = NULL; Ptrait p; p.exps = exps; p.e1 = ex; p.ident = e->ident; overloadApply(f, &p, &fptraits); TupleExp *tup = new TupleExp(e->loc, exps); return tup->semantic(sc); } else assert(0); } else if (e->ident == Id::classInstanceSize) { if (dim != 1) goto Ldimerror; RootObject *o = (*e->args)[0]; Dsymbol *s = getDsymbol(o); ClassDeclaration *cd; if (!s || (cd = s->isClassDeclaration()) == NULL) { e->error("first argument is not a class"); goto Lfalse; } if (cd->sizeok == SIZEOKnone) { if (cd->scope) cd->semantic(cd->scope); } if (cd->sizeok != SIZEOKdone) { e->error("%s %s is forward referenced", cd->kind(), cd->toChars()); goto Lfalse; } return new IntegerExp(e->loc, cd->structsize, Type::tsize_t); } else if (e->ident == Id::getAliasThis) { if (dim != 1) goto Ldimerror; RootObject *o = (*e->args)[0]; Dsymbol *s = getDsymbol(o); AggregateDeclaration *ad; if (!s || (ad = s->isAggregateDeclaration()) == NULL) { e->error("argument is not an aggregate type"); goto Lfalse; } Expressions *exps = new Expressions(); if (ad->aliasthis) exps->push(new StringExp(e->loc, ad->aliasthis->ident->toChars())); Expression *ex = new TupleExp(e->loc, exps); ex = ex->semantic(sc); return ex; } else if (e->ident == Id::getAttributes) { if (dim != 1) goto Ldimerror; RootObject *o = (*e->args)[0]; Dsymbol *s = getDsymbol(o); if (!s) { #if 0 Expression *x = isExpression(o); Type *t = isType(o); if (x) printf("e = %s %s\n", Token::toChars(x->op), x->toChars()); if (t) printf("t = %d %s\n", t->ty, t->toChars()); #endif e->error("first argument is not a symbol"); goto Lfalse; } //printf("getAttributes %s, attrs = %p, scope = %p\n", s->toChars(), s->userAttributes, s->userAttributesScope); UserAttributeDeclaration *udad = s->userAttribDecl; TupleExp *tup = new TupleExp(e->loc, udad ? udad->getAttributes() : new Expressions()); return tup->semantic(sc); } else if (e->ident == Id::getFunctionAttributes) { /// extract all function attributes as a tuple (const/shared/inout/pure/nothrow/etc) except UDAs. if (dim != 1) goto Ldimerror; RootObject *o = (*e->args)[0]; Dsymbol *s = getDsymbol(o); Type *t = isType(o); TypeFunction *tf = NULL; if (s) { if (FuncDeclaration *f = s->isFuncDeclaration()) t = f->type; else if (VarDeclaration *v = s->isVarDeclaration()) t = v->type; } if (t) { if (t->ty == Tfunction) tf = (TypeFunction *)t; else if (t->ty == Tdelegate) tf = (TypeFunction *)t->nextOf(); else if (t->ty == Tpointer && t->nextOf()->ty == Tfunction) tf = (TypeFunction *)t->nextOf(); } if (!tf) { e->error("first argument is not a function"); goto Lfalse; } Expressions *mods = new Expressions(); PushAttributes pa; pa.mods = mods; tf->modifiersApply(&pa, &PushAttributes::fp); tf->attributesApply(&pa, &PushAttributes::fp, TRUSTformatSystem); TupleExp *tup = new TupleExp(e->loc, mods); return tup->semantic(sc); } else if (e->ident == Id::allMembers || e->ident == Id::derivedMembers) { if (dim != 1) goto Ldimerror; RootObject *o = (*e->args)[0]; Dsymbol *s = getDsymbol(o); ScopeDsymbol *sds; if (!s) { e->error("argument has no members"); goto Lfalse; } Import *import; if ((import = s->isImport()) != NULL) { // Bugzilla 9692 sds = import->mod; } else if ((sds = s->isScopeDsymbol()) == NULL) { e->error("%s %s has no members", s->kind(), s->toChars()); goto Lfalse; } // use a struct as local function struct PushIdentsDg { static int dg(void *ctx, size_t n, Dsymbol *sm) { if (!sm) return 1; //printf("\t[%i] %s %s\n", i, sm->kind(), sm->toChars()); if (sm->ident) { if (sm->ident != Id::ctor && sm->ident != Id::dtor && sm->ident != Id::_postblit && memcmp(sm->ident->string, "__", 2) == 0) { return 0; } //printf("\t%s\n", sm->ident->toChars()); Identifiers *idents = (Identifiers *)ctx; /* Skip if already present in idents[] */ for (size_t j = 0; j < idents->dim; j++) { Identifier *id = (*idents)[j]; if (id == sm->ident) return 0; #ifdef DEBUG // Avoid using strcmp in the first place due to the performance impact in an O(N^2) loop. assert(strcmp(id->toChars(), sm->ident->toChars()) != 0); #endif } idents->push(sm->ident); } else { EnumDeclaration *ed = sm->isEnumDeclaration(); if (ed) { ScopeDsymbol::foreach(NULL, ed->members, &PushIdentsDg::dg, (Identifiers *)ctx); } } return 0; } }; Identifiers *idents = new Identifiers; ScopeDsymbol::foreach(sc, sds->members, &PushIdentsDg::dg, idents); ClassDeclaration *cd = sds->isClassDeclaration(); if (cd && e->ident == Id::allMembers) { struct PushBaseMembers { static void dg(ClassDeclaration *cd, Identifiers *idents) { for (size_t i = 0; i < cd->baseclasses->dim; i++) { ClassDeclaration *cb = (*cd->baseclasses)[i]->base; ScopeDsymbol::foreach(NULL, cb->members, &PushIdentsDg::dg, idents); if (cb->baseclasses->dim) dg(cb, idents); } } }; PushBaseMembers::dg(cd, idents); } // Turn Identifiers into StringExps reusing the allocated array assert(sizeof(Expressions) == sizeof(Identifiers)); Expressions *exps = (Expressions *)idents; for (size_t i = 0; i < idents->dim; i++) { Identifier *id = (*idents)[i]; StringExp *se = new StringExp(e->loc, id->toChars()); (*exps)[i] = se; } /* Making this a tuple is more flexible, as it can be statically unrolled. * To make an array literal, enclose __traits in [ ]: * [ __traits(allMembers, ...) ] */ Expression *ex = new TupleExp(e->loc, exps); ex = ex->semantic(sc); return ex; } else if (e->ident == Id::compiles) { /* Determine if all the objects - types, expressions, or symbols - * compile without error */ if (!dim) goto Lfalse; for (size_t i = 0; i < dim; i++) { unsigned errors = global.startGagging(); unsigned oldspec = global.speculativeGag; global.speculativeGag = global.gag; Scope *sc2 = sc->push(); sc2->speculative = true; sc2->flags = sc->flags & ~SCOPEctfe | SCOPEcompile; bool err = false; RootObject *o = (*e->args)[i]; Type *t = isType(o); Expression *ex = t ? t->toExpression() : isExpression(o); if (!ex && t) { Dsymbol *s; t->resolve(e->loc, sc2, &ex, &t, &s); if (t) { t->semantic(e->loc, sc2); if (t->ty == Terror) err = true; } else if (s && s->errors) err = true; } if (ex) { ex = ex->semantic(sc2); ex = resolvePropertiesOnly(sc2, ex); ex = ex->optimize(WANTvalue); ex = checkGC(sc2, ex); if (ex->op == TOKerror) err = true; } sc2->pop(); global.speculativeGag = oldspec; if (global.endGagging(errors) || err) { goto Lfalse; } } goto Ltrue; } else if (e->ident == Id::isSame) { /* Determine if two symbols are the same */ if (dim != 2) goto Ldimerror; if (!TemplateInstance::semanticTiargs(e->loc, sc, e->args, 0)) return new ErrorExp(); RootObject *o1 = (*e->args)[0]; RootObject *o2 = (*e->args)[1]; Dsymbol *s1 = getDsymbol(o1); Dsymbol *s2 = getDsymbol(o2); //printf("isSame: %s, %s\n", o1->toChars(), o2->toChars()); #if 0 printf("o1: %p\n", o1); printf("o2: %p\n", o2); if (!s1) { Expression *ea = isExpression(o1); if (ea) printf("%s\n", ea->toChars()); Type *ta = isType(o1); if (ta) printf("%s\n", ta->toChars()); goto Lfalse; } else printf("%s %s\n", s1->kind(), s1->toChars()); #endif if (!s1 && !s2) { Expression *ea1 = isExpression(o1); Expression *ea2 = isExpression(o2); if (ea1 && ea2) { if (ea1->equals(ea2)) goto Ltrue; } } if (!s1 || !s2) goto Lfalse; s1 = s1->toAlias(); s2 = s2->toAlias(); if (s1->isFuncAliasDeclaration()) s1 = ((FuncAliasDeclaration *)s1)->toAliasFunc(); if (s2->isFuncAliasDeclaration()) s2 = ((FuncAliasDeclaration *)s2)->toAliasFunc(); if (s1 == s2) goto Ltrue; else goto Lfalse; } else if (e->ident == Id::getUnitTests) { if (dim != 1) goto Ldimerror; RootObject *o = (*e->args)[0]; Dsymbol *s = getDsymbol(o); if (!s) { e->error("argument %s to __traits(getUnitTests) must be a module or aggregate", o->toChars()); goto Lfalse; } Import *imp = s->isImport(); if (imp) // Bugzilla 10990 s = imp->mod; ScopeDsymbol* scope = s->isScopeDsymbol(); if (!scope) { e->error("argument %s to __traits(getUnitTests) must be a module or aggregate, not a %s", s->toChars(), s->kind()); goto Lfalse; } Expressions* unitTests = new Expressions(); Dsymbols* symbols = scope->members; if (global.params.useUnitTests && symbols) { // Should actually be a set AA* uniqueUnitTests = NULL; collectUnitTests(symbols, uniqueUnitTests, unitTests); } TupleExp *tup = new TupleExp(e->loc, unitTests); return tup->semantic(sc); } else if(e->ident == Id::getVirtualIndex) { if (dim != 1) goto Ldimerror; RootObject *o = (*e->args)[0]; Dsymbol *s = getDsymbol(o); FuncDeclaration *fd; if (!s || (fd = s->isFuncDeclaration()) == NULL) { e->error("first argument to __traits(getVirtualIndex) must be a function"); goto Lfalse; } fd = fd->toAliasFunc(); // Neccessary to support multiple overloads. return new IntegerExp(e->loc, fd->vtblIndex, Type::tptrdiff_t); } else { if (const char *sub = (const char *)speller(e->ident->toChars(), &trait_search_fp, NULL, idchars)) e->error("unrecognized trait '%s', did you mean '%s'?", e->ident->toChars(), sub); else e->error("unrecognized trait '%s'", e->ident->toChars()); goto Lfalse; } return NULL; Ldimerror: e->error("wrong number of arguments %d", (int)dim); goto Lfalse; Lfalse: return new IntegerExp(e->loc, 0, Type::tbool); Ltrue: return new IntegerExp(e->loc, 1, Type::tbool); }
// rename all variable names to unique names. int Semantic::renameVariables(List<Symbol> &localscope) { // check of predicate or expression if (isExpression()) { // get expression record Expression *pe = (Expression *)prep; // check if we have quantifier int popscope = 0; if (pe->type == Expression::Universal) { // we have a quantifier, rename variable popscope = 1; String uname = uniqueName(String("_Q")); localscope.insertAtFront( Symbol(pe->name, uname, Symbol::UniversalVariable)); // change name in semantic record pe->name = uname; } else if (pe->type == Expression::Existential) { // we have a quantifier, rename variable popscope = 1; String uname = uniqueName(String("_Q")); localscope.insertAtFront( Symbol(pe->name, uname, Symbol::ExistentialVariable)); // change name in semantic record pe->name = uname; } // follow left and right branches if (pe->left != NULL && pe->left->renameVariables(localscope) != OK) return(NOTOK); if (pe->right != NULL && pe->right->renameVariables(localscope) != OK) return(NOTOK); // pop scope variable if required if (popscope) { Symbol tmp; MustBeTrue(localscope.removeAtFront(tmp) == OK); } } else if (isPredicate()) { // get predicate record Predicate *pp = (Predicate *)prep; // check if a function if (pp->type == Predicate::Function) { // we have a function, scan argument list ListIterator<Semantic *> pargsIter(*pp->pargs); for ( ; !pargsIter.done(); pargsIter++) { Semantic *parg = pargsIter(); if (parg != NULL && parg->renameVariables(localscope) != OK) return(NOTOK); } } } else if (isArgument()) { // check if a variable, function or anything else Argument *pa = (Argument *)prep; if (pa->type == Argument::Variable) { // find variable in scope Symbol usym(pa->name); if (localscope.retrieve(usym) == OK) { pa->name = usym.getUniqueName(); MustBeTrue(pa->name != String("")); } } else if (pa->type == Argument::Function) { // we have a function, scan argument list ListIterator<Semantic *> pargsIter(*pa->pargs); for ( ; !pargsIter.done(); pargsIter++) { Semantic *parg = pargsIter(); if (parg != NULL && parg->renameVariables(localscope) != OK) return(NOTOK); } } } else { MustBeTrue(0); } // all done return(OK); }
// Logic: // - If it is a number then just add it to the actions vector (but adding two // times a number is not allowed as "3 4 6 =" is not a correct syntax. "3 + 6 =" would be correct.) // - If it is an expression-operation (like "3+4-") then do the operation with the operation before that // ("3+4" in the example) and add it to "left expression" (m_leftExpression). // - If it is a term-operation (like 3+4x) add the left number (3) to m_leftExpression and // the right handside number (4) of the expression operation to m_leftTerm. // - "=" and "None" as an operation means that a totally new calculation started from there, // meaning that the first number after them are just assigned to "left expression" (m_leftExpression). // After "=" and "None" the first temporary results (untill the next expression operator) // go to m_leftTerm and m_leftExpression remains zero. // return value: Returns true if input was valid otherwise false bool Calculator::addInput(const Action& input) { const Calculator::Action lastInput = getLastInput(); if (input.actionType == ActionType::Number) { // adding a number after a number would be an error -> that entry is ignored if (lastInput.actionType != ActionType::Number) m_actions.push_back(input); } else if (isOperation(input.actionType)) { if (lastInput.actionType == ActionType::Number) { ActionType lastOperation = getLastOperation(); switch (lastOperation) { case ActionType::Plus: if (isExpression(input.actionType) || input.actionType == ActionType::Equals) { // "3 + 4 -", "3 + 4 =" m_leftExpression.add(lastInput.value); m_leftTerm.reset(); } else if (isTerm(input.actionType)) { // "3 + 4 x", m_leftTerm.set(lastInput.value); } break; case ActionType::Minus: if (isExpression(input.actionType) || input.actionType == ActionType::Equals) { // "3 - 4 -", "3 - 4 =" m_leftExpression.add(-lastInput.value); m_leftTerm.reset(); } else if (isTerm(input.actionType)) { // "3 - 4 x", m_leftTerm.set(-lastInput.value); } break; case ActionType::Multiply: if (isExpression(input.actionType) || input.actionType == ActionType::Equals) { // "3 x 4 +", "3 x 4 =" m_leftExpression.add(m_leftTerm.getValue() * lastInput.value); m_leftTerm.reset(); } else if (isTerm(input.actionType)) // "3 x 4 x" m_leftTerm.multiplyBy(lastInput.value); break; case ActionType::Divide: if (isExpression(input.actionType) || input.actionType == ActionType::Equals) { if (lastInput.value == 0.0) { CalculatorException divByZeroException("Error: Cannot Divide By Zero", CalculatorException::ExceptionType::DividedByZero); throw divByZeroException; } else { // "3 / 4 +", "3 / 4 =" m_leftExpression.add(m_leftTerm.getValue() / lastInput.value); m_leftTerm.reset(); } } else if (isTerm(input.actionType)) // "3 / 4 x" m_leftTerm.multiplyBy(1.0 / lastInput.value); break; case ActionType::Equals: // "=" is the start of a new beginnning, see (h: *) if (isTerm(input.actionType)) { // "= 3 x " m_leftExpression.reset(); m_leftTerm.set(lastInput.value); } else if (isExpression(input.actionType)) { // "= 3 + " m_leftExpression.set(lastInput.value); m_leftTerm.reset(); } break; case ActionType::None: // "None" is the start of a new beginnning, see (h: *) if (isTerm(input.actionType)) { // "3 x " m_leftExpression.reset(); m_leftTerm.set(lastInput.value); } else if (isExpression(input.actionType)) { // "3 + " m_leftExpression.set(lastInput.value); m_leftTerm.reset(); } break; } m_actions.push_back(input); return true; } } return false; }
QString QgsFieldExpressionWidget::asExpression() const { return isExpression() ? currentText() : QgsExpression::quotedColumnRef( currentText() ); }
/*配列範囲外参照と未定義処理の検証式の生成*/ void writeArrayCheck(CSTLString *output, ARRAY_OFFSET_LISTIterator aoff_list_i, int undefined_control_check, int array_unbound_check){ int array_offset_level; int offset_level_counter; OFFSET_LISTIterator off_list_i; //オフセットレベルの取得 array_offset_level = OFFSET_LIST_size(ARRAY_OFFSET_LIST_data(aoff_list_i)->offset_list); //オフセットレベルが0を超える場合(すなわち、オフセット情報が存在する場合) if(array_offset_level > 0){ //配列の形を保持する情報(処理中で使用される) CSTLString *array_string = CSTLString_new(); CSTLString *basis_location_content = CSTLString_new(); CSTLString_assign(array_string, ""); CSTLString_assign(basis_location_content, ""); //オフセット情報を参照する for(offset_level_counter = 1, off_list_i = OFFSET_LIST_begin(ARRAY_OFFSET_LIST_data(aoff_list_i)->offset_list); off_list_i != OFFSET_LIST_end(ARRAY_OFFSET_LIST_data(aoff_list_i)->offset_list); offset_level_counter++, off_list_i = OFFSET_LIST_next(off_list_i)){ int is_expression_flag = isExpression(*OFFSET_LIST_data(off_list_i)); CSTLString *statement = CSTLString_new(); //未定義処理チェックフラグが成り立っている場合、 //レベルごとの未定義処理の検証式を生成する。未定義処理の検証式の形式は以下の通りである。 //if(defined_階層_変数名 == 0 && max_size_階層_変数名 == 0){ // printf("#ファイル名#:行数: detected undefine pointer access in variable 変数名); // assert(0); // リターン式; //} if(undefined_control_check){ CSTLString_printf(statement,0,"if(*defined_%d_%s%s == 0 && *malloc_flag_%d_%s%s == 0){\n", offset_level_counter, (char*)CSTLString_c_str(ARRAY_OFFSET_LIST_data(aoff_list_i)->variable_name), (char*)CSTLString_c_str(array_string), offset_level_counter, (char*)CSTLString_c_str(ARRAY_OFFSET_LIST_data(aoff_list_i)->variable_name), (char*)CSTLString_c_str(array_string) ); CSTLString_printf(statement,1,"printf(\"#%s#:%d: detected undefine pointer access in variable %s\");\n ",getFileName(), ARRAY_OFFSET_LIST_data(aoff_list_i)->target_statement->line, (char*)CSTLString_c_str(ARRAY_OFFSET_LIST_data(aoff_list_i)->variable_name)); CSTLString_printf(statement, 1, "assert(0);\n"); //リターン命令の返却型に応じる変更(もし、void型であれば、「return;」にする) if(CSTLString_compare_with_char(ARRAY_OFFSET_LIST_data(aoff_list_i)->target_statement->return_type, "void") == 0){ CSTLString_printf(statement, 1, "return;\n"); }else{ CSTLString_printf(statement, 1, "return 1;\n"); } CSTLString_printf(statement, 1, "}\n"); } //配列範囲外チェックフラグが成り立っていた場合、 //レベルごとの配列範囲外参照の検証式を生成する。配列範囲外参照の式の形式は以下の通りである //if(0 > 式 + 基本位置 || 式 + 基本位置 < 対象変数の配列長){ // printf("#ファイル名#:行数: detected unbound access in variable 変数名 basis_location = %d 式 = %d\n", basis_location, 式); // assert(0); // リターン式; //} if(array_unbound_check){ CSTLString_printf(statement,1,"if(0 > %s + basis_location_%d_%s%s){\n", *OFFSET_LIST_data(off_list_i), offset_level_counter, (char*)CSTLString_c_str(ARRAY_OFFSET_LIST_data(aoff_list_i)->variable_name), (char*)CSTLString_c_str(array_string)); /* CSTLString_printf(statement,1,"printf(\"#%s#:%d:detected unbound access in variable %s ",getFileName(), ARRAY_OFFSET_LIST_data(aoff_list_i)->target_statement->line, (char*)CSTLString_c_str(ARRAY_OFFSET_LIST_data(aoff_list_i)->variable_name)); //basis_locationの内容も出力する CSTLString_printf(statement,1," basis_location = %%d "); //もし、オフセットの内容が式であれば、式=値という形で出力する if(is_expression_flag == 1){ CSTLString_printf(statement,1,"(%s = %%d)\\n\"", *OFFSET_LIST_data(off_list_i)); //basis_locationの内容を含めた引数の内容を入れる CSTLString_printf(statement,1,", basis_location_%d_%s%s, %s",offset_level_counter, (char*)CSTLString_c_str(ARRAY_OFFSET_LIST_data(aoff_list_i)->variable_name), (char*)CSTLString_c_str(array_string) , *OFFSET_LIST_data(off_list_i)); } //そうでなければ、値という形で出力する else{ CSTLString_printf(statement,1,"(%s)\\n\"", *OFFSET_LIST_data(off_list_i)); //basis_locationの内容の引数の内容を入れる CSTLString_printf(statement,1,", basis_location_%d_%s%s", offset_level_counter, (char*)CSTLString_c_str(ARRAY_OFFSET_LIST_data(aoff_list_i)->variable_name), (char*)CSTLString_c_str(array_string)); } CSTLString_printf(statement, 1, ");\n"); */ //エラーのXMLを出力 CSTLString_printf(statement,1,"printf(\"<error type = #dquot#Lower Unbound#dquot# variable=#dquot#%s#dquot#>\");\n",(char*)CSTLString_c_str(ARRAY_OFFSET_LIST_data(aoff_list_i)->variable_name)); if(is_expression_flag == 1){ CSTLString_printf(statement,1,"printf(\"<expression text=#dquot#%s#dquot# value=#dquot#%%d#dquot#></expression>\",%s);\n", *OFFSET_LIST_data(off_list_i), *OFFSET_LIST_data(off_list_i)); }else{ CSTLString_printf(statement,1,"printf(\"<expression value=#dquot#%%d#dquot#></expression>\",%s);\n",*OFFSET_LIST_data(off_list_i)); } CSTLString_printf(statement,1,"printf(\"<basic_location value=#dquot#%%d#dquot#></basic_location>\", basis_location_%d_%s%s);\n", offset_level_counter, (char*)CSTLString_c_str(ARRAY_OFFSET_LIST_data(aoff_list_i)->variable_name), (char*)CSTLString_c_str(array_string)); CSTLString_printf(statement,1,"printf(\"</error>\");\n"); CSTLString_printf(statement,1,"printf(\"</source>\");\n"); CSTLString_printf(statement, 1, "assert(0);\n"); //リターン命令の返却型に応じる変更(もし、void型であれば、「return;」にする) if(CSTLString_compare_with_char(ARRAY_OFFSET_LIST_data(aoff_list_i)->target_statement->return_type, "void") == 0){ CSTLString_printf(statement, 1, "return;\n"); }else{ CSTLString_printf(statement, 1, "return 1;\n"); } CSTLString_printf(statement, 1, "}\n"); CSTLString_printf(statement, 1, "if(%s + basis_location_%d_%s%s >= *max_size_%d_%s%s){", *OFFSET_LIST_data(off_list_i), offset_level_counter, (char*)CSTLString_c_str(ARRAY_OFFSET_LIST_data(aoff_list_i)->variable_name), (char*)CSTLString_c_str(array_string), offset_level_counter, (char*)CSTLString_c_str(ARRAY_OFFSET_LIST_data(aoff_list_i)->variable_name), (char*)CSTLString_c_str(array_string)); //エラーのXMLを出力 outputErrorXml(statement, aoff_list_i, off_list_i, offset_level_counter, array_string); /* CSTLString_printf(statement,1,"printf(\"<error type = #dquot#Upper Unbound#dquot# variable=#dquot#%s#dquot#>\");\n",(char*)CSTLString_c_str(ARRAY_OFFSET_LIST_data(aoff_list_i)->variable_name)); if(is_expression_flag == 1){ CSTLString_printf(statement,1,"printf(\"<expression text=#dquot#%s#dquot# value=#dquot#%%d#dquot#></expression>\",%s);\n", *OFFSET_LIST_data(off_list_i), *OFFSET_LIST_data(off_list_i)); }else{ CSTLString_printf(statement,1,"printf(\"<expression value=#dquot#%%d#dquot#></expression>\",%s);\n",*OFFSET_LIST_data(off_list_i)); } CSTLString_printf(statement,1,"printf(\"<basic_location value=#dquot#%%d#dquot#></basic_location>\", basis_location_%d_%s%s);\n", offset_level_counter, (char*)CSTLString_c_str(ARRAY_OFFSET_LIST_data(aoff_list_i)->variable_name), (char*)CSTLString_c_str(array_string)); CSTLString_printf(statement,1,"printf(\"</error>\");\n"); CSTLString_printf(statement,1,"printf(\"</source>\");\n");*/ CSTLString_printf(statement, 1, "assert(0);\n"); //リターン命令の返却型に応じる変更(もし、void型であれば、「return;」にする) if(CSTLString_compare_with_char(ARRAY_OFFSET_LIST_data(aoff_list_i)->target_statement->return_type, "void") == 0){ CSTLString_printf(statement, 1, "return;\n"); }else{ CSTLString_printf(statement, 1, "return 1;\n"); } CSTLString_printf(statement, 1, "}\n"); } CSTLString_printf(output, 1, "%s", (char*)CSTLString_c_str(statement)); //次のレベルのための配列を生成する。 CSTLString_printf(basis_location_content, 0, "basis_location_%d_%s%s", offset_level_counter, (char*)CSTLString_c_str(ARRAY_OFFSET_LIST_data(aoff_list_i)->variable_name), (char*)CSTLString_c_str(array_string)); CSTLString_printf(array_string, 1," [ %s + %s ]", *OFFSET_LIST_data(off_list_i), (char*)CSTLString_c_str(basis_location_content)); CSTLString_delete(statement); } CSTLString_delete(array_string); CSTLString_delete(basis_location_content); } }
shared_ptr<Object> Context::getProperty(const string& expression) { assert (isExpression(expression)); return impl->evaluateObject(expression); }
Expression *TraitsExp::semantic(Scope *sc) { #if LOGSEMANTIC printf("TraitsExp::semantic() %s\n", toChars()); #endif if (ident != Id::compiles && ident != Id::isSame) TemplateInstance::semanticTiargs(loc, sc, args, 1); size_t dim = args ? args->dim : 0; Object *o; FuncDeclaration *f; #define ISTYPE(cond) \ for (size_t i = 0; i < dim; i++) \ { Type *t = getType((Object *)args->data[i]); \ if (!t) \ goto Lfalse; \ if (!(cond)) \ goto Lfalse; \ } \ if (!dim) \ goto Lfalse; \ goto Ltrue; #define ISDSYMBOL(cond) \ for (size_t i = 0; i < dim; i++) \ { Dsymbol *s = getDsymbol((Object *)args->data[i]); \ if (!s) \ goto Lfalse; \ if (!(cond)) \ goto Lfalse; \ } \ if (!dim) \ goto Lfalse; \ goto Ltrue; if (ident == Id::isArithmetic) { ISTYPE(t->isintegral() || t->isfloating()) } else if (ident == Id::isFloating) { ISTYPE(t->isfloating()) } else if (ident == Id::isIntegral) { ISTYPE(t->isintegral()) } else if (ident == Id::isScalar) { ISTYPE(t->isscalar()) } else if (ident == Id::isUnsigned) { ISTYPE(t->isunsigned()) } else if (ident == Id::isAssociativeArray) { ISTYPE(t->toBasetype()->ty == Taarray) } else if (ident == Id::isStaticArray) { ISTYPE(t->toBasetype()->ty == Tsarray) } else if (ident == Id::isAbstractClass) { ISTYPE(t->toBasetype()->ty == Tclass && ((TypeClass *)t->toBasetype())->sym->isAbstract()) } else if (ident == Id::isFinalClass) { ISTYPE(t->toBasetype()->ty == Tclass && ((TypeClass *)t->toBasetype())->sym->storage_class & STCfinal) } else if (ident == Id::isAbstractFunction) { ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isAbstract()) } else if (ident == Id::isVirtualFunction) { ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isVirtual()) } else if (ident == Id::isFinalFunction) { ISDSYMBOL((f = s->isFuncDeclaration()) != NULL && f->isFinal()) } else if (ident == Id::hasMember || ident == Id::getMember || ident == Id::getVirtualFunctions) { if (dim != 2) goto Ldimerror; Object *o = (Object *)args->data[0]; Expression *e = isExpression((Object *)args->data[1]); if (!e) { // error("expression expected as second argument of __traits %s", ident->toChars()); goto Lfalse; } e = e->optimize(WANTvalue | WANTinterpret); if (e->op != TOKstring) { // error("string expected as second argument of __traits %s instead of %s", ident->toChars(), e->toChars()); goto Lfalse; } StringExp *se = (StringExp *)e; se = se->toUTF8(sc); if (se->sz != 1) { // error("string must be chars"); goto Lfalse; } Identifier *id = Lexer::idPool((char *)se->string); Type *t = isType(o); e = isExpression(o); Dsymbol *s = isDsymbol(o); if (t) e = new TypeDotIdExp(loc, t, id); else if (e) e = new DotIdExp(loc, e, id); else if (s) { e = new DsymbolExp(loc, s); e = new DotIdExp(loc, e, id); } else { // error("invalid first argument"); goto Lfalse; } if (ident == Id::hasMember) { /* Take any errors as meaning it wasn't found */ unsigned errors = global.errors; global.gag++; e = e->semantic(sc); global.gag--; if (errors != global.errors) { if (global.gag == 0) global.errors = errors; goto Lfalse; } else goto Ltrue; } else if (ident == Id::getMember) { e = e->semantic(sc); return e; } else if (ident == Id::getVirtualFunctions) { unsigned errors = global.errors; Expression *ex = e; e = e->semantic(sc); /* if (errors < global.errors) error("%s cannot be resolved", ex->toChars()); */ /* Create tuple of virtual function overloads of e */ //e->dump(0); Expressions *exps = new Expressions(); FuncDeclaration *f; if (e->op == TOKvar) { VarExp *ve = (VarExp *)e; f = ve->var->isFuncDeclaration(); } else if (e->op == TOKdotvar) { DotVarExp *dve = (DotVarExp *)e; f = dve->var->isFuncDeclaration(); } else f = NULL; Pvirtuals p; p.exps = exps; p.e1 = e; overloadApply(f, fpvirtuals, &p); TupleExp *tup = new TupleExp(loc, exps); return tup->semantic(sc); } else assert(0); } else if (ident == Id::classInstanceSize) { if (dim != 1) goto Ldimerror; Object *o = (Object *)args->data[0]; Dsymbol *s = getDsymbol(o); ClassDeclaration *cd; if (!s || (cd = s->isClassDeclaration()) == NULL) { // error("first argument is not a class"); goto Lfalse; } return new IntegerExp(loc, cd->structsize, Type::tsize_t); } else if (ident == Id::allMembers || ident == Id::derivedMembers) { if (dim != 1) goto Ldimerror; Object *o = (Object *)args->data[0]; Dsymbol *s = getDsymbol(o); ScopeDsymbol *sd; if (!s) { // error("argument has no members"); goto Lfalse; } if ((sd = s->isScopeDsymbol()) == NULL) { // error("%s %s has no members", s->kind(), s->toChars()); goto Lfalse; } Expressions *exps = new Expressions; while (1) { size_t dim = ScopeDsymbol::dim(sd->members); for (size_t i = 0; i < dim; i++) { Dsymbol *sm = ScopeDsymbol::getNth(sd->members, i); //printf("\t[%i] %s %s\n", i, sm->kind(), sm->toChars()); if (sm->ident) { //printf("\t%s\n", sm->ident->toChars()); char *str = sm->ident->toChars(); /* Skip if already present in exps[] */ for (size_t j = 0; j < exps->dim; j++) { StringExp *se2 = (StringExp *)exps->data[j]; if (strcmp(str, (char *)se2->string) == 0) goto Lnext; } StringExp *se = new StringExp(loc, str); exps->push(se); } Lnext: ; } ClassDeclaration *cd = sd->isClassDeclaration(); if (cd && cd->baseClass && ident == Id::allMembers) sd = cd->baseClass; // do again with base class else break; } Expression *e = new ArrayLiteralExp(loc, exps); e = e->semantic(sc); return e; } else if (ident == Id::compiles) { /* Determine if all the objects - types, expressions, or symbols - * compile without error */ if (!dim) goto Lfalse; for (size_t i = 0; i < dim; i++) { Object *o = (Object *)args->data[i]; Type *t; Expression *e; Dsymbol *s; unsigned errors = global.errors; global.gag++; t = isType(o); if (t) { t->resolve(loc, sc, &e, &t, &s); if (t) t->semantic(loc, sc); else if (e) e->semantic(sc); } else { e = isExpression(o); if (e) e->semantic(sc); } global.gag--; if (errors != global.errors) { if (global.gag == 0) global.errors = errors; goto Lfalse; } } goto Ltrue; } else if (ident == Id::isSame) { /* Determine if two symbols are the same */ if (dim != 2) goto Ldimerror; TemplateInstance::semanticTiargs(loc, sc, args, 0); Object *o1 = (Object *)args->data[0]; Object *o2 = (Object *)args->data[1]; Dsymbol *s1 = getDsymbol(o1); Dsymbol *s2 = getDsymbol(o2); #if 0 printf("o1: %p\n", o1); printf("o2: %p\n", o2); if (!s1) { Expression *ea = isExpression(o1); if (ea) printf("%s\n", ea->toChars()); Type *ta = isType(o1); if (ta) printf("%s\n", ta->toChars()); goto Lfalse; } else printf("%s %s\n", s1->kind(), s1->toChars()); #endif if (!s1 && !s2) { Expression *ea1 = isExpression(o1); Expression *ea2 = isExpression(o2); if (ea1 && ea2 && ea1->equals(ea2)) goto Ltrue; } if (!s1 || !s2) goto Lfalse; s1 = s1->toAlias(); s2 = s2->toAlias(); if (s1 == s2) goto Ltrue; else goto Lfalse; } else { // error("unrecognized trait %s", ident->toChars()); goto Lfalse; } return NULL; Lnottype: // error("%s is not a type", o->toChars()); goto Lfalse; Ldimerror: // error("wrong number of arguments %d", dim); goto Lfalse; Lfalse: return new IntegerExp(loc, 0, Type::tbool); Ltrue: return new IntegerExp(loc, 1, Type::tbool); }
void source_name(Dsymbol *s) { char *name = s->ident->toChars(); TemplateInstance *ti = s->isTemplateInstance(); if (ti) { if (!substitute(ti->tempdecl)) { store(ti->tempdecl); name = ti->name->toChars(); buf.printf("%d%s", strlen(name), name); } buf.writeByte('I'); bool is_var_arg = false; for (size_t i = 0; i < ti->tiargs->dim; i++) { RootObject *o = (RootObject *)(*ti->tiargs)[i]; TemplateParameter *tp = NULL; TemplateValueParameter *tv = NULL; TemplateTupleParameter *tt = NULL; if (!is_var_arg) { TemplateDeclaration *td = ti->tempdecl->isTemplateDeclaration(); tp = (*td->parameters)[i]; tv = tp->isTemplateValueParameter(); tt = tp->isTemplateTupleParameter(); } /* * <template-arg> ::= <type> # type or template * ::= <expr-primary> # simple expressions */ if (tt) { buf.writeByte('I'); is_var_arg = true; tp = NULL; } if (tv) { // <expr-primary> ::= L <type> <value number> E # integer literal if (tv->valType->isintegral()) { Expression* e = isExpression(o); assert(e); buf.writeByte('L'); tv->valType->accept(this); if (tv->valType->isunsigned()) { buf.printf("%llu", e->toUInteger()); } else { dinteger_t val = e->toInteger(); if (val < 0) { val = -val; buf.writeByte('n'); } buf.printf("%lld", val); } buf.writeByte('E'); } else { s->error("ICE: C++ %s template value parameter is not supported", tv->valType->toChars()); assert(0); } } else if (!tp || tp->isTemplateTypeParameter()) { Type *t = isType(o); assert(t); t->accept(this); } else if (tp->isTemplateAliasParameter()) { Dsymbol* d = isDsymbol(o); Expression* e = isExpression(o); if (!d && !e) { s->error("ICE: %s is unsupported parameter for C++ template: (%s)", o->toChars()); assert(0); } if (d && d->isFuncDeclaration()) { bool is_nested = d->toParent() && !d->toParent()->isModule() && ((TypeFunction *)d->isFuncDeclaration()->type)->linkage == LINKcpp; if (is_nested) buf.writeByte('X'); buf.writeByte('L'); mangle_function(d->isFuncDeclaration()); buf.writeByte('E'); if (is_nested) buf.writeByte('E'); } else if (e && e->op == TOKvar && ((VarExp*)e)->var->isVarDeclaration()) { VarDeclaration *vd = ((VarExp*)e)->var->isVarDeclaration(); buf.writeByte('L'); mangle_variable(vd, true); buf.writeByte('E'); } else if (d && d->isTemplateDeclaration() && d->isTemplateDeclaration()->onemember) { if (!substitute(d)) { cpp_mangle_name(d); store(d); } } else { s->error("ICE: %s is unsupported parameter for C++ template", o->toChars()); assert(0); } } else { s->error("ICE: C++ templates support only integral value , type parameters, alias templates and alias function parameters"); assert(0); } } if (is_var_arg) { buf.writeByte('E'); } buf.writeByte('E'); return; } else { buf.printf("%d%s", strlen(name), name); } }
LLFunction* DtoInlineIRFunction(FuncDeclaration* fdecl) { const char* mangled_name = mangleExact(fdecl); TemplateInstance* tinst = fdecl->parent->isTemplateInstance(); assert(tinst); Objects& objs = tinst->tdtypes; assert(objs.dim == 3); Expression* a0 = isExpression(objs[0]); assert(a0); StringExp* strexp = a0->toStringExp(); assert(strexp); assert(strexp->sz == 1); std::string code(static_cast<char*>(strexp->string), strexp->len); Type* ret = isType(objs[1]); assert(ret); Tuple* a2 = isTuple(objs[2]); assert(a2); Objects& arg_types = a2->objects; std::string str; llvm::raw_string_ostream stream(str); stream << "define " << *DtoType(ret) << " @" << mangled_name << "("; for(size_t i = 0; ;) { Type* ty = isType(arg_types[i]); //assert(ty); if(!ty) { error(tinst->loc, "All parameters of a template defined with pragma llvm_inline_ir, except for the first one, should be types"); fatal(); } stream << *DtoType(ty); i++; if(i >= arg_types.dim) break; stream << ", "; } if(ret->ty == Tvoid) code.append("\nret void"); stream << ")\n{\n" << code << "\n}"; llvm::SMDiagnostic err; #if LDC_LLVM_VER >= 306 std::unique_ptr<llvm::Module> m = llvm::parseAssemblyString( stream.str().c_str(), err, gIR->context()); #elif LDC_LLVM_VER >= 303 llvm::Module* m = llvm::ParseAssemblyString( stream.str().c_str(), NULL, err, gIR->context()); #else llvm::ParseAssemblyString( stream.str().c_str(), gIR->module, err, gIR->context()); #endif std::string errstr = err.getMessage(); if(errstr != "") error(tinst->loc, "can't parse inline LLVM IR:\n%s\n%s\n%s\nThe input string was: \n%s", #if LDC_LLVM_VER >= 303 err.getLineContents().str().c_str(), #else err.getLineContents().c_str(), #endif (std::string(err.getColumnNo(), ' ') + '^').c_str(), errstr.c_str(), stream.str().c_str()); #if LDC_LLVM_VER >= 306 llvm::Linker(gIR->module).linkInModule(m.get()); #else #if LDC_LLVM_VER >= 303 std::string errstr2 = ""; #if LDC_LLVM_VER >= 306 llvm::Linker(gIR->module).linkInModule(m.get(), &errstr2); #else llvm::Linker(gIR->module).linkInModule(m, &errstr2); #endif if(errstr2 != "") error(tinst->loc, "Error when linking in llvm inline ir: %s", errstr2.c_str()); #endif #endif LLFunction* fun = gIR->module->getFunction(mangled_name); fun->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage); fun->addFnAttr(LDC_ATTRIBUTE(AlwaysInline)); return fun; }