Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/main.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
require_relative 'translators/cpp'
# require_relative 'translators/rust'
require_relative 'translators/docs'
require_relative 'translators/csharpwasm'

# Access to config vars
include Config
Expand Down
2 changes: 1 addition & 1 deletion src/translators/abstract_translator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def all
.to_h
end
def adapters
all.select { |c| ![:CLIB, :DOCS].include? c }.values
all.select { |c| ![:CLIB, :DOCS, :CSHARPWASM].include? c }.values
end
module_function :all
module_function :adapters
Expand Down
160 changes: 160 additions & 0 deletions src/translators/csharpwasm.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
require_relative 'abstract_translator'

module Translators
#
# C# WASM binding generator (primitive-only)
#
class CSharpWasm < AbstractTranslator
PRIMITIVE_TYPES = %w[
void bool char int short long float double string
].to_set

def initialize(data, logging = false)
super(data, logging)
end

def render_templates
grouped = grouped_data
{
'SplashKitBindings.Generated.cs' => render_csharp_bindings(grouped_data),
'splashKitMethods.generated.js' => render_method_names_js(grouped)
}
end

def grouped_data
@data
.group_by { |_, header| header[:group] }
.map do |group_key, group_data|
tmpl = {
brief: '', description: '', functions: [],
typedefs: [], structs: [], enums: [], defines: []
}
merged = group_data.to_h.values.reduce(tmpl) do |memo, h|
h.each { |k, v| memo[k] += v if v && memo.key?(k) && !v.empty? }
memo
end
map_signatures(merged)
[group_key, merged]
end
.sort
.to_h
end

def run_for_each_adapter
Translators.adapters.each { |cls| yield cls.new(@data) }
end

def map_signatures(data)
run_for_each_adapter do |adpt|
key = adpt.name.to_s.downcase

data[:functions].each do |fn|
fn[:signatures] ||= {}
fn[:signatures][key] =
if adpt.respond_to?(:docs_signatures_for)
adpt.docs_signatures_for(fn)
else
adpt.sk_signature_for(fn)
end
end

data[:enums].each do |enum|
enum[:signatures] ||= {}
vals = enum[:constants].map do |n, d|
{
name: n.to_s,
description: d[:description] || '',
value: d[:number] || 0
}
end
if adpt.respond_to?(:enum_signature_syntax)
enum[:signatures][key] = adpt.enum_signature_syntax(enum[:name], vals)
end
end
end
end

def render_csharp_bindings(grouped)
lines = []
lines << 'using System.Runtime.InteropServices.JavaScript;'
lines << ''
lines << 'namespace SplashKitSDK'
lines << '{'
lines << ' public partial class SplashKit'
lines << ' {'

grouped.each_value do |grp|
grp[:functions].each do |fn|
sigs = fn[:signatures] || {}
raw = sigs['csharpwasm'] || sigs['csharp']
next unless raw

arr = raw.is_a?(Array) ? raw : [raw]
sig_line = arr.find { |s| s =~ /public static .*SplashKit\./ } || arr.find { |s| s =~ /\w+\(.*\)/ }
next unless sig_line

if sig_line =~ /public\s+static\s+(\w+)\s+SplashKit\.(\w+)\((.*)\);?/
ret, fn_name, params = $1, $2, $3
next unless primitive_type?(ret)

param_list = params.strip.split(',').map do |p|
p.strip.split(' ', 2)
end
next unless param_list.all? { |t, _n| primitive_type?(t) }

cs_method = fn_name.gsub(/(?:^|_)([a-z])/) { $1.upcase }
cs_params = param_list.map { |t, n| "#{cs_type(t)} #{n}" }.join(', ')

lines << " [JSImport(\"SplashKitBackendWASM.#{fn[:name]}\", \"main.js\")]"
lines << " public static partial #{cs_type(ret)} #{cs_method}(#{cs_params});"
lines << ''
end
end
end

lines << ' }'
lines << '}'
lines.join("\n")
end

def render_method_names_js(grouped)
method_names = grouped.values.flat_map do |grp|
grp[:functions].map { |fn| fn[:name] }
end.uniq.sort

lines = []
lines << 'const methods = `'
lines += method_names.map.with_index do |name, i|
suffix = i == method_names.size - 1 ? '' : ','
" #{name}#{suffix}"
end
lines << '`;'
lines << ''
lines << 'export default methods;'

lines.join("\n")
end

def post_execute
puts 'Place `splashKitMethods.generated.js` and `SplashKitBindings.Generated.cs` in `generated/csharpwasm` of the `splashkit-core` repo'
end

private

def cs_type(type)
{
'int' => 'int',
'float' => 'float',
'double' => 'double',
'bool' => 'bool',
'char' => 'char',
'void' => 'void',
'string' => 'string'
}[type] || type.split('_').map(&:capitalize).join
end

def primitive_type?(type)
PRIMITIVE_TYPES.include?(type.downcase)
end
end
end
2 changes: 1 addition & 1 deletion src/translators/python.rb
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ def sk_signature_for(function)
#
def enum_signature_syntax(enum_name, enum_values)
# Convert the enum name to snake case
formatted_enum_name = enum_name.to_s.to_snake_case
formatted_enum_name = enum_name.to_s.to_pascal_case

# Format each enum value with the category prefix, and join them with a comma
formatted_values = enum_values.map do |value|
Expand Down