added stdlib tests

This commit is contained in:
Sven Vogel 2024-08-02 18:01:39 +02:00
parent d9791cc0a2
commit 81e8c833e3
18 changed files with 336 additions and 79 deletions

View File

@ -24,8 +24,12 @@ add_library(gscmem ${STDLIB_MEM_SOURCE_FILES})
file(GLOB_RECURSE STDLIB_OS_SOURCE_FILES src/os/*.c) file(GLOB_RECURSE STDLIB_OS_SOURCE_FILES src/os/*.c)
add_library(gscos ${STDLIB_OS_SOURCE_FILES}) 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 # Complete standard library
add_library(gscstd add_library(gscstd
${STDLIB_IO_SOURCE_FILES} ${STDLIB_IO_SOURCE_FILES}
${STDLIB_MEM_SOURCE_FILES} ${STDLIB_MEM_SOURCE_FILES}
${STDLIB_OS_SOURCE_FILES}) ${STDLIB_OS_SOURCE_FILES}
${STDLIB_MATH_SOURCE_FILES})

12
lib/src/math.gsc Normal file
View File

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

9
lib/src/math/api.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef GEMSTONE_STD_LIB_MATH_H_
#define GEMSTONE_STD_LIB_MATH_H_
#include <def/api.h>
void mod(u32 a, u32 b, u32* c);
#endif //GEMSTONE_STD_LIB_MATH_H_

10
lib/src/math/impl.c Normal file
View File

@ -0,0 +1,10 @@
//
// Created by servostar on 01.08.24.
//
#include <math/api.h>
#include <capi.h>
void mod(u32 a, u32 b, u32* c) {
c[0] = a % b;
}

View File

@ -14,3 +14,6 @@ include "io.gsc"
# memory management # memory management
include "mem.gsc" include "mem.gsc"
# mathematical utilities
include "math.gsc"

View File

@ -96,6 +96,7 @@ const char* AST_node_to_string(const struct AST_Node_t* node) {
switch(node->kind) { switch(node->kind) {
case AST_Int: case AST_Int:
case AST_Char:
case AST_Float: case AST_Float:
case AST_String: case AST_String:
case AST_Ident: case AST_Ident:

View File

@ -80,6 +80,7 @@ enum AST_SyntaxElement_t {
AST_Dereference, AST_Dereference,
AST_Reference, AST_Reference,
AST_Include, AST_Include,
AST_Char,
AST_ELEMENT_COUNT AST_ELEMENT_COUNT
}; };

View File

@ -95,6 +95,13 @@
[0-9]*\.[0-9]+ {DEBUG("\"%s\" tokenized with \'ValFloat\'", yytext); yylval.string = mem_strdup(MemoryNamespaceLex, yytext); return(ValFloat);}; [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); }; [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])*\" { \"([^\"\n])*\" {
yytext = yytext +1; yytext = yytext +1;
yytext[yyleng - 2] = 0; yytext[yyleng - 2] = 0;

View File

@ -20,14 +20,14 @@ BackendError impl_bitwise_operation(LLVMBackendCompileUnit *unit,
if (operation->impl.bitwise == BitwiseNot) { if (operation->impl.bitwise == BitwiseNot) {
// single operand // single operand
rhs = g_array_index(operation->operands, Expression*, 0); 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 { } else {
// two operands // two operands
lhs = g_array_index(operation->operands, Expression*, 0); 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); 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) { switch (operation->impl.bitwise) {
@ -80,14 +80,14 @@ BackendError impl_logical_operation(LLVMBackendCompileUnit *unit,
if (operation->impl.logical == LogicalNot) { if (operation->impl.logical == LogicalNot) {
// single operand // single operand
rhs = g_array_index(operation->operands, Expression*, 0); 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 { } else {
// two operands // two operands
lhs = g_array_index(operation->operands, Expression*, 0); 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); 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) { switch (operation->impl.logical) {
@ -144,10 +144,10 @@ BackendError impl_relational_operation(LLVMBackendCompileUnit *unit,
// two operands // two operands
lhs = g_array_index(operation->operands, Expression*, 0); 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); 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)) { if (is_integral(rhs->result)) {
// integral type // integral type
@ -206,14 +206,14 @@ BackendError impl_arithmetic_operation(LLVMBackendCompileUnit *unit,
if (operation->impl.arithmetic == Negate) { if (operation->impl.arithmetic == Negate) {
// single operand // single operand
rhs = g_array_index(operation->operands, Expression*, 0); 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 { } else {
// two operands // two operands
lhs = g_array_index(operation->operands, Expression*, 0); 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); 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)) { if (is_integral(rhs->result)) {
@ -297,7 +297,7 @@ BackendError impl_transmute(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope,
LLVMValueRef *llvm_result) { LLVMValueRef *llvm_result) {
LLVMValueRef operand = NULL; 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; LLVMTypeRef target_type = NULL;
BackendError err = get_type_impl(unit, scope->func_scope->global_scope, 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, BackendError impl_typecast(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope,
LLVMBuilderRef builder, TypeCast *typecast, LLVMBuilderRef builder, TypeCast *typecast,
bool reference,
LLVMValueRef *llvm_result) { LLVMValueRef *llvm_result) {
LLVMValueRef operand = NULL; 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; LLVMTypeRef target_type = NULL;
BackendError err = get_type_impl(unit, scope->func_scope->global_scope, 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, LLVMBuilderRef builder, AddressOf* addressOf,
LLVMValueRef *llvm_result) { 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) { if (err.kind != Success) {
return err; return err;
@ -445,11 +446,13 @@ BackendError impl_address_of(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope
BackendError impl_deref(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, BackendError impl_deref(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope,
LLVMBuilderRef builder, Dereference* dereference, LLVMBuilderRef builder, Dereference* dereference,
bool reference,
uint32_t deref_depth,
LLVMValueRef *llvm_result) { LLVMValueRef *llvm_result) {
BackendError err; BackendError err;
LLVMValueRef llvm_pointer = NULL; 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) { if (err.kind != Success) {
return err; return err;
} }
@ -461,14 +464,16 @@ BackendError impl_deref(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope,
} }
LLVMValueRef* index = mem_alloc(MemoryNamespaceLlvm, sizeof(LLVMValueRef)); 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) { if (err.kind != Success) {
return err; return err;
} }
*llvm_result = LLVMBuildGEP2(builder, llvm_deref_type, llvm_pointer, index, 1, "expr.deref.gep2"); *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; return err;
} }
@ -476,6 +481,7 @@ BackendError impl_deref(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope,
BackendError impl_expr(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, BackendError impl_expr(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope,
LLVMBuilderRef builder, Expression *expr, LLVMBuilderRef builder, Expression *expr,
LLVMBool reference, LLVMBool reference,
uint32_t deref_depth,
LLVMValueRef *llvm_result) { LLVMValueRef *llvm_result) {
DEBUG("implementing expression: %ld", expr->kind); DEBUG("implementing expression: %ld", expr->kind);
BackendError err = SUCCESS; BackendError err = SUCCESS;
@ -491,6 +497,7 @@ BackendError impl_expr(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope,
break; break;
case ExpressionKindTypeCast: case ExpressionKindTypeCast:
err = impl_typecast(unit, scope, builder, &expr->impl.typecast, err = impl_typecast(unit, scope, builder, &expr->impl.typecast,
reference,
llvm_result); llvm_result);
break; break;
case ExpressionKindOperation: case ExpressionKindOperation:
@ -513,6 +520,8 @@ BackendError impl_expr(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope,
break; break;
case ExpressionKindDereference: case ExpressionKindDereference:
err = impl_deref(unit, scope, builder, &expr->impl.dereference, err = impl_deref(unit, scope, builder, &expr->impl.dereference,
reference,
deref_depth,
llvm_result); llvm_result);
break; break;
default: default:

View File

@ -13,6 +13,7 @@
BackendError impl_expr(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, BackendError impl_expr(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope,
LLVMBuilderRef builder, Expression *expr, LLVMBuilderRef builder, Expression *expr,
LLVMBool reference, LLVMBool reference,
uint32_t deref_depth,
LLVMValueRef *llvm_result); LLVMValueRef *llvm_result);
#endif // LLVM_BACKEND_EXPR_H #endif // LLVM_BACKEND_EXPR_H

View File

@ -55,7 +55,7 @@ BackendError impl_storage_expr(
case StorageExprKindDereference: case StorageExprKindDereference:
LLVMValueRef index = NULL; 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) { if (err.kind != Success) {
return err; return err;
} }
@ -73,7 +73,7 @@ BackendError impl_storage_expr(
} }
} }
if (expr->impl.dereference.array->kind == StorageExprKindDereference) { if (true) {
LLVMTypeRef deref_type = NULL; LLVMTypeRef deref_type = NULL;
err = get_type_impl(unit, scope->func_scope->global_scope, expr->impl.dereference.array->target_type, &deref_type); err = get_type_impl(unit, scope->func_scope->global_scope, expr->impl.dereference.array->target_type, &deref_type);
if (err.kind != Success) { if (err.kind != Success) {
@ -111,7 +111,7 @@ BackendError impl_assign_stmt(
DEBUG("implementing assignment for variable: %p", assignment); DEBUG("implementing assignment for variable: %p", assignment);
LLVMValueRef llvm_value = NULL; 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) { if (err.kind != Success) {
return err; return err;
} }
@ -182,7 +182,7 @@ BackendError impl_while(LLVMBackendCompileUnit *unit,
LLVMPositionBuilderAtEnd(builder, while_cond_block); LLVMPositionBuilderAtEnd(builder, while_cond_block);
// Resolve condition in block to a variable // Resolve condition in block to a variable
LLVMValueRef cond_result = NULL; 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) { if (err.kind != Success) {
return err; return err;
} }
@ -232,37 +232,43 @@ BackendError impl_func_call(LLVMBackendCompileUnit *unit,
DEBUG("implementing function call..."); DEBUG("implementing function call...");
BackendError err = SUCCESS; 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++) { // prevent memory allocation when number of bytes would be zero
Expression *arg = g_array_index(call->expressions, Expression*, i); // avoid going of assertion in memory cache
if (call->expressions->len > 0) {
arguments = mem_alloc(MemoryNamespaceLlvm, sizeof(LLVMValueRef) * call->expressions->len);
GArray* param_list; for (size_t i = 0; i < call->expressions->len; i++) {
if (call->function->kind == FunctionDeclarationKind) { Expression *arg = g_array_index(call->expressions, Expression*, i);
param_list = call->function->impl.definition.parameter;
} else {
param_list = call->function->impl.declaration.parameter;
}
Parameter param = g_array_index(param_list, Parameter, i); GArray* param_list;
if (call->function->kind == FunctionDeclarationKind) {
LLVMValueRef llvm_arg = NULL; param_list = call->function->impl.definition.parameter;
err = impl_expr(unit, scope, builder, arg, is_parameter_out(&param), &llvm_arg); } else {
param_list = call->function->impl.declaration.parameter;
if (err.kind != Success) {
break;
}
if (is_parameter_out(&param)) {
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; Parameter param = g_array_index(param_list, Parameter, i);
LLVMValueRef llvm_arg = NULL;
err = impl_expr(unit, scope, builder, arg, is_parameter_out(&param), 0, &llvm_arg);
if (err.kind != Success) {
break;
}
if (is_parameter_out(&param)) {
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) { if (err.kind == Success) {
@ -291,7 +297,7 @@ impl_cond_block(LLVMBackendCompileUnit *unit, LLVMBuilderRef builder, LLVMLocalS
"stmt.branch.cond"); "stmt.branch.cond");
LLVMPositionBuilderAtEnd(builder, *cond_block); LLVMPositionBuilderAtEnd(builder, *cond_block);
// Resolve condition in block to a variable // 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) { if (err.kind == Success) {
// build body of loop // build body of loop
err = impl_basic_block(unit, builder, scope, block, start_body_block, end_body_block); 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; 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) { if (err.kind != Success) {
return err; return err;
} }

View File

@ -6,16 +6,11 @@
#include <set/types.h> #include <set/types.h>
#include <sys/log.h> #include <sys/log.h>
#include <set/set.h> #include <set/set.h>
#include <stdlib.h>
#include <mem/cache.h> #include <mem/cache.h>
#define BASE_BYTES 4 #define BASE_BYTES 4
#define BITS_PER_BYTE 8 #define BITS_PER_BYTE 8
char* guid() {
return "uuid";
}
static BackendError get_const_primitive_value(PrimitiveType primitive, static BackendError get_const_primitive_value(PrimitiveType primitive,
LLVMTypeRef llvm_type, LLVMTypeRef llvm_type,
const char* value, const char* value,
@ -27,6 +22,10 @@ static BackendError get_const_primitive_value(PrimitiveType primitive,
case Float: case Float:
*llvm_value = LLVMConstRealOfString(llvm_type, value); *llvm_value = LLVMConstRealOfString(llvm_type, value);
break; break;
case Char:
gunichar codepoint = g_utf8_get_char(value);
*llvm_value = LLVMConstInt(llvm_type, codepoint, false);
break;
} }
return SUCCESS; return SUCCESS;
@ -116,9 +115,12 @@ BackendError impl_primtive_type(LLVMBackendCompileUnit* unit,
DEBUG("implementing primtive float type..."); DEBUG("implementing primtive float type...");
*llvm_type = LLVMFloatTypeInContext(unit->context); *llvm_type = LLVMFloatTypeInContext(unit->context);
break; break;
case Char:
DEBUG("implementing primitive codepoint type...");
*llvm_type = LLVMInt32TypeInContext(unit->context);
break;
default: default:
PANIC("invalid primitive type"); PANIC("invalid primitive type");
break;
} }
return SUCCESS; return SUCCESS;

View File

@ -302,7 +302,7 @@ int set_get_type_impl(AST_NODE_PTR currentNode, Type **type) {
} }
print_diagnostic(&AST_get_last_node(currentNode)->location, Error, 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; return SEMANTIC_ERROR;
} }
@ -332,14 +332,14 @@ int addVarToScope(Variable *variable);
int createRef(AST_NODE_PTR currentNode, Type **reftype) { int createRef(AST_NODE_PTR currentNode, Type **reftype) {
assert(currentNode != NULL); assert(currentNode != NULL);
assert(currentNode->children->len == 1); assert(currentNode->children->len == 1);
assert(AST_get_node(currentNode, 0)->kind == AST_Type);
Type *type = mem_alloc(MemoryNamespaceSet, sizeof(Type)); Type *type = mem_alloc(MemoryNamespaceSet, sizeof(Type));
Type *referenceType = mem_alloc(MemoryNamespaceSet, sizeof(Type)); Type *referenceType = mem_alloc(MemoryNamespaceSet, sizeof(Type));
referenceType->kind = TypeKindReference; referenceType->kind = TypeKindReference;
referenceType->nodePtr = currentNode; 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) { if (signal) {
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
@ -496,8 +496,10 @@ char *type_to_string(Type *type) {
case TypeKindPrimitive: case TypeKindPrimitive:
if (type->impl.primitive == Int) { if (type->impl.primitive == Int) {
string = mem_strdup(MemoryNamespaceSet, "int"); string = mem_strdup(MemoryNamespaceSet, "int");
} else { } else if (type->impl.primitive == Float){
string = mem_strdup(MemoryNamespaceSet, "float"); string = mem_strdup(MemoryNamespaceSet, "float");
} else if (type->impl.primitive == Char){
string = mem_strdup(MemoryNamespaceSet, "codepoint");
} }
break; break;
case TypeKindComposite: { case TypeKindComposite: {
@ -637,6 +639,14 @@ TypeValue createTypeValue(AST_NODE_PTR currentNode) {
case AST_Float: case AST_Float:
type->impl.primitive = Float; type->impl.primitive = Float;
break; break;
case AST_Char:
// validate we have a single UTF-8 codepoint
if (g_utf8_strlen(currentNode->value, 4) != 1) {
print_diagnostic(&currentNode->location, Error, "Character must be UTF-8 codepoint");
}
type->impl.primitive = Char;
break;
default: default:
PANIC("Node is not an expression but from kind: %i", currentNode->kind); PANIC("Node is not an expression but from kind: %i", currentNode->kind);
break; 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 != TypeKindPrimitive
&& ParentExpression->impl.typecast.operand->result->kind != TypeKindReference) { && ParentExpression->impl.typecast.operand->result->kind != TypeKindReference) {
print_diagnostic(&currentNode->location, Error, "cannot cast type: `%s`", type_to_string(ParentExpression->impl.typecast.operand->result));
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
Type *target = mem_alloc(MemoryNamespaceSet, sizeof(Type)); Type *target = mem_alloc(MemoryNamespaceSet, sizeof(Type));
int status = set_get_type_impl(AST_get_node(currentNode, 1), &target); int status = set_get_type_impl(AST_get_node(currentNode, 1), &target);
if (status) { if (status) {
print_diagnostic(&AST_get_node(currentNode, 1)->location, Error, "Unknown type");
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
ParentExpression->impl.typecast.targetType = target; ParentExpression->impl.typecast.targetType = target;
@ -1461,6 +1471,7 @@ Expression *createExpression(AST_NODE_PTR currentNode) {
switch (currentNode->kind) { switch (currentNode->kind) {
case AST_Int: case AST_Int:
case AST_Float: case AST_Float:
case AST_Char:
expression->kind = ExpressionKindConstant; expression->kind = ExpressionKindConstant;
expression->impl.constant = createTypeValue(currentNode); expression->impl.constant = createTypeValue(currentNode);
expression->result = expression->impl.constant.type; expression->result = expression->impl.constant.type;
@ -1595,35 +1606,48 @@ Expression *createExpression(AST_NODE_PTR currentNode) {
} }
bool compareTypes(Type *leftType, Type *rightType) { bool compareTypes(Type *leftType, Type *rightType) {
if (leftType->kind != rightType->kind) { if (leftType->kind == TypeKindPrimitive && rightType->kind == TypeKindPrimitive) {
return FALSE;
}
if (leftType->kind == TypeKindPrimitive) {
return leftType->impl.primitive == rightType->impl.primitive; return leftType->impl.primitive == rightType->impl.primitive;
} }
if (leftType->kind == TypeKindComposite) { if (leftType->kind == TypeKindComposite) {
CompositeType leftComposite = leftType->impl.composite; if (rightType->kind == TypeKindPrimitive) {
CompositeType rightComposite = leftType->impl.composite; CompositeType leftComposite = leftType->impl.composite;
if (leftComposite.primitive != rightComposite.primitive) {
if (leftComposite.scale == 1 && leftComposite.sign == Signed) {
return leftComposite.primitive == rightType->impl.primitive;
}
return FALSE; 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; return FALSE;
}
if (leftComposite.scale != rightComposite.scale) {
return FALSE;
}
return TRUE;
} }
if (leftType->kind == TypeKindBox) { if (leftType->kind == TypeKindBox && rightType->kind == TypeKindBox) {
if (leftType->impl.box != rightType->impl.box) { if (leftType->impl.box != rightType->impl.box) {
return FALSE; return FALSE;
} }
return TRUE; return TRUE;
} }
if (leftType->kind == TypeKindReference) { if (leftType->kind == TypeKindReference && rightType->kind == TypeKindReference) {
bool result = compareTypes(leftType->impl.reference, rightType->impl.reference); bool result = compareTypes(leftType->impl.reference, rightType->impl.reference);
return result; return result;
} }
@ -1869,6 +1893,14 @@ int createBranch(Statement *ParentStatement, AST_NODE_PTR currentNode) {
int getFunction(const char *name, Function **function); 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) { int createfuncall(Statement *parentStatement, AST_NODE_PTR currentNode) {
assert(currentNode != NULL); assert(currentNode != NULL);
assert(currentNode->children->len == 2); assert(currentNode->children->len == 2);
@ -1881,7 +1913,7 @@ int createfuncall(Statement *parentStatement, AST_NODE_PTR currentNode) {
if (nameNode->kind == AST_Ident) { if (nameNode->kind == AST_Ident) {
int result = getFunction(nameNode->value, &fun); int result = getFunction(nameNode->value, &fun);
if (result == SEMANTIC_ERROR) { if (result == SEMANTIC_ERROR) {
print_diagnostic(&currentNode->location, Error, "Unknown function: `%s`", nameNode); print_diagnostic(&currentNode->location, Error, "Unknown function: `%s`", nameNode->value);
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
} }
@ -1935,6 +1967,16 @@ int createfuncall(Statement *parentStatement, AST_NODE_PTR currentNode) {
return SEMANTIC_ERROR; 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); g_array_append_val(expressions, expr);
} }
} }

View File

@ -16,7 +16,9 @@ typedef enum PrimitiveType_t {
// 4 byte signed integer in two's complement // 4 byte signed integer in two's complement
Int =0, Int =0,
// 4 byte IEEE-754 single precision // 4 byte IEEE-754 single precision
Float =1 Float =1,
// 4 byte encoded UTF-8 codepoint
Char = 2,
} PrimitiveType; } PrimitiveType;
/** /**
@ -236,6 +238,8 @@ typedef struct Function_t {
const char * name; const char * name;
} Function; } Function;
Parameter get_param_from_func(Function* func, size_t index);
// .------------------------------------------------. // .------------------------------------------------.
// | Variables | // | Variables |
// '------------------------------------------------' // '------------------------------------------------'

View File

@ -6,6 +6,7 @@
#include <ast/ast.h> #include <ast/ast.h>
#include <sys/col.h> #include <sys/col.h>
#include <io/files.h> #include <io/files.h>
#include <glib.h>
extern int yylineno; extern int yylineno;
extern ModuleFile* current_file; extern ModuleFile* current_file;
@ -82,6 +83,7 @@
%token <string> Ident %token <string> Ident
%token <string> ValFloat %token <string> ValFloat
%token <string> ValStr %token <string> ValStr
%token <string> ValChar
%token <string> ValMultistr %token <string> ValMultistr
%token KeyShort %token KeyShort
%token KeyLong %token KeyLong
@ -156,6 +158,7 @@ programbody: moduleimport {$$ = $1;}
expr: ValFloat {$$ = AST_new_node(new_loc(), AST_Float, $1);} expr: ValFloat {$$ = AST_new_node(new_loc(), AST_Float, $1);}
| ValInt {$$ = AST_new_node(new_loc(), AST_Int, $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);} | ValMultistr {$$ = AST_new_node(new_loc(), AST_String, $1);}
| ValStr {$$ = 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);} | Ident {$$ = AST_new_node(new_loc(), AST_Ident, $1);}

View File

@ -13,3 +13,21 @@ mode = "application"
output = "bin" output = "bin"
archive = "archive" archive = "archive"
print_ir = true 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

View File

@ -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)
}

View File

@ -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()
}