link to the Guile library and add some Guile demo code – evaluate code from CLI argument
try:
relpipe-in-fstab | relpipe-tr-guile 'fstab' '(or (= a b) (= a a) )' | relpipe-out-tabular
relpipe-in-fstab | relpipe-tr-guile 'fstab' '(or (= a b) (= a 9) )' | relpipe-out-tabular
--- a/nbproject/configurations.xml Sat Jan 19 16:01:08 2019 +0100
+++ b/nbproject/configurations.xml Sun Jan 20 01:02:40 2019 +0100
@@ -82,6 +82,7 @@
<pElem>../relpipe-lib-reader.cpp/include</pElem>
<pElem>../relpipe-lib-writer.cpp/include</pElem>
<pElem>../relpipe-lib-cli.cpp/include</pElem>
+ <pElem>/usr/include/guile/2.2</pElem>
<pElem>build/Debug/src</pElem>
</incDir>
</ccTool>
--- a/src/CMakeLists.txt Sat Jan 19 16:01:08 2019 +0100
+++ b/src/CMakeLists.txt Sun Jan 20 01:02:40 2019 +0100
@@ -18,7 +18,7 @@
# Relpipe libraries:
INCLUDE(FindPkgConfig)
-pkg_check_modules (RELPIPE_LIBS relpipe-lib-reader.cpp relpipe-lib-writer.cpp relpipe-lib-cli.cpp)
+pkg_check_modules (RELPIPE_LIBS relpipe-lib-reader.cpp relpipe-lib-writer.cpp relpipe-lib-cli.cpp guile-2.2)
include_directories(${RELPIPE_LIBS_INCLUDE_DIRS})
link_directories(${RELPIPE_LIBS_LIBRARY_DIRS})
--- a/src/GuileHandler.h Sat Jan 19 16:01:08 2019 +0100
+++ b/src/GuileHandler.h Sun Jan 20 01:02:40 2019 +0100
@@ -26,6 +26,8 @@
#include <codecvt>
#include <regex>
+#include <libguile.h>
+
#include <relpipe/reader/typedefs.h>
#include <relpipe/reader/TypeId.h>
#include <relpipe/reader/handlers/RelationalReaderStringHandler.h>
@@ -46,6 +48,8 @@
class GuileHandler : public RelationalReaderStringHadler {
private:
+ std::wstring_convert<codecvt_utf8<wchar_t>> convertor; // TODO: support also other encodings.
+
shared_ptr<writer::RelationalWriter> relationalWriter;
wregex relationNameRegEx;
@@ -55,6 +59,44 @@
integer_t currentAttributeIndex = 0;
boolean_t includeCurrentRecord = false;
boolean_t filterCurrentRelation = false;
+ string_t guileCode;
+
+ SCM toGuileSymbol(const string_t& name) {
+ return scm_string_to_symbol(scm_from_locale_string(convertor.to_bytes(name).c_str()));
+ }
+
+ SCM toGuileString(const string_t& value) {
+ return scm_from_locale_string(convertor.to_bytes(value).c_str());
+ }
+
+ SCM toGuileInteger(const string_t& value) {
+ return scm_from_uint64(stoul(value));
+ }
+
+ SCM toGuileBoolean(const string_t& value) {
+ return value == L"true" ? SCM_BOOL_T : SCM_BOOL_F;
+ }
+
+ void defineGuileVariable(const string_t& name, TypeId type, const string_t& value) {
+ // TODO: RelationalReaderValueHadler?
+ switch (type) {
+ case TypeId::BOOLEAN:
+ scm_define(toGuileSymbol(name), toGuileBoolean(value));
+ break;
+ case TypeId::INTEGER:
+ scm_define(toGuileSymbol(name), toGuileInteger(value));
+ break;
+ case TypeId::STRING:
+ scm_define(toGuileSymbol(name), toGuileString(value));
+ break;
+ default:
+ throw cli::RelpipeCLIException(L"Unsupported type in defineGuileVariable()", cli::CLI::EXIT_CODE_UNEXPECTED_ERROR);
+ }
+ }
+
+ void undefineGuileVariable(const string_t& name, TypeId type, const string_t& value) {
+ scm_define(toGuileSymbol(name), scm_make_undefined_variable()); // undefined != (define n)
+ }
public:
@@ -62,8 +104,9 @@
relationalWriter.reset(writer::Factory::create(output));
// TODO: options and parser
- if (arguments.size() == 1) {
+ if (arguments.size() == 2) {
relationNameRegEx = wregex(arguments[0]);
+ guileCode = arguments[1];
} else {
throw cli::RelpipeCLIException(L"Usage: relpipe-tr-guile <relationNameRegExp>", cli::CLI::EXIT_CODE_UNKNOWN_COMMAND);
}
@@ -74,9 +117,10 @@
// TODO: move to a reusable method (or use same metadata on both reader and writer side?)
vector<writer::AttributeMetadata> writerMetadata;
for (AttributeMetadata readerMetadata : attributes) {
+
writerMetadata.push_back({readerMetadata.getAttributeName(), relationalWriter->toTypeId(readerMetadata.getTypeName())});
}
-
+
currentRecord.resize(attributes.size());
filterCurrentRelation = regex_match(name, relationNameRegEx);
@@ -89,6 +133,21 @@
currentRecord[currentAttributeIndex] = value;
includeCurrentRecord = false;
+ // TODO: remove, just a demo code
+ defineGuileVariable(L"hello", TypeId::STRING, L"world");
+ defineGuileVariable(L"a", TypeId::INTEGER, L"123");
+ defineGuileVariable(L"b", TypeId::INTEGER, L"456");
+ defineGuileVariable(L"tr", TypeId::BOOLEAN, L"true");
+ defineGuileVariable(L"fa", TypeId::BOOLEAN, L"false");
+
+ //integer_t guileResult = scm_to_uint64(scm_eval_string(toGuileString(guileCode)));
+ //std::wcerr << "result from Guile: " << guileResult << std::endl;
+
+ includeCurrentRecord = scm_to_bool(scm_eval_string(toGuileString(guileCode)));
+ //scm_shell(0, nullptr);
+ // --------
+
+
currentAttributeIndex++;
if (currentAttributeIndex > 0 && currentAttributeIndex % currentMetadata.size() == 0) {
@@ -98,6 +157,7 @@
currentAttributeIndex = currentAttributeIndex % currentMetadata.size();
} else {
+
relationalWriter->writeAttribute(value);
}
}
--- a/src/relpipe-tr-guile.cpp Sat Jan 19 16:01:08 2019 +0100
+++ b/src/relpipe-tr-guile.cpp Sun Jan 20 01:02:40 2019 +0100
@@ -38,7 +38,7 @@
using namespace relpipe::reader;
using namespace relpipe::tr::guile;
-int main(int argc, char**argv) {
+static void relpipeMain(void *closure, int argc, char **argv) {
setlocale(LC_ALL, "");
CLI::untieStdIO();
CLI cli(argc, argv);
@@ -63,5 +63,10 @@
resultCode = CLI::EXIT_CODE_DATA_ERROR;
}
- return resultCode;
+ exit(resultCode);
}
+
+int main(int argc, char**argv) {
+ scm_boot_guile(argc, argv, relpipeMain, nullptr);
+ return 999; // never reached – see exit(resultCode) above
+}