Add assembler directive early evaluation option
A directive may be marked as requiring to be evaluated early. These directives will be evaluated as soon as they are parsed. Usages are ie. constant directives, wherein the constant may need to be made available during pseudo instruction expansion.
MODIFY
src/assembler/assembler.h
src/assembler/assembler.h
@@ -83,6 +83,9 @@ protected:
" has already been registerred.");
}
m_directivesMap[directive] = iter;
+ if (iter->early()) {
+ m_earlyDirectives.insert(iter->name());
+ }
}
}
@@ -100,14 +103,19 @@ protected:
return std::get<LineTokens>(joinedtokens);
}
- virtual HandleDirectiveRes assembleDirective(const TokenizedSrcLine& line, bool& ok) const {
+ virtual HandleDirectiveRes assembleDirective(const TokenizedSrcLine& line, bool& ok,
+ bool skipEarlyDirectives = true) const {
ok = false;
if (line.directive.isEmpty()) {
return std::nullopt;
}
ok = true;
try {
- return m_directivesMap.at(line.directive)->handle(this, line);
+ const auto& directive = m_directivesMap.at(line.directive);
+ if (directive->early() && skipEarlyDirectives) {
+ return std::nullopt;
+ }
+ return directive->handle(this, line);
} catch (const std::out_of_range&) {
return {Error(line.sourceLine, "Unknown directive '" + line.directive + "'")};
}
@@ -219,6 +227,7 @@ protected:
*/
DirectiveVec m_directives;
DirectiveMap m_directivesMap;
+ EarlyDirectives m_earlyDirectives;
/**
* @brief m_sectionBasePointers maintains the base position for the segments
@@ -380,6 +389,11 @@ protected:
carry.clear();
tokenizedLines.push_back(tsl);
}
+
+ if (!tsl.directive.isEmpty() && m_earlyDirectives.count(tsl.directive)) {
+ bool wasDirective; // unused
+ runOperation(directiveBytes, std::optional<QByteArray>, assembleDirective, tsl, wasDirective, false);
+ }
}
if (errors.size() != 0) {
return {errors};

MODIFY
src/assembler/directive.h
src/assembler/directive.h
@@ -17,20 +17,28 @@ class AssemblerBase;
class Directive {
public:
using DirectiveHandler = std::function<HandleDirectiveRes(const AssemblerBase*, const TokenizedSrcLine&)>;
- Directive(const QString& directive, const DirectiveHandler& handler) : m_directive(directive), m_handler(handler) {}
+ Directive(const QString& directive, const DirectiveHandler& handler, bool isEarly = false)
+ : m_directive(directive), m_handler(handler), m_early(isEarly) {}
HandleDirectiveRes handle(const AssemblerBase* assembler, const TokenizedSrcLine& line) {
return m_handler(assembler, line);
}
const QString& name() const { return m_directive; }
+ bool early() const { return m_early; }
private:
const QString m_directive;
DirectiveHandler m_handler;
+
+ /**
+ * @brief m_early
+ * An early directive will be executed as soon as it is parsed
+ */
+ bool m_early;
};
using DirectiveMap = std::map<QString, std::shared_ptr<Directive>>;
using DirectiveVec = std::vector<std::shared_ptr<Directive>>;
-
+using EarlyDirectives = std::set<QString>;
} // namespace Assembler
} // namespace Ripes

Add assembler directive early evaluation option

A directive may be marked as requiring to be evaluated early. These directives will be evaluated as soon as they are parsed. Usages are ie. constant directives, wherein the constant may need to be made available during pseudo instruction expansion.