talk 2.0.1 → 2.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|