From 77449a7f3b3295c5f14142c32a2de9e61750d95a Mon Sep 17 00:00:00 2001 From: rpkak Date: Sat, 2 Dec 2023 21:57:45 +0100 Subject: [PATCH] wip --- CMakeLists.txt | 14 ++ src/ptlang_ast/ptlang_ast.c | 23 +++ src/ptlang_ast/ptlang_ast.h | 1 + src/ptlang_eval/ptlang_eval.c | 59 ++++++ src/ptlang_eval/ptlang_eval.h | 18 ++ src/ptlang_eval/ptlang_eval_impl.h | 14 ++ src/ptlang_ir_builder/ptlang_ir_builder.c | 216 ++++++++++++---------- src/ptlang_ir_builder/ptlang_ir_builder.h | 32 ++++ src/ptlang_utils/ptlang_utils.h | 1 + src/ptlang_verify/ptlang_verify.c | 210 ++++++++++++++++++--- 10 files changed, 465 insertions(+), 123 deletions(-) create mode 100644 src/ptlang_eval/ptlang_eval.c create mode 100644 src/ptlang_eval/ptlang_eval.h create mode 100644 src/ptlang_eval/ptlang_eval_impl.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a80af3b..3dc0c12 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,7 @@ set(PTLANG_MAIN_SRC_DIR ${PTLANG_SRC_DIR}/ptlang_main) set(PTLANG_IR_BUILDER_SRC_DIR ${PTLANG_SRC_DIR}/ptlang_ir_builder) set(PTLANG_VERIFY_SRC_DIR ${PTLANG_SRC_DIR}/ptlang_verify) set(PTLANG_UTILS_SRC_DIR ${PTLANG_SRC_DIR}/ptlang_utils) +set(PTLANG_EVAL_SRC_DIR ${PTLANG_SRC_DIR}/ptlang_eval) set(PTLANG_THIRD_PARTY_DIR ${PROJECT_SOURCE_DIR}/third-party) set(PTLANG_STB_DIR ${PTLANG_THIRD_PARTY_DIR}/stb) @@ -105,6 +106,19 @@ target_include_directories(ptlang_verify PUBLIC ${PTLANG_STB_DIR} ) + +add_library(ptlang_eval OBJECT + ${PTLANG_EVAL_SRC_DIR}/ptlang_eval.c) + + +target_include_directories(ptlang_eval + PRIVATE ${PTLANG_AST_SRC_DIR} + # PRIVATE ${PTLANG_MAIN_SRC_DIR} + PRIVATE ${PTLANG_IR_BUILDER_SRC_DIR} + PRIVATE ${PTLANG_UTILS_SRC_DIR} + PUBLIC ${PTLANG_STB_DIR} + ) + # llvm_map_components_to_libnames(llvm_libs support core irreader) diff --git a/src/ptlang_ast/ptlang_ast.c b/src/ptlang_ast/ptlang_ast.c index 3dce124..bac54e2 100644 --- a/src/ptlang_ast/ptlang_ast.c +++ b/src/ptlang_ast/ptlang_ast.c @@ -482,6 +482,18 @@ ptlang_ast_exp ptlang_ast_exp_reference_new(bool writable, ptlang_ast_exp value, UNARY_OP(dereference, DEREFERENCE) +ptlang_ast_exp ptlang_ast_exp_binary_new(uint8_t *binary, ptlang_ast_exp prev) +{ + ptlang_ast_exp exp = ptlang_malloc(sizeof(struct ptlang_ast_exp_s)); + *exp = (struct ptlang_ast_exp_s){ + .type = PTLANG_AST_EXP_BINARY, + .content.binary = binary, + .pos = prev->pos, + .ast_type = prev->ast_type, + }; + return exp; +} + ptlang_ast_stmt ptlang_ast_stmt_block_new(ptlang_ast_code_position pos) { ptlang_ast_stmt stmt = ptlang_malloc(sizeof(struct ptlang_ast_stmt_s)); @@ -972,3 +984,14 @@ ptlang_ast_code_position ptlang_ast_code_position_copy(ptlang_ast_code_position }); return new_pos; } + +ptlang_ast_ident ptlang_ast_ident_copy(ptlang_ast_ident ident) +{ + size_t name_len = strlen(ident.name) + 1; + ptlang_ast_ident new_ident = { + .name = ptlang_malloc(name_len), + .pos = ptlang_ast_code_position_copy(ident.pos), + }; + memcpy(new_ident.name, ident.name, name_len); + return new_ident; +} \ No newline at end of file diff --git a/src/ptlang_ast/ptlang_ast.h b/src/ptlang_ast/ptlang_ast.h index 0df380c..2ca5d3c 100644 --- a/src/ptlang_ast/ptlang_ast.h +++ b/src/ptlang_ast/ptlang_ast.h @@ -153,6 +153,7 @@ ptlang_ast_exp ptlang_ast_exp_array_element_new(ptlang_ast_exp array, ptlang_ast ptlang_ast_exp ptlang_ast_exp_reference_new(bool writable, ptlang_ast_exp value, ptlang_ast_code_position pos); ptlang_ast_exp ptlang_ast_exp_dereference_new(ptlang_ast_exp value, ptlang_ast_code_position pos); +ptlang_ast_exp ptlang_ast_exp_binary_new(uint8_t* binary, ptlang_ast_exp prev); ptlang_ast_stmt ptlang_ast_stmt_block_new(ptlang_ast_code_position pos); void ptlang_ast_stmt_block_add_stmt(ptlang_ast_stmt block_stmt, ptlang_ast_stmt stmt); diff --git a/src/ptlang_eval/ptlang_eval.c b/src/ptlang_eval/ptlang_eval.c new file mode 100644 index 0000000..8baf29e --- /dev/null +++ b/src/ptlang_eval/ptlang_eval.c @@ -0,0 +1,59 @@ +#include "ptlang_eval_impl.h" + +ptlang_ast_exp ptlang_eval_const_exp(ptlang_ast_exp exp) +{ + LLVMContextRef C = LLVMContextCreate(); + LLVMModuleRef M = LLVMModuleCreateWithNameInContext("ptlang_eval", C); + + LLVMTypeRef type = ptlang_ir_builder_type(exp->ast_type, NULL, C); + + LLVMTypeRef func_type = + LLVMFunctionType(LLVMVoidTypeInContext(C), (LLVMTypeRef[]){LLVMPointerTypeInContext(C, 0)}, 1, false); + + LLVMValueRef function = LLVMAddFunction(M, "main", func_type); + + LLVMTypeRef size_func_type = LLVMFunctionType(LLVMInt64TypeInContext(C), NULL, 0, false); + + LLVMValueRef size_func = LLVMAddFunction(M, "size", size_func_type); + + LLVMBuilderRef B = LLVMCreateBuilderInContext(C); + + LLVMBasicBlockRef size_entry = LLVMAppendBasicBlockInContext(C, size_func, "size_entry"); + + LLVMPositionBuilderAtEnd(B, size_entry); + LLVMValueRef size_value = LLVMSizeOf(type); + LLVMBuildRet(B, size_value); + + LLVMBasicBlockRef entry = LLVMAppendBasicBlockInContext(C, function, "entry"); + + ptlang_ir_builder_build_context cxt = { + .builder = B, + .module = M, + .function = function, + }; + LLVMPositionBuilderAtEnd(B, entry); + + LLVMValueRef value = ptlang_ir_builder_exp(exp, &cxt); + LLVMBuildStore(B, value, LLVMGetParam(function, 0)); + LLVMBuildRetVoid(B); + LLVMLinkInInterpreter(); + + LLVMExecutionEngineRef ee; + LLVMCreateExecutionEngineForModule(&ee, M, NULL); + + LLVMGenericValueRef in_llvm_size = LLVMRunFunction(ee, size_func, 0, NULL); + unsigned long long size = LLVMGenericValueToInt(in_llvm_size, false); + + uint8_t *binary = NULL; + + arrsetlen(binary, size); + + LLVMGenericValueRef in_llvm_binary = LLVMCreateGenericValueOfPointer(binary); + LLVMRunFunction(ee, function, 1, &in_llvm_binary); + LLVMDisposeExecutionEngine(ee); + + LLVMDisposeModule(M); + LLVMContextDispose(C); + + return ptlang_ast_exp_binary_new(binary, exp); +} \ No newline at end of file diff --git a/src/ptlang_eval/ptlang_eval.h b/src/ptlang_eval/ptlang_eval.h new file mode 100644 index 0000000..15f9e30 --- /dev/null +++ b/src/ptlang_eval/ptlang_eval.h @@ -0,0 +1,18 @@ +#pragma once + +#include "ptlang_ast_impl.h" +#include + +// typedef ptlang_eval_value; + +// typedef struct ptlang_eval_var_s +// { +// char *key; +// ptlang_eval_value value; +// } ptlang_eval_var; + +// ptlang_eval_value ptlang_eval_const_exp(ptlang_ast_exp exp, ptlang_ast_type type, ptlang_eval_var *vars); + +// LLVMValueRef ptlang_eval_byte_array_to_llvm(ptlang_eval_value val); + +ptlang_ast_exp ptlang_eval_const_exp(ptlang_ast_exp exp); \ No newline at end of file diff --git a/src/ptlang_eval/ptlang_eval_impl.h b/src/ptlang_eval/ptlang_eval_impl.h new file mode 100644 index 0000000..f2bb0cd --- /dev/null +++ b/src/ptlang_eval/ptlang_eval_impl.h @@ -0,0 +1,14 @@ +#pragma once + +#include "ptlang_eval.h" +#include "ptlang_ir_builder.h" +#include "ptlang_utils.h" + +#include +#include + +// typedef struct ptlang_eval_value_s +// { +// uint8_t *data; +// ptlang_ast_type type; +// } ptlang_eval_value; diff --git a/src/ptlang_ir_builder/ptlang_ir_builder.c b/src/ptlang_ir_builder/ptlang_ir_builder.c index 77909c2..24ac5ab 100644 --- a/src/ptlang_ir_builder/ptlang_ir_builder.c +++ b/src/ptlang_ir_builder/ptlang_ir_builder.c @@ -33,8 +33,6 @@ typedef struct ptlang_ir_builder_scope_entry_s ptlang_ir_builder_scope_entry_value value; } ptlang_ir_builder_scope_entry; -typedef struct ptlang_ir_builder_scope_s ptlang_ir_builder_scope; - struct ptlang_ir_builder_scope_s { ptlang_ir_builder_scope *parent; @@ -103,11 +101,11 @@ static inline LLVMValueRef ptlang_ir_builder_scope_get(ptlang_ir_builder_scope * exit(EXIT_FAILURE); } -typedef struct ptlang_ir_builder_struct_def_s +struct ptlang_ir_builder_struct_def_s { char *key; ptlang_ast_decl *value; -} ptlang_ir_builder_struct_def; +}; typedef struct ptlang_ir_builder_type_scope_entry_s { @@ -115,11 +113,11 @@ typedef struct ptlang_ir_builder_type_scope_entry_s ptlang_ast_type ptlang_type; } ptlang_ir_builder_type_scope_entry; -typedef struct ptlang_ir_builder_type_scope_s +struct ptlang_ir_builder_type_scope_s { char *key; ptlang_ir_builder_type_scope_entry value; -} ptlang_ir_builder_type_scope; +}; struct break_and_continue_block { @@ -127,26 +125,6 @@ struct break_and_continue_block LLVMBasicBlockRef continue_; }; -typedef struct ptlang_ir_builder_build_context_s -{ - LLVMBuilderRef builder; - LLVMModuleRef module; - LLVMValueRef function; - ptlang_ir_builder_type_scope *type_scope; - ptlang_ir_builder_scope *scope; - uint64_t scope_number; - ptlang_ir_builder_scope **scopes; - LLVMValueRef return_ptr; - LLVMBasicBlockRef return_block; - struct break_and_continue_block *break_and_continue_blocks; - ptlang_ast_type return_type; - ptlang_ir_builder_struct_def *struct_defs; - LLVMTargetDataRef target_info; - LLVMValueRef malloc_func; - LLVMValueRef realloc_func; - LLVMValueRef free_func; -} ptlang_ir_builder_build_context; - static inline ptlang_ast_type ptlang_ir_builder_unname_type(ptlang_ast_type type, ptlang_ir_builder_build_context *ctx) { @@ -168,10 +146,7 @@ INIT_FUNCTION(realloc, LLVMPointerType(LLVMInt8Type(), 0), ((LLVMTypeRef[]){LLVMPointerType(LLVMInt8Type(), 0), LLVMIntPtrType(ctx->target_info)})) INIT_FUNCTION(free, LLVMVoidType(), (LLVMTypeRef[]){LLVMPointerType(LLVMInt8Type(), 0)}) -static LLVMTypeRef ptlang_ir_builder_type(ptlang_ast_type type, ptlang_ir_builder_build_context *ctx); - static ptlang_ast_type ptlang_ir_builder_exp_type(ptlang_ast_exp exp, ptlang_ir_builder_build_context *ctx); -static LLVMValueRef ptlang_ir_builder_exp(ptlang_ast_exp exp, ptlang_ir_builder_build_context *ctx); static LLVMValueRef ptlang_ir_builder_exp_ptr(ptlang_ast_exp exp, ptlang_ir_builder_build_context *ctx) { @@ -189,7 +164,7 @@ static LLVMValueRef ptlang_ir_builder_exp_ptr(ptlang_ast_exp exp, ptlang_ir_buil else { ptlang_ast_type struct_type = ptlang_ir_builder_exp_type(exp->content.struct_member.struct_, ctx); - LLVMTypeRef struct_type_llvm = ptlang_ir_builder_type(struct_type, ctx); + LLVMTypeRef struct_type_llvm = ptlang_ir_builder_type(struct_type, ctx, LLVMGetGlobalContext()); ptlang_ast_decl *members = shget(ctx->struct_defs, struct_type->content.name); ptlang_ast_type_destroy(struct_type); @@ -213,7 +188,7 @@ static LLVMValueRef ptlang_ir_builder_exp_ptr(ptlang_ast_exp exp, ptlang_ir_buil LLVMValueRef array_ptr = ptlang_ir_builder_exp_ptr(exp->content.array_element.array, ctx); if (array_ptr != NULL) { - LLVMTypeRef llvm_array_type = ptlang_ir_builder_type(array_type, ctx); + LLVMTypeRef llvm_array_type = ptlang_ir_builder_type(array_type, ctx, LLVMGetGlobalContext()); element_ptr = LLVMBuildInBoundsGEP2( ctx->builder, llvm_array_type, array_ptr, (LLVMValueRef[]){LLVMConstInt(LLVMInt1Type(), 0, false), index}, 2, "arrayelement"); @@ -223,11 +198,13 @@ static LLVMValueRef ptlang_ir_builder_exp_ptr(ptlang_ast_exp exp, ptlang_ir_buil { LLVMValueRef struct_ptr = ptlang_ir_builder_exp_ptr(exp->content.array_element.array, ctx); LLVMValueRef heap_ptr; - LLVMTypeRef llvm_element_type = ptlang_ir_builder_type(array_type->content.heap_array.type, ctx); + LLVMTypeRef llvm_element_type = + ptlang_ir_builder_type(array_type->content.heap_array.type, ctx, LLVMGetGlobalContext()); if (struct_ptr != NULL) { LLVMValueRef heap_ptr_ptr = LLVMBuildStructGEP2( - ctx->builder, ptlang_ir_builder_type(array_type, ctx), struct_ptr, 0, "heapptrptr"); + ctx->builder, ptlang_ir_builder_type(array_type, ctx, LLVMGetGlobalContext()), struct_ptr, + 0, "heapptrptr"); heap_ptr = LLVMBuildLoad2(ctx->builder, LLVMPointerType(llvm_element_type, 0), heap_ptr_ptr, "heapptr"); } @@ -250,7 +227,7 @@ static LLVMValueRef ptlang_ir_builder_exp_ptr(ptlang_ast_exp exp, ptlang_ir_buil if (heap_arr_ptr != NULL) { ptlang_ast_type array_type = ptlang_ir_builder_exp_type(exp->content.unary_operator, ctx); - LLVMTypeRef array_llvm_type = ptlang_ir_builder_type(array_type, ctx); + LLVMTypeRef array_llvm_type = ptlang_ir_builder_type(array_type, ctx, LLVMGetGlobalContext()); ptlang_ast_type_destroy(array_type); return LLVMBuildStructGEP2(ctx->builder, array_llvm_type, heap_arr_ptr, 1, "heaparraylengthptr"); } @@ -293,7 +270,8 @@ static ptlang_ast_type ptlang_ir_builder_combine_types(ptlang_ast_type a, ptlang } } -static LLVMTypeRef ptlang_ir_builder_type(ptlang_ast_type type, ptlang_ir_builder_build_context *ctx) +LLVMTypeRef ptlang_ir_builder_type(ptlang_ast_type type, ptlang_ir_builder_build_context *ctx, + LLVMContextRef C) { LLVMTypeRef *param_types; LLVMTypeRef function_type; @@ -301,38 +279,39 @@ static LLVMTypeRef ptlang_ir_builder_type(ptlang_ast_type type, ptlang_ir_builde switch (type->type) { case PTLANG_AST_TYPE_VOID: - return LLVMVoidType(); + return LLVMVoidTypeInContext(C); case PTLANG_AST_TYPE_INTEGER: - return LLVMIntType(type->content.integer.size); + return LLVMIntTypeInContext(C, type->content.integer.size); case PTLANG_AST_TYPE_FLOAT: switch (type->content.float_size) { case PTLANG_AST_TYPE_FLOAT_16: - return LLVMHalfType(); + return LLVMHalfTypeInContext(C); case PTLANG_AST_TYPE_FLOAT_32: - return LLVMFloatType(); + return LLVMFloatTypeInContext(C); case PTLANG_AST_TYPE_FLOAT_64: - return LLVMDoubleType(); + return LLVMDoubleTypeInContext(C); case PTLANG_AST_TYPE_FLOAT_128: - return LLVMFP128Type(); + return LLVMFP128TypeInContext(C); } case PTLANG_AST_TYPE_FUNCTION: param_types = ptlang_malloc(sizeof(LLVMTypeRef) * arrlenu(type->content.function.parameters)); for (size_t i = 0; i < arrlenu(type->content.function.parameters); i++) { - param_types[i] = ptlang_ir_builder_type(type->content.function.parameters[i], ctx); + param_types[i] = ptlang_ir_builder_type(type->content.function.parameters[i], ctx, C); } - function_type = LLVMFunctionType(ptlang_ir_builder_type(type->content.function.return_type, ctx), + function_type = LLVMFunctionType(ptlang_ir_builder_type(type->content.function.return_type, ctx, C), param_types, arrlenu(type->content.function.parameters), false); ptlang_free(param_types); - function_type = LLVMPointerType(function_type, 0); + function_type = LLVMPointerTypeInContext(C, 0); return function_type; case PTLANG_AST_TYPE_HEAP_ARRAY: - return HEAP_ARRAY_TYPE(ptlang_ir_builder_type(type->content.heap_array.type, ctx), ctx); + return HEAP_ARRAY_TYPE(ptlang_ir_builder_type(type->content.heap_array.type, ctx, C), ctx); case PTLANG_AST_TYPE_ARRAY: - return LLVMArrayType(ptlang_ir_builder_type(type->content.array.type, ctx), type->content.array.len); + return LLVMArrayType(ptlang_ir_builder_type(type->content.array.type, ctx, C), + type->content.array.len); case PTLANG_AST_TYPE_REFERENCE: - return LLVMPointerType(ptlang_ir_builder_type(type->content.reference.type, ctx), 0); + return LLVMPointerType(ptlang_ir_builder_type(type->content.reference.type, ctx, C), 0); case PTLANG_AST_TYPE_NAMED: return shget(ctx->type_scope, type->content.name).type; } @@ -406,6 +385,7 @@ static ptlang_ast_type ptlang_ir_builder_type_copy_and_unname(ptlang_ast_type ty static ptlang_ast_type ptlang_ir_builder_exp_type(ptlang_ast_exp exp, ptlang_ir_builder_build_context *ctx) { + return exp->ast_type; switch (exp->type) { case PTLANG_AST_EXP_ASSIGNMENT: @@ -613,7 +593,7 @@ static LLVMValueRef ptlang_ir_builder_type_default_value(ptlang_ast_type type, ptlang_ir_builder_build_context *ctx) { type = ptlang_ir_builder_unname_type(type, ctx); - LLVMTypeRef llvm_type = ptlang_ir_builder_type(type, ctx); + LLVMTypeRef llvm_type = ptlang_ir_builder_type(type, ctx, LLVMGetGlobalContext()); switch (type->type) { case PTLANG_AST_TYPE_VOID: @@ -627,7 +607,8 @@ static LLVMValueRef ptlang_ir_builder_type_default_value(ptlang_ast_type type, case PTLANG_AST_TYPE_HEAP_ARRAY: return LLVMConstStruct( (LLVMValueRef[]){ - LLVMGetPoison(LLVMPointerType(ptlang_ir_builder_type(type->content.heap_array.type, ctx), 0)), + LLVMGetPoison(LLVMPointerType( + ptlang_ir_builder_type(type->content.heap_array.type, ctx, LLVMGetGlobalContext()), 0)), LLVMConstInt(LLVMIntPtrType(ctx->target_info), 0, false), }, 2, false); @@ -639,8 +620,9 @@ static LLVMValueRef ptlang_ir_builder_type_default_value(ptlang_ast_type type, { element_values[i] = element_value; } - LLVMValueRef array = LLVMConstArray(ptlang_ir_builder_type(type->content.array.type, ctx), - element_values, type->content.array.len); + LLVMValueRef array = + LLVMConstArray(ptlang_ir_builder_type(type->content.array.type, ctx, LLVMGetGlobalContext()), + element_values, type->content.array.len); ptlang_free(element_values); return array; } @@ -674,16 +656,19 @@ static LLVMValueRef ptlang_ir_builder_build_cast(LLVMValueRef input, ptlang_ast_ { if (from->content.integer.is_signed) { - return LLVMBuildSExt(ctx->builder, input, ptlang_ir_builder_type(to, ctx), "cast"); + return LLVMBuildSExt(ctx->builder, input, + ptlang_ir_builder_type(to, ctx, LLVMGetGlobalContext()), "cast"); } else { - return LLVMBuildZExt(ctx->builder, input, ptlang_ir_builder_type(to, ctx), "cast"); + return LLVMBuildZExt(ctx->builder, input, + ptlang_ir_builder_type(to, ctx, LLVMGetGlobalContext()), "cast"); } } else if (from->content.integer.size > to->content.integer.size) { - return LLVMBuildTrunc(ctx->builder, input, ptlang_ir_builder_type(to, ctx), "cast"); + return LLVMBuildTrunc(ctx->builder, input, + ptlang_ir_builder_type(to, ctx, LLVMGetGlobalContext()), "cast"); } else { @@ -694,11 +679,13 @@ static LLVMValueRef ptlang_ir_builder_build_cast(LLVMValueRef input, ptlang_ast_ { if (from->content.float_size < to->content.float_size) { - return LLVMBuildFPExt(ctx->builder, input, ptlang_ir_builder_type(to, ctx), "cast"); + return LLVMBuildFPExt(ctx->builder, input, + ptlang_ir_builder_type(to, ctx, LLVMGetGlobalContext()), "cast"); } else if (from->content.float_size > to->content.float_size) { - return LLVMBuildFPTrunc(ctx->builder, input, ptlang_ir_builder_type(to, ctx), "cast"); + return LLVMBuildFPTrunc(ctx->builder, input, + ptlang_ir_builder_type(to, ctx, LLVMGetGlobalContext()), "cast"); } else { @@ -709,22 +696,26 @@ static LLVMValueRef ptlang_ir_builder_build_cast(LLVMValueRef input, ptlang_ast_ { if (from->content.integer.is_signed) { - return LLVMBuildSIToFP(ctx->builder, input, ptlang_ir_builder_type(to, ctx), "cast"); + return LLVMBuildSIToFP(ctx->builder, input, + ptlang_ir_builder_type(to, ctx, LLVMGetGlobalContext()), "cast"); } else { - return LLVMBuildUIToFP(ctx->builder, input, ptlang_ir_builder_type(to, ctx), "cast"); + return LLVMBuildUIToFP(ctx->builder, input, + ptlang_ir_builder_type(to, ctx, LLVMGetGlobalContext()), "cast"); } } else if (from->type == PTLANG_AST_TYPE_FLOAT && to->type == PTLANG_AST_TYPE_INTEGER) { if (to->content.integer.is_signed) { - return LLVMBuildFPToSI(ctx->builder, input, ptlang_ir_builder_type(to, ctx), "cast"); + return LLVMBuildFPToSI(ctx->builder, input, + ptlang_ir_builder_type(to, ctx, LLVMGetGlobalContext()), "cast"); } else { - return LLVMBuildFPToUI(ctx->builder, input, ptlang_ir_builder_type(to, ctx), "cast"); + return LLVMBuildFPToUI(ctx->builder, input, + ptlang_ir_builder_type(to, ctx, LLVMGetGlobalContext()), "cast"); } } else @@ -747,15 +738,18 @@ static void ptlang_ir_builder_prepare_binary_op(ptlang_ast_exp exp, LLVMValueRef LLVMValueRef *right_value, ptlang_ast_type *ret_type, ptlang_ir_builder_build_context *ctx) { - ptlang_ast_type left_type = ptlang_ir_builder_exp_type(exp->content.binary_operator.left_value, ctx); - ptlang_ast_type right_type = ptlang_ir_builder_exp_type(exp->content.binary_operator.right_value, ctx); - *ret_type = ptlang_ir_builder_combine_types(left_type, right_type, ctx->type_scope); + // ptlang_ast_type left_type = ptlang_ir_builder_exp_type(exp->content.binary_operator.left_value, ctx); + ptlang_ast_type left_type = exp->content.binary_operator.left_value->ast_type; + // ptlang_ast_type right_type = ptlang_ir_builder_exp_type(exp->content.binary_operator.right_value, ctx); + ptlang_ast_type right_type = exp->content.binary_operator.right_value->ast_type; + // *ret_type = ptlang_ir_builder_combine_types(left_type, right_type, ctx->type_scope); + *ret_type = exp->ast_type; LLVMValueRef left_value_uncasted = ptlang_ir_builder_exp(exp->content.binary_operator.left_value, ctx); *left_value = ptlang_ir_builder_build_cast(left_value_uncasted, left_type, *ret_type, ctx); LLVMValueRef right_value_uncasted = ptlang_ir_builder_exp(exp->content.binary_operator.right_value, ctx); *right_value = ptlang_ir_builder_build_cast(right_value_uncasted, right_type, *ret_type, ctx); - ptlang_ast_type_destroy(left_type); - ptlang_ast_type_destroy(right_type); + // ptlang_ast_type_destroy(left_type); + // ptlang_ast_type_destroy(right_type); } static LLVMValueRef ptlang_ir_builder_exp_as_bool(ptlang_ast_exp exp, ptlang_ir_builder_build_context *ctx) @@ -764,7 +758,7 @@ static LLVMValueRef ptlang_ir_builder_exp_as_bool(ptlang_ast_exp exp, ptlang_ir_ LLVMValueRef value = ptlang_ir_builder_exp(exp, ctx); - LLVMTypeRef llvm_type = ptlang_ir_builder_type(type, ctx); + LLVMTypeRef llvm_type = ptlang_ir_builder_type(type, ctx, LLVMGetGlobalContext()); if (type->type == PTLANG_AST_TYPE_INTEGER && type->content.integer.size != 1) { @@ -778,7 +772,7 @@ static LLVMValueRef ptlang_ir_builder_exp_as_bool(ptlang_ast_exp exp, ptlang_ir_ return value; } -static LLVMValueRef ptlang_ir_builder_exp(ptlang_ast_exp exp, ptlang_ir_builder_build_context *ctx) +LLVMValueRef ptlang_ir_builder_exp(ptlang_ast_exp exp, ptlang_ir_builder_build_context *ctx) { switch (exp->type) { @@ -813,9 +807,10 @@ static LLVMValueRef ptlang_ir_builder_exp(ptlang_ast_exp exp, ptlang_ir_builder_ exp->content.binary_operator.left_value->content.unary_operator, ctx); ptlang_ast_type heap_arr_type = ptlang_ir_builder_exp_type( exp->content.binary_operator.left_value->content.unary_operator, ctx); - LLVMTypeRef heap_arr_llvm_type = ptlang_ir_builder_type(heap_arr_type, ctx); + LLVMTypeRef heap_arr_llvm_type = + ptlang_ir_builder_type(heap_arr_type, ctx, LLVMGetGlobalContext()); LLVMTypeRef heap_arr_element_type = - ptlang_ir_builder_type(heap_arr_type->content.heap_array.type, ctx); + ptlang_ir_builder_type(heap_arr_type->content.heap_array.type, ctx, LLVMGetGlobalContext()); ptlang_ast_type_destroy(heap_arr_type); LLVMValueRef heap_len_ptr = LLVMBuildStructGEP2(ctx->builder, heap_arr_llvm_type, heap_arr_ptr, 1, "reallocheaplenptr"); @@ -1440,12 +1435,13 @@ static LLVMValueRef ptlang_ir_builder_exp(ptlang_ast_exp exp, ptlang_ir_builder_ args[i] = ptlang_ir_builder_exp_and_cast(exp->content.function_call.parameters[i], function_type->content.function.parameters[i], ctx); - param_types[i] = ptlang_ir_builder_type(function_type->content.function.parameters[i], ctx); + param_types[i] = ptlang_ir_builder_type(function_type->content.function.parameters[i], ctx, + LLVMGetGlobalContext()); } - LLVMTypeRef type = - LLVMFunctionType(ptlang_ir_builder_type(function_type->content.function.return_type, ctx), - param_types, arrlenu(exp->content.function_call.parameters), false); + LLVMTypeRef type = LLVMFunctionType( + ptlang_ir_builder_type(function_type->content.function.return_type, ctx, LLVMGetGlobalContext()), + param_types, arrlenu(exp->content.function_call.parameters), false); ptlang_free(param_types); // LLVMTypeRef type = ptlang_ir_builder_type(function_type_unnamed, ctx); @@ -1468,7 +1464,7 @@ static LLVMValueRef ptlang_ir_builder_exp(ptlang_ast_exp exp, ptlang_ir_builder_ { return ptr; } - LLVMTypeRef t = ptlang_ir_builder_type(type, ctx); + LLVMTypeRef t = ptlang_ir_builder_type(type, ctx, LLVMGetGlobalContext()); return LLVMBuildLoad2(ctx->builder, t, ptr, "loadvar"); } case PTLANG_AST_EXP_INTEGER: @@ -1494,8 +1490,9 @@ static LLVMValueRef ptlang_ir_builder_exp(ptlang_ast_exp exp, ptlang_ir_builder_ ptlang_ast_type type = ptlang_ir_builder_exp_type(exp, ctx); - LLVMValueRef value = LLVMConstIntOfStringAndSize(ptlang_ir_builder_type(type, ctx), - exp->content.str_prepresentation, str_len, 10); + LLVMValueRef value = + LLVMConstIntOfStringAndSize(ptlang_ir_builder_type(type, ctx, LLVMGetGlobalContext()), + exp->content.str_prepresentation, str_len, 10); ptlang_ast_type_destroy(type); return value; } @@ -1518,8 +1515,9 @@ static LLVMValueRef ptlang_ir_builder_exp(ptlang_ast_exp exp, ptlang_ir_builder_ ptlang_ast_type type = ptlang_ir_builder_exp_type(exp, ctx); - LLVMValueRef value = LLVMConstRealOfStringAndSize(ptlang_ir_builder_type(type, ctx), - exp->content.str_prepresentation, str_len); + LLVMValueRef value = + LLVMConstRealOfStringAndSize(ptlang_ir_builder_type(type, ctx, LLVMGetGlobalContext()), + exp->content.str_prepresentation, str_len); ptlang_ast_type_destroy(type); return value; } @@ -1527,7 +1525,7 @@ static LLVMValueRef ptlang_ir_builder_exp(ptlang_ast_exp exp, ptlang_ir_builder_ { ptlang_ast_type type = ptlang_ir_builder_exp_type(exp, ctx); ptlang_ast_decl *members = shget(ctx->struct_defs, type->content.name); - LLVMTypeRef struct_type = ptlang_ir_builder_type(type, ctx); + LLVMTypeRef struct_type = ptlang_ir_builder_type(type, ctx, LLVMGetGlobalContext()); ptlang_ast_type_destroy(type); LLVMValueRef *struct_members = ptlang_malloc(sizeof(LLVMValueRef) * arrlenu(members)); @@ -1561,7 +1559,8 @@ static LLVMValueRef ptlang_ir_builder_exp(ptlang_ast_exp exp, ptlang_ir_builder_ { ptlang_ast_type unnamed_type = ptlang_ir_builder_unname_type(exp->content.array.type, ctx); - LLVMTypeRef element_type = ptlang_ir_builder_type(unnamed_type->content.array.type, ctx); + LLVMTypeRef element_type = + ptlang_ir_builder_type(unnamed_type->content.array.type, ctx, LLVMGetGlobalContext()); LLVMValueRef *array_elements = ptlang_malloc(sizeof(LLVMValueRef) * unnamed_type->content.array.len); size_t i = 0; @@ -1604,7 +1603,8 @@ static LLVMValueRef ptlang_ir_builder_exp(ptlang_ast_exp exp, ptlang_ir_builder_ LLVMPositionBuilderAtEnd(ctx->builder, end_block); - LLVMValueRef phi = LLVMBuildPhi(ctx->builder, ptlang_ir_builder_type(type, ctx), "ternary"); + LLVMValueRef phi = + LLVMBuildPhi(ctx->builder, ptlang_ir_builder_type(type, ctx, LLVMGetGlobalContext()), "ternary"); ptlang_ast_type_destroy(type); @@ -1619,7 +1619,7 @@ static LLVMValueRef ptlang_ir_builder_exp(ptlang_ast_exp exp, ptlang_ir_builder_ case PTLANG_AST_EXP_STRUCT_MEMBER: { ptlang_ast_type type = ptlang_ir_builder_exp_type(exp, ctx); - LLVMTypeRef ret_type = ptlang_ir_builder_type(type, ctx); + LLVMTypeRef ret_type = ptlang_ir_builder_type(type, ctx, LLVMGetGlobalContext()); ptlang_ast_type_destroy(type); LLVMValueRef as_ptr = ptlang_ir_builder_exp_ptr(exp, ctx); @@ -1648,7 +1648,7 @@ static LLVMValueRef ptlang_ir_builder_exp(ptlang_ast_exp exp, ptlang_ir_builder_ case PTLANG_AST_EXP_ARRAY_ELEMENT: { ptlang_ast_type type = ptlang_ir_builder_exp_type(exp, ctx); - LLVMTypeRef ret_type = ptlang_ir_builder_type(type, ctx); + LLVMTypeRef ret_type = ptlang_ir_builder_type(type, ctx, LLVMGetGlobalContext()); ptlang_ast_type_destroy(type); LLVMValueRef as_ptr = ptlang_ir_builder_exp_ptr(exp, ctx); @@ -1669,11 +1669,18 @@ static LLVMValueRef ptlang_ir_builder_exp(ptlang_ast_exp exp, ptlang_ir_builder_ case PTLANG_AST_EXP_DEREFERENCE: { ptlang_ast_type type = ptlang_ir_builder_exp_type(exp->content.unary_operator, ctx); - LLVMTypeRef ret_type = ptlang_ir_builder_type(type->content.reference.type, ctx); + LLVMTypeRef ret_type = + ptlang_ir_builder_type(type->content.reference.type, ctx, LLVMGetGlobalContext()); ptlang_ast_type_destroy(type); return LLVMBuildLoad2(ctx->builder, ret_type, ptlang_ir_builder_exp(exp->content.unary_operator, ctx), "dereference"); } + case PTLANG_AST_EXP_BINARY: + { + size_t bytes = arrlenu(exp->content.binary); + + // TODO create array of LLVMValueRefs of bytes, bytecast to LLVMValueRef of ast_type + } } abort(); } @@ -1701,11 +1708,12 @@ static void ptlang_ir_builder_stmt_allocas(ptlang_ast_stmt stmt, ptlang_ir_build break; } case PTLANG_AST_STMT_DECL: - ptlang_ir_builder_scope_add(ctx->scope, stmt->content.decl->name.name, - LLVMBuildAlloca(ctx->builder, - ptlang_ir_builder_type(stmt->content.decl->type, ctx), - stmt->content.decl->name.name), - stmt->content.decl->type, false); + ptlang_ir_builder_scope_add( + ctx->scope, stmt->content.decl->name.name, + LLVMBuildAlloca(ctx->builder, + ptlang_ir_builder_type(stmt->content.decl->type, ctx, LLVMGetGlobalContext()), + stmt->content.decl->name.name), + stmt->content.decl->type, false); break; case PTLANG_AST_STMT_IF: case PTLANG_AST_STMT_WHILE: @@ -1957,7 +1965,8 @@ LLVMModuleRef ptlang_ir_builder_module(ptlang_ast_module ast_module, LLVMTargetD ptlang_malloc(sizeof(LLVMTypeRef) * arrlenu(ast_module->struct_defs[i]->members)); for (size_t j = 0; j < arrlenu(ast_module->struct_defs[i]->members); j++) { - elements[j] = ptlang_ir_builder_type(ast_module->struct_defs[i]->members[j]->type, &ctx); + elements[j] = ptlang_ir_builder_type(ast_module->struct_defs[i]->members[j]->type, &ctx, + LLVMGetGlobalContext()); } LLVMStructSetBody(structs[i], elements, arrlenu(ast_module->struct_defs[i]->members), false); ptlang_free(elements); @@ -1967,7 +1976,8 @@ LLVMModuleRef ptlang_ir_builder_module(ptlang_ast_module ast_module, LLVMTargetD LLVMValueRef *glob_decl_values = ptlang_malloc(sizeof(LLVMValueRef) * arrlenu(ast_module->declarations)); for (size_t i = 0; i < arrlenu(ast_module->declarations); i++) { - LLVMTypeRef t = ptlang_ir_builder_type(ast_module->declarations[i]->type, &ctx); + LLVMTypeRef t = + ptlang_ir_builder_type(ast_module->declarations[i]->type, &ctx, LLVMGetGlobalContext()); glob_decl_values[i] = LLVMAddGlobal(llvm_module, t, ast_module->declarations[i]->name.name); LLVMSetGlobalConstant(glob_decl_values[i], !ast_module->declarations[i]->writable); LLVMSetLinkage(glob_decl_values[i], @@ -1988,11 +1998,12 @@ LLVMModuleRef ptlang_ir_builder_module(ptlang_ast_module ast_module, LLVMTargetD { arrput(param_type_list, ptlang_ast_type_copy(ast_module->functions[i]->parameters[j]->type)); - param_types[j] = ptlang_ir_builder_type(ast_module->functions[i]->parameters[j]->type, &ctx); + param_types[j] = ptlang_ir_builder_type(ast_module->functions[i]->parameters[j]->type, &ctx, + LLVMGetGlobalContext()); } - LLVMTypeRef function_type = - LLVMFunctionType(ptlang_ir_builder_type(ast_module->functions[i]->return_type, &ctx), param_types, - arrlenu(ast_module->functions[i]->parameters), false); + LLVMTypeRef function_type = LLVMFunctionType( + ptlang_ir_builder_type(ast_module->functions[i]->return_type, &ctx, LLVMGetGlobalContext()), + param_types, arrlenu(ast_module->functions[i]->parameters), false); ptlang_free(param_types); functions[i] = LLVMAddFunction(llvm_module, ast_module->functions[i]->name.name, function_type); LLVMSetLinkage(functions[i], @@ -2047,16 +2058,20 @@ LLVMModuleRef ptlang_ir_builder_module(ptlang_ast_module ast_module, LLVMTargetD if (ast_module->functions[i]->return_type->type != PTLANG_AST_TYPE_VOID) { ctx.return_ptr = LLVMBuildAlloca( - ctx.builder, ptlang_ir_builder_type(ast_module->functions[i]->return_type, &ctx), "return"); + ctx.builder, + ptlang_ir_builder_type(ast_module->functions[i]->return_type, &ctx, LLVMGetGlobalContext()), + "return"); } LLVMValueRef *param_ptrs = ptlang_malloc(sizeof(LLVMValueRef) * arrlenu(ast_module->functions[i]->parameters)); for (size_t j = 0; j < arrlenu(ast_module->functions[i]->parameters); j++) { - param_ptrs[j] = LLVMBuildAlloca( - ctx.builder, ptlang_ir_builder_type(ast_module->functions[i]->parameters[j]->type, &ctx), - ast_module->functions[i]->parameters[j]->name.name); + param_ptrs[j] = + LLVMBuildAlloca(ctx.builder, + ptlang_ir_builder_type(ast_module->functions[i]->parameters[j]->type, &ctx, + LLVMGetGlobalContext()), + ast_module->functions[i]->parameters[j]->name.name); ptlang_ir_builder_scope_add(&function_scope, ast_module->functions[i]->parameters[j]->name.name, param_ptrs[j], ast_module->functions[i]->parameters[j]->type, false); } @@ -2108,7 +2123,8 @@ LLVMModuleRef ptlang_ir_builder_module(ptlang_ast_module ast_module, LLVMTargetD if (ast_module->functions[i]->return_type->type != PTLANG_AST_TYPE_VOID) { - LLVMTypeRef t = ptlang_ir_builder_type(ast_module->functions[i]->return_type, &ctx); + LLVMTypeRef t = + ptlang_ir_builder_type(ast_module->functions[i]->return_type, &ctx, LLVMGetGlobalContext()); LLVMValueRef return_value = LLVMBuildLoad2(ctx.builder, t, ctx.return_ptr, ""); LLVMBuildRet(ctx.builder, return_value); diff --git a/src/ptlang_ir_builder/ptlang_ir_builder.h b/src/ptlang_ir_builder/ptlang_ir_builder.h index 362435b..b48f85a 100644 --- a/src/ptlang_ir_builder/ptlang_ir_builder.h +++ b/src/ptlang_ir_builder/ptlang_ir_builder.h @@ -4,3 +4,35 @@ #include LLVMModuleRef ptlang_ir_builder_module(ptlang_ast_module module, LLVMTargetDataRef target_info); + +typedef struct ptlang_ir_builder_type_scope_s ptlang_ir_builder_type_scope; +typedef struct ptlang_ir_builder_scope_s ptlang_ir_builder_scope; + +typedef struct ptlang_ir_builder_struct_def_s ptlang_ir_builder_struct_def; + + +typedef struct ptlang_ir_builder_build_context_s +{ + LLVMBuilderRef builder; + LLVMModuleRef module; + LLVMValueRef function; + ptlang_ir_builder_type_scope *type_scope; + ptlang_ir_builder_scope *scope; + uint64_t scope_number; + ptlang_ir_builder_scope **scopes; + LLVMValueRef return_ptr; + LLVMBasicBlockRef return_block; + struct break_and_continue_block *break_and_continue_blocks; + ptlang_ast_type return_type; + ptlang_ir_builder_struct_def *struct_defs; + LLVMTargetDataRef target_info; + LLVMValueRef malloc_func; + LLVMValueRef realloc_func; + LLVMValueRef free_func; +} ptlang_ir_builder_build_context; + +LLVMTypeRef ptlang_ir_builder_type(ptlang_ast_type type, ptlang_ir_builder_build_context *ctx, + LLVMContextRef C); + + LLVMValueRef ptlang_ir_builder_exp(ptlang_ast_exp exp, ptlang_ir_builder_build_context *ctx); + diff --git a/src/ptlang_utils/ptlang_utils.h b/src/ptlang_utils/ptlang_utils.h index 02b504f..fb6772c 100644 --- a/src/ptlang_utils/ptlang_utils.h +++ b/src/ptlang_utils/ptlang_utils.h @@ -6,6 +6,7 @@ #include #define ptlang_malloc(size) size == 0 ? NULL : malloc(size) +#define ptlang_malloc_zero(size) size == 0 ? NULL : memset(ptlang_malloc(size), 0, size) #define ptlang_free(ptr) free(ptr) #define ptlang_realloc(ptr, size) size == 0 ? (free(ptr), NULL) : realloc(ptr, size) diff --git a/src/ptlang_verify/ptlang_verify.c b/src/ptlang_verify/ptlang_verify.c index 6fef97a..55e6ba2 100644 --- a/src/ptlang_verify/ptlang_verify.c +++ b/src/ptlang_verify/ptlang_verify.c @@ -112,6 +112,7 @@ static void ptlang_verify_statement(ptlang_ast_stmt statement, uint64_t nesting_ ? statement->content.control_flow2.condition : statement->content.control_flow.condition; ptlang_verify_exp(condition, ctx, errors); + // TODO check if condition is u1 if (condition != NULL && condition->ast_type->type != PTLANG_AST_TYPE_INTEGER && condition->ast_type->type != PTLANG_AST_TYPE_FLOAT) { @@ -631,14 +632,15 @@ static void ptlang_verify_exp(ptlang_ast_exp exp, ptlang_context *ctx, ptlang_er } else { - exp->ast_type = ptlang_ast_type_copy( - exp->content.function_call.function->ast_type->content.function.return_type); + exp->ast_type = ptlang_context_copy_unname_type( + exp->content.function_call.function->ast_type->content.function.return_type, + ctx->type_scope); if (arrlenu(exp->content.function_call.parameters) > arrlenu(exp->content.function_call.function->ast_type->content.function.parameters)) { - size_t message_len = sizeof("These parameters are to many."); + size_t message_len = sizeof("These parameters are too many."); char *message = ptlang_malloc(message_len); - memcpy(message, "These parameters are to many.", message_len); + memcpy(message, "These parameters are too many.", message_len); arrput( *errors, ((ptlang_error){ @@ -704,7 +706,7 @@ static void ptlang_verify_exp(ptlang_ast_exp exp, ptlang_context *ctx, ptlang_er } else { - exp->ast_type = ptlang_ast_type_copy(decl->type); + exp->ast_type = ptlang_context_copy_unname_type(decl->type, ctx->type_scope); } break; } @@ -1510,7 +1512,7 @@ static ptlang_ast_type ptlang_verify_unify_types(ptlang_ast_type type1, ptlang_a return ptlang_ast_type_copy(type1); if (ptlang_context_type_equals(type1, type2, ctx->type_scope)) - return type1; + return ptlang_ast_type_copy(type1); if (type1->type == PTLANG_AST_TYPE_REFERENCE && type2->type == PTLANG_AST_TYPE_REFERENCE) { @@ -1700,7 +1702,7 @@ static void ptlang_verify_exp_check_const(ptlang_ast_exp exp, ptlang_context *ct } break; } - case PTLANG_AST_EXP_ARRAY: + case PTLANG_AST_EXP_ARRAY: // TODO { for (size_t i = 0; i < arrlenu(exp->content.array.values); i++) { @@ -1742,7 +1744,8 @@ static void ptlang_verify_exp_check_const(ptlang_ast_exp exp, ptlang_context *ct static ptlang_ast_exp ptlang_verify_eval(ptlang_ast_exp exp, ptlang_context *ctx) { - ptlang_ast_exp substituted = ptlang_malloc(sizeof(struct ptlang_ast_exp_s));; + ptlang_ast_exp substituted = ptlang_malloc(sizeof(struct ptlang_ast_exp_s)); + ptlang_ast_exp evaluated = NULL; switch (exp->type) { case PTLANG_AST_EXP_ADDITION: @@ -1767,60 +1770,134 @@ static ptlang_ast_exp ptlang_verify_eval(ptlang_ast_exp exp, ptlang_context *ctx { ptlang_ast_exp left_value = ptlang_verify_eval(exp->content.binary_operator.left_value, ctx); ptlang_ast_exp right_value = ptlang_verify_eval(exp->content.binary_operator.right_value, ctx); - *substituted = (struct ptlang_ast_exp_s){ - .type = exp->type, - .content.binary_operator = - { - .left_value = left_value, - .right_value = right_value, - }, - .pos = exp->pos, - }; + *substituted = (struct ptlang_ast_exp_s){.type = exp->type, + .content.binary_operator = + { + .left_value = left_value, + .right_value = right_value, + }, + .pos = ptlang_ast_code_position_copy(exp->pos), + .ast_type = ptlang_ast_type_copy(exp->ast_type)}; + } + case PTLANG_AST_EXP_LENGTH: + { + // TODO } case PTLANG_AST_EXP_NEGATION: case PTLANG_AST_EXP_NOT: case PTLANG_AST_EXP_BITWISE_INVERSE: - case PTLANG_AST_EXP_LENGTH: - case PTLANG_AST_EXP_DEREFERENCE: + case PTLANG_AST_EXP_DEREFERENCE: // TODO { ptlang_ast_exp operand = ptlang_verify_eval(exp->content.unary_operator, ctx); *substituted = (struct ptlang_ast_exp_s){ .type = exp->type, .content.unary_operator = operand, + .pos = exp->pos, + .ast_type = exp->ast_type, }; } - // TODO case PTLANG_AST_EXP_VARIABLE: { // assumes that global variable was already initialized - substituted = ptlang_verify_eval(ptlang_decl_list_find_last(ctx->scope, exp->content.str_prepresentation)->init, ctx); + evaluated = ptlang_verify_eval( + ptlang_decl_list_find_last(ctx->scope, exp->content.str_prepresentation)->init, ctx); break; } case PTLANG_AST_EXP_INTEGER: case PTLANG_AST_EXP_FLOAT: { + evaluated = exp; break; } case PTLANG_AST_EXP_STRUCT: { + // TODO fill with defaults vals + evaluated = exp; + // ptlang_ast_struct_member_list struct_members = NULL; + // for (size_t i = 0; i < arrlenu(exp->content.struct_.members); i++) + // { + + // arrpush(struct_members, ((struct ptlang_ast_struct_member_s){ + // .pos = exp->content.struct_.members[i].pos, + // .str = exp->content.struct_.members[i].str, + // .exp = ptlang_verify_eval(exp->content.struct_.members[i].exp, + // ctx), + // })); + // } + // struct ptlang_ast_exp_struct_s struct_content = (struct ptlang_ast_exp_struct_s){ + // .type = exp->content.struct_.type, + // .members = struct_members, + // }; + // *substituted = (struct ptlang_ast_exp_s){ + // .type = exp->type, + // .content.struct_ = struct_content, + // .pos = exp->pos, + // .ast_type = exp->ast_type, + // }; break; } case PTLANG_AST_EXP_ARRAY: { + // TODO fill with defaults vals + evaluated = exp; + // ptlang_ast_exp *array_values = NULL; + // for (size_t i = 0; i < arrlenu(exp->content.array.values); i++) + // { + // arrpush(array_values, ptlang_verify_eval(exp->content.array.values[i], ctx)); + // } + // struct ptlang_ast_exp_array_s array_content = (struct ptlang_ast_exp_array_s){ + // .type = exp->content.array.values, + // .values = array_values, + // }; + // *substituted = (struct ptlang_ast_exp_s){ + // .type = exp->type, + // .content.array = array_content, + // .pos = exp->pos, + // .ast_type = exp->ast_type, + // }; break; } case PTLANG_AST_EXP_TERNARY: { + ptlang_ast_exp condition = ptlang_verify_eval(exp->content.ternary_operator.condition, ctx); + // TODO recheck cycles + if (condition->content.binary[0] == 0) + { + ptlang_ast_exp else_value = ptlang_verify_eval(exp->content.ternary_operator.else_value, ctx); + evaluated = else_value; + } + else + { + ptlang_ast_exp if_value = ptlang_verify_eval(exp->content.ternary_operator.if_value, ctx); + evaluated = if_value; + } + break; } case PTLANG_AST_EXP_CAST: { + ptlang_ast_exp value = ptlang_verify_eval(exp->content.cast.value, ctx); + *substituted = (struct ptlang_ast_exp_s){ + .type = exp->type, + .content.cast.type = exp->content.cast.type, + .content.cast.value = value, + .pos = exp->pos, + .ast_type = exp->ast_type, + }; break; } case PTLANG_AST_EXP_STRUCT_MEMBER: { + ptlang_ast_exp struct_ = ptlang_verify_eval(exp->content.struct_member.struct_, ctx); + // cycles should already have been checked + for (size_t i = 0; i < arrlenu(struct_->content.struct_.members); i++){ + if (0 == strcmp(struct_->content.struct_.members[i].str.name, exp->content.struct_member.member_name.name)){ + evaluated = ptlang_verify_eval(struct_->content.struct_.members[i].exp, ctx); + } + } break; } + // TODO other types case PTLANG_AST_EXP_ARRAY_ELEMENT: { break; @@ -1831,7 +1908,94 @@ static ptlang_ast_exp ptlang_verify_eval(ptlang_ast_exp exp, ptlang_context *ctx } } - ptlang_ast_exp evaluated = ptlang_eval_const_exp(substituted); + if (evaluated == NULL) + evaluated = ptlang_eval_const_exp(substituted); + ptlang_free(substituted); return evaluated; -} \ No newline at end of file +} + +ptlang_ast_exp ptlang_verify_get_default_value(ptlang_ast_type type, ptlang_context *ctx) +{ + switch (type->type) + { + case PTLANG_AST_TYPE_VOID: + case PTLANG_AST_TYPE_HEAP_ARRAY: + case PTLANG_AST_TYPE_FUNCTION: + case PTLANG_AST_TYPE_REFERENCE: + return NULL; + } + type = ptlang_context_copy_unname_type(type, ctx->type_scope); + ptlang_ast_exp default_value = ptlang_malloc(sizeof(struct ptlang_ast_exp_s)); + switch (type->type) + { + case PTLANG_AST_TYPE_INTEGER: + { + *default_value = (struct ptlang_ast_exp_s){ + .type = PTLANG_AST_EXP_BINARY, + .content.binary = ptlang_malloc_zero(((type->content.integer.size - 1) >> 3) + 1), + }; + } + case PTLANG_AST_TYPE_FLOAT: + { + *default_value = (struct ptlang_ast_exp_s){ + .type = PTLANG_AST_EXP_BINARY, + .content.binary = ptlang_malloc_zero(type->content.float_size >> 3), + }; + return default_value; + } + case PTLANG_AST_TYPE_ARRAY: + { + ptlang_ast_exp default_value = ptlang_malloc(sizeof(struct ptlang_ast_exp_s)); + ptlang_ast_exp *array_values = NULL; + for (size_t i = 0; i < type->content.array.len; i++) + { + ptlang_ast_exp element_default = ptlang_verify_get_default_value(type->content.array.type, ctx); + arrpush(array_values, element_default); + } + *default_value = (struct ptlang_ast_exp_s){ + .type = PTLANG_AST_EXP_ARRAY, + .content.array.type = ptlang_context_copy_unname_type(type->content.array.type, ctx->type_scope), + .content.array.values = array_values, + }; + } + case PTLANG_AST_TYPE_NAMED: + { + // Get struct def + char *name = type->content.name; + ptlang_ast_struct_def struct_def = NULL; + while (true) + { + ptlang_context_type_scope_entry entry = shget(ctx->type_scope, name); + if (entry.type == PTLANG_CONTEXT_TYPE_SCOPE_ENTRY_STRUCT) + { + struct_def = entry.value.struct_def; + break; + } + name = entry.value.ptlang_type->content.name; + } + + // Init members + ptlang_ast_struct_member_list struct_members = NULL; + for (size_t i = 0; i < arrlenu(struct_def->members); i++) + { + struct ptlang_ast_struct_member_s member_default = (struct ptlang_ast_struct_member_s){ + .exp = ptlang_verify_get_default_value(struct_def->members[i]->type, ctx), + .str = ptlang_ast_ident_copy(struct_def->members[i]->name), + .pos = NULL, + }; + + arrpush(struct_members, member_default); + } + *default_value = (struct ptlang_ast_exp_s){ + .type = PTLANG_AST_EXP_STRUCT, + .content.struct_.type = ptlang_context_copy_unname_type(type, ctx->type_scope), + .content.struct_.members = struct_members, + }; + } + // TODO other types + } + default_value->ast_type = type; + default_value->pos = NULL; + return default_value; +}