qed 2.1.1 → 2.2.0
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.
- data/COPYING +622 -344
- data/DIARY.rdoc +117 -0
- data/HISTORY +36 -0
- data/PROFILE +16 -0
- data/README.rdoc +69 -36
- data/REQUIRE +9 -0
- data/ROADMAP +12 -0
- data/VERSION +5 -0
- data/demo/01_demos.rdoc +56 -0
- data/demo/02_advice.rdoc +158 -0
- data/demo/03_helpers.rdoc +42 -0
- data/demo/04_fixtures.rdoc +29 -0
- data/demo/05_quote.rdoc +24 -0
- data/demo/07_toplevel.rdoc +42 -0
- data/demo/08_cross_script.rdoc +27 -0
- data/demo/09_cross_script.rdoc +27 -0
- data/demo/10_constant_lookup.rdoc +16 -0
- data/demo/applique/constant.rb +2 -0
- data/demo/applique/env.rb +5 -0
- data/demo/applique/fileutils.rb +1 -0
- data/demo/applique/markup.rb +10 -0
- data/demo/applique/quote.rb +4 -0
- data/demo/applique/toplevel.rb +15 -0
- data/demo/fixtures/data.txt +1 -0
- data/demo/fixtures/table.yml +5 -0
- data/demo/helpers/advice.rb +40 -0
- data/demo/helpers/sample.rb +4 -0
- data/demo/helpers/toplevel.rb +6 -0
- data/eg/hello_world.rdoc +15 -0
- data/{demo/error.rdoc → eg/view_error.rdoc} +0 -0
- data/{demo → eg}/website.rdoc +0 -0
- data/lib/qed.rb +20 -1
- data/lib/qed/advice.rb +4 -30
- data/lib/qed/advice/events.rb +6 -3
- data/lib/qed/advice/patterns.rb +37 -19
- data/lib/qed/applique.rb +85 -0
- data/lib/qed/command.rb +3 -5
- data/lib/qed/evaluator.rb +52 -56
- data/lib/qed/package.yml +5 -0
- data/lib/qed/parser.rb +149 -0
- data/lib/qed/profile.yml +16 -0
- data/lib/qed/reporter/{base.rb → abstract.rb} +17 -19
- data/lib/qed/reporter/bullet.rb +14 -16
- data/lib/qed/reporter/dotprogress.rb +7 -6
- data/lib/qed/reporter/html.rb +21 -3
- data/lib/qed/reporter/verbatim.rb +28 -26
- data/lib/qed/scope.rb +98 -82
- data/lib/qed/script.rb +21 -69
- data/lib/qed/session.rb +44 -3
- data/script/qedoc +2 -0
- data/script/test +2 -0
- metadata +74 -28
- data/doc/qedoc/index.html +0 -515
- data/doc/qedoc/jquery.js +0 -19
- data/meta/authors +0 -1
- data/meta/created +0 -1
- data/meta/description +0 -2
- data/meta/homepage +0 -1
- data/meta/name +0 -1
- data/meta/released +0 -1
- data/meta/repository +0 -1
- data/meta/requires +0 -5
- data/meta/ruby +0 -2
- data/meta/suite +0 -1
- data/meta/summary +0 -1
- data/meta/title +0 -1
- data/meta/version +0 -1
data/lib/qed/profile.yml
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
---
|
2
|
+
title: QED
|
3
|
+
suite: proutils
|
4
|
+
summary: Quod Erat Demonstrandum
|
5
|
+
authors: Thomas Sawyer <transfire@gmail.com>
|
6
|
+
created: 2006-12-16
|
7
|
+
|
8
|
+
description:
|
9
|
+
QED (Quality Ensured Demonstrations) is a TDD/BDD framework
|
10
|
+
utilizing Literate Programming techniques.
|
11
|
+
|
12
|
+
resources:
|
13
|
+
home: http://proutils.github.com/qed
|
14
|
+
work: http://github.com/protuils/qed
|
15
|
+
repo: git://github.com/proutils/qed.git
|
16
|
+
|
@@ -4,18 +4,15 @@ module Reporter
|
|
4
4
|
require 'facets/string'
|
5
5
|
require 'ansi/code'
|
6
6
|
|
7
|
-
# = Reporter
|
7
|
+
# = Reporter Absract Base Class
|
8
8
|
#
|
9
9
|
# Serves as the base class for all other output formats.
|
10
10
|
#
|
11
|
-
class
|
11
|
+
class Abstract
|
12
12
|
|
13
13
|
attr :io
|
14
14
|
attr :steps
|
15
15
|
attr :omit
|
16
|
-
attr :pass
|
17
|
-
attr :fail
|
18
|
-
attr :error
|
19
16
|
|
20
17
|
def initialize(options={})
|
21
18
|
@io = options[:io] || STDOUT
|
@@ -29,6 +26,10 @@ module Reporter
|
|
29
26
|
@error = []
|
30
27
|
end
|
31
28
|
|
29
|
+
def passes ; @pass ; end
|
30
|
+
def errors ; @error ; end
|
31
|
+
def failures ; @fail ; end
|
32
|
+
|
32
33
|
#
|
33
34
|
def trace?
|
34
35
|
@trace
|
@@ -79,23 +80,16 @@ module Reporter
|
|
79
80
|
@demos += 1
|
80
81
|
end
|
81
82
|
|
82
|
-
#
|
83
|
-
def tag(element)
|
84
|
-
end
|
85
|
-
|
86
83
|
#
|
87
84
|
def load(demo)
|
88
85
|
end
|
86
|
+
|
89
87
|
#
|
90
88
|
def import(file)
|
91
89
|
end
|
92
90
|
|
93
|
-
#
|
94
|
-
|
95
|
-
end
|
96
|
-
|
97
|
-
def comment(elem)
|
98
|
-
end
|
91
|
+
#def comment(elem)
|
92
|
+
#end
|
99
93
|
|
100
94
|
# Before running a step that is omitted.
|
101
95
|
#def omit_step(step)
|
@@ -107,6 +101,14 @@ module Reporter
|
|
107
101
|
@steps += 1
|
108
102
|
end
|
109
103
|
|
104
|
+
# Right before running code.
|
105
|
+
def code(section)
|
106
|
+
end
|
107
|
+
|
108
|
+
# Right before text section.
|
109
|
+
def text(section)
|
110
|
+
end
|
111
|
+
|
110
112
|
# After running a step that passed.
|
111
113
|
def pass(step)
|
112
114
|
@pass << step
|
@@ -127,10 +129,6 @@ module Reporter
|
|
127
129
|
def after_code(step, file)
|
128
130
|
end
|
129
131
|
|
130
|
-
#
|
131
|
-
def after_element(elem)
|
132
|
-
end
|
133
|
-
|
134
132
|
#
|
135
133
|
def unload
|
136
134
|
end
|
data/lib/qed/reporter/bullet.rb
CHANGED
@@ -1,22 +1,20 @@
|
|
1
1
|
module QED
|
2
2
|
module Reporter #:nodoc:
|
3
3
|
|
4
|
-
require 'qed/reporter/
|
4
|
+
require 'qed/reporter/abstract'
|
5
5
|
|
6
6
|
# = Bullet Point Reporter
|
7
7
|
#
|
8
|
-
# Similar to the
|
8
|
+
# Similar to the Verbose reporter, but does
|
9
9
|
# not display test code for passing tests.
|
10
|
-
class BulletPoint <
|
10
|
+
class BulletPoint < Abstract
|
11
11
|
|
12
12
|
#
|
13
|
-
def
|
14
|
-
case step.
|
15
|
-
when
|
16
|
-
#
|
17
|
-
|
18
|
-
io.puts ANSI::Code.bold("#{step.text}\n")
|
19
|
-
when 'p'
|
13
|
+
def text(step)
|
14
|
+
case step.text
|
15
|
+
when /^\=/
|
16
|
+
io.puts "#{step.text}".ansi(:bold)
|
17
|
+
else
|
20
18
|
txt = step.text.to_s.strip.tabto(2)
|
21
19
|
txt[0,1] = "*"
|
22
20
|
io.puts txt
|
@@ -25,17 +23,17 @@ module Reporter #:nodoc:
|
|
25
23
|
end
|
26
24
|
|
27
25
|
def pass(step)
|
28
|
-
#io.puts
|
26
|
+
#io.puts "#{step}".ansi(:green)
|
29
27
|
end
|
30
28
|
|
31
29
|
def fail(step, assertion)
|
32
30
|
msg = ''
|
33
31
|
msg << " ##### FAIL #####\n"
|
34
32
|
msg << " # " + assertion.to_s
|
35
|
-
msg =
|
33
|
+
msg = msg.ansi(:magenta)
|
36
34
|
io.puts msg
|
37
35
|
#io.puts
|
38
|
-
io.puts
|
36
|
+
io.puts "#{step.text}".ansi(:red)
|
39
37
|
end
|
40
38
|
|
41
39
|
def error(step, exception)
|
@@ -44,10 +42,10 @@ module Reporter #:nodoc:
|
|
44
42
|
msg << " ##### ERROR #####\n"
|
45
43
|
msg << " # " + exception.to_s + "\n"
|
46
44
|
msg << " # " + clean_backtrace(exception.backtrace[0])
|
47
|
-
msg =
|
45
|
+
msg = msg.ansi(:magenta)
|
48
46
|
io.puts msg
|
49
47
|
#io.puts
|
50
|
-
io.puts
|
48
|
+
io.puts "#{step.text}".ansi(:red)
|
51
49
|
end
|
52
50
|
|
53
51
|
#def report(str)
|
@@ -69,7 +67,7 @@ module Reporter #:nodoc:
|
|
69
67
|
# txt[0,1] = "*"
|
70
68
|
# io.puts txt
|
71
69
|
# #io.puts
|
72
|
-
# #io.puts
|
70
|
+
# #io.puts "#{step}".ansi(:magenta)
|
73
71
|
#end
|
74
72
|
|
75
73
|
end #class Summary
|
@@ -1,11 +1,11 @@
|
|
1
1
|
module QED
|
2
2
|
module Reporter #:nodoc:
|
3
3
|
|
4
|
-
require 'qed/reporter/
|
4
|
+
require 'qed/reporter/abstract'
|
5
5
|
|
6
6
|
# = DotProgress Reporter
|
7
7
|
#
|
8
|
-
class DotProgress <
|
8
|
+
class DotProgress < Abstract
|
9
9
|
|
10
10
|
#
|
11
11
|
def before_session(session)
|
@@ -16,7 +16,8 @@ module Reporter #:nodoc:
|
|
16
16
|
#
|
17
17
|
def before_code(step, file)
|
18
18
|
super(step, file)
|
19
|
-
io.print "."
|
19
|
+
io.print "."
|
20
|
+
io.flush
|
20
21
|
end
|
21
22
|
|
22
23
|
#
|
@@ -25,7 +26,7 @@ module Reporter #:nodoc:
|
|
25
26
|
|
26
27
|
@error.each do |step, exception|
|
27
28
|
backtrace = clean_backtrace(exception.backtrace[0])
|
28
|
-
io.puts
|
29
|
+
io.puts "***** ERROR *****".ansi(:red)
|
29
30
|
io.puts "#{exception}"
|
30
31
|
io.puts ":#{backtrace}:"
|
31
32
|
#io.puts ":#{exception.backtrace[1]}:"
|
@@ -35,8 +36,8 @@ module Reporter #:nodoc:
|
|
35
36
|
|
36
37
|
@fail.each do |step, assertion|
|
37
38
|
backtrace = clean_backtrace(assertion.backtrace[0])
|
38
|
-
io.puts
|
39
|
-
io.puts
|
39
|
+
io.puts "***** FAIL *****".ansi(:red)
|
40
|
+
io.puts "#{assertion}".ansi(:bold)
|
40
41
|
io.puts ":#{backtrace}:"
|
41
42
|
#io.puts assertion if $VERBOSE
|
42
43
|
io.puts
|
data/lib/qed/reporter/html.rb
CHANGED
@@ -1,11 +1,29 @@
|
|
1
1
|
module QED
|
2
|
-
module Reporter
|
2
|
+
module Reporter
|
3
3
|
|
4
|
-
require 'qed/reporter/
|
4
|
+
require 'qed/reporter/abstract'
|
5
5
|
|
6
6
|
# = Html Reporter
|
7
7
|
#
|
8
|
-
|
8
|
+
# TODO: This must be completely redesigned since we moved back
|
9
|
+
# to text based evaluation --which makes generting HTML with
|
10
|
+
# modifications from the evaluation tricky. But I've come up
|
11
|
+
# with a farily clever way to handle this. Take the original
|
12
|
+
# and use Tilt to translate it into HTML, then take the
|
13
|
+
# evaluation results for code steps and use it to search
|
14
|
+
# the HTML for "the closest match". Find the \<pre> tag
|
15
|
+
# associated with the text and add class and color style.
|
16
|
+
# Of course the tricky part is the matching, but if we
|
17
|
+
# run the text snippet through Tilt as well we should be
|
18
|
+
# able to get an exact match. It won't be fast, but it should
|
19
|
+
# work.
|
20
|
+
|
21
|
+
class Html < Abstract
|
22
|
+
|
23
|
+
#
|
24
|
+
def initialize(*args)
|
25
|
+
raise "HTML format is not currently working"
|
26
|
+
end
|
9
27
|
|
10
28
|
#
|
11
29
|
def pass(step)
|
@@ -1,44 +1,46 @@
|
|
1
1
|
module QED
|
2
2
|
module Reporter #:nodoc:
|
3
3
|
|
4
|
-
require 'qed/reporter/
|
4
|
+
require 'qed/reporter/abstract'
|
5
5
|
|
6
6
|
# = Verbose ANSI Console Reporter
|
7
7
|
#
|
8
|
-
class Verbatim <
|
8
|
+
class Verbatim < Abstract
|
9
9
|
|
10
10
|
#
|
11
|
-
def
|
12
|
-
case
|
13
|
-
when
|
14
|
-
#
|
15
|
-
|
16
|
-
io.
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
when 'li'
|
24
|
-
io.print "* #{element.text.strip}\n"
|
11
|
+
def text(section)
|
12
|
+
case section.text
|
13
|
+
when /^\=/
|
14
|
+
io.puts "#{section.text}".ansi(:bold)
|
15
|
+
else
|
16
|
+
io.puts(section.text + "\n")
|
17
|
+
end
|
18
|
+
if !section.cont.empty?
|
19
|
+
section.cont.each do |c|
|
20
|
+
io.puts(c.ansi(:blue))
|
21
|
+
io.puts
|
22
|
+
end
|
25
23
|
end
|
26
24
|
end
|
27
25
|
|
26
|
+
# headers ?
|
27
|
+
|
28
28
|
#
|
29
29
|
def pass(step)
|
30
30
|
txt = step.text.rstrip.sub("\n",'')
|
31
|
-
io.print
|
31
|
+
io.print "#{txt}\n\n".ansi(:green)
|
32
32
|
end
|
33
33
|
|
34
34
|
#
|
35
35
|
def fail(step, error)
|
36
36
|
txt = step.text.rstrip.sub("\n",'')
|
37
37
|
tab = step.text.index(/\S/) - 1
|
38
|
-
io.print
|
38
|
+
io.print "#{txt}\n\n".ansi(:red)
|
39
39
|
msg = []
|
40
|
-
msg << ANSI::Code.bold(ANSI::Code.red("FAIL: ")) + error.to_str
|
41
|
-
msg << ANSI::Code.bold(clean_backtrace(error.backtrace[0]))
|
40
|
+
#msg << ANSI::Code.bold(ANSI::Code.red("FAIL: ")) + error.to_str
|
41
|
+
#msg << ANSI::Code.bold(clean_backtrace(error.backtrace[0]))
|
42
|
+
msg << "FAIL: ".ansi(:bold, :red) + error.to_str
|
43
|
+
msg << clean_backtrace(error.backtrace[0]).ansi(:bold)
|
42
44
|
io.puts msg.join("\n").tabto(tab||2)
|
43
45
|
io.puts
|
44
46
|
end
|
@@ -48,11 +50,11 @@ module Reporter #:nodoc:
|
|
48
50
|
raise error if $DEBUG
|
49
51
|
txt = step.text.rstrip.sub("\n",'')
|
50
52
|
tab = step.text.index(/\S/) - 1
|
51
|
-
io.print
|
53
|
+
io.print "#{txt}\n\n".ansi(:red)
|
52
54
|
msg = []
|
53
|
-
msg <<
|
54
|
-
msg <<
|
55
|
-
#msg =
|
55
|
+
msg << "ERROR: #{error.class} ".ansi(:bold,:red) + error.to_str #.sub(/for QED::Context.*?$/,'')
|
56
|
+
msg << clean_backtrace(error.backtrace[0]).ansi(:bold)
|
57
|
+
#msg = msg.ansi(:red)
|
56
58
|
io.puts msg.join("\n").tabto(tab||2)
|
57
59
|
io.puts
|
58
60
|
end
|
@@ -65,14 +67,14 @@ module Reporter #:nodoc:
|
|
65
67
|
#end
|
66
68
|
|
67
69
|
#def report_table(set)
|
68
|
-
# puts
|
70
|
+
# puts set.to_yaml.tabto(2).ansi(:magenta)
|
69
71
|
#end
|
70
72
|
|
71
73
|
#
|
72
74
|
#def macro(step)
|
73
75
|
# #io.puts
|
74
76
|
# #io.puts step.text
|
75
|
-
# io.print
|
77
|
+
# io.print "#{step}".ansi(:magenta)
|
76
78
|
# #io.puts
|
77
79
|
#end
|
78
80
|
|
data/lib/qed/scope.rb
CHANGED
@@ -1,102 +1,118 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require 'ae'
|
4
|
-
require 'qed/advice'
|
1
|
+
require 'ae'
|
5
2
|
|
6
|
-
|
7
|
-
# used to build QED documents.
|
3
|
+
module QED
|
8
4
|
|
9
|
-
|
5
|
+
# Scope is the context in which QED documents are run.
|
6
|
+
#
|
7
|
+
class Scope < Module
|
8
|
+
|
9
|
+
#
|
10
|
+
def self.new(applique)
|
11
|
+
@applique = applique
|
12
|
+
super(applique)
|
13
|
+
end
|
10
14
|
|
11
|
-
|
15
|
+
#
|
16
|
+
def self.const_missing(name)
|
17
|
+
@applique.const_get(name)
|
18
|
+
end
|
12
19
|
|
13
|
-
#
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
blk.call(*set)
|
22
|
-
end
|
23
|
-
@__tables__ ||= []
|
24
|
-
@__tables__ << file
|
20
|
+
#
|
21
|
+
def initialize(applique)
|
22
|
+
super()
|
23
|
+
@applique = applique
|
24
|
+
extend self
|
25
|
+
extend applique # TODO: extend or include applique or none ?
|
26
|
+
#extend DSLi
|
27
|
+
create_clean_binding_method
|
25
28
|
end
|
26
29
|
|
27
|
-
#
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
def Data(file, &content)
|
32
|
-
raise if File.directory?(file)
|
33
|
-
if content
|
34
|
-
FileUtils.mkdir_p(File.dirname(fname))
|
35
|
-
case File.extname(file)
|
36
|
-
when '.yml', '.yaml'
|
37
|
-
File.open(file, 'w'){ |f| f << content.call.to_yaml }
|
38
|
-
else
|
39
|
-
File.open(file, 'w'){ |f| f << content.call }
|
40
|
-
end
|
41
|
-
else
|
42
|
-
#raise LoadError, "no such fixture file -- #{fname}" unless File.exist?(fname)
|
43
|
-
case File.extname(file)
|
44
|
-
when '.yml', '.yaml'
|
45
|
-
YAML.load(File.new(file))
|
46
|
-
else
|
47
|
-
File.read(file)
|
48
|
-
end
|
30
|
+
# This turned out to be the key to proper scoping.
|
31
|
+
def create_clean_binding_method
|
32
|
+
define_method(:__binding__) do
|
33
|
+
@__binding__ ||= binding
|
49
34
|
end
|
50
35
|
end
|
51
36
|
|
52
|
-
#
|
53
|
-
#
|
54
|
-
# This is useful to transform human readable code examples
|
55
|
-
# into proper exectuable code. For example, say you want to
|
56
|
-
# run shell code, but want to make if look like typical
|
57
|
-
# shelle examples:
|
58
|
-
#
|
59
|
-
# $ cp fixture/a.rb fixture/b.rb
|
60
|
-
#
|
61
|
-
# You can use a transform to convert lines starting with '$'
|
62
|
-
# into executable Ruby using #system.
|
63
|
-
#
|
64
|
-
# system('cp fixture/a.rb fixture/b.rb')
|
65
|
-
#
|
66
|
-
#def Transform(pattern=nil, &procedure)
|
67
|
-
#
|
68
|
-
#end
|
37
|
+
#module DSLi
|
69
38
|
|
70
|
-
|
71
|
-
binding
|
72
|
-
|
39
|
+
#def initialize
|
40
|
+
# @__binding__ = binding
|
41
|
+
#end
|
73
42
|
|
74
|
-
|
43
|
+
#def __binding__
|
44
|
+
# @__binding__
|
45
|
+
#end
|
75
46
|
|
76
|
-
|
77
|
-
|
47
|
+
#
|
48
|
+
#def __binding__
|
49
|
+
# @__binding__ ||= binding
|
50
|
+
#end
|
78
51
|
|
79
|
-
|
52
|
+
#
|
53
|
+
def eval(code)
|
54
|
+
super(code, __binding__)
|
55
|
+
end
|
80
56
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
TOPLEVEL_BINDING.eval('self')
|
86
|
-
)
|
87
|
-
end
|
57
|
+
#
|
58
|
+
def When(*patterns, &procedure)
|
59
|
+
@applique.When(*patterns, &procedure)
|
60
|
+
end
|
88
61
|
|
89
|
-
|
62
|
+
#
|
63
|
+
def Before(type=:code, &procedure)
|
64
|
+
@applique.Before(type, &procedure)
|
65
|
+
end
|
90
66
|
|
91
|
-
|
92
|
-
|
93
|
-
|
67
|
+
#
|
68
|
+
def After(type=:code, &procedure)
|
69
|
+
@applique.After(type, &procedure)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Table-based steps.
|
73
|
+
#--
|
74
|
+
# TODO: Look for files relative to script first?
|
75
|
+
#++
|
76
|
+
def Table(file=nil, &blk)
|
77
|
+
file = file || @_tables.last
|
78
|
+
tbl = YAML.load(File.new(file))
|
79
|
+
tbl.each do |set|
|
80
|
+
blk.call(*set)
|
81
|
+
end
|
82
|
+
@__tables__ ||= []
|
83
|
+
@__tables__ << file
|
84
|
+
end
|
85
|
+
|
86
|
+
# Read/Write a static data fixture.
|
87
|
+
#--
|
88
|
+
# TODO: Perhaps #Data would be best as some sort of Kernel extension.
|
89
|
+
#
|
90
|
+
# TODO: Look for files relative to script first?
|
91
|
+
#++
|
92
|
+
def Data(file, &content)
|
93
|
+
raise if File.directory?(file)
|
94
|
+
if content
|
95
|
+
FileUtils.mkdir_p(File.dirname(fname))
|
96
|
+
case File.extname(file)
|
97
|
+
when '.yml', '.yaml'
|
98
|
+
File.open(file, 'w'){ |f| f << content.call.to_yaml }
|
99
|
+
else
|
100
|
+
File.open(file, 'w'){ |f| f << content.call }
|
101
|
+
end
|
102
|
+
else
|
103
|
+
#raise LoadError, "no such fixture file -- #{fname}" unless File.exist?(fname)
|
104
|
+
case File.extname(file)
|
105
|
+
when '.yml', '.yaml'
|
106
|
+
YAML.load(File.new(file))
|
107
|
+
else
|
108
|
+
File.read(file)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
94
112
|
|
95
|
-
#
|
96
|
-
# @__binding__
|
97
|
-
#end
|
98
|
-
end
|
113
|
+
#end#module DSL
|
99
114
|
|
100
|
-
end
|
115
|
+
end#class Scope
|
101
116
|
|
117
|
+
end#module QED
|
102
118
|
|