Browse Source

Experiment with generating all Jolt enums

Lucien Greathouse 1 year ago
parent
commit
009dabcfb5
1 changed files with 47 additions and 53 deletions
  1. 47 53
      generate/src/main.rs

+ 47 - 53
generate/src/main.rs

@@ -1,3 +1,4 @@
+use std::collections::HashMap;
 use std::fmt::Write;
 
 use anyhow::Context;
@@ -17,6 +18,8 @@ fn main() {
 fn generate() -> anyhow::Result<()> {
     let mut output = String::new();
 
+    writeln!(output, "// Generated by JoltC-generate").unwrap();
+
     for entry in WalkDir::new("JoltPhysics/Jolt") {
         let entry = entry?;
         let file_name = entry
@@ -25,61 +28,38 @@ fn generate() -> anyhow::Result<()> {
             .context("invalid UTF-8 in file name")?;
 
         if file_name.ends_with(".h") {
-            println!("Processing {file_name}...");
+            eprintln!("Processing {file_name}...");
 
             let header = fs::read_to_string(entry.path())?;
 
             convert_enums(&header, &mut output);
-            convert_classes(&header, &mut output);
         }
     }
 
-    eprintln!();
-    eprintln!();
-    eprintln!();
-    eprintln!("{output}");
+    println!("{output}");
 
     Ok(())
 }
 
-fn convert_classes(header: &str, output: &mut String) {
-    let class = Regex::new(r"^\s*class\s*JPH_EXPORT\s*(\w+)").unwrap();
-    let field = Regex::new(r"^([\w<>])").unwrap();
-
-    struct WipClass {
-        cpp_name: String,
-        c_name: String,
-    }
-
-    let mut current_class = None;
-
-    for line in header.lines() {
-        if current_class.is_none() {
-            if let Some(captures) = class.captures(line) {
-                let name = &captures[1];
-                println!("Found exported class: {name}");
-
-                current_class = Some(WipClass {
-                    cpp_name: name.to_owned(),
-                    c_name: format!("{PREFIX}_{name}"),
-                });
-            }
-
-            continue;
-        }
-
-        if let Some(current) = &current_class {}
-    }
-}
-
 fn convert_enums(header: &str, output: &mut String) {
     struct WipEnum {
         cpp_name: String,
         c_name: String,
+        shouty_c_name: String,
+        next_value: u32,
+        num_variants: u32,
     }
 
+    let enum_types: HashMap<&str, &str> = HashMap::from_iter([
+        ("int", "int"),
+        ("uint", "unsigned int"),
+        ("uint8", "uint8_t"),
+        ("uint16", "uint16_t"),
+        ("uint32", "uint32_t"),
+    ]);
+
     let enum_class = Regex::new(r"^\s*enum\s+class\s+(\w+)(?:\s*:\s*(\w+))?").unwrap();
-    let enum_member = Regex::new(r"^\s*(\w+)(?:\s*=\s*(.+?),)?").unwrap();
+    let enum_member = Regex::new(r"^\s*(\w+)(?:\s*=\s*(.+?)(?:,|/|$))?").unwrap();
     let end_block = Regex::new(r"^\s*}").unwrap();
 
     let mut current_enum = None;
@@ -88,24 +68,30 @@ fn convert_enums(header: &str, output: &mut String) {
         if current_enum.is_none() {
             if let Some(captures) = enum_class.captures(line) {
                 let mut name = &captures[1];
-                let repr = captures.get(2).map(|m| m.as_str());
+                let given_repr = captures.get(2).map(|m| m.as_str()).unwrap_or("int");
+
+                let repr = enum_types
+                    .get(given_repr)
+                    .unwrap_or_else(|| panic!("unknown enum type {given_repr}"));
 
                 // EShapeSubType => ShapeSubType
                 if name.starts_with('E') && name.as_bytes()[1].is_ascii_uppercase() {
                     name = &name[1..];
                 }
 
-                let c_name = format!("{PREFIX}_{}", AsShoutySnakeCase(name));
+                let c_name = format!("{PREFIX}_{}", name);
 
-                if let Some(repr) = repr {
-                    writeln!(output, "typedef enum {c_name} : {repr} {{").unwrap();
-                } else {
-                    writeln!(output, "typedef enum {c_name} {{").unwrap();
-                }
+                let shouty_c_name =
+                    format!("{}", AsShoutySnakeCase(&c_name)).replace("DO_FS", "DOFS");
+
+                writeln!(output, "typedef {repr} {c_name};").unwrap();
 
                 current_enum = Some(WipEnum {
                     cpp_name: name.to_owned(),
                     c_name,
+                    shouty_c_name,
+                    next_value: 0,
+                    num_variants: 0,
                 });
 
                 continue;
@@ -114,24 +100,32 @@ fn convert_enums(header: &str, output: &mut String) {
             continue;
         }
 
-        if let Some(current) = &current_enum {
+        if let Some(current) = &mut current_enum {
             if end_block.is_match(line) {
-                writeln!(output, "}} {};", current.c_name).unwrap();
+                writeln!(output).unwrap();
+
                 current_enum = None;
                 continue;
             }
 
             if let Some(captures) = enum_member.captures(line) {
-                let name = &captures[1];
-                let value = captures.get(2).map(|m| m.as_str());
+                current.num_variants += 1;
 
-                let c_name = format!("{}_{}", current.c_name, AsShoutySnakeCase(name));
+                let name = &captures[1];
+                let given_value = captures.get(2).map(|m| m.as_str().trim().to_string());
 
-                if let Some(value) = value {
-                    writeln!(output, "    {} = {value},", c_name).unwrap();
-                } else {
-                    writeln!(output, "    {},", c_name).unwrap();
+                if given_value.is_none() && current.num_variants > 1 && current.next_value == 0 {
+                    panic!("Enum {} variant {name} did not have a value, but is set to use auto values", current.cpp_name);
                 }
+
+                let value = given_value.unwrap_or_else(|| {
+                    let v = current.next_value;
+                    current.next_value += 1;
+                    v.to_string()
+                });
+
+                let c_name = format!("{}_{}", current.shouty_c_name, AsShoutySnakeCase(name));
+                writeln!(output, "static {} {c_name} = {value};", current.c_name).unwrap();
             }
         }
     }