Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,8 @@ target_link_libraries(simfil
sfl::sfl
fmt::fmt
tl::expected
Bitsery::bitsery)
Bitsery::bitsery
asyncpp)

if (SIMFIL_FPIC OR NOT SIMFIL_SHARED)
set_property(TARGET simfil PROPERTY
Expand Down
4 changes: 4 additions & 0 deletions cmake/deps.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ CPMAddPackage(
"EXPECTED_BUILD_TESTS OFF"
"EXPECTED_BUILD_PACKAGE_DEB OFF")

# asyncpp
CPMAddPackage(
URI "gh:asyncpp/asyncpp@0.0.1#c1d3831")

# nlohmann/json
if (SIMFIL_WITH_MODEL_JSON)
CPMAddPackage("gh:nlohmann/json@3.11.3")
Expand Down
5 changes: 5 additions & 0 deletions include/simfil/environment.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,11 @@ struct Context
return *timeout < std::chrono::steady_clock::now();
return false;
}

auto compiling() const -> bool
{
return phase == Compilation;
}
};

/**
Expand Down
25 changes: 17 additions & 8 deletions include/simfil/expression.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@
#include "simfil/token.h"
#include "simfil/value.h"
#include "simfil/environment.h"
#include "simfil/result.h"

#include "asyncpp/generator.h"

#include <coroutine>
#include <memory>
#include <utility>

namespace simfil
{

using EvalStream = asyncpp::generator<tl::expected<Value, Error>>;

class ExprVisitor;

class Expr
Expand Down Expand Up @@ -59,36 +64,46 @@
/* Debug */
virtual auto toString() const -> std::string = 0;

auto eval(Context ctx, Value val) const -> EvalStream
{
if (ctx.canceled())
return {};

return ieval(ctx, std::move(val));
}

/*
auto eval(Context ctx, const Value& val, const ResultFn& res) const -> tl::expected<Result, Error>
{
if (ctx.canceled())
return Result::Stop;

if (auto dbg = ctx.env->debug) [[unlikely]] {
auto dbgVal = Value{val};
dbg->evalBegin(*this, ctx, dbgVal, res);
auto r = ieval(ctx, std::move(dbgVal), res);
dbg->evalEnd(*this);
return r;
}

return ieval(ctx, val, res);
}

auto eval(Context ctx, Value&& val, const ResultFn& res) const -> tl::expected<Result, Error>
{
if (ctx.canceled())
return Result::Stop;

if (auto dbg = ctx.env->debug) [[unlikely]] {
dbg->evalBegin(*this, ctx, val, res);
auto r = ieval(ctx, std::move(val), res);
dbg->evalEnd(*this);
return r;
}

return ieval(ctx, std::move(val), res);
}
*/

Check warning on line 106 in include/simfil/expression.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove the commented out code.

See more on https://sonarcloud.io/project/issues?id=Klebert-Engineering_simfil&issues=AZ1uEWzCpnXB8hKEf_fS&open=AZ1uEWzCpnXB8hKEf_fS&pullRequest=141

/* Accept expression visitor */
virtual auto accept(ExprVisitor& v) const -> void = 0;
Expand All @@ -102,13 +117,7 @@

private:
/* Abstract evaluation implementation */
virtual auto ieval(Context ctx, const Value& value, const ResultFn& result) const -> tl::expected<Result, Error> = 0;

/* Move-optimized evaluation implementation */
virtual auto ieval(Context ctx, Value&& value, const ResultFn& result) const -> tl::expected<Result, Error>
{
return ieval(ctx, value, result);
}
virtual auto ieval(Context ctx, Value value) const -> EvalStream = 0;

ExprId id_;
SourceLocation sourceLocation_;
Expand Down
38 changes: 19 additions & 19 deletions include/simfil/function.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
virtual ~Function() = default;

