You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

144 lines
4.5 KiB

#pragma once
#include <string>
#include <set>
#include <vector>
#include <memory>
#include <optional>
#include <charconv>
#include <concepts>
#include "molasses/lexer.h"
namespace molasses {
struct type {
[[nodiscard]] virtual std::string name() const = 0;
[[nodiscard]] virtual size_t byte_size() const = 0;
};
inline auto operator<=>(const type& lhs, const type& rhs) {
return lhs.name() <=> rhs.name();
}
struct primitive_type : public type {
std::string _name;
size_t _byte_size;
primitive_type(std::string name, size_t byte_size)
: _name(std::forward<std::string>(name))
, _byte_size(byte_size)
{}
[[nodiscard]] std::string name() const final {
return _name;
}
[[nodiscard]] size_t byte_size() const final {
return _byte_size;
};
};
struct parser_context;
struct operation {
[[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[]
};
struct primitive_operation : public operation {
std::string _name;
std::vector<std::string> _args;
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)
: _name(std::forward<std::string>(name))
, _args(std::forward<std::vector<std::string>>(args))
, _rets(std::forward<std::vector<std::string>>(rets))
{}
[[nodiscard]] std::string name() const final {
return _name;
}
[[nodiscard]] std::vector<std::string> argument_types() const final {
return _args;
}
[[nodiscard]] std::vector<std::string> return_types() const final {
return _rets;
}
[[nodiscard]] std::vector<std::string> generate(const parser_context&) const final {
return _instructions;
}
};
struct procedure_operation : public operation {
std::string _name;
std::vector<std::string> _args;
std::vector<std::string> _rets;
std::vector<symbol> _body;
procedure_operation(std::string name, std::vector<std::string> args, std::vector<std::string> rets, std::vector<symbol> body)
: _name(std::forward<std::string>(name))
, _args(std::forward<std::vector<std::string>>(args))
, _rets(std::forward<std::vector<std::string>>(rets))
, _body(std::forward<std::vector<symbol>>(body))
{}
[[nodiscard]] std::string name() const final {
return _name;
}
[[nodiscard]] std::vector<std::string> argument_types() const final {
return _args;
}
[[nodiscard]] std::vector<std::string> return_types() const final {
return _rets;
}
[[nodiscard]] std::vector<std::string> generate(const parser_context&) const final;
};
inline auto operator<=>(const operation& lhs, const operation& rhs) {
return lhs.name() <=> rhs.name();
}
struct TypeInputError : std::runtime_error {
TypeInputError() : std::runtime_error("Bad type provided") {}
// TODO: Better error message
};
struct ValueMissingError : std::runtime_error {
ValueMissingError() : std::runtime_error("Expected value, none provided") {}
// TODO: Better error message
};
struct ProcedureStackError : std::runtime_error {
ProcedureStackError() : std::runtime_error("Expected the stack to look like the return stack upon completion") {}
// TODO: Better error message
};
struct UnexpectedTokenError : std::runtime_error {
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
};
std::vector<std::string> operator>>(std::vector<std::string> current_stack, const operation& next_op);
std::optional<int32_t> try_parse_int32(const std::string& str);
struct parser_context {
std::vector<std::shared_ptr<type>> types;
std::vector<std::shared_ptr<operation>> operations;
[[nodiscard]] std::shared_ptr<type> lookup_type(const std::string&) const;
[[nodiscard]] std::shared_ptr<operation> lookup_operation(const std::string&) const;
};
parser_context parse(parser_context, const lexed_output&);
parser_context register_integers(parser_context);
bool type_check(const parser_context&, const lexed_output&, const std::vector<symbol>&, std::vector<std::string> execution_input, const std::vector<std::string>& execution_output);
}