Skip to content

Commit

Permalink
got the first push on file system connectd with basic instructions wo…
Browse files Browse the repository at this point in the history
…rking like ls, more, append, mkdir. light testing.
  • Loading branch information
okram committed Jul 24, 2024
1 parent 1d8e0f9 commit 9b0f8c3
Show file tree
Hide file tree
Showing 12 changed files with 117 additions and 45 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ IF (BUILD_NATIVE)
${ROOT_SOURCE_DIR}/language/obj.hpp
${ROOT_SOURCE_DIR}/process/abstract_scheduler.hpp
${ROOT_SOURCE_DIR}/structure/furi.hpp)
TARGET_PRECOMPILE_HEADERS(${PROJECT_NAME} PRIVATE ${HEADER_FILES})
# TARGET_PRECOMPILE_HEADERS(${PROJECT_NAME} PRIVATE ${HEADER_FILES})
###############################
ADD_COMPILE_OPTIONS("-Wno-ambiguous-reversed-operator")
ADD_DEFINITIONS("-DNATIVE")
Expand Down
4 changes: 2 additions & 2 deletions docs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ IF (BUILD_DOCS)
MATH(EXPR COUNTER "${COUNTER}+1")
MESSAGE(CHECK_START "${.y}CMaking ${PACKAGE_RUNNER}${..}")
ADD_EXECUTABLE(${PACKAGE_RUNNER} ${CMAKE_SOURCE_DIR}/docs/src/${PACKAGE}/${PACKAGE_RUNNER}/${PACKAGE_RUNNER}.cpp)
ADD_DEFINITIONS("-DNATIVE" "-Wno-ambiguous-reversed-operator")
ADD_COMPILE_OPTIONS("-Wno-dev")
TARGET_LINK_LIBRARIES(${PACKAGE_RUNNER} tsl::ordered_map paho-mqttpp3)
TARGET_PRECOMPILE_HEADERS(${PACKAGE_RUNNER} REUSE_FROM ${PROJECT_NAME})
# TARGET_PRECOMPILE_HEADERS(${PACKAGE_RUNNER} REUSE_FROM ${PROJECT_NAME})
SET_TARGET_PROPERTIES(${PACKAGE_RUNNER} PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/docs/build"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/docs/build"
Expand Down
7 changes: 4 additions & 3 deletions docs/fhatos.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ fhatos> define(/rec/person,|[name=>as(/str/),age=>as(/int/nat)])
fhatos> person[[name=>'fhatty',age=>0]]
[ERROR] [/sys/lang/type/] 0 is not a /int/nat[is[gt[0]]]
fhatos> person[[name=>'fhatty',age=>1]]
==>person[[name=>'fhatty',age=>1]]
==>person[[/rec/name=>'fhatty',/rec/age=>1]]
----
++++
<!-- OUTPUT:END -->
Expand Down Expand Up @@ -205,8 +205,9 @@ fhatos> __(1,2,3,4).plus(10)
==>13
==>14
fhatos> 16.to(b)
==>16
fhatos> *b.plus(45)
==>61
----
++++
<!-- OUTPUT:END -->
++++
10 changes: 4 additions & 6 deletions docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ <h3 id="_the_mm_adt_language">The mm-ADT Language</h3>
fhatos&gt; person[[name=&gt;'fhatty',age=&gt;0]]
[ERROR] [/sys/lang/type/] 0 is not a /int/nat[is[gt[0]]]
fhatos&gt; person[[name=&gt;'fhatty',age=&gt;1]]
==&gt;person[[name=&gt;'fhatty',age=&gt;1]]</code></pre>
==&gt;person[[/rec/name=&gt;'fhatty',/rec/age=&gt;1]]</code></pre>
</div>
</div>
<!-- OUTPUT:END -->
Expand Down Expand Up @@ -459,21 +459,19 @@ <h3 id="_furi_and_mqtt">fURI and MQTT</h3>
==&gt;13
==&gt;14
fhatos&gt; 16.to(b)
==&gt;16
fhatos&gt; *b.plus(45)

&lt;!-- OUTPUT:END --&gt;
++++</code></pre>
==&gt;61</code></pre>
</div>
</div>
<!-- OUTPUT:END -->
</div>
</div>
</div>
</div>
<div id="footer">
<div id="footer-text">
Version 0.1<br>
Last updated 2024-07-23 17:29:57 -0600
Last updated 2024-07-24 02:04:06 -0600
</div>
</div>
<script src="./highlight/highlight.min.js"></script>
Expand Down
21 changes: 19 additions & 2 deletions src/language/insts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -459,11 +459,11 @@ namespace fhatos {
if (key2->isUri())
Router::write(key2->uri_value(), val2);
}
Router::write(lhs->uri_value(), Obj::to_lst(links));
Router::write(lhs->uri_value(), Obj::to_rec(rec2));
return Obj::to_rec(rec2);
} else {
const Obj_p o = rhs->apply(lhs);
Router::write(o->isUri() ? o->uri_value() : lhs->uri_value(), rhs);
Router::write(o->isUri() ? o->apply(lhs)->uri_value() : lhs->uri_value(), o);
return o;
}
};
Expand Down Expand Up @@ -512,7 +512,24 @@ namespace fhatos {
return map;
}

