summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorrealtradam <[email protected]>2022-03-11 05:08:38 -0500
committerrealtradam <[email protected]>2022-03-11 05:08:38 -0500
commit9c0d9e5e086d8b593057b0eab5981968e10874bb (patch)
tree352561cf531a3844a9eb3edf9015938940b1326a
parent39db5fbee576ad02da3d1c07dd63c0183829be0d (diff)
downloadFelBind-9c0d9e5e086d8b593057b0eab5981968e10874bb.tar.gz
FelBind-9c0d9e5e086d8b593057b0eab5981968e10874bb.zip
completed accessor generation
-rw-r--r--Readme.mdown10
-rw-r--r--generate.rb68
-rw-r--r--templates.rb46
3 files changed, 106 insertions, 18 deletions
diff --git a/Readme.mdown b/Readme.mdown
index 6deb78b..296955e 100644
--- a/Readme.mdown
+++ b/Readme.mdown
@@ -18,20 +18,24 @@ A binding assistant and generator for C/C++ to mruby(Under heavy WIP)
- insert bindings you made yourself
3. Run the generator with the configuration file - this generates the resulting binding code
-Todo:
+#### Todo:
- [X] parse C files for function and struct declarations
- [X] plan for DSL for configuration file
- [ ] create generator's default output
- [X] phase 1 - bind returnless, paramless functions
- - [ ] phase 2 - bind standard type return functions(e.g string or int), but still paramless
+ - [X] phase 2 - bind standard type return functions(e.g string or int), but still paramless
- bool
- int
- float
- double
- string
- - [ ] phase 3 - bind standard type return or params
+ - [X] phase 3 - bind standard type return or params
- [ ] phase 4 - bind struct construction(returning struct objects)
+ - [X] returning structs
+ - [X] accessors for values inside structs
+ - [ ] bind struct initializer
- [ ] phase 5 - bind struct params(unwrapping structs)
+- [ ] clean up code
- [ ] have generator use config DSL file to customize bindings
- [ ] do it all again for C++
diff --git a/generate.rb b/generate.rb
index 38edd9c..1502bfb 100644
--- a/generate.rb
+++ b/generate.rb
@@ -21,6 +21,7 @@ glue = JSON.parse(File.read(options[:glue]))
# configuration
Tplt.treated_as_int |= ['unsigned char']
+LibraryName = 'Test'
$phase1 = {}
$phase2 = {}
@@ -105,16 +106,49 @@ def debug_mark_binding(func, params)
end
+$all_params = []
+$bound_params = []
# generates structs
# TODO
# Auto generate struct accessors
#
glue.last.each do |struct, params|
defines += Tplt.init_struct_wrapper(struct)
- init_body += Tplt.init_class(struct, 'test')
+ init_body += Tplt.init_class(struct, LibraryName.downcase)
params.each do |param|
- #puts param
+ $all_params.push param
+ rpart = param.rpartition(' ')
+ param_datatype = rpart.first
+ param_name = rpart.last
+
+ next unless Tplt.non_struct_types.include? param_datatype
+ $bound_params.push param
+
+ # getter
+ # take no params
+ # unwrap struct
+ # return(using correct type conversion)
+ body = Tplt.unwrap_struct("#{struct} *struct_#{struct.downcase}", 'self', "mrb_#{struct}_struct", struct)
+ body += "return #{Tplt.to_mrb(param_datatype, "struct_#{struct.downcase}->#{param_name}")};\n"
+ defines += Tplt.function("#{struct}_get_#{param_name}", body)
+ init_body += Tplt.init_function("#{struct.downcase}_class", param_name, "#{struct}_get_#{param_name}", "MRB_ARGS_NONE()")
+
+ # setter
+ # init var of correct type
+ # take 1 arg param
+ # unwrap struct
+ # set value in struct
+ # return same value
+ body = Tplt.get_args({ "#{param_name}": "#{param_datatype}" })
+ body += Tplt.unwrap_struct("#{struct} *struct_#{struct.downcase}", 'self', "mrb_#{struct}_struct", struct)
+ body += "struct_#{struct.downcase}->#{param_name} = #{param_name};\n"
+ body += "return #{Tplt.to_mrb(param_datatype, param_name)};\n"
+ defines += Tplt.function("#{struct}_set_#{param_name}", body)
+ init_body += Tplt.init_function("#{struct.downcase}_class", "#{param_name}=", "#{struct}_set_#{param_name}", "MRB_ARGS_REQ(1)")
+
+ # init var with correct type
+
end
end
@@ -141,7 +175,7 @@ glue.first.each do |func, params|
#defines += 'PHASE 1\n'
defines += "\n//#{func}"
defines += Tplt.function(func_name, body)
- init_body += Tplt.init_module_function('test', Tplt.rubify_func_name(func_name), func_name, "MRB_ARGS_NONE()")
+ init_body += Tplt.init_module_function(LibraryName.downcase, Tplt.rubify_func_name(func_name), func_name, "MRB_ARGS_NONE()")
debug_mark_binding(func, params)
else Tplt.non_struct_types.include? func_datatype # accept params
@@ -175,7 +209,7 @@ glue.first.each do |func, params|
# if return isnt regular types, add struct to init
unless Tplt.non_struct_types.include? func_datatype
- init_var_body += "#{func_datatype} *return_value = {0};\n"
+ #init_var_body += "#{func_datatype} *wrapped_value = {0};\n"
end
body = Tplt.get_kwargs(params.length, init_var_body, init_array_body)
@@ -185,14 +219,26 @@ glue.first.each do |func, params|
if Tplt.non_struct_types.include? func_datatype
body += Tplt.return_format(func, params)
else
- body += Tplt.get_module('Test')
- body += Tplt.get_class(func_datatype, 'test')
- body += Tplt.return_format_struct(func)
+ body += Tplt.get_module(LibraryName)
+ body += Tplt.get_class(func_datatype, LibraryName.downcase)
+ #body += "mrb_value *object_mrb;"
+ #body += Tplt.wrap_struct('wrapped_value', '*object_mrb', "mrb_#{func_datatype}_struct" , func_datatype)
+ #body += Tplt.return_format_struct(func)
+ #body += Tplt.make_mrb_obj_from_struct("*object_mrb", func, 'wrapped_value')
+ body += "#{func_datatype} *wrapped_value = (#{func_datatype} *)mrb_malloc(mrb, sizeof(#{func_datatype}));\n"
+ body += "*wrapped_value = #{func_name}("
+ params.each do |param|
+ temp_rpart = param.rpartition(' ')
+ body += "#{temp_rpart.last}, "
+ end
+ body.delete_suffix!(', ')
+ body += ");\n"
+ body += "return mrb_obj_value(Data_Wrap_Struct(mrb, #{func_datatype.downcase}_mrb_class, &mrb_#{func_datatype}_struct, wrapped_value));"
end
defines += "\n//#{func}"
defines += Tplt.function(func_name, body)
- init_body += Tplt.init_module_function('test', Tplt.rubify_func_name(func_name), func_name, "MRB_ARGS_OPT(1)") # opt stuff isnt correct, need to look at this again
+ init_body += Tplt.init_module_function(LibraryName.downcase, Tplt.rubify_func_name(func_name), func_name, "MRB_ARGS_OPT(1)") # opt stuff isnt correct, need to look at this again
# ---
#puts func
debug_mark_binding(func, params)
@@ -203,12 +249,12 @@ glue.first.each do |func, params|
end
end
-init_body.prepend(Tplt.define_module('Test'))
+init_body.prepend(Tplt.define_module(LibraryName))
result = %{
#{includes}
#{defines}
-#{Tplt.base('test', init_body, nil)}
+#{Tplt.base(LibraryName.downcase, init_body, nil)}
}
result += "//Bound Functions: #{$complete_phase1.length + $complete_phase2.length + $complete_phase3.length + $complete_phase4.length + $complete_phase5.length} / #{$phase1.length + $phase2.length + $phase3.length + $phase4.length + $phase5.length}\n//---\n"
@@ -218,6 +264,8 @@ result += "//Phase 2 Functions: #{$complete_phase2.length} / #{$phase2.length}\n
result += "//Phase 3 Functions: #{$complete_phase3.length} / #{$phase3.length}\n"
result += "//Phase 4 Functions: #{$complete_phase4.length} / #{$phase4.length}\n"
result += "//Phase 5 Functions: #{$complete_phase5.length} / #{$phase5.length}\n"
+result += "\n"
+result += "//Struct Accessors: #{$bound_params.length} / #{$all_params.length}\n"
puts result
diff --git a/templates.rb b/templates.rb
index 981d79c..b4ca43c 100644
--- a/templates.rb
+++ b/templates.rb
@@ -110,14 +110,42 @@ if (mrb_undef_p(kw_values[#{kwarg_iter}])) {
}
end
+ def get_args(req_arg_hash, opt_arg_hash=nil)
+ raise if opt_arg_hash
+ result = ''
+ tail = ''
+ flags = ''
+ req_arg_hash.each do |var_name, var_datatype|
+ if var_datatype != 'unsigned char'
+ result += "#{var_datatype} #{var_name};\n"
+ else
+ result += "mrb_int #{var_name};\n"
+ end
+ tail += ", &#{var_name}"
+ flags += datatype_to_arg_flag(var_datatype)
+ end
+ result += "mrb_get_args(mrb, \"#{flags}\"#{tail});\n"
+ end
+
+ def datatype_to_arg_flag(datatype)
+ if treated_as_int.include? datatype
+ 'i'
+ elsif treated_as_bool.include? datatype
+ 'b'
+ elsif treated_as_float.include? datatype
+ 'f'
+ elsif treated_as_string.include? datatype
+ 'z'
+ end
+ end
def unwrap_struct(var_name, target, mrb_type, type)
- %{#{var_name} = DATA_GET_PTR(mrb, #{target}, &#{mrb_type}, #{type})}
+ %{#{var_name} = DATA_GET_PTR(mrb, #{target}, &#{mrb_type}, #{type});\n}
end
def wrap_struct(var_name, target, mrb_type, type)
%{
- #{var_name} = (#{type} *)DATA_PTR(#{target})
+ #{var_name} = (#{type} *)DATA_PTR(#{target});
if(#{var_name}) #{'{'} mrb_free(mrb, #{var_name}); #{'}'}
mrb_data_init(#{target}, NULL, &#{mrb_type});
#{var_name} = (#{type} *)mrb_malloc(mrb, sizeof(#{type}));
@@ -196,6 +224,7 @@ mrb_data_init(#{target}, NULL, &#{mrb_type});
result
end
+ # doesnt seem correct?
def return_format_struct(function)
func_rpart = function.rpartition(' ')
func_datatype = func_rpart.first.delete_suffix(' *')
@@ -203,6 +232,13 @@ mrb_data_init(#{target}, NULL, &#{mrb_type});
"return mrb_obj_value(Data_Wrap_Struct(mrb, #{func_datatype.downcase}_mrb_class, &mrb_#{func_datatype}_struct, return_value));"
end
+ def make_mrb_obj_from_struct(mrb_var, func, struct_var)
+ func_rpart = func.rpartition(' ')
+ func_datatype = func_rpart.first.delete_suffix(' *')
+ func_name = func_rpart.last
+ "mrb_data_init(#{mrb_var}, #{struct_var}, &mrb_#{func_rpart.first}_struct);\n"
+ end
+
# wrapping an existing struct to be used by ruby
def init_struct_wrapper(struct, free_body = nil)
%{
@@ -222,9 +258,9 @@ static const struct mrb_data_type mrb_#{struct}_struct = {
if free_body
%{
- void
- mrb_helper_#{struct}_free(mrb_state* mrb, void*ptr) {
-#{struct} *struct_data = (#{struct}*)ptr;
+ void
+ mrb_helper_#{struct}_free(mrb_state* mrb, void*ptr) {
+ #{struct} *struct_data = (#{struct}*)ptr;
#{free_body}
mrb_free(mrb, ptr);
}