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 {
bool nostdlib = false;
void printHelp() {
std::cout << "Solstice compiler\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 << " Specifies the type of output.\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) {
@@ -35,13 +44,12 @@ namespace ArgParser {
printHelp();
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++;
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]));
continue;
} else {
@@ -52,10 +60,6 @@ namespace ArgParser {
else if (strcmp(argv[i], "-t") == 0 || strcmp(argv[i], "--type") == 0) {
i++;
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]));
continue;
} else {

View File

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

View File

@@ -4,6 +4,7 @@
#include <fstream>
#include <iostream>
#include <sstream>
#include <filesystem>
#include "lexer.h"
#include "parser.h"
@@ -31,32 +32,51 @@ int main(int argc, char** argv) {
GroundProgram program = Solstice::Parser::assembleProgram(parsed);
Solstice::Error::summariseErrors();
if (args.output.has_value()) {
std::FILE* originalStdout = stdout;
std::FILE* tmp = std::tmpfile();
if (!tmp) {
std::cout << "Failed to create tmp file\n";
exit(1);
if (!args.outputtype.has_value() || args.outputtype.value().value == "ground") {
std::FILE* originalStdout = stdout;
std::FILE* tmp = std::tmpfile();
if (!tmp) {
std::cout << "Failed to create tmp file\n";
exit(1);
}
stdout = tmp;
groundPrintProgram(&program);
std::fflush(tmp);
std::fseek(tmp, 0, SEEK_END);
long size = std::ftell(tmp);
std::fseek(tmp, 0, SEEK_SET);
std::string result(size, '\0');
std::fread(&result[0], 1, size, tmp);
stdout = originalStdout;
std::fclose(tmp);
std::ofstream outputFile(args.output.value().value);
if (!outputFile) {
std::cout << "Failed to write to " << args.output.value().value << "\n";
}
outputFile << result;
outputFile.close();
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);
}
stdout = tmp;
groundPrintProgram(&program);
std::fflush(tmp);
std::fseek(tmp, 0, SEEK_END);
long size = std::ftell(tmp);
std::fseek(tmp, 0, SEEK_SET);
std::string result(size, '\0');
std::fread(&result[0], 1, size, tmp);
stdout = originalStdout;
std::fclose(tmp);
std::ofstream outputFile(args.output.value().value);
if (!outputFile) {
std::cout << "Failed to write to " << args.output.value().value << "\n";
}
outputFile << result;
outputFile.close();
exit(0);
} else {
GroundValue gv = groundRunProgram(&program);
if (gv.type == INT) {

View File

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