summaryrefslogtreecommitdiffhomepage
path: root/templates.rb
diff options
context:
space:
mode:
authorrealtradam <[email protected]>2022-08-31 08:29:23 -0400
committerrealtradam <[email protected]>2022-08-31 08:29:23 -0400
commitc51ded6c4efef4e0ef5a157a72ae79c402b7964b (patch)
tree46802e9bfaae9d97538ab94285c3357f7ca65c94 /templates.rb
parent8caf4473882f3eab9018b0ed4500792d459bdc98 (diff)
downloadFelBind-c51ded6c4efef4e0ef5a157a72ae79c402b7964b.tar.gz
FelBind-c51ded6c4efef4e0ef5a157a72ae79c402b7964b.zip
starting work on the backend system
Diffstat (limited to 'templates.rb')
-rw-r--r--templates.rb623
1 files changed, 0 insertions, 623 deletions
diff --git a/templates.rb b/templates.rb
deleted file mode 100644
index 7d88876..0000000
--- a/templates.rb
+++ /dev/null
@@ -1,623 +0,0 @@
-module Template # Template
- # methods that convert something from ruby-land to c-land
- module C
- class << self
- def to_c_function_name(function_name:)
- "mrb_#{function_name}"
- end
-
- def to_getter_name(struct_name:, variable_name:)
- "mrb_#{struct_name}_get_#{variable_name}"
- end
-
- def to_setter_name(struct_name:, variable_name:)
- "mrb_#{struct_name}_set_#{variable_name}"
- end
-
- def to_initializer_name(struct_name:)
- "mrb_#{struct_name}_initialize"
- end
-
- def format_type(param_datatype)
- if Template.treated_as_int =~ param_datatype
- 'int'
- elsif Template.treated_as_int_pointer =~ param_datatype
- 'int'
- elsif Template.treated_as_bool =~ param_datatype
- 'bool'
- elsif Template.treated_as_bool_pointer =~ param_datatype
- 'bool'
- elsif Template.treated_as_float =~ param_datatype
- 'float'
- elsif Template.treated_as_float_pointer =~ param_datatype
- 'float'
- elsif Template.treated_as_string =~ param_datatype
- 'char *'
- # Ignore for now
- #elsif Template.treated_as_string_pointer =~ param_datatype
- # 'char *'
- elsif Template.struct_types =~ param_datatype
- "#{param_datatype}"
- elsif Template.struct_types_pointer =~ param_datatype
- "#{param_datatype.gsub(/ *\*+$/,'')}"
- else
- nil # cannot be formated
- end
- end
-
- def format_mrb_type(param_datatype)
- if Template.treated_as_int =~ param_datatype
- 'mrb_int'
- elsif Template.treated_as_int_pointer =~ param_datatype
- 'mrb_int'
- elsif Template.treated_as_bool =~ param_datatype
- 'mrb_bool'
- elsif Template.treated_as_bool_pointer =~ param_datatype
- 'mrb_bool'
- elsif Template.treated_as_float =~ param_datatype
- 'mrb_float'
- elsif Template.treated_as_float_pointer =~ param_datatype
- 'mrb_float'
- elsif Template.treated_as_string =~ param_datatype
- 'char *'
- # Ignore for now
- #elsif Template.treated_as_string_pointer =~ param_datatype
- # 'char *'
- elsif Template.struct_types =~ param_datatype
- "mrb_value" #"#{param_datatype}"
- elsif Template.struct_types_pointer =~ param_datatype
- "mrb_value" #"#{param_datatype.gsub(/ *\*+$/,'')}"
- else
- nil # cannot be formated
- end
- end
-
- def convention_parameter(param)
- "parameter_#{param}"
- end
-
- def convention_mrb_parameter(param)
- "parameter_mrb_#{param}"
- end
-
- def convention_return_variable(func_name)
- "return_of_#{func_name}"
- end
-
- def initialize_variables_for_kwargs(params, structs, func_name=nil)
- result = ''
- return result if params.first == 'void'
- params.each do |param|
- rpart = param.rpartition(' ')
- format = Template::C.format_type(rpart.first)
- if format
- result += format + " #{'*' if Template.struct_types =~ rpart.first.gsub(/ *\*+$/,'')}#{Template::C.convention_parameter(rpart.last)};\n"
- elsif !func_name.nil?
- puts "// \"#{rpart.first}\" is not a parameter datatype that can be currently autobound. From function: \"#{func_name}\" and param: #{rpart.last}\n\n"
- #raise
- end
- end
- result + "\n"
- end
-
- #def needs_mrb_conversion?(datatype)
- # test = Template::C.datatype_to_arg_flag(datatype)
- # if ['i','b','z','f'].include? test
- # false
- # elsif ['o'].include? test
- # true
- # else
- # nil
- # end
- #end
-
- def initialize_variables_for_args(params, structs, func_name=nil)
- result = ''
- return result if params.first == 'void'
- params.each do |param|
- rpart = param.rpartition(' ')
- format = Template::C.format_mrb_type(rpart.first)
- if format
- if Template.struct_types =~ rpart.first || Template.struct_types_pointer =~ rpart.first
- result += format + " #{Template::C.convention_mrb_parameter(rpart.last)};\n"
- else
- result += format + " #{Template::C.convention_parameter(rpart.last)};\n"
- end
- elsif !func_name.nil?
- puts "// \"#{rpart.first}\" is not a parameter datatype that can be currently autobound. From function: \"#{func_name}\" and param: #{rpart.last}\n\n"
- #raise
- end
- end
- result + "\n"
- end
-
- def initialize_return_var(func_datatype, func_name)
- return '' if func_datatype == 'void'
- result = ''
- depointer_datatype = func_datatype.delete_suffix(' *')
- if Template.struct_types =~ depointer_datatype
- result += Template.get_module('Test')
- result += Template.get_class(depointer_datatype, 'Test')
- result += "#{depointer_datatype} *#{Template::C.convention_return_variable(func_name)} = (#{depointer_datatype} *)mrb_malloc(mrb, sizeof(#{depointer_datatype}));\n"
- else
- result += "#{func_datatype} #{Template::C.convention_return_variable(func_name)};\n"
- end
- result
- end
-
- def get_kwargs(params)
- init_array_body = ''
- params.each do |param|
- rpart = param.rpartition(' ')
- init_array_body += "mrb_intern_lit(mrb, \"#{rpart.last.underscore}\"),\n"
- end
- init_array_body.delete_suffix!(",\n")
- %{uint32_t kw_num = #{params.length};
-const mrb_sym kw_names[] = {
-#{init_array_body}
-};
-mrb_value kw_values[kw_num];
-const mrb_kwargs kwargs = { kw_num, 0, kw_names, kw_values, NULL };
-mrb_get_args(mrb, "|:", &kwargs);
- }
- end
-
- def parse_kwargs(params)
- result = ''
- skipped = 0
- params.each_with_index do |param, index|
- rpart = param.rpartition(' ')
- datatype, _space, var_name = param.rpartition(' ')
- if Template.struct_types_all =~ datatype
-
- unwrap = Template.unwrap_struct(Template::C.convention_parameter(var_name), "kw_values[#{index - skipped}]", "mrb_#{datatype.delete_suffix(' *')}_struct", datatype.delete_suffix(' *'))
-
- result += Template::C.unwrap_kwarg(index - skipped,unwrap, nil, "Missing kwarg: #{var_name.underscore}")
- elsif Template.non_struct_types_all =~ datatype
- unwrap = "#{Template::C.convention_parameter(var_name)} = #{Template.to_c(datatype, "kw_values[#{index - skipped}]")};"
- result += Template::C.unwrap_kwarg(index - skipped, unwrap, nil, "#{var_name.underscore}")
- else
- skipped += 1
- next
- end
- end
- result
- end
-
- # unwrap structs
- # convert floats?
- # ignore string
- # ignore boolean
- # ignore int
- def parse_args(params)
- result = ''
- params.each do |param|
- datatype, _space, var_name = param.rpartition(' ')
- next unless Template.struct_types =~ datatype || Template.struct_types_pointer =~ datatype
- format = Template::C.format_type(datatype)
- if format
- # init var
- result += format + " *#{Template::C.convention_parameter(var_name)};\n"
- # unwrap var
- result += Template.unwrap_struct(Template::C.convention_parameter(var_name), Template::C.convention_mrb_parameter(var_name), "mrb_#{datatype.delete_suffix(' *')}_struct", datatype.delete_suffix(' *'))
- else
- # error
- end
- end
- result
- end
-
- def unwrap_kwarg(kwarg_iter, body_if_defined, body_if_undefined = nil, no_argument_error_message = 'Missing Keyword Argument')
- %{
-if (mrb_undef_p(kw_values[#{kwarg_iter}])) {
-#{body_if_undefined || "mrb_load_string(mrb, \"raise ArgumentError.new \\\"#{no_argument_error_message}\\\"\");"}
-} else {
-#{body_if_defined}
-}
- }
- end
-
- end
- end
-
- # methods that convert something from c-land to ruby-land
- module MRuby
- class << self
- # convert a C function name to be
- # formatted like a Ruby method name
- def rubify_func_name(function, params=[])
- func = function.underscore
- if func.start_with? 'is_'
- func = func.delete_prefix('is_') + '?'
- elsif func.start_with? 'set_'
- func = func.delete_prefix('set_') + '=' if params.count == 1 && params.first != 'void'
- end
- func.delete_prefix('get_')
- end
-
- def to_c_function_name(function_name:)
- rubify_func_name(function_name)
- end
-
- def to_getter_name(struct_name:, variable_name: nil)
- rubify_func_name(variable_name)
- end
-
- def to_setter_name(struct_name:, variable_name: nil)
- rubify_func_name(variable_name) + '='
- end
-
- def to_initializer_name(struct_name: nil)
- "initialize"
- end
- end
- end
-
-
- class << self
-
- # could be unsigned
- attr_writer :treated_as_int
- def treated_as_int
- @treated_as_int ||= /^((un)?signed )?int$|^((un)?signed )?long$|^((un)?signed )?short$|^((un)?signed )char$/
- end
- attr_writer :treated_as_int_pointer
- def treated_as_int_pointer
- @treated_as_int_pointer ||= /^((un)?signed )?int \*$|^((un)?signed )?long \*$|^((un)?signed )?short \*$|^((un)?signed )char \*$/
- end
-
- attr_writer :treated_as_bool
- def treated_as_bool
- @treated_as_bool ||= /^bool$/
- end
- attr_writer :treated_as_bool_pointer
- def treated_as_bool_pointer
- @treated_as_bool_pointer ||= /^bool \*$/
- end
-
- attr_writer :treated_as_float
- def treated_as_float
- @treated_as_float ||= /^float$|^double$/
- end
- attr_writer :treated_as_float_pointer
- def treated_as_float_pointer
- @treated_as_float_pointer ||= /^float \*$|^double \*$/
- end
-
- attr_writer :treated_as_string
- def treated_as_string
- @treated_as_string ||= /^(const )?char \*$/
- end
- # Ignore for now
- #attr_writer :treated_as_string_pointer
- #def treated_as_string_pointer
- # @treated_as_string_pointer ||= /^(const )?char \*\*$/
- #end
-
- attr_writer :treated_as_void
- def treated_as_void
- @treated_as_void ||= /^void$/
- end
-
- def non_struct_types
- @non_struct_types ||= Regexp.union(treated_as_int, treated_as_bool, treated_as_float, treated_as_string, treated_as_void)
- end
- def non_struct_types_pointer
- @non_struct_types_pointer ||= Regexp.union(treated_as_int_pointer, treated_as_bool_pointer, treated_as_float_pointer)#, treated_as_string_pointer)
- end
- def non_struct_types_all
- @non_struct_types_all ||= Regexp.union(non_struct_types, non_struct_types_pointer)
- end
-
- attr_writer :struct_types
- def struct_types
- if @struct_types
- @struct_types
- else
- raise "Struct types were not parsed\nRun 'parse_struct_types' first"
- end
- end
- attr_writer :struct_types_pointer
- def struct_types_pointer
- if @struct_types_pointer
- @struct_types_pointer
- else
- raise "Struct types were not parsed\nRun 'parse_struct_types' first"
- end
- end
- attr_writer :struct_types_all
- def struct_types_all
- @struct_types_all ||= Regexp.union(struct_types, struct_types_pointer)
- end
-
- def parse_struct_types(structs)
- struct_types = structs.keys
- struct_types_pointer = struct_types.map do |string|
- "^#{string} \\*$"
- end
- struct_types.map! do |string|
- "^#{string}$"
- end
- @struct_types_pointer = /#{struct_types_pointer.join('|')}/
- @struct_types = /#{struct_types.join('|')}/
- end
-
- def valid_types
- @valid_types ||= Regexp.union(non_struct_types, struct_types)
- end
- def valid_types_pointer
- @valid_types_pointer ||= Regexp.union(non_struct_types_pointer, struct_types_pointer)
- end
- def all_valid_types
- @all_valid_types ||= Regexp.union(valid_types, valid_types_pointer)
- end
-
- def base(gem_name, init_body, final_body)
- %{
- void
- mrb_mruby_#{gem_name}_gem_init(mrb_state* mrb) {
- #{init_body}
-}
-
-void
-mrb_mruby_#{gem_name}_gem_final(mrb_state* mrb) {
-#{final_body}
-}
- }
- end
-
- def format_method_call(func_datatype, func_name, params, is_struct=false)
- result = ''
- #if params.first == 'void'
- # result += "return #{'*' if is_struct}#{Template::C.convention_return_variable(func_name)} = "
- #end
- result += "#{func_name}("
- unless params.first == 'void'
- params.each do |param|
- rpart = param.rpartition(' ')
- result += "#{'*' if Template.struct_types =~ rpart.first}#{"(#{rpart.first})&" if Template.non_struct_types_pointer =~ rpart.first}#{Template::C.convention_parameter(rpart.last)}, "
- end
- end
- result.delete_suffix(', ') + ")"
- end
-
- def format_set_method_call(func_datatype, func_name, params, is_struct=false)
- result = format_method_call(func_datatype, func_name, params, is_struct) + ";\n"
- unless func_datatype == 'void'
- if Template.struct_types_pointer =~ func_datatype
- result = '*' + result
- end
- result = "#{Template::C.convention_return_variable(func_name)} = #{result}"
- if is_struct
- result = '*' + result
- end
- end
- result
- end
-
- def format_return(func_datatype, func_name)
- "return #{Template.to_mrb(func_datatype, Template::C.convention_return_variable(func_name))};"
- end
-
- def init_module(module_name)
- "struct RClass *#{module_name.downcase}_module = mrb_define_module(mrb, \"#{module_name}\");"
- end
-
- def get_module(module_name)
- "struct RClass *#{module_name.downcase}_mrb_module = mrb_module_get(mrb, \"#{module_name}\");\n"
- end
-
- def get_class(class_name, defined_under)
- "struct RClass *#{class_name.downcase}_mrb_class = mrb_class_get_under(mrb, #{defined_under.downcase}_mrb_module, mrb_#{class_name}_struct.struct_name);\n"
- end
-
- def init_module_function(module_name, function_name, mrb_function_name, mrb_args)
- %{
- mrb_define_module_function(mrb, #{module_name}, "#{function_name}", mrb_#{mrb_function_name}, #{mrb_args});
- }
- end
-
- # define under needs the C name, not the ruby name which may be confusing
- def init_class(class_name, define_under, is_struct_wrapper = true)
- %{
- struct RClass *#{class_name.downcase}_class = mrb_define_class_under(mrb, #{define_under}, \"#{class_name}\", mrb->object_class);#{
- if is_struct_wrapper
- "\nMRB_SET_INSTANCE_TT(#{class_name.downcase}_class, MRB_TT_DATA);"
- end
-}
- }
- end
-
- def function(function_name, body)
- %{
-static mrb_value
-mrb_#{function_name}(mrb_state* mrb, mrb_value self) {
-#{body}
-}
- }
- end
-
- def init_function(class_name, function_name, mrb_function_name, mrb_args)
- %{mrb_define_method(mrb, #{class_name}, "#{function_name}", mrb_#{mrb_function_name}, #{mrb_args});
- }
- end
-
- def get_args(req_arg_hash, opt_arg_hash=nil)
- raise 'opt_arg_hash feature not implemented yet' if opt_arg_hash
- result = ''
- tail = ''
- flags = ''
- req_arg_hash.each do |var_name, var_datatype|
- #if var_datatype != 'unsigned char'
- #if Template.non_struct_types =~ var_datatype
- #result += "#{Template::C.format_type(var_datatype)} #{Template::C.convention_parameter(var_name)};\n"
- #else
- # result += "mrb_int #{var_name};\n"
- #end
- if Template.struct_types_all =~ var_datatype
- tail += ", &#{Template::C.convention_mrb_parameter(var_name)}"
- else
- tail += ", &#{Template::C.convention_parameter(var_name)}"
- end
- flags += datatype_to_arg_flag(var_datatype)
- end
- result += "mrb_get_args(mrb, \"#{flags}\"#{tail});\n"
- end
-
- def datatype_to_arg_flag(datatype)
- if Template.treated_as_int =~ datatype || Template.treated_as_int_pointer =~ datatype
- 'i'
- elsif Template.treated_as_bool =~ datatype || Template.treated_as_bool_pointer =~ datatype
- 'b'
- elsif Template.treated_as_float =~ datatype || Template.treated_as_float_pointer =~ datatype
- 'f'
- elsif Template.treated_as_string =~ datatype
- 'z'
- elsif Template.struct_types =~ datatype || Template.struct_types_pointer =~ datatype
- 'o'
- else # failed to match
- nil
- end
- end
-
- def unwrap_struct(var_name, 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});
- if(#{var_name}) #{'{'} mrb_free(mrb, #{var_name}); #{'}'}
- mrb_data_init(#{target}, NULL, &#{mrb_type});
-#{var_name} = (#{type} *)mrb_malloc(mrb, sizeof(#{type}));
- }
- end
-
- def define_module(module_name)
- %{struct RClass *#{module_name.downcase} = mrb_define_module(mrb, "#{module_name}");
- }
- end
-
- # for converting mrb to C
- def to_c(type, variable)
- if (Template.treated_as_int =~ type) || (Template.treated_as_bool =~ type)
- "mrb_as_int(mrb, #{variable})"
- elsif (Template.treated_as_int_pointer =~ type) || (Template.treated_as_bool_pointer =~ type)
- "mrb_as_int(mrb, #{variable})"
- elsif Template.treated_as_float =~ type
- "mrb_as_float(mrb, #{variable})"
- elsif Template.treated_as_float_pointer =~ type
- "mrb_as_float(mrb, #{variable})"
- elsif Template.treated_as_string =~ type
- "mrb_str_to_cstr(mrb, #{variable})"
- else
- "#{type} and #{variable}"
- end
- end
-
- # for converting C to mrb
- def to_mrb(type, variable)
- if Template.treated_as_int =~ type
- "mrb_fixnum_value(#{variable})"
- elsif Template.treated_as_float =~ type
- "mrb_float_value(mrb, #{variable})"
- elsif Template.treated_as_bool =~ type
- "mrb_bool_value(#{variable})"
- elsif Template.treated_as_int_pointer =~ type
- "mrb_fixnum_value(*#{variable})"
- elsif Template.treated_as_float_pointer =~ type
- "mrb_float_value(mrb, *#{variable})"
- elsif Template.treated_as_bool_pointer =~ type
- "mrb_bool_value(*#{variable})"
- elsif Template.treated_as_string =~ type
- "mrb_str_new_cstr(mrb, #{variable})"
- elsif Template.treated_as_void =~ type
- 'mrb_nil_value()'
- elsif Template.struct_types =~ type
- "mrb_obj_value(Data_Wrap_Struct(mrb, #{type.downcase}_mrb_class, &mrb_#{type}_struct, #{variable}))"
- elsif Template.struct_types_pointer =~ type
- "mrb_obj_value(Data_Wrap_Struct(mrb, #{type.delete_suffix(' *').downcase}_mrb_class, &mrb_#{type.delete_suffix(' *')}_struct, #{variable}))"
- end
- end
-
-
- # generate a return of a ruby bound C function
- def return_format(function, params)
- func_rpart = function.rpartition(' ')
- func_datatype = func_rpart.first
- func_name = func_rpart.last
- result = ''
- if func_datatype == 'void'
- if params.first == 'void'
- result = "#{func_name}();\nreturn mrb_nil_value();"
- else
- result = "#{func_name}("
- result += params.first.rpartition(' ').last
-
- params.drop(1).each do |param|
- result += ", #{param.rpartition(' ').last}"
- end
- result += ");\nreturn mrb_nil_value();"
- end
- elsif params.first == 'void'
- result = "return " + Tplt.to_mrb(func_datatype, "#{func_name}()") + ';'
- else
- temp_params = params.first.rpartition(' ').last
-
- params.drop(1).each do |param|
- temp_params += ", #{param.rpartition(' ').last}"
- end
- result = 'return ' + Tplt.to_mrb(func_datatype, "#{func_name}(#{temp_params})") + ';'
- end
- result
- end
-
- # doesnt seem correct?
- def return_format_struct(function)
- func_rpart = function.rpartition(' ')
- func_datatype = func_rpart.first.delete_suffix(' *')
- func_name = func_rpart.last
- "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)
- %{
- #{"void mrb_helper_#{struct}_free(mrb_state*, void*);" if free_body}
-
- static const struct mrb_data_type mrb_#{struct}_struct = {
- "#{struct}",
- #{
- if free_body
- "mrb_helper_#{struct}_free"
- else
- "mrb_free"
- end
-}
- };
- #{
- if free_body
-
- %{
- void
- mrb_helper_#{struct}_free(mrb_state* mrb, void*ptr) {
- #{struct} *struct_data = (#{struct}*)ptr;
- #{free_body}
-mrb_free(mrb, ptr);
- }
- }
- end
- }
- }
- end
-
- end
-end
-