virtual auto ident() const -> const FnInfo& = 0;
virtual auto eval(Context, const Value&, const std::vector<ExprPtr>&, const ResultFn&) const -> tl::expected<Result, Error> = 0;
virtual auto eval(Context, Value, const std::vector<ExprPtr>&) const -> EvalStream = 0;
};

class CountFn : public Function
Expand All @@ -44,7 +44,7 @@
CountFn();

auto ident() const -> const FnInfo& override;
auto eval(Context, const Value&, const std::vector<ExprPtr>&, const ResultFn&) const -> tl::expected<Result, Error> override;
auto eval(Context, Value, const std::vector<ExprPtr>&) const -> EvalStream override;
};

class TraceFn : public Function
Expand All @@ -55,7 +55,7 @@
TraceFn();

auto ident() const -> const FnInfo& override;
auto eval(Context, const Value&, const std::vector<ExprPtr>&, const ResultFn&) const -> tl::expected<Result, Error> override;
auto eval(Context, Value, const std::vector<ExprPtr>&) const -> EvalStream override;
};

class RangeFn : public Function
Expand All @@ -66,7 +66,7 @@
RangeFn();

auto ident() const -> const FnInfo& override;
auto eval(Context, const Value&, const std::vector<ExprPtr>&, const ResultFn&) const -> tl::expected<Result, Error> override;
auto eval(Context, Value, const std::vector<ExprPtr>&) const -> EvalStream override;
};

class ReFn : public Function
Expand All @@ -77,7 +77,7 @@
ReFn();

auto ident() const -> const FnInfo& override;
auto eval(Context, const Value&, const std::vector<ExprPtr>&, const ResultFn&) const -> tl::expected<Result, Error> override;
auto eval(Context, Value, const std::vector<ExprPtr>&) const -> EvalStream override;
};

class ArrFn : public Function
Expand All @@ -88,7 +88,7 @@
ArrFn();

auto ident() const -> const FnInfo& override;
auto eval(Context, const Value&, const std::vector<ExprPtr>&, const ResultFn&) const -> tl::expected<Result, Error> override;
auto eval(Context, Value, const std::vector<ExprPtr>&) const -> EvalStream override;
};

class SplitFn : public Function
Expand All @@ -99,7 +99,7 @@
SplitFn();

auto ident() const -> const FnInfo& override;
auto eval(Context, const Value&, const std::vector<ExprPtr>&, const ResultFn&) const -> tl::expected<Result, Error> override;
auto eval(Context, Value, const std::vector<ExprPtr>&) const -> EvalStream override;
};

class SelectFn : public Function
Expand All @@ -110,7 +110,7 @@
SelectFn();

auto ident() const -> const FnInfo& override;
auto eval(Context, const Value&, const std::vector<ExprPtr>&, const ResultFn&) const -> tl::expected<Result, Error> override;
auto eval(Context, Value, const std::vector<ExprPtr>&) const -> EvalStream override;
};

class SumFn : public Function
Expand All @@ -121,7 +121,7 @@
SumFn();

auto ident() const -> const FnInfo& override;
auto eval(Context, const Value&, const std::vector<ExprPtr>&, const ResultFn&) const -> tl::expected<Result, Error> override;
auto eval(Context, Value, const std::vector<ExprPtr>&) const -> EvalStream override;
};

class KeysFn : public Function
Expand All @@ -132,26 +132,26 @@
KeysFn();

auto ident() const -> const FnInfo& override;
auto eval(Context, const Value&, const std::vector<ExprPtr>&, const ResultFn&) const -> tl::expected<Result, Error> override;
auto eval(Context, Value, const std::vector<ExprPtr>&) const -> EvalStream override;
};

