Return action result and Value from all interfaces. Force callers to rpovide them, to make them handle errors etc.
This commit is contained in:
parent
e2c1067a82
commit
0c1c22f002
@ -68,8 +68,8 @@ namespace cling {
|
||||
/// have in case of multi input mode.
|
||||
///\returns -1 if quit was requiested.
|
||||
///
|
||||
int process(const char* input_line, cling::StoredValueRef* result = 0,
|
||||
Interpreter::CompilationResult* compRes = 0);
|
||||
int process(const char* input_line, cling::StoredValueRef& result,
|
||||
Interpreter::CompilationResult& compRes);
|
||||
|
||||
///\brief When continuation is requested, this cancels and ignores previous
|
||||
/// input, resetting the continuation to a new line.
|
||||
@ -91,8 +91,8 @@ namespace cling {
|
||||
///\returns true on success
|
||||
///
|
||||
bool executeFile(llvm::StringRef file, llvm::StringRef args,
|
||||
cling::StoredValueRef* result = 0,
|
||||
Interpreter::CompilationResult* compRes = 0);
|
||||
cling::StoredValueRef& result,
|
||||
Interpreter::CompilationResult& compRes);
|
||||
|
||||
///\brief Get the file name that is currently executing as passed to
|
||||
/// the currently active executeFile(). The returned StringRef::data() is
|
||||
@ -121,7 +121,7 @@ namespace cling {
|
||||
///
|
||||
Interpreter::CompilationResult
|
||||
readInputFromFile(llvm::StringRef filename,
|
||||
StoredValueRef* result /* = 0 */,
|
||||
StoredValueRef& result,
|
||||
bool ignoreOutmostBlock = false);
|
||||
|
||||
};
|
||||
|
@ -81,18 +81,15 @@ namespace cling {
|
||||
consumeToken();
|
||||
}
|
||||
|
||||
bool MetaParser::isMetaCommand() {
|
||||
return isCommandSymbol() && isCommand();
|
||||
bool MetaParser::isMetaCommand(StoredValueRef& resultValue,
|
||||
MetaSema::ActionResult& actionResult) {
|
||||
return isCommandSymbol() && isCommand(resultValue, actionResult);
|
||||
}
|
||||
|
||||
bool MetaParser::isQuitRequested() const {
|
||||
return m_Actions->isQuitRequested();
|
||||
}
|
||||
|
||||
StoredValueRef MetaParser::getLastResultedValue() const {
|
||||
return m_Actions->getLastResultedValue();
|
||||
}
|
||||
|
||||
bool MetaParser::isCommandSymbol() {
|
||||
for (size_t i = 0; i < m_MetaSymbolCache.size(); ++i) {
|
||||
if (getCurTok().getKind() != m_MetaSymbolCache[i].getKind())
|
||||
@ -102,18 +99,23 @@ namespace cling {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MetaParser::isCommand() {
|
||||
return isLCommand() || isXCommand() || isqCommand()
|
||||
|| isUCommand() || isICommand() || israwInputCommand()
|
||||
bool MetaParser::isCommand(StoredValueRef& resultValue,
|
||||
MetaSema::ActionResult& actionResult) {
|
||||
resultValue = StoredValueRef();
|
||||
return isLCommand(actionResult)
|
||||
|| isXCommand(resultValue, actionResult)
|
||||
|| isqCommand()
|
||||
|| isUCommand(actionResult) || isICommand() || israwInputCommand()
|
||||
|| isprintASTCommand() || isdynamicExtensionsCommand() || ishelpCommand()
|
||||
|| isfileExCommand() || isfilesCommand() || isClassCommand()
|
||||
|| isgCommand() || isTypedefCommand() || isShellCommand();
|
||||
|| isgCommand() || isTypedefCommand()
|
||||
|| isShellCommand(resultValue, actionResult);
|
||||
}
|
||||
|
||||
// L := 'L' FilePath
|
||||
// FilePath := AnyString
|
||||
// AnyString := .*^(' ' | '\t')
|
||||
bool MetaParser::isLCommand() {
|
||||
bool MetaParser::isLCommand(MetaSema::ActionResult& actionResult) {
|
||||
bool result = false;
|
||||
if (getCurTok().is(tok::ident) && getCurTok().getIdent().equals("L")) {
|
||||
consumeAnyStringToken();
|
||||
@ -135,7 +137,9 @@ namespace cling {
|
||||
// FilePath := AnyString
|
||||
// ArgList := (ExtraArgList) ' ' [ArgList]
|
||||
// ExtraArgList := AnyString [, ExtraArgList]
|
||||
bool MetaParser::isXCommand() {
|
||||
bool MetaParser::isXCommand(StoredValueRef& resultValue,
|
||||
MetaSema::ActionResult& actionResult) {
|
||||
resultValue = StoredValueRef();
|
||||
bool result = false;
|
||||
const Token& Tok = getCurTok();
|
||||
if (Tok.is(tok::ident) && (Tok.getIdent().equals("x")
|
||||
@ -144,20 +148,20 @@ namespace cling {
|
||||
consumeAnyStringToken(tok::l_paren);
|
||||
llvm::sys::Path file(getCurTok().getIdent());
|
||||
llvm::StringRef args;
|
||||
result = true;
|
||||
consumeToken();
|
||||
if (getCurTok().is(tok::l_paren) && isExtraArgList()) {
|
||||
args = getCurTok().getIdent();
|
||||
consumeToken(); // consume the closing paren
|
||||
}
|
||||
m_Actions->actOnxCommand(file, args);
|
||||
actionResult = m_Actions->actOnxCommand(file, args, resultValue);
|
||||
|
||||
if (getCurTok().is(tok::comment)) {
|
||||
consumeAnyStringToken();
|
||||
m_Actions->actOnComment(getCurTok().getIdent());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return actionResult == MetaSema::AR_Success;
|
||||
}
|
||||
|
||||
// ExtraArgList := AnyString [, ExtraArgList]
|
||||
@ -177,9 +181,10 @@ namespace cling {
|
||||
return result;
|
||||
}
|
||||
|
||||
bool MetaParser::isUCommand() {
|
||||
bool MetaParser::isUCommand(MetaSema::ActionResult& actionResult) {
|
||||
actionResult = MetaSema::AR_Failure;
|
||||
if (getCurTok().is(tok::ident) && getCurTok().getIdent().equals("U")) {
|
||||
m_Actions->actOnUCommand();
|
||||
actionResult = m_Actions->actOnUCommand();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -314,7 +319,10 @@ namespace cling {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MetaParser::isShellCommand() {
|
||||
bool MetaParser::isShellCommand(StoredValueRef& resultValue,
|
||||
MetaSema::ActionResult& actionResult) {
|
||||
resultValue = StoredValueRef();
|
||||
actionResult = MetaSema::AR_Failure;
|
||||
const Token& Tok = getCurTok();
|
||||
if (Tok.is(tok::excl_mark)) {
|
||||
consumeAnyStringToken(tok::eof);
|
||||
@ -322,7 +330,8 @@ namespace cling {
|
||||
if (NextTok.is(tok::raw_ident)) {
|
||||
llvm::StringRef commandLine(NextTok.getIdent());
|
||||
if (!commandLine.empty())
|
||||
m_Actions->actOnShellCommand(commandLine);
|
||||
actionResult = m_Actions->actOnShellCommand(commandLine,
|
||||
resultValue);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
#define CLING_META_PARSER_H
|
||||
|
||||
#include "MetaLexer.h" // for cling::Token
|
||||
#include "MetaSema.h" // for ActionResult
|
||||
#include "cling/Interpreter/StoredValueRef.h"
|
||||
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
@ -64,12 +65,14 @@ namespace cling {
|
||||
void skipWhitespace();
|
||||
|
||||
bool isCommandSymbol();
|
||||
bool isCommand();
|
||||
bool isLCommand();
|
||||
bool isCommand(StoredValueRef& resultValue,
|
||||
MetaSema::ActionResult& actionResult);
|
||||
bool isLCommand(MetaSema::ActionResult& actionResult);
|
||||
bool isExtraArgList();
|
||||
bool isXCommand();
|
||||
bool isXCommand(StoredValueRef& resultValue,
|
||||
MetaSema::ActionResult& actionResult);
|
||||
bool isqCommand();
|
||||
bool isUCommand();
|
||||
bool isUCommand(MetaSema::ActionResult& actionResult);
|
||||
bool isICommand();
|
||||
bool israwInputCommand();
|
||||
bool isprintASTCommand();
|
||||
@ -80,7 +83,8 @@ namespace cling {
|
||||
bool isClassCommand();
|
||||
bool isgCommand();
|
||||
bool isTypedefCommand();
|
||||
bool isShellCommand();
|
||||
bool isShellCommand(StoredValueRef& resultValue,
|
||||
MetaSema::ActionResult& actionResult);
|
||||
public:
|
||||
MetaParser(MetaSema* Actions);
|
||||
void enterNewInputLine(llvm::StringRef Line);
|
||||
@ -89,13 +93,14 @@ namespace cling {
|
||||
///
|
||||
///\returns true if it was meta command.
|
||||
///
|
||||
bool isMetaCommand();
|
||||
bool isMetaCommand(StoredValueRef& resultValue,
|
||||
MetaSema::ActionResult& actionResult);
|
||||
|
||||
///\brief Returns whether quit was requested via .q command
|
||||
///
|
||||
bool isQuitRequested() const;
|
||||
|
||||
StoredValueRef getLastResultedValue() const;
|
||||
MetaSema& getActions() const { return *m_Actions.get(); }
|
||||
};
|
||||
} // end namespace cling
|
||||
|
||||
|
@ -37,16 +37,14 @@ namespace cling {
|
||||
MetaProcessor::~MetaProcessor() {}
|
||||
|
||||
int MetaProcessor::process(const char* input_text,
|
||||
StoredValueRef* result /*=0*/,
|
||||
Interpreter::CompilationResult* compRes /*=0*/ ) {
|
||||
StoredValueRef& result,
|
||||
Interpreter::CompilationResult& compRes) {
|
||||
result = StoredValueRef();
|
||||
compRes = Interpreter::kSuccess;
|
||||
int expectedIndent = m_InputValidator->getExpectedIndent();
|
||||
if (compRes) {
|
||||
if (expectedIndent) {
|
||||
*compRes = Interpreter::kMoreInputExpected;
|
||||
} else {
|
||||
*compRes = Interpreter::kSuccess;
|
||||
}
|
||||
}
|
||||
|
||||
if (expectedIndent)
|
||||
compRes = Interpreter::kMoreInputExpected;
|
||||
if (!input_text || !input_text[0]) {
|
||||
// nullptr / empty string, nothing to do.
|
||||
return expectedIndent;
|
||||
@ -57,34 +55,31 @@ namespace cling {
|
||||
}
|
||||
// Check for and handle meta commands.
|
||||
m_MetaParser->enterNewInputLine(input_line);
|
||||
if (m_MetaParser->isMetaCommand()) {
|
||||
MetaSema::ActionResult actionResult = MetaSema::AR_Success;
|
||||
if (m_MetaParser->isMetaCommand(result, actionResult)) {
|
||||
|
||||
if (m_MetaParser->isQuitRequested())
|
||||
return -1;
|
||||
|
||||
//TODO: set the compilation result if there was error in the meta commands
|
||||
if (result)
|
||||
*result = m_MetaParser->getLastResultedValue();
|
||||
if (actionResult != MetaSema::AR_Success)
|
||||
compRes = Interpreter::kFailure;
|
||||
return expectedIndent;
|
||||
}
|
||||
|
||||
// Check if the current statement is now complete. If not, return to
|
||||
// prompt for more.
|
||||
if (m_InputValidator->validate(input_line) == InputValidator::kIncomplete) {
|
||||
if (compRes)
|
||||
*compRes = Interpreter::kMoreInputExpected;
|
||||
compRes = Interpreter::kMoreInputExpected;
|
||||
return m_InputValidator->getExpectedIndent();
|
||||
}
|
||||
|
||||
// We have a complete statement, compile and execute it.
|
||||
std::string input = m_InputValidator->getInput();
|
||||
m_InputValidator->reset();
|
||||
Interpreter::CompilationResult compResLocal;
|
||||
// if (m_Options.RawInput)
|
||||
// compResLocal = m_Interp.declare(input);
|
||||
// else
|
||||
compResLocal = m_Interp.process(input, result);
|
||||
if (compRes) *compRes = compResLocal;
|
||||
compRes = m_Interp.process(input, &result);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -99,8 +94,8 @@ namespace cling {
|
||||
|
||||
// Run a file: .x file[(args)]
|
||||
bool MetaProcessor::executeFile(llvm::StringRef file, llvm::StringRef args,
|
||||
StoredValueRef* result,
|
||||
Interpreter::CompilationResult* compRes /*=0*/) {
|
||||
StoredValueRef& result,
|
||||
Interpreter::CompilationResult& compRes) {
|
||||
// Look for start of parameters:
|
||||
typedef std::pair<llvm::StringRef,llvm::StringRef> StringRefPair;
|
||||
|
||||
@ -118,19 +113,19 @@ namespace cling {
|
||||
if (topmost)
|
||||
m_TopExecutingFile = m_CurrentlyExecutingFile;
|
||||
|
||||
interpRes = m_Interp.process(expression, result);
|
||||
interpRes = m_Interp.process(expression, &result);
|
||||
|
||||
m_CurrentlyExecutingFile = llvm::StringRef();
|
||||
if (topmost)
|
||||
m_TopExecutingFile = llvm::StringRef();
|
||||
}
|
||||
if (compRes) *compRes = interpRes;
|
||||
compRes = interpRes;
|
||||
return (interpRes != Interpreter::kFailure);
|
||||
}
|
||||
|
||||
Interpreter::CompilationResult
|
||||
MetaProcessor::readInputFromFile(llvm::StringRef filename,
|
||||
StoredValueRef* result /* = 0 */,
|
||||
StoredValueRef& result,
|
||||
bool ignoreOutmostBlock /*=false*/) {
|
||||
|
||||
{
|
||||
@ -209,7 +204,7 @@ namespace cling {
|
||||
if (topmost)
|
||||
m_TopExecutingFile = m_CurrentlyExecutingFile;
|
||||
Interpreter::CompilationResult ret = Interpreter::kSuccess;
|
||||
if (process(content.c_str(), result, &ret)) {
|
||||
if (process(content.c_str(), result, ret)) {
|
||||
// Input file has to be complete.
|
||||
llvm::errs()
|
||||
<< "Error in cling::MetaProcessor: file "
|
||||
|
@ -11,12 +11,14 @@
|
||||
#include "cling/Interpreter/Interpreter.h"
|
||||
#include "cling/MetaProcessor/MetaProcessor.h"
|
||||
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
#include "clang/Frontend/CompilerInstance.h"
|
||||
#include "clang/Serialization/ASTReader.h"
|
||||
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ExecutionEngine/GenericValue.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
|
||||
#include <cstdlib>
|
||||
@ -25,14 +27,13 @@ namespace cling {
|
||||
|
||||
MetaSema::MetaSema(Interpreter& interp, MetaProcessor& meta)
|
||||
: m_Interpreter(interp), m_MetaProcessor(meta), m_IsQuitRequested(false),
|
||||
m_Outs(m_MetaProcessor.getOuts()){
|
||||
m_LastResultedValue = StoredValueRef::invalidValue();
|
||||
}
|
||||
m_Outs(m_MetaProcessor.getOuts()){ }
|
||||
|
||||
|
||||
void MetaSema::actOnLCommand(llvm::sys::Path file) const {
|
||||
m_Interpreter.loadFile(file.str());
|
||||
MetaSema::ActionResult MetaSema::actOnLCommand(llvm::sys::Path file) const {
|
||||
// TODO: extra checks. Eg if the path is readable, if the file exists...
|
||||
if (m_Interpreter.loadFile(file.str()) == Interpreter::kSuccess)
|
||||
return AR_Success;
|
||||
return AR_Failure;
|
||||
}
|
||||
|
||||
void MetaSema::actOnComment(llvm::StringRef comment) const {
|
||||
@ -40,11 +41,17 @@ namespace cling {
|
||||
m_Interpreter.declare(comment);
|
||||
}
|
||||
|
||||
void MetaSema::actOnxCommand(llvm::sys::Path file, llvm::StringRef args)
|
||||
{
|
||||
MetaSema::ActionResult MetaSema::actOnxCommand(llvm::sys::Path file,
|
||||
llvm::StringRef args,
|
||||
StoredValueRef& result) {
|
||||
// Fall back to the meta processor for now.
|
||||
m_LastResultedValue = StoredValueRef::invalidValue();
|
||||
m_MetaProcessor.executeFile(file.str(), args.str(), &m_LastResultedValue);
|
||||
Interpreter::CompilationResult compRes = Interpreter::kFailure;
|
||||
m_MetaProcessor.executeFile(file.str(), args.str(), result, compRes);
|
||||
ActionResult actionResult = AR_Failure;
|
||||
if (compRes == Interpreter::kSuccess)
|
||||
actionResult = AR_Success;
|
||||
return actionResult;
|
||||
|
||||
//m_Interpreter.loadFile(path.str());
|
||||
// TODO: extra checks. Eg if the path is readable, if the file exists...
|
||||
}
|
||||
@ -53,8 +60,10 @@ namespace cling {
|
||||
m_IsQuitRequested = true;
|
||||
}
|
||||
|
||||
void MetaSema::actOnUCommand() const {
|
||||
MetaSema::ActionResult MetaSema::actOnUCommand() const {
|
||||
// FIXME: unload, once implemented, must return success / failure
|
||||
m_Interpreter.unload();
|
||||
return AR_Success;
|
||||
}
|
||||
|
||||
void MetaSema::actOnICommand(llvm::sys::Path path) const {
|
||||
@ -185,12 +194,25 @@ namespace cling {
|
||||
DisplayTypedef(m_Outs, &m_Interpreter, typedefName.str().c_str());
|
||||
}
|
||||
|
||||
void MetaSema::actOnShellCommand(llvm::StringRef commandLine) const {
|
||||
MetaSema::ActionResult
|
||||
MetaSema::actOnShellCommand(llvm::StringRef commandLine,
|
||||
StoredValueRef& result) const {
|
||||
llvm::StringRef trimmed(commandLine.trim(" \t\n\v\f\r "));
|
||||
if (!trimmed.empty()) {
|
||||
int ret = std::system(trimmed.str().c_str());
|
||||
(void) ret; // Silence warning unused return result of system.
|
||||
int ret = std::system(trimmed.str().c_str());
|
||||
|
||||
// Build the result
|
||||
clang::ASTContext& Ctx = m_Interpreter.getCI()->getASTContext();
|
||||
llvm::GenericValue retGV;
|
||||
retGV.IntVal = llvm::APInt(sizeof(int) * 8, ret, true /*isSigned*/);
|
||||
Value V(retGV, Ctx.IntTy);
|
||||
result = StoredValueRef::bitwiseCopy(Ctx, V);
|
||||
|
||||
return (ret == 0) ? AR_Success : AR_Failure;
|
||||
}
|
||||
result = StoredValueRef();
|
||||
// nothing to run - should this be success or failure?
|
||||
return AR_Failure;
|
||||
}
|
||||
|
||||
} // end namespace cling
|
||||
|
@ -28,7 +28,6 @@ namespace cling {
|
||||
Interpreter& m_Interpreter;
|
||||
MetaProcessor& m_MetaProcessor;
|
||||
bool m_IsQuitRequested;
|
||||
StoredValueRef m_LastResultedValue;
|
||||
llvm::raw_ostream& m_Outs; // Shortens m_MetaProcessor->getOuts()
|
||||
public:
|
||||
enum SwitchMode {
|
||||
@ -36,18 +35,22 @@ namespace cling {
|
||||
kOn = 1,
|
||||
kToggle = 2
|
||||
};
|
||||
|
||||
enum ActionResult {
|
||||
AR_Failure = 0,
|
||||
AR_Success = 1
|
||||
};
|
||||
public:
|
||||
MetaSema(Interpreter& interp, MetaProcessor& meta);
|
||||
|
||||
const Interpreter& getInterpreter() const { return m_Interpreter; }
|
||||
bool isQuitRequested() const { return m_IsQuitRequested; }
|
||||
StoredValueRef getLastResultedValue() const { return m_LastResultedValue; };
|
||||
|
||||
///\brief L command includes the given file or loads the given library.
|
||||
///
|
||||
///\param[in] file - The file/library to be loaded.
|
||||
///
|
||||
void actOnLCommand(llvm::sys::Path file) const;
|
||||
ActionResult actOnLCommand(llvm::sys::Path file) const;
|
||||
|
||||
///\brief Actions that need to be performed on occurance of a comment.
|
||||
///
|
||||
@ -67,7 +70,8 @@ namespace cling {
|
||||
///\param[in] file - The filename to load.
|
||||
///\param[in] args - The optional list of arguments.
|
||||
///
|
||||
void actOnxCommand(llvm::sys::Path file, llvm::StringRef args);
|
||||
ActionResult actOnxCommand(llvm::sys::Path file, llvm::StringRef args,
|
||||
StoredValueRef& result);
|
||||
|
||||
///\brief Actions to be performed on quit.
|
||||
///
|
||||
@ -76,7 +80,7 @@ namespace cling {
|
||||
///\brief Actions to be performed on unload command. For now it tries to
|
||||
/// unload the last transaction.
|
||||
///
|
||||
void actOnUCommand() const;
|
||||
ActionResult actOnUCommand() const;
|
||||
|
||||
///\brief Actions to be performed on add include path. It registers new
|
||||
/// folder where header files can be searched.
|
||||
@ -147,7 +151,8 @@ namespace cling {
|
||||
///\param[in] commandLine - shell command + optional
|
||||
// list of parameters.
|
||||
///
|
||||
void actOnShellCommand(llvm::StringRef commandLine) const;
|
||||
ActionResult actOnShellCommand(llvm::StringRef commandLine,
|
||||
StoredValueRef& result) const;
|
||||
};
|
||||
|
||||
} // end namespace cling
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "cling/UserInterface/UserInterface.h"
|
||||
|
||||
#include "cling/Interpreter/StoredValueRef.h"
|
||||
#include "cling/MetaProcessor/MetaProcessor.h"
|
||||
#include "textinput/TextInput.h"
|
||||
#include "textinput/StreamReader.h"
|
||||
@ -68,8 +69,10 @@ namespace cling {
|
||||
if (RR == TextInput::kRREOF) {
|
||||
break;
|
||||
}
|
||||
|
||||
int indent = m_MetaProcessor->process(line.c_str());
|
||||
|
||||
cling::StoredValueRef result;
|
||||
cling::Interpreter::CompilationResult compRes;
|
||||
int indent = m_MetaProcessor->process(line.c_str(), result, compRes);
|
||||
// Quit requested
|
||||
if (indent < 0)
|
||||
break;
|
||||
|
@ -5,6 +5,7 @@
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#include "cling/Interpreter/Interpreter.h"
|
||||
#include "cling/Interpreter/StoredValueRef.h"
|
||||
#include "cling/MetaProcessor/MetaProcessor.h"
|
||||
#include "cling/UserInterface/UserInterface.h"
|
||||
|
||||
@ -53,7 +54,9 @@ int main( int argc, char **argv ) {
|
||||
for (size_t I = 0, N = Inputs.size(); I < N; ++I) {
|
||||
std::string line(".x ");
|
||||
line += Inputs[I].getFile();
|
||||
ui.getMetaProcessor()->process(line.c_str());
|
||||
cling::StoredValueRef result;
|
||||
cling::Interpreter::CompilationResult compRes;
|
||||
ui.getMetaProcessor()->process(line.c_str(), result, compRes);
|
||||
ret = !CI->getDiagnostics().getClient()->getNumErrors();
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user