package codegen import "core:fmt" import "core:os" import "core:strings" import "core:unicode/utf8" string_iterate_words :: proc(content: ^string) -> (word: string, new_paragraph: bool, cond: bool) { num_newlines := 0 word_start := -1 word_end := len(content) for r, i in content { if strings.is_space(r) { if word_start >= 0 { word_end = i break } if r == '\n' { num_newlines += 1 } continue } if word_start < 0 { word_start = i } } if word_start == -1 { return "", false, false } word = content[word_start:word_end] content^ = content[word_end:] return word, num_newlines > 1, true } gen_normalized_text :: proc(file: ^os.File, content: string, prefix := "") { content := content width := WIDTH - utf8.rune_count(prefix) column_rune_i := 0 for word, new_paragraph in string_iterate_words(&content) { word_rune_width := utf8.rune_count(word) if new_paragraph { fmt.fprint(file, "\n\n") column_rune_i = 0 } else if column_rune_i > 0 && column_rune_i + word_rune_width > width { fmt.fprint(file, "\n") column_rune_i = 0 } if column_rune_i == 0 && prefix != "" { fmt.fprint(file, prefix) } fmt.fprintf(file, "{} ", word) column_rune_i += word_rune_width + 1 } fmt.fprint(file, "\n") } gen_description :: proc(file: ^os.File, description: Description) { if description.summary == "" && description.body == "" { return } fmt.fprintln(file, BLOCK_COMMENT_BEGIN) if description.summary != "" { gen_normalized_text(file, description.summary) fmt.fprintln(file) } if description.body != "" { gen_normalized_text(file, description.body) } fmt.fprintln(file, BLOCK_COMMENT_END) } gen_header :: proc(file: ^os.File, protocol: Protocol) { fmt.fprintln( file, BLOCK_COMMENT_BEGIN, BIG_BLOCK_SEPARATOR, CODEGEN_HEADER, BIG_BLOCK_SEPARATOR, "", protocol.file_name, "", sep="\n" ) gen_normalized_text(file, protocol.copyright) fmt.fprintln(file, "", BIG_BLOCK_SEPARATOR, sep="\n") if protocol.description.summary != "" || protocol.description.body != "" { fmt.fprint(file, "\n") if protocol.description.summary != "" { gen_normalized_text(file, protocol.description.body) } if protocol.description.body != "" { gen_normalized_text(file, protocol.description.body) } fmt.fprint(file, "\n") fmt.fprintln(file, BIG_BLOCK_SEPARATOR) } fmt.fprintln(file, BLOCK_COMMENT_END, "\n") } gen_imports :: proc(file: ^os.File, protocol: Protocol) { fmt.fprintln( file, """ #+build linux package wayland import "base:intrinsics" import "core:fmt" import "core:log" import "core:io" """, ) } gen_interface :: proc(file: ^os.File, protocol: Protocol, interface: Interface) { fmt.fprintln(file, BIG_SEPARATOR) fmt.fprintln(file, "// ", strings.to_upper_snake_case(interface.name), "\n", sep="") gen_description(file, interface.description) interface_name := strings.to_ada_case(interface.name) fmt.fprintln(file, interface_name, "_ID :: distinct Object_ID", sep="") screaming_interface_name := strings.to_upper_snake_case(interface.name) fmt.fprintln(file, screaming_interface_name, "_INTERFACE_NAME :: \"", interface.name, "\"", sep="") fmt.fprintln(file, screaming_interface_name, "_INTERFACE_VERSION :: ", interface.version, sep="") fmt.fprintln(file) if len(interface.requests) > 0 { fmt.fprintln(file, SMALL_SEPARATOR, "// REQUESTS", "", sep="\n") fmt.fprintln(file, interface_name, "_Request :: enum Opcode {", sep="") for request, i in interface.requests { fmt.fprint(file, "\t", strings.to_ada_case(request.name), " = ", i, ",", sep="") if request.description.summary != "" { fmt.fprint(file, " //", request.description.summary) } fmt.fprintln(file) } fmt.fprintln(file, "}", "", sep="\n") for request in interface.requests { gen_request(file, protocol, interface, request) } } if len(interface.events) > 0 { fmt.fprintln(file, SMALL_SEPARATOR, "// EVENTS", "", sep="\n") } fmt.fprintln(file) } gen_request :: proc(file: ^os.File, protocol: Protocol, interface: Interface, request: Message) { if request.description.summary != "" || request.description.body != "" { fmt.fprintln(file, BLOCK_COMMENT_BEGIN) if request.description.summary != "" { gen_normalized_text(file, request.description.summary) fmt.fprint(file, "\n") } if request.description.body != "" { gen_normalized_text(file, request.description.body) } fmt.fprintln(file, BLOCK_COMMENT_END) } fmt.fprintln(file, REQUIRE_RESULTS_ATTRIBUTE) fmt.fprintln( file, strings.to_snake_case(interface.name), "_", strings.to_snake_case(request.name), " :: proc(session: ^Session) {}", sep="" ) fmt.fprintln(file) }