Skip to content
Merged
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
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ add_library(simfil ${LIBRARY_TYPE}
src/value.cpp
src/overlay.cpp
src/exception-handler.cpp
src/expression-visitor.cpp
src/model/model.cpp
src/model/nodes.cpp
src/model/string-pool.cpp)
Expand All @@ -94,6 +95,7 @@ target_sources(simfil PUBLIC
include/simfil/transient.h
include/simfil/simfil.h
include/simfil/exception-handler.h
include/simfil/expression-visitor.h

include/simfil/model/arena.h
include/simfil/model/column.h
Expand Down
115 changes: 100 additions & 15 deletions include/simfil/diagnostics.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,48 @@

#pragma once

#include "simfil/sourcelocation.h"
#include "simfil/value.h"
#include "simfil/token.h"
#include "simfil/error.h"
#include "simfil/expression.h"

#include <limits>
#include <tl/expected.hpp>
#include <optional>
#include <vector>
#include <string>
#include <memory>
#include <cstdlib>

namespace simfil
{

class AST;
class Expr;
struct Environment;
struct ModelNode;

/** Query Diagnostics. */
struct Diagnostics
class Diagnostics
{
static constexpr std::uint32_t InvalidIndex = std::numeric_limits<std::uint32_t>::max();
public:
using ExprId = std::uint32_t;
struct FieldExprData
{
SourceLocation location;
std::uint32_t hits = 0;
std::uint32_t evaluations = 0;
std::string name;
};


struct ComparisonExprData
{
SourceLocation location;
TypeFlags leftTypes;
TypeFlags rightTypes;
std::uint32_t evaluations = 0u;
std::uint32_t falseResults = 0u;
std::uint32_t trueResults = 0u;
};

struct Message
{
Expand All @@ -42,6 +61,12 @@ struct Diagnostics
Diagnostics(Diagnostics&&) noexcept;
~Diagnostics();

/**
* Get diagnostics data for a single Expr.
*/
template <class DiagnosticsDataType>
auto get(const Expr& expr) -> DiagnosticsDataType&;

/**
* Append/merge another diagnostics object into this one.
*/
Expand All @@ -53,22 +78,82 @@ struct Diagnostics
auto write(std::ostream& stream) const -> tl::expected<void, Error>;
auto read(std::istream& stream) -> tl::expected<void, Error>;

struct Data;
private:
friend auto eval(Environment&, const AST&, const ModelNode&, Diagnostics*) -> tl::expected<std::vector<Value>, Error>;
friend auto diagnostics(Environment& env, const AST& ast, const Diagnostics& diag) -> tl::expected<std::vector<Message>, Error>;

std::unique_ptr<Data> data;

/**
* Collect diagnostics data from an AST.
* Build the exprIndex_ map for the AST.
*/
auto collect(Expr& ast) -> void;
auto prepareIndices(const Expr& ast) -> void;

/** ExprId to diagnostics data index mapping. */
std::vector<std::uint32_t> exprIndex_;

/** FieldExpr diagnostics data. */
std::vector<FieldExprData> fieldData_;

/** ComparisonExpr diagnostics data. */
std::vector<ComparisonExprData> comparisonData_;

private:
friend auto diagnostics(const Diagnostics& diag) -> tl::expected<std::vector<Message>, Error>;

/**
* Build messages from this objecst diagnostics data.
*/
auto buildMessages(Environment& env, const AST& ast) const -> std::vector<Message>;
auto buildMessages() const -> std::vector<Message>;

mutable std::mutex mtx_;
};

namespace detail
{

template <class T>
struct DiagnosticsStorage;

template <>
struct DiagnosticsStorage<Diagnostics::FieldExprData>
{
static auto get(Diagnostics& diag)
{
return &diag.fieldData_;
}
};

template <>
struct DiagnosticsStorage<Diagnostics::ComparisonExprData>
{
static auto get(Diagnostics& diag)
{
return &diag.comparisonData_;
}
};

}

/**
* Get typed diagnostics data for a single Expr.
*/
template <class DiagnosticsDataType>
auto Diagnostics::get(const Expr& expr) -> DiagnosticsDataType&
{
auto* data = detail::DiagnosticsStorage<DiagnosticsDataType>::get(*this);

const auto id = expr.id();
if (exprIndex_.size() <= id) [[unlikely]] {
exprIndex_.resize(id + 1u, Diagnostics::InvalidIndex);
exprIndex_[id] = data->size();
}

auto index = exprIndex_[id];
if (index == Diagnostics::InvalidIndex) {
exprIndex_[id] = data->size();
index = exprIndex_[id];
}

if (data->size() <= index) {
data->resize(index + 1u);
}

return (*data)[index];
}

}
5 changes: 4 additions & 1 deletion include/simfil/environment.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ namespace simfil

class Expr;
class Function;
class Diagnostics;
struct ResultFn;
struct Debug;

Expand Down Expand Up @@ -138,6 +139,7 @@ struct Environment
struct Context
{
Environment* const env;
Diagnostics* const diag;

/* Current phase under which the evaluation
* takes place. */
Expand All @@ -151,7 +153,8 @@ struct Context
/* Timeout after which the evaluation should be canceled. */
std::optional<std::chrono::time_point<std::chrono::steady_clock>> timeout;

Context(Environment* env, Phase = Phase::Evaluation);
Context() = delete;
Context(Environment* env, Diagnostics* diag, Phase = Phase::Evaluation);

auto canceled() const -> bool
{
Expand Down
77 changes: 77 additions & 0 deletions include/simfil/expression-visitor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright (c) Navigation Data Standard e.V. - See "LICENSE" file.

#pragma once

#include <cstdlib>

namespace simfil
{

class Expr;
class WildcardExpr;
class AnyChildExpr;
class MultiConstExpr;
class ConstExpr;
class SubscriptExpr;
class SubExpr;
class AnyExpr;
class EachExpr;
class CallExpression;
class UnpackExpr;
class UnaryWordOpExpr;
class BinaryWordOpExpr;
class FieldExpr;
class PathExpr;
class AndExpr;
class OrExpr;
struct OperatorEq;
struct OperatorNeq;
struct OperatorLt;
struct OperatorLtEq;
struct OperatorGt;
struct OperatorGtEq;
template <class> class UnaryExpr;
template <class> class BinaryExpr;

/**
* Visitor base for visiting expressions recursively.
*/
class ExprVisitor
{
public:
ExprVisitor();
virtual ~ExprVisitor();

virtual void visit(const Expr& expr);
virtual void visit(const WildcardExpr& expr);
virtual void visit(const AnyChildExpr& expr);
virtual void visit(const MultiConstExpr& expr);
virtual void visit(const ConstExpr& expr);
virtual void visit(const SubscriptExpr& expr);
virtual void visit(const SubExpr& expr);
virtual void visit(const AnyExpr& expr);
virtual void visit(const EachExpr& expr);
virtual void visit(const CallExpression& expr);
virtual void visit(const PathExpr& expr);
virtual void visit(const FieldExpr& expr);
virtual void visit(const UnpackExpr& expr);
virtual void visit(const UnaryWordOpExpr& expr);
virtual void visit(const BinaryWordOpExpr& expr);
virtual void visit(const AndExpr& expr);
virtual void visit(const OrExpr& expr);
virtual void visit(const BinaryExpr<OperatorEq>& expr);
virtual void visit(const BinaryExpr<OperatorNeq>& expr);
virtual void visit(const BinaryExpr<OperatorLt>& expr);
virtual void visit(const BinaryExpr<OperatorLtEq>& expr);
virtual void visit(const BinaryExpr<OperatorGt>& expr);
virtual void visit(const BinaryExpr<OperatorGtEq>& expr);

protected:
/* Returns the index of the current expression */
std::size_t index() const;

private:
std::size_t index_ = 0;
};

}
33 changes: 20 additions & 13 deletions include/simfil/expression.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#include "simfil/token.h"
#include "simfil/value.h"
#include "simfil/environment.h"
#include "simfil/diagnostics.h"
#include "simfil/result.h"

#include <memory>
Expand All @@ -19,6 +18,8 @@ class Expr
{
friend class AST;
public:
using ExprId = std::uint32_t;

/**
* Type of an expression.
*/
Expand All @@ -30,8 +31,12 @@ class Expr
VALUE,
};

Expr() = default;
explicit Expr(const Token& token)
Expr() = delete;
explicit Expr(ExprId id)
: id_(id)
{}
explicit Expr(ExprId id, const Token& token)
: id_(id)
{
assert(token.end >= token.begin);
sourceLocation_.offset = token.begin;
Expand All @@ -41,6 +46,10 @@ class Expr
virtual ~Expr() = default;

/* Category */
auto id() const -> ExprId
{
return id_;
}
virtual auto type() const -> Type = 0;
virtual auto constant() const -> bool
{
Expand All @@ -50,7 +59,7 @@ class Expr
/* Debug */
virtual auto toString() const -> std::string = 0;

auto eval(Context ctx, const Value& val, const ResultFn& res) -> tl::expected<Result, Error>
auto eval(Context ctx, const Value& val, const ResultFn& res) const -> tl::expected<Result, Error>
{
if (ctx.canceled())
return Result::Stop;
Expand All @@ -66,7 +75,7 @@ class Expr
return ieval(ctx, val, res);
}

auto eval(Context ctx, Value&& val, const ResultFn& res) -> tl::expected<Result, Error>
auto eval(Context ctx, Value&& val, const ResultFn& res) const -> tl::expected<Result, Error>
{
if (ctx.canceled())
return Result::Stop;
Expand All @@ -81,12 +90,8 @@ class Expr
return ieval(ctx, std::move(val), res);
}

/* Recursive clone */
[[nodiscard]]
virtual auto clone() const -> std::unique_ptr<Expr> = 0;

/* Accept expression visitor */
virtual auto accept(ExprVisitor& v) -> void = 0;
virtual auto accept(ExprVisitor& v) const -> void = 0;

/* Source location the expression got parsed from */
[[nodiscard]]
Expand All @@ -97,13 +102,15 @@ class Expr

private:
/* Abstract evaluation implementation */
virtual auto ieval(Context ctx, const Value& value, const ResultFn& result) -> tl::expected<Result, Error> = 0;
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) -> tl::expected<Result, Error> {
virtual auto ieval(Context ctx, Value&& value, const ResultFn& result) const -> tl::expected<Result, Error>
{
return ieval(ctx, value, result);
}

ExprId id_;
SourceLocation sourceLocation_;
};

Expand All @@ -119,7 +126,7 @@ class AST

~AST();

auto expr() const -> Expr&
auto expr() const -> const Expr&
{
return *expr_;
}
Expand Down
2 changes: 1 addition & 1 deletion include/simfil/model/nodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class ModelPool;
class Model;
struct ModelNode;
struct Environment;
struct Diagnostics;
class Diagnostics;
class AST;
class Expr;

Expand Down
Loading
Loading