From 81e8c833e3156516f8b301795a3f897ec660a335 Mon Sep 17 00:00:00 2001 From: servostar Date: Fri, 2 Aug 2024 18:01:39 +0200 Subject: [PATCH] added stdlib tests --- lib/CMakeLists.txt | 6 ++- lib/src/math.gsc | 12 +++++ lib/src/math/api.h | 9 ++++ lib/src/math/impl.c | 10 ++++ lib/src/std.gsc | 3 ++ src/ast/ast.c | 1 + src/ast/ast.h | 1 + src/lex/lexer.l | 7 +++ src/llvm/llvm-ir/expr.c | 43 +++++++++------- src/llvm/llvm-ir/expr.h | 1 + src/llvm/llvm-ir/stmt.c | 70 ++++++++++++++------------ src/llvm/llvm-ir/types.c | 14 +++--- src/set/set.c | 86 +++++++++++++++++++++++-------- src/set/types.h | 6 ++- src/yacc/parser.y | 3 ++ tests/stdlib/build.toml | 18 +++++++ tests/stdlib/src/letters.gsc | 27 ++++++++++ tests/stdlib/src/matrix.gsc | 98 ++++++++++++++++++++++++++++++++++++ 18 files changed, 336 insertions(+), 79 deletions(-) create mode 100644 lib/src/math.gsc create mode 100644 lib/src/math/api.h create mode 100644 lib/src/math/impl.c create mode 100644 tests/stdlib/src/letters.gsc create mode 100644 tests/stdlib/src/matrix.gsc diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 097546c..69002ea 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -24,8 +24,12 @@ add_library(gscmem ${STDLIB_MEM_SOURCE_FILES}) file(GLOB_RECURSE STDLIB_OS_SOURCE_FILES src/os/*.c) add_library(gscos ${STDLIB_OS_SOURCE_FILES}) +file(GLOB_RECURSE STDLIB_MATH_SOURCE_FILES src/math/*.c) +add_library(gscmath ${STDLIB_MATH_SOURCE_FILES}) + # Complete standard library add_library(gscstd ${STDLIB_IO_SOURCE_FILES} ${STDLIB_MEM_SOURCE_FILES} - ${STDLIB_OS_SOURCE_FILES}) + ${STDLIB_OS_SOURCE_FILES} + ${STDLIB_MATH_SOURCE_FILES}) diff --git a/lib/src/math.gsc b/lib/src/math.gsc new file mode 100644 index 0000000..0af7470 --- /dev/null +++ b/lib/src/math.gsc @@ -0,0 +1,12 @@ +# Author: Sven Vogel +# Edited: 01.08.2024 +# License: GPL-2.0 + +# ,----------------------------------------. +# | Mathematical utilities | +# `----------------------------------------` + +include "def.gsc" + +# Compute the module of a by base b and store the result in c +fun mod(in u32: a, in u32: b)(out u32: c) diff --git a/lib/src/math/api.h b/lib/src/math/api.h new file mode 100644 index 0000000..5bf5ab4 --- /dev/null +++ b/lib/src/math/api.h @@ -0,0 +1,9 @@ + +#ifndef GEMSTONE_STD_LIB_MATH_H_ +#define GEMSTONE_STD_LIB_MATH_H_ + +#include + +void mod(u32 a, u32 b, u32* c); + +#endif //GEMSTONE_STD_LIB_MATH_H_ diff --git a/lib/src/math/impl.c b/lib/src/math/impl.c new file mode 100644 index 0000000..277fd21 --- /dev/null +++ b/lib/src/math/impl.c @@ -0,0 +1,10 @@ +// +// Created by servostar on 01.08.24. +// + +#include +#include + +void mod(u32 a, u32 b, u32* c) { + c[0] = a % b; +} diff --git a/lib/src/std.gsc b/lib/src/std.gsc index 36d6a75..89a2e02 100644 --- a/lib/src/std.gsc +++ b/lib/src/std.gsc @@ -14,3 +14,6 @@ include "io.gsc" # memory management include "mem.gsc" + +# mathematical utilities +include "math.gsc" \ No newline at end of file diff --git a/src/ast/ast.c b/src/ast/ast.c index 9f00f56..a0321bb 100644 --- a/src/ast/ast.c +++ b/src/ast/ast.c @@ -96,6 +96,7 @@ const char* AST_node_to_string(const struct AST_Node_t* node) { switch(node->kind) { case AST_Int: + case AST_Char: case AST_Float: case AST_String: case AST_Ident: diff --git a/src/ast/ast.h b/src/ast/ast.h index a7be0be..ea2b332 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -80,6 +80,7 @@ enum AST_SyntaxElement_t { AST_Dereference, AST_Reference, AST_Include, + AST_Char, AST_ELEMENT_COUNT }; diff --git a/src/lex/lexer.l b/src/lex/lexer.l index e955b0e..d98c1da 100644 --- a/src/lex/lexer.l +++ b/src/lex/lexer.l @@ -95,6 +95,13 @@ [0-9]*\.[0-9]+ {DEBUG("\"%s\" tokenized with \'ValFloat\'", yytext); yylval.string = mem_strdup(MemoryNamespaceLex, yytext); return(ValFloat);}; [a-zA-Z_0-9]+ {DEBUG("\"%s\" tokenized with \'Ident\'", yytext); yylval.string = mem_strdup(MemoryNamespaceLex, yytext); return(Ident); }; +'.' { + DEBUG("\"%s\" tokenized with \'Char\'", yytext); + yylval.string = mem_strdup(MemoryNamespaceLex, yytext + 1); + long int len = strlen(yytext); + yylval.string[len - 2] = '\0'; + return(ValChar); +} \"([^\"\n])*\" { yytext = yytext +1; yytext[yyleng - 2] = 0; diff --git a/src/llvm/llvm-ir/expr.c b/src/llvm/llvm-ir/expr.c index d3a3c66..d4129ea 100644 --- a/src/llvm/llvm-ir/expr.c +++ b/src/llvm/llvm-ir/expr.c @@ -20,14 +20,14 @@ BackendError impl_bitwise_operation(LLVMBackendCompileUnit *unit, if (operation->impl.bitwise == BitwiseNot) { // single operand rhs = g_array_index(operation->operands, Expression*, 0); - impl_expr(unit, scope, builder, rhs, FALSE, &llvm_rhs); + impl_expr(unit, scope, builder, rhs, FALSE, 0, &llvm_rhs); } else { // two operands lhs = g_array_index(operation->operands, Expression*, 0); - impl_expr(unit, scope, builder, lhs, FALSE, &llvm_lhs); + impl_expr(unit, scope, builder, lhs, FALSE, 0, &llvm_lhs); rhs = g_array_index(operation->operands, Expression*, 1); - impl_expr(unit, scope, builder, rhs, FALSE, &llvm_rhs); + impl_expr(unit, scope, builder, rhs, FALSE, 0, &llvm_rhs); } switch (operation->impl.bitwise) { @@ -80,14 +80,14 @@ BackendError impl_logical_operation(LLVMBackendCompileUnit *unit, if (operation->impl.logical == LogicalNot) { // single operand rhs = g_array_index(operation->operands, Expression*, 0); - impl_expr(unit, scope, builder, rhs, FALSE, &llvm_rhs); + impl_expr(unit, scope, builder, rhs, FALSE, 0, &llvm_rhs); } else { // two operands lhs = g_array_index(operation->operands, Expression*, 0); - impl_expr(unit, scope, builder, lhs, FALSE, &llvm_lhs); + impl_expr(unit, scope, builder, lhs, FALSE, 0, &llvm_lhs); rhs = g_array_index(operation->operands, Expression*, 1); - impl_expr(unit, scope, builder, rhs, FALSE, &llvm_rhs); + impl_expr(unit, scope, builder, rhs, FALSE, 0, &llvm_rhs); } switch (operation->impl.logical) { @@ -144,10 +144,10 @@ BackendError impl_relational_operation(LLVMBackendCompileUnit *unit, // two operands lhs = g_array_index(operation->operands, Expression*, 0); - impl_expr(unit, scope, builder, lhs, FALSE, &llvm_lhs); + impl_expr(unit, scope, builder, lhs, FALSE, 0, &llvm_lhs); rhs = g_array_index(operation->operands, Expression*, 1); - impl_expr(unit, scope, builder, rhs, FALSE, &llvm_rhs); + impl_expr(unit, scope, builder, rhs, FALSE, 0, &llvm_rhs); if (is_integral(rhs->result)) { // integral type @@ -206,14 +206,14 @@ BackendError impl_arithmetic_operation(LLVMBackendCompileUnit *unit, if (operation->impl.arithmetic == Negate) { // single operand rhs = g_array_index(operation->operands, Expression*, 0); - impl_expr(unit, scope, builder, rhs, FALSE, &llvm_rhs); + impl_expr(unit, scope, builder, rhs, FALSE, 0, &llvm_rhs); } else { // two operands lhs = g_array_index(operation->operands, Expression*, 0); - impl_expr(unit, scope, builder, lhs, FALSE, &llvm_lhs); + impl_expr(unit, scope, builder, lhs, FALSE, 0, &llvm_lhs); rhs = g_array_index(operation->operands, Expression*, 1); - impl_expr(unit, scope, builder, rhs, FALSE, &llvm_rhs); + impl_expr(unit, scope, builder, rhs, FALSE, 0, &llvm_rhs); } if (is_integral(rhs->result)) { @@ -297,7 +297,7 @@ BackendError impl_transmute(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, LLVMValueRef *llvm_result) { LLVMValueRef operand = NULL; - impl_expr(unit, scope, builder, transmute->operand, FALSE, &operand); + impl_expr(unit, scope, builder, transmute->operand, FALSE, 0, &operand); LLVMTypeRef target_type = NULL; BackendError err = get_type_impl(unit, scope->func_scope->global_scope, @@ -324,9 +324,10 @@ static LLVMBool is_type_signed(const Type *type) { BackendError impl_typecast(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, LLVMBuilderRef builder, TypeCast *typecast, + bool reference, LLVMValueRef *llvm_result) { LLVMValueRef operand = NULL; - impl_expr(unit, scope, builder, typecast->operand, FALSE, &operand); + impl_expr(unit, scope, builder, typecast->operand, reference, 0, &operand); LLVMTypeRef target_type = NULL; BackendError err = get_type_impl(unit, scope->func_scope->global_scope, @@ -434,7 +435,7 @@ BackendError impl_address_of(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope LLVMBuilderRef builder, AddressOf* addressOf, LLVMValueRef *llvm_result) { - BackendError err = impl_expr(unit, scope, builder, addressOf->variable, FALSE, llvm_result); + BackendError err = impl_expr(unit, scope, builder, addressOf->variable, TRUE, 0, llvm_result); if (err.kind != Success) { return err; @@ -445,11 +446,13 @@ BackendError impl_address_of(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope BackendError impl_deref(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, LLVMBuilderRef builder, Dereference* dereference, + bool reference, + uint32_t deref_depth, LLVMValueRef *llvm_result) { BackendError err; LLVMValueRef llvm_pointer = NULL; - err = impl_expr(unit, scope, builder, dereference->variable, TRUE, &llvm_pointer); + err = impl_expr(unit, scope, builder, dereference->variable, false, deref_depth + 1, &llvm_pointer); if (err.kind != Success) { return err; } @@ -461,14 +464,16 @@ BackendError impl_deref(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, } LLVMValueRef* index = mem_alloc(MemoryNamespaceLlvm, sizeof(LLVMValueRef)); - err = impl_expr(unit, scope, builder, dereference->index, FALSE, index); + err = impl_expr(unit, scope, builder, dereference->index, FALSE, deref_depth + 1, index); if (err.kind != Success) { return err; } *llvm_result = LLVMBuildGEP2(builder, llvm_deref_type, llvm_pointer, index, 1, "expr.deref.gep2"); - *llvm_result = LLVMBuildLoad2(builder, llvm_deref_type, *llvm_result, "expr.deref.load"); + if (!reference || deref_depth > 0) { + *llvm_result = LLVMBuildLoad2(builder, llvm_deref_type, *llvm_result, "expr.deref.load"); + } return err; } @@ -476,6 +481,7 @@ BackendError impl_deref(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, BackendError impl_expr(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, LLVMBuilderRef builder, Expression *expr, LLVMBool reference, + uint32_t deref_depth, LLVMValueRef *llvm_result) { DEBUG("implementing expression: %ld", expr->kind); BackendError err = SUCCESS; @@ -491,6 +497,7 @@ BackendError impl_expr(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, break; case ExpressionKindTypeCast: err = impl_typecast(unit, scope, builder, &expr->impl.typecast, + reference, llvm_result); break; case ExpressionKindOperation: @@ -513,6 +520,8 @@ BackendError impl_expr(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, break; case ExpressionKindDereference: err = impl_deref(unit, scope, builder, &expr->impl.dereference, + reference, + deref_depth, llvm_result); break; default: diff --git a/src/llvm/llvm-ir/expr.h b/src/llvm/llvm-ir/expr.h index 354fa16..7df2d39 100644 --- a/src/llvm/llvm-ir/expr.h +++ b/src/llvm/llvm-ir/expr.h @@ -13,6 +13,7 @@ BackendError impl_expr(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, LLVMBuilderRef builder, Expression *expr, LLVMBool reference, + uint32_t deref_depth, LLVMValueRef *llvm_result); #endif // LLVM_BACKEND_EXPR_H diff --git a/src/llvm/llvm-ir/stmt.c b/src/llvm/llvm-ir/stmt.c index 9f20c20..2bae20d 100644 --- a/src/llvm/llvm-ir/stmt.c +++ b/src/llvm/llvm-ir/stmt.c @@ -55,7 +55,7 @@ BackendError impl_storage_expr( case StorageExprKindDereference: LLVMValueRef index = NULL; - err = impl_expr(unit, scope, builder, expr->impl.dereference.index, false, &index); + err = impl_expr(unit, scope, builder, expr->impl.dereference.index, false, 0, &index); if (err.kind != Success) { return err; } @@ -73,7 +73,7 @@ BackendError impl_storage_expr( } } - if (expr->impl.dereference.array->kind == StorageExprKindDereference) { + if (true) { LLVMTypeRef deref_type = NULL; err = get_type_impl(unit, scope->func_scope->global_scope, expr->impl.dereference.array->target_type, &deref_type); if (err.kind != Success) { @@ -111,7 +111,7 @@ BackendError impl_assign_stmt( DEBUG("implementing assignment for variable: %p", assignment); LLVMValueRef llvm_value = NULL; - err = impl_expr(unit, scope, builder, assignment->value, false, &llvm_value); + err = impl_expr(unit, scope, builder, assignment->value, false, 0, &llvm_value); if (err.kind != Success) { return err; } @@ -182,7 +182,7 @@ BackendError impl_while(LLVMBackendCompileUnit *unit, LLVMPositionBuilderAtEnd(builder, while_cond_block); // Resolve condition in block to a variable LLVMValueRef cond_result = NULL; - err = impl_expr(unit, scope, builder, (Expression *) while_stmt->conditon, FALSE, &cond_result); + err = impl_expr(unit, scope, builder, (Expression *) while_stmt->conditon, FALSE, 0, &cond_result); if (err.kind != Success) { return err; } @@ -232,37 +232,43 @@ BackendError impl_func_call(LLVMBackendCompileUnit *unit, DEBUG("implementing function call..."); BackendError err = SUCCESS; - LLVMValueRef* arguments = mem_alloc(MemoryNamespaceLlvm, sizeof(LLVMValueRef) * call->expressions->len); + LLVMValueRef* arguments = NULL; - for (size_t i = 0; i < call->expressions->len; i++) { - Expression *arg = g_array_index(call->expressions, Expression*, i); + // prevent memory allocation when number of bytes would be zero + // avoid going of assertion in memory cache + if (call->expressions->len > 0) { + arguments = mem_alloc(MemoryNamespaceLlvm, sizeof(LLVMValueRef) * call->expressions->len); - GArray* param_list; - if (call->function->kind == FunctionDeclarationKind) { - param_list = call->function->impl.definition.parameter; - } else { - param_list = call->function->impl.declaration.parameter; - } + for (size_t i = 0; i < call->expressions->len; i++) { + Expression *arg = g_array_index(call->expressions, Expression*, i); - Parameter param = g_array_index(param_list, Parameter, i); - - LLVMValueRef llvm_arg = NULL; - err = impl_expr(unit, scope, builder, arg, is_parameter_out(¶m), &llvm_arg); - - if (err.kind != Success) { - break; - } - - if (is_parameter_out(¶m)) { - if ((arg->kind == ExpressionKindParameter && !is_parameter_out(arg->impl.parameter)) || arg->kind != ExpressionKindParameter) { - LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), 0, false); - LLVMTypeRef llvm_type = NULL; - get_type_impl(unit, scope->func_scope->global_scope, param.impl.declaration.type, &llvm_type); - llvm_arg = LLVMBuildGEP2(builder, llvm_type, llvm_arg, &index, 1, ""); + GArray* param_list; + if (call->function->kind == FunctionDeclarationKind) { + param_list = call->function->impl.definition.parameter; + } else { + param_list = call->function->impl.declaration.parameter; } - } - arguments[i] = llvm_arg; + Parameter param = g_array_index(param_list, Parameter, i); + + LLVMValueRef llvm_arg = NULL; + err = impl_expr(unit, scope, builder, arg, is_parameter_out(¶m), 0, &llvm_arg); + + if (err.kind != Success) { + break; + } + + if (is_parameter_out(¶m)) { + if ((arg->kind == ExpressionKindParameter && !is_parameter_out(arg->impl.parameter)) || arg->kind != ExpressionKindParameter) { + LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), 0, false); + LLVMTypeRef llvm_type = NULL; + get_type_impl(unit, scope->func_scope->global_scope, param.impl.declaration.type, &llvm_type); + llvm_arg = LLVMBuildGEP2(builder, llvm_type, llvm_arg, &index, 1, ""); + } + } + + arguments[i] = llvm_arg; + } } if (err.kind == Success) { @@ -291,7 +297,7 @@ impl_cond_block(LLVMBackendCompileUnit *unit, LLVMBuilderRef builder, LLVMLocalS "stmt.branch.cond"); LLVMPositionBuilderAtEnd(builder, *cond_block); // Resolve condition in block to a variable - err = impl_expr(unit, scope, builder, cond, FALSE, llvm_cond); + err = impl_expr(unit, scope, builder, cond, FALSE, 0, llvm_cond); if (err.kind == Success) { // build body of loop err = impl_basic_block(unit, builder, scope, block, start_body_block, end_body_block); @@ -441,7 +447,7 @@ BackendError impl_def(LLVMBackendCompileUnit *unit, } LLVMValueRef initial_value = NULL; - err = impl_expr(unit, scope, builder, def->initializer, FALSE, &initial_value); + err = impl_expr(unit, scope, builder, def->initializer, FALSE, 0, &initial_value); if (err.kind != Success) { return err; } diff --git a/src/llvm/llvm-ir/types.c b/src/llvm/llvm-ir/types.c index d5d2efa..1d0005e 100644 --- a/src/llvm/llvm-ir/types.c +++ b/src/llvm/llvm-ir/types.c @@ -6,16 +6,11 @@ #include #include #include -#include #include #define BASE_BYTES 4 #define BITS_PER_BYTE 8 -char* guid() { - return "uuid"; -} - static BackendError get_const_primitive_value(PrimitiveType primitive, LLVMTypeRef llvm_type, const char* value, @@ -27,6 +22,10 @@ static BackendError get_const_primitive_value(PrimitiveType primitive, case Float: *llvm_value = LLVMConstRealOfString(llvm_type, value); break; + case Char: + gunichar codepoint = g_utf8_get_char(value); + *llvm_value = LLVMConstInt(llvm_type, codepoint, false); + break; } return SUCCESS; @@ -116,9 +115,12 @@ BackendError impl_primtive_type(LLVMBackendCompileUnit* unit, DEBUG("implementing primtive float type..."); *llvm_type = LLVMFloatTypeInContext(unit->context); break; + case Char: + DEBUG("implementing primitive codepoint type..."); + *llvm_type = LLVMInt32TypeInContext(unit->context); + break; default: PANIC("invalid primitive type"); - break; } return SUCCESS; diff --git a/src/set/set.c b/src/set/set.c index 0d41b2e..a904bad 100644 --- a/src/set/set.c +++ b/src/set/set.c @@ -302,7 +302,7 @@ int set_get_type_impl(AST_NODE_PTR currentNode, Type **type) { } print_diagnostic(&AST_get_last_node(currentNode)->location, Error, - "Expected either primitive or composite type"); + "Expected either primitive or composite type: `%s`", AST_get_last_node(currentNode)->value); return SEMANTIC_ERROR; } @@ -332,14 +332,14 @@ int addVarToScope(Variable *variable); int createRef(AST_NODE_PTR currentNode, Type **reftype) { assert(currentNode != NULL); assert(currentNode->children->len == 1); - assert(AST_get_node(currentNode, 0)->kind == AST_Type); Type *type = mem_alloc(MemoryNamespaceSet, sizeof(Type)); Type *referenceType = mem_alloc(MemoryNamespaceSet, sizeof(Type)); referenceType->kind = TypeKindReference; referenceType->nodePtr = currentNode; - int signal = set_get_type_impl(AST_get_node(currentNode, 0), &type); + AST_NODE_PTR ast_type = AST_get_node(currentNode, 0); + int signal = set_get_type_impl(ast_type, &type); if (signal) { return SEMANTIC_ERROR; } @@ -496,8 +496,10 @@ char *type_to_string(Type *type) { case TypeKindPrimitive: if (type->impl.primitive == Int) { string = mem_strdup(MemoryNamespaceSet, "int"); - } else { + } else if (type->impl.primitive == Float){ string = mem_strdup(MemoryNamespaceSet, "float"); + } else if (type->impl.primitive == Char){ + string = mem_strdup(MemoryNamespaceSet, "codepoint"); } break; case TypeKindComposite: { @@ -637,6 +639,14 @@ TypeValue createTypeValue(AST_NODE_PTR currentNode) { case AST_Float: type->impl.primitive = Float; break; + case AST_Char: + // validate we have a single UTF-8 codepoint + if (g_utf8_strlen(currentNode->value, 4) != 1) { + print_diagnostic(¤tNode->location, Error, "Character must be UTF-8 codepoint"); + } + + type->impl.primitive = Char; + break; default: PANIC("Node is not an expression but from kind: %i", currentNode->kind); break; @@ -1331,13 +1341,13 @@ int createTypeCast(Expression *ParentExpression, AST_NODE_PTR currentNode) { && ParentExpression->impl.typecast.operand->result->kind != TypeKindPrimitive && ParentExpression->impl.typecast.operand->result->kind != TypeKindReference) { + print_diagnostic(¤tNode->location, Error, "cannot cast type: `%s`", type_to_string(ParentExpression->impl.typecast.operand->result)); return SEMANTIC_ERROR; } Type *target = mem_alloc(MemoryNamespaceSet, sizeof(Type)); int status = set_get_type_impl(AST_get_node(currentNode, 1), &target); if (status) { - print_diagnostic(&AST_get_node(currentNode, 1)->location, Error, "Unknown type"); return SEMANTIC_ERROR; } ParentExpression->impl.typecast.targetType = target; @@ -1461,6 +1471,7 @@ Expression *createExpression(AST_NODE_PTR currentNode) { switch (currentNode->kind) { case AST_Int: case AST_Float: + case AST_Char: expression->kind = ExpressionKindConstant; expression->impl.constant = createTypeValue(currentNode); expression->result = expression->impl.constant.type; @@ -1595,35 +1606,48 @@ Expression *createExpression(AST_NODE_PTR currentNode) { } bool compareTypes(Type *leftType, Type *rightType) { - if (leftType->kind != rightType->kind) { - return FALSE; - } - if (leftType->kind == TypeKindPrimitive) { + if (leftType->kind == TypeKindPrimitive && rightType->kind == TypeKindPrimitive) { return leftType->impl.primitive == rightType->impl.primitive; } + if (leftType->kind == TypeKindComposite) { - CompositeType leftComposite = leftType->impl.composite; - CompositeType rightComposite = leftType->impl.composite; - if (leftComposite.primitive != rightComposite.primitive) { + if (rightType->kind == TypeKindPrimitive) { + CompositeType leftComposite = leftType->impl.composite; + + if (leftComposite.scale == 1 && leftComposite.sign == Signed) { + return leftComposite.primitive == rightType->impl.primitive; + } + return FALSE; + + } else if (rightType->kind == TypeKindComposite) { + // Compare composites + + CompositeType leftComposite = leftType->impl.composite; + CompositeType rightComposite = rightType->impl.composite; + if (leftComposite.primitive != rightComposite.primitive) { + return FALSE; + } + if (leftComposite.sign != rightComposite.sign) { + return FALSE; + } + if (leftComposite.scale != rightComposite.scale) { + return FALSE; + } + return TRUE; } - if (leftComposite.sign != rightComposite.sign) { - return FALSE; - } - if (leftComposite.scale != rightComposite.scale) { - return FALSE; - } - return TRUE; + + return FALSE; } - if (leftType->kind == TypeKindBox) { + if (leftType->kind == TypeKindBox && rightType->kind == TypeKindBox) { if (leftType->impl.box != rightType->impl.box) { return FALSE; } return TRUE; } - if (leftType->kind == TypeKindReference) { + if (leftType->kind == TypeKindReference && rightType->kind == TypeKindReference) { bool result = compareTypes(leftType->impl.reference, rightType->impl.reference); return result; } @@ -1869,6 +1893,14 @@ int createBranch(Statement *ParentStatement, AST_NODE_PTR currentNode) { int getFunction(const char *name, Function **function); +Parameter get_param_from_func(Function* func, size_t index) { + if (func->kind == FunctionDeclarationKind) { + return g_array_index(func->impl.declaration.parameter, Parameter, index); + } else { + return g_array_index(func->impl.definition.parameter, Parameter, index); + } +} + int createfuncall(Statement *parentStatement, AST_NODE_PTR currentNode) { assert(currentNode != NULL); assert(currentNode->children->len == 2); @@ -1881,7 +1913,7 @@ int createfuncall(Statement *parentStatement, AST_NODE_PTR currentNode) { if (nameNode->kind == AST_Ident) { int result = getFunction(nameNode->value, &fun); if (result == SEMANTIC_ERROR) { - print_diagnostic(¤tNode->location, Error, "Unknown function: `%s`", nameNode); + print_diagnostic(¤tNode->location, Error, "Unknown function: `%s`", nameNode->value); return SEMANTIC_ERROR; } } @@ -1935,6 +1967,16 @@ int createfuncall(Statement *parentStatement, AST_NODE_PTR currentNode) { return SEMANTIC_ERROR; } + Parameter param = get_param_from_func(fun, i + currentExprList->children->len - j - 1); + + if (!compareTypes(expr->result, param.impl.declaration.type)) { + print_diagnostic(&expr_node->location, Error, + "parameter and argument `%s` type mismatch, expected `%s` got `%s`", + param.name, type_to_string(param.impl.declaration.type), type_to_string(expr->result)); + + return SEMANTIC_ERROR; + } + g_array_append_val(expressions, expr); } } diff --git a/src/set/types.h b/src/set/types.h index 828f14e..501b053 100644 --- a/src/set/types.h +++ b/src/set/types.h @@ -16,7 +16,9 @@ typedef enum PrimitiveType_t { // 4 byte signed integer in two's complement Int =0, // 4 byte IEEE-754 single precision - Float =1 + Float =1, + // 4 byte encoded UTF-8 codepoint + Char = 2, } PrimitiveType; /** @@ -236,6 +238,8 @@ typedef struct Function_t { const char * name; } Function; +Parameter get_param_from_func(Function* func, size_t index); + // .------------------------------------------------. // | Variables | // '------------------------------------------------' diff --git a/src/yacc/parser.y b/src/yacc/parser.y index 29dd70c..3408b94 100644 --- a/src/yacc/parser.y +++ b/src/yacc/parser.y @@ -6,6 +6,7 @@ #include #include #include + #include extern int yylineno; extern ModuleFile* current_file; @@ -82,6 +83,7 @@ %token Ident %token ValFloat %token ValStr +%token ValChar %token ValMultistr %token KeyShort %token KeyLong @@ -156,6 +158,7 @@ programbody: moduleimport {$$ = $1;} expr: ValFloat {$$ = AST_new_node(new_loc(), AST_Float, $1);} | ValInt {$$ = AST_new_node(new_loc(), AST_Int, $1);} + | ValChar {$$ = AST_new_node(new_loc(), AST_Char, $1);} | ValMultistr {$$ = AST_new_node(new_loc(), AST_String, $1);} | ValStr {$$ = AST_new_node(new_loc(), AST_String, $1);} | Ident {$$ = AST_new_node(new_loc(), AST_Ident, $1);} diff --git a/tests/stdlib/build.toml b/tests/stdlib/build.toml index 456b20e..749e8fa 100644 --- a/tests/stdlib/build.toml +++ b/tests/stdlib/build.toml @@ -13,3 +13,21 @@ mode = "application" output = "bin" archive = "archive" print_ir = true + +[target.letters] +link-paths = [ "../../bin/std" ] +import-paths = [ "../../lib/src" ] +root = "src/letters.gsc" +mode = "application" +output = "bin" +archive = "archive" +print_ir = true + +[target.matrix] +link-paths = [ "../../bin/std" ] +import-paths = [ "../../lib/src" ] +root = "src/matrix.gsc" +mode = "application" +output = "bin" +archive = "archive" +print_ir = true \ No newline at end of file diff --git a/tests/stdlib/src/letters.gsc b/tests/stdlib/src/letters.gsc new file mode 100644 index 0000000..ffdee3c --- /dev/null +++ b/tests/stdlib/src/letters.gsc @@ -0,0 +1,27 @@ + +import "std" + +cstr: EOL = "\n" + +fun main() { + + handle: stdin = nullHandle + getStdinHandle(stdin) + + handle: stdout = nullHandle + getStdoutHandle(stdout) + + ref u8: buffer = 0 as ref u8 + heapAlloc(256)(buffer) + + u32: bytesRead = 0 as u32 + readBytes(stdin, buffer, 8)(bytesRead) + + buffer[0] = 'a' as u8 + + u32: bytesWritten = 0 as u32 + writeBytes(stdout, buffer, bytesRead)(bytesWritten) + writeBytes(stdout, EOL, 1)(bytesWritten) + + heapFree(buffer) +} diff --git a/tests/stdlib/src/matrix.gsc b/tests/stdlib/src/matrix.gsc new file mode 100644 index 0000000..e14b1a3 --- /dev/null +++ b/tests/stdlib/src/matrix.gsc @@ -0,0 +1,98 @@ + +import "std" + +fun ulog10(in u32: num, out u32: log) +{ + u32: base = 1 as u32 + u32: count = 0 as u32 + + while base < num + { + base = base * 10 as u32 + count = count + 1 as u32 + } + + if count == 0 as u32 { + count = 1 as u32 + } + + log = count +} + +fun u32ToCstr(in u32: number)(out cstr: result, out u32: len) +{ + u32: bytes = 0 as u32 + ulog10(number, bytes) + + cstr: buf = 0 as cstr + heapAlloc(bytes)(buf as ref u8) + + u32: idx = bytes - 1 as u32 + u32: tmp = number + while (idx > 0 || idx == 0) + { + u32: digit = 0 as u32 + mod(tmp, 10 as u32, digit) + + buf[idx] = (digit + '0') as u8 + + tmp = tmp / 10 as u32 + idx = idx - 1 as u32 + } + + len = bytes + result = buf +} + +fun printU32(in u32: val) +{ + cstr: str = 0 as cstr + u32: len = 0 as u32 + + u32ToCstr(val)(str, len) + + handle: stdout = nullHandle + getStdoutHandle(stdout) + + u32: written = 0 as u32 + writeBytes(stdout, str, len, written) + + heapFree(str) + + writeBytes(stdout, " ", 1 as u32, written) +} + +fun test_matrix() +{ + ref ref u32: matrix + heapAlloc((8 * 4) as u32)(matrix as ref u8) + + u32: written = 0 as u32 + handle: stdout = nullHandle + getStdoutHandle(stdout) + + u32: idx = 0 as u32 + while idx < 4 { + heapAlloc((4 * 4) as u32)(matrix[idx] as ref u8) + + u32: idy = 0 as u32 + while idy < 4 { + matrix[idx][idy] = idy + + printU32(matrix[idx][idy]) + + idy = idy + 1 as u32 + } + writeBytes(stdout, "\n", 1 as u32, written) + + heapFree(matrix[idx] as ref u8) + idx = idx + 1 as u32 + } + + heapFree(matrix as ref u8) +} + +fun main() +{ + test_matrix() +}