raiguard/odin-wayland
git clone https://git.raiguard.me/raiguard/odin-wayland
27d1580
trunk
1package codegen 2 3import "core:fmt" 4import "core:os" 5import "core:strings" 6import "core:unicode/utf8" 7 8string_iterate_words :: proc ( content : ^ string ) -> ( word : string , new_paragraph : bool , cond : bool ) { 9num_newlines := 0 10word_start := -1 11word_end := len ( content ) 12for r , i in content { 13if strings . is_space ( r ) { 14if word_start >= 0 { 15word_end = i 16break 17} 18if r == '\n' { 19num_newlines += 1 20} 21continue 22} 23if word_start < 0 { 24word_start = i 25} 26} 27 28if word_start == -1 { 29return "" , false , false 30} 31 32word = content [ word_start : word_end ] 33content ^ = content [ word_end :] 34return word , num_newlines > 1 , true 35} 36 37gen_normalized_text :: proc ( file : ^ os . File , content : string , prefix := "" ) { 38content := content 39width := WIDTH - utf8 . rune_count ( prefix ) 40 41column_rune_i := 0 42for word , new_paragraph in string_iterate_words ( & content ) { 43word_rune_width := utf8 . rune_count ( word ) 44if new_paragraph { 45fmt . fprint ( file , "\n\n" ) 46column_rune_i = 0 47} else if column_rune_i > 0 && column_rune_i + word_rune_width > width { 48fmt . fprint ( file , "\n" ) 49column_rune_i = 0 50} 51if column_rune_i == 0 && prefix != "" { 52fmt . fprint ( file , prefix ) 53} 54fmt . fprintf ( file , "{} " , word ) 55column_rune_i += word_rune_width + 1 56} 57fmt . fprint ( file , "\n" ) 58} 59 60gen_description :: proc ( file : ^ os . File , description : Description ) { 61if description . summary == "" && description . body == "" { 62return 63} 64 65fmt . fprintln ( file , BLOCK_COMMENT_BEGIN ) 66if description . summary != "" { 67gen_normalized_text ( file , description . summary ) 68fmt . fprintln ( file ) 69} 70if description . body != "" { 71gen_normalized_text ( file , description . body ) 72} 73fmt . fprintln ( file , BLOCK_COMMENT_END ) 74} 75 76gen_header :: proc ( file : ^ os . File , protocol : Protocol ) { 77fmt . fprintln ( 78file , 79BLOCK_COMMENT_BEGIN , 80BIG_BLOCK_SEPARATOR , 81CODEGEN_HEADER , 82BIG_BLOCK_SEPARATOR , 83"" , 84protocol . file_name , 85"" , 86sep = "\n" 87) 88gen_normalized_text ( file , protocol . copyright ) 89fmt . fprintln ( file , "" , BIG_BLOCK_SEPARATOR , sep = "\n" ) 90 91if protocol . description . summary != "" || protocol . description . body != "" { 92fmt . fprint ( file , "\n" ) 93if protocol . description . summary != "" { 94gen_normalized_text ( file , protocol . description . body ) 95} 96if protocol . description . body != "" { 97gen_normalized_text ( file , protocol . description . body ) 98} 99fmt . fprint ( file , "\n" ) 100fmt . fprintln ( file , BIG_BLOCK_SEPARATOR ) 101} 102fmt . fprintln ( file , BLOCK_COMMENT_END , "\n" ) 103} 104 105gen_imports :: proc ( file : ^ os . File , protocol : Protocol ) { 106fmt . fprintln ( 107file , 108""" 109#+build linux 110package wayland 111 112import " base : intrinsics " 113import " core : fmt " 114import " core : log " 115import " core : io " 116 117""" , 118) 119} 120 121gen_interface :: proc ( file : ^ os . File , protocol : Protocol , interface : Interface ) { 122fmt . fprintln ( file , BIG_SEPARATOR ) 123fmt . fprintln ( file , "// " , strings . to_upper_snake_case ( interface . name ), "\n" , sep = "" ) 124 125gen_description ( file , interface . description ) 126 127interface_name := strings . to_ada_case ( interface . name ) 128fmt . fprintln ( file , interface_name , "_ID :: distinct Object_ID" , sep = "" ) 129screaming_interface_name := strings . to_upper_snake_case ( interface . name ) 130fmt . fprintln ( file , screaming_interface_name , "_INTERFACE_NAME :: \"" , interface . name , "\"" , sep = "" ) 131fmt . fprintln ( file , screaming_interface_name , "_INTERFACE_VERSION :: " , interface . version , sep = "" ) 132fmt . fprintln ( file ) 133 134if len ( interface . requests ) > 0 { 135fmt . fprintln ( file , SMALL_SEPARATOR , "// REQUESTS" , "" , sep = "\n" ) 136fmt . fprintln ( file , interface_name , "_Request :: enum Opcode {" , sep = "" ) 137for request , i in interface . requests { 138fmt . fprint ( file , "\t" , strings . to_ada_case ( request . name ), " = " , i , "," , sep = "" ) 139if request . description . summary != "" { 140fmt . fprint ( file , " //" , request . description . summary ) 141} 142fmt . fprintln ( file ) 143} 144fmt . fprintln ( file , "}" , "" , sep = "\n" ) 145for request in interface . requests { 146gen_request ( file , protocol , interface , request ) 147} 148} 149 150if len ( interface . events ) > 0 { 151fmt . fprintln ( file , SMALL_SEPARATOR , "// EVENTS" , "" , sep = "\n" ) 152} 153 154fmt . fprintln ( file ) 155} 156 157gen_request :: proc ( file : ^ os . File , protocol : Protocol , interface : Interface , request : Message ) { 158if request . description . summary != "" || request . description . body != "" { 159fmt . fprintln ( file , BLOCK_COMMENT_BEGIN ) 160if request . description . summary != "" { 161gen_normalized_text ( file , request . description . summary ) 162fmt . fprint ( file , "\n" ) 163} 164if request . description . body != "" { 165gen_normalized_text ( file , request . description . body ) 166} 167fmt . fprintln ( file , BLOCK_COMMENT_END ) 168} 169 170fmt . fprintln ( file , REQUIRE_RESULTS_ATTRIBUTE ) 171fmt . fprintln ( 172file , 173strings . to_snake_case ( interface . name ), 174"_" , 175strings . to_snake_case ( request . name ), 176" :: proc(session: ^Session) {}" , 177sep = "" 178) 179 180fmt . fprintln ( file ) 181}