From addd54dc31603dc204773d3108dba4e000cd7657 Mon Sep 17 00:00:00 2001
From: A404M <ahmadmahmoudiprogrammer@gmail.com>
Date: Tue, 8 Oct 2024 04:16:27 +0330
Subject: added fasm support added compiler options tried to compile to fasm
 first

---
 src/compiler/fasm_generator/fasm_generator.c | 208 +++++++++++++++++++++++++++
 src/compiler/fasm_generator/fasm_generator.h |  31 ++++
 2 files changed, 239 insertions(+)
 create mode 100644 src/compiler/fasm_generator/fasm_generator.c
 create mode 100644 src/compiler/fasm_generator/fasm_generator.h

(limited to 'src/compiler/fasm_generator')

diff --git a/src/compiler/fasm_generator/fasm_generator.c b/src/compiler/fasm_generator/fasm_generator.c
new file mode 100644
index 0000000..b83f3d2
--- /dev/null
+++ b/src/compiler/fasm_generator/fasm_generator.c
@@ -0,0 +1,208 @@
+#include "fasm_generator.h"
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "compiler/tree_parser/tree_parser.h"
+#include "utils/memory/memory.h"
+
+FasmLines generateFasm(SourceCode *code) {
+  ParsedTree *root = treeParser(code);
+  if (root != NULL) {
+    FasmLines lines = _generateFasm(root, code);
+
+    deleteParsedTree(root);
+    return lines;
+  }
+  const FasmLines error = {
+      .lines = NULL,
+      /*.size = ERROR_SIZE,*/
+  };
+  return error;
+}
+
+FasmLines generateFasmWithPrint(SourceCode *code) {
+  ParsedTree *root = treeParser(code);
+  if (root != NULL) {
+    printf("----tree parsed:\n");
+    printParsedTreeNode(root);
+    FasmLines lines = _generateFasm(root, code);
+
+    deleteParsedTree(root);
+    return lines;
+  }
+  fprintf(stderr, "error in tree parser\n");
+  const FasmLines error = {
+      .lines = NULL,
+      /*.size = ERROR_SIZE,*/
+  };
+  return error;
+}
+
+FasmLines _generateFasm(const ParsedTree *root, SourceCode *code) {
+  const TreeScopeMetadata *metadata = root->metadata;
+
+  FasmVariables thisVariables = {
+      .variables = a404m_malloc(metadata->variables_size *
+                                sizeof(*thisVariables.variables)),
+      .size = metadata->variables_size,
+  };
+
+  size_t size = 0;
+
+  for (size_t i = 0; i < metadata->variables_size; ++i) {
+    const TreeDefineVariableMetadata *variable = metadata->variables[i];
+    FasmVariable keyValue = {
+        .variable = variable,
+        .value = size,
+    };
+    thisVariables.variables[i] = keyValue;
+    size += 8;
+  }
+
+  const size_t variables_size = 1;
+  FasmVariables *variables[1] = {
+      &thisVariables,
+  };
+
+  FasmLines lines = {
+      .lines = a404m_malloc(0),
+      /*.size = 0,*/
+  };
+
+  for (size_t i = 0; i < metadata->lines_size; ++i) {
+    const ParsedTree *node = metadata->lines[i];
+    if (!nodeToFasmLine(node, &lines, variables, variables_size, code)) {
+      goto RETURN_ERROR;
+    }
+  }
+
+  return lines;
+
+RETURN_ERROR:
+  free(lines.lines);
+
+  const FasmLines error = {
+      .lines = NULL,
+      /*.size = ERROR_SIZE,*/
+  };
+  return error;
+}
+
+bool nodeToFasmLine(const ParsedTree *node, FasmLines *lines,
+                    FasmVariables *variables[], size_t variables_size,
+                    SourceCode *code) {
+  switch (node->token) {
+    case TREE_TOKEN_NONE:
+    case TREE_TOKEN_ROOT:
+      printError("Is not allowed in compiler line %s:%d", code, node->strBegin,
+                 node->strBegin, __FILE_NAME__, __LINE__);
+      exit(1);
+    case TREE_TOKEN_GLOBAL_SCOPE:
+    case TREE_TOKEN_LOCAL_SCOPE: {
+      const TreeScopeMetadata *metadata = node->metadata;
+
+      FasmVariables thisVariables = {
+          .variables = a404m_malloc(metadata->variables_size *
+                                    sizeof(*thisVariables.variables)),
+          .size = metadata->variables_size,
+      };
+
+      size_t size = 0;
+
+      for (size_t i = 0; i < metadata->variables_size; ++i) {
+        const TreeDefineVariableMetadata *variable = metadata->variables[i];
+        FasmVariable keyValue = {
+            .variable = variable,
+            .value = size,
+            .isGlobal = node->token == TREE_TOKEN_GLOBAL_SCOPE,
+        };
+        thisVariables.variables[i] = keyValue;
+        size += getSizeOfVariable(variable);
+      }
+
+      size_t newVariables_size = variables_size + 1;
+      FasmVariables *newVariables[newVariables_size];
+
+      for (size_t i = 0; i < variables_size; ++i) {
+        newVariables[i] = variables[i];
+      }
+      newVariables[variables_size] = &thisVariables;
+
+      for (size_t i = 0; i < metadata->lines_size; ++i) {
+        if (!nodeToFasmLine(metadata->lines[i], lines, newVariables,
+                            newVariables_size, code)) {
+          return false;
+        }
+      }
+      return true;
+    }
+    case TREE_TOKEN_FUNCTION_CALL: {
+      const TreeFunctionCallMetadata *metadata = node->metadata;
+      return true;
+    }
+    case TREE_TOKEN_FUNCTION: {
+      const TreeFunctionMetadata *metadata = node->metadata;
+      return true;
+    }
+    case TREE_TOKEN_IDENTIFIER: {
+      const TreeIdentifierMetadata *metadata = node->metadata;
+
+      const FasmVariable fasmVariable = getVariableFasmKeyValue(
+          metadata->variable, variables, variables_size);
+      if (fasmVariable.variable == NULL) {
+        return false;
+      }
+
+      FasmLine line = {
+          /*.label = NULL,*/
+          // TODO: do it
+      };
+
+      pushFasmLine(lines, line);
+
+      return true;
+    }
+    case TREE_TOKEN_DEFINE_VARIABLE:
+    case TREE_TOKEN_DEFINE_CONSTANT:
+    case TREE_TOKEN_VALUE_STRING:
+    case TREE_TOKEN_STRUCT:
+  }
+  fprintf(stderr, "Bad parsed token '%d' %s:%d", node->token, __FILE_NAME__,
+          __LINE__);
+  exit(1);
+}
+
+void pushFasmLine(FasmLines *lines, FasmLine line) {
+  const size_t size =
+      a404m_malloc_usable_size(lines->lines) / sizeof(*lines->lines);
+  /*if (size == lines->size) {
+    lines->lines =
+        a404m_realloc(lines->lines, (size * 2 + 1) * sizeof(*lines->lines));
+  }
+  lines->lines[lines->size] = line;
+  lines->size += 1;*/
+}
+
+size_t getSizeOfVariable(const TreeDefineVariableMetadata *variable) {
+  return 8;  // TODO: do it;
+}
+
+FasmVariable getVariableFasmKeyValue(const TreeDefineVariableMetadata *variable,
+                                     FasmVariables *variables[],
+                                     size_t variables_size) {
+  for (size_t i = 0; i < variables_size; ++i) {
+    for (size_t j = 0; j < variables[i]->size; ++j) {
+      if (variables[i]->variables[j].variable == variable) {
+        return variables[i]->variables[j];
+      }
+    }
+  }
+  const FasmVariable error = {
+      .variable = NULL,
+      .value = 0,
+      .isGlobal = false,
+  };
+  return error;
+}
diff --git a/src/compiler/fasm_generator/fasm_generator.h b/src/compiler/fasm_generator/fasm_generator.h
new file mode 100644
index 0000000..c6925ad
--- /dev/null
+++ b/src/compiler/fasm_generator/fasm_generator.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include <compiler/tree_parser/tree_parser.h>
+#include <fasm/lexer/lexer.h>
+#include <stdint.h>
+
+typedef struct FasmVariable {
+  TreeDefineVariableMetadata const *variable;
+  uint64_t value;
+  bool isGlobal;
+} FasmVariable;
+
+typedef struct FasmVariables {
+  FasmVariable *variables;
+  size_t size;
+} FasmVariables;
+
+extern FasmLines generateFasm(SourceCode *code);
+extern FasmLines generateFasmWithPrint(SourceCode *code);
+extern FasmLines _generateFasm(const ParsedTree *root, SourceCode *code);
+
+extern bool nodeToFasmLine(const ParsedTree *node, FasmLines *lines,
+                           FasmVariables *variables[], size_t variables_size,
+                           SourceCode *code);
+
+extern void pushFasmLine(FasmLines *lines, FasmLine line);
+
+extern size_t getSizeOfVariable(const TreeDefineVariableMetadata *variable);
+extern FasmVariable getVariableFasmKeyValue(
+    const TreeDefineVariableMetadata *variable, FasmVariables *variables[],
+    size_t variables_size);
-- 
cgit v1.2.3