Top Level Namespace

Defined Under Namespace

Modules: CTokenizer, CType, Caphir, DBC, OCL, ParseErrorHandler, Preprocessor Classes: Module, ParserSettings, SearchPath, String

Instance Method Summary collapse

Instance Method Details

#expand_function(conditions, context, body, start_line, line_info) ⇒ Object


8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/dbc/expand_function.rb', line 8

def expand_function(conditions, context, body, start_line, line_info)
	raise 'should be a function' unless context.function?

	context_str = context.short_name
	f_cond = conditions[context_str]

	outstr = ''
	outstr << "\n"

	pre_text = ''			# preconditions
	post_text = ''		# postconditions
	inv_text = ''			# invariants
	final_text = ''		# stuff at the end

	if f_cond
		# get the conditions
		f_cond.conditions.each do |c|
			case c.type
				when "pre"
					pre_text
				when "post"
					post_text
				else
					raise ParseError, "unexpected condition type: #{c.type} for #{context_str}"
			end << c.to_cexp("\t")
		end
		# set up old values
		f_cond.old_values.each do |identifier, var_used|
			# figures out the type of identifiers such as a->b->c
			begin
				p_type = context.evaluate(identifier)
			rescue CType::EvaluationError
				raise CType::EvaluationError, "#{line_info}: in #{context_str}, #{$!} for #{identifier}"
			end
			# initializations
			outstr << "\t" << p_type.to_init_s(var_used)
			outstr << ' = ' << identifier << ";\n"
		end
	end

	context.parameters.each do |p|
		inv = conditions[p.short_name]
		if inv then inv.conditions.each do |c|
			raise ParseError, "expecting invariant got #{c.long_type} for #{p.to_s}" \
				unless c.type == "inv"
			exp_str = c.to_cexp("\t", context_str)
			# fix me - this could be better
			sub_str = '\1' + p.identifier + '\2'
			exp_str.gsub!(/(\W)self(\W+)/, sub_str)
			inv_text << exp_str
		end; end
	end
	
	if pre_text.empty? and post_text.empty? and inv_text.empty?
		# we're done early
		return body.collect! { |t| t.at(1) }.join
	end

	void_return_type = (context.base_type.to_s == 'void')

	unless void_return_type or (post_text.empty? and inv_text.empty?)
		outstr << "\t" << context.base_type.to_init_s('ocl__ret_val') << ";\n"
	end
	
	# output invariants and preconditions
	outstr << "\t/* Invariants: */\n" << inv_text unless inv_text.empty?
	outstr << "\t/* Preconditions: */\n" << pre_text unless pre_text.empty?

	outstr << "{\n"
	outstr << '#line ' << start_line.to_s << "\n" if line_info

	# output function body
	if post_text.empty? and inv_text.empty?
		outstr << body.collect! do |t|
			start_line += CTokenizer.line_count(t = t.at(1))
			t
		end.join
	else
		output_label = false
		if void_return_type
			outstr << body.collect do |t|
				start_line += CTokenizer.line_count( t = t.at(1) )
				if t == 'return'
					output_label = true
					'goto ocl__return_here'
				else
					t
				end
			end.join # do
		else
			until body.empty?
				start_line += CTokenizer.line_count( t = body.shift.at(1) )
				if t == 'return'
					output_label = true
					outstr << '{ ocl__ret_val = ( '
					until body.empty?
						start_line += CTokenizer.line_count( t = body.shift.at(1) )
						break if t == ';'
						outstr << t
					end
					outstr << ' ); goto ocl__return_here; }'
				else
					outstr << t
				end
			end # until
		end # if
		outstr << "\nocl__return_here:\n" if output_label
		# must explicitly return the return value unless return value is void
		final_text << "\treturn ocl__ret_val;\n" unless void_return_type
	end
	outstr << "\n"

	# output postconditions and invariants
	outstr << "\t/* Postconditions: */\n" << post_text unless post_text.empty?
	outstr << "\t/* Invariants: */\n" << inv_text unless inv_text.empty?

	outstr << final_text
	outstr << "}\n"
	outstr << '#line ' << start_line.to_s << "\n" if line_info
	outstr
end

#expand_version(pre, version) ⇒ Object

Removes dots and zero pads


5
6
7
8
9
# File 'lib/caphir/preprocessor_conf.rb', line 5

def expand_version(pre, version)
	version.delete!('.')
	(3 - version.length).times { version << '0' }
	"#{pre}#{version}"
end