Repository: veryl-lang/veryl (Rust)

Issue:
Boolean literal given as generic arg is not translated
Boolean literal given as generic arg is not translated.

Veryl
```systemverilog
module ModuleA::<A: bool> {
  let _a: bool = A;
}
module ModuleB {
  inst u: ModuleA::<true>;
}
```

Generated SV
```systemverilog
module project___ModuleA__true;
    logic _a; always_comb _a = true;
endmodule
module project_ModuleB;
    project___ModuleA__true u ();
endmodule
```


Discussion:

Patch:
diff --git a/crates/analyzer/src/symbol_path.rs b/crates/analyzer/src/symbol_path.rs
index df86d62b0..d772fe505 100644
--- a/crates/analyzer/src/symbol_path.rs
+++ b/crates/analyzer/src/symbol_path.rs
@@ -238,7 +238,7 @@ pub enum GenericSymbolPathKind {
     IntegerAllBit,
     RealExponent,
     RealFixedPoint,
-    Boolean,
+    Boolean(bool),
 }
 
 impl fmt::Display for GenericSymbolPathKind {
@@ -251,7 +251,7 @@ impl fmt::Display for GenericSymbolPathKind {
             GenericSymbolPathKind::IntegerAllBit => "integer all bit".to_string(),
             GenericSymbolPathKind::RealExponent => "real exponent".to_string(),
             GenericSymbolPathKind::RealFixedPoint => "read fixed point".to_string(),
-            GenericSymbolPathKind::Boolean => "boolean".to_string(),
+            GenericSymbolPathKind::Boolean(x) => format!("{x}"),
         };
         text.fmt(f)
     }
@@ -621,16 +621,16 @@ impl From<&syntax_tree::Number> for GenericSymbolPath {
 
 impl From<&syntax_tree::BooleanLiteral> for GenericSymbolPath {
     fn from(value: &syntax_tree::BooleanLiteral) -> Self {
-        let token = match value {
-            syntax_tree::BooleanLiteral::True(x) => x.r#true.true_token.token,
-            syntax_tree::BooleanLiteral::False(x) => x.r#false.false_token.token,
+        let (token, value) = match value {
+            syntax_tree::BooleanLiteral::True(x) => (x.r#true.true_token.token, true),
+            syntax_tree::BooleanLiteral::False(x) => (x.r#false.false_token.token, false),
         };
         GenericSymbolPath {
             paths: vec![GenericSymbol {
                 base: token,
                 arguments: Vec::new(),
             }],
-            kind: GenericSymbolPathKind::Boolean,
+            kind: GenericSymbolPathKind::Boolean(value),
             range: token.into(),
         }
     }
diff --git a/crates/emitter/src/emitter.rs b/crates/emitter/src/emitter.rs
index d124b3f8f..735f9508e 100644
--- a/crates/emitter/src/emitter.rs
+++ b/crates/emitter/src/emitter.rs
@@ -13,7 +13,9 @@ use veryl_analyzer::symbol::TypeModifierKind as SymTypeModifierKind;
 use veryl_analyzer::symbol::{
     GenericMap, GenericTables, Port, Symbol, SymbolId, SymbolKind, TypeKind, VariableAffiliation,
 };
-use veryl_analyzer::symbol_path::{GenericSymbolPath, SymbolPath, SymbolPathNamespace};
+use veryl_analyzer::symbol_path::{
+    GenericSymbolPath, GenericSymbolPathKind, SymbolPath, SymbolPathNamespace,
+};
 use veryl_analyzer::symbol_table::{self, ResolveError, ResolveResult};
 use veryl_analyzer::{msb_table, namespace_table};
 use veryl_metadata::{Build, BuiltinType, ClockType, Format, Metadata, ResetType, SourceMapTarget};
@@ -2266,9 +2268,13 @@ impl VerylWalker for Emitter {
                 }
                 (Err(_), path) if !path.is_resolvable() => {
                     // emit literal by generics
-                    let text = path.base_path(0).0[0].to_string();
+                    let text = if let GenericSymbolPathKind::Boolean(x) = path.kind {
+                        if x { "1'b1" } else { "1'b0" }
+                    } else {
+                        &path.base_path(0).0[0].to_string()
+                    };
                     self.identifier(&Identifier {
-                        identifier_token: arg.identifier().replace(&text),
+                        identifier_token: arg.identifier().replace(text),
                     });
                 }
                 _ => {}


Test patch:
diff --git a/crates/emitter/src/tests.rs b/crates/emitter/src/tests.rs
index 1db4dcfc4..0635b87c4 100644
--- a/crates/emitter/src/tests.rs
+++ b/crates/emitter/src/tests.rs
@@ -2104,3 +2104,40 @@ endmodule
     println!("ret\n{}exp\n{}", ret, expect);
     assert_eq!(ret, expect);
 }
+
+#[test]
+fn boolean_literal_as_generic_arg() {
+    let code = r#"module ModuleA::<A: bool> {
+    let _a: bool = A;
+}
+module ModuleB {
+    inst u0: ModuleA::<true> ;
+    inst u1: ModuleA::<false>;
+}
+"#;
+
+    let expect = r#"module prj___ModuleA__true;
+    logic _a; always_comb _a = 1'b1;
+endmodule
+module prj___ModuleA__false;
+    logic _a; always_comb _a = 1'b0;
+endmodule
+module prj_ModuleB;
+    prj___ModuleA__true u0 ();
+    prj___ModuleA__false u1 ();
+endmodule
+//# sourceMappingURL=test.sv.map
+"#;
+
+    let metadata: Metadata =
+        toml::from_str(&Metadata::create_default_toml("prj").unwrap()).unwrap();
+
+    let ret = if cfg!(windows) {
+        emit(&metadata, code).replace("\r\n", "\n")
+    } else {
+        emit(&metadata, code)
+    };
+
+    println!("ret\n{}exp\n{}", ret, expect);
+    assert_eq!(ret, expect);
+}