csquare 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gemtest +0 -0
- data/Gemfile +8 -0
- data/History.txt +12 -0
- data/Manifest.txt +21 -0
- data/README.rdoc +63 -0
- data/Rakefile +39 -0
- data/lib/csquare.rb +1089 -0
- data/lib/csquare/base.rb +36 -0
- data/lib/csquare/cerb.rb +82 -0
- data/lib/csquare/function.rb +175 -0
- data/lib/csquare/generator.rb +374 -0
- data/lib/csquare/generator/assign_op.rb +53 -0
- data/lib/csquare/generator/binary_op.rb +72 -0
- data/lib/csquare/generator/blueprint.rb +357 -0
- data/lib/csquare/generator/boolean_op.rb +32 -0
- data/lib/csquare/generator/enum.rb +99 -0
- data/lib/csquare/generator/enum/namer.rb +13 -0
- data/lib/csquare/generator/enum/op_namer.rb +34 -0
- data/lib/csquare/generator/enum/sparse_op_namer.rb +7 -0
- data/lib/csquare/generator/index.rb +340 -0
- data/lib/csquare/generator/op.rb +102 -0
- data/lib/csquare/generator/type.rb +62 -0
- metadata +140 -0
data/lib/csquare/base.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
class CSquare::Base
|
2
|
+
EXTRA_TYPE_NAMES = %w{bool}
|
3
|
+
|
4
|
+
def initialize code, type_names
|
5
|
+
@parser = C::Parser.new
|
6
|
+
type_names = (type_names + EXTRA_TYPE_NAMES).uniq
|
7
|
+
type_names.each { |t| @parser.type_names << t }
|
8
|
+
|
9
|
+
tree = begin
|
10
|
+
@parser.parse(code)
|
11
|
+
rescue C::ParseError => e
|
12
|
+
if e.message.include?("parse error on ID (")
|
13
|
+
STDERR.puts "CSquare::Base: A parse error was encountered: #{e.message}"
|
14
|
+
STDERR.puts "This typically means you're using a special typename which CSquare does not know how to recognize."
|
15
|
+
STDERR.puts "It is recommended that you avoid doing so; however, if you must, try modifying CSquare::Base::EXTRA_TYPE_NAMES."
|
16
|
+
else
|
17
|
+
STDERR.puts "CSquare::Base: An unrecognized parse error was encountered."
|
18
|
+
STDERR.puts code.to_s
|
19
|
+
end
|
20
|
+
|
21
|
+
STDERR.puts "The currently defined types are: #{type_names.inspect}"
|
22
|
+
|
23
|
+
raise(e)
|
24
|
+
end
|
25
|
+
|
26
|
+
raise(ArgumentError, "multiple entities not supported") if tree.entities.size > 1
|
27
|
+
|
28
|
+
@entity = tree.entities[0]
|
29
|
+
end
|
30
|
+
|
31
|
+
def code
|
32
|
+
entity.to_s
|
33
|
+
end
|
34
|
+
|
35
|
+
attr_reader :entity, :parser
|
36
|
+
end
|
data/lib/csquare/cerb.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
# Loosely based on ERB by Masatoshi Seki.
|
2
|
+
#
|
3
|
+
# For handling Ruby code embedded in CSquare (C) sources.
|
4
|
+
#
|
5
|
+
#
|
6
|
+
# int main() {
|
7
|
+
# #RUBY if blueprint.id == :rational
|
8
|
+
# return 0;
|
9
|
+
# #RUBY else
|
10
|
+
# return 1;
|
11
|
+
# #RUBY end
|
12
|
+
# }
|
13
|
+
#
|
14
|
+
# TODO: Rewrite this so it uses a grammar that can recognize comments.
|
15
|
+
#
|
16
|
+
# NOTE: DO NOT USE PRY IN HERE. Annoying to kill.
|
17
|
+
|
18
|
+
|
19
|
+
class CERB
|
20
|
+
SPLIT_REGEXP = /^\s*#\s*RUBY\s+/
|
21
|
+
|
22
|
+
def initialize file, blueprint
|
23
|
+
@blueprint = blueprint
|
24
|
+
|
25
|
+
out = Buffer.new
|
26
|
+
eval_str = nil
|
27
|
+
@src = []
|
28
|
+
|
29
|
+
while line = file.gets
|
30
|
+
line.chomp!
|
31
|
+
|
32
|
+
c_code, eval_str = line.split(SPLIT_REGEXP, 2)
|
33
|
+
|
34
|
+
#binding.pry if line == "#RUBY if blueprint.id != :complex"
|
35
|
+
|
36
|
+
if eval_str.nil?
|
37
|
+
out.push c_code
|
38
|
+
else
|
39
|
+
unless out.empty?
|
40
|
+
@src << "puts #{out.result.dump}"
|
41
|
+
out.reset!
|
42
|
+
end
|
43
|
+
|
44
|
+
@src << "puts ''" # empty line in place of #RUBY statements (ensures line numbers match source files in debugging)
|
45
|
+
@src << eval_str
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
@src << "puts #{out.result.dump}" if eval_str.nil? && !out.empty?
|
50
|
+
@src << "puts ''" # prevent EOF errors
|
51
|
+
|
52
|
+
#binding.pry
|
53
|
+
|
54
|
+
eval @src.join("\n")
|
55
|
+
end
|
56
|
+
attr_reader :blueprint, :src
|
57
|
+
|
58
|
+
|
59
|
+
|
60
|
+
class Buffer
|
61
|
+
def initialize
|
62
|
+
@code = []
|
63
|
+
end
|
64
|
+
|
65
|
+
def push code
|
66
|
+
@code << code
|
67
|
+
end
|
68
|
+
|
69
|
+
def result
|
70
|
+
@code.join("\n")
|
71
|
+
end
|
72
|
+
|
73
|
+
def reset!
|
74
|
+
@code = []
|
75
|
+
end
|
76
|
+
|
77
|
+
def empty?
|
78
|
+
@code.size == 0
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
@@ -0,0 +1,175 @@
|
|
1
|
+
# Represents a C function template.
|
2
|
+
class CSquare::Function < CSquare::Base
|
3
|
+
def initialize code, type_names
|
4
|
+
super code, type_names
|
5
|
+
@decorated_name = false
|
6
|
+
raise(SyntaxError, "expected function definition") unless entity.FunctionDef?
|
7
|
+
end
|
8
|
+
|
9
|
+
# Make a deep copy of this function.
|
10
|
+
def clone
|
11
|
+
CSquare::Function.new(self.code, @parser.type_names.to_a)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Return the function declaration for the header file
|
15
|
+
def declaration
|
16
|
+
t = @entity.type
|
17
|
+
"#{t.type.to_s} #{name}(#{t.params.to_s});"
|
18
|
+
end
|
19
|
+
|
20
|
+
def rename! new_name
|
21
|
+
@entity.name = new_name
|
22
|
+
end
|
23
|
+
|
24
|
+
def decorate_name! type_symbol
|
25
|
+
@entity.name = decorated_name(type_symbol)
|
26
|
+
@decorated_name = true
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
def decorated_name type_symbol
|
31
|
+
@decorated_name ? @entity.name : "#{@entity.name}_#{type_symbol}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def name
|
35
|
+
@entity.name
|
36
|
+
end
|
37
|
+
|
38
|
+
# Return a hash of function parameters => types. Passing the argument :string will return type strings instead of CAST types.
|
39
|
+
def params(as=nil)
|
40
|
+
@entity.params(as)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Return a hash of function local variables => types. You may pass :string as the sole argument if you want
|
44
|
+
def locals(as=nil)
|
45
|
+
@entity.def.locals(as)
|
46
|
+
end
|
47
|
+
|
48
|
+
def definition
|
49
|
+
@entity.def
|
50
|
+
end
|
51
|
+
|
52
|
+
def return_type
|
53
|
+
@entity.type.type
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
# Get those parameters which we need to watch, based on the template typenames given (as an argument).
|
58
|
+
def template_params typenames
|
59
|
+
watch_params = {}
|
60
|
+
|
61
|
+
params.each_pair do |varname, fparam|
|
62
|
+
if typenames.include?(fparam.underlying_typename)
|
63
|
+
watch_params[varname] = fparam.underlying_typename
|
64
|
+
end
|
65
|
+
end
|
66
|
+
watch_params
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
# Get those local variables which we need to watch when applying templates, based on the template typenames given (only argument).
|
71
|
+
def template_locals typenames
|
72
|
+
watch_locals = {}
|
73
|
+
|
74
|
+
locals.each_pair do |varname, fdec|
|
75
|
+
if typenames.include?(fdec.underlying_typename)
|
76
|
+
watch_locals[varname] = fdec.underlying_typename
|
77
|
+
end
|
78
|
+
end
|
79
|
+
watch_locals
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
# Given some hash of typenames to replacement types, change all parameters and declarations.
|
84
|
+
#
|
85
|
+
# Hash should consist of string values only.
|
86
|
+
def replace_types! h
|
87
|
+
# STDERR.puts "parser typenames: #{@parser.type_names.inspect}"
|
88
|
+
|
89
|
+
h.each_value do |new_typename|
|
90
|
+
@parser.type_names << new_typename
|
91
|
+
C.default_parser.type_names << new_typename
|
92
|
+
end
|
93
|
+
|
94
|
+
# Replace the types in the function prototype
|
95
|
+
@entity.entries[0].replace_types! h
|
96
|
+
|
97
|
+
# Recurse down into function blocks
|
98
|
+
@entity.entries[1].replace_types! h
|
99
|
+
|
100
|
+
# Replace typecasts
|
101
|
+
@entity.recursively_replace_casts! h
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
# Given all function calls, figure out what they should instead be and change the tree as we go.
|
106
|
+
def decorate_calls! blueprint, type_symbol
|
107
|
+
@entity.recursively_decorate_calls! blueprint, type_symbol
|
108
|
+
end
|
109
|
+
|
110
|
+
|
111
|
+
# Return a list of local variables, function names, parameters, etc; hashed to type (string).
|
112
|
+
def locals_and_types blueprint
|
113
|
+
vars_and_types = blueprint.generator.externs.merge(blueprint.externs).
|
114
|
+
merge(params).
|
115
|
+
merge(locals)
|
116
|
+
|
117
|
+
# Go through and remove const indicators, as these will only get in the way
|
118
|
+
vars_and_types.each_pair do |var, type|
|
119
|
+
if type.is_a?(C::DirectType)
|
120
|
+
vars_and_types[var].const = false
|
121
|
+
vars_and_types[var] = vars_and_types[var].to_s
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
vars_and_types
|
126
|
+
end
|
127
|
+
|
128
|
+
|
129
|
+
# Is some local identifier in use?
|
130
|
+
def has_local? var, blueprint=nil
|
131
|
+
@entity.has_local? var, blueprint
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
# Return the type associated with some variable. Optionally can look for globals if blueprint is given.
|
136
|
+
def type_of var, blueprint=nil
|
137
|
+
@entity.type_of var, blueprint
|
138
|
+
end
|
139
|
+
|
140
|
+
|
141
|
+
def mutate! blueprint, new_type_symbol, params = nil
|
142
|
+
|
143
|
+
# Create a frozen duplicate of this function, that hasn't had its typenames changed.
|
144
|
+
f = self.clone
|
145
|
+
|
146
|
+
self.decorate_name! new_type_symbol
|
147
|
+
|
148
|
+
self.entity.recombine! f, blueprint, new_type_symbol
|
149
|
+
|
150
|
+
self.replace_types!(params || blueprint.params(new_type_symbol))
|
151
|
+
|
152
|
+
self
|
153
|
+
end
|
154
|
+
|
155
|
+
|
156
|
+
class << self
|
157
|
+
def find_broken_ast tree
|
158
|
+
begin
|
159
|
+
tree.to_s
|
160
|
+
return nil
|
161
|
+
rescue TypeError
|
162
|
+
tree.each do |e|
|
163
|
+
x = CSquare::Function.find_broken_ast(e)
|
164
|
+
unless x.nil?
|
165
|
+
require "pry"
|
166
|
+
binding.pry
|
167
|
+
end
|
168
|
+
end
|
169
|
+
return tree
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
|
175
|
+
end
|
@@ -0,0 +1,374 @@
|
|
1
|
+
class CSquare::Generator
|
2
|
+
include CSquare::Indexable
|
3
|
+
|
4
|
+
DEFAULT_EXTERNS = {'fprintf' => 'int'}
|
5
|
+
|
6
|
+
acts_as_indexable
|
7
|
+
|
8
|
+
# To use for :inline index functions -- need to know return type
|
9
|
+
OP_RETURN_TYPES = {
|
10
|
+
:'<' => :boolean,
|
11
|
+
:'>' => :boolean,
|
12
|
+
:'<=' => :boolean,
|
13
|
+
:'>=' => :boolean,
|
14
|
+
:'==' => :boolean,
|
15
|
+
:'!=' => :boolean,
|
16
|
+
:'+' => :key,
|
17
|
+
:'-' => :key,
|
18
|
+
:'*' => :key,
|
19
|
+
:'/' => :key,
|
20
|
+
:'%' => :key
|
21
|
+
}
|
22
|
+
|
23
|
+
# To use for :inline index functions that should be automatically generated
|
24
|
+
OP_FUNCTION_NAMES = {
|
25
|
+
:'<' => 'lt',
|
26
|
+
:'>' => 'gt',
|
27
|
+
:'<=' => 'lte',
|
28
|
+
:'>=' => 'gte',
|
29
|
+
:'==' => 'eqeq',
|
30
|
+
:'!=' => 'neq',
|
31
|
+
:'+' => 'add',
|
32
|
+
:'-' => 'sub',
|
33
|
+
:'*' => 'mul',
|
34
|
+
:'/' => 'div',
|
35
|
+
:'%' => 'mod'
|
36
|
+
}
|
37
|
+
|
38
|
+
BOOL_CAST_TO_OP = {
|
39
|
+
C::Less => :'<',
|
40
|
+
C::More => :'>',
|
41
|
+
C::LessOrEqual => :'<=',
|
42
|
+
C::MoreOrEqual => :'>=',
|
43
|
+
C::Equal => :'==',
|
44
|
+
C::NotEqual => :'!=',
|
45
|
+
C::And => :'&&',
|
46
|
+
C::Or => :'||'
|
47
|
+
}
|
48
|
+
|
49
|
+
UNARY_CAST_TO_OP = {
|
50
|
+
C::Negative => :'-@',
|
51
|
+
C::Not => :'!@',
|
52
|
+
C::Arrow => :'->',
|
53
|
+
C::Dereference => :'*@'
|
54
|
+
}
|
55
|
+
|
56
|
+
ASSIGN_CAST_TO_OP = {
|
57
|
+
C::Assign => :'=',
|
58
|
+
}
|
59
|
+
|
60
|
+
BINARY_ASSIGN_CAST_TO_OP = {
|
61
|
+
C::AddAssign => :'+=',
|
62
|
+
C::SubtractAssign => :'-=',
|
63
|
+
C::MultiplyAssign => :'*=',
|
64
|
+
C::DivideAssign => :'/=',
|
65
|
+
C::ModAssign => :'%='
|
66
|
+
}
|
67
|
+
|
68
|
+
BINARY_CAST_TO_OP = {
|
69
|
+
C::Add => :'+',
|
70
|
+
C::Subtract => :'-',
|
71
|
+
C::Multiply => :'*',
|
72
|
+
C::Divide => :'/',
|
73
|
+
C::Mod => :'%',}
|
74
|
+
|
75
|
+
BIT_CAST_TO_OP = {
|
76
|
+
C::BitAnd => :'&',
|
77
|
+
C::BitOr => :'|',
|
78
|
+
C::BitXor => :'^',
|
79
|
+
C::ShiftLeft => :'<<',
|
80
|
+
C::ShiftRight => :'>>'
|
81
|
+
}
|
82
|
+
|
83
|
+
CAST_TO_OP = BOOL_CAST_TO_OP.
|
84
|
+
merge(UNARY_CAST_TO_OP).
|
85
|
+
merge(ASSIGN_CAST_TO_OP).
|
86
|
+
merge(BINARY_CAST_TO_OP).
|
87
|
+
merge(BIT_CAST_TO_OP).
|
88
|
+
merge(BINARY_ASSIGN_CAST_TO_OP)
|
89
|
+
|
90
|
+
def initialize path, c_output_basename, options = {}
|
91
|
+
options = {
|
92
|
+
:include_guards => true,
|
93
|
+
:header => true,
|
94
|
+
:include_header => true
|
95
|
+
}.merge(options)
|
96
|
+
|
97
|
+
@default_key = 'TYPE'
|
98
|
+
@path = path
|
99
|
+
@basename = c_output_basename
|
100
|
+
@externs = DEFAULT_EXTERNS
|
101
|
+
@blueprints = {}
|
102
|
+
@enumerators = {}
|
103
|
+
|
104
|
+
yield self
|
105
|
+
|
106
|
+
# STDERR.puts "GENERATOR EXTERNS: " + @externs.inspect
|
107
|
+
|
108
|
+
@blueprints.each_key do |id|
|
109
|
+
@blueprints[id].expand_ops!
|
110
|
+
end
|
111
|
+
|
112
|
+
mutant_functions = []
|
113
|
+
blueprints.each_value do |blueprint|
|
114
|
+
blueprint.types.each_pair do |type_symbol,type|
|
115
|
+
mutant_functions = mutant_functions.concat(blueprint.mutate_functions(type_symbol))
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
declarations = write_c_file(options[:include_guards], options[:include_header], mutant_functions)
|
120
|
+
write_h_file(options[:include_guards], declarations) if options[:header]
|
121
|
+
end
|
122
|
+
|
123
|
+
attr_reader :blueprints, :path, :basename, :enumerators
|
124
|
+
|
125
|
+
def inspect
|
126
|
+
obj_id = "0x#{(self.object_id << 1).to_s(16)}"
|
127
|
+
"#<#{self.class.to_s}:#{obj_id} basename=#{@basename.inspect} blueprint_ids=#{@blueprints.keys.inspect} path=#{@path.inspect}>"
|
128
|
+
end
|
129
|
+
|
130
|
+
def default_key k=nil
|
131
|
+
return @default_key if k.nil?
|
132
|
+
@default_key = k
|
133
|
+
end
|
134
|
+
|
135
|
+
|
136
|
+
def c_include_guard
|
137
|
+
"#{@basename.upcase}_C"
|
138
|
+
end
|
139
|
+
|
140
|
+
def h_include_guard
|
141
|
+
"#{@basename.upcase}_H"
|
142
|
+
end
|
143
|
+
|
144
|
+
|
145
|
+
def c_filename
|
146
|
+
"#{@basename}.c"
|
147
|
+
end
|
148
|
+
|
149
|
+
def h_filename
|
150
|
+
"#{@basename}.h"
|
151
|
+
end
|
152
|
+
|
153
|
+
# Shorthand for blueprints[id]
|
154
|
+
def [] blueprint_id
|
155
|
+
blueprints[blueprint_id]
|
156
|
+
end
|
157
|
+
|
158
|
+
# Register symbols available to all functions, and their types. Takes a hash as only argument.
|
159
|
+
#
|
160
|
+
# Example:
|
161
|
+
#
|
162
|
+
# c.externs 'NM_MAX' => :integer, 'CblasNoTrans' => 'char', 'fprintf' => 'int'
|
163
|
+
#
|
164
|
+
#
|
165
|
+
def externs h=nil
|
166
|
+
return @externs if h.nil?
|
167
|
+
@externs.merge!(h)
|
168
|
+
end
|
169
|
+
|
170
|
+
# Create a blueprint for a set of types that all behave a certain way.
|
171
|
+
#
|
172
|
+
# At minimum, you should provide the name of the blueprint (e.g., <tt>blueprint(:integer)</tt>). You may also provide
|
173
|
+
# a template parameter name, which defaults to TYPE, and field parameters.
|
174
|
+
#
|
175
|
+
# Example (complex):
|
176
|
+
#
|
177
|
+
# c.blueprint(:complex, 'TYPE', :r => 'FLOAT', :i => 'FLOAT') do |t|
|
178
|
+
# # ...
|
179
|
+
# end
|
180
|
+
#
|
181
|
+
def blueprint id, template_param = 'TYPE', field_params = {}, &block
|
182
|
+
raise(ArgumentError, "id #{id} already declared") if @blueprints.has_key?(id)
|
183
|
+
|
184
|
+
# Clear cache of blueprints by type_id
|
185
|
+
@blueprint_for = nil
|
186
|
+
|
187
|
+
@blueprints[id] = Blueprint.new(self, id, template_param, field_params, &block)
|
188
|
+
|
189
|
+
self
|
190
|
+
end
|
191
|
+
|
192
|
+
|
193
|
+
# Get all types stored in the various template types
|
194
|
+
def types
|
195
|
+
h = {}
|
196
|
+
@blueprints.each_value do |blueprint|
|
197
|
+
blueprint.types.each_pair do |id, type|
|
198
|
+
if h.has_key?(id)
|
199
|
+
raise(StandardError, "two types with same id: #{id}")
|
200
|
+
else
|
201
|
+
h[id] = type
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
h
|
206
|
+
end
|
207
|
+
|
208
|
+
# Returns the blueprint corresponding to some type_id. Caches types for faster lookup.
|
209
|
+
def blueprint_for type_id
|
210
|
+
@blueprint_for ||= types
|
211
|
+
@blueprint_for[type_id].blueprint
|
212
|
+
end
|
213
|
+
|
214
|
+
|
215
|
+
def enumerate name, opts = {}
|
216
|
+
@enumerators[name] = CSquare::Generator::Enum.new(name, opts)
|
217
|
+
end
|
218
|
+
|
219
|
+
# Get a list of ops used (just the symbols)
|
220
|
+
def op_symbols
|
221
|
+
ary = []
|
222
|
+
@blueprints.each_value do |blueprint|
|
223
|
+
ary = ary.concat blueprint.op_symbols
|
224
|
+
end
|
225
|
+
ary.sort.uniq
|
226
|
+
end
|
227
|
+
|
228
|
+
def indices_c_code
|
229
|
+
ary = []
|
230
|
+
|
231
|
+
# Blueprint-scoped indices
|
232
|
+
@blueprints.each_value do |blueprint|
|
233
|
+
blueprint.indices.values.flatten.each do |index|
|
234
|
+
blueprint.types.each_key do |type_id|
|
235
|
+
ary << index.to_c(type_id)
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
# Add generator-scoped indices
|
241
|
+
@indices.values.flatten.each do |index|
|
242
|
+
ary << index.to_c
|
243
|
+
end
|
244
|
+
|
245
|
+
ary
|
246
|
+
end
|
247
|
+
|
248
|
+
|
249
|
+
def read_source source_filename
|
250
|
+
begin
|
251
|
+
g = self.is_a?(CSquare::Generator) ? self : self.generator
|
252
|
+
Dir.chdir(g.path) do
|
253
|
+
if File.exists?(source_filename)
|
254
|
+
preprocess_source File.new(source_filename, "r")
|
255
|
+
else
|
256
|
+
raise IOError, "file '#{source_filename}' not found in '#{g.path}' or '#{File.join(g.path, self.id.to_s)}'"
|
257
|
+
end
|
258
|
+
end
|
259
|
+
rescue Errno::ENOENT => e
|
260
|
+
# This is really helpful for people who are using rake compile and don't know what
|
261
|
+
# the template directory should be, since they don't know their current location.
|
262
|
+
STDERR.puts "CSquare: Exception thrown: #{e.inspect}"
|
263
|
+
STDERR.puts "CSquare: Current directory: #{Dir.pwd.inspect}"
|
264
|
+
raise e
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
|
269
|
+
# Return a hash giving mappings from template typenames (keys, e.g., 'TYPE') to ctypes.
|
270
|
+
def params type_symbol
|
271
|
+
types_ = types[type_symbol]
|
272
|
+
k = types_.ctype_keys # hash of typenames to type ids
|
273
|
+
|
274
|
+
begin
|
275
|
+
k[@default_key] = types_.ctype
|
276
|
+
rescue NoMethodError
|
277
|
+
STDERR.puts "NoMethodError: @default_key=#{@default_key}, type_symbol = #{type_symbol}"
|
278
|
+
end
|
279
|
+
k["LONG_#{@default_key}"] = (types_.long || types_).ctype
|
280
|
+
k
|
281
|
+
end
|
282
|
+
|
283
|
+
|
284
|
+
# Return all possible typenames for a given source
|
285
|
+
def keys_for f_name
|
286
|
+
ary = self.template_keys(f_name)
|
287
|
+
@blueprints.each_value do |blueprint|
|
288
|
+
next unless blueprint.has_source?(f_name)
|
289
|
+
ary << blueprint.template_keys(f_name)
|
290
|
+
end
|
291
|
+
ary.flatten.compact.uniq
|
292
|
+
end
|
293
|
+
|
294
|
+
|
295
|
+
protected
|
296
|
+
def write_c_file with_guards = true, include_header = true, functions = []
|
297
|
+
declarations = []
|
298
|
+
|
299
|
+
out = File.new(c_filename, "w")
|
300
|
+
|
301
|
+
out.puts("#ifndef #{c_include_guard}\n# define #{c_include_guard}\n\n") if with_guards
|
302
|
+
|
303
|
+
h = include_header == true ? h_filename : include_header
|
304
|
+
|
305
|
+
out.puts("#include \"#{h}\"\n\n") if include_header
|
306
|
+
|
307
|
+
out.puts indices_c_code.join("\n\n")
|
308
|
+
|
309
|
+
functions.each do |f|
|
310
|
+
begin
|
311
|
+
out.puts f.entity.to_s + "\n"
|
312
|
+
rescue TypeError => e
|
313
|
+
STDERR.puts e.inspect
|
314
|
+
CSquare::Function.find_broken_ast(f.entity)
|
315
|
+
end
|
316
|
+
declarations << f.declaration
|
317
|
+
end
|
318
|
+
|
319
|
+
out.puts("#endif // #{c_include_guard}") if with_guards
|
320
|
+
|
321
|
+
out.close
|
322
|
+
|
323
|
+
declarations
|
324
|
+
end
|
325
|
+
|
326
|
+
|
327
|
+
def write_h_file with_guards = true, declarations = []
|
328
|
+
out = File.new(h_filename, "w")
|
329
|
+
|
330
|
+
out.puts("#ifndef #{h_include_guard}\n# define #{h_include_guard}\n\n") if with_guards
|
331
|
+
|
332
|
+
enumerators.each_value do |enum|
|
333
|
+
out.puts enum.to_c
|
334
|
+
end
|
335
|
+
|
336
|
+
declarations.each do |d|
|
337
|
+
out.puts d
|
338
|
+
end
|
339
|
+
|
340
|
+
out.puts("#endif // #{h_include_guard}") if with_guards
|
341
|
+
|
342
|
+
out.close
|
343
|
+
end
|
344
|
+
|
345
|
+
|
346
|
+
def keys
|
347
|
+
k = [@default_key, "LONG_#{@default_key}"]
|
348
|
+
types.each_pair do |type_symbol, type|
|
349
|
+
k = k.concat(type.keys.keys)
|
350
|
+
end
|
351
|
+
k
|
352
|
+
end
|
353
|
+
|
354
|
+
def extra_template_keys_for source
|
355
|
+
keys = []
|
356
|
+
blueprints.each_value do |blueprint|
|
357
|
+
new_keys = blueprint.extra_keys(source) if blueprint.extra_templates_by_source.has_key?(source)
|
358
|
+
keys = keys.concat(new_keys) unless new_keys.nil?
|
359
|
+
end
|
360
|
+
keys.compact.uniq
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
require_relative 'generator/blueprint'
|
365
|
+
require_relative 'generator/index'
|
366
|
+
require_relative 'generator/type'
|
367
|
+
require_relative 'generator/op'
|
368
|
+
require_relative 'generator/binary_op'
|
369
|
+
require_relative 'generator/boolean_op'
|
370
|
+
require_relative 'generator/assign_op'
|
371
|
+
require_relative 'generator/enum'
|
372
|
+
require_relative 'generator/enum/namer'
|
373
|
+
require_relative 'generator/enum/op_namer'
|
374
|
+
require_relative 'generator/enum/sparse_op_namer'
|