shen-ruby 0.1.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/.gitignore +4 -0
- data/.rspec +0 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +20 -0
- data/MIT_LICENSE.txt +26 -0
- data/README.md +94 -0
- data/bin/shen_test_suite.rb +9 -0
- data/bin/srrepl +23 -0
- data/lib/kl.rb +7 -0
- data/lib/kl/absvector.rb +12 -0
- data/lib/kl/compiler.rb +253 -0
- data/lib/kl/cons.rb +51 -0
- data/lib/kl/empty_list.rb +12 -0
- data/lib/kl/environment.rb +123 -0
- data/lib/kl/error.rb +4 -0
- data/lib/kl/internal_error.rb +7 -0
- data/lib/kl/lexer.rb +186 -0
- data/lib/kl/primitives/arithmetic.rb +60 -0
- data/lib/kl/primitives/assignments.rb +18 -0
- data/lib/kl/primitives/booleans.rb +17 -0
- data/lib/kl/primitives/error_handling.rb +13 -0
- data/lib/kl/primitives/generic_functions.rb +22 -0
- data/lib/kl/primitives/lists.rb +21 -0
- data/lib/kl/primitives/streams.rb +38 -0
- data/lib/kl/primitives/strings.rb +55 -0
- data/lib/kl/primitives/symbols.rb +17 -0
- data/lib/kl/primitives/time.rb +17 -0
- data/lib/kl/primitives/vectors.rb +30 -0
- data/lib/kl/reader.rb +40 -0
- data/lib/kl/trampoline.rb +14 -0
- data/lib/shen_ruby.rb +7 -0
- data/lib/shen_ruby/version.rb +3 -0
- data/shen-ruby.gemspec +26 -0
- data/shen/README.txt +17 -0
- data/shen/lib/shen_ruby/shen.rb +124 -0
- data/shen/license.txt +34 -0
- data/shen/release/benchmarks/N_queens.shen +45 -0
- data/shen/release/benchmarks/README.shen +14 -0
- data/shen/release/benchmarks/benchmarks.shen +56 -0
- data/shen/release/benchmarks/bigprog +2173 -0
- data/shen/release/benchmarks/br.shen +13 -0
- data/shen/release/benchmarks/einstein.shen +33 -0
- data/shen/release/benchmarks/heatwave.gif +0 -0
- data/shen/release/benchmarks/interpreter.shen +219 -0
- data/shen/release/benchmarks/picture.jpg +0 -0
- data/shen/release/benchmarks/plato.jpg +0 -0
- data/shen/release/benchmarks/powerset.shen +10 -0
- data/shen/release/benchmarks/prime.shen +10 -0
- data/shen/release/benchmarks/short.shen +129 -0
- data/shen/release/benchmarks/text.txt +68 -0
- data/shen/release/k_lambda/core.kl +1002 -0
- data/shen/release/k_lambda/declarations.kl +1021 -0
- data/shen/release/k_lambda/load.kl +94 -0
- data/shen/release/k_lambda/macros.kl +479 -0
- data/shen/release/k_lambda/prolog.kl +1309 -0
- data/shen/release/k_lambda/reader.kl +1058 -0
- data/shen/release/k_lambda/sequent.kl +556 -0
- data/shen/release/k_lambda/sys.kl +582 -0
- data/shen/release/k_lambda/t-star.kl +3493 -0
- data/shen/release/k_lambda/toplevel.kl +223 -0
- data/shen/release/k_lambda/track.kl +208 -0
- data/shen/release/k_lambda/types.kl +455 -0
- data/shen/release/k_lambda/writer.kl +108 -0
- data/shen/release/k_lambda/yacc.kl +280 -0
- data/shen/release/test_programs/Chap13/problems.txt +26 -0
- data/shen/release/test_programs/README.shen +53 -0
- data/shen/release/test_programs/TinyLispFunctions.txt +16 -0
- data/shen/release/test_programs/TinyTypes.shen +55 -0
- data/shen/release/test_programs/binary.shen +24 -0
- data/shen/release/test_programs/bubble_version_1.shen +28 -0
- data/shen/release/test_programs/bubble_version_2.shen +22 -0
- data/shen/release/test_programs/calculator.shen +21 -0
- data/shen/release/test_programs/cartprod.shen +23 -0
- data/shen/release/test_programs/change.shen +25 -0
- data/shen/release/test_programs/classes-defaults.shen +94 -0
- data/shen/release/test_programs/classes-inheritance.shen +100 -0
- data/shen/release/test_programs/classes-typed.shen +74 -0
- data/shen/release/test_programs/classes-untyped.shen +46 -0
- data/shen/release/test_programs/depth_.shen +14 -0
- data/shen/release/test_programs/einstein.shen +33 -0
- data/shen/release/test_programs/fruit_machine.shen +46 -0
- data/shen/release/test_programs/interpreter.shen +219 -0
- data/shen/release/test_programs/metaprog.shen +85 -0
- data/shen/release/test_programs/minim.shen +193 -0
- data/shen/release/test_programs/mutual.shen +11 -0
- data/shen/release/test_programs/n_queens.shen +45 -0
- data/shen/release/test_programs/newton_version_1.shen +33 -0
- data/shen/release/test_programs/newton_version_2.shen +24 -0
- data/shen/release/test_programs/parse.prl +14 -0
- data/shen/release/test_programs/parser.shen +52 -0
- data/shen/release/test_programs/powerset.shen +10 -0
- data/shen/release/test_programs/prime.shen +10 -0
- data/shen/release/test_programs/proof_assistant.shen +81 -0
- data/shen/release/test_programs/proplog_version_1.shen +25 -0
- data/shen/release/test_programs/proplog_version_2.shen +27 -0
- data/shen/release/test_programs/qmachine.shen +67 -0
- data/shen/release/test_programs/red-black.shen +55 -0
- data/shen/release/test_programs/search.shen +56 -0
- data/shen/release/test_programs/semantic_net.shen +44 -0
- data/shen/release/test_programs/spreadsheet.shen +35 -0
- data/shen/release/test_programs/stack.shen +27 -0
- data/shen/release/test_programs/streams.shen +20 -0
- data/shen/release/test_programs/strings.shen +59 -0
- data/shen/release/test_programs/structures-typed.shen +71 -0
- data/shen/release/test_programs/structures-untyped.shen +42 -0
- data/shen/release/test_programs/tests.shen +294 -0
- data/shen/release/test_programs/types.shen +11 -0
- data/shen/release/test_programs/whist.shen +240 -0
- data/shen/release/test_programs/yacc.shen +136 -0
- data/spec/kl/cons_spec.rb +12 -0
- data/spec/kl/environment_spec.rb +306 -0
- data/spec/kl/lexer_spec.rb +149 -0
- data/spec/kl/primitives/generic_functions_spec.rb +29 -0
- data/spec/kl/primitives/symbols_spec.rb +21 -0
- data/spec/kl/reader_spec.rb +36 -0
- data/spec/spec_helper.rb +2 -0
- metadata +189 -0
data/lib/kl/cons.rb
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
require 'kl/empty_list'
|
|
2
|
+
|
|
3
|
+
module Kl
|
|
4
|
+
class Cons
|
|
5
|
+
include Enumerable
|
|
6
|
+
|
|
7
|
+
attr_reader :hd, :tl
|
|
8
|
+
|
|
9
|
+
def initialize(hd, tl)
|
|
10
|
+
@hd = hd
|
|
11
|
+
@tl = tl
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def ==(other)
|
|
15
|
+
other.kind_of?(Kl::Cons) && hd == other.hd && tl == other.tl
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def each
|
|
19
|
+
cell = self
|
|
20
|
+
while !cell.kind_of? Kl::EmptyList
|
|
21
|
+
yield cell.hd
|
|
22
|
+
cell = cell.tl
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class << self
|
|
27
|
+
def list(array)
|
|
28
|
+
if array.empty?
|
|
29
|
+
Kl::EmptyList.instance
|
|
30
|
+
else
|
|
31
|
+
index = array.size - 1
|
|
32
|
+
head = new(array[index], Kl::EmptyList.instance)
|
|
33
|
+
index = index - 1
|
|
34
|
+
while index >= 0
|
|
35
|
+
head = new(array[index], head)
|
|
36
|
+
index = index - 1
|
|
37
|
+
end
|
|
38
|
+
head
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def list_to_string(f)
|
|
43
|
+
if f.kind_of? Kl::Cons
|
|
44
|
+
'(' + f.map {|x| list_to_string(x)}.join(' ') + ')'
|
|
45
|
+
else
|
|
46
|
+
f.to_s
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
require 'kl/compiler'
|
|
2
|
+
require 'kl/primitives/booleans'
|
|
3
|
+
require 'kl/primitives/symbols'
|
|
4
|
+
require 'kl/primitives/strings'
|
|
5
|
+
require 'kl/primitives/assignments'
|
|
6
|
+
require 'kl/primitives/error_handling'
|
|
7
|
+
require 'kl/primitives/lists'
|
|
8
|
+
require 'kl/primitives/generic_functions'
|
|
9
|
+
require 'kl/primitives/vectors'
|
|
10
|
+
require 'kl/primitives/streams'
|
|
11
|
+
require 'kl/primitives/time'
|
|
12
|
+
require 'kl/primitives/arithmetic'
|
|
13
|
+
|
|
14
|
+
module Kl
|
|
15
|
+
class Environment
|
|
16
|
+
include ::Kl::Primitives::Booleans
|
|
17
|
+
include ::Kl::Primitives::Symbols
|
|
18
|
+
include ::Kl::Primitives::Strings
|
|
19
|
+
include ::Kl::Primitives::Assignments
|
|
20
|
+
include ::Kl::Primitives::ErrorHandling
|
|
21
|
+
include ::Kl::Primitives::Lists
|
|
22
|
+
include ::Kl::Primitives::GenericFunctions
|
|
23
|
+
include ::Kl::Primitives::Vectors
|
|
24
|
+
include ::Kl::Primitives::Streams
|
|
25
|
+
include ::Kl::Primitives::Time
|
|
26
|
+
include ::Kl::Primitives::Arithmetic
|
|
27
|
+
|
|
28
|
+
def initialize
|
|
29
|
+
@dump_code = false
|
|
30
|
+
@tramp_fn = @tramp_args = nil
|
|
31
|
+
@variables = {}
|
|
32
|
+
@eigenklass = class << self; self; end
|
|
33
|
+
@arity_cache = Hash.new { |h, k| h[k] = method(k).arity }
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Trampoline-aware function application
|
|
37
|
+
def __apply(fn, args)
|
|
38
|
+
while fn
|
|
39
|
+
@tramp_fn = nil
|
|
40
|
+
if fn.kind_of? Symbol
|
|
41
|
+
if respond_to? fn
|
|
42
|
+
arity = @arity_cache[fn]
|
|
43
|
+
if arity == args.size || arity == -1
|
|
44
|
+
result = send(fn, *args)
|
|
45
|
+
elsif arity > args.size
|
|
46
|
+
# Partial application
|
|
47
|
+
result = method(fn).to_proc.curry.call(*args)
|
|
48
|
+
else
|
|
49
|
+
# Uncurrying. Apply fn to its expected number of arguments
|
|
50
|
+
# and hope that the result is a function that can be applied
|
|
51
|
+
# to the remainder.
|
|
52
|
+
fn = __apply(fn, args[0, arity])
|
|
53
|
+
args = args[arity..-1]
|
|
54
|
+
next
|
|
55
|
+
end
|
|
56
|
+
else
|
|
57
|
+
raise Kl::Error, "The function #{fn} is undefined"
|
|
58
|
+
end
|
|
59
|
+
else
|
|
60
|
+
arity = fn.arity
|
|
61
|
+
if arity == args.size || arity == -1
|
|
62
|
+
result = fn.call(*args)
|
|
63
|
+
elsif arity > args.size
|
|
64
|
+
result = fn.curry.call(*args)
|
|
65
|
+
else
|
|
66
|
+
# Uncurrying. Apply fn to its expected number of arguments
|
|
67
|
+
# and hope that the result is a function that can be applied
|
|
68
|
+
# to the remainder.
|
|
69
|
+
fn = __apply(fn, args[0, arity])
|
|
70
|
+
args = args[arity..-1]
|
|
71
|
+
next
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
if fn = @tramp_fn
|
|
76
|
+
# Bounce on the trampoline
|
|
77
|
+
args = @tramp_args
|
|
78
|
+
@tramp_args = nil
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
result
|
|
82
|
+
rescue SystemStackError
|
|
83
|
+
raise ::Kl::Error, 'maximum stack depth exceeded'
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def __eval(form)
|
|
87
|
+
if @dump_code
|
|
88
|
+
puts "=" * 70
|
|
89
|
+
puts "Compiling:"
|
|
90
|
+
puts Kl::Cons.list_to_string(form)
|
|
91
|
+
puts '-----'
|
|
92
|
+
end
|
|
93
|
+
code = ::Kl::Compiler.compile(form, {}, true)
|
|
94
|
+
if @dump_code
|
|
95
|
+
puts code
|
|
96
|
+
puts "=" * 70
|
|
97
|
+
end
|
|
98
|
+
@tramp_fn = nil
|
|
99
|
+
result = instance_eval(code)
|
|
100
|
+
# Handle top-level trampolines
|
|
101
|
+
if @tramp_fn
|
|
102
|
+
fn = @tramp_fn
|
|
103
|
+
args = @tramp_args
|
|
104
|
+
@tramp_fn = nil
|
|
105
|
+
@tramp_args = nil
|
|
106
|
+
__apply(fn, args)
|
|
107
|
+
else
|
|
108
|
+
result
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
class << self
|
|
113
|
+
def load_file(env, path)
|
|
114
|
+
File.open(path, 'r') do |file|
|
|
115
|
+
reader = Kl::Reader.new(file)
|
|
116
|
+
while form = reader.next
|
|
117
|
+
env.__eval(form)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
data/lib/kl/error.rb
ADDED
data/lib/kl/lexer.rb
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
require 'singleton'
|
|
2
|
+
require 'kl/error'
|
|
3
|
+
|
|
4
|
+
module Kl
|
|
5
|
+
class Lexer
|
|
6
|
+
SYMBOL_CHARS = /[-=*\/+_?$!\@~><&%'#`;:{}a-zA-Z0-9.]/
|
|
7
|
+
|
|
8
|
+
# Syntax tokens
|
|
9
|
+
class OpenParen
|
|
10
|
+
include Singleton
|
|
11
|
+
end
|
|
12
|
+
class CloseParen
|
|
13
|
+
include Singleton
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def initialize(stream)
|
|
17
|
+
@stream = stream
|
|
18
|
+
@buffer = []
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def eof?
|
|
22
|
+
@buffer.empty? && @stream.eof?
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def getc
|
|
26
|
+
if @buffer.empty?
|
|
27
|
+
@stream.getc
|
|
28
|
+
else
|
|
29
|
+
@buffer.pop
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def ungetc(c)
|
|
34
|
+
@buffer.push(c)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def next
|
|
38
|
+
drain_whitespace
|
|
39
|
+
unless eof?
|
|
40
|
+
c = getc
|
|
41
|
+
case c
|
|
42
|
+
when '('
|
|
43
|
+
OpenParen.instance
|
|
44
|
+
when ')'
|
|
45
|
+
CloseParen.instance
|
|
46
|
+
when '"'
|
|
47
|
+
consume_string
|
|
48
|
+
when SYMBOL_CHARS
|
|
49
|
+
ungetc(c)
|
|
50
|
+
consume_number_or_symbol
|
|
51
|
+
else
|
|
52
|
+
raise Error, "illegal character: #{c}"
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
def drain_whitespace
|
|
59
|
+
until eof?
|
|
60
|
+
c = getc
|
|
61
|
+
if c =~ /\S/
|
|
62
|
+
ungetc(c)
|
|
63
|
+
break
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def consume_string
|
|
69
|
+
chars = []
|
|
70
|
+
loop do
|
|
71
|
+
raise Error, "unterminated string" if eof?
|
|
72
|
+
c = getc
|
|
73
|
+
break if c == '"'
|
|
74
|
+
chars << c
|
|
75
|
+
end
|
|
76
|
+
chars.join
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def consume_number
|
|
80
|
+
# Shen allows multiple leading plusses and minuses. The plusses
|
|
81
|
+
# are ignored and an even number of minuses cancel each other.
|
|
82
|
+
# Thus '------+-7' is read as 7.
|
|
83
|
+
#
|
|
84
|
+
# The Shen reader parses "7." as the integer 7 and the symbol '.'
|
|
85
|
+
decimal_seen = false
|
|
86
|
+
negative = false
|
|
87
|
+
past_sign = false
|
|
88
|
+
chars = []
|
|
89
|
+
loop do
|
|
90
|
+
break if eof?
|
|
91
|
+
c = getc
|
|
92
|
+
if c =~ /\d/
|
|
93
|
+
past_sign = true
|
|
94
|
+
chars << c
|
|
95
|
+
elsif c == '.' && !decimal_seen
|
|
96
|
+
past_sign = true
|
|
97
|
+
decimal_seen = true
|
|
98
|
+
chars << c
|
|
99
|
+
elsif c == '+' && !past_sign
|
|
100
|
+
# ignore
|
|
101
|
+
elsif c == '-' && !past_sign
|
|
102
|
+
negative = !negative
|
|
103
|
+
else
|
|
104
|
+
ungetc c
|
|
105
|
+
break
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
chars.unshift('-') if negative
|
|
109
|
+
if chars.last == '.'
|
|
110
|
+
# A trailing decimal point is treated as part of the next
|
|
111
|
+
# token. Forget we saw it.
|
|
112
|
+
ungetc(chars.pop)
|
|
113
|
+
decimal_seen = false
|
|
114
|
+
end
|
|
115
|
+
str = chars.join
|
|
116
|
+
decimal_seen ? str.to_f : str.to_i
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def consume_symbol
|
|
120
|
+
chars = []
|
|
121
|
+
loop do
|
|
122
|
+
break if eof?
|
|
123
|
+
c = getc
|
|
124
|
+
unless c =~ SYMBOL_CHARS
|
|
125
|
+
ungetc c
|
|
126
|
+
break
|
|
127
|
+
end
|
|
128
|
+
chars << c
|
|
129
|
+
end
|
|
130
|
+
str = chars.join
|
|
131
|
+
|
|
132
|
+
case str
|
|
133
|
+
when 'true'
|
|
134
|
+
true
|
|
135
|
+
when 'false'
|
|
136
|
+
false
|
|
137
|
+
else
|
|
138
|
+
str.to_sym
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def consume_number_or_symbol
|
|
143
|
+
# First drain optional leading signs
|
|
144
|
+
# Then drain optional decimal point
|
|
145
|
+
# If there is another character and it is a digit, then it
|
|
146
|
+
# is a number. Otherwise it is a symbol.
|
|
147
|
+
chars = []
|
|
148
|
+
loop do
|
|
149
|
+
break if eof?
|
|
150
|
+
c = getc
|
|
151
|
+
unless c =~ /[-+]/
|
|
152
|
+
ungetc c
|
|
153
|
+
break
|
|
154
|
+
end
|
|
155
|
+
chars << c
|
|
156
|
+
end
|
|
157
|
+
if eof?
|
|
158
|
+
chars.reverse.each {|x| ungetc x}
|
|
159
|
+
return consume_symbol
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
c = getc
|
|
163
|
+
chars << c
|
|
164
|
+
if c == '.'
|
|
165
|
+
if eof?
|
|
166
|
+
chars.reverse.each {|x| ungetc x}
|
|
167
|
+
return consume_symbol
|
|
168
|
+
end
|
|
169
|
+
c = getc
|
|
170
|
+
chars << c
|
|
171
|
+
chars.reverse.each {|x| ungetc x}
|
|
172
|
+
if c =~ /\d/
|
|
173
|
+
return consume_number
|
|
174
|
+
else
|
|
175
|
+
return consume_symbol
|
|
176
|
+
end
|
|
177
|
+
elsif c =~ /\d/
|
|
178
|
+
chars.reverse.each {|x| ungetc x}
|
|
179
|
+
return consume_number
|
|
180
|
+
else
|
|
181
|
+
chars.reverse.each {|x| ungetc x}
|
|
182
|
+
return consume_symbol
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
module Kl
|
|
2
|
+
module Primitives
|
|
3
|
+
module Arithmetic
|
|
4
|
+
def +(a, b)
|
|
5
|
+
raise ::Kl::Error, "#{a} is not a number" unless a.kind_of? Numeric
|
|
6
|
+
raise ::Kl::Error, "#{b} is not a number" unless b.kind_of? Numeric
|
|
7
|
+
a + b
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def -(a, b)
|
|
11
|
+
raise ::Kl::Error, "#{a} is not a number" unless a.kind_of? Numeric
|
|
12
|
+
raise ::Kl::Error, "#{b} is not a number" unless b.kind_of? Numeric
|
|
13
|
+
a - b
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def *(a, b)
|
|
17
|
+
raise ::Kl::Error, "#{a} is not a number" unless a.kind_of? Numeric
|
|
18
|
+
raise ::Kl::Error, "#{b} is not a number" unless b.kind_of? Numeric
|
|
19
|
+
a * b
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def /(a, b)
|
|
23
|
+
raise ::Kl::Error, "#{a} is not a number" unless a.kind_of? Numeric
|
|
24
|
+
raise ::Kl::Error, "#{b} is not a number" unless b.kind_of? Numeric
|
|
25
|
+
if a.kind_of?(Fixnum) && b.kind_of?(Fixnum) && a % b != 0
|
|
26
|
+
a = a.to_f
|
|
27
|
+
end
|
|
28
|
+
a / b
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def >(a, b)
|
|
32
|
+
raise ::Kl::Error, "#{a} is not a number" unless a.kind_of? Numeric
|
|
33
|
+
raise ::Kl::Error, "#{b} is not a number" unless b.kind_of? Numeric
|
|
34
|
+
a > b
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def <(a, b)
|
|
38
|
+
raise ::Kl::Error, "#{a} is not a number" unless a.kind_of? Numeric
|
|
39
|
+
raise ::Kl::Error, "#{b} is not a number" unless b.kind_of? Numeric
|
|
40
|
+
a < b
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def >=(a, b)
|
|
44
|
+
raise ::Kl::Error, "#{a} is not a number" unless a.kind_of? Numeric
|
|
45
|
+
raise ::Kl::Error, "#{b} is not a number" unless b.kind_of? Numeric
|
|
46
|
+
a >= b
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def <=(a, b)
|
|
50
|
+
raise ::Kl::Error, "#{a} is not a number" unless a.kind_of? Numeric
|
|
51
|
+
raise ::Kl::Error, "#{b} is not a number" unless b.kind_of? Numeric
|
|
52
|
+
a <= b
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def number?(a)
|
|
56
|
+
a.kind_of?(Numeric)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|