WARNING! Access to this system is limited to authorised users only.
Unauthorised users may be subject to prosecution.
Unauthorised access to this system is a criminal offence under Australian law (Federal Crimes Act 1914 Part VIA)
It is a criminal offence to:
(1) Obtain access to data without authority. -Penalty 2 years imprisonment.
(2) Damage, delete, alter or insert data without authority. -Penalty 10 years imprisonment.
User activity is monitored and recorded. Anyone using this system expressly consents to such monitoring and recording.

Commit ed8e3905 authored by Kunshan Wang's avatar Kunshan Wang
Browse files

API-GEN: WIP: generating forwarders...

api_bridge.rs will convert low-level C valus to high-level Rust value,
such as CMuValue* -> [&APIMuValue].
parent 15a48ed7
// Invoke "python3 muapi2rustapi.py", and then
// invoke "rustc --test __api_gen_tester_mod.rs -o /tmp/api_gen_tester_junk"
// to test whether the generated code compiles.
mod api_c;
mod api_bridge;
mod api_impl;
This diff is collapsed.
......@@ -7,6 +7,7 @@
// This file is for interfacing with C, so it is not idiomatic Rust code.
#![allow(non_camel_case_types)]
#![allow(dead_code)]
use std::os::raw::*;
......
mod api_old;
mod api_new;
//mod api_old;
//mod api_new;
mod api_c;
//mod api_bridge; // FIXME: Implement the bridges
mod api_impl;
pub use vm::api::api_new::*;
//pub use vm::api::api_new::*;
......@@ -11,7 +11,7 @@ import sys
import os, os.path
import re
import tempfile
from typing import Tuple
from typing import Tuple, List
import muapiparser
import injecttools
......@@ -405,16 +405,20 @@ def generate_enum_converters(ast):
return "\n".join(lines)
def generate_things(ast):
stubs = generate_stubs(ast)
__rust_kw_rewrite = {
"ref": "reff",
}
enums = generate_enums(ast)
def avoid_rust_kws(name):
return __rust_kw_rewrite.get(name, name)
enum_convs = generate_enum_converters(ast)
def filler_name_for(struct_name):
return "_fill__" + struct_name
return "\n".join([stubs, enums, enum_convs])
def forwarder_name_for(struct_name, meth_name):
return "_forwarder__" + struct_name + "__" + meth_name
def generate_method_field(meth):
def generate_struct_field(meth) -> str:
name = meth['name']
params = meth['params']
ret_ty = meth['ret_ty']
......@@ -426,24 +430,123 @@ def generate_method_field(meth):
rust_param_tys.append(rust_ty)
rust_ret_ty = None if ret_ty == "void" else to_rust_type(ret_ty)
ret_ty_text = "" if rust_ret_ty == None else "-> {}".format(rust_ret_ty)
field_def = " pub {}: fn({}){},".format(
name, ", ".join(rust_param_tys),
"" if rust_ret_ty == None else "-> {}".format(rust_ret_ty))
name, ", ".join(rust_param_tys), ret_ty_text)
return field_def
def generate_struct(st) -> str:
def generate_forwarder(st, meth) -> str:
name = meth['name']
params = meth['params']
ret_ty = meth['ret_ty']
stmts = []
forwarder_name = forwarder_name_for(st["name"], name)
# formal parameter list
param_nts = []
for param in params:
cpn = param['name']
rpn = avoid_rust_kws(cpn)
cty = param['type']
rty = to_rust_type(cty)
param_nts.append("{}: {}".format(rpn, rty))
formal_param_list = ", ".join(param_nts)
# return type
rust_ret_ty = None if ret_ty == "void" else to_rust_type(ret_ty)
ret_ty_text = "" if rust_ret_ty == None else "-> {}".format(rust_ret_ty)
# preparing args
for param in params:
is_sz_param = param.get("is_sz_param", False)
if is_sz_param:
continue
cpn = param['name']
rpn = avoid_rust_kws(cpn)
cty = param['type']
rty = to_rust_type(cty)
arg_name = "_arg_" + rpn
array_sz_param = param.get("array_sz_param", None)
is_optional = param.get("is_optional", False)
if array_sz_param != None:
assert cty.endswith("*")
c_base_ty = cty[:-1]
sz_cpn = array_sz_param
sz_rpn = avoid_rust_kws(sz_cpn)
if type_is_ptr(c_base_ty):
converter = "from_ptr_array({}, {})".format(
rpn, sz_rpn)
elif type_is_node(c_base_ty):
converter = "from_MuID_array({}, {})".format(
rpn, sz_rpn)
else:
converter = "from_{}_array({}, {})".format(
c_base_ty, rpn, sz_rpn)
elif is_optional:
if type_is_ptr(cty):
converter = "from_ptr_optional({})".format(rpn)
elif type_is_node(cty):
converter = "from_node_optional({})".format(rpn)
elif cty in ["MuCString", "MuID"]:
converter = "from_{}_optional({})".format(cty, rpn)
else:
raise Exception("Not expecting {} to be optional".format(cty))
else:
if cty.endswith("*"):
c_base_ty = cty[:-1]
converter = "from_{}_ptr({})".format(c_base_ty, rpn)
else:
converter = "from_{}({})".format(cty, rpn)
stmt = " let mut {} = {};".format(arg_name, converter)
stmts.append(stmt)
# call
stmts.append(' panic!("not implemented")')
all_stmts = "\n".join(stmts)
bridge = """\
fn {forwarder_name}({formal_param_list}){ret_ty_text} {{
{all_stmts}
}}
""".format(**locals())
return bridge
def visit_method(st, meth) -> Tuple[str, str]:
field_def = generate_struct_field(meth)
bridge = generate_forwarder(st, meth)
return field_def, bridge
def visit_struct(st) -> Tuple[str, List[str]]:
name = st["name"]
methods = st["methods"]
rust_name = "C" + name
field_defs = []
forwarders = []
for meth in methods:
field_def = generate_method_field(meth)
field_def, forwarder = visit_method(st, meth)
field_defs.append(field_def)
forwarders.append(forwarder)
fields = "\n".join(field_defs)
......@@ -457,21 +560,23 @@ pub struct {rust_name} {{
}}
""".format(**locals())
return struct_def
return struct_def, forwarders
def generate_structs(ast) -> str:
def visit_structs(ast) -> Tuple[str, str]:
struct_defs = []
forwarders = []
structs = ast["structs"]
for struct in structs:
struct_def = generate_struct(struct)
struct_def, my_forwarders = visit_struct(struct)
struct_defs.append(struct_def)
forwarders.extend(my_forwarders)
return "\n".join(struct_defs)
return "\n".join(struct_defs), "\n".join(forwarders)
def generate_enums(ast):
def visit_enums(ast):
const_defs = []
for enum in ast['enums']:
......@@ -484,7 +589,7 @@ def generate_enums(ast):
return "\n".join(const_defs)
def generate_types(ast):
def visit_types(ast):
types = []
for c, p in ast["typedefs_order"]:
if p.startswith("_"):
......@@ -503,11 +608,11 @@ def main():
ast = muapiparser.parse_muapi(src_text)
types = generate_types(ast)
types = visit_types(ast)
structs = generate_structs(ast)
structs, forwarders = visit_structs(ast)
enums = generate_enums(ast)
enums = visit_enums(ast)
injectable_files["api_c.rs"].inject_many({
"Types": types,
......@@ -515,5 +620,9 @@ def main():
"Enums": enums,
})
injectable_files["api_bridge.rs"].inject_many({
"Forwarders": forwarders,
})
if __name__=='__main__':
main()
......@@ -13,4 +13,6 @@ muapi_h_path = os.path.join(_my_dir, "muapi.h")
injectable_files = injecttools.make_injectable_file_set(_mu_impl_fast_root, [
("api_c.rs", "src/vm/api/api_c.rs",
["Types", "Structs", "Enums"]),
("api_bridge.rs", "src/vm/api/api_bridge.rs",
["Fillers", "Forwarders"]),
])
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment