Compare commits

...

3 Commits

Author SHA1 Message Date
55388bc6e3 Parse listinitializer 2026-04-15 16:07:07 +03:00
aa698c7ed6 Fix string type lvalue return type 2026-04-15 15:59:12 +03:00
eacbac9205 Implement ListInitializer 2026-04-15 15:57:54 +03:00
6 changed files with 179 additions and 11 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

@ -49,7 +49,9 @@ namespace AST {
if (scope.is_lvalue) {
return codegen::StackValue{
global_str,
std::unique_ptr<types::Type>{stack_type},
std::unique_ptr<types::Type>{
new types::PointerType { std::shared_ptr<types::Type> {stack_type } }
},
};
}
else {
@ -190,14 +192,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 +325,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

@ -71,9 +71,49 @@ namespace parsing {
}
}
Result<std::unique_ptr<AST::Expression>, std::string> parse_list_initializer(token::TokenStream& stream) {
token::TokenStream inner{ stream };
try {
auto before_meta = inner.metadata();
inner.expect(token::Type::Symbol, "{");
std::vector<std::unique_ptr<AST::Expression>> expressions{};
int counter = 0;
while (inner.peek().content != "}") {
if (counter++ > 0) {
inner.expect(token::Type::Symbol, ",");
}
expressions.push_back(parse_expression(inner).unwrap());
}
inner.expect(token::Type::Symbol, "}");
stream.m_position = inner.m_position;
return std::unique_ptr<AST::Expression> {
new AST::ListInitializerExpression(
before_meta + inner.metadata(),
std::move(expressions),
std::shared_ptr<types::Type> {
new types::FundamentalType{ types::FundamentalTypeKind::Any }
})
};
}
catch (std::runtime_error& error) {
return std::string{ error.what() };
}
}
Result<std::unique_ptr<AST::Expression>, std::string> parse_plain_expression(token::TokenStream& stream) {
token::TokenStream inner{ stream };
try {
if (auto list_init = parse_list_initializer(inner); list_init.ok()) {
stream.m_position = inner.m_position;
return std::unique_ptr<AST::Expression> { list_init.unwrap() };
}
auto token = inner.next();
if (token.type == token::Type::LiteralInt) {
stream.m_position = inner.m_position;

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);

3
test.c
View File

@ -14,9 +14,8 @@ int main() {
char text[29] = "10th fibonacci number is %d!";
printf(text, fibonacci(10));
char somelist[5];
char somelist[5] = { 1, 2, 3, 4, 5 };
somelist[0] = 15;
change_first(somelist);
return somelist[0];