aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorA404M <ahmadmahmoudiprogrammer@gmail.com>2025-05-23 23:58:30 +0330
committerA404M <ahmadmahmoudiprogrammer@gmail.com>2025-05-23 23:58:30 +0330
commit3c9aea642e3b2f4083705f1cd42fa911d35ee696 (patch)
treed990b2ffdb63161a9aef7cce20e5714461f86085
parent093c3bece426686b175db9ddaecd6abc8908fd87 (diff)
add way to call C functions
-rw-r--r--Makefile6
-rw-r--r--code/main.felan74
-rw-r--r--src/compiler/ast-tree.c605
-rw-r--r--src/compiler/ast-tree.h23
-rw-r--r--src/compiler/lexer.c20
-rw-r--r--src/compiler/lexer.h2
-rw-r--r--src/compiler/parser.c21
-rw-r--r--src/compiler/parser.h2
-rw-r--r--src/main.c3
-rw-r--r--src/runner/runner.c229
-rw-r--r--src/runner/runner.h8
-rw-r--r--src/utils/dl.c66
-rw-r--r--src/utils/dl.h8
13 files changed, 937 insertions, 130 deletions
diff --git a/Makefile b/Makefile
index 9819bce..a80a497 100644
--- a/Makefile
+++ b/Makefile
@@ -20,12 +20,12 @@ INC_DIRS := $(SRC_DIR)
INC_FLAGS := $(addprefix -I,$(INC_DIRS))
# OP_FLAG := -Ofast
-OP_FLAG := -O3
+# OP_FLAG := -O3
# OP_FLAG := -Oz
-# OP_FLAG := -g
+OP_FLAG := -g
# CFLAGS := $(INC_FLAGS) -Wall -Wextra -std=gnu23 -DPRINT_STATISTICS -DPRINT_COMPILE_TREE $(OP_FLAG)
-CFLAGS := $(INC_FLAGS) -Wall -Wextra -std=gnu23 -DPRINT_STATISTICS $(OP_FLAG)
+CFLAGS := $(INC_FLAGS) -Wall -Wextra -std=gnu23 -lffi -DPRINT_STATISTICS $(OP_FLAG)
# CFLAGS := $(INC_FLAGS) -Wall -Wextra -std=gnu23 $(OP_FLAG)
EXEC_FILE := $(BUILD_DIR)/$(PROJECT_NAME)
diff --git a/code/main.felan b/code/main.felan
index c2e573c..dffcf15 100644
--- a/code/main.felan
+++ b/code/main.felan
@@ -1,69 +1,11 @@
-@import("basic.felan");
-
-print :: (comptime t:type,v:t)->void{
- if @type_of(v) == u8
- @putc(v);
- else
- @putc('n');
-};
-
-fun0 :: () -> void {
- i := 0;
- while true {
- i += 1;
- if i == 7
- return;
- else if i % 2 == 0
- continue;
- else if i == 8
- break;
- print(u8,@cast(i,u8)+'0');
- print(u16,@cast(@cast(i,u8) + '0',u16));
- }
-};
-
-fun1 :: ()->void{
- a :[20]u8 = undefined;
- a[0] = '2';
- b := a;
- @putc(a[0]);
- @putc(b[0]);
-};
-
-fun2 :: ()->void{
- b := '2';
- c := &b;
- d := &c;
- d.*.* = '6';
- @putc(b);
- @putc(c.*);
- @putc(d.*.*);
-};
-
-fun3 :: ()->void{
- st :: struct{
- a : i64;
- };
- a : st = undefined;
- a.a = 2;
- @putc(@cast(a.a,u8)+'0');
-};
-
-fun4 :: ()->void{
- p := @size_of(123);
- @putc(@cast(p,u8)+'0');
-};
-
-/*
-libc :: @c_library("/lib/libc.so");
-
-putchar : (i8)->void : @c_function(libc,"putchar");
-*/
+libc :: @c_library("/lib/libc.so.6");
+putchar :: @c_function(libc,"putchar",(i32)->i32);
+puts :: @c_function(libc,"puts",(*u8)->i32);
main :: ()->void{
- // fun0();
- // fun1();
- // fun2();
- // fun3();
- fun4();
+ a :i32= 97;
+ a = putchar(a);
+ putchar(a);
+ b := "hello\0";
+ puts(&(b[0]));
};
diff --git a/src/compiler/ast-tree.c b/src/compiler/ast-tree.c
index 23d047f..628784a 100644
--- a/src/compiler/ast-tree.c
+++ b/src/compiler/ast-tree.c
@@ -157,6 +157,14 @@ AstTree AST_TREE_SHAPE_SHIFTER_TYPE = {
.str_end = NULL,
};
+AstTree AST_TREE_C_LIBRARY_TYPE = {
+ .token = AST_TREE_TOKEN_TYPE_C_LIBRARY,
+ .metadata = NULL,
+ .type = &AST_TREE_TYPE_TYPE,
+ .str_begin = NULL,
+ .str_end = NULL,
+};
+
AstTree AST_TREE_VOID_VALUE = {
.token = AST_TREE_TOKEN_VALUE_VOID,
.metadata = NULL,
@@ -220,6 +228,8 @@ const char *AST_TREE_TOKEN_STRINGS[] = {
"AST_TREE_TOKEN_TYPE_CODE",
"AST_TREE_TOKEN_TYPE_NAMESPACE",
"AST_TREE_TOKEN_TYPE_SHAPE_SHIFTER",
+ "AST_TREE_TOKEN_TYPE_C_LIBRARY",
+ "AST_TREE_TOKEN_TYPE_C_FUNCTION",
"AST_TREE_TOKEN_TYPE_BOOL",
"AST_TREE_TOKEN_VALUE_VOID",
@@ -230,6 +240,8 @@ const char *AST_TREE_TOKEN_STRINGS[] = {
"AST_TREE_TOKEN_VALUE_UNDEFINED",
"AST_TREE_TOKEN_VALUE_NAMESPACE",
"AST_TREE_TOKEN_VALUE_SHAPE_SHIFTER",
+ "AST_TREE_TOKEN_VALUE_C_LIBRARY",
+ "AST_TREE_TOKEN_VALUE_C_FUNCTION",
"AST_TREE_TOKEN_VALUE_INT",
"AST_TREE_TOKEN_VALUE_FLOAT",
"AST_TREE_TOKEN_VALUE_BOOL",
@@ -356,6 +368,7 @@ void astTreePrint(const AstTree *tree, int indent) {
case AST_TREE_TOKEN_TYPE_CODE:
case AST_TREE_TOKEN_TYPE_NAMESPACE:
case AST_TREE_TOKEN_TYPE_SHAPE_SHIFTER:
+ case AST_TREE_TOKEN_TYPE_C_LIBRARY:
case AST_TREE_TOKEN_TYPE_BOOL:
case AST_TREE_TOKEN_VALUE_VOID:
case AST_TREE_TOKEN_VALUE_NULL:
@@ -363,6 +376,8 @@ void astTreePrint(const AstTree *tree, int indent) {
case AST_TREE_TOKEN_VARIABLE_DEFINE:
case AST_TREE_TOKEN_RAW_VALUE_NOT_OWNED:
goto RETURN_SUCCESS;
+ case AST_TREE_TOKEN_TYPE_C_FUNCTION:
+ NOT_IMPLEMENTED;
case AST_TREE_TOKEN_KEYWORD_BREAK:
case AST_TREE_TOKEN_KEYWORD_CONTINUE: {
AstTreeLoopControl *meatadata = tree->metadata;
@@ -791,6 +806,7 @@ void astTreeDestroy(AstTree tree) {
case AST_TREE_TOKEN_TYPE_CODE:
case AST_TREE_TOKEN_TYPE_NAMESPACE:
case AST_TREE_TOKEN_TYPE_SHAPE_SHIFTER:
+ case AST_TREE_TOKEN_TYPE_C_LIBRARY:
case AST_TREE_TOKEN_TYPE_BOOL:
case AST_TREE_TOKEN_VALUE_NULL:
case AST_TREE_TOKEN_VALUE_UNDEFINED:
@@ -983,6 +999,25 @@ void astTreeDestroy(AstTree tree) {
free(metadata);
}
return;
+ case AST_TREE_TOKEN_TYPE_C_FUNCTION: {
+ AstTreeCFunctionType *metadata = tree.metadata;
+ astTreeDelete(metadata->funcType);
+ free(metadata);
+ }
+ return;
+ case AST_TREE_TOKEN_VALUE_C_LIBRARY: {
+ AstTreeCLibrary *metadata = tree.metadata;
+ free(metadata);
+ }
+ return;
+ case AST_TREE_TOKEN_VALUE_C_FUNCTION: {
+ AstTreeCFunction *metadata = tree.metadata;
+ astTreeDelete(metadata->library);
+ astTreeDelete(metadata->name);
+ astTreeDelete(metadata->funcType);
+ free(metadata);
+ }
+ return;
case AST_TREE_TOKEN_NONE:
}
printLog("token = %d", tree.token);
@@ -1026,7 +1061,8 @@ bool astTreeShouldDelete(AstTree *tree) {
tree != &AST_TREE_F32_TYPE && tree != &AST_TREE_F64_TYPE &&
tree != &AST_TREE_F128_TYPE && tree != &AST_TREE_CODE_TYPE &&
tree != &AST_TREE_NAMESPACE_TYPE &&
- tree != &AST_TREE_SHAPE_SHIFTER_TYPE && tree != &AST_TREE_VOID_VALUE;
+ tree != &AST_TREE_SHAPE_SHIFTER_TYPE &&
+ tree != &AST_TREE_C_LIBRARY_TYPE && tree != &AST_TREE_VOID_VALUE;
}
void astTreeRootDelete(AstTreeRoot *root) {
@@ -1098,6 +1134,7 @@ AstTree *copyAstTreeBack(AstTree *tree, AstTreeVariables oldVariables[],
case AST_TREE_TOKEN_TYPE_CODE:
case AST_TREE_TOKEN_TYPE_NAMESPACE:
case AST_TREE_TOKEN_TYPE_SHAPE_SHIFTER:
+ case AST_TREE_TOKEN_TYPE_C_LIBRARY:
return tree;
case AST_TREE_TOKEN_VALUE_VOID:
if (tree == &AST_TREE_VOID_VALUE) {
@@ -1554,6 +1591,49 @@ AstTree *copyAstTreeBack(AstTree *tree, AstTreeVariables oldVariables[],
variables_size, safetyCheck),
tree->str_begin, tree->str_end);
}
+ case AST_TREE_TOKEN_TYPE_C_FUNCTION: {
+ AstTreeCFunctionType *metadata = tree->metadata;
+ AstTreeCFunctionType *new_metadata = a404m_malloc(sizeof(*new_metadata));
+
+ new_metadata->funcType =
+ copyAstTreeBack(metadata->funcType, oldVariables, newVariables,
+ variables_size, safetyCheck);
+
+ return newAstTree(tree->token, new_metadata,
+ copyAstTreeBack(tree->type, oldVariables, newVariables,
+ variables_size, safetyCheck),
+ tree->str_begin, tree->str_end);
+ }
+ case AST_TREE_TOKEN_VALUE_C_LIBRARY: {
+ AstTreeCLibrary *metadata = tree->metadata;
+ AstTreeCLibrary *new_metadata = a404m_malloc(sizeof(*new_metadata));
+
+ new_metadata->dl = metadata->dl;
+
+ return newAstTree(tree->token, new_metadata,
+ copyAstTreeBack(tree->type, oldVariables, newVariables,
+ variables_size, safetyCheck),
+ tree->str_begin, tree->str_end);
+ }
+ case AST_TREE_TOKEN_VALUE_C_FUNCTION: {
+ AstTreeCFunction *metadata = tree->metadata;
+ AstTreeCFunction *new_metadata = a404m_malloc(sizeof(*new_metadata));
+
+ new_metadata->library =
+ copyAstTreeBack(metadata->library, oldVariables, newVariables,
+ variables_size, safetyCheck);
+ new_metadata->name =
+ copyAstTreeBack(metadata->name, oldVariables, newVariables,
+ variables_size, safetyCheck);
+ new_metadata->funcType =
+ copyAstTreeBack(metadata->funcType, oldVariables, newVariables,
+ variables_size, safetyCheck);
+
+ return newAstTree(tree->token, new_metadata,
+ copyAstTreeBack(tree->type, oldVariables, newVariables,
+ variables_size, safetyCheck),
+ tree->str_begin, tree->str_end);
+ }
case AST_TREE_TOKEN_NONE:
}
printLog("Bad token %d", tree->token);
@@ -2074,6 +2154,8 @@ AstTreeRoot *makeAstRoot(const ParserNode *parsedRoot, char *filePath) {
case PARSER_TOKEN_TYPE_CODE:
case PARSER_TOKEN_TYPE_NAMESPACE:
case PARSER_TOKEN_TYPE_SHAPE_SHIFTER:
+ case PARSER_TOKEN_TYPE_C_LIBRARY:
+ case PARSER_TOKEN_TYPE_C_FUNCTION:
case PARSER_TOKEN_TYPE_BOOL:
case PARSER_TOKEN_OPERATOR_POINTER:
case PARSER_TOKEN_OPERATOR_ADDRESS:
@@ -2268,6 +2350,10 @@ AstTree *astTreeParse(const ParserNode *parserNode) {
return &AST_TREE_NAMESPACE_TYPE;
case PARSER_TOKEN_TYPE_SHAPE_SHIFTER:
return &AST_TREE_SHAPE_SHIFTER_TYPE;
+ case PARSER_TOKEN_TYPE_C_LIBRARY:
+ return &AST_TREE_C_LIBRARY_TYPE;
+ case PARSER_TOKEN_TYPE_C_FUNCTION:
+ NOT_IMPLEMENTED;
case PARSER_TOKEN_TYPE_BOOL:
return &AST_TREE_BOOL_TYPE;
case PARSER_TOKEN_FUNCTION_CALL:
@@ -2364,8 +2450,8 @@ AstTree *astTreeParse(const ParserNode *parserNode) {
case PARSER_TOKEN_OPERATOR_MINUS:
return astTreeParseUnaryOperator(parserNode, AST_TREE_TOKEN_OPERATOR_MINUS);
case PARSER_TOKEN_OPERATOR_POINTER:
- return astTreeParseUnaryOperator(parserNode,
- AST_TREE_TOKEN_OPERATOR_POINTER);
+ return astTreeParseUnaryOperatorSingleChild(
+ parserNode, AST_TREE_TOKEN_OPERATOR_POINTER);
case PARSER_TOKEN_OPERATOR_ADDRESS:
return astTreeParseUnaryOperatorSingleChild(
parserNode, AST_TREE_TOKEN_OPERATOR_ADDRESS);
@@ -2495,6 +2581,8 @@ AstTree *astTreeParseFunction(const ParserNode *parserNode) {
case PARSER_TOKEN_TYPE_CODE:
case PARSER_TOKEN_TYPE_NAMESPACE:
case PARSER_TOKEN_TYPE_SHAPE_SHIFTER:
+ case PARSER_TOKEN_TYPE_C_LIBRARY:
+ case PARSER_TOKEN_TYPE_C_FUNCTION:
case PARSER_TOKEN_TYPE_BOOL:
case PARSER_TOKEN_KEYWORD_RETURN:
case PARSER_TOKEN_KEYWORD_BREAK:
@@ -2662,10 +2750,12 @@ AstTree *astTreeParseTypeFunction(const ParserNode *parserNode) {
argument.isComptime = false;
}
- if (!typeIsEqual(argument.type->type, &AST_TREE_TYPE_TYPE)) {
- printError(argument.str_begin, argument.str_end, "Type is incorrenct");
- return NULL;
- }
+ /*
+if (!typeIsEqual(argument.type->type, &AST_TREE_TYPE_TYPE)) {
+ printError(argument.str_begin, argument.str_end, "Type is incorrenct");
+ return NULL;
+}
+ */
if (typeFunction->arguments_size == arguments_size) {
arguments_size += arguments_size / 2 + 1;
@@ -2745,43 +2835,25 @@ AstTree *astTreeParseValue(const ParserNode *parserNode, AstTreeToken token,
AstTree *astTreeParseString(const ParserNode *parserNode) {
ParserNodeStringMetadata *node_metadata = parserNode->metadata;
- AstTreeObject *metadata = a404m_malloc(sizeof(*metadata));
-
- metadata->variables.size = node_metadata->end - node_metadata->begin;
- metadata->variables.data = a404m_malloc(metadata->variables.size *
- sizeof(*metadata->variables.data));
-
- for (size_t i = 0; i < metadata->variables.size; ++i) {
- AstTreeInt *cellMetadata = a404m_malloc(sizeof(*cellMetadata));
- *cellMetadata = node_metadata->begin[i];
-
- metadata->variables.data[i] =
- a404m_malloc(sizeof(*metadata->variables.data[i]));
- metadata->variables.data[i]->isConst = true;
- metadata->variables.data[i]->isLazy = false;
- metadata->variables.data[i]->name_begin = NULL;
- metadata->variables.data[i]->name_end = NULL;
- metadata->variables.data[i]->type = copyAstTree(&AST_TREE_U8_TYPE);
- metadata->variables.data[i]->value =
- newAstTree(AST_TREE_TOKEN_VALUE_INT, cellMetadata,
- copyAstTree(&AST_TREE_U8_TYPE), NULL, NULL);
- metadata->variables.data[i]->initValue = NULL;
- }
+ const size_t size = node_metadata->end - node_metadata->begin;
+ AstTreeRawValue *metadata = a404m_malloc(size * sizeof(u8));
+ memcpy(metadata, node_metadata->begin, size);
AstTreeBracket *type_metadata = a404m_malloc(sizeof(*type_metadata));
type_metadata->operand = &AST_TREE_U8_TYPE;
- AstTreeInt *parameter_metadata = a404m_malloc(sizeof(*parameter_metadata));
- *parameter_metadata = metadata->variables.size;
- AstTree *parameter = newAstTree(AST_TREE_TOKEN_VALUE_INT, parameter_metadata,
- &AST_TREE_I64_TYPE, NULL, NULL);
+ AstTreeRawValue *parameter_metadata =
+ a404m_malloc(getSizeOfType(&AST_TREE_U64_TYPE));
+ *(u64 *)parameter_metadata = size;
+ AstTree *parameter = newAstTree(AST_TREE_TOKEN_RAW_VALUE, parameter_metadata,
+ &AST_TREE_U64_TYPE, NULL, NULL);
type_metadata->parameters.size = 1;
type_metadata->parameters.data = a404m_malloc(
type_metadata->parameters.size * sizeof(*type_metadata->parameters.data));
type_metadata->parameters.data[0] = parameter;
- return newAstTree(AST_TREE_TOKEN_VALUE_OBJECT, metadata,
+ return newAstTree(AST_TREE_TOKEN_RAW_VALUE, metadata,
newAstTree(AST_TREE_TOKEN_TYPE_ARRAY, type_metadata,
&AST_TREE_TYPE_TYPE, NULL, NULL),
parserNode->str_begin, parserNode->str_end);
@@ -3111,6 +3183,8 @@ AstTree *astTreeParseCurlyBracket(const ParserNode *parserNode) {
case PARSER_TOKEN_TYPE_CODE:
case PARSER_TOKEN_TYPE_NAMESPACE:
case PARSER_TOKEN_TYPE_SHAPE_SHIFTER:
+ case PARSER_TOKEN_TYPE_C_LIBRARY:
+ case PARSER_TOKEN_TYPE_C_FUNCTION:
case PARSER_TOKEN_TYPE_BOOL:
case PARSER_TOKEN_KEYWORD_RETURN:
case PARSER_TOKEN_KEYWORD_BREAK:
@@ -3359,7 +3433,8 @@ AstTree *astTreeParseBracket(const ParserNode *parserNode, AstTreeToken token) {
bool isFunction(AstTree *value) {
return value->type->token == AST_TREE_TOKEN_TYPE_FUNCTION ||
- value->type->token == AST_TREE_TOKEN_TYPE_SHAPE_SHIFTER;
+ value->type->token == AST_TREE_TOKEN_TYPE_SHAPE_SHIFTER ||
+ value->type->token == AST_TREE_TOKEN_TYPE_C_FUNCTION;
}
bool isShapeShifter(AstTreeFunction *function) {
@@ -3418,6 +3493,8 @@ bool isConst(AstTree *tree) {
case AST_TREE_TOKEN_TYPE_CODE:
case AST_TREE_TOKEN_TYPE_NAMESPACE:
case AST_TREE_TOKEN_TYPE_SHAPE_SHIFTER:
+ case AST_TREE_TOKEN_TYPE_C_LIBRARY:
+ case AST_TREE_TOKEN_TYPE_C_FUNCTION:
case AST_TREE_TOKEN_TYPE_BOOL:
case AST_TREE_TOKEN_VALUE_NULL:
case AST_TREE_TOKEN_VALUE_UNDEFINED:
@@ -3550,6 +3627,8 @@ AstTree *makeTypeOf(AstTree *value) {
case AST_TREE_TOKEN_TYPE_CODE:
case AST_TREE_TOKEN_TYPE_NAMESPACE:
case AST_TREE_TOKEN_TYPE_SHAPE_SHIFTER:
+ case AST_TREE_TOKEN_TYPE_C_LIBRARY:
+ case AST_TREE_TOKEN_TYPE_C_FUNCTION:
case AST_TREE_TOKEN_TYPE_BOOL:
case AST_TREE_TOKEN_OPERATOR_POINTER:
case AST_TREE_TOKEN_KEYWORD_STRUCT:
@@ -3852,7 +3931,17 @@ bool typeIsEqualBack(const AstTree *type0, const AstTree *type1) {
case AST_TREE_TOKEN_TYPE_CODE:
case AST_TREE_TOKEN_TYPE_NAMESPACE:
case AST_TREE_TOKEN_TYPE_SHAPE_SHIFTER:
+ case AST_TREE_TOKEN_TYPE_C_LIBRARY:
return type1->token == type0->token;
+ case AST_TREE_TOKEN_TYPE_C_FUNCTION: {
+ if (type1->token != type0->token) {
+ return false;
+ }
+ AstTreeCFunctionType *type0_metadata = type0->metadata;
+ AstTreeCFunctionType *type1_metadata = type1->metadata;
+
+ return typeIsEqualBack(type0_metadata->funcType, type1_metadata->funcType);
+ }
case AST_TREE_TOKEN_OPERATOR_POINTER: {
if (type1->token != type0->token) {
return false;
@@ -3980,6 +4069,8 @@ AstTree *getValue(AstTree *tree, bool copy) {
case AST_TREE_TOKEN_TYPE_CODE:
case AST_TREE_TOKEN_TYPE_NAMESPACE:
case AST_TREE_TOKEN_TYPE_SHAPE_SHIFTER:
+ case AST_TREE_TOKEN_TYPE_C_LIBRARY:
+ case AST_TREE_TOKEN_TYPE_C_FUNCTION:
case AST_TREE_TOKEN_TYPE_BOOL:
case AST_TREE_TOKEN_VALUE_NULL:
case AST_TREE_TOKEN_VALUE_UNDEFINED:
@@ -4124,6 +4215,8 @@ bool isIntType(AstTree *type) {
case AST_TREE_TOKEN_TYPE_CODE:
case AST_TREE_TOKEN_TYPE_NAMESPACE:
case AST_TREE_TOKEN_TYPE_SHAPE_SHIFTER:
+ case AST_TREE_TOKEN_TYPE_C_LIBRARY:
+ case AST_TREE_TOKEN_TYPE_C_FUNCTION:
case AST_TREE_TOKEN_TYPE_BOOL:
case AST_TREE_TOKEN_VALUE_VOID:
case AST_TREE_TOKEN_VALUE_NAMESPACE:
@@ -4223,6 +4316,8 @@ bool isFloatType(AstTree *type) {
case AST_TREE_TOKEN_TYPE_CODE:
case AST_TREE_TOKEN_TYPE_NAMESPACE:
case AST_TREE_TOKEN_TYPE_SHAPE_SHIFTER:
+ case AST_TREE_TOKEN_TYPE_C_LIBRARY:
+ case AST_TREE_TOKEN_TYPE_C_FUNCTION:
case AST_TREE_TOKEN_TYPE_BOOL:
case AST_TREE_TOKEN_VALUE_VOID:
case AST_TREE_TOKEN_VALUE_NAMESPACE:
@@ -4292,11 +4387,15 @@ bool isEqual(AstTree *left, AstTree *right) {
case AST_TREE_TOKEN_TYPE_CODE:
case AST_TREE_TOKEN_TYPE_NAMESPACE:
case AST_TREE_TOKEN_TYPE_SHAPE_SHIFTER:
+ case AST_TREE_TOKEN_TYPE_C_LIBRARY:
case AST_TREE_TOKEN_TYPE_BOOL:
case AST_TREE_TOKEN_VALUE_VOID:
case AST_TREE_TOKEN_VALUE_NULL:
case AST_TREE_TOKEN_VALUE_UNDEFINED:
return true;
+ case AST_TREE_TOKEN_TYPE_C_FUNCTION: {
+ NOT_IMPLEMENTED;
+ }
case AST_TREE_TOKEN_VALUE_NAMESPACE: {
AstTreeNamespace *left_metadata = left->metadata;
AstTreeNamespace *right_metadata = right->metadata;
@@ -4568,8 +4667,11 @@ bool setAllTypes(AstTree *tree, AstTreeSetTypesHelper helper,
case AST_TREE_TOKEN_TYPE_CODE:
case AST_TREE_TOKEN_TYPE_NAMESPACE:
case AST_TREE_TOKEN_TYPE_SHAPE_SHIFTER:
+ case AST_TREE_TOKEN_TYPE_C_LIBRARY:
case AST_TREE_TOKEN_VALUE_VOID:
return true;
+ case AST_TREE_TOKEN_TYPE_C_FUNCTION:
+ NOT_IMPLEMENTED;
case AST_TREE_TOKEN_VALUE_NAMESPACE:
NOT_IMPLEMENTED;
case AST_TREE_TOKEN_VALUE_BOOL:
@@ -4691,9 +4793,9 @@ bool setAllTypes(AstTree *tree, AstTreeSetTypesHelper helper,
case AST_TREE_TOKEN_BUILTIN_PUTC:
return setTypesBuiltinPutc(tree, helper, functionCall);
case AST_TREE_TOKEN_BUILTIN_C_LIBRARY:
- NOT_IMPLEMENTED;
+ return setTypesBuiltinCLibrary(tree, helper, functionCall);
case AST_TREE_TOKEN_BUILTIN_C_FUNCTION:
- NOT_IMPLEMENTED;
+ return setTypesBuiltinCFunction(tree, helper, functionCall);
case AST_TREE_TOKEN_TYPE_ARRAY:
return setTypesTypeArray(tree, helper);
case AST_TREE_TOKEN_OPERATOR_ARRAY_ACCESS:
@@ -5355,6 +5457,77 @@ bool setTypesFunctionCall(AstTree *tree, AstTreeSetTypesHelper _helper) {
AstTreeTypeFunction *function = metadata->function->type->metadata;
tree->type = copyAstTree(function->returnType);
+ } else if (metadata->function->type->token ==
+ AST_TREE_TOKEN_TYPE_C_FUNCTION) {
+ AstTreeCFunctionType *cFunction = metadata->function->type->metadata;
+ AstTreeTypeFunction *function = cFunction->funcType->metadata;
+ if (function == NULL) {
+ printError(tree->str_begin, tree->str_end, "Bad function");
+ return NULL;
+ } else if (function->arguments_size != metadata->parameters_size) {
+ printError(tree->str_begin, tree->str_end,
+ "Arguments doesn't match %ld != %ld", function->arguments_size,
+ metadata->parameters_size);
+ return NULL;
+ }
+
+ AstTreeFunctionCallParam initedArguments[function->arguments_size];
+ size_t initedArguments_size = function->arguments_size;
+
+ for (size_t i = 0; i < initedArguments_size; ++i) {
+ initedArguments[i].value = NULL;
+ }
+
+ for (size_t i = 0; i < metadata->parameters_size; ++i) {
+ AstTreeFunctionCallParam param = metadata->parameters[i];
+ if (param.nameBegin != param.nameEnd) {
+ const size_t param_name_size = param.nameEnd - param.nameBegin;
+ for (size_t j = 0; j < function->arguments_size; ++j) {
+ AstTreeTypeFunctionArgument arg = function->arguments[j];
+ if ((size_t)(arg.name_end - arg.name_begin) == param_name_size &&
+ strnEquals(arg.name_begin, param.nameBegin, param_name_size)) {
+ initedArguments[j] = param;
+ goto END_OF_NAMED_FOR2;
+ }
+ }
+ printError(param.value->str_begin, param.value->str_end,
+ "Argument not found");
+ return false;
+ }
+ END_OF_NAMED_FOR2:
+ }
+
+ for (size_t i = 0; i < metadata->parameters_size; ++i) {
+ AstTreeFunctionCallParam param = metadata->parameters[i];
+ if (param.nameBegin == param.nameEnd) {
+ for (size_t j = 0; j < function->arguments_size; ++j) {
+ // AstTreeTypeFunctionArgument arg = function->arguments[j];
+ if (initedArguments[j].value == NULL) {
+ initedArguments[j] = param;
+ goto END_OF_UNNAMED_FOR2;
+ }
+ }
+ printError(param.value->str_begin, param.value->str_end,
+ "Too many arguments");
+ return false;
+ }
+ END_OF_UNNAMED_FOR2:
+ }
+
+ for (size_t i = 0; i < function->arguments_size; ++i) {
+ AstTreeTypeFunctionArgument arg = function->arguments[i];
+ if (initedArguments[i].value == NULL) {
+ printError(arg.str_begin, arg.str_end, "Argument is not initialized");
+ return false;
+ }
+ }
+
+ for (size_t i = 0; i < initedArguments_size; ++i) {
+ metadata->parameters[i] = initedArguments[i];
+ }
+ tree->type = copyAstTree(function->returnType);
+ } else {
+ UNREACHABLE;
}
return true;
@@ -5530,12 +5703,6 @@ bool setTypesOperatorAddress(AstTree *tree, AstTreeSetTypesHelper helper) {
return false;
}
- if (metadata->token != AST_TREE_TOKEN_VARIABLE) {
- printError(tree->str_begin, tree->str_end,
- "Can only get address of a variable (for now)");
- return false;
- }
-
tree->type =
newAstTree(AST_TREE_TOKEN_OPERATOR_POINTER, copyAstTree(metadata->type),
&AST_TREE_TYPE_TYPE, tree->str_begin, tree->str_end);
@@ -6102,7 +6269,7 @@ bool setTypesBuiltinSizeOf(AstTree *tree, AstTreeSetTypesHelper helper,
if (type == NULL) {
return false;
- } else if (!typeIsEqual(type, &AST_TREE_TYPE_TYPE)) {
+ } else if (!typeIsEqual(type->type, &AST_TREE_TYPE_TYPE)) {
printError(type->str_begin, type->str_end,
"Type missmatch, the argument should be `type`");
return false;
@@ -6204,10 +6371,70 @@ bool setTypesBuiltinIsComptime(AstTree *tree, AstTreeSetTypesHelper helper) {
bool setTypesBuiltinStackAlloc(AstTree *tree, AstTreeSetTypesHelper helper,
AstTreeFunctionCall *functionCall) {
- (void)tree;
(void)helper;
- (void)functionCall;
- NOT_IMPLEMENTED;
+ if (functionCall->parameters_size == 1) {
+ AstTree *size = NULL;
+
+ static const char SIZE_STR[] = "size";
+ static const size_t SIZE_STR_SIZE =
+ sizeof(SIZE_STR) / sizeof(*SIZE_STR) - sizeof(*SIZE_STR);
+
+ for (size_t i = 0; i < functionCall->parameters_size; ++i) {
+ AstTreeFunctionCallParam param = functionCall->parameters[i];
+ const size_t param_name_size = param.nameEnd - param.nameBegin;
+
+ if (param_name_size == 0) {
+ if (size == NULL) {
+ size = param.value;
+ } else {
+ printError(param.value->str_begin, param.value->str_end,
+ "Bad paramter");
+ return false;
+ }
+ } else if (param_name_size == SIZE_STR_SIZE &&
+ strnEquals(param.nameBegin, SIZE_STR, SIZE_STR_SIZE) &&
+ size == NULL) {
+ size = param.value;
+ } else {
+ printError(param.value->str_begin, param.value->str_end,
+ "Bad paramter");
+ return false;
+ }
+ }
+
+ if (size == NULL) {
+ return false;
+ } else if (!typeIsEqual(size->type, &AST_TREE_U64_TYPE)) {
+ printError(size->str_begin, size->str_end,
+ "Type missmatch, the argument should be `u64`");
+ return false;
+ }
+
+ AstTreeTypeFunction *type_metadata = a404m_malloc(sizeof(*type_metadata));
+ type_metadata->arguments_size = 1;
+ type_metadata->arguments = a404m_malloc(type_metadata->arguments_size *
+ sizeof(*type_metadata->arguments));
+
+ type_metadata->returnType =
+ newAstTree(AST_TREE_TOKEN_OPERATOR_POINTER, &AST_TREE_VOID_TYPE,
+ &AST_TREE_TYPE_TYPE, NULL, NULL);
+
+ type_metadata->arguments[0] = (AstTreeTypeFunctionArgument){
+ .type = copyAstTree(&AST_TREE_TYPE_TYPE),
+ .name_begin = SIZE_STR,
+ .name_end = SIZE_STR + SIZE_STR_SIZE,
+ .str_begin = NULL,
+ .str_end = NULL,
+ .isComptime = false,
+ };
+
+ tree->type = newAstTree(AST_TREE_TOKEN_TYPE_FUNCTION, type_metadata,
+ &AST_TREE_TYPE_TYPE, NULL, NULL);
+ return true;
+ } else {
+ printError(tree->str_begin, tree->str_end, "Too many or too few arguments");
+ return false;
+ }
}
bool setTypesBuiltinHeapAlloc(AstTree *tree, AstTreeSetTypesHelper helper,
@@ -6294,6 +6521,8 @@ bool setTypesBuiltinUnary(AstTree *tree, AstTreeSetTypesHelper helper,
case AST_TREE_TOKEN_TYPE_CODE:
case AST_TREE_TOKEN_TYPE_NAMESPACE:
case AST_TREE_TOKEN_TYPE_SHAPE_SHIFTER:
+ case AST_TREE_TOKEN_TYPE_C_LIBRARY:
+ case AST_TREE_TOKEN_TYPE_C_FUNCTION:
case AST_TREE_TOKEN_TYPE_BOOL:
case AST_TREE_TOKEN_VALUE_VOID:
case AST_TREE_TOKEN_VALUE_NAMESPACE:
@@ -6571,6 +6800,194 @@ bool setTypesBuiltinPutc(AstTree *tree, AstTreeSetTypesHelper helper,
return true;
}
+bool setTypesBuiltinCLibrary(AstTree *tree, AstTreeSetTypesHelper helper,
+ AstTreeFunctionCall *functionCall) {
+ (void)helper;
+ if (functionCall->parameters_size == 1) {
+ AstTree *path = NULL;
+
+ static const char PATH_STR[] = "path";
+ static const size_t PATH_STR_SIZE =
+ sizeof(PATH_STR) / sizeof(*PATH_STR) - sizeof(*PATH_STR);
+
+ for (size_t i = 0; i < functionCall->parameters_size; ++i) {
+ AstTreeFunctionCallParam param = functionCall->parameters[i];
+ const size_t param_name_size = param.nameEnd - param.nameBegin;
+
+ if (param_name_size == 0) {
+ if (path == NULL) {
+ path = param.value;
+ } else {
+ printError(param.value->str_begin, param.value->str_end,
+ "Bad paramter");
+ return false;
+ }
+ } else if (param_name_size == PATH_STR_SIZE &&
+ strnEquals(param.nameBegin, PATH_STR, PATH_STR_SIZE) &&
+ path == NULL) {
+ path = param.value;
+ } else {
+ printError(param.value->str_begin, param.value->str_end,
+ "Bad paramter");
+ return false;
+ }
+ }
+
+ AstTree *path_type = makeStringType();
+
+ if (path == NULL) {
+ return false;
+ } else if (!typeIsEqual(path->type, path_type)) {
+ astTreeDelete(path_type);
+ printError(path->str_begin, path->str_end,
+ "Type missmatch, the argument should be `type`");
+ return false;
+ }
+
+ AstTreeTypeFunction *type_metadata = a404m_malloc(sizeof(*type_metadata));
+ type_metadata->arguments_size = 1;
+ type_metadata->arguments = a404m_malloc(type_metadata->arguments_size *
+ sizeof(*type_metadata->arguments));
+
+ type_metadata->returnType = copyAstTree(&AST_TREE_C_LIBRARY_TYPE);
+
+ type_metadata->arguments[0] = (AstTreeTypeFunctionArgument){
+ .type = path_type,
+ .name_begin = PATH_STR,
+ .name_end = PATH_STR + PATH_STR_SIZE,
+ .str_begin = NULL,
+ .str_end = NULL,
+ .isComptime = false,
+ };
+
+ tree->type = newAstTree(AST_TREE_TOKEN_TYPE_FUNCTION, type_metadata,
+ &AST_TREE_TYPE_TYPE, NULL, NULL);
+ return true;
+ } else {
+ printError(tree->str_begin, tree->str_end, "Too many or too few arguments");
+ return false;
+ }
+}
+
+bool setTypesBuiltinCFunction(AstTree *tree, AstTreeSetTypesHelper helper,
+ AstTreeFunctionCall *functionCall) {
+ (void)helper;
+ if (functionCall->parameters_size != 3) {
+ printError(tree->str_begin, tree->str_end, "Too many or too few arguments");
+ return false;
+ }
+ AstTree *library = NULL;
+ AstTree *name = NULL;
+ AstTree *funcType = NULL;
+
+ static char LIBRARY_STR[] = "library";
+ static const size_t LIBRARY_STR_SIZE =
+ sizeof(LIBRARY_STR) / sizeof(*LIBRARY_STR) - sizeof(*LIBRARY_STR);
+ static char NAME_STR[] = "name";
+ static const size_t NAME_STR_SIZE =
+ sizeof(NAME_STR) / sizeof(*NAME_STR) - sizeof(*NAME_STR);
+ static char FUNC_TYPE_STR[] = "func_type";
+ static const size_t FUNC_TYPE_STR_SIZE =
+ sizeof(FUNC_TYPE_STR) / sizeof(*FUNC_TYPE_STR) - sizeof(*FUNC_TYPE_STR);
+
+ for (size_t i = 0; i < functionCall->parameters_size; ++i) {
+ AstTreeFunctionCallParam param = functionCall->parameters[i];
+ const size_t param_name_size = param.nameEnd - param.nameBegin;
+
+ if (param_name_size == 0) {
+ if (library == NULL) {
+ library = param.value;
+ } else if (name == NULL) {
+ name = param.value;
+ } else if (funcType == NULL) {
+ funcType = param.value;
+ } else {
+ printError(param.value->str_begin, param.value->str_end,
+ "Bad paramter");
+ return false;
+ }
+ } else if (param_name_size == LIBRARY_STR_SIZE &&
+ strnEquals(param.nameBegin, LIBRARY_STR, LIBRARY_STR_SIZE) &&
+ library == NULL) {
+ library = param.value;
+ } else if (param_name_size == NAME_STR_SIZE &&
+ strnEquals(param.nameBegin, NAME_STR, NAME_STR_SIZE) &&
+ name == NULL) {
+ name = param.value;
+ } else if (param_name_size == FUNC_TYPE_STR_SIZE &&
+ strnEquals(param.nameBegin, FUNC_TYPE_STR, FUNC_TYPE_STR_SIZE) &&
+ library == NULL) {
+ funcType = param.value;
+ } else {
+ printError(param.value->str_begin, param.value->str_end, "Bad paramter");
+ return false;
+ }
+ }
+
+ AstTree *str_type = makeStringType();
+
+ if (library == NULL || name == NULL || funcType == NULL) {
+ return false;
+ } else if (!typeIsEqual(library->type, &AST_TREE_C_LIBRARY_TYPE)) {
+ printError(library->str_begin, library->str_end,
+ "library must have a type of `c_library`");
+ return false;
+ } else if (!typeIsEqual(name->type, str_type)) {
+ astTreeDelete(str_type);
+ printError(name->str_begin, name->str_end,
+ "name must have a type of `[]u8`");
+ return false;
+ } else if (funcType->token != AST_TREE_TOKEN_TYPE_FUNCTION) {
+ astTreeDelete(str_type);
+ printError(funcType->str_begin, funcType->str_end,
+ "func_type must have a type of `function type`");
+ return false;
+ }
+ astTreeDelete(str_type);
+
+ AstTreeTypeFunction *type_metadata = a404m_malloc(sizeof(*type_metadata));
+ type_metadata->arguments_size = 3;
+ type_metadata->arguments = a404m_malloc(type_metadata->arguments_size *
+ sizeof(*type_metadata->arguments));
+
+ AstTreeCFunctionType *retType = a404m_malloc(sizeof(*retType));
+ retType->funcType = copyAstTree(funcType);
+
+ type_metadata->returnType = newAstTree(
+ AST_TREE_TOKEN_TYPE_C_FUNCTION, retType, &AST_TREE_TYPE_TYPE, NULL, NULL);
+
+ type_metadata->arguments[0] = (AstTreeTypeFunctionArgument){
+ .type = copyAstTree(library->type),
+ .name_begin = LIBRARY_STR,
+ .name_end = LIBRARY_STR + LIBRARY_STR_SIZE,
+ .str_begin = NULL,
+ .str_end = NULL,
+ .isComptime = false,
+ };
+
+ type_metadata->arguments[1] = (AstTreeTypeFunctionArgument){
+ .type = copyAstTree(name->type),
+ .name_begin = NAME_STR,
+ .name_end = NAME_STR + NAME_STR_SIZE,
+ .str_begin = NULL,
+ .str_end = NULL,
+ .isComptime = false,
+ };
+
+ type_metadata->arguments[2] = (AstTreeTypeFunctionArgument){
+ .type = copyAstTree(funcType->type),
+ .name_begin = FUNC_TYPE_STR,
+ .name_end = FUNC_TYPE_STR + FUNC_TYPE_STR_SIZE,
+ .str_begin = NULL,
+ .str_end = NULL,
+ .isComptime = false,
+ };
+
+ tree->type = newAstTree(AST_TREE_TOKEN_TYPE_FUNCTION, type_metadata,
+ &AST_TREE_TYPE_TYPE, NULL, NULL);
+ return true;
+}
+
bool setTypesTypeArray(AstTree *tree, AstTreeSetTypesHelper helper) {
AstTreeBracket *metadata = tree->metadata;
@@ -6972,6 +7389,73 @@ AstTreeVariable *setTypesFindVariable(const char *name_begin,
astTreeVariableDelete(arguments.data[i]);
}
free(arguments.data);
+ } else if (var->type->token == AST_TREE_TOKEN_TYPE_C_FUNCTION) {
+ AstTreeCFunctionType *cFunction = var->type->metadata;
+ AstTreeTypeFunction *function = cFunction->funcType->metadata;
+
+ if (function->arguments_size != functionCall->parameters_size) {
+ continue;
+ }
+
+ AstTreeFunctionCallParam initedArguments[function->arguments_size];
+ size_t initedArguments_size = function->arguments_size;
+
+ for (size_t i = 0; i < initedArguments_size; ++i) {
+ initedArguments[i].value = NULL;
+ }
+
+ for (size_t i = 0; i < functionCall->parameters_size; ++i) {
+ AstTreeFunctionCallParam param = functionCall->parameters[i];
+ if (param.nameBegin != param.nameEnd) {
+ const size_t param_name_size = param.nameEnd - param.nameBegin;
+ for (size_t j = 0; j < function->arguments_size; ++j) {
+ AstTreeTypeFunctionArgument arg = function->arguments[j];
+ if ((size_t)(arg.name_end - arg.name_begin) == param_name_size &&
+ strnEquals(arg.name_begin, param.nameBegin,
+ param_name_size)) {
+ if (!typeIsEqual(arg.type, param.value->type) ||
+ (arg.isComptime && !isConst(param.value))) {
+ goto CONTINUE_OUTER;
+ }
+ initedArguments[j] = param;
+ goto END_OF_NAMED_FOR2;
+ }
+ }
+ goto CONTINUE_OUTER;
+ }
+ END_OF_NAMED_FOR2:
+ }
+
+ for (size_t i = 0; i < functionCall->parameters_size; ++i) {
+ AstTreeFunctionCallParam param = functionCall->parameters[i];
+ if (param.nameBegin == param.nameEnd) {
+ for (size_t j = 0; j < function->arguments_size; ++j) {
+ AstTreeTypeFunctionArgument arg = function->arguments[j];
+ if (initedArguments[j].value == NULL) {
+ if (!typeIsEqual(arg.type, param.value->type) ||
+ (arg.isComptime && !isConst(param.value))) {
+ goto CONTINUE_OUTER;
+ }
+ initedArguments[j] = param;
+ goto END_OF_UNNAMED_FOR2;
+ }
+ }
+ goto CONTINUE_OUTER;
+ }
+ END_OF_UNNAMED_FOR2:
+ }
+
+ for (size_t i = 0; i < function->arguments_size; ++i) {
+ if (initedArguments[i].value == NULL) {
+ goto CONTINUE_OUTER;
+ }
+ }
+ if (variable != NULL) {
+ printError(name_begin, name_end, "Multiple candidates found for %.*s",
+ (int)(name_end - name_begin), name_begin);
+ return NULL;
+ }
+ variable = var;
}
CONTINUE_OUTER:
}
@@ -6986,13 +7470,26 @@ AstTreeVariable *setTypesFindVariable(const char *name_begin,
}
char *u8ArrayToCString(AstTree *tree) {
- AstTreeObject *object = tree->metadata;
- char *str = a404m_malloc((object->variables.size + 1) * sizeof(*str));
- for (size_t i = 0; i < object->variables.size; ++i) {
- str[i] = *(AstTreeInt *)object->variables.data[i]->value->metadata;
+ if (tree->token == AST_TREE_TOKEN_RAW_VALUE ||
+ tree->token == AST_TREE_TOKEN_RAW_VALUE_NOT_OWNED) {
+ AstTreeRawValue *value = tree->metadata;
+ const size_t size = getSizeOfType(tree->type);
+
+ char *newValue = a404m_malloc((size + 1) * sizeof(*newValue));
+ memcpy(newValue, value, size);
+ newValue[size] = '\0';
+
+ return newValue;
+ } else if (tree->token == AST_TREE_TOKEN_VALUE_OBJECT) {
+ AstTreeObject *object = tree->metadata;
+ char *str = a404m_malloc((object->variables.size + 1) * sizeof(*str));
+ for (size_t i = 0; i < object->variables.size; ++i) {
+ str[i] = *(AstTreeInt *)object->variables.data[i]->value->metadata;
+ }
+ str[object->variables.size] = '\0';
+ return str;
}
- str[object->variables.size] = '\0';
- return str;
+ UNREACHABLE;
}
AstTree *makeStringType() {
@@ -7055,6 +7552,8 @@ size_t getSizeOfType(AstTree *type) {
case AST_TREE_TOKEN_TYPE_CODE:
case AST_TREE_TOKEN_TYPE_NAMESPACE:
case AST_TREE_TOKEN_TYPE_SHAPE_SHIFTER:
+ case AST_TREE_TOKEN_TYPE_C_LIBRARY:
+ case AST_TREE_TOKEN_TYPE_C_FUNCTION:
case AST_TREE_TOKEN_FUNCTION:
case AST_TREE_TOKEN_BUILTIN_CAST:
case AST_TREE_TOKEN_BUILTIN_TYPE_OF:
diff --git a/src/compiler/ast-tree.h b/src/compiler/ast-tree.h
index d05db7b..ff8529e 100644
--- a/src/compiler/ast-tree.h
+++ b/src/compiler/ast-tree.h
@@ -61,6 +61,8 @@ typedef enum AstTreeToken {
AST_TREE_TOKEN_TYPE_CODE,
AST_TREE_TOKEN_TYPE_NAMESPACE,
AST_TREE_TOKEN_TYPE_SHAPE_SHIFTER,
+ AST_TREE_TOKEN_TYPE_C_LIBRARY,
+ AST_TREE_TOKEN_TYPE_C_FUNCTION,
AST_TREE_TOKEN_TYPE_BOOL,
AST_TREE_TOKEN_VALUE_VOID,
AST_TREE_TOKEN_STATIC_VARS_END = AST_TREE_TOKEN_VALUE_VOID,
@@ -72,6 +74,8 @@ typedef enum AstTreeToken {
AST_TREE_TOKEN_VALUE_UNDEFINED,
AST_TREE_TOKEN_VALUE_NAMESPACE,
AST_TREE_TOKEN_VALUE_SHAPE_SHIFTER,
+ AST_TREE_TOKEN_VALUE_C_LIBRARY,
+ AST_TREE_TOKEN_VALUE_C_FUNCTION,
AST_TREE_TOKEN_VALUE_INT,
AST_TREE_TOKEN_VALUE_FLOAT,
AST_TREE_TOKEN_VALUE_BOOL,
@@ -139,6 +143,7 @@ extern AstTree AST_TREE_F128_TYPE;
extern AstTree AST_TREE_CODE_TYPE;
extern AstTree AST_TREE_NAMESPACE_TYPE;
extern AstTree AST_TREE_SHAPE_SHIFTER_TYPE;
+extern AstTree AST_TREE_C_LIBRARY_TYPE;
extern AstTree AST_TREE_VOID_VALUE;
typedef struct AstTreeVariable {
@@ -313,6 +318,20 @@ typedef struct AstTreeLoopControl {
typedef struct AstTreeRawValue {
} AstTreeRawValue;
+typedef struct AstTreeCFunctionType {
+ AstTree *funcType;
+} AstTreeCFunctionType;
+
+typedef struct AstTreeCLibrary {
+ void *dl;
+} AstTreeCLibrary;
+
+typedef struct AstTreeCFunction {
+ AstTree *library;
+ AstTree *name;
+ AstTree *funcType;
+} AstTreeCFunction;
+
#ifdef PRINT_COMPILE_TREE
void astTreePrint(const AstTree *tree, int indent);
void astTreeVariablePrint(const AstTreeVariable *variable, int indent);
@@ -477,6 +496,10 @@ bool setTypesBuiltinBinaryWithRet(AstTree *tree, AstTreeSetTypesHelper helper,
AstTree *retType);
bool setTypesBuiltinPutc(AstTree *tree, AstTreeSetTypesHelper helper,
AstTreeFunctionCall *functionCall);
+bool setTypesBuiltinCLibrary(AstTree *tree, AstTreeSetTypesHelper helper,
+ AstTreeFunctionCall *functionCall);
+bool setTypesBuiltinCFunction(AstTree *tree, AstTreeSetTypesHelper helper,
+ AstTreeFunctionCall *functionCall);
bool setTypesTypeArray(AstTree *tree, AstTreeSetTypesHelper helper);
bool setTypesArrayAccess(AstTree *tree, AstTreeSetTypesHelper helper);
bool setTypesAstFunction(AstTreeFunction *function,
diff --git a/src/compiler/lexer.c b/src/compiler/lexer.c
index 577b009..1fbba2f 100644
--- a/src/compiler/lexer.c
+++ b/src/compiler/lexer.c
@@ -56,6 +56,8 @@ const char *LEXER_TOKEN_STRINGS[] = {
"LEXER_TOKEN_KEYWORD_CODE",
"LEXER_TOKEN_KEYWORD_NAMESPACE",
"LEXER_TOKEN_KEYWORD_SHAPE_SHIFTER",
+ "LEXER_TOKEN_KEYWORD_C_LIBRARY",
+ "LEXER_TOKEN_KEYWORD_C_FUNCTION",
"LEXER_TOKEN_NUMBER",
"LEXER_TOKEN_CHAR",
"LEXER_TOKEN_STRING",
@@ -167,15 +169,18 @@ static const size_t LEXER_SYMBOL_SIZE =
sizeof(LEXER_SYMBOL_TOKENS) / sizeof(*LEXER_SYMBOL_TOKENS);
static const char *LEXER_KEYWORD_STRINGS[] = {
- "type", "void", "i8", "u8", "i16", "u16",
- "i32", "u32", "i64", "u64",
+ "type", "void", "i8", "u8",
+ "i16", "u16", "i32", "u32",
+ "i64", "u64",
#ifdef FLOAT_16_SUPPORT
"f16",
#endif
- "f32", "f64", "f128", "bool", "return", "true",
- "false", "if", "else", "while", "comptime", "null",
- "struct", "undefined", "code", "lazy", "namespace", "shape_shifter",
- "break", "continue",
+ "f32", "f64", "f128", "bool",
+ "return", "true", "false", "if",
+ "else", "while", "comptime", "null",
+ "struct", "undefined", "code", "lazy",
+ "namespace", "shape_shifter", "break", "continue",
+ "c_library", "c_function",
};
static const LexerToken LEXER_KEYWORD_TOKENS[] = {
LEXER_TOKEN_KEYWORD_TYPE, LEXER_TOKEN_KEYWORD_VOID,
@@ -196,6 +201,7 @@ static const LexerToken LEXER_KEYWORD_TOKENS[] = {
LEXER_TOKEN_KEYWORD_CODE, LEXER_TOKEN_KEYWORD_LAZY,
LEXER_TOKEN_KEYWORD_NAMESPACE, LEXER_TOKEN_KEYWORD_SHAPE_SHIFTER,
LEXER_TOKEN_KEYWORD_BREAK, LEXER_TOKEN_KEYWORD_CONTINUE,
+ LEXER_TOKEN_KEYWORD_C_LIBRARY, LEXER_TOKEN_KEYWORD_C_FUNCTION,
};
static const size_t LEXER_KEYWORD_SIZE =
sizeof(LEXER_KEYWORD_TOKENS) / sizeof(*LEXER_KEYWORD_TOKENS);
@@ -522,6 +528,8 @@ lexerPushClear(LexerNodeArray *array, size_t *array_size, char const *iter,
case LEXER_TOKEN_KEYWORD_SHAPE_SHIFTER:
case LEXER_TOKEN_KEYWORD_BREAK:
case LEXER_TOKEN_KEYWORD_CONTINUE:
+ case LEXER_TOKEN_KEYWORD_C_LIBRARY:
+ case LEXER_TOKEN_KEYWORD_C_FUNCTION:
if (*array_size == array->size) {
*array_size += 1 + *array_size / 2;
array->data =
diff --git a/src/compiler/lexer.h b/src/compiler/lexer.h
index 3523a5f..e56617f 100644
--- a/src/compiler/lexer.h
+++ b/src/compiler/lexer.h
@@ -58,6 +58,8 @@ typedef enum LexerToken {
LEXER_TOKEN_KEYWORD_CODE,
LEXER_TOKEN_KEYWORD_NAMESPACE,
LEXER_TOKEN_KEYWORD_SHAPE_SHIFTER,
+ LEXER_TOKEN_KEYWORD_C_LIBRARY,
+ LEXER_TOKEN_KEYWORD_C_FUNCTION,
LEXER_TOKEN_NUMBER,
LEXER_TOKEN_CHAR,
LEXER_TOKEN_STRING,
diff --git a/src/compiler/parser.c b/src/compiler/parser.c
index ba7a4a0..f85c412 100644
--- a/src/compiler/parser.c
+++ b/src/compiler/parser.c
@@ -62,6 +62,8 @@ const char *PARSER_TOKEN_STRINGS[] = {
"PARSER_TOKEN_TYPE_CODE",
"PARSER_TOKEN_TYPE_NAMESPACE",
"PARSER_TOKEN_TYPE_SHAPE_SHIFTER",
+ "PARSER_TOKEN_TYPE_C_LIBRARY",
+ "PARSER_TOKEN_TYPE_C_FUNCTION",
"PARSER_TOKEN_KEYWORD_BREAK",
"PARSER_TOKEN_KEYWORD_CONTINUE",
@@ -287,6 +289,8 @@ void parserNodePrint(const ParserNode *node, int indent) {
case PARSER_TOKEN_TYPE_CODE:
case PARSER_TOKEN_TYPE_NAMESPACE:
case PARSER_TOKEN_TYPE_SHAPE_SHIFTER:
+ case PARSER_TOKEN_TYPE_C_LIBRARY:
+ case PARSER_TOKEN_TYPE_C_FUNCTION:
case PARSER_TOKEN_KEYWORD_NULL:
case PARSER_TOKEN_KEYWORD_UNDEFINED:
case PARSER_TOKEN_KEYWORD_BREAK:
@@ -595,6 +599,8 @@ void parserNodeDelete(ParserNode *node) {
case PARSER_TOKEN_TYPE_CODE:
case PARSER_TOKEN_TYPE_NAMESPACE:
case PARSER_TOKEN_TYPE_SHAPE_SHIFTER:
+ case PARSER_TOKEN_TYPE_C_LIBRARY:
+ case PARSER_TOKEN_TYPE_C_FUNCTION:
case PARSER_TOKEN_KEYWORD_NULL:
case PARSER_TOKEN_KEYWORD_UNDEFINED:
case PARSER_TOKEN_KEYWORD_BREAK:
@@ -943,6 +949,10 @@ ParserNode *parseNode(LexerNode *node, LexerNode *begin, LexerNode *end,
return parserNoMetadata(node, parent, PARSER_TOKEN_TYPE_NAMESPACE);
case LEXER_TOKEN_KEYWORD_SHAPE_SHIFTER:
return parserNoMetadata(node, parent, PARSER_TOKEN_TYPE_SHAPE_SHIFTER);
+ case LEXER_TOKEN_KEYWORD_C_LIBRARY:
+ return parserNoMetadata(node, parent, PARSER_TOKEN_TYPE_C_LIBRARY);
+ case LEXER_TOKEN_KEYWORD_C_FUNCTION:
+ return parserNoMetadata(node, parent, PARSER_TOKEN_TYPE_C_FUNCTION);
case LEXER_TOKEN_KEYWORD_NULL:
return parserNoMetadata(node, parent, PARSER_TOKEN_KEYWORD_NULL);
case LEXER_TOKEN_KEYWORD_UNDEFINED:
@@ -1720,6 +1730,8 @@ ParserNode *parserFunction(LexerNode *node, LexerNode *begin, LexerNode *end,
case PARSER_TOKEN_TYPE_CODE:
case PARSER_TOKEN_TYPE_NAMESPACE:
case PARSER_TOKEN_TYPE_SHAPE_SHIFTER:
+ case PARSER_TOKEN_TYPE_C_LIBRARY:
+ case PARSER_TOKEN_TYPE_C_FUNCTION:
case PARSER_TOKEN_KEYWORD_NULL:
case PARSER_TOKEN_KEYWORD_UNDEFINED:
case PARSER_TOKEN_KEYWORD_BREAK:
@@ -2261,6 +2273,8 @@ bool isExpression(ParserNode *node) {
case PARSER_TOKEN_TYPE_CODE:
case PARSER_TOKEN_TYPE_NAMESPACE:
case PARSER_TOKEN_TYPE_SHAPE_SHIFTER:
+ case PARSER_TOKEN_TYPE_C_LIBRARY:
+ case PARSER_TOKEN_TYPE_C_FUNCTION:
case PARSER_TOKEN_KEYWORD_NULL:
case PARSER_TOKEN_KEYWORD_UNDEFINED:
case PARSER_TOKEN_KEYWORD_BREAK:
@@ -2299,6 +2313,8 @@ bool isType(ParserNode *node) {
case PARSER_TOKEN_TYPE_CODE:
case PARSER_TOKEN_TYPE_NAMESPACE:
case PARSER_TOKEN_TYPE_SHAPE_SHIFTER:
+ case PARSER_TOKEN_TYPE_C_LIBRARY:
+ case PARSER_TOKEN_TYPE_C_FUNCTION:
case PARSER_TOKEN_TYPE_BOOL:
case PARSER_TOKEN_IDENTIFIER:
case PARSER_TOKEN_SYMBOL_PARENTHESIS:
@@ -2460,6 +2476,8 @@ bool isValue(ParserNode *node) {
case PARSER_TOKEN_TYPE_CODE:
case PARSER_TOKEN_TYPE_NAMESPACE:
case PARSER_TOKEN_TYPE_SHAPE_SHIFTER:
+ case PARSER_TOKEN_TYPE_C_LIBRARY:
+ case PARSER_TOKEN_TYPE_C_FUNCTION:
case PARSER_TOKEN_KEYWORD_NULL:
case PARSER_TOKEN_KEYWORD_UNDEFINED:
case PARSER_TOKEN_KEYWORD_IF:
@@ -2521,6 +2539,9 @@ char escapeChar(char const *begin, char const *end, bool *success) {
case '"':
*success = true;
return '\"';
+ case '0':
+ *success = true;
+ return '\0';
default:
*success = false;
return 0;
diff --git a/src/compiler/parser.h b/src/compiler/parser.h
index 1967dd6..6ef1427 100644
--- a/src/compiler/parser.h
+++ b/src/compiler/parser.h
@@ -59,6 +59,8 @@ typedef enum ParserToken {
PARSER_TOKEN_TYPE_CODE,
PARSER_TOKEN_TYPE_NAMESPACE,
PARSER_TOKEN_TYPE_SHAPE_SHIFTER,
+ PARSER_TOKEN_TYPE_C_LIBRARY,
+ PARSER_TOKEN_TYPE_C_FUNCTION,
PARSER_TOKEN_KEYWORD_BREAK,
PARSER_TOKEN_KEYWORD_CONTINUE,
diff --git a/src/main.c b/src/main.c
index 4d918dd..afede73 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,5 +1,6 @@
#include "compiler/ast-tree.h"
#include "runner/runner.h"
+#include "utils/dl.h"
#include "utils/file.h"
#include "utils/log.h"
#include <stdio.h>
@@ -70,6 +71,7 @@ static int run(const char *filePath) {
int main(int argc, char *argv[]) {
fileInit();
+ dynamicLibraryInit();
if (argc < 2) {
// compileRun("test/main.felan", "build/out", false);
@@ -79,6 +81,7 @@ int main(int argc, char *argv[]) {
}
const int ret = run(argv[1]);
+ dynamicLibraryDestroy();
fileDelete();
return ret;
}
diff --git a/src/runner/runner.c b/src/runner/runner.c
index faeb956..c5355cc 100644
--- a/src/runner/runner.c
+++ b/src/runner/runner.c
@@ -1,9 +1,13 @@
#include "runner.h"
#include "compiler/ast-tree.h"
+#include "utils/dl.h"
#include "utils/log.h"
#include "utils/memory.h"
#include "utils/string.h"
#include "utils/type.h"
+#include <dlfcn.h>
+#include <ffi.h>
+#include <iso646.h>
#include <stdatomic.h>
#include <stdio.h>
#include <stdlib.h>
@@ -932,12 +936,103 @@ AstTree *runAstTreeBuiltin(AstTree *tree, AstTreeScope *scope,
putchar(*(u8 *)arguments[0]->metadata);
return copyAstTree(&AST_TREE_VOID_VALUE);
}
+ case AST_TREE_TOKEN_BUILTIN_C_LIBRARY: {
+ AstTree *path = arguments[0];
+ char *str = u8ArrayToCString(path);
+ void *dl = dynamicLibraryOpen(str);
+
+ if (dl == NULL) {
+ printLog("Can't open dl %s", str);
+ UNREACHABLE;
+ }
+ free(str);
+
+ AstTreeCLibrary *metadata = a404m_malloc(sizeof(*metadata));
+ metadata->dl = dl;
+
+ return newAstTree(AST_TREE_TOKEN_VALUE_C_LIBRARY, metadata,
+ &AST_TREE_C_LIBRARY_TYPE, NULL, NULL);
+ }
+ case AST_TREE_TOKEN_BUILTIN_C_FUNCTION: {
+ AstTree *library = arguments[0];
+ AstTree *name = arguments[1];
+ AstTree *funcType = arguments[2];
+
+ AstTreeCFunction *metadata = a404m_malloc(sizeof(*metadata));
+ metadata->library = copyAstTree(library);
+ metadata->name = copyAstTree(name);
+ metadata->funcType = copyAstTree(funcType);
+
+ if (tree->type->token != AST_TREE_TOKEN_TYPE_FUNCTION) {
+ UNREACHABLE;
+ }
+
+ AstTreeTypeFunction *function = tree->type->metadata;
+
+ return newAstTree(AST_TREE_TOKEN_VALUE_C_FUNCTION, metadata,
+ copyAstTree(function->returnType), NULL, NULL);
+ }
case AST_TREE_TOKEN_BUILTIN_IMPORT:
default:
}
UNREACHABLE;
}
+AstTree *runAstTreeCFunction(AstTree *tree, AstTree **arguments,
+ size_t arguments_size) {
+ AstTreeCFunction *metadata = tree->metadata;
+ AstTreeCLibrary *lib = metadata->library->metadata;
+ char *name = u8ArrayToCString(metadata->name);
+ AstTreeTypeFunction *funcType = metadata->funcType->metadata;
+
+ void (*fun)() = dlsym(lib->dl, name);
+ free(name);
+ if (dlerror() != NULL) {
+ UNREACHABLE;
+ }
+
+ ffi_cif cif;
+ ffi_type *args[arguments_size];
+ void *values[arguments_size];
+ ffi_arg rc;
+
+ if (funcType->arguments_size != arguments_size) {
+ UNREACHABLE;
+ }
+
+ for (size_t i = 0; i < arguments_size; ++i) {
+ AstTreeTypeFunctionArgument arg = funcType->arguments[i];
+ args[i] = toFFIType(arg.type);
+ if (!typeIsEqual(arg.type, arguments[i]->type)) {
+ printLog("%s %s", AST_TREE_TOKEN_STRINGS[arg.type->token],
+ AST_TREE_TOKEN_STRINGS[arguments[i]->type->token]);
+ UNREACHABLE;
+ } else if (arguments[i]->token != AST_TREE_TOKEN_RAW_VALUE &&
+ arguments[i]->token != AST_TREE_TOKEN_RAW_VALUE_NOT_OWNED) {
+ UNREACHABLE;
+ }
+ values[i] = arguments[i]->metadata;
+ }
+
+ if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, arguments_size,
+ toFFIType(funcType->returnType), args) == FFI_OK) {
+ ffi_call(&cif, fun, &rc, values);
+ if (typeIsEqual(funcType->returnType, &AST_TREE_VOID_TYPE)) {
+ return &AST_TREE_VOID_TYPE;
+ } else {
+ size_t size = getSizeOfType(funcType->returnType);
+ AstTreeRawValue *value = a404m_malloc(size);
+ memcpy(value, &rc, size);
+ return newAstTree(AST_TREE_TOKEN_RAW_VALUE, value,
+ copyAstTree(funcType->returnType), NULL, NULL);
+ }
+ } else {
+ UNREACHABLE;
+ }
+
+ return &AST_TREE_VOID_VALUE;
+}
+
AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet,
bool isLeft, bool isComptime, u32 *breakCount,
bool *shouldContinue) {
@@ -998,6 +1093,23 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet,
astTreeDelete(args[i]);
}
}
+ } else if (function->token == AST_TREE_TOKEN_VALUE_C_FUNCTION) {
+ for (size_t i = 0; i < args_size; ++i) {
+ AstTreeFunctionCallParam param = metadata->parameters[i];
+ args[i] = getForVariable(param.value, scope, shouldRet, false,
+ isComptime, breakCount, shouldContinue, false);
+ if (discontinue(*shouldRet, *breakCount)) {
+ astTreeDelete(function);
+ for (size_t j = 0; j < i; ++j) {
+ astTreeDelete(args[i]);
+ }
+ return args[i];
+ }
+ }
+ result = runAstTreeCFunction(function, args, args_size);
+ for (size_t i = 0; i < args_size; ++i) {
+ astTreeDelete(args[i]);
+ }
} else {
UNREACHABLE;
}
@@ -1243,6 +1355,8 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet,
case AST_TREE_TOKEN_TYPE_CODE:
case AST_TREE_TOKEN_TYPE_NAMESPACE:
case AST_TREE_TOKEN_TYPE_SHAPE_SHIFTER:
+ case AST_TREE_TOKEN_TYPE_C_LIBRARY:
+ case AST_TREE_TOKEN_TYPE_C_FUNCTION:
case AST_TREE_TOKEN_VALUE_NULL:
case AST_TREE_TOKEN_VALUE_UNDEFINED:
case AST_TREE_TOKEN_VALUE_VOID:
@@ -1298,7 +1412,7 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet,
AstTreeRawValue *address = a404m_malloc(sizeof(void *));
*(void **)address = operand->metadata;
- AstTree *type = copyAstTree(operand->type);
+ AstTree *type = copyAstTree(expr->type);
astTreeDelete(operand);
return newAstTree(AST_TREE_TOKEN_RAW_VALUE, address, type, NULL, NULL);
@@ -1967,3 +2081,116 @@ AstTree *castTo(AstTree *tree, AstTree *to) {
UNREACHABLE;
}
}
+
+ffi_type *toFFIType(AstTree *type) {
+ switch (type->token) {
+ case AST_TREE_TOKEN_TYPE_VOID:
+ return &ffi_type_void;
+ case AST_TREE_TOKEN_TYPE_BOOL:
+ case AST_TREE_TOKEN_TYPE_U8:
+ return &ffi_type_uint8;
+ case AST_TREE_TOKEN_TYPE_I8:
+ return &ffi_type_sint8;
+ case AST_TREE_TOKEN_TYPE_I16:
+ return &ffi_type_sint16;
+ case AST_TREE_TOKEN_TYPE_U16:
+ return &ffi_type_uint16;
+ case AST_TREE_TOKEN_TYPE_I32:
+ return &ffi_type_sint32;
+ case AST_TREE_TOKEN_TYPE_U32:
+ return &ffi_type_uint32;
+ case AST_TREE_TOKEN_TYPE_I64:
+ return &ffi_type_sint64;
+ case AST_TREE_TOKEN_TYPE_U64:
+ return &ffi_type_uint64;
+ case AST_TREE_TOKEN_TYPE_F16:
+ NOT_IMPLEMENTED;
+ case AST_TREE_TOKEN_TYPE_F32:
+ return &ffi_type_float;
+ case AST_TREE_TOKEN_TYPE_F64:
+ return &ffi_type_double;
+ case AST_TREE_TOKEN_TYPE_F128:
+ return &ffi_type_longdouble;
+ case AST_TREE_TOKEN_OPERATOR_POINTER:
+ return &ffi_type_pointer;
+ case AST_TREE_TOKEN_TYPE_ARRAY:
+ case AST_TREE_TOKEN_TYPE_CODE:
+ case AST_TREE_TOKEN_TYPE_TYPE:
+ case AST_TREE_TOKEN_TYPE_FUNCTION:
+ case AST_TREE_TOKEN_TYPE_NAMESPACE:
+ case AST_TREE_TOKEN_TYPE_SHAPE_SHIFTER:
+ case AST_TREE_TOKEN_TYPE_C_LIBRARY:
+ case AST_TREE_TOKEN_TYPE_C_FUNCTION:
+ case AST_TREE_TOKEN_FUNCTION:
+ case AST_TREE_TOKEN_BUILTIN_CAST:
+ case AST_TREE_TOKEN_BUILTIN_TYPE_OF:
+ case AST_TREE_TOKEN_BUILTIN_SIZE_OF:
+ case AST_TREE_TOKEN_BUILTIN_IMPORT:
+ case AST_TREE_TOKEN_BUILTIN_IS_COMPTIME:
+ case AST_TREE_TOKEN_BUILTIN_STACK_ALLOC:
+ case AST_TREE_TOKEN_BUILTIN_HEAP_ALLOC:
+ case AST_TREE_TOKEN_BUILTIN_NEG:
+ case AST_TREE_TOKEN_BUILTIN_ADD:
+ case AST_TREE_TOKEN_BUILTIN_SUB:
+ case AST_TREE_TOKEN_BUILTIN_MUL:
+ case AST_TREE_TOKEN_BUILTIN_DIV:
+ case AST_TREE_TOKEN_BUILTIN_MOD:
+ case AST_TREE_TOKEN_BUILTIN_EQUAL:
+ case AST_TREE_TOKEN_BUILTIN_NOT_EQUAL:
+ case AST_TREE_TOKEN_BUILTIN_GREATER:
+ case AST_TREE_TOKEN_BUILTIN_SMALLER:
+ case AST_TREE_TOKEN_BUILTIN_GREATER_OR_EQUAL:
+ case AST_TREE_TOKEN_BUILTIN_SMALLER_OR_EQUAL:
+ case AST_TREE_TOKEN_BUILTIN_PUTC:
+ case AST_TREE_TOKEN_BUILTIN_C_LIBRARY:
+ case AST_TREE_TOKEN_BUILTIN_C_FUNCTION:
+ case AST_TREE_TOKEN_KEYWORD_RETURN:
+ case AST_TREE_TOKEN_KEYWORD_BREAK:
+ case AST_TREE_TOKEN_KEYWORD_CONTINUE:
+ case AST_TREE_TOKEN_KEYWORD_IF:
+ case AST_TREE_TOKEN_KEYWORD_WHILE:
+ case AST_TREE_TOKEN_KEYWORD_COMPTIME:
+ case AST_TREE_TOKEN_KEYWORD_STRUCT:
+ case AST_TREE_TOKEN_VALUE_VOID:
+ case AST_TREE_TOKEN_FUNCTION_CALL:
+ case AST_TREE_TOKEN_VARIABLE:
+ case AST_TREE_TOKEN_VARIABLE_DEFINE:
+ case AST_TREE_TOKEN_VALUE_NULL:
+ case AST_TREE_TOKEN_VALUE_UNDEFINED:
+ case AST_TREE_TOKEN_VALUE_NAMESPACE:
+ case AST_TREE_TOKEN_VALUE_SHAPE_SHIFTER:
+ case AST_TREE_TOKEN_VALUE_C_LIBRARY:
+ case AST_TREE_TOKEN_VALUE_C_FUNCTION:
+ case AST_TREE_TOKEN_VALUE_INT:
+ case AST_TREE_TOKEN_VALUE_FLOAT:
+ case AST_TREE_TOKEN_VALUE_BOOL:
+ case AST_TREE_TOKEN_VALUE_OBJECT:
+ case AST_TREE_TOKEN_RAW_VALUE:
+ case AST_TREE_TOKEN_RAW_VALUE_NOT_OWNED:
+ case AST_TREE_TOKEN_SHAPE_SHIFTER_ELEMENT:
+ case AST_TREE_TOKEN_OPERATOR_ASSIGN:
+ case AST_TREE_TOKEN_OPERATOR_PLUS:
+ case AST_TREE_TOKEN_OPERATOR_MINUS:
+ case AST_TREE_TOKEN_OPERATOR_SUM:
+ case AST_TREE_TOKEN_OPERATOR_SUB:
+ case AST_TREE_TOKEN_OPERATOR_MULTIPLY:
+ case AST_TREE_TOKEN_OPERATOR_DIVIDE:
+ case AST_TREE_TOKEN_OPERATOR_MODULO:
+ case AST_TREE_TOKEN_OPERATOR_EQUAL:
+ case AST_TREE_TOKEN_OPERATOR_NOT_EQUAL:
+ case AST_TREE_TOKEN_OPERATOR_GREATER:
+ case AST_TREE_TOKEN_OPERATOR_SMALLER:
+ case AST_TREE_TOKEN_OPERATOR_GREATER_OR_EQUAL:
+ case AST_TREE_TOKEN_OPERATOR_SMALLER_OR_EQUAL:
+ case AST_TREE_TOKEN_OPERATOR_ADDRESS:
+ case AST_TREE_TOKEN_OPERATOR_DEREFERENCE:
+ case AST_TREE_TOKEN_OPERATOR_ACCESS:
+ case AST_TREE_TOKEN_OPERATOR_LOGICAL_NOT:
+ case AST_TREE_TOKEN_OPERATOR_LOGICAL_AND:
+ case AST_TREE_TOKEN_OPERATOR_LOGICAL_OR:
+ case AST_TREE_TOKEN_OPERATOR_ARRAY_ACCESS:
+ case AST_TREE_TOKEN_SCOPE:
+ case AST_TREE_TOKEN_NONE:
+ }
+ UNREACHABLE;
+}
diff --git a/src/runner/runner.h b/src/runner/runner.h
index 789f0a9..00322c6 100644
--- a/src/runner/runner.h
+++ b/src/runner/runner.h
@@ -1,6 +1,7 @@
#pragma once
#include "compiler/ast-tree.h"
+#include <ffi.h>
void runnerVariableSetValue(AstTreeVariable *variable, AstTree *value);
void runnerVariableSetValueWihtoutConstCheck(AstTreeVariable *variable,
@@ -15,6 +16,9 @@ AstTree *runAstTreeFunction(AstTree *tree, AstTree **arguments,
AstTree *runAstTreeBuiltin(AstTree *tree, AstTreeScope *scope,
AstTree **arguments);
+AstTree *runAstTreeCFunction(AstTree *tree, AstTree **arguments,
+ size_t arguments_size);
+
AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet,
bool isLeft, bool isComptime, u32 *breakCount,
bool *shouldContinue);
@@ -27,4 +31,6 @@ bool discontinue(bool shouldRet, u32 breakCount);
AstTree *toRawValue(AstTree *value);
-AstTree *castTo(AstTree *value,AstTree *to);
+AstTree *castTo(AstTree *value, AstTree *to);
+
+ffi_type *toFFIType(AstTree *type);
diff --git a/src/utils/dl.c b/src/utils/dl.c
new file mode 100644
index 0000000..1a1c430
--- /dev/null
+++ b/src/utils/dl.c
@@ -0,0 +1,66 @@
+#include "dl.h"
+#include "utils/memory.h"
+#include "utils/string.h"
+#include <dlfcn.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+void **dynamicLibraries;
+char **dynamicLibraries_str;
+size_t dynamicLibraries_length;
+size_t dynamicLibraries_capacity;
+
+void dynamicLibraryInit() {
+ dynamicLibraries = a404m_malloc(0);
+ dynamicLibraries_str = a404m_malloc(0);
+ dynamicLibraries_length = 0;
+ dynamicLibraries_capacity = 0;
+}
+
+void dynamicLibraryDestroy() {
+ for (size_t i = 0; i < dynamicLibraries_length; ++i) {
+ dlclose(dynamicLibraries[i]);
+ free(dynamicLibraries_str[i]);
+ }
+ free(dynamicLibraries);
+ free(dynamicLibraries_str);
+}
+
+void *dynamicLibraryOpen(char *file) {
+ for (size_t i = 0; i < dynamicLibraries_length; ++i) {
+ if (strEquals(file, dynamicLibraries_str[i])) {
+ return dynamicLibraries[i];
+ }
+ }
+
+ void *dl = dlopen(file, RTLD_LAZY);
+ if (dl == NULL) {
+ fputs(dlerror(), stderr);
+ return NULL;
+ }
+
+ if (dynamicLibraries_capacity == dynamicLibraries_length) {
+ dynamicLibraries_capacity += dynamicLibraries_capacity / 2 + 1;
+ dynamicLibraries_str =
+ a404m_realloc(dynamicLibraries_str, sizeof(*dynamicLibraries_str) *
+ dynamicLibraries_capacity);
+ dynamicLibraries =
+ a404m_realloc(dynamicLibraries,
+ sizeof(*dynamicLibraries) * dynamicLibraries_capacity);
+ }
+ dynamicLibraries[dynamicLibraries_length] = dl;
+
+ const size_t file_length = strLength(file);
+ dynamicLibraries_str[dynamicLibraries_length] =
+ a404m_malloc(sizeof(**dynamicLibraries) * (file_length + 1));
+
+ for (size_t i = 0; i < file_length; ++i) {
+ dynamicLibraries_str[dynamicLibraries_length][i] = file[i];
+ }
+ dynamicLibraries_str[dynamicLibraries_length][file_length] = '\0';
+
+ dynamicLibraries_length += 1;
+
+ return dl;
+}
diff --git a/src/utils/dl.h b/src/utils/dl.h
new file mode 100644
index 0000000..74cb865
--- /dev/null
+++ b/src/utils/dl.h
@@ -0,0 +1,8 @@
+#pragma once
+
+#include <stddef.h>
+
+void dynamicLibraryInit();
+void dynamicLibraryDestroy();
+
+void* dynamicLibraryOpen(char *file);