int FollowLocationJob::execute() { const Symbol symbol = project()->findSymbol(location); if (symbol.isNull()) return 1; if (queryFlags() & QueryMessage::AllTargets) { const Set<String> usrs = project()->findTargetUsrs(location); for (const String &usr : usrs) { for (const Symbol &s : project()->findByUsr(usr, location.fileId(), Project::ArgDependsOn, location)) { write(s.toString()); } } } const auto target = project()->findTarget(symbol); if (target.isNull()) return 1; if (symbol.usr == target.usr) { write(target.location); return 0; } if (queryFlags() & QueryMessage::DeclarationOnly ? target.isDefinition() : !target.isDefinition()) { const auto other = project()->findTarget(target); if (!other.isNull() && other.usr == target.usr) { write(other.location); return 0; } } write(target.location); return 0; }
void DefinitionsInHeadersCheck::registerMatchers(MatchFinder *Finder) { if (UseHeaderFileExtension) { Finder->addMatcher( namedDecl(anyOf(functionDecl(isDefinition()), varDecl(isDefinition())), isHeaderFileExtension()).bind("name-decl"), this); } else { Finder->addMatcher( namedDecl(anyOf(functionDecl(isDefinition()), varDecl(isDefinition())), anyOf(isHeaderFileExtension(), unless(isExpansionInMainFile()))).bind("name-decl"), this); } }
String CursorInfo::toString(unsigned cursorInfoFlags, unsigned keyFlags) const { String ret = String::format<1024>("SymbolName: %s\n" "Kind: %s\n" "Type: %s\n" "SymbolLength: %u\n" "%s" // range "%s" // enumValue "%s", // definition symbolName.constData(), RTags::eatString(clang_getCursorKindSpelling(kind)).constData(), RTags::eatString(clang_getTypeKindSpelling(type)).constData(), symbolLength, start != -1 && end != -1 ? String::format<32>("Range: %d-%d\n", start, end).constData() : "", kind == CXCursor_EnumConstantDecl ? String::format<32>("Enum Value: %lld\n", enumValue).constData() : "", isDefinition() ? "Definition\n" : ""); if (!targets.isEmpty() && !(cursorInfoFlags & IgnoreTargets)) { ret.append("Targets:\n"); for (Set<Location>::const_iterator tit = targets.begin(); tit != targets.end(); ++tit) { const Location &l = *tit; ret.append(String::format<128>(" %s\n", l.key(keyFlags).constData())); } } if (!references.isEmpty() && !(cursorInfoFlags & IgnoreReferences)) { ret.append("References:\n"); for (Set<Location>::const_iterator rit = references.begin(); rit != references.end(); ++rit) { const Location &l = *rit; ret.append(String::format<128>(" %s\n", l.key(keyFlags).constData())); } } return ret; }
void ConstReturnTypeCheck::registerMatchers(MatchFinder *Finder) { // Find all function definitions for which the return types are `const` // qualified. Finder->addMatcher( functionDecl(returns(isConstQualified()), isDefinition()).bind("func"), this); }
void InterfacesGlobalInitCheck::registerMatchers(MatchFinder *Finder) { const auto IsGlobal = allOf(hasGlobalStorage(), hasDeclContext(anyOf(translationUnitDecl(), // Global scope. namespaceDecl(), // Namespace scope. recordDecl())), // Class scope. unless(isConstexpr())); const auto ReferencesUndefinedGlobalVar = declRefExpr(hasDeclaration( varDecl(IsGlobal, unless(isDefinition())).bind("referencee"))); Finder->addMatcher( varDecl(IsGlobal, isDefinition(), hasInitializer(expr(hasDescendant(ReferencesUndefinedGlobalVar)))) .bind("var"), this); }
TEST_F(StructuralEquivalenceCXXMethodTest, OutOfClass2) { auto t = makeDecls<FunctionDecl>( "struct X { virtual void f(); }; void X::f() { }", "struct X { void f(); }; void X::f() { }", Lang_CXX, functionDecl(allOf(hasName("f"), isDefinition()))); EXPECT_FALSE(testStructuralMatch(t)); }
void DefinitionsInHeadersCheck::registerMatchers(MatchFinder *Finder) { if (!getLangOpts().CPlusPlus) return; auto DefinitionMatcher = anyOf(functionDecl(isDefinition(), unless(isDeleted())), varDecl(isDefinition())); if (UseHeaderFileExtension) { Finder->addMatcher(namedDecl(DefinitionMatcher, usesHeaderFileExtension(HeaderFileExtensions)) .bind("name-decl"), this); } else { Finder->addMatcher( namedDecl(DefinitionMatcher, anyOf(usesHeaderFileExtension(HeaderFileExtensions), unless(isExpansionInMainFile()))) .bind("name-decl"), this); } }
void UnnecessaryValueParamCheck::registerMatchers(MatchFinder *Finder) { const auto ExpensiveValueParamDecl = parmVarDecl(hasType(hasCanonicalType(allOf(matchers::isExpensiveToCopy(), unless(referenceType())))), decl().bind("param")); Finder->addMatcher( functionDecl(isDefinition(), unless(cxxMethodDecl(isOverride())), unless(isInstantiated()), has(typeLoc(forEach(ExpensiveValueParamDecl))), decl().bind("functionDecl")), this); }
void AvoidConstParamsInDecls::registerMatchers(MatchFinder *Finder) { const auto ConstParamDecl = parmVarDecl(hasType(qualType(isConstQualified()))).bind("param"); Finder->addMatcher( functionDecl(unless(isDefinition()), // Lambdas are always their own definition, but they // generate a non-definition FunctionDecl too. Ignore those. // Class template instantiations have a non-definition // CXXMethodDecl for methods that aren't used in this // translation unit. Ignore those, as the template will have // already been checked. unless(cxxMethodDecl(ofClass(cxxRecordDecl(anyOf( isLambda(), ast_matchers::isTemplateInstantiation()))))), has(typeLoc(forEach(ConstParamDecl)))) .bind("func"), this); }
String CursorInfo::toString(unsigned cursorInfoFlags, unsigned keyFlags) const { String ret = String::format<1024>("SymbolName: %s\n" "Kind: %s\n" "Type: %s\n" // type "SymbolLength: %u\n" "%s" // range "%s" // enumValue "%s", // definition symbolName.constData(), kindSpelling().constData(), RTags::eatString(clang_getTypeKindSpelling(type)).constData(), symbolLength, startLine != -1 ? String::format<32>("Range: %d:%d-%d:%d\n", startLine, startColumn, endLine, endColumn).constData() : "", #if CINDEX_VERSION_MINOR > 1 kind == CXCursor_EnumConstantDecl ? String::format<32>("Enum Value: %lld\n", enumValue).constData() : #endif "", isDefinition() ? "Definition\n" : ""); if (!targets.isEmpty() && !(cursorInfoFlags & IgnoreTargets)) { ret.append("Targets:\n"); for (auto tit = targets.begin(); tit != targets.end(); ++tit) { const Location &l = *tit; ret.append(String::format<128>(" %s\n", l.key(keyFlags).constData())); } } if (!references.isEmpty() && !(cursorInfoFlags & IgnoreReferences)) { ret.append("References:\n"); for (auto rit = references.begin(); rit != references.end(); ++rit) { const Location &l = *rit; ret.append(String::format<128>(" %s\n", l.key(keyFlags).constData())); } } return ret; }
void ReturnBracedInitListCheck::registerMatchers(MatchFinder *Finder) { // Only register the matchers for C++. if (!getLangOpts().CPlusPlus11) return; // Skip list initialization and constructors with an initializer list. auto ConstructExpr = cxxConstructExpr( unless(anyOf(hasDeclaration(cxxConstructorDecl(isExplicit())), isListInitialization(), hasDescendant(initListExpr()), isInTemplateInstantiation()))) .bind("ctor"); auto CtorAsArgument = materializeTemporaryExpr(anyOf( has(ConstructExpr), has(cxxFunctionalCastExpr(has(ConstructExpr))))); Finder->addMatcher( functionDecl(isDefinition(), // Declarations don't have return statements. returns(unless(anyOf(builtinType(), autoType()))), hasDescendant(returnStmt(hasReturnValue( has(cxxConstructExpr(has(CtorAsArgument))))))) .bind("fn"), this); }
String Symbol::toString(const std::shared_ptr<Project> &project, const Flags<ToStringFlag> cursorInfoFlags, Flags<Location::ToStringFlag> locationToStringFlags, const Set<String> &pieceFilters) const { auto filterPiece = [&pieceFilters](const char *name) { return pieceFilters.isEmpty() || pieceFilters.contains(name); }; auto properties = [this, &filterPiece]() -> String { List<String> ret; if (isDefinition() && filterPiece("definition")) ret << "Definition"; if (isContainer() && filterPiece("container")) ret << "Container"; if ((flags & PureVirtualMethod) == PureVirtualMethod && filterPiece("purevirtual")) ret << "Pure Virtual"; if (flags & VirtualMethod && filterPiece("virtual")) ret << "Virtual"; if (flags & ConstMethod) { if (filterPiece("constmethod")) ret << "ConstMethod"; } else if (flags & StaticMethod && filterPiece("static")) { ret << "Static"; } if (flags & Variadic && filterPiece("variadic")) ret << "Variadic"; if (flags & Auto && filterPiece("auto")) ret << "Auto"; if (flags & MacroExpansion && filterPiece("macroexpansion")) ret << "MacroExpansion"; if (flags & TemplateSpecialization && filterPiece("templatespecialization")) ret << "TemplateSpecialization"; if (flags & TemplateReference && filterPiece("templatereference")) ret << "TemplateReference"; if (ret.isEmpty()) return String(); return String::join(ret, ' ') + '\n'; }; List<String> bases; List<String> args; if (project) { if (filterPiece("baseclasses")) { for (const auto &base : baseClasses) { bool found = false; for (const auto &sym : project->findByUsr(base, location.fileId(), Project::ArgDependsOn)) { bases << sym.symbolName; found = true; break; } if (!found) { bases << base; } } } if (filterPiece("arguments")) { for (const auto &arg : arguments) { const String symName = project->findSymbol(arg.cursor).symbolName; if (!symName.isEmpty()) { args << symName; } else { args << arg.cursor.toString(locationToStringFlags & ~Location::ShowContext); } } } } else if (filterPiece("baseClasses")) { bases = baseClasses; } String ret; auto writePiece = [&ret, &filterPiece](const char *key, const char *filter, const String &piece) { if (piece.isEmpty()) return; if (!filterPiece(filter)) return; if (key && strlen(key)) ret << key << ": "; ret << piece << "\n"; }; writePiece(0, "location", location.toString(locationToStringFlags)); writePiece("SymbolName", "symbolname", symbolName); writePiece("Kind", "kind", kindSpelling()); if (filterPiece("type")) { if (!typeName.isEmpty()) { ret += "Type: " + typeName + "\n"; } else if (type != CXType_Invalid) { ret += "Type: " + RTags::eatString(clang_getTypeKindSpelling(type)) + "\n"; } } writePiece("SymbolLength", "symbollength", std::to_string(symbolLength)); if (startLine != -1) writePiece("Range", "range", String::format<32>("%d:%d-%d:%d", startLine, startColumn, endLine, endColumn)); #if CINDEX_VERSION_MINOR > 1 if (kind == CXCursor_EnumConstantDecl) writePiece("Enum Value", "enumvalue", String::format<32>("%lld/0x%0llx", static_cast<long long>(enumValue), static_cast<long long>(enumValue))); if (isDefinition() && RTags::isFunction(kind)) writePiece("Stack cost", "stackcost", std::to_string(stackCost)); #endif writePiece(0, "linkage", linkageSpelling(linkage)); ret += properties(); writePiece("Usr", "usr", usr); if (size) writePiece("sizeof", "sizeof", std::to_string(size)); if (fieldOffset >= 0) writePiece("Field offset (bits/bytes)", "fieldoffset", String::format<32>("%d/%d", fieldOffset, fieldOffset / 8)); if (alignment >= 0) writePiece("Alignment", "alignment", std::to_string(alignment)); if (!args.isEmpty()) writePiece("Arguments", "arguments", String::join(args, ", ")); if (!bases.isEmpty()) writePiece("Base classes", "baseclasses", String::join(bases, ", ")); writePiece("Brief comment", "briefcomment", briefComment); writePiece("XML comment", "xmlcomment", xmlComment); if ((cursorInfoFlags & IncludeParents && filterPiece("parent")) || (cursorInfoFlags & (IncludeContainingFunction) && filterPiece("cf")) || (cursorInfoFlags & (IncludeContainingFunctionLocation) && filterPiece("cfl"))) { auto syms = project->openSymbols(location.fileId()); uint32_t idx = -1; if (syms) { idx = syms->lowerBound(location); if (idx == std::numeric_limits<uint32_t>::max()) { idx = syms->count() - 1; } } const unsigned int line = location.line(); const unsigned int column = location.column(); while (idx-- > 0) { const Symbol s = syms->valueAt(idx); if (s.isDefinition() && s.isContainer() && comparePosition(line, column, s.startLine, s.startColumn) >= 0 && comparePosition(line, column, s.endLine, s.endColumn) <= 0) { if (cursorInfoFlags & IncludeContainingFunctionLocation) writePiece("Containing function location", "cfl", s.location.toString(locationToStringFlags)); if (cursorInfoFlags & IncludeContainingFunction) writePiece("Containing function", "cf", s.symbolName); if (cursorInfoFlags & IncludeParents) writePiece("Parent", "parent", s.location.toString(locationToStringFlags)); // redundant, this is a mess break; } } } if (cursorInfoFlags & IncludeTargets && project && filterPiece("targets")) { const auto targets = project->findTargets(*this); if (targets.size()) { ret.append("Targets:\n"); auto best = RTags::bestTarget(targets); ret.append(String::format<128>(" %s\n", best.location.toString(locationToStringFlags).constData())); for (const auto &tit : targets) { if (tit.location != best.location) ret.append(String::format<128>(" %s\n", tit.location.toString(locationToStringFlags).constData())); } } } if (cursorInfoFlags & IncludeReferences && project && !isReference() && filterPiece("references")) { const auto references = project->findCallers(*this); if (references.size()) { ret.append("References:\n"); for (const auto &r : references) { ret.append(String::format<128>(" %s\n", r.location.toString(locationToStringFlags).constData())); } } } return ret; }
bool Symbol::isReference() const { return RTags::isReference(kind) || (linkage == CXLinkage_External && !isDefinition() && !RTags::isFunction(kind)); }
uint16_t Symbol::targetsValue() const { return RTags::createTargetsValue(kind, isDefinition()); }
void InheritanceBuilder::tackOnto(MatchFinder &MF) { MF.addMatcher(cxxRecordDecl(isDefinition(), unless(hasAncestor(namespaceDecl(isAnonymous())))) .bind("class"), this); }
String Symbol::toString(Flags<ToStringFlag> cursorInfoFlags, Flags<Location::ToStringFlag> locationToStringFlags, const std::shared_ptr<Project> &project) const { auto properties = [this]() { List<String> ret; if (isDefinition()) ret << "Definition"; if (isContainer()) ret << "Container"; if ((flags & PureVirtualMethod) == PureVirtualMethod) { ret << "Pure Virtual"; } else if (flags & VirtualMethod) { ret << "Virtual"; } if (flags & ConstMethod) { ret << "Const"; } else if (flags & StaticMethod) { ret << "Static"; } if (flags & Variadic) ret << "Variadic"; if (flags & Auto) ret << "Auto"; if (flags & AutoRef) ret << "AutoRef"; if (flags & MacroExpansion) ret << "MacroExpansion"; if (flags & TemplateSpecialization) ret << "TemplateSpecialization"; if (ret.isEmpty()) return String(); String joined = String::join(ret, ' '); joined += '\n'; return joined; }; List<String> bases; if (project) { extern String findSymbolNameByUsr(const std::shared_ptr<Project> &, const String &, const Location &location); for (const auto &base : baseClasses) { const String symbolName = findSymbolNameByUsr(project, base, location); if (!symbolName.isEmpty()) { bases << symbolName; } } } else { bases = baseClasses; } auto printTypeName = [this]() { String str; if (!typeName.isEmpty()) { str = typeName; } else if (type != CXType_Invalid) { str = RTags::eatString(clang_getTypeKindSpelling(type)); } else { return String(); } return String::format<128>("Type: %s\n", str.constData()); }; String ret = String::format<1024>("SymbolName: %s\n" "Kind: %s\n" "%s" // type "SymbolLength: %u\n" "%s" // range "%s" // enumValue "%s" // linkage "%s" // properties "%s" // usr "%s" // sizeof "%s" // fieldoffset "%s" // baseclasses "%s" // briefComment "%s", // xmlComment symbolName.constData(), kindSpelling().constData(), printTypeName().constData(), symbolLength, startLine != -1 ? String::format<32>("Range: %d:%d-%d:%d\n", startLine, startColumn, endLine, endColumn).constData() : "", #if CINDEX_VERSION_MINOR > 1 kind == CXCursor_EnumConstantDecl ? String::format<32>("Enum Value: %lld\n", enumValue).constData() : #endif "", linkageSpelling(linkage), properties().constData(), usr.isEmpty() ? "" : String::format<64>("Usr: %s\n", usr.constData()).constData(), size > 0 ? String::format<16>("sizeof: %d\n", size).constData() : "", fieldOffset >= 0 ? String::format<32>("field offset (bits/bytes): %d/%d\n", fieldOffset, fieldOffset / 8).constData() : "", alignment >= 0 ? String::format<32>("alignment (bytes): %d\n", alignment).constData() : "", bases.isEmpty() ? "" : String::format<64>("BaseClasses: %s\n", String::join(bases, ", ").constData()).constData(), briefComment.isEmpty() ? "" : String::format<1024>("Brief comment: %s\n", briefComment.constData()).constData(), xmlComment.isEmpty() ? "" : String::format<16384>("Xml comment: %s\n", xmlComment.constData()).constData()); if (!(cursorInfoFlags & IgnoreTargets) && project) { extern Set<Symbol> findTargets(const std::shared_ptr<Project> &, const Symbol &); auto targets = findTargets(project, *this); if (targets.size()) { ret.append("Targets:\n"); auto best = RTags::bestTarget(targets); ret.append(String::format<128>(" %s\n", best.location.toString(locationToStringFlags).constData())); for (const auto &tit : targets) { if (tit.location != best.location) ret.append(String::format<128>(" %s\n", tit.location.toString(locationToStringFlags).constData())); } } } if (!(cursorInfoFlags & IgnoreReferences) && project && !isReference()) { extern Set<Symbol> findCallers(const std::shared_ptr<Project> &, const Symbol &); auto references = findCallers(project, *this); if (references.size()) { ret.append("References:\n"); for (const auto &r : references) { ret.append(String::format<128>(" %s\n", r.location.toString(locationToStringFlags).constData())); } } } return ret; }
String Symbol::toString(Flags<ToStringFlag> cursorInfoFlags, Flags<Location::ToStringFlag> locationToStringFlags, const std::shared_ptr<Project> &project) const { auto properties = [this]() { List<String> ret; if (isDefinition()) ret << "Definition"; if (isContainer()) ret << "Container"; if ((flags & PureVirtualMethod) == PureVirtualMethod) { ret << "Pure Virtual"; } else if (flags & VirtualMethod) { ret << "Virtual"; } if (flags & ConstMethod) { ret << "Const"; } else if (flags & StaticMethod) { ret << "Static"; } if (flags & Variadic) ret << "Variadic"; if (flags & Auto) ret << "Auto"; if (flags & AutoRef) ret << "AutoRef"; if (flags & MacroExpansion) ret << "MacroExpansion"; if (flags & TemplateSpecialization) ret << "TemplateSpecialization"; if (ret.isEmpty()) return String(); String joined = String::join(ret, ' '); joined += '\n'; return joined; }; List<String> bases; List<String> args; if (project) { for (const auto &base : baseClasses) { bool found = false; for (const auto &sym : project->findByUsr(base, location.fileId(), Project::ArgDependsOn, location)) { bases << sym.symbolName; found = true; break; } if (!found) { bases << base; } } for (const auto &arg : arguments) { const String symName = project->findSymbol(arg.cursor).symbolName; if (!symName.isEmpty()) { args << symName; } else { args << arg.cursor.toString(locationToStringFlags & ~Location::ShowContext); } } } else { bases = baseClasses; } auto printTypeName = [this]() { String str; if (!typeName.isEmpty()) { str = typeName; } else if (type != CXType_Invalid) { str = RTags::eatString(clang_getTypeKindSpelling(type)); } else { return String(); } return String::format<128>("Type: %s\n", str.constData()); }; String ret = String::format<1024>("%s\n" "SymbolName: %s\n" "Kind: %s\n" "%s" // type "SymbolLength: %u\n" "%s" // range "%s" // enumValue/stackCost "%s" // linkage "%s" // properties "%s" // usr "%s" // sizeof "%s" // fieldoffset "%s" // alignment "%s" // arguments "%s" // baseclasses "%s" // briefComment "%s", // xmlComment location.toString(locationToStringFlags).constData(), symbolName.constData(), kindSpelling().constData(), printTypeName().constData(), symbolLength, startLine != -1 ? String::format<32>("Range: %d:%d-%d:%d\n", startLine, startColumn, endLine, endColumn).constData() : "", #if CINDEX_VERSION_MINOR > 1 (kind == CXCursor_EnumConstantDecl ? String::format<32>("Enum Value: %lld/0x%0llx\n", static_cast<long long>(enumValue), static_cast<long long>(enumValue)).constData() : (isDefinition() && RTags::isFunction(kind) ? String::format<32>("Stack cost: %d\n", stackCost).constData() : "")), #else "", #endif linkageSpelling(linkage), properties().constData(), usr.isEmpty() ? "" : String::format<64>("Usr: %s\n", usr.constData()).constData(), size > 0 ? String::format<16>("sizeof: %d\n", size).constData() : "", fieldOffset >= 0 ? String::format<32>("field offset (bits/bytes): %d/%d\n", fieldOffset, fieldOffset / 8).constData() : "", alignment >= 0 ? String::format<32>("alignment (bytes): %d\n", alignment).constData() : "", args.isEmpty() ? "" : String::format<1024>("Arguments: %s\n", String::join(args, ", ").constData()).constData(), bases.isEmpty() ? "" : String::format<64>("BaseClasses: %s\n", String::join(bases, ", ").constData()).constData(), briefComment.isEmpty() ? "" : String::format<1024>("Brief comment: %s\n", briefComment.constData()).constData(), xmlComment.isEmpty() ? "" : String::format<16384>("XML comment: %s\n", xmlComment.constData()).constData()); if (cursorInfoFlags & IncludeTargets && project) { const auto targets = project->findTargets(*this); if (targets.size()) { ret.append("Targets:\n"); auto best = RTags::bestTarget(targets); ret.append(String::format<128>(" %s\n", best.location.toString(locationToStringFlags).constData())); for (const auto &tit : targets) { if (tit.location != best.location) ret.append(String::format<128>(" %s\n", tit.location.toString(locationToStringFlags).constData())); } } } if (cursorInfoFlags & IncludeReferences && project && !isReference()) { const auto references = project->findCallers(*this); if (references.size()) { ret.append("References:\n"); for (const auto &r : references) { ret.append(String::format<128>(" %s\n", r.location.toString(locationToStringFlags).constData())); } } } return ret; }
void MustOverrideChecker::registerMatchers(MatchFinder *AstMatcher) { AstMatcher->addMatcher(cxxRecordDecl(isDefinition()).bind("class"), this); }
sExpression *eval(sExpression *exp, sEnvironment *env){ /* ------------------atom-----------------------*/ /* 1, 10, false, null, "abc" */ if(isSelfEval(exp)) { return exp; } /* a symbol */ else if(isVariable(exp, env)) { return lookupVariable(toSymb(exp), env); } /* ------------------list-----------------------*/ /* (quote blur blur) */ else if(isQuoted(exp)) { return textOfQuoted(exp); } /* (set! name value) */ else if(isAssignment(exp)) { return evalAssignment(exp, env); } /* (define name value) */ else if(isDefinition(exp)) { return evalDefine(exp, env); } /* (define-syntax name ...) */ else if(isDefinitionSyntax(exp)) { return evalDefineSyntax(exp, env); } /* (if blur blur blur) */ else if(isIf(exp)) { return evalIf(toList(exp), env); } /* (lambda (args) (body)) */ else if(isLambdaConst(exp)) { sList *body; sList *param = toList( cadr(toList(exp))); sExpression *temp = cdr(toList( cdr(toList(exp)))); if(isList(temp)){ body = toList(temp); }else{ body = toList(cons(temp, &sNull)); } return newLambda(param, body, env); } /* (syntax blur blur) syntax rule */ else if(isSymbol(car(toList(exp))) && isSyntaxRule(eval(car(toList(exp)), env))) { sExpression *exp2 = evalSyntaxRule(toSyntax(eval(car(toList(exp)), env)), exp); return eval(exp2, env); } /* the other list (x . y) */ else if(isApplication(exp)) { if(LAZY_EVAL){ sExpression *proexp = actualValue(operator(toList(exp)), env); if(isLambdaType(proexp) || isPrimitiveProc(proexp)){ sExpression *operand = operands(toList(exp)); return applyLazly(proexp, operand, env); } }else{ sExpression *proexp = eval(operator(toList(exp)), env); if(isLambdaType(proexp) || isPrimitiveProc(proexp)){ sExpression *operand = operands(toList(exp)); sExpression *arguments = listOfValues(operand, env); return apply(proexp, arguments, env); } } } return &sError; }
const Node<Scope>& Function::scope() const { assert(isDefinition() && !isDefaultDefinition()); return scope_; }
bool Function::isDefaultDefinition() const { return isDefinition() && isDefaultDefinition_; }