talk 2.0.1 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +4 -0
- data/.travis.yml +6 -0
- data/Gemfile +10 -0
- data/README.md +6 -0
- data/Rakefile +9 -0
- data/features/class-field.feature +226 -0
- data/features/class.feature +95 -0
- data/features/enumeration-constant.feature +76 -0
- data/features/enumeration.feature +35 -0
- data/features/glossary-term.feature +46 -0
- data/features/glossary.feature +35 -0
- data/features/step_definitions/class-field.rb +74 -0
- data/features/step_definitions/class.rb +50 -0
- data/features/step_definitions/enumeration-constant.rb +42 -0
- data/features/step_definitions/enumeration.rb +29 -0
- data/features/step_definitions/glossary-term.rb +31 -0
- data/features/step_definitions/glossary.rb +23 -0
- data/features/support/env.rb +261 -0
- data/lib/context.rb +282 -0
- data/lib/context_class.rb +224 -0
- data/lib/contexts/README.md +274 -0
- data/lib/contexts/base.rb +6 -0
- data/lib/contexts/boolean.rb +5 -0
- data/lib/contexts/class.rb +11 -0
- data/lib/contexts/constant.rb +5 -0
- data/lib/contexts/enumeration.rb +20 -0
- data/lib/contexts/field.rb +47 -0
- data/lib/contexts/glossary.rb +7 -0
- data/lib/contexts/inherits.rb +3 -0
- data/lib/contexts/map.rb +7 -0
- data/lib/contexts/meta.rb +2 -0
- data/lib/contexts/method.rb +15 -0
- data/lib/contexts/numeric.rb +5 -0
- data/lib/contexts/protocol.rb +8 -0
- data/lib/contexts/reference.rb +6 -0
- data/lib/contexts/string.rb +5 -0
- data/lib/contexts/target.rb +11 -0
- data/lib/contexts/term.rb +11 -0
- data/lib/languages/java/java.rb +145 -0
- data/lib/languages/java/templates/class.java.erb +22 -0
- data/lib/languages/java/templates/enumeration.java.erb +10 -0
- data/lib/languages/java/templates/glossary.java.erb +8 -0
- data/lib/languages/language.rb +172 -0
- data/lib/languages/objc/objc.rb +162 -0
- data/lib/languages/objc/templates/TalkClasses.h.erb +3 -0
- data/lib/languages/objc/templates/TalkClassesForward.h.erb +2 -0
- data/lib/languages/objc/templates/TalkConstants.h.erb +22 -0
- data/lib/languages/objc/templates/TalkObjectList.h.erb +4 -0
- data/lib/languages/objc/templates/class.h.erb +21 -0
- data/lib/languages/objc/templates/class.m.erb +43 -0
- data/lib/parse_error.rb +4 -0
- data/lib/parser.rb +119 -0
- data/lib/registry.rb +151 -0
- data/lib/talk.rb +5 -0
- data/talk.gemspec +18 -0
- metadata +71 -3
@@ -0,0 +1,11 @@
|
|
1
|
+
property :name
|
2
|
+
|
3
|
+
tag_description
|
4
|
+
tag :language, :class => :string
|
5
|
+
tag :destination, :class => :string
|
6
|
+
tag :map, :multi => true
|
7
|
+
tag :meta, :multi => true, :unique => :name
|
8
|
+
tag :rootclass, :class => :string
|
9
|
+
tag :template, :class => :string
|
10
|
+
tag :prune, :class => :boolean
|
11
|
+
tag_end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
def make_source
|
4
|
+
types = [ :class, :enumeration, :glossary]
|
5
|
+
types.each do |type|
|
6
|
+
@base[type].each do |current|
|
7
|
+
@current = current
|
8
|
+
@current[:field] ||= [] if type == :class
|
9
|
+
generate_template(filename_for_entity(@current), type.to_s+".java.erb")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def filename_for_entity(name)
|
15
|
+
name = name[:name] if name.is_a? Hash
|
16
|
+
name.gsub(".", "/") + ".java"
|
17
|
+
end
|
18
|
+
|
19
|
+
def autogenerated_warning
|
20
|
+
<<-AUTOGEN_DONE
|
21
|
+
/* Autogenerated from Talk
|
22
|
+
** Please do not edit this file directly. Instead, modify the underlying .talk files. */
|
23
|
+
AUTOGEN_DONE
|
24
|
+
end
|
25
|
+
|
26
|
+
def definition_reference(tag)
|
27
|
+
"@talkFile #{tag[:__meta][:file]}:#{tag[:__meta][:line]}"
|
28
|
+
end
|
29
|
+
|
30
|
+
def rootclass
|
31
|
+
@target[:rootclass] || "io.usetalk.TalkObject"
|
32
|
+
end
|
33
|
+
|
34
|
+
def superclass(cls)
|
35
|
+
cls[:inherits] || rootclass
|
36
|
+
end
|
37
|
+
|
38
|
+
def class_package(cls)
|
39
|
+
cls[:name].split(".")[0..-2].join(".")
|
40
|
+
end
|
41
|
+
|
42
|
+
def list_references_for_class(cls)
|
43
|
+
references = Set.new
|
44
|
+
cls[:field].each do |field|
|
45
|
+
unless is_primitive?(field[:type].first) then
|
46
|
+
references.add(field[:type])
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
references.to_a
|
51
|
+
end
|
52
|
+
|
53
|
+
def import_classes
|
54
|
+
(list_references_for_class(@current).map { |name| "import #{name};"}).join("\n")
|
55
|
+
end
|
56
|
+
|
57
|
+
def comment_block(tag, indent_level=0)
|
58
|
+
lines = []
|
59
|
+
indent = "\t" * indent_level
|
60
|
+
lines.push(indent + "/*!")
|
61
|
+
lines.push(wrap_text_to_width(tag[:description], 80, indent + " * ")) unless tag[:description].nil?
|
62
|
+
lines.push(indent + " * ")
|
63
|
+
lines.push(indent + " * " + definition_reference(tag))
|
64
|
+
lines.push(indent + " */")
|
65
|
+
|
66
|
+
lines.join("\n")
|
67
|
+
end
|
68
|
+
|
69
|
+
def detail_comment_block(cls)
|
70
|
+
lines = []
|
71
|
+
lines.push("\t/**")
|
72
|
+
lines.push("\t * #{truncated_name cls[:name]}")
|
73
|
+
cls[:field].each { |f| lines.push("\t * @param #{field_datatype f} #{f[:name]}") }
|
74
|
+
lines.join("\n")
|
75
|
+
end
|
76
|
+
|
77
|
+
def field_datatype_rec(field, stack)
|
78
|
+
return field_datatype_basic(field, stack.last) if stack.length == 1
|
79
|
+
t = stack.last
|
80
|
+
|
81
|
+
r = field_datatype_rec(field, stack[0 .. -2])
|
82
|
+
if is_array? t then
|
83
|
+
"[]"
|
84
|
+
elsif is_dict? t then
|
85
|
+
"Map<String, #{r}>"
|
86
|
+
else
|
87
|
+
nil
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def field_datatype_basic(field, type)
|
92
|
+
if is_primitive? type then
|
93
|
+
case type
|
94
|
+
when "string"
|
95
|
+
"String"
|
96
|
+
when "real"
|
97
|
+
"double"
|
98
|
+
when "bool"
|
99
|
+
"boolean"
|
100
|
+
when "object"
|
101
|
+
"Object"
|
102
|
+
when "talkobject"
|
103
|
+
"TalkObject"
|
104
|
+
else
|
105
|
+
size = integer_size(type)
|
106
|
+
size *= 2 if is_unsigned? type # java has no unsigned type; just use the next size up
|
107
|
+
case
|
108
|
+
when 8
|
109
|
+
"byte"
|
110
|
+
when 16
|
111
|
+
"short"
|
112
|
+
when 32
|
113
|
+
"int"
|
114
|
+
when 64
|
115
|
+
"long"
|
116
|
+
when 128
|
117
|
+
"BigDecimal"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
else
|
121
|
+
truncated_name type
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def field_datatype(field)
|
126
|
+
field_datatype_rec(field, field[:type])
|
127
|
+
end
|
128
|
+
|
129
|
+
def field_variable(field)
|
130
|
+
lines = []
|
131
|
+
lines.push comment_block(field, 1)
|
132
|
+
lines.push "\tprotected #{field_datatype(field)} #{field[:name]};"
|
133
|
+
lines.join("\n")
|
134
|
+
end
|
135
|
+
|
136
|
+
def field_accessors(field)
|
137
|
+
lines.push wrap_text(field[:description], " * ", 1)
|
138
|
+
lines.push field[:deprecated] if field.has_key? :deprecated
|
139
|
+
lines.push definition_reference(field)
|
140
|
+
lines.push " * @param #{field[:name]} #{field[:description]}"
|
141
|
+
lines.push "\tpublic void #{setter_name(field)}(#{field_datatype(field)} #{field[:name]}) {"
|
142
|
+
lines.push "\t\tthis.#{field[:name]} = #{field[:name]}"
|
143
|
+
lines.push "\t}"
|
144
|
+
lines.join "\n"
|
145
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<%= autogenerated_warning %>
|
2
|
+
package <%= class_package(@current) %>;
|
3
|
+
<%= import_classes %>
|
4
|
+
|
5
|
+
<%= comment_block(@current) %>
|
6
|
+
public class <%= truncated_name(@current) %> extends <%= superclass(@current) %>
|
7
|
+
{
|
8
|
+
<%= detail_comment_block(@current) %>
|
9
|
+
/**
|
10
|
+
* <%= truncated_name @current %> - Default Constructor
|
11
|
+
*
|
12
|
+
*/
|
13
|
+
public <%= truncated_name @current %>() {}
|
14
|
+
<%=
|
15
|
+
(@current[:field].map do |f|
|
16
|
+
field_variable(f)
|
17
|
+
end).join("\n")
|
18
|
+
|
19
|
+
(@current[:field].map do |f|
|
20
|
+
field_accessors(f)
|
21
|
+
end).join("\n")
|
22
|
+
%>}
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<%= autogenerated_warning %>
|
2
|
+
package <%= class_package(@current) %>;
|
3
|
+
|
4
|
+
<%= comment_block(@current) %>
|
5
|
+
public class <%= truncated_name(@current) %> extends <%= rootclass %>
|
6
|
+
{<% @current[:field].each do |field| %>
|
7
|
+
// <%= field[:description] %>
|
8
|
+
@TalkDescription(description = "<%= field[:description] %>")
|
9
|
+
public final static int <%= field[:name] %> = <%= field[:value] %>;
|
10
|
+
<%= end %>}
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<%= autogenerated_warning %>
|
2
|
+
package <%= class_package(@current) %>;
|
3
|
+
|
4
|
+
<%= comment_block(@current) %>
|
5
|
+
public class <%= truncated_name(@current) %>
|
6
|
+
{<%= @current[:field].each do |field| %>
|
7
|
+
public final static String <%= field[:name] %> = "<%= field[:value] %>";<% end %>
|
8
|
+
}
|
@@ -0,0 +1,172 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
def classname_for_filename(name) # /path/to/file_name.rb to FileName
|
5
|
+
File.basename(name.to_s, ".rb").split('_').collect { |word| word.capitalize }.join("")
|
6
|
+
end
|
7
|
+
|
8
|
+
def is_primitive?(type)
|
9
|
+
primitives = [
|
10
|
+
"uint8", "uint16", "uint32", "uint64",
|
11
|
+
"int8", "int16", "int32", "int64",
|
12
|
+
"string", "real", "bool", "object", "talkobject" ]
|
13
|
+
primitives.include? type
|
14
|
+
end
|
15
|
+
|
16
|
+
module Talk
|
17
|
+
class Language
|
18
|
+
attr_reader :supported_languages
|
19
|
+
|
20
|
+
class << self
|
21
|
+
def path_for_language(lang)
|
22
|
+
File.absolute_path(File.join(File.dirname(__FILE__), "#{lang}/#{lang}.rb"))
|
23
|
+
end
|
24
|
+
|
25
|
+
def load_supported_languages
|
26
|
+
@languages ||= {}
|
27
|
+
|
28
|
+
local_dir = File.dirname(__FILE__)
|
29
|
+
trimmed = Dir["#{local_dir}/*/"].map { |subdir| subdir.gsub(/\/$/, "") }
|
30
|
+
supported = trimmed.select { |subdir| File.exists?(File.join(subdir, File.basename(subdir)+".rb")) }
|
31
|
+
supported.each { |lang| load_language(lang) }
|
32
|
+
supported.map { |lang| lang.to_sym }
|
33
|
+
end
|
34
|
+
|
35
|
+
def load_language(lang_name)
|
36
|
+
lang_name = File.basename(lang_name.to_s, ".rb").to_sym
|
37
|
+
new_classname = classname_for_filename(lang_name)
|
38
|
+
source_file = path_for_language(lang_name)
|
39
|
+
|
40
|
+
lang = Class.new(Talk::Language) {}
|
41
|
+
|
42
|
+
lang.class_eval( IO.read(source_file), source_file )
|
43
|
+
lang.class_eval( "def path\n\t\"#{File.dirname(source_file)}\"\nend" )
|
44
|
+
lang.class_eval( "def name\n\t\"#{lang_name}\"\nend" )
|
45
|
+
@languages[lang_name.to_sym] = lang
|
46
|
+
end
|
47
|
+
|
48
|
+
def language_named(lang_name)
|
49
|
+
load_supported_languages if @languages.nil?
|
50
|
+
@languages[lang_name.to_sym].new
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def initialize
|
55
|
+
@written = {}
|
56
|
+
end
|
57
|
+
|
58
|
+
def render(base, target)
|
59
|
+
@base = base
|
60
|
+
@target = target
|
61
|
+
@output_path = find_output_path
|
62
|
+
|
63
|
+
make_source
|
64
|
+
prune if @target[:prune]
|
65
|
+
end
|
66
|
+
|
67
|
+
def write(path, contents, conditional=true)
|
68
|
+
@written[File.absolute_path(path)] = contents
|
69
|
+
return if conditional and File.exists? path and IO.read(path) == contents
|
70
|
+
|
71
|
+
FileUtils::mkdir_p(File.dirname(path))
|
72
|
+
File.write(path, contents)
|
73
|
+
end
|
74
|
+
|
75
|
+
def prune
|
76
|
+
# Delete anything we didn't conditionally write, unless it's a directory
|
77
|
+
dirs = []
|
78
|
+
Dir.glob(@output_path+"/**/*").each do |path|
|
79
|
+
abs_path = File.absolute_path(path)
|
80
|
+
unless @written.has_key?(abs_path) then
|
81
|
+
if File.directory?(abs_path) then
|
82
|
+
dirs.push abs_path
|
83
|
+
else
|
84
|
+
FileUtils::rm(abs_path)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Now sort the directories by length, so longest directories are first
|
90
|
+
# Since these are abspaths, that should guarantee subdirectories come before parents
|
91
|
+
# Then delete each empty directory, tested by containing no entries other than '.' and '..'
|
92
|
+
dirs.sort! { |a,b| b.length <=> a.length }
|
93
|
+
dirs.each { |dir| FileUtils::rmdir(dir) if (Dir.entries(dir) - %w{ . .. }).empty? }
|
94
|
+
end
|
95
|
+
|
96
|
+
def find_output_path
|
97
|
+
@target[:destination]
|
98
|
+
end
|
99
|
+
|
100
|
+
def generate_template(output_file, template_file=nil)
|
101
|
+
template_file ||= output_file + ".erb"
|
102
|
+
template_contents = IO.read(File.join(self.path, "templates", template_file))
|
103
|
+
erb = ERB.new(template_contents)
|
104
|
+
erb.filename = template_file
|
105
|
+
source = erb.result(binding)
|
106
|
+
filename = File.join(@output_path, output_file)
|
107
|
+
write(filename, source)
|
108
|
+
source
|
109
|
+
end
|
110
|
+
|
111
|
+
def meta(name)
|
112
|
+
return nil if @target[:meta].nil?
|
113
|
+
name = name.to_s
|
114
|
+
|
115
|
+
@target[:meta].each do |meta|
|
116
|
+
return meta[:value] if meta[:name].to_s == name
|
117
|
+
end
|
118
|
+
|
119
|
+
nil
|
120
|
+
end
|
121
|
+
|
122
|
+
def string_overlap(a,b)
|
123
|
+
[a.length, b.length].min.times do |i|
|
124
|
+
if a[i] != b[i] then
|
125
|
+
return "" if i == 0
|
126
|
+
return a[0..i-1]
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
a.length < b.length ? a : b
|
131
|
+
end
|
132
|
+
|
133
|
+
def wrap_text_to_width(text, width=80, preamble="")
|
134
|
+
width -= preamble.length
|
135
|
+
words = text.split(/\s+/)
|
136
|
+
lines = []
|
137
|
+
|
138
|
+
words.each do |word|
|
139
|
+
if lines.empty? or (lines.last + " " + word).length >= width then
|
140
|
+
lines.push (preamble + word)
|
141
|
+
else
|
142
|
+
lines.last << " " + word
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
lines.empty? ? "" : lines.join("\n")
|
147
|
+
end
|
148
|
+
|
149
|
+
def common_class_prefix
|
150
|
+
prefix = nil
|
151
|
+
@base[:class].each do |cls|
|
152
|
+
if prefix.nil? then
|
153
|
+
prefix = cls[:name]
|
154
|
+
else
|
155
|
+
prefix = string_overlap(prefix, cls[:name])
|
156
|
+
return nil if prefix.length == 0
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
prefix
|
161
|
+
end
|
162
|
+
|
163
|
+
def classname_for_filename(name) # /path/to/file_name.rb to FileName
|
164
|
+
File.basename(name.to_s, ".rb").split('_').collect { |word| word.capitalize }.join("")
|
165
|
+
end
|
166
|
+
|
167
|
+
def truncated_name(name)
|
168
|
+
name = name[:name] if name.is_a? Hash
|
169
|
+
name.split('.').last
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
def make_source
|
2
|
+
@prefix = common_class_prefix if meta(:namespace) == "true"
|
3
|
+
master_files = [ "TalkClasses.h", "TalkClassesForward.h", "TalkConstants.h", "TalkObjectList.h"]
|
4
|
+
master_files.each { |template| generate_template(template) }
|
5
|
+
|
6
|
+
@base[:class].each do |cls|
|
7
|
+
@current_class = cls
|
8
|
+
@current_class[:field] ||= []
|
9
|
+
file_base = filename_for_class(cls)
|
10
|
+
[".h", ".m"].each { |ext| generate_template(file_base+ext, "class"+ext+".erb") }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def filename_for_class(cls)
|
15
|
+
class_dir = "classes"
|
16
|
+
if meta(:namespace) == "true" then
|
17
|
+
namespace = cls[:name][@prefix.length..-1].split(".")[0..-2]
|
18
|
+
return File.join(class_dir, truncated_name(cls)) if namespace.empty?
|
19
|
+
|
20
|
+
namespace = namespace[1..-1] while namespace[0].length == 0
|
21
|
+
File.join(class_dir, namespace.join("/"), truncated_name(cls))
|
22
|
+
else
|
23
|
+
File.join(class_dir, truncated_name(cls))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def autogenerated_warning
|
28
|
+
<<-AUTOGEN_DONE
|
29
|
+
// Autogenerated from Talk
|
30
|
+
// Please do not edit this file directly. Instead, modify the underlying .talk files.
|
31
|
+
AUTOGEN_DONE
|
32
|
+
end
|
33
|
+
|
34
|
+
def glossary_term_name(name)
|
35
|
+
"k"+name
|
36
|
+
end
|
37
|
+
|
38
|
+
def constant_definition(constant)
|
39
|
+
"#{constant[:name]} = #{constant[:value].to_i}, #{comment_line(constant)}"
|
40
|
+
end
|
41
|
+
|
42
|
+
def comment_line(tag)
|
43
|
+
tag[:description].nil? ? "" : "//!< #{tag[:description]}"
|
44
|
+
end
|
45
|
+
|
46
|
+
def comment_block(tag, indent_level=0)
|
47
|
+
lines = []
|
48
|
+
indent = "\t" * indent_level
|
49
|
+
lines.push(indent + "/*!")
|
50
|
+
lines.push(wrap_text_to_width(tag[:description], 80, indent + " * ")) unless tag[:description].nil?
|
51
|
+
lines.push(indent + " * ")
|
52
|
+
lines.push(indent + " * " + definition_reference(tag))
|
53
|
+
lines.push(indent + " */")
|
54
|
+
|
55
|
+
lines.join("\n")
|
56
|
+
end
|
57
|
+
|
58
|
+
def definition_reference(tag)
|
59
|
+
"@talkFile #{tag[:__meta][:file]}:#{tag[:__meta][:line]}"
|
60
|
+
end
|
61
|
+
|
62
|
+
def rootclass
|
63
|
+
@target[:rootclass] || "TalkObject"
|
64
|
+
end
|
65
|
+
|
66
|
+
def superclass(cls)
|
67
|
+
cls[:inherits] || rootclass
|
68
|
+
end
|
69
|
+
|
70
|
+
def is_native?(type)
|
71
|
+
type != "talkobject" and is_primitive?(type)
|
72
|
+
end
|
73
|
+
|
74
|
+
def is_array?(type)
|
75
|
+
type == "[]"
|
76
|
+
end
|
77
|
+
|
78
|
+
def is_dict?(type)
|
79
|
+
type == "{}"
|
80
|
+
end
|
81
|
+
|
82
|
+
def mapped_name(container_name, object_name, type, name_key=:name)
|
83
|
+
object_name = object_name[:name] if object_name.is_a? Hash
|
84
|
+
container_name = container_name[:name] if container_name.is_a? Hash
|
85
|
+
container_name = truncated_name(container_name)
|
86
|
+
|
87
|
+
@target[:map].each do |map|
|
88
|
+
matches = (map[:type] == type.to_s && map[:class_name] == container_name && map[:field_name] == object_name)
|
89
|
+
return map[:new_field_name] if matches
|
90
|
+
end
|
91
|
+
|
92
|
+
object_name
|
93
|
+
end
|
94
|
+
|
95
|
+
def assist_line(field)
|
96
|
+
return nil if field[:type].length <= 1
|
97
|
+
elements = []
|
98
|
+
field[:type].reverse.each do |type|
|
99
|
+
elements.push case
|
100
|
+
when is_array?(type)
|
101
|
+
"array"
|
102
|
+
when is_dict?(type)
|
103
|
+
"dict"
|
104
|
+
when type == "talkobject"
|
105
|
+
"TalkObject"
|
106
|
+
when is_native?(type)
|
107
|
+
"native"
|
108
|
+
else
|
109
|
+
truncated_name(type)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
elements.join(".")
|
114
|
+
end
|
115
|
+
|
116
|
+
def trimmed_fields(cls)
|
117
|
+
return cls[:field] unless truncated_name(cls[:name]) == 'NamedObjectWrapper'
|
118
|
+
cls[:field].reject { |f| f[:name] == "body" }
|
119
|
+
end
|
120
|
+
|
121
|
+
def dynamic_body_for_named_wrapper
|
122
|
+
return "@dynamic body;" if truncated_name(@current_class[:name]) == 'NamedObjectWrapper'
|
123
|
+
""
|
124
|
+
end
|
125
|
+
|
126
|
+
def primitive_type(unsigned, size)
|
127
|
+
type = "int#{size}_t"
|
128
|
+
type = "u" + type if unsigned
|
129
|
+
type
|
130
|
+
end
|
131
|
+
|
132
|
+
def field_tags(field)
|
133
|
+
case field[:type].last
|
134
|
+
when "real", "bool", "uint8", "uint16", "uint32", "uint64", "int8", "int16", "int32", "int64"
|
135
|
+
"(readwrite,assign)"
|
136
|
+
else
|
137
|
+
"(readwrite,nonatomic,retain)"
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def field_definition(cls, field)
|
142
|
+
base_type = field[:type].last
|
143
|
+
objc_type = case
|
144
|
+
when is_array?(base_type)
|
145
|
+
"NSMutableArray *"
|
146
|
+
when is_dict?(base_type)
|
147
|
+
"NSMutableDictionary *"
|
148
|
+
when (base_type == "talkobject" or base_type == "object")
|
149
|
+
"TalkObject *"
|
150
|
+
when base_type.match(/(u)?int(8|16|32|64)/)
|
151
|
+
primitive_type(not($1.nil?), $2)
|
152
|
+
when base_type == "real"
|
153
|
+
"double"
|
154
|
+
when base_type == "bool"
|
155
|
+
"BOOL"
|
156
|
+
when base_type == "string"
|
157
|
+
"NSString *"
|
158
|
+
else
|
159
|
+
truncated_name(base_type) + " *"
|
160
|
+
end
|
161
|
+
"#{objc_type} #{mapped_name(cls, field, :field)}"
|
162
|
+
end
|