feat: introduce sizeof instruction

Closes: #34
This commit is contained in:
2026-07-05 22:33:15 +02:00
parent 642d57622a
commit ee9eadeea8
11 changed files with 32 additions and 2 deletions
+1
View File
@@ -114,6 +114,7 @@ enum class unaryop_expression_node_t {
PrefixDecrement, /**< Prefix decrement */
PostfixDecrement, /**< Postfix decrement */
Pointerof, /**< Pointerof */
Sizeof, /**< Sizeof */
};
/**
+3
View File
@@ -158,6 +158,7 @@ enum class keyword_token {
Public, /**< `public` */
Private, /**< `private` */
Pointerof, /**< `pointerof` */
Sizeof, /**< `sizeof` */
Int32, /**< `int32` */
};
@@ -175,6 +176,7 @@ static inline std::ostream& operator<<(std::ostream& os, keyword_token keyword)
case keyword_token::Public: return os << "public";
case keyword_token::Private: return os << "private";
case keyword_token::Pointerof: return os << "pointerof";
case keyword_token::Sizeof: return os << "sizeof";
case keyword_token::Int32: return os << "int32";
}
return os;
@@ -193,6 +195,7 @@ static inline std::string operator+(const std::string& str, keyword_token keywor
case keyword_token::Public: return str + "public";
case keyword_token::Private: return str + "private";
case keyword_token::Pointerof: return str + "pointerof";
case keyword_token::Sizeof: return str + "sizeof";
case keyword_token::Int32: return str + "int32";
}
return str;
+2
View File
@@ -38,6 +38,7 @@ std::ostream& operator<<(std::ostream& os, unaryop_expression_node_t type) {
case unaryop_expression_node_t::PrefixDecrement:
case unaryop_expression_node_t::PostfixDecrement: return os << "--";
case unaryop_expression_node_t::Pointerof: return os << "pointerof";
case unaryop_expression_node_t::Sizeof: return os << "sizeof";
}
return os;
}
@@ -56,6 +57,7 @@ std::ostream& unary_op_expression_node::print(std::ostream& os) const {
case unaryop_expression_node_t::PostfixIncrement:
case unaryop_expression_node_t::PostfixDecrement: return os << '(' << *m_node << m_type << ')';
case unaryop_expression_node_t::Pointerof: return os << "pointerof " << *m_node;
case unaryop_expression_node_t::Sizeof: return os << "sizeof " << *m_node;
}
return os;
}
+3 -1
View File
@@ -59,6 +59,7 @@ static inline furvm::instruction_t op_type(furlang::ir::instruction_t type) {
switch (type) {
// Unary
case furlang::ir::instruction_t::Pointerof: return furvm::instruction_t::Pointerof;
case furlang::ir::instruction_t::Sizeof: return furvm::instruction_t::Sizeof;
// Binary
case furlang::ir::instruction_t::Add: return furvm::instruction_t::Add;
@@ -116,7 +117,8 @@ void furvm_generator::generate_instruction(furvm::mod& mod,
mod.bytecode().push_back((var >> 8) & 0xFF);
static_assert(sizeof(var) == 2, "sizeof(furvm::variable_t) has changed");
} break;
case furlang::ir::instruction_t::Pointerof: {
case furlang::ir::instruction_t::Pointerof:
case furlang::ir::instruction_t::Sizeof: {
mod.bytecode().push_back(static_cast<furvm::byte>(op_type(instr.type())));
if (ctx.variables.find(instr.destination().reg()) == ctx.variables.end()) {
+1
View File
@@ -135,6 +135,7 @@ void ir_generator::visit(const ast::var_read_expression_node& node) {
static inline furlang::ir::instruction_t unary_op_instruction_t(ast::unaryop_expression_node_t type) {
switch (type) {
case ast::unaryop_expression_node_t::Pointerof: return furlang::ir::instruction_t::Pointerof;
case ast::unaryop_expression_node_t::Sizeof: return furlang::ir::instruction_t::Sizeof;
default: throw std::runtime_error("unimplemented");
}
}
+1
View File
@@ -105,6 +105,7 @@ token_r lexer::next_token() {
{ "public", keyword_token::Public },
{ "private", keyword_token::Private },
{ "pointerof", keyword_token::Pointerof },
{ "sizeof", keyword_token::Sizeof },
{ "int32", keyword_token::Int32 },
};
+1
View File
@@ -323,6 +323,7 @@ static inline std::optional<unaryop_info> get_unaryop_info(const token_r& token)
};
static std::unordered_map<keyword_token, unaryop_info> s_keywords = {
{ keyword_token::Pointerof, unaryop_info{ ast::unaryop_expression_node_t::Pointerof, 2 } },
{ keyword_token::Sizeof, unaryop_info{ ast::unaryop_expression_node_t::Sizeof, 2 } },
};
if (token->type == token_t::Keyword) {
+1 -1
View File
@@ -23,7 +23,7 @@ int main(void) {
while (x < y) {
x = x + z;
}
print(pointerof x);
print(sizeof x);
}
)";
furlang::arena arena{};
@@ -32,6 +32,7 @@ enum class instruction_t {
LessEq, /**< Less or equal */
GreaterEq, /**< Greater or equal */
Pointerof, /**< Pointerof */
Sizeof, /**< Sizeof */
Call, /**< Call */
Branch, /**< Branch */
BranchCond, /**< Conditional branch */
@@ -55,6 +56,7 @@ static inline std::ostream& operator<<(std::ostream& os, instruction_t type) {
case instruction_t::LessEq: return os << "lessEq";
case instruction_t::GreaterEq: return os << "greaterEq";
case instruction_t::Pointerof: return os << "pointerof";
case instruction_t::Sizeof: return os << "sizeof";
case instruction_t::Call: return os << "call";
case instruction_t::Branch: return os << "branch";
case instruction_t::BranchCond: return os << "branchCond";
+5
View File
@@ -107,6 +107,11 @@ enum class instruction_t : byte {
*/
Pointerof,
/**
* @brief Pushes a size of popped-off thing onto the stack.
*/
Sizeof,
/**
* @brief Pushes a variable onto the stack.
*
+12
View File
@@ -175,6 +175,18 @@ void executor::step() {
default: throw std::runtime_error("unreachable");
}
} break;
case instruction_t::Sizeof: {
auto thing = pop_thing()->resolve();
auto ptr = push_thing({ *m_context->at("core")->type_at(3), m_context, m_context->thing_alloc() });
auto type = furvm::thing<>::resolve_type(thing.type(), m_context);
switch (type->t) {
case type_t::Primitive: ptr->get<long_t>() = static_cast<long_t>(type->primitive); break;
case type_t::List: ptr->get<long_t>() = thing.get<list_t>().size; break;
case type_t::Reference:
case type_t::Import:
default: throw std::runtime_error("unreachable");
}
} break;
case instruction_t::Load: {
variable_t variable = static_cast<std::uint16_t>(frame.mod->byte(frame.position)) |
(static_cast<std::uint16_t>(frame.mod->byte(frame.position + 1)) << 8);