summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAmlal El Mahrouss <amlal@nekernel.org>2026-01-23 10:21:30 +0100
committerAmlal El Mahrouss <amlal@nekernel.org>2026-01-23 10:22:13 +0100
commitbaa456251dc978b3bdb33c77a5c02c2e53fb2d3e (patch)
treeb717b671841a2757ea3b49b7d3044a3ab659ad58
parenta092f344f33e18a5323f9631b650c73f02635c74 (diff)
chore: necdrv: AST improvements and frontend milestones and new
keywords. Signed-off-by: Amlal El Mahrouss <amlal@nekernel.org>
-rw-r--r--doc/specs/SPEC_NECTAR_LANG.md2
-rw-r--r--example/example_02_nectar/example.nc10
-rw-r--r--include/CompilerKit/AST.h15
-rw-r--r--src/CompilerKit/src/Assemblers/Assembler+AMD64.cc5
-rw-r--r--src/CompilerKit/src/Compilers/NectarCompiler+AMD64.cc100
5 files changed, 108 insertions, 24 deletions
diff --git a/doc/specs/SPEC_NECTAR_LANG.md b/doc/specs/SPEC_NECTAR_LANG.md
index f900a61..9663893 100644
--- a/doc/specs/SPEC_NECTAR_LANG.md
+++ b/doc/specs/SPEC_NECTAR_LANG.md
@@ -26,6 +26,8 @@
- `let` Pointer/Reference variable declaration.
- `const` and `let` declaration.
- Functions support.
+- `import` import bss data.
+- `extern` import text data.
- Nested Stubs support.
===================================
diff --git a/example/example_02_nectar/example.nc b/example/example_02_nectar/example.nc
index d83cff9..7a08953 100644
--- a/example/example_02_nectar/example.nc
+++ b/example/example_02_nectar/example.nc
@@ -1,8 +1,10 @@
+extern sleep;
+
const main() {
_sleep(0x1);
- _putchar(0x0, 'H');
- _putchar(0x0, 'i');
- _putchar(0x0, '!');
+ let _ := _putchar(0x0, '!');
+
+ let foo := 42;
- return 0;
+ return foo;
}
diff --git a/include/CompilerKit/AST.h b/include/CompilerKit/AST.h
index 7529d73..fef5279 100644
--- a/include/CompilerKit/AST.h
+++ b/include/CompilerKit/AST.h
@@ -51,6 +51,8 @@ enum struct KeywordKind {
kKeywordKindSpecifier,
kKeywordKindInvalid,
kKeywordKindReturn,
+ kKeywordKindExtern,
+ kKeywordKindImport,
kKeywordKindCommentInline,
kKeywordKindCommentMultiLineStart,
kKeywordKindCommentMultiLineEnd,
@@ -88,17 +90,20 @@ struct SyntaxLeafList final {
using Reference = SyntaxLeaf&;
using ConstReference = const SyntaxLeaf&;
+ enum {
+ kPlaceNone = 0,
+ kPlaceBefore = 100,
+ kPlaceAfter,
+ };
+
/// \brief User data type.
Int32 fUserType{};
-
/// \brief User data buffer.
SyntaxKeyword fUserData{{}, KeywordKind::kKeywordKindInvalid};
-
/// \brief User data value
STLString fUserValue{};
-
- /// \brief Next user data on list.
- Ptr fNext{nullptr};
+ /// \brief Should this value be placed before or after?
+ Int32 fPlaceType{};
};
using ArrayType = std::vector<SyntaxLeaf>;
diff --git a/src/CompilerKit/src/Assemblers/Assembler+AMD64.cc b/src/CompilerKit/src/Assemblers/Assembler+AMD64.cc
index efe9b8c..e8283d3 100644
--- a/src/CompilerKit/src/Assemblers/Assembler+AMD64.cc
+++ b/src/CompilerKit/src/Assemblers/Assembler+AMD64.cc
@@ -608,7 +608,8 @@ bool CompilerKit::EncoderAMD64::WriteNumber(const std::size_t& pos, std::string&
}
}
- auto res = strtol(jump_label.substr(pos).c_str(), nullptr, 10);
+ /// @note We assume base 10 here. As other cases have failed.
+ auto res = strtol(jump_label.substr(pos + 1).c_str(), nullptr, 10);
res += kOrigin;
if (errno != 0) {
@@ -622,7 +623,7 @@ bool CompilerKit::EncoderAMD64::WriteNumber(const std::size_t& pos, std::string&
}
if (kVerbose) {
- kStdOut << "AssemblerAMD64: Found a base 10 number here: " << jump_label.substr(pos) << "\n";
+ kStdOut << "AssemblerAMD64: Found a base 10 number here: " << jump_label.substr(pos + 1) << "\n";
}
return true;
diff --git a/src/CompilerKit/src/Compilers/NectarCompiler+AMD64.cc b/src/CompilerKit/src/Compilers/NectarCompiler+AMD64.cc
index 0827ea1..25349ad 100644
--- a/src/CompilerKit/src/Compilers/NectarCompiler+AMD64.cc
+++ b/src/CompilerKit/src/Compilers/NectarCompiler+AMD64.cc
@@ -285,6 +285,7 @@ static auto nectar_get_impl_member(const CompilerKit::STLString& class_name,
CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendNectarAMD64::Compile(
CompilerKit::STLString& text, const CompilerKit::STLString& file) {
CompilerKit::SyntaxLeafList::SyntaxLeaf syntax_tree;
+ CompilerKit::STLString syntax_rem_buffer;
if (text.empty()) return syntax_tree;
@@ -575,9 +576,6 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendNectarAMD64::Compile(
if (valueOfVar.find("{") != CompilerKit::STLString::npos) {
break;
- } else if (CompilerKit::KeywordKind::kKeywordKindFunctionAccess == keyword.first.fKeywordKind) {
- syntax_tree.fUserValue += (kNasmOutput ? "section .text\nextern " : "extern_segment .code64") +
- text.substr(0, text.find(keyword.first.fKeywordName)) + "\n";
}
if (CompilerKit::KeywordKind::kKeywordKindFunctionAccess == keyword.first.fKeywordKind)
@@ -597,6 +595,20 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendNectarAMD64::Compile(
auto method = text.substr(0, text.find(keyword.first.fKeywordName));
+ if (method.find("let ") != CompilerKit::STLString::npos) {
+ method.erase(0, method.find("let ") + strlen("let "));
+ } else if (method.find("const ") != CompilerKit::STLString::npos) {
+ method.erase(0, method.find("const ") + strlen("const "));
+ }
+
+ if (method.find(":=") != CompilerKit::STLString::npos) {
+ method.erase(0, method.find(":=") + strlen(":="));
+ }
+
+ while (method.find(" ") != CompilerKit::STLString::npos) {
+ method.erase(method.find(" "), 1);
+ }
+
if (!nectar_get_variable_ref(nameVar).empty())
syntax_tree.fUserValue += "lea r8, " + nectar_get_variable_ref(nameVar) + "\n";
@@ -609,6 +621,8 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendNectarAMD64::Compile(
auto index = 9;
auto cnter = 0;
+ CompilerKit::STLString buf;
+
for (auto& ch : args) {
if (ch == ',' || ch == ')') {
if (index <= 15) {
@@ -626,8 +640,7 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendNectarAMD64::Compile(
}
}
- if (!arg.empty())
- syntax_tree.fUserValue += "mov r" + std::to_string(index) + ", " + val + "\n";
+ if (!arg.empty()) buf += "mov r" + std::to_string(index) + ", " + val + "\n";
arg.clear();
++index;
@@ -642,6 +655,7 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendNectarAMD64::Compile(
if (!nectar_get_variable_ref(nameVar).empty()) {
if (!kNasmOutput) {
+ syntax_tree.fUserValue += buf;
syntax_tree.fUserValue += "call ";
syntax_tree.fUserValue +=
(keyword.first.fKeywordName.ends_with('>') ? " __ptr __offset " : " __offset ") +
@@ -661,7 +675,11 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendNectarAMD64::Compile(
}
}
} else {
- syntax_tree.fUserValue += "call " + method + "\n";
+ auto res = buf;
+ res += "call " + method + "\n";
+ res += syntax_rem_buffer;
+
+ syntax_tree.fUserValue += res;
}
break;
@@ -821,16 +839,16 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendNectarAMD64::Compile(
kExternalSymbols.insert(mangled + valueOfVar);
if (!kNasmOutput) {
- if (valueOfVar.ends_with(")"))
+ if (valueOfVar.ends_with(")") &&
+ valueOfVar.find("->") != CompilerKit::STLString::npos ||
+ valueOfVar.find(".") != CompilerKit::STLString::npos)
syntax_tree.fUserValue += instr + nectar_get_variable_ref(varName) +
", __thiscall " + mangled + valueOfVar + "\n";
else
syntax_tree.fUserValue +=
instr + nectar_get_variable_ref(varName) + ", " + mangled + valueOfVar + "\n";
} else {
- // NASM: Generate call and move result
- syntax_tree.fUserValue += "call " + mangled + valueOfVar + "\n";
- syntax_tree.fUserValue += instr + nectar_get_variable_ref(varName) + ", rax\n";
+ syntax_rem_buffer = instr + nectar_get_variable_ref(varName) + ", rax\n";
}
}
@@ -844,6 +862,40 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendNectarAMD64::Compile(
break;
}
+ case CompilerKit::KeywordKind::kKeywordKindImport: {
+ auto tmp = text;
+
+ if (tmp.find(";") != CompilerKit::STLString::npos)
+ tmp.erase(tmp.find(";"));
+
+ while (tmp.find(" ") != CompilerKit::STLString::npos) {
+ tmp.erase(tmp.find(" "), 1);
+ }
+
+ if (!kNasmOutput)
+ syntax_tree.fUserValue += "extern_segment .zero64 _" + tmp.substr(tmp.find(keyword.first.fKeywordName) + keyword.first.fKeywordName.size()) + "\n";
+ else
+ syntax_tree.fUserValue += "section .data\nextern _" + tmp.substr(tmp.find(keyword.first.fKeywordName) + keyword.first.fKeywordName.size()) + "\n";
+
+ break;
+ }
+ case CompilerKit::KeywordKind::kKeywordKindExtern: {
+ auto tmp = text;
+
+ if (tmp.find(";") != CompilerKit::STLString::npos)
+ tmp.erase(tmp.find(";"));
+
+ while (tmp.find(" ") != CompilerKit::STLString::npos) {
+ tmp.erase(tmp.find(" "), 1);
+ }
+
+ if (!kNasmOutput)
+ syntax_tree.fUserValue += "extern_segment .code64 _" + tmp.substr(tmp.find(keyword.first.fKeywordName) + keyword.first.fKeywordName.size()) + "\n";
+ else
+ syntax_tree.fUserValue += "section .text\nextern _" + tmp.substr(tmp.find(keyword.first.fKeywordName) + keyword.first.fKeywordName.size()) + "\n";
+
+ break;
+ }
case CompilerKit::KeywordKind::kKeywordKindReturn: {
try {
auto pos = text.find("return");
@@ -1107,7 +1159,8 @@ static Int32 nectar_allocate_stack_variable(const CompilerKit::STLString& var_na
"CompilerKit");
if (var->fStackOffset > 0)
- CompilerKit::Detail::print_error("Variable " + var_name + " is already defined.", "CompilerKit");
+ CompilerKit::Detail::print_error("Variable " + var_name + " is already defined.",
+ "CompilerKit");
}
VariableInfo varInfo;
@@ -1407,10 +1460,29 @@ class AssemblyNectarInterfaceAMD64 final CK_ASSEMBLY_INTERFACE {
// First pass: compile all lines and collect symbols
CompilerKit::STLString compiledCode;
+ std::size_t lastRes{};
+ std::string prevRes;
+ std::string nextRes;
+
while (std::getline(src_fp, line_source)) {
- auto res = kFrontend->Compile(line_source, src).fUserValue;
+ auto res = kFrontend->Compile(line_source, src);
if (kAcceptableErrors > 0) return EXIT_FAILURE;
- compiledCode += res;
+
+ if (res.fPlaceType == CompilerKit::SyntaxLeafList::SyntaxLeaf::kPlaceBefore) {
+ compiledCode.insert(compiledCode.find(prevRes), res.fUserValue, 0, res.fUserValue.size());
+ } else if (res.fPlaceType == CompilerKit::SyntaxLeafList::SyntaxLeaf::kPlaceAfter) {
+ nextRes = res.fUserValue;
+ continue;
+ } else {
+ compiledCode += res.fUserValue;
+ if (!nextRes.empty()) {
+ compiledCode += nextRes;
+ nextRes.clear();
+ }
+ }
+
+ lastRes = res.fUserValue.size();
+ prevRes = res.fUserValue;
}
// Output header
@@ -1465,6 +1537,8 @@ NECTAR_MODULE(CompilerNectarAMD64) {
kKeywords.emplace_back("(", CompilerKit::KeywordKind::kKeywordKindFunctionAccess);
kKeywords.emplace_back(";", CompilerKit::KeywordKind::kKeywordKindEndLine);
kKeywords.emplace_back("return", CompilerKit::KeywordKind::kKeywordKindReturn);
+ kKeywords.emplace_back("extern", CompilerKit::KeywordKind::kKeywordKindExtern);
+ kKeywords.emplace_back("import", CompilerKit::KeywordKind::kKeywordKindImport);
kKeywords.emplace_back("if", CompilerKit::KeywordKind::kKeywordKindIf);