@@ -2,10 +2,11 @@ use crate::config::GenDocs;
22use crate :: dev_aid:: port_diagram;
33use crate :: file_position:: FileText ;
44use crate :: flattening:: {
5- ClockVisibility , FieldDeclKind , InterfaceDeclaration , InterfaceKind , Module ,
5+ ClockVisibility , FieldDeclKind , InterfaceDeclaration , InterfaceKind , Module , NamedConstant ,
6+ StructType ,
67} ;
78use crate :: latency:: port_latency_inference:: InferenceTarget ;
8- use crate :: linker:: { FileData , GlobalObj , LinkInfo } ;
9+ use crate :: linker:: { FileData , GlobalObj , IsExtern , LinkInfo } ;
910use crate :: prelude:: * ;
1011use crate :: typing:: template:: TemplateKind ;
1112use pulldown_cmark:: { Options , Parser , html:: push_html as md_push_html} ;
@@ -116,14 +117,8 @@ fn build_interface_block(md: &Module, ft: &FileText) -> String {
116117 let li = & md. link_info ;
117118 let mut out = String :: new ( ) ;
118119
119- if li. parameters . is_empty ( ) {
120- out. push_str ( & format ! ( "module {} {{\n " , li. name) ) ;
121- } else {
122- out. push_str ( & format ! (
123- "module {} {{\n " ,
124- li. display_full_name_and_args( ft)
125- ) ) ;
126- }
120+ let name = li. display_full_name_and_args :: < true > ( ft) ;
121+ out. push_str ( & format ! ( "module {name} {{\n " ) ) ;
127122
128123 // Collect (source_pos, line) for clocks and fields, then sort to preserve source order.
129124 let mut items: Vec < ( usize , String ) > = Vec :: new ( ) ;
@@ -251,11 +246,8 @@ fn render_module_section(
251246 let name = & li. name ;
252247 let raw_doc = li. documentation . to_string ( ft) ;
253248
254- let heading = if li. parameters . is_empty ( ) {
255- html_escape ( name)
256- } else {
257- html_escape ( & li. display_full_name_and_args ( ft) . to_string ( ) )
258- } ;
249+ let module_name = li. display_full_name_and_args :: < true > ( ft) ;
250+ let heading = html_escape ( & module_name. to_string ( ) ) ;
259251
260252 let mut s = format ! ( "<section class=\" module\" id=\" {name}\" >\n " ) ;
261253 s. push_str ( & format ! (
@@ -280,6 +272,93 @@ fn render_module_section(
280272 s
281273}
282274
275+ fn build_struct_block ( typ : & StructType , ft : & FileText ) -> String {
276+ let li = & typ. link_info ;
277+ let name = li. display_full_name_and_args :: < true > ( ft) ;
278+ if matches ! ( li. is_extern, IsExtern :: Builtin ) {
279+ format ! ( "__builtin__ struct {name}" )
280+ } else {
281+ let mut out = format ! ( "struct {name} {{\n " , ) ;
282+ let mut items: Vec < ( usize , String ) > = Vec :: new ( ) ;
283+ for ( _, field) in & typ. fields {
284+ let decl = li. instructions [ field. declaration_instruction ] . unwrap_declaration ( ) ;
285+ items. push ( (
286+ field. name_span . start ,
287+ format ! ( " {}\n " , li. display_decl( None , decl, ft) ) ,
288+ ) ) ;
289+ }
290+ items. sort_by_key ( |( pos, _) | * pos) ;
291+ for ( _, line) in items {
292+ out. push_str ( & line) ;
293+ }
294+ out. push ( '}' ) ;
295+ out
296+ }
297+ }
298+
299+ fn render_struct_section (
300+ typ : & StructType ,
301+ ft : & FileText ,
302+ current_stem : & str ,
303+ index : & ModuleIndex ,
304+ ) -> String {
305+ let li = & typ. link_info ;
306+ let name = & li. name ;
307+ let raw_doc = li. documentation . to_string ( ft) ;
308+ let struct_name = li. display_full_name_and_args :: < true > ( ft) ;
309+ let heading = html_escape ( & struct_name. to_string ( ) ) ;
310+ let mut s = format ! ( "<section class=\" module\" id=\" {name}\" >\n " ) ;
311+ s. push_str ( & format ! (
312+ "<div class=\" module-heading\" ><h2>{heading}</h2></div>\n "
313+ ) ) ;
314+ let block = build_struct_block ( typ, ft) ;
315+ s. push_str ( "<div class=\" interface-block\" ><pre><code class=\" language-sus\" >" ) ;
316+ s. push_str ( & html_escape ( & block) ) ;
317+ s. push_str ( "</code></pre></div>\n " ) ;
318+ if !raw_doc. trim ( ) . is_empty ( ) {
319+ s. push_str ( "<div class=\" doc-prose\" >\n " ) ;
320+ s. push_str ( & render_prose ( & raw_doc, current_stem, index) ) ;
321+ s. push_str ( "</div>\n " ) ;
322+ }
323+ s. push_str ( "</section>\n " ) ;
324+ s
325+ }
326+
327+ fn build_const_block ( cst : & NamedConstant , ft : & FileText ) -> String {
328+ let li = & cst. link_info ;
329+ let decl = li. instructions [ cst. output_decl ] . unwrap_declaration ( ) ;
330+ let return_type = & ft[ decl. typ_expr . get_span ( ) ] ;
331+ let const_name = li. display_full_name_and_args :: < true > ( ft) ;
332+ format ! ( "const {return_type} {const_name}" )
333+ }
334+
335+ fn render_const_section (
336+ cst : & NamedConstant ,
337+ ft : & FileText ,
338+ current_stem : & str ,
339+ index : & ModuleIndex ,
340+ ) -> String {
341+ let li = & cst. link_info ;
342+ let name = & li. name ;
343+ let raw_doc = li. documentation . to_string ( ft) ;
344+ let heading = html_escape ( & li. display_full_name_and_args :: < true > ( ft) . to_string ( ) ) ;
345+ let mut s = format ! ( "<section class=\" module\" id=\" {name}\" >\n " ) ;
346+ s. push_str ( & format ! (
347+ "<div class=\" module-heading\" ><h2>{heading}</h2></div>\n "
348+ ) ) ;
349+ let block = build_const_block ( cst, ft) ;
350+ s. push_str ( "<div class=\" interface-block\" ><pre><code class=\" language-sus\" >" ) ;
351+ s. push_str ( & html_escape ( & block) ) ;
352+ s. push_str ( "</code></pre></div>\n " ) ;
353+ if !raw_doc. trim ( ) . is_empty ( ) {
354+ s. push_str ( "<div class=\" doc-prose\" >\n " ) ;
355+ s. push_str ( & render_prose ( & raw_doc, current_stem, index) ) ;
356+ s. push_str ( "</div>\n " ) ;
357+ }
358+ s. push_str ( "</section>\n " ) ;
359+ s
360+ }
361+
283362fn generate_file_html (
284363 file_stem : & str ,
285364 linker : & Linker ,
@@ -320,59 +399,81 @@ fn generate_file_html(
320399 for stem in all_stems {
321400 if stem == file_stem {
322401 html. push_str ( & format ! (
323- "<li><a href =\" {stem}.html \" class =\" sidebar-current \" >{stem}</a></li>\n "
402+ "<li><a class =\" language-item-ref sidebar-current \" href =\" {stem}.html \" >{stem}</a></li>\n "
324403 ) ) ;
325404 } else {
326- html. push_str ( & format ! ( "<li><a href=\" {stem}.html\" >{stem}</a></li>\n " ) ) ;
405+ html. push_str ( & format ! (
406+ "<li><a class=\" language-item-ref\" href=\" {stem}.html\" >{stem}</a></li>\n "
407+ ) ) ;
327408 }
328409 }
329410 html. push_str ( "</ul>\n " ) ;
330411 }
331412
332413 if has_structs {
333- html. push_str ( "<p class=\" sidebar-title\" >Structs</p >\n <ul>\n " ) ;
414+ html. push_str ( "<a href= \" #Types \" class=\" sidebar-title\" >Types</a >\n <ul>\n " ) ;
334415 for obj_id in & file_data. associated_values {
335416 let GlobalObj :: Type ( typ_id) = obj_id else {
336417 continue ;
337418 } ;
338419 let name = & linker. globals . types [ * typ_id] . link_info . name ;
339- html. push_str ( & format ! ( "<li><a href=\" #{name}\" >{name}</a></li>\n " ) ) ;
420+ html. push_str ( & format ! (
421+ "<li><a class=\" language-item-ref\" href=\" #{name}\" >{name}</a></li>\n "
422+ ) ) ;
340423 }
341424 html. push_str ( "</ul>\n " ) ;
342425 }
343426
344427 if has_modules {
345- html. push_str ( "<p class=\" sidebar-title\" >Modules</p >\n <ul>\n " ) ;
428+ html. push_str ( "<a href= \" #Modules \" class=\" sidebar-title\" >Modules</a >\n <ul>\n " ) ;
346429 for obj_id in & file_data. associated_values {
347430 let GlobalObj :: Module ( md_id) = obj_id else {
348431 continue ;
349432 } ;
350433 let name = & linker. globals . modules [ * md_id] . link_info . name ;
351- html. push_str ( & format ! ( "<li><a href=\" #{name}\" >{name}</a></li>\n " ) ) ;
434+ html. push_str ( & format ! (
435+ "<li><a class=\" language-item-ref\" href=\" #{name}\" >{name}</a></li>\n "
436+ ) ) ;
352437 }
353438 html. push_str ( "</ul>\n " ) ;
354439 }
355440
356441 if has_consts {
357- html. push_str ( "<p class=\" sidebar-title\" >Compile-Time Functions</p >\n <ul>\n " ) ;
442+ html. push_str ( "<a href= \" #CompileTimeFunctions \" class=\" sidebar-title\" >Compile-Time Functions</a >\n <ul>\n " ) ;
358443 for obj_id in & file_data. associated_values {
359444 let GlobalObj :: Constant ( const_id) = obj_id else {
360445 continue ;
361446 } ;
362447 let name = & linker. globals . constants [ * const_id] . link_info . name ;
363- html. push_str ( & format ! ( "<li><a href=\" #{name}\" >{name}</a></li>\n " ) ) ;
448+ html. push_str ( & format ! (
449+ "<li><a class=\" language-item-ref\" href=\" #{name}\" >{name}</a></li>\n "
450+ ) ) ;
364451 }
365452 html. push_str ( "</ul>\n " ) ;
366453 }
367454
368455 html. push_str ( "</aside>\n " ) ;
369456
370457 html. push_str ( "<div class=\" doc-main\" >\n " ) ;
371-
372458 html. push_str ( & format ! ( "<h1 class=\" page-title\" >{file_stem}</h1>\n " ) ) ;
373459
374- // TODO Add structs
460+ if has_structs {
461+ html. push_str ( "<h2 class=\" doc-section\" id=\" Types\" >Types</h2>\n " ) ;
462+ for obj_id in & file_data. associated_values {
463+ let GlobalObj :: Type ( typ_id) = obj_id else {
464+ continue ;
465+ } ;
466+ let typ = & linker. globals . types [ * typ_id] ;
467+ html. push_str ( & render_struct_section (
468+ typ,
469+ & file_data. file_text ,
470+ file_stem,
471+ index,
472+ ) ) ;
473+ }
474+ }
375475 if has_modules {
476+ html. push_str ( "<h2 class=\" doc-section\" id=\" Modules\" >Modules</h2>\n " ) ;
376477 for obj_id in & file_data. associated_values {
377478 let GlobalObj :: Module ( md_id) = obj_id else {
378479 continue ;
@@ -385,10 +486,26 @@ fn generate_file_html(
385486 index,
386487 ) ) ;
387488 }
388- html. push_str ( "</div>\n " ) ;
389489 }
390- // TODO Add consts
490+ if has_consts {
491+ html. push_str (
492+ "<h2 class=\" doc-section\" id=\" CompileTimeFunctions\" >Compile-Time Functions</h2>\n " ,
493+ ) ;
494+ for obj_id in & file_data. associated_values {
495+ let GlobalObj :: Constant ( const_id) = obj_id else {
496+ continue ;
497+ } ;
498+ let cst = & linker. globals . constants [ * const_id] ;
499+ html. push_str ( & render_const_section (
500+ cst,
501+ & file_data. file_text ,
502+ file_stem,
503+ index,
504+ ) ) ;
505+ }
506+ }
391507
508+ html. push_str ( "</div>\n " ) ;
392509 html. push_str ( "</div>\n </main>\n " ) ;
393510 html. push_str ( & format ! (
394511 "<script src=\" {host}/docs/highlight.js\" ></script>\n "
0 commit comments