Implement ListInitializer

This commit is contained in:
Sofia 2026-04-15 15:57:54 +03:00
parent 5175878407
commit eacbac9205
4 changed files with 135 additions and 8 deletions

View File

@ -68,6 +68,21 @@ namespace AST {
return out.str();
}
std::string ListInitializerExpression::formatted() {
std::stringstream out{ "" };
out << "{ ";
int counter = 0;
for (auto& expr : this->m_expressions) {
if (counter++ > 0)
out << ", ";
out << expr->formatted();
}
out << " }";
return out.str();
}
std::string ExpressionStatement::formatted() {
std::stringstream out{ "" };
out << this->m_expr->formatted();

View File

@ -245,6 +245,30 @@ namespace AST {
) override;
};
class ListInitializerExpression : public Expression {
private:
std::vector<std::unique_ptr<Expression>> m_expressions;
std::shared_ptr<types::Type> m_ty;
public:
ListInitializerExpression(
token::Metadata meta,
std::vector<std::unique_ptr<Expression>> expressions,
std::shared_ptr<types::Type> type)
: Expression{ meta }
, m_expressions{ std::move(expressions) }
, m_ty{ type } {
}
virtual ~ListInitializerExpression() override = default;
virtual std::string formatted() override;
virtual codegen::StackValue codegen(codegen::Builder& builder, codegen::Scope& scope) override;
virtual std::shared_ptr<types::Type> get_codegen_type(codegen::Scope& scope) override;
virtual std::shared_ptr<types::Type> typecheck(
typecheck::State& state,
typecheck::Scope& scope,
std::optional<std::shared_ptr<types::Type>> expected_ty
) override;
};
class ReturnStatement : public Statement {
private:

View File

@ -190,14 +190,6 @@ namespace AST {
auto expr = this->m_expr->codegen(builder, scope);
auto cast = types::find_cast(scope.casts, expr.ty, this->m_ty);
if (cast) {
// if (cast->target_ty->m_kind == types::TypeKind::Pointer && cast->casted_ty->m_kind == types::TypeKind::Array) {
// auto allocated = builder.builder->CreateAlloca(cast->casted_ty->codegen(builder));
// builder.builder->CreateStore(expr.value, allocated);
// return codegen::StackValue{
// cast->codegen(builder, cast->target_ty, allocated),
// cast->target_ty
// };
// }
return codegen::StackValue{
cast->codegen(builder, cast->target_ty, expr.value),
cast->target_ty
@ -331,6 +323,44 @@ namespace AST {
}
std::shared_ptr<types::Type> ListInitializerExpression::get_codegen_type(codegen::Scope&) {
return this->m_ty;
}
codegen::StackValue ListInitializerExpression::codegen(codegen::Builder& builder, codegen::Scope& scope) {
auto array_ptr = builder.builder->CreateAlloca(this->m_ty->codegen(builder));
if (this->m_ty->m_kind == types::TypeKind::Array) {
auto array_ty = dynamic_cast<types::ArrayType*>(this->m_ty.get());
int counter = 0;
for (auto& expr : this->m_expressions) {
std::vector<llvm::Value*> indices{};
indices.push_back(llvm::ConstantInt::get(builder.builder->getInt32Ty(), counter++));
auto gep = builder.builder->CreateGEP(
array_ty->m_inner->codegen(builder), array_ptr, indices, "GEP");
builder.builder->CreateStore(expr->codegen(builder, scope).value, gep);
}
auto ptr_ty = std::shared_ptr<types::Type>{
new types::PointerType{this->m_ty}
};
if (scope.is_lvalue) {
return codegen::StackValue{ array_ptr, ptr_ty };
}
else {
auto loaded = ptr_ty->load(builder, array_ptr);
return codegen::StackValue{ loaded.first, loaded.second };
}
}
else {
throw CompileError("Tried to list-initialize a non-array!", this->m_meta);
}
}
void ReturnStatement::codegen(codegen::Builder& builder, codegen::Scope& scope) {
if (!builder.block)
return;

View File

@ -309,6 +309,64 @@ namespace AST {
};
}
std::shared_ptr<types::Type> ListInitializerExpression::typecheck(
typecheck::State& state,
typecheck::Scope& scope,
std::optional<std::shared_ptr<types::Type>> expected_ty
) {
if (expected_ty) {
if ((*expected_ty)->m_kind == types::TypeKind::Array) {
auto array_ty = dynamic_cast<types::ArrayType*>(expected_ty->get());
for (auto& expr : this->m_expressions) {
auto expr_ty = expr->typecheck(state, scope, array_ty->m_inner);
auto expr_res = check_type(state, expr_ty, array_ty->m_inner);
expr = handle_res(std::move(expr), expr_res, state);
}
this->m_ty = std::shared_ptr<types::Type>{
new types::ArrayType{
array_ty->m_inner,
static_cast<uint32_t>(this->m_expressions.size())
}
};
}
else {
return std::shared_ptr<types::Type> {
new types::FundamentalType{ types::FundamentalTypeKind::Void }
};
}
return this->m_ty;
}
// No expected ty, try to infer array type from elements
if (this->m_expressions.size() == 0) {
this->m_ty = std::shared_ptr<types::Type>{
new types::ArrayType{
std::make_shared<types::FundamentalType>(types::FundamentalTypeKind::Void),
0
}
};
return this->m_ty;
}
else {
auto first_expr_ty = this->m_expressions[0]->typecheck(state, scope, {});
for (int i = 1; i < static_cast<int>(this->m_expressions.size()); i++) {
auto expr_ty = this->m_expressions[i]->typecheck(state, scope, first_expr_ty);
auto expr_res = check_type(state, expr_ty, first_expr_ty);
this->m_expressions[i] = handle_res(std::move(this->m_expressions[i]), expr_res, state);
}
this->m_ty = std::shared_ptr<types::Type>{
new types::ArrayType{
first_expr_ty,
static_cast<uint32_t>(this->m_expressions.size())
}
};
return this->m_ty;
}
}
void ReturnStatement::typecheck(typecheck::State& state, typecheck::Scope& scope) {
auto res_ty = this->m_expr->typecheck(state, scope, scope.return_ty);