2026-01-01 22:18:25 -05:00
|
|
|
#ifndef INTERPRETER_H
|
|
|
|
|
#define INTERPRETER_H
|
|
|
|
|
|
|
|
|
|
#include "ast.h"
|
|
|
|
|
|
|
|
|
|
#include <QDataStream>
|
|
|
|
|
#include <QVariantMap>
|
|
|
|
|
#include <QIODevice>
|
2026-01-07 16:35:35 -05:00
|
|
|
#include <functional>
|
2026-01-01 22:18:25 -05:00
|
|
|
|
|
|
|
|
struct Runtime {
|
|
|
|
|
QDataStream* in = nullptr;
|
|
|
|
|
Module* module = nullptr; // Non-const to allow modifying globals
|
|
|
|
|
|
|
|
|
|
ByteOrder order = ByteOrder::LE;
|
|
|
|
|
QVariantMap vars;
|
|
|
|
|
|
|
|
|
|
QString filePath;
|
2026-01-07 16:35:35 -05:00
|
|
|
|
|
|
|
|
// Error context tracking
|
|
|
|
|
QStringList typeStack; // Stack of types being parsed
|
|
|
|
|
QString currentType() const { return typeStack.isEmpty() ? QString() : typeStack.last(); }
|
|
|
|
|
void pushType(const QString& t) { typeStack.append(t); }
|
|
|
|
|
void popType() { if (!typeStack.isEmpty()) typeStack.removeLast(); }
|
|
|
|
|
QString typeStackString() const { return typeStack.join(" -> "); }
|
2026-01-01 22:18:25 -05:00
|
|
|
};
|
|
|
|
|
|
2026-01-07 16:35:35 -05:00
|
|
|
using ProgressCallback = std::function<void(qint64 pos, qint64 size)>;
|
|
|
|
|
|
2026-01-01 22:18:25 -05:00
|
|
|
class Interpreter {
|
|
|
|
|
public:
|
|
|
|
|
explicit Interpreter(Module mod);
|
|
|
|
|
|
|
|
|
|
// Parse a given type name from a device/stream
|
|
|
|
|
QVariantMap runType(const QString& typeName, QIODevice* dev, const QString& filePath = QString()) const;
|
|
|
|
|
|
|
|
|
|
// Run from existing QDataStream (for nested parse)
|
|
|
|
|
QVariantMap runType(const QString& typeName, QDataStream& stream, const QString &filePath = QString()) const;
|
|
|
|
|
|
|
|
|
|
// Check if the criteria for a certain filetype matches
|
|
|
|
|
bool checkCriteria(const QString& typeName, QIODevice* dev, const QString filePath) const;
|
|
|
|
|
|
|
|
|
|
QVariantMap runTypeInternal(const QString& typeName,
|
|
|
|
|
QDataStream& stream,
|
|
|
|
|
const QString& filePath,
|
|
|
|
|
std::optional<ByteOrder> inheritedOrder) const;
|
|
|
|
|
|
|
|
|
|
static void seedFileVars(Runtime &rt, const QString &filePath);
|
|
|
|
|
|
2026-01-07 16:35:35 -05:00
|
|
|
// Progress reporting
|
|
|
|
|
void setProgressCallback(ProgressCallback cb);
|
|
|
|
|
void setFileSize(qint64 size);
|
|
|
|
|
|
2026-01-01 22:18:25 -05:00
|
|
|
private:
|
|
|
|
|
QVariant evalExpr(Runtime& rt, const Expr& e) const;
|
|
|
|
|
QVariant evalCall(Runtime& rt, const Expr::Call& c) const;
|
|
|
|
|
QVariant evalPipe(Runtime& rt, const Expr::Pipe& p) const;
|
|
|
|
|
|
|
|
|
|
void execStmt(Runtime& rt, const Stmt& s) const;
|
|
|
|
|
void execBlock(Runtime& rt, const QVector<StmtPtr>& body) const;
|
|
|
|
|
|
|
|
|
|
// helpers
|
|
|
|
|
void applyByteOrder(Runtime& rt) const;
|
|
|
|
|
QVariant readScalar(Runtime& rt, ScalarType t) const;
|
|
|
|
|
QByteArray readBytes(Runtime& rt, qint64 n) const;
|
|
|
|
|
QByteArray readEOF(Runtime& rt) const;
|
|
|
|
|
|
|
|
|
|
qint64 toInt(const QVariant& v) const;
|
|
|
|
|
bool toBool(const QVariant& v) const;
|
2026-01-07 16:35:35 -05:00
|
|
|
void reportProgress(Runtime& rt) const;
|
2026-01-01 22:18:25 -05:00
|
|
|
|
|
|
|
|
private:
|
2026-01-07 16:35:35 -05:00
|
|
|
mutable Module m_mod;
|
|
|
|
|
mutable ProgressCallback m_progressCallback;
|
|
|
|
|
mutable qint64 m_fileSize = 0; // Mutable to allow modifying globals from const methods
|
2026-01-01 22:18:25 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#endif // INTERPRETER_H
|