Skip to content

Commit

Permalink
Merge pull request #103 from heinezen/ns-load
Browse files Browse the repository at this point in the history
Fix Fiesta
  • Loading branch information
TheJJ authored Jun 12, 2023
2 parents f9ef23b + 05ab50b commit 97ab90a
Show file tree
Hide file tree
Showing 10 changed files with 317 additions and 126 deletions.
10 changes: 8 additions & 2 deletions nyan/ast.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2016-2021 the nyan authors, LGPLv3+. See copying.md for legal info.
// Copyright 2016-2023 the nyan authors, LGPLv3+. See copying.md for legal info.

#include "ast.h"

Expand Down Expand Up @@ -301,7 +301,9 @@ void ASTObject::ast_members(TokenStream &tokens) {
bool object_next = false;
auto lookahead = tokens.next();

if (lookahead->type == token_type::OPERATOR or lookahead->type == token_type::COLON) {
if (lookahead->type == token_type::OPERATOR // value assignment
or lookahead->type == token_type::COLON // type declaration
or lookahead->type == token_type::DOT) { // inherited member access (e.g. Parent.some_member)
object_next = false;
}
else if (lookahead->type == token_type::LANGLE or lookahead->type == token_type::LBRACKET or lookahead->type == token_type::LPAREN) {
Expand Down Expand Up @@ -340,6 +342,10 @@ void ASTObject::ast_members(TokenStream &tokens) {

token = tokens.next();
}

if (token->type == token_type::ENDFILE) {
tokens.reinsert_last();
}
}


Expand Down
3 changes: 3 additions & 0 deletions nyan/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ constexpr const order_t LATEST_T = std::numeric_limits<order_t>::max();
/** fully-qualified object name */
using fqon_t = std::string;

/** fully-qualified namespace name */
using fqnn_t = fqon_t;

/** member name identifier type */
using memberid_t = std::string;

Expand Down
93 changes: 72 additions & 21 deletions nyan/database.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2017-2021 the nyan authors, LGPLv3+. See copying.md for legal info.
// Copyright 2017-2023 the nyan authors, LGPLv3+. See copying.md for legal info.

#include "database.h"

Expand Down Expand Up @@ -90,13 +90,16 @@ void Database::load(const std::string &filename,
// the location is the first request origin.
std::unordered_map<Namespace, Location> to_import;

// push the first namespace to import
to_import.insert(
{
Namespace::from_filename(filename),
Location{" -> requested by native call to Database::load()"}
}
);
auto file_ns = Namespace::from_filename(filename);
if (not this->meta_info.has_namespace(file_ns.to_fqon())) {
// push the first namespace to import
to_import.insert(
{
file_ns,
Location{" -> requested by native call to Database::load()"}
}
);
}

// descend to all imports and load the files
while (to_import.size() > 0) {
Expand Down Expand Up @@ -147,15 +150,16 @@ void Database::load(const std::string &filename,
}

// check if this import was already requested or is known.
// todo: also check if that ns is already fully loaded in the db
auto was_imported = imports.find(request);
auto import_requested = to_import.find(request);

if (was_imported == std::end(imports) and
import_requested == std::end(to_import)) {

// add the request to the pending imports
to_import.insert({std::move(request), import.get()});
if (not this->meta_info.has_namespace(request.to_fqon())) {
// add the request to the pending imports
to_import.insert({std::move(request), import.get()});
}
}
}

Expand Down Expand Up @@ -214,7 +218,11 @@ void Database::load(const std::string &filename,
throw InternalError{"object info could not be retrieved"};
}

info->set_children(std::move(children));
info->add_children(std::move(children));
}

for (auto loaded: imports) {
this->meta_info.add_namespace(loaded.first);
}

// TODO: check pending objectvalues (probably not needed as they're all loaded)
Expand Down Expand Up @@ -283,11 +291,14 @@ void Database::create_obj_content(std::vector<fqon_t> *new_objs,
fqon_t parent_id = scope.find(ns, parent, this->meta_info);

// this object is therefore a child of the parent one.
auto ins = child_assignments->emplace(
parent_id,
std::unordered_set<fqon_t>{}
);
ins.first->second.insert(obj_fqon);
auto ins = child_assignments->find(parent_id);
if (ins == std::end(*child_assignments)) {
ins = child_assignments->emplace(
parent_id,
std::unordered_set<fqon_t>{}
).first;
}
ins->second.insert(obj_fqon);

object_parents.push_back(std::move(parent_id));
}
Expand Down Expand Up @@ -367,6 +378,19 @@ void Database::find_member(bool skip_first,

bool finished = false;

// if the member is inherited, it can be prefixed with the ID
// of the object it's inherited from, e.g. ParentObj.some_member
memberid_t member_name = member_id;
std::optional<fqon_t> member_obj_id = std::nullopt;
std::vector<std::string> member_parts = util::split(member_id, '.');
if (member_parts.size() > 1) {
member_name = member_parts.back();
member_parts.pop_back();

// TODO: we might need to resolve aliases here
member_obj_id = util::strjoin(".", member_parts);
}

// member doesn't have type yet. find it.
for (auto &obj : search_objs) {

Expand All @@ -377,22 +401,35 @@ void Database::find_member(bool skip_first,
continue;
}

// TODO: if the obj fqon is prefixed, we can skip objects that don't match
// TODO: This requires that aliases and fqons are properly resolved
// if (member_obj_id and member_obj_id != obj) {
// continue;
// }

ObjectInfo *obj_info = this->meta_info.get_object(obj);
if (unlikely(obj_info == nullptr)) {
throw InternalError{"object information not retrieved"};
}
const MemberInfo *obj_member_info = obj_info->get_member(member_id);
const MemberInfo *obj_member_info = obj_info->get_member(member_name);

// obj doesn't have this member
if (not obj_member_info) {
// TODO: fail here if the member is prefixed with the parent fqon
// but the object doesn't have the member
// TODO: This requires that aliases and fqons are properly resolved
// if (unlikely(member_obj_id)) {
// throw InternalError{"specified parent object doesn't have the member"};
// }

continue;
}

const ObjectState *par_state = this->state->get(obj)->get();
if (unlikely(par_state == nullptr)) {
throw InternalError{"object state not retrieved"};
}
const Member *member = par_state->get(member_id);
const Member *member = par_state->get(member_name);

finished = member_found(obj, *obj_member_info, member);

Expand All @@ -412,7 +449,7 @@ void Database::find_member(bool skip_first,
// recurse into the target.
// check if the patch defines the member as well -> error.
// otherwise, infer type from patch.
this->find_member(false, member_id,
this->find_member(false, member_name,
obj_info->get_linearization(),
*obj_info, member_found);
}
Expand Down Expand Up @@ -782,12 +819,26 @@ void Database::check_hierarchy(const std::vector<fqon_t> &new_objs,

for (auto &it : state_members) {
const memberid_t &member_id = it.first;

// if the member is inherited, its ID can be prefixed with the ID
// of the object it's inherited from, e.g. ParentObj.some_member
memberid_t member_name = member_id;
std::optional<fqon_t> member_obj_id = std::nullopt;
std::vector<std::string> member_parts = util::split(member_id, '.');
if (member_parts.size() > 1) {
member_name = member_parts.back();
member_parts.pop_back();

// TODO: resolve aliases here
member_obj_id = util::strjoin(".", member_parts);
}

const Member &member = it.second;
nyan_op op = member.get_operation();

// member has = operation, so it's no longer pending.
if (op == nyan_op::ASSIGN) {
pending_members.erase(member_id);
pending_members.erase(member_name);
}
}
}
Expand Down
23 changes: 22 additions & 1 deletion nyan/meta_info.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2017-2021 the nyan authors, LGPLv3+. See copying.md for legal info.
// Copyright 2017-2023 the nyan authors, LGPLv3+. See copying.md for legal info.

#include "meta_info.h"

Expand Down Expand Up @@ -50,6 +50,27 @@ bool MetaInfo::has_object(const fqon_t &name) const {
return this->object_info.count(name) == 1;
}

Namespace &MetaInfo::add_namespace(const Namespace &ns) {
auto ret = this->namespaces.insert({fqnn_t(ns.to_fqon()), ns});

return ret.first->second;
}

Namespace *MetaInfo::get_namespace(const fqnn_t &name) {
return const_cast<Namespace *>(std::as_const(*this).get_namespace(name));
}

const Namespace *MetaInfo::get_namespace(const fqnn_t &name) const {
auto it = this->namespaces.find(name);
if (it == std::end(this->namespaces)) {
return nullptr;
}
return &it->second;
}

bool MetaInfo::has_namespace(const fqnn_t &name) const {
return this->namespaces.contains(name);
}

std::string MetaInfo::str() const {
std::ostringstream builder;
Expand Down
45 changes: 44 additions & 1 deletion nyan/meta_info.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2017-2021 the nyan authors, LGPLv3+. See copying.md for legal info.
// Copyright 2017-2023 the nyan authors, LGPLv3+. See copying.md for legal info.
#pragma once

#include <memory>
Expand All @@ -7,6 +7,7 @@

#include "config.h"
#include "object_info.h"
#include "namespace.h"


namespace nyan {
Expand All @@ -18,6 +19,7 @@ namespace nyan {
class MetaInfo {
public:
using obj_info_t = std::unordered_map<fqon_t, ObjectInfo>;
using ns_info_t = std::unordered_map<fqnn_t, Namespace>;

MetaInfo() = default;
~MetaInfo() = default;
Expand Down Expand Up @@ -69,6 +71,42 @@ class MetaInfo {
*/
bool has_object(const fqon_t &name) const;

/**
* Add a namespace to the database.
*
* @param ns Namespace to add.
*
* @return The stored namespace.
*/
Namespace &add_namespace(const Namespace &ns);

/**
* Get a namespace from the database.
*
* @param name Identifier of the namespace.
*
* @return The stored namespace.
*/
Namespace *get_namespace(const fqnn_t &name);

/**
* Get a namespace from the database.
*
* @param name Identifier of the namespace.
*
* @return The stored namespace.
*/
const Namespace *get_namespace(const fqnn_t &name) const;

/**
* Check if a namespace is in the database.
*
* @param name Identifier of the namespace.
*
* @return true if the namespace is in the database, else false.
*/
bool has_namespace(const fqnn_t &name) const;

/**
* Get a string representation of all metadata information objects.
*
Expand All @@ -82,6 +120,11 @@ class MetaInfo {
* This is for displaying error messages and line information.
*/
obj_info_t object_info;

/**
* Namespaces loaded in the database.
*/
ns_info_t namespaces;
};

} // namespace nyan
29 changes: 25 additions & 4 deletions nyan/namespace.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2016-2021 the nyan authors, LGPLv3+. See copying.md for legal info.
// Copyright 2016-2023 the nyan authors, LGPLv3+. See copying.md for legal info.

#include "namespace.h"

Expand Down Expand Up @@ -94,9 +94,30 @@ Namespace Namespace::from_filename(const std::string &filename) {
throw APIError{"there's too many dots in the path"};
}

// strip off the file extension
std::string namespace_name{filename, 0, filename.size() - extension.size()};
std::replace(namespace_name.begin(), namespace_name.end(), '/', '.');
// sanitize the filename
// TODO: Do this via a file API
std::string namespace_name;
char prev_char;
char cur_char;
// condition strips off file extension
for (size_t i = 0; i < filename.size() - extension.size(); ++i) {
cur_char = filename[i];

// slashes get replaced with dots
if (cur_char == '/') {
// strip multiple slashes
if (prev_char == '/') {
continue;
}
namespace_name += '.';
}
// normal chars get copied
else {
namespace_name += cur_char;
}

prev_char = cur_char;
}

// the fqon_t constructor.
return Namespace{namespace_name};
Expand Down
7 changes: 6 additions & 1 deletion nyan/object_info.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2017-2021 the nyan authors, LGPLv3+. See copying.md for legal info.
// Copyright 2017-2023 the nyan authors, LGPLv3+. See copying.md for legal info.

#include "object_info.h"

Expand Down Expand Up @@ -104,6 +104,11 @@ const std::vector<fqon_t> &ObjectInfo::get_linearization() const {
}


void ObjectInfo::add_children(std::unordered_set<fqon_t> &&children) {
this->initial_children.insert(children.begin(), children.end());
}


void ObjectInfo::set_children(std::unordered_set<fqon_t> &&children) {
this->initial_children = std::move(children);
}
Expand Down
Loading

0 comments on commit 97ab90a

Please sign in to comment.