diff --git a/lang/compile.py b/lang/compile.py index fc54021..3b3f3ef 100755 --- a/lang/compile.py +++ b/lang/compile.py @@ -921,11 +921,8 @@ ## C file output -def generate_header(ir, source): - header = "/* Autogenerated by compile.py.\n\n" - header += source - header += "*/\n\n" - header += "#define MODULE_INTERNAL_API\n" +def generate_header(source): + include_output = "" includes = [ '"bytecode.h"', '"module.h"', @@ -934,8 +931,24 @@ '', ] for i in includes: - header += "\n#include %s" % i - return header + include_output += "\n#include %s" % i + return """/* Autogenerated by compile.py. + +%s +*/ + +#define MODULE_INTERNAL_API +%s""" % (source, include_output) + +def generate_bytecode(node): + bytecode = generate_bytecode_function(node) + if bytecode is None: + print("Unknown bytecode node: %s" % (node)) + return None + fixed_bytecode = bytecode_fixup(bytecode) + c_bytecode = generate_bytecode_c(fixed_bytecode) + return "static const unsigned char bytecode_%s_%s [] = {%s};\n\n" \ + % (node.class_, node.name, c_bytecode) def generate_module_args(module_args): return """static struct object_list *create_args(VmState state, struct object_list *use_modules) { @@ -954,7 +967,7 @@ object_list_free(args); }""" % (len(module_args)) -def generate_callbacks(): +def generate_class_boilerplate(): return """static struct object_class CLASSNAME_class; static Object CLASSNAME_create(VmState state, struct object_list *use_modules) { @@ -974,57 +987,47 @@ bytecode_run(state, obj, (const unsigned char *)priv, *args); }""" -def generate_structures(functions): - structures = """static struct object_call CLASSNAME_calls[] = {\n""" - for function in functions: - structures += "\t" + function + "\n" - structures += "\t{.name = NULL, /* end */}\n};" - structures += """\n +def generate_class_call(class_name, func_name): + call = '{.name = "%s", .handler = CLASSNAME_call_bytecode, ' % (func_name) + call += '\n\t\t.priv = (void *)bytecode_%s_%s },\n\t' % (class_name, func_name) + return call + +def generate_class_structs(class_ir): + calls = "" + for func in class_ir.functions: + calls += generate_class_call(class_ir.name, func) + return """static struct object_call CLASSNAME_calls[] = { + %s{.name = NULL, /* end */} +}; + static struct object_class CLASSNAME_class = { .cleanup = CLASSNAME_cleanup, .calls = &CLASSNAME_calls[0], -};""" - return structures - -def generate_bytecode(node): - bytecode = generate_bytecode_function(node) - if bytecode is None: - print("Unknown bytecode node: %s" % (node)) - return None - fixed_bytecode = bytecode_fixup(bytecode) - output = "static const unsigned char " - output += "bytecode_%s_%s [] = {" % (node.class_, node.name) - output += generate_bytecode_c(fixed_bytecode) - output += "};\n\n" - return output - -def generate_call(class_name, func_name): - call = '{.name = "%s", .handler = CLASSNAME_call_bytecode, ' % (func_name) - call += '\n\t\t.priv = (void *)bytecode_%s_%s},' % (class_name, func_name) - return call - -def generate_metadata(node): - output = "static const char* module_uses[] = {\n" - for use in node.uses: - output += "\t\"%s\",\n" % (use) - output += "\tNULL\n};\n\n" - output += "const struct module_info module_info_%s = {\n" % (node.id) - output += "\t.name = \"%s\",\n" % (node.name) - output += "\t.uses = module_uses,\n" - output += "\t.create = %s_create,\n" % (node.name) - output += "};" - return output +};""" % (calls) def generate_c_class(class_ir): functions = [] - for func in class_ir.functions: - functions.append(generate_call(class_ir.name, func)) - output = generate_callbacks() + output = generate_class_boilerplate() output += "\n\n" - output += generate_structures(functions) + output += generate_class_structs(class_ir) output = output.replace('CLASSNAME', class_ir.name) return output +def generate_metadata(node): + uses = "" + for use in node.uses: + uses += "\t\"%s\",\n" % (use) + return """static const char* module_uses[] = { +%s NULL, /* end */ +}; + +const struct module_info module_info_%s = { + .name = "%s", + .uses = module_uses, + .create = %s_create, +}; +""" % (uses, node.id, node.name, node.name) + def generate_c_file(module_args, ir, source): metadata = "" bytecodes = "" @@ -1046,7 +1049,7 @@ if not success: print("Can't generate node: %s" % (node)) return None - output = generate_header(ir, source) + output = generate_header(source) output += "\n\n/* BYTECODES */\n\n" output += bytecodes output += "/* MODULE ARGS */\n\n"