|
| 1 | +import sys |
| 2 | +import re |
| 3 | +from itertools import chain |
| 4 | + |
| 5 | +templ_c = """\ |
| 6 | +/* generated by {generated_by} */ |
| 7 | +#include "{name}_backend_generated.h" |
| 8 | +
|
| 9 | +const uint8_t m4_{name}_backend_code[{code_array_size}] = {{ |
| 10 | +{code_array_content} |
| 11 | +}}; |
| 12 | +
|
| 13 | +const uint8_t m4_{name}_backend_chore_a[{a_size}] = {{ |
| 14 | + {a_code} /* {a_src} */ |
| 15 | +}}; |
| 16 | +const uint8_t m4_{name}_backend_chore_b[{b_size}] = {{ |
| 17 | + {b_code} /* {b_src} */ |
| 18 | +}}; |
| 19 | +const uint8_t m4_{name}_backend_chore_y[{y_size}] = {{ |
| 20 | + {y_code} /* {y_src} */ |
| 21 | +}}; |
| 22 | +const uint8_t m4_{name}_backend_chore_z[{z_size}] = {{ |
| 23 | + {z_code} /* {z_src} */ |
| 24 | +}}; |
| 25 | +
|
| 26 | +const m4_backend_table_entry_t m4_{name}_backend_table[{code_table_count}] = {{ |
| 27 | +{code_table_content} |
| 28 | +}}; |
| 29 | +""" |
| 30 | + |
| 31 | +templ_h = """\ |
| 32 | +/* generated by {generated_by} */ |
| 33 | +#include "mcp_forth.h" |
| 34 | +
|
| 35 | +extern const uint8_t m4_{name}_backend_chore_a[{a_size}]; |
| 36 | +extern const uint8_t m4_{name}_backend_chore_b[{b_size}]; |
| 37 | +extern const uint8_t m4_{name}_backend_chore_y[{y_size}]; |
| 38 | +extern const uint8_t m4_{name}_backend_chore_z[{z_size}]; |
| 39 | +
|
| 40 | +extern const uint8_t m4_{name}_backend_code[{code_array_size}]; |
| 41 | +extern const m4_backend_table_entry_t m4_{name}_backend_table[{code_table_count}]; |
| 42 | +""" |
| 43 | + |
| 44 | +def generate_builtins(backend_name, builtins, elidables, src_to_code_cb): |
| 45 | + a_code = src_to_code_cb(elidables[0][0] + "\n") |
| 46 | + b_code = src_to_code_cb(elidables[1][0] + "\n") |
| 47 | + y_code = src_to_code_cb(elidables[2][0] + "\n") |
| 48 | + z_code = src_to_code_cb(elidables[3][0] + "\n") |
| 49 | + |
| 50 | + code_content = [] |
| 51 | + table_content = [] |
| 52 | + code_cumulative_len = 0 |
| 53 | + for word, flags, src in builtins: |
| 54 | + src_lines = list(line for line in src.splitlines() if line.strip()) |
| 55 | + flag_a = len(src_lines) > 0 and re.fullmatch(elidables[0][1], src_lines[0]) is not None |
| 56 | + flag_b = flag_a and len(src_lines) > 1 and re.fullmatch(elidables[1][1], src_lines[1]) is not None |
| 57 | + flag_clob = flag_b and "clobber" in flags |
| 58 | + if not flag_clob and "clobber" in flags: |
| 59 | + print("warning: clobber flag given but criteria not met") |
| 60 | + flag_z = len(src_lines) > 0 and re.fullmatch(elidables[3][1], src_lines[-1]) is not None |
| 61 | + flag_y = flag_z and len(src_lines) > 1 and re.fullmatch(elidables[2][1], src_lines[-2]) is not None |
| 62 | + if(flag_a): del src_lines[0] |
| 63 | + if(flag_b): del src_lines[0] |
| 64 | + if(flag_z): del src_lines[-1] |
| 65 | + if(flag_y): del src_lines[-1] |
| 66 | + src_reduced = "".join(line + '\n' for line in src_lines) |
| 67 | + code = src_to_code_cb(src_reduced) |
| 68 | + code_content.append( |
| 69 | + f" /* {word} */ " |
| 70 | + + "".join(f"0x{b:02x}," for b in code) |
| 71 | + ) |
| 72 | + pos_str = f"{code_cumulative_len},".ljust(7) |
| 73 | + len_str = f"{len(code)},".ljust(6) |
| 74 | + code_cumulative_len += len(code) |
| 75 | + flags_str = " | ".join(chain.from_iterable(( |
| 76 | + ("M4_BACKEND_FLAG_A",) if flag_a else (), |
| 77 | + ("M4_BACKEND_FLAG_B",) if flag_b else (), |
| 78 | + ("M4_BACKEND_FLAG_CLOB",) if flag_clob else (), |
| 79 | + ("M4_BACKEND_FLAG_Y",) if flag_y else (), |
| 80 | + ("M4_BACKEND_FLAG_Z",) if flag_z else (), |
| 81 | + ))) |
| 82 | + table_content.append( |
| 83 | + f" {{{pos_str}{len_str}{flags_str}}}," |
| 84 | + ) |
| 85 | + |
| 86 | + c = templ_c.format( |
| 87 | + generated_by = sys.argv[0], |
| 88 | + name = backend_name, |
| 89 | + code_array_size = code_cumulative_len, |
| 90 | + code_array_content = "\n".join(code_content), |
| 91 | + a_size = len(a_code), |
| 92 | + a_code = ",".join(f"0x{b:02x}" for b in a_code), |
| 93 | + a_src = elidables[0][0], |
| 94 | + b_size = len(b_code), |
| 95 | + b_code = ",".join(f"0x{b:02x}" for b in b_code), |
| 96 | + b_src = elidables[1][0], |
| 97 | + y_size = len(y_code), |
| 98 | + y_code = ",".join(f"0x{b:02x}" for b in y_code), |
| 99 | + y_src = elidables[2][0], |
| 100 | + z_size = len(z_code), |
| 101 | + z_code = ",".join(f"0x{b:02x}" for b in z_code), |
| 102 | + z_src = elidables[3][0], |
| 103 | + code_table_count = len(table_content), |
| 104 | + code_table_content = "\n".join(table_content) |
| 105 | + ) |
| 106 | + |
| 107 | + h = templ_h.format( |
| 108 | + generated_by = sys.argv[0], |
| 109 | + name = backend_name, |
| 110 | + a_size = len(a_code), |
| 111 | + b_size = len(b_code), |
| 112 | + y_size = len(y_code), |
| 113 | + z_size = len(z_code), |
| 114 | + code_array_size = code_cumulative_len, |
| 115 | + code_table_count = len(table_content) |
| 116 | + ) |
| 117 | + |
| 118 | + with open(f"{backend_name}_backend_generated.c", "w") as f: |
| 119 | + f.write(c) |
| 120 | + |
| 121 | + with open(f"{backend_name}_backend_generated.h", "w") as f: |
| 122 | + f.write(h) |
0 commit comments