/** Utility functions for working with arguments*/
namespace util
{

inline auto evalArg1Any(Context ctx, const Value& val, const ExprPtr& expr) -> std::tuple<bool, Value>

Check warning on line 142 in include/simfil/function.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Pass large object "ctx" by reference to const.

See more on https://sonarcloud.io/project/issues?id=Klebert-Engineering_simfil&issues=AZ1uEWwkpnXB8hKEf_fP&open=AZ1uEWwkpnXB8hKEf_fP&pullRequest=141
{
if (!expr)
return {false, Value::undef()};
auto n = 0;
auto out = Value::undef();
(void)expr->eval(ctx, val, LambdaResultFn([&n, &out](auto, Value v) {
++n;
out = std::move(v);
return Result::Continue;
}));

return {n == 1, std::move(out)};

auto n = 0u;
std::optional<Value> out ;
for (auto&& value : expr->eval(ctx, val)) {
n++;
out.emplace(*value);
}

return {n == 1, std::move(out).value_or(Value::undef())};
}

template <class CType>
Expand Down
70 changes: 70 additions & 0 deletions include/simfil/model/arena.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#pragma once

#include <algorithm>
#include <asyncpp/generator.h>
#include <cstdint>
#include <functional>
#include <vector>
Expand Down Expand Up @@ -59,7 +60,7 @@
size_t PageSize = 4096,
size_t ChunkPageSize = 4096,
typename SizeType_ = uint32_t>
class ArrayArena

Check warning on line 63 in include/simfil/model/arena.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Class has 36 methods, which is greater than the 35 authorized. Split it into smaller classes.

See more on https://sonarcloud.io/project/issues?id=Klebert-Engineering_simfil&issues=AZ1uEWw8pnXB8hKEf_fR&open=AZ1uEWw8pnXB8hKEf_fR&pullRequest=141
{
friend struct bitsery::ext::ArrayArenaExt;

Expand Down Expand Up @@ -628,6 +629,15 @@
iterate_chunked(a, std::forward<Func>(lambda));
}

auto iterate(ArrayIndex idx) -> asyncpp::generator<ElementType>
{
if (is_singleton_handle(idx))
return iterate_singleton(idx);
if (heads_.empty() && compactHeads_)
return iterate_compact(idx);
return iterate_chunked(idx);
}

private:
// Represents a chunk of an array in the arena.
struct Chunk
Expand Down Expand Up @@ -682,6 +692,16 @@
}
}

template <typename Value>
static ElementType materialize_iter_value(Value&& value)
{
if constexpr (requires { std::forward<Value>(value).to_value(); }) {
return std::forward<Value>(value).to_value();
} else {
return std::forward<Value>(value);
}
}

template <typename Func>
void iterate_singleton(ArrayIndex a, Func&& lambda)
{
Expand All @@ -698,6 +718,22 @@
invoke_iter_callback(lambda, value, 0);
}

auto iterate_singleton(ArrayIndex idx) -> asyncpp::generator<ElementType> // TODO: should be an expected with an error!

Check warning on line 721 in include/simfil/model/arena.h

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Complete the task associated to this "TODO" comment.

See more on https://sonarcloud.io/project/issues?id=Klebert-Engineering_simfil&issues=AZ1uEWw8pnXB8hKEf_fQ&open=AZ1uEWw8pnXB8hKEf_fQ&pullRequest=141
{
auto singletonIndex = singleton_payload(idx);
if (singletonIndex >= singletonValues_.size() ||
singletonIndex >= singletonOccupied_.size()) {
raise<std::out_of_range>("ArrayArena singleton handle index out of range.");
co_return;
}
else if (singletonOccupied_.at(singletonIndex) == 0) {
co_return;
}

auto value = materialize_iter_value(singletonValues_.at(singletonIndex));
co_yield value;
}

template <typename Func>
void iterate_compact(ArrayIndex a, Func&& lambda)
{
Expand All @@ -715,6 +751,20 @@
}
}

auto iterate_compact(ArrayIndex idx) -> asyncpp::generator<ElementType>
{
if (idx >= compactHeads_->size()) {
raise<std::out_of_range>("ArrayArena head index out of range.");
co_return;
}

auto const& compact = (*compactHeads_)[idx];
for (size_t i = 0; i < static_cast<size_t>(compact.size); ++i) {
auto value = materialize_iter_value(data_[static_cast<size_t>(compact.offset) + i]);
co_yield value;
}
}

