Browse Source

It compiles things!

master
Ludovic 'Archivist' Lagouardette 1 year ago
parent
commit
f0b6af9dad
4 changed files with 132 additions and 74 deletions
  1. +1
    -1
      CMakeLists.txt
  2. +21
    -13
      include/molasses/parser_primitives.h
  3. +14
    -1
      src/main.cpp
  4. +96
    -59
      src/molasses/parser_primitives.cpp

+ 1
- 1
CMakeLists.txt View File

@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.24)
project(sugar)
find_package(cppfront REQUIRED)
# find_package(cppfront REQUIRED)
set(CMAKE_CXX_STANDARD 20)

+ 21
- 13
include/molasses/parser_primitives.h View File

@ -42,9 +42,8 @@ namespace molasses {
[[nodiscard]] virtual std::string name() const = 0;
[[nodiscard]] virtual std::vector<std::string> argument_types() const = 0;
[[nodiscard]] virtual std::vector<std::string> return_types() const = 0;
[[nodiscard]] virtual std::vector<std::string> generate(const parser_context&) const = 0;
// Add generate() -> instruction[]
[[nodiscard]] virtual std::vector<std::string> generate(const parser_context&, const lexed_output& lexer_data) const = 0;
[[nodiscard]] virtual std::vector<std::string> emit(const parser_context&) const = 0;
};
struct primitive_operation : public operation {
@ -53,10 +52,11 @@ namespace molasses {
std::vector<std::string> _rets;
std::vector<std::string> _instructions;
primitive_operation(std::string name, std::vector<std::string> args, std::vector<std::string> rets)
primitive_operation(std::string name, std::vector<std::string> args, std::vector<std::string> rets, std::vector<std::string> body)
: _name(std::forward<std::string>(name))
, _args(std::forward<std::vector<std::string>>(args))
, _rets(std::forward<std::vector<std::string>>(rets))
, _rets(std::forward<std::vector<std::string>>(rets))
, _instructions(std::forward<std::vector<std::string>>(body))
{}
[[nodiscard]] std::string name() const final {
@ -68,9 +68,12 @@ namespace molasses {
[[nodiscard]] std::vector<std::string> return_types() const final {
return _rets;
}
[[nodiscard]] std::vector<std::string> generate(const parser_context&) const final {
return _instructions;
}
[[nodiscard]] std::vector<std::string> generate(const parser_context&, const lexed_output& lexer_data) const final {
return {};
}
[[nodiscard]] std::vector<std::string> emit(const parser_context&) const final {
return _instructions;
}
};
struct procedure_operation : public operation {
@ -95,7 +98,8 @@ namespace molasses {
[[nodiscard]] std::vector<std::string> return_types() const final {
return _rets;
}
[[nodiscard]] std::vector<std::string> generate(const parser_context&) const final;
[[nodiscard]] std::vector<std::string> generate(const parser_context&, const lexed_output& lexer_data) const final;
[[nodiscard]] std::vector<std::string> emit(const parser_context&) const final;
};
inline auto operator<=>(const operation& lhs, const operation& rhs) {
@ -118,10 +122,14 @@ namespace molasses {
UnexpectedTokenError() : std::runtime_error("An unexpected token has been encountered") {}
// TODO: Better error message
};
struct ExpectingTokenError : std::runtime_error {
ExpectingTokenError() : std::runtime_error("An expected token has not been encountered before the end of the input") {}
// TODO: Better error message
};
struct ExpectingTokenError : std::runtime_error {
ExpectingTokenError() : std::runtime_error("An expected token has not been encountered before the end of the input") {}
// TODO: Better error message
};
struct UnknownTokenError : std::runtime_error {
UnknownTokenError() : std::runtime_error("An unknown token has not been encountered") {}
// TODO: Better error message
};
std::vector<std::string> operator>>(std::vector<std::string> current_stack, const operation& next_op);

+ 14
- 1
src/main.cpp View File

@ -44,7 +44,20 @@ int main() {
molasses::parser_context ctx;
ctx = molasses::register_integers(ctx);
ctx.operations.emplace_back(std::make_shared<molasses::primitive_operation>(std::string{"+"}, std::vector<std::string>({"i32", "i32"}), std::vector<std::string>({"i32"})));
ctx.operations.emplace_back(
std::make_shared<molasses::primitive_operation>(
std::string{"+"},
std::vector<std::string>({"i32", "i32"}),
std::vector<std::string>({"i32"}),
std::vector<std::string>({
" popq %rax\n",
" popq %rbx\n",
" addl %ebx, %eax\n",
" andl $0xFFFFFFFF, %eax\n",
" pushq %rax\n"
})
)
);
molasses::parse(ctx, lexed);
}

+ 96
- 59
src/molasses/parser_primitives.cpp View File

@ -1,5 +1,6 @@
#include <algorithm>
#include <cassert>
#include <iostream>
#include "molasses/parser_primitives.h"
namespace molasses {
@ -88,7 +89,27 @@ namespace molasses {
return type_stack == execution_output;
}
std::vector<std::string> initialize_stack() {
return {
".bss\n",// TODO: make threadlocal
"stack_instruction:\n",
" .quad 0\n",
".text\n",
"initialize_callstack:\n",
" movq $9, %rax\n",
" movq $0, %rdi\n",
" movq $8192, %rsi\n",
" movq $3, %rdx\n",
" movq $34, %r10\n",
" movq $-1, %r8\n",
" movq $0, %r9\n",
" syscall\n",
" movq %rax, (stack_instruction)\n",
" retq\n",
};
}
parser_context parse(parser_context ctx, const lexed_output& lexer_data) {
enum op : int {
DO_KW = 1,
@ -159,70 +180,86 @@ namespace molasses {
return std::make_pair(it, std::make_shared<procedure_operation>(name, argument_types, return_types, body));
#undef CHECK_FOR_UNEXPECTED_STREAM_END
};
auto [iterator, procedure] = parse_proc(tokens.symbols.begin());
ctx.operations.push_back(procedure);
parsed_procedures.emplace_back(std::move(procedure));
auto progress = tokens.symbols.begin();
do {
auto [iterator, procedure] = parse_proc(progress);
ctx.operations.push_back(procedure);
parsed_procedures.emplace_back(std::move(procedure));
progress = iterator;
} while (progress != tokens.symbols.end());
for(auto& proc : parsed_procedures) {
if(not type_check(ctx, tokens, proc->_body, proc->_args, proc->_rets)) {
throw ProcedureStackError();
}
}
std::vector<std::string> generated;
for(auto instr : initialize_stack()) {
generated.push_back(instr);
}
for(auto proc : parsed_procedures) {
for(auto instr : proc->generate(ctx, tokens)) {
generated.push_back(instr);
}
}
for(auto line : generated) {
std::cout << line;
}
return ctx;
}
std::vector<std::string> initialize_stack() {
return {
".bss\n",// TODO: make threadlocal
"stack_instruction:",
" .quad 0",
".text\n",
"initialize_callstack:\n",
" movq $9, %rax\n",
" movq $0, %rdi\n",
" movq $8192, %rsi\n",
" movq $3, %rdx\n",
" movq $34, %r10\n",
" movq $-1, %r8\n",
" movq $0, %r9\n",
" syscall\n",
" movq %rax, (stack_instruction)\n",
" retq\n",
};
}
std::vector<std::string> generate_call(std::string target) {
static uint64_t label_count= 0;
return {
"movq return_label_n"+std::to_string(label_count)+", (stack_instruction)\n",
"addq $8, stack_instruction\n",
"jmp "+target+"\n",
"return_label_n"+std::to_string(label_count++)+":"
};
}
std::vector<std::string> procedure_operation::generate(const parser_context& ctx) const {
size_t initial_stack = 0;
size_t final_stack = 0;
for(const auto& elem : argument_types()) {
initial_stack += ctx.lookup_type(elem)->byte_size();
}
for(const auto& elem : return_types()) {
final_stack += ctx.lookup_type(elem)->byte_size();
}
std::vector<std::string> ops;
ops.emplace_back(name()+":\n");
// Return to caller
ops.emplace_back(" addq $-8, stack_instruction\n");
ops.emplace_back(" movq (stack_instruction), %rax\n");
ops.emplace_back(" pushq %rax\n");
ops.emplace_back(" retq\n");
return ops;
}
std::vector<std::string> generate_call(std::string target) {
static uint64_t label_count= 0;
return {
" movq return_label_n"+std::to_string(label_count)+", (stack_instruction)\n",
" addq $8, stack_instruction\n",
" jmp "+target+"\n",
" return_label_n"+std::to_string(label_count++)+":"
};
}
std::vector<std::string> generate_push_int32(int32_t target) {
return {
" pushq $" +std::to_string(target)+ "\n"
};
}
std::vector<std::string> procedure_operation::generate(const parser_context& ctx, const lexed_output& lexer_data) const {
std::vector<std::string> ops;
ops.emplace_back(name()+":\n");
for(auto elem : _body) {
auto token = lexer_data.dictionary.at(elem);
if(auto result = try_parse_int32(token); result) {
for(auto&& elem : generate_push_int32(result.value())) {
ops.push_back(elem);
}
} else if(auto op = ctx.lookup_operation(token); op) {
for(auto&& elem : op->emit(ctx)) {
ops.push_back(elem);
}
} else {
throw UnknownTokenError();
}
}
ops.emplace_back(" // Return to caller\n");
ops.emplace_back(" addq $-8, stack_instruction\n");
ops.emplace_back(" movq (stack_instruction), %rax\n");
ops.emplace_back(" pushq %rax\n");
ops.emplace_back(" retq\n");
return ops;
}
std::vector<std::string> procedure_operation::emit(const parser_context& ctx) const {
return generate_call(name());
}
}

Loading…
Cancel
Save