summaryrefslogtreecommitdiff
path: root/src/sim86/sim86_meta.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sim86/sim86_meta.c')
-rw-r--r--src/sim86/sim86_meta.c181
1 files changed, 181 insertions, 0 deletions
diff --git a/src/sim86/sim86_meta.c b/src/sim86/sim86_meta.c
new file mode 100644
index 0000000..37fe0c3
--- /dev/null
+++ b/src/sim86/sim86_meta.c
@@ -0,0 +1,181 @@
+
+#if __clang__
+# define COMPILER_CLANG 1
+#elif _MSC_VER
+# define COMPILER_MSVC 1
+#elif __GNUC__
+# define COMPILER_GNU 1
+#endif
+
+#if defined(COMPILER_GNU)
+# define PUSH_WARNINGS \
+_Pragma("GCC diagnostic push") \
+_Pragma("GCC diagnostic ignored \"-Weverything\"")
+# define POP_WARNINGS \
+_Pragma("GCC diagnostic pop")
+#elif defined(COMPILER_CLANG)
+# define PUSH_WARNINGS \
+_Pragma("clang diagnostic push") \
+_Pragma("clang diagnostic ignored \"-Weverything\"")
+# define POP_WARNINGS \
+_Pragma("clang diagnostic pop")
+#else
+# define PUSH_WARNINGS \
+_Pragma("message \"No compatible compiler found\"")
+# define POP_WARNINGS
+#endif
+
+PUSH_WARNINGS
+#include "md.h"
+#include "md.c"
+POP_WARNINGS
+
+#define Assert(Expression) if(!(Expression)) { __asm__ volatile("int3"); }
+
+static MD_Arena *Arena = 0;
+
+int main(int ArgsCount, char *Args[])
+{
+ if(ArgsCount > 1)
+ {
+ Arena = MD_ArenaAlloc();
+ MD_String8 FileName = MD_S8CString(Args[1]);
+ MD_ParseResult Parse = MD_ParseWholeFile(Arena, FileName);
+
+ // print metadesk errors
+ for(MD_Message *Message = Parse.errors.first;
+ Message != 0;
+ Message = Message->next)
+ {
+ MD_CodeLoc code_loc = MD_CodeLocFromNode(Message->node);
+ MD_PrintMessage(stdout, code_loc, Message->kind, Message->string);
+ }
+
+ if(Parse.errors.max_message_kind < MD_MessageKind_Error)
+ {
+ MD_Node *Root = Parse.node->first_child;
+
+ MD_String8List Stream = {0};
+ for(MD_EachNode(Node, Root))
+ {
+
+ // 1. If we find a table_gen_enum_flags tag
+ if(MD_NodeHasTag(Node, MD_S8Lit("table_gen_enum_flags"), 0))
+ {
+ MD_String8 TableName = MD_NodeAtIndex(Node->first_tag->first_child, 0)->string;
+ MD_String8 MemberName = MD_NodeAtIndex(Node->first_tag->first_child, 1)->string;
+
+ // 2. Find the table in the first argument
+ // TODO(luca): Check for not nil otherwise print error
+ MD_Node *TableNode = MD_FirstNodeWithString(Root, TableName, 0);
+ MD_Node *TableTag = MD_TagFromString(TableNode, MD_S8Lit("table"), 0);
+
+ // TODO(luca): Check for not nil otherwise print error
+ MD_Node *MemberNode = MD_FirstNodeWithString(TableTag->first_child, MemberName, 0);
+ int MemberIndex = MD_IndexFromNode(MemberNode);
+
+ // Header
+ MD_S8ListPushFmt(Arena, &Stream, "enum %S\n{\n", Node->string);
+
+ int MemberCount = 0;
+ for(MD_EachNode(Member, TableNode->first_child))
+ {
+ // 3. Use the member of it in the second argument
+ MD_Node *MemberNode = MD_NodeAtIndex(Member->first_child, MemberIndex);
+
+ // 4. For each member in the table
+ // 1. Create an enum where you create flags in the form
+ // Flag_None 0 << 1
+ // Flag_First 1 << 1
+ // ...
+ MD_S8ListPushFmt(Arena, &Stream, " Flag_%S = (1 << %d),\n",
+ MemberNode->string, MemberCount);
+ MemberCount++;
+ }
+
+ MD_S8ListPush(Arena, &Stream, MD_S8Lit("};\n\n"));
+ }
+
+ // 1. If we find a table_gen_data tag
+ if(MD_NodeHasTag(Node, MD_S8Lit("table_gen_data"), 0))
+ {
+ MD_String8 TableName = MD_NodeAtIndex(Node->first_tag->first_child, 0)->string;
+ MD_String8 Type = MD_NodeAtIndex(Node->first_tag->first_child, 1)->string;
+ MD_String8 MemberName = MD_NodeAtIndex(Node->first_tag->first_child, 2)->string;
+
+ MD_Node *Table = MD_FirstNodeWithString(Root, TableName, 0);
+
+ MD_Node *TableTag = MD_TagFromString(Table, MD_S8Lit("table"), 0);
+ MD_Node *MemberNode = MD_FirstNodeWithString(TableTag->first_child, MemberName, 0);
+ int MemberIndex = MD_IndexFromNode(MemberNode);
+
+ int MemberCount = MD_ChildCountFromNode(Table);
+
+ MD_S8ListPushFmt(Arena, &Stream, "int %S_count = %d;\n", Node->string, MemberCount);
+ // Header
+ MD_S8ListPushFmt(Arena, &Stream, "%S%S[] =\n{\n", Type, Node->string);
+
+ for(MD_EachNode(Member, Table->first_child))
+ {
+ MD_Node *ValueNode = MD_NodeAtIndex(Member->first_child, MemberIndex);
+ MD_S8ListPushFmt(Arena, &Stream, " %S,\n", ValueNode->raw_string);
+ }
+
+ MD_S8ListPush(Arena, &Stream, MD_S8Lit("};\n\n"));
+ }
+
+#if 0
+ if(MD_NodeHasTag(Node, MD_S8Lit("table"), 0))
+ {
+ Assert(0);
+ }
+#endif
+
+ if(MD_NodeHasTag(Node, MD_S8Lit("table_gen_enum"), 0))
+ {
+ // Header
+ MD_S8ListPushFmt(Arena, &Stream, "enum %S\n{\n", Node->string);
+
+ for(MD_EachNode(Member, Node->first_child))
+ {
+ if(MD_NodeHasTag(Member, MD_S8Lit("expand"), 0))
+ {
+ MD_Node *Tag = MD_TagFromString(Member, MD_S8Lit("expand"), 0);
+ MD_String8 TableName = MD_NodeAtIndex(Tag->first_child, 0)->string;
+ MD_Node *Table = MD_FirstNodeWithString(Root, TableName, 0);
+
+ // 2. For each node in the table
+ for(MD_EachNode(TableMember, Table->first_child))
+ {
+ // 3. Evaluate the expression
+ // 1. Search Member->string for a '$' sign
+ // 2. If it's followed by a dot and a name, parse that name.
+ // 3. Store the name and use it to lookup the members
+ // TODO(luca):
+
+
+ Member->string;
+ }
+
+ }
+ else
+ {
+ MD_S8ListPush(Arena, &Stream, Member->string);
+ MD_S8ListPush(Arena, &Stream, MD_S8Lit("\n"));
+ }
+
+ }
+
+ MD_S8ListPush(Arena, &Stream, MD_S8Lit("};\n"));
+ }
+
+ // MD_PrintDebugDumpFromNode(stderr, Node, MD_GenerateFlags_All);
+ }
+
+ MD_String8 Str = MD_S8ListJoin(Arena, Stream, 0);
+ fwrite(Str.str, 1, Str.size, stdout);
+ }
+
+ }
+ return 0;
+} \ No newline at end of file