template <typename Func>
void iterate_chunked(ArrayIndex a, Func&& lambda)
{
Expand All @@ -740,6 +790,26 @@
}
}

auto iterate_chunked(ArrayIndex idx) -> asyncpp::generator<ElementType>
{
if (idx >= heads_.size()) {
raise<std::out_of_range>("ArrayArena head index out of range.");
co_return;
}

Chunk const* current = &heads_[idx];
while (current != nullptr) {
for (size_t i = 0; i < current->size && i < current->capacity; ++i) {
auto value = materialize_iter_value(data_[current->offset + i]);
co_yield value;
}

current = (current->next != InvalidArrayIndex)
? &continuations_[current->next]
: nullptr;
}
}

void ensure_regular_head_pool()
{
if (!heads_.empty()) {
Expand Down
20 changes: 19 additions & 1 deletion include/simfil/model/nodes.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <asyncpp/generator.h>
#include <tl/expected.hpp>
#include <memory>
#include <type_traits>
Expand Down Expand Up @@ -303,6 +304,8 @@ struct ModelNode
};
virtual bool iterate(IterCallback const& cb) const; // NOLINT (allow discard)

virtual auto iterate() const -> asyncpp::generator<ModelNode::Ptr>;

/// Iterator Support
/// * `fieldNames()`: Returns range object which supports `for(StringId const& f: node.fieldNames())`
/// * `fields()`: Returns range object which supports `for(auto const& [fieldId, value] : node.fields())`
Expand Down Expand Up @@ -430,6 +433,7 @@ struct ModelNodeBase : public ModelNode
[[nodiscard]] StringId keyAt(int64_t) const override;
[[nodiscard]] uint32_t size() const override;
bool iterate(IterCallback const&) const override {return true;} // NOLINT (allow discard)
auto iterate() const -> asyncpp::generator<ModelNode::Ptr> override {co_return;}

public:
explicit ModelNodeBase(detail::mp_key key) : ModelNode(key) {}
Expand Down Expand Up @@ -548,6 +552,7 @@ struct BaseArray : public MandatoryDerivedModelNodeBase<ModelType>
[[nodiscard]] ModelNode::Ptr at(int64_t) const override;
[[nodiscard]] uint32_t size() const override;
bool iterate(ModelNode::IterCallback const& cb) const override; // NOLINT (allow discard)
auto iterate() const -> asyncpp::generator<ModelNode::Ptr> override;

protected:
BaseArray& appendInternal(ModelNode::Ptr const& value={});
Expand Down Expand Up @@ -612,7 +617,8 @@ struct BaseObject : public MandatoryDerivedModelNodeBase<ModelType>
[[nodiscard]] uint32_t size() const override;
[[nodiscard]] ModelNode::Ptr get(const StringId &) const override;
[[nodiscard]] StringId keyAt(int64_t) const override;
bool iterate(ModelNode::IterCallback const& cb) const override; // NOLINT (allow discard)
bool iterate(ModelNode::IterCallback const& cb) const override; // NOLINT (allow discard)
auto iterate() const -> asyncpp::generator<ModelNode::Ptr> override;

protected:
/**
Expand Down Expand Up @@ -710,6 +716,18 @@ class ProceduralObject : public Object
return true;
}

auto iterate() const -> asyncpp::generator<ModelNode::Ptr> override
{
for (auto const& [k, v] : fields_) {
auto vv = v(static_cast<LambdaThisType const&>(*this));
co_yield vv;
}

if (members_ != InvalidArrayIndex)
for (auto member : Object::iterate())
co_yield member;
}

inline ModelPoolDerivedModel& model() const {return *modelPtr<ModelPoolDerivedModel>();} // NOLINT

public:
Expand Down
Loading
Loading