Compilation with ground->asm

This commit is contained in:
2026-01-21 16:26:17 +11:00
parent 9397f410da
commit c82f81f668
4 changed files with 65 additions and 36 deletions

View File

@@ -6,6 +6,8 @@
namespace ArgParser { namespace ArgParser {
bool nostdlib = false;
void printHelp() { void printHelp() {
std::cout << "Solstice compiler\n"; std::cout << "Solstice compiler\n";
std::cout << "This program takes a Solstice source file (.sols) and compiles it to Ground\n"; std::cout << "This program takes a Solstice source file (.sols) and compiles it to Ground\n";
@@ -20,7 +22,14 @@ namespace ArgParser {
std::cout << " -t type or --type type\n"; std::cout << " -t type or --type type\n";
std::cout << " Specifies the type of output.\n"; std::cout << " Specifies the type of output.\n";
std::cout << " Currently supported options:\n"; std::cout << " Currently supported options:\n";
std::cout << " text\n"; std::cout << " ground, native (BETA) (Requires --nostdlib)\n";
std::cout << " Choosing the 'ground' option outputs the compiled program as a .grnd textual representation file.\n";
std::cout << " Choosing the 'native' option uses Ground's ground->asm compiler to create a native executable.\n";
std::cout << " This feature is currently in beta, as Ground's ground->asm compiler is not fully complete.\n";
std::cout << " This feature requires the '--nostdlib' flag as Ground's ground->asm compiler does not support functions.\n";
std::cout << " See https://sols.dev/docs#nativecompiler for more details\n";
std::cout << " --nostdlib\n";
std::cout << " Excludes the Solstice stdlib from compilation.\n";
} }
Args parseArgs(int argc, char** argv) { Args parseArgs(int argc, char** argv) {
@@ -35,13 +44,12 @@ namespace ArgParser {
printHelp(); printHelp();
exit(1); exit(1);
} }
if (strcmp(argv[i], "-o") == 0 || strcmp(argv[i], "--output") == 0) { else if (strcmp(argv[i], "--nostdlib") == 0) {
nostdlib = true;
}
else if (strcmp(argv[i], "-o") == 0 || strcmp(argv[i], "--output") == 0) {
i++; i++;
if (i < argc) { if (i < argc) {
if (args.output.has_value()) {
std::cout << "(error) Multiple output values provided\n";
exit(1);
}
args.output = Argument(ArgType::OUTPUT, std::string(argv[i])); args.output = Argument(ArgType::OUTPUT, std::string(argv[i]));
continue; continue;
} else { } else {
@@ -52,10 +60,6 @@ namespace ArgParser {
else if (strcmp(argv[i], "-t") == 0 || strcmp(argv[i], "--type") == 0) { else if (strcmp(argv[i], "-t") == 0 || strcmp(argv[i], "--type") == 0) {
i++; i++;
if (i < argc) { if (i < argc) {
if (args.output.has_value()) {
std::cout << "(error) Multiple type values provided\n";
exit(1);
}
args.outputtype = Argument(ArgType::OUTPUTTYPE, std::string(argv[i])); args.outputtype = Argument(ArgType::OUTPUTTYPE, std::string(argv[i]));
continue; continue;
} else { } else {

View File

@@ -5,6 +5,8 @@
namespace ArgParser { namespace ArgParser {
extern bool nostdlib;
enum class ArgType { enum class ArgType {
FILE, OUTPUT, OUTPUTTYPE FILE, OUTPUT, OUTPUTTYPE
}; };

View File

@@ -4,6 +4,7 @@
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <filesystem>
#include "lexer.h" #include "lexer.h"
#include "parser.h" #include "parser.h"
@@ -31,6 +32,7 @@ int main(int argc, char** argv) {
GroundProgram program = Solstice::Parser::assembleProgram(parsed); GroundProgram program = Solstice::Parser::assembleProgram(parsed);
Solstice::Error::summariseErrors(); Solstice::Error::summariseErrors();
if (args.output.has_value()) { if (args.output.has_value()) {
if (!args.outputtype.has_value() || args.outputtype.value().value == "ground") {
std::FILE* originalStdout = stdout; std::FILE* originalStdout = stdout;
std::FILE* tmp = std::tmpfile(); std::FILE* tmp = std::tmpfile();
if (!tmp) { if (!tmp) {
@@ -57,6 +59,24 @@ int main(int argc, char** argv) {
outputFile << result; outputFile << result;
outputFile.close(); outputFile.close();
exit(0); exit(0);
} else if (args.outputtype.value().value == "native") {
std::string assembly(groundCompileProgram(&program));
std::string folder = "." + args.output.value().value + "_solsbuild";
std::filesystem::create_directory(folder);
std::ofstream asmfile(folder + "/program.s");
if (asmfile) {
asmfile << assembly;
asmfile.close();
} else {
std::cout << "Failed to create temporary file for assembly\n";
exit(1);
}
std::string command = "nasm -f elf64 -o " + folder + "/program.o " + folder + "/program.s";
std::system(command.c_str());
command = "ld -o " + args.output.value().value + " " + folder + "/program.o";
std::system(command.c_str());
exit(0);
}
} else { } else {
GroundValue gv = groundRunProgram(&program); GroundValue gv = groundRunProgram(&program);
if (gv.type == INT) { if (gv.type == INT) {

View File

@@ -2,6 +2,7 @@
#include "error.h" #include "error.h"
#include "lexer.h" #include "lexer.h"
#include "solstice_stdlib.h" #include "solstice_stdlib.h"
#include "argparser.h"
#include <groundvm.h> #include <groundvm.h>
#include <cstring> #include <cstring>
#include <string> #include <string>
@@ -209,10 +210,12 @@ namespace Solstice {
std::vector<SolGroundCodeBlock> code; std::vector<SolGroundCodeBlock> code;
if (nodeType == SolNodeType::Root) { if (nodeType == SolNodeType::Root) {
// Compile and insert standard library // Compile and insert standard library
if (!ArgParser::nostdlib) {
auto parsedStdlib = Parser(Lexer(getStdLib()).lex()).parse(); auto parsedStdlib = Parser(Lexer(getStdLib()).lex()).parse();
parsedStdlib.nodeType = SolNodeType::None; parsedStdlib.nodeType = SolNodeType::None;
code = parsedStdlib.generateCode(); code = parsedStdlib.generateCode();
} }
}
if (nodeType != SolNodeType::If && nodeType != SolNodeType::While) for (auto& child : children) { if (nodeType != SolNodeType::If && nodeType != SolNodeType::While) for (auto& child : children) {
auto childCode = child.generateCode(); auto childCode = child.generateCode();
code.insert(code.end(), childCode.begin(), childCode.end()); code.insert(code.end(), childCode.begin(), childCode.end());