static Map<ID, Function<List<Obj_p>, Inst_p>> *INSTS_MAP() {
static Map<ID, Function<List<Obj_p>, Inst_p>> map = Map<ID, Function<List<Obj_p>, Inst_p>>();
return &map;
}
static void register_inst(const ID &type, const Function<List<Obj_p>, Inst_p> &func) {
INSTS_MAP()->insert({type, func});
LOG(INFO, "Instruction registered: %s\n", type.toString().c_str());
ID shortID = INST_FURI->resolve(type.name());
if (!INSTS_MAP()->count(shortID)) {
INSTS_MAP()->insert({shortID, func});
LOG(INFO, FOS_TAB_4 "Shorthand registered: !b%s!!\n", shortID.toString().c_str());
} else {
LOG(WARN, FOS_TAB_4 "Unable to register shorthand: !b%s!!\n", shortID.toString().c_str());
}
}
static Inst_p to_inst(const ID &type, const List<Obj_p> &args) {
if (INSTS_MAP()->count(type)) // check registered instructions
return INSTS_MAP()->at(type)(args);
if (type == INST_FURI->resolve("start") || type == INST_FURI->resolve("__"))
return Insts::start(Objs::to_objs(args));
if (type == INST_FURI->resolve("end") || type == INST_FURI->resolve(";"))
Expand Down
11 changes: 8 additions & 3 deletions src/language/obj.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -943,7 +943,7 @@ namespace fhatos {
auto itB = objsB->begin();
for (const auto &itA: *objsA) {
LOG(TRACE, "MATCHING: %s vs. %s\n", itA->toString().c_str(), (*itB)->toString().c_str());
if (!itA->match(*itB) || !itA->match(*itB))
if (!itA->match(*itB))
return false;
++itB;
}
Expand Down Expand Up @@ -1067,7 +1067,12 @@ namespace fhatos {

static Rec_p to_rec(const RecMap_p<> &map, const fURI_p &furi = REC_FURI) {
assert(furi->path(0, 1) == OTypes.toChars(OType::REC));
return share(Obj(map, furi));
RecMap_p<> convert = share(RecMap<>());
for (const auto &[key, val]: *map) {
convert->insert({key->isUri() ? Obj::to_uri(furi->resolve(key->uri_value())) : key,
val->isUri() ? Obj::to_uri(furi->resolve(val->uri_value())) : val});
}
return share(Obj(convert, furi));
}

static Rec_p to_rec(const std::initializer_list<Pair<const Obj, Obj>> &xrec, const fURI_p &furi = REC_FURI) {
Expand All @@ -1081,7 +1086,7 @@ namespace fhatos {
static Rec_p to_rec(const std::initializer_list<Pair<const Obj_p, Obj_p>> &xrec, const fURI_p &furi = REC_FURI) {
RecMap<> map = RecMap<>();
for (const auto &pair: xrec) {
map.insert(make_pair(pair.first,pair.second));
map.insert(make_pair(pair.first, pair.second));
}
return to_rec(share(map), furi);
}
Expand Down
4 changes: 1 addition & 3 deletions src/language/processor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,18 +85,16 @@ namespace fhatos {
if(!this->bcode->isBytecode())
throw fError("Processor requires a bcode obj to execute: %s\n", bcode->toString().c_str());
this->bcode = Rewriter({Rewriter::by()}).apply(this->bcode);
bool first = true; // TODO HACK:: ZERO_TO_Y OR X_TO_Y instructions need to be determined based on location in bcode
for (const Inst_p &inst: this->bcode->bcode_value()) {
if (Insts::isBarrier(inst)) {
const Monad_p monad = share(Monad(inst->inst_seed(), inst));
this->barriers->push_back(monad);
LOG(DEBUG, FOS_TAB_2 "!yBarrier!! monad: %s\n", monad->toString().c_str());
} else if (Insts::isInitial(inst) && first) {
} else if (Insts::isInitial(inst)) {
const Monad_p monad = share(Monad(inst->inst_seed(), inst));
this->running->push_back(monad);
LOG(DEBUG, FOS_TAB_2 "!mStarting!! monad: %s\n", monad->toString().c_str());
}
first = false;
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/structure/console/console.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ namespace fhatos {
} else if (index == string::npos) {
std::get<2>(_MENU_MAP->at(command))();
} else {
const string value = this->_line.substr(index);
string value = this->_line.substr(index);
StringHelper::trim(value);
std::get<1>(_MENU_MAP->at(command))(
Parser::singleton()->tryParseObj(value).value()->apply(Obj::to_noobj()));
Expand Down
47 changes: 42 additions & 5 deletions src/structure/io/filesystem/abstract_filesystem.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,26 +31,60 @@ namespace fhatos {

static const fURI_p FILE_FURI = fURI_p(new fURI("/uri/file"));
static const fURI_p DIR_FURI = fURI_p(new fURI("/uri/dir"));
static const fURI_p INST_FS_FURI = fURI_p(new fURI("/inst/fs/"));

class AbstractFileSystem : public Actor<Coroutine> {
public:
const ID_p _root;
ID_p _root;
explicit AbstractFileSystem(const ID &id, const ID &localRoot) : Actor<Coroutine>(id), _root(share(localRoot)) {}

void setup() override {
Actor::setup();
LOG_TASK(INFO, this, "!b%s!! !ydirectory!! mounted\n", this->_root->toString().c_str());
TYPE_WRITER(*FILE_FURI, Obj::to_bcode({}));
TYPE_WRITER(*DIR_FURI, Obj::to_bcode({}));
// TYPE_WRITER("/inst/root",
// Obj::to_inst("root", {}, [this](const Obj_p &lhs) { return this->root(); }, IType::ONE_TO_ONE));
this->publish(*this->id(), Obj::to_uri(*this->_root), RETAIN_MESSAGE);
this->subscribe("#", [this](const Message_p &message) {
if (message->retain) {
const ID file = makeRouterPath(message->target);
const File_p f = this->exists(file) ? this->to_file(file) : this->touch(file);
this->append(f, message->payload);
}
});
///////////////////////////////////////////////////////////////////
Insts::register_inst(INST_FS_FURI->resolve("root"), [this](List<Obj_p> args) {
return Obj::to_inst(
"root", {}, [this](const Obj_p &lhs) { return this->root(); }, IType::ZERO_TO_ONE, Obj::to_noobj(),
share(INST_FS_FURI->resolve("root")));
});
Insts::register_inst(INST_FS_FURI->resolve("ls"), [this](List<Obj_p> args) {
return Obj::to_inst(
"ls", args,
[this, args](const Obj_p &lhs) {
return args.empty() ? this->ls(lhs, "#") : this->ls(args.at(0)->apply(lhs), "#");
},
IType::ONE_TO_MANY, Obj::to_objs(), share(INST_FS_FURI->resolve("ls")));
});
Insts::register_inst(INST_FS_FURI->resolve("mkdir"), [this](List<Obj_p> args) {
return Obj::to_inst(
"mkdir", {args.at(0)},
[this, args](const Obj_p &lhs) { return this->mkdir(args.at(0)->apply(lhs)->uri_value()); },
IType::ONE_TO_MANY, Obj::to_objs(), share(INST_FS_FURI->resolve("ls")));
});
Insts::register_inst(INST_FS_FURI->resolve("more"), [this](List<Obj_p> args) {
return Obj::to_inst(
"more", args,
[this, args](const Obj_p &lhs) {
return args.empty() ? this->more(lhs) : this->more(args.at(0)->apply(lhs));
},
IType::ONE_TO_ONE, Obj::to_noobj(), share(INST_FS_FURI->resolve("more")));
});
Insts::register_inst(INST_FS_FURI->resolve("append"), [this](List<Obj_p> args) {
return Obj::to_inst(
"append",args,
[this, args](const Obj_p &lhs) { return this->append(lhs, args.at(0)->apply(lhs)); }, IType::ONE_TO_ONE,
Obj::to_noobj(), share(INST_FS_FURI->resolve("append")));
});
}

virtual File_p to_file(const ID &path) const { throw fError("must be implemented"); }
Expand All @@ -59,14 +93,17 @@ namespace fhatos {
virtual ID makeFilePath(const ID &path) const {
return ID(path.toString().substr(this->id()->toString().length() + 1));
}
virtual ID makeFhatPath(const ID &path) const {
return this->id()->extend(path.toString().c_str());
}
virtual ID makeRouterPath(const ID &path) const { return ID(this->id()->toString() + "/" + path.toString()); }
////
virtual Dir_p root() const { throw fError("must be implemented"); }
virtual bool exists(const ID &path) const { throw fError("must be implemented"); }
virtual Dir_p mkdir(const ID &path) const { throw fError("must be implemented"); }
virtual Objs_p ls(const Dir_p &dir, const Pattern &pattern) const { throw fError("must be implemented"); }
virtual Objs_p more(const File_p &file) const { throw fError("must be implemented"); }
virtual void append(const File_p &file, const Obj_p &content) { throw fError("must be implemented"); }
virtual Obj_p more(const File_p &file) const { throw fError("must be implemented"); }
virtual File_p append(const File_p &file, const Obj_p &content) { throw fError("must be implemented"); }
virtual File_p touch(const ID &path) const { throw fError("must be implemented"); }
};
} // namespace fhatos
Expand Down
45 changes: 27 additions & 18 deletions src/structure/io/filesystem/native/filesystem.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,17 @@ namespace fs = std::filesystem;
namespace fhatos {
class FileSystem : public AbstractFileSystem {
private:
explicit FileSystem(const ID &id, const ID &root) :
AbstractFileSystem(id, root) {}
explicit FileSystem(const ID &id, const ID &root) : AbstractFileSystem(id, root) {
LOG(INFO, "Original working directory: %s\n", fs::current_path().c_str());
const fs::path p = fs::current_path().concat("/tmp");
// int removed = fs::remove_all(p);
// LOG(INFO, "Deleted existing working directory with %i items\n", removed);
// assert(fs::create_directory(p));
fs::current_path(p); //
LOG(INFO, "Creating new working directory: %s\n", p.c_str());
LOG(INFO, "Test working directory: %s\n", fs::current_path().c_str());
this->_root = share(ID(fs::current_path()));
}

public:
static FileSystem *singleton(const ID &id = ID("/sys/io/fs"), const ID &root = ID(fs::current_path())) {
Expand All @@ -47,16 +56,14 @@ namespace fhatos {
Dir_p to_dir(const ID &path) const override {
if (is_directory(fs::path(makeLocalPath(path).toString())))
return Obj::to_uri(path, DIR_FURI);
throw fError("!g[!!%s!g]!! %s does not reference a directory\n",
throw fError("!g[!b%s!g]!! %s does not reference a directory\n",
FileSystem::singleton()->id()->toString().c_str(), path.toString().c_str());
}
ID makeLocalPath(const ID &path) const override {
return ID(singleton()->_root->toString() + "/" + path.toString());
}
Dir_p root() const override { return to_dir(makeLocalPath("")); }
ID makeLocalPath(const ID &path) const override { return singleton()->_root->extend(path.toString().c_str()); }
Dir_p root() const override { return to_dir("/"); }
Dir_p mkdir(const ID &path) const override {
if (fs::is_directory(makeLocalPath(path).toString())) {
throw fError("!g[!!%s!g]!! %s already exists\n", FileSystem::singleton()->id()->toString().c_str(),
throw fError("!g[!b%s!g]!! %s already exists\n", FileSystem::singleton()->id()->toString().c_str(),
path.toString().c_str());
}
fs::create_directory(makeLocalPath(path).toString());
Expand All @@ -65,25 +72,27 @@ namespace fhatos {
Objs_p ls(const Dir_p &dir, const Pattern &pattern) const override {
auto *listing = new List<Uri_p>();
for (const auto &p: fs::directory_iterator(fs::path(makeLocalPath(dir->uri_value()).toString()))) {
if ((p.is_directory() || p.is_regular_file()) && ID(p.path()).matches(pattern)) {
if ((fs::is_directory(p) || fs::is_regular_file(p)) /*&& ID(p.path()).matches(pattern)*/) {
const ID pp =
ID(p.path().string().substr(this->_root->toString().length() + 1)); // clip off local mount location
if (pp.matches(pattern)) {
listing->push_back(p.is_directory() ? to_dir(pp) : to_file(pp));
}
// if (pp.matches(pattern)) {
listing->push_back(fs::is_directory(p) ? to_dir(pp) : to_file(pp));
}
}
return Obj::to_objs(ptr<List<Uri_p>>(listing));
}
Objs_p more(const File_p &file) const override {
std::ifstream fstrm(makeLocalPath(file->uri_value()).toString());
return Obj::to_str(std::string((std::istreambuf_iterator<char>(fstrm)), std::istreambuf_iterator<char>()));
Obj_p more(const File_p &file) const override {
std::ifstream fstrm(fs::path(makeLocalPath(file->uri_value()).toString()));
std::stringstream buffer;
buffer << fstrm.rdbuf();
return Obj::to_str(buffer.str().c_str());
}
void append(const File_p &file, const Obj_p &content) override {
File_p append(const File_p &file, const Obj_p &content) override {
std::ofstream outfile;
outfile.open(this->id()->toString(), std::ios_base::app);
outfile.open(fs::path(makeLocalPath(file->uri_value()).toString()), std::ios_base::app);
const string s = content->toString();
outfile.write(s.c_str(), s.length());
outfile << s.c_str();
return file;
}
File_p touch(const ID &path) const override {
if (fs::is_regular_file(makeLocalPath(path).toString())) {
Expand Down
6 changes: 6 additions & 0 deletions src/util/fhat_error.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ namespace fhatos {
va_start(arg, format);
int length = vsnprintf(_message, FOS_ERROR_MESSAGE_SIZE, format, arg);
_message[length] = '\0';
if (length >= FOS_ERROR_MESSAGE_SIZE) {
_message[FOS_ERROR_MESSAGE_SIZE - 1] = '\n';
_message[FOS_ERROR_MESSAGE_SIZE - 2] = '.';
_message[FOS_ERROR_MESSAGE_SIZE - 3] = '.';
_message[FOS_ERROR_MESSAGE_SIZE - 4] = '.';
}
va_end(arg);
};
const char *what() const noexcept override { return this->_message; }
Expand Down
3 changes: 2 additions & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@ IF (BUILD_TESTS)
MATH(EXPR COUNTER "${COUNTER}+1")
MESSAGE(CHECK_START "${.y}CMaking ${PACKAGE_TEST}${..}")
ADD_EXECUTABLE(${PACKAGE_TEST} ${CMAKE_SOURCE_DIR}/test/${PACKAGE}/${PACKAGE_TEST}/${PACKAGE_TEST}.cpp)
ADD_COMPILE_OPTIONS("-Wno-dev")
ADD_DEFINITIONS("-DFOS_LOGGING=DEBUG" "-DNATIVE" "-Wno-ambiguous-reversed-operator")
TARGET_LINK_LIBRARIES(${PACKAGE_TEST} unity::framework tsl::ordered_map paho-mqttpp3)
#TARGET_PRECOMPILE_HEADERS(${PACKAGE_TEST} PUBLIC ${ROOT_SOURCE_DIR}/test_fhatos.hpp)
TARGET_PRECOMPILE_HEADERS(${PACKAGE_TEST} REUSE_FROM ${PROJECT_NAME})
#TARGET_PRECOMPILE_HEADERS(${PACKAGE_TEST} REUSE_FROM ${PROJECT_NAME})
SET_TARGET_PROPERTIES(${PACKAGE_TEST} PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/test/build"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/test/build"
Expand Down

0 comments on commit 9b0f8c3

Please sign in to comment.