skeem 0.2.12 → 0.2.13
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -0
- data/README.md +4 -4
- data/lib/skeem/datum_dsl.rb +19 -2
- data/lib/skeem/grammar.rb +1 -0
- data/lib/skeem/primitive/primitive_builder.rb +83 -1
- data/lib/skeem/skm_simple_datum.rb +8 -1
- data/lib/skeem/tokenizer.rb +25 -7
- data/lib/skeem/version.rb +1 -1
- data/spec/skeem/primitive/primitive_builder_spec.rb +90 -0
- data/spec/skeem/tokenizer_spec.rb +27 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 56bd360c4a30ba9dae003a18c922b150924fd0471fe74f1196e75967161ed767
|
4
|
+
data.tar.gz: 90a2af34b4aa7b327656d7f889c94cead17d7a906d5db36e31d7a4ab3af5e920
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 87827300a4e54068a2e885ef74b5aba42d21d3639a933cb4060b02b39f55b74cc15697098134ca341b1c1bceb6c027c67e1b113de9c10d4455f3b3fed0e0f009
|
7
|
+
data.tar.gz: 3875d43e7c46826a7b6246f5ea07da250401281d54479bb933e0fe73b3da610ac43e1104bdacf975ad658d1ef2834a34a895b24142545cb201b59e028ad5aaa9
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
## [0.2.13] - 2019-06-22
|
2
|
+
- Skeem now accepts integers in hexadecimal notation
|
3
|
+
- Added procedures: `char->integer`, `integer->char`, `char=?`, `char<?`, `char>?`, `char<=?`, `char>=?`
|
4
|
+
|
5
|
+
### Changed
|
6
|
+
- Class Tokenizer updated to recognize integer literals in hexadecimal notation.
|
7
|
+
- `DatumDSL#char(aLiteral): added conversion of char literal into SkmChar.
|
8
|
+
- File `grammar.rb` Added a rule to derive a simple datum from a character literal
|
9
|
+
- File `primitive_builder.rb` Implemented primitive procedures `char->integer`, `integer->char`, `char=?`, `char<?`, `char>?`, `char<=?`, `char>=?`
|
10
|
+
- File `README.md` Added mentions to new procedures.
|
11
|
+
- File `tokenize_spec.rb: added tests for haxadecimal integers.
|
12
|
+
- File `primitive_builder_spec.rb`: Added tests for new procedures.
|
13
|
+
|
14
|
+
|
1
15
|
## [0.2.12] - 2019-06-19
|
2
16
|
- Skeem now supports character datatype
|
3
17
|
- Added procedures: `boolean=?`, `char?`, `string`, `make-string`, `reverse`
|
data/README.md
CHANGED
@@ -176,7 +176,7 @@ Here are a few pointers for the Scheme programming language:
|
|
176
176
|
- Of the number hierarchy:
|
177
177
|
`real` (e.g. 2.718, 6.671e-11),
|
178
178
|
`rational` (e.g. 22/7, 1/137, -13/41)
|
179
|
-
`integer` (42, -3)
|
179
|
+
`integer` (42, -3 also in hexadecimal notation: #x3af)
|
180
180
|
- Lists (quoted) : '(1 two "three")
|
181
181
|
- Strings: `"Hello, world."`
|
182
182
|
- Identifiers (symbols): `really-cool-procedure`
|
@@ -249,17 +249,17 @@ This section lists the implemented standard procedures
|
|
249
249
|
* `eqv?`, `equal?`
|
250
250
|
|
251
251
|
#### Boolean procedures
|
252
|
-
* `boolean?`, `and`, `or`, `not`
|
252
|
+
* `boolean?`, `boolean=?`, `and`, `or`, `not`
|
253
253
|
|
254
254
|
#### Character procedures
|
255
|
-
* `char?`
|
255
|
+
* `char?` `char->integer`, `char=?`, `char<?`, `char>?`,`char<=?`, `char>=?`
|
256
256
|
|
257
257
|
#### Numerical operations
|
258
258
|
* Number-level: `number?`, `complex?`, `real?`, `rational?`, `integer?`, `zero?`, `exact?`, `inexact?`, `exact-integer?` , `+`, `-`, `*`, `/`,
|
259
259
|
`=`, `square`, `number->string`
|
260
260
|
* Real-level: `positive?`, `negative?`, `<`, `>`, `<=`, `>=`, `abs`, `max`, `min`, `floor/`, `floor-quotient`, `floor-remainder`, `truncate/`, `truncate-quotient`,
|
261
261
|
`truncate-remainder`, `quotient`, `remainder`, `modulo`, `gcd`, `lcm`, `numerator`, `denominator`, `floor`, `ceiling`, `truncate`, `round`
|
262
|
-
* Integer-level: `even?`, `odd
|
262
|
+
* Integer-level: `even?`, `odd?`, `integer->char`
|
263
263
|
|
264
264
|
#### List procedures
|
265
265
|
* `list?`, `null?`, `pair?`, `append`, `car`, `cdr`, `caar`, `cadr`, `cdar`, `cddr`, `cons`, `length`, `list`, `list-copy`, `list->vector`, `reverse`, `set-car!`, `set-cdr!`
|
data/lib/skeem/datum_dsl.rb
CHANGED
@@ -33,7 +33,7 @@ module Skeem
|
|
33
33
|
raise StandardError, aLiteral.inspect
|
34
34
|
end
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
def rational(aLiteral)
|
38
38
|
return aLiteral if aLiteral.kind_of?(SkmRational)
|
39
39
|
|
@@ -45,7 +45,7 @@ module Skeem
|
|
45
45
|
else
|
46
46
|
raise StandardError, aLiteral.inspect
|
47
47
|
end
|
48
|
-
end
|
48
|
+
end
|
49
49
|
|
50
50
|
def real(aLiteral)
|
51
51
|
return aLiteral if aLiteral.kind_of?(SkmReal)
|
@@ -60,6 +60,23 @@ module Skeem
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
+
def char(aLiteral)
|
64
|
+
return aLiteral if aLiteral.kind_of?(SkmChar)
|
65
|
+
|
66
|
+
result = case aLiteral
|
67
|
+
when Numeric
|
68
|
+
SkmChar.create_from_int(aLiteral)
|
69
|
+
when String
|
70
|
+
value = aLiteral.empty? ? '' : aLiteral.chr
|
71
|
+
SkmChar.create(value)
|
72
|
+
when SkmString
|
73
|
+
value = aLiteral.value.empty? ? '' : aLiteral.value.chr
|
74
|
+
SkmChar.create(value)
|
75
|
+
else
|
76
|
+
raise StandardError, aLiteral.inspect
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
63
80
|
def string(aLiteral)
|
64
81
|
return aLiteral if aLiteral.kind_of?(SkmString)
|
65
82
|
|
data/lib/skeem/grammar.rb
CHANGED
@@ -95,6 +95,13 @@ module Skeem
|
|
95
95
|
|
96
96
|
def add_char_procedures(aRuntime)
|
97
97
|
create_object_predicate(aRuntime, 'char?')
|
98
|
+
create_char2int(aRuntime)
|
99
|
+
create_int2char(aRuntime)
|
100
|
+
create_char_equal(aRuntime)
|
101
|
+
create_char_lt(aRuntime)
|
102
|
+
create_char_gt(aRuntime)
|
103
|
+
create_char_lte(aRuntime)
|
104
|
+
create_char_gte(aRuntime)
|
98
105
|
end
|
99
106
|
|
100
107
|
def add_string_procedures(aRuntime)
|
@@ -572,14 +579,89 @@ module Skeem
|
|
572
579
|
end
|
573
580
|
end
|
574
581
|
|
582
|
+
# Return true, if all arguments are monotonously increasing
|
583
|
+
def compare_all(first_operand, arglist, operation)
|
584
|
+
if arglist.empty?
|
585
|
+
result = true
|
586
|
+
else
|
587
|
+
result = first_operand.value.send(operation, arglist[0].value)
|
588
|
+
if result
|
589
|
+
arglist.each_cons(2) do |(operand1, operand2)|
|
590
|
+
value1 = operand1.value
|
591
|
+
result &&= value1.send(operation, operand2.value)
|
592
|
+
end
|
593
|
+
end
|
594
|
+
end
|
595
|
+
boolean(result)
|
596
|
+
end
|
597
|
+
|
575
598
|
def create_boolean_equal(aRuntime)
|
576
599
|
primitive = ->(_runtime, first_operand, arglist) do
|
577
|
-
|
600
|
+
compare_all(first_operand, arglist, :==)
|
578
601
|
end
|
579
602
|
|
580
603
|
define_primitive_proc(aRuntime, 'boolean=?', one_or_more, primitive)
|
581
604
|
end
|
582
605
|
|
606
|
+
def create_char2int(aRuntime)
|
607
|
+
primitive = ->(runtime, arg_evaluated) do
|
608
|
+
check_argtype(arg_evaluated, SkmChar, 'character', 'char->integer')
|
609
|
+
integer(arg_evaluated.value.ord)
|
610
|
+
end
|
611
|
+
|
612
|
+
define_primitive_proc(aRuntime, 'char->integer', unary, primitive)
|
613
|
+
end
|
614
|
+
|
615
|
+
def create_int2char(aRuntime)
|
616
|
+
primitive = ->(runtime, arg_evaluated) do
|
617
|
+
check_argtype(arg_evaluated, SkmInteger, 'integer', 'integer->char')
|
618
|
+
char(arg_evaluated.value.ord)
|
619
|
+
end
|
620
|
+
|
621
|
+
define_primitive_proc(aRuntime, 'integer->char', unary, primitive)
|
622
|
+
end
|
623
|
+
|
624
|
+
def create_char_equal(aRuntime)
|
625
|
+
primitive = ->(_runtime, first_operand, arglist) do
|
626
|
+
compare_all(first_operand, arglist, :==)
|
627
|
+
end
|
628
|
+
|
629
|
+
define_primitive_proc(aRuntime, 'char=?', one_or_more, primitive)
|
630
|
+
end
|
631
|
+
|
632
|
+
def create_char_lt(aRuntime)
|
633
|
+
primitive = ->(_runtime, first_operand, arglist) do
|
634
|
+
compare_all(first_operand, arglist, :<)
|
635
|
+
end
|
636
|
+
|
637
|
+
define_primitive_proc(aRuntime, 'char<?', one_or_more, primitive)
|
638
|
+
end
|
639
|
+
|
640
|
+
def create_char_gt(aRuntime)
|
641
|
+
primitive = ->(_runtime, first_operand, arglist) do
|
642
|
+
compare_all(first_operand, arglist, :>)
|
643
|
+
end
|
644
|
+
|
645
|
+
define_primitive_proc(aRuntime, 'char>?', one_or_more, primitive)
|
646
|
+
end
|
647
|
+
|
648
|
+
def create_char_lte(aRuntime)
|
649
|
+
primitive = ->(_runtime, first_operand, arglist) do
|
650
|
+
compare_all(first_operand, arglist, :<=)
|
651
|
+
end
|
652
|
+
|
653
|
+
define_primitive_proc(aRuntime, 'char<=?', one_or_more, primitive)
|
654
|
+
end
|
655
|
+
|
656
|
+
def create_char_gte(aRuntime)
|
657
|
+
primitive = ->(_runtime, first_operand, arglist) do
|
658
|
+
compare_all(first_operand, arglist, :>=)
|
659
|
+
end
|
660
|
+
|
661
|
+
define_primitive_proc(aRuntime, 'char>=?', one_or_more, primitive)
|
662
|
+
end
|
663
|
+
|
664
|
+
|
583
665
|
def create_make_string(aRuntime)
|
584
666
|
primitive = ->(runtime, count_arg, arglist) do
|
585
667
|
count = count_arg
|
@@ -152,7 +152,14 @@ module Skeem
|
|
152
152
|
class SkmChar < SkmSimpleDatum
|
153
153
|
def char?
|
154
154
|
true
|
155
|
-
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def self.create_from_int(anInteger)
|
158
|
+
int_value = anInteger.kind_of?(SkmInteger) ? anInteger.value : anInteger
|
159
|
+
char_value = int_value < 0xff ? int_value.chr : [int_value].pack('U')
|
160
|
+
create(char_value)
|
161
|
+
end
|
162
|
+
|
156
163
|
end # class
|
157
164
|
|
158
165
|
class SkmString < SkmSimpleDatum
|
data/lib/skeem/tokenizer.rb
CHANGED
@@ -93,15 +93,17 @@ module Skeem
|
|
93
93
|
token = build_token(@@lexeme2name[lexeme], lexeme)
|
94
94
|
elsif (token = recognize_char_token)
|
95
95
|
# Do nothing
|
96
|
-
elsif (lexeme = scanner.scan(/#(?:(?:true)|(?:false)|(?:u8)|[\\\(tfeiodx]|(?:\d+[=#]))/))
|
97
|
-
token = cardinal_token(lexeme)
|
98
96
|
elsif (lexeme = scanner.scan(/[+-]?[0-9]+\/[0-9]+(?=\s|[|()";]|$)/))
|
99
97
|
token = build_token('RATIONAL', lexeme) # Decimal radix
|
100
|
-
elsif (lexeme = scanner.scan(/[+-]?[0-9]+(?:.0+)?(?=\s|[|()";]|$)/))
|
98
|
+
elsif (lexeme = scanner.scan(/(?:#[dD])?[+-]?[0-9]+(?:.0+)?(?=\s|[|()";]|$)/))
|
101
99
|
token = build_token('INTEGER', lexeme) # Decimal radix
|
100
|
+
elsif (lexeme = scanner.scan(/#[xX][+-]?[0-9a-fA-F]+(?=\s|[|()";]|$)/))
|
101
|
+
token = build_token('INTEGER', lexeme) # Hexadecimal radix
|
102
102
|
elsif (lexeme = scanner.scan(/[+-]?[0-9]+(?:\.[0-9]*)?(?:(?:e|E)[+-]?[0-9]+)?/))
|
103
103
|
# Order dependency: must be tested after INTEGER case
|
104
104
|
token = build_token('REAL', lexeme)
|
105
|
+
elsif (lexeme = scanner.scan(/#(?:(?:true)|(?:false)|(?:u8)|[\\\(tfeiodx]|(?:\d+[=#]))/))
|
106
|
+
token = cardinal_token(lexeme)
|
105
107
|
elsif (lexeme = scanner.scan(/"(?:\\"|[^"])*"/)) # Double quotes literal?
|
106
108
|
token = build_token('STRING_LIT', lexeme)
|
107
109
|
elsif (lexeme = scanner.scan(/[a-zA-Z!$%&*\/:<=>?@^_~][a-zA-Z0-9!$%&*+-.\/:<=>?@^_~+-]*/))
|
@@ -136,7 +138,6 @@ Bytevector constants are terminated by ) .
|
|
136
138
|
numbers (section 6.2.5).
|
137
139
|
#<n>= #<n># These are used for labeling and referencing
|
138
140
|
other literal data (section 2.4).
|
139
|
-
# token = build_token('BOOLEAN', lexeme)
|
140
141
|
=end
|
141
142
|
def cardinal_token(aLexeme)
|
142
143
|
case aLexeme
|
@@ -210,9 +211,26 @@ other literal data (section 2.4).
|
|
210
211
|
end
|
211
212
|
|
212
213
|
def to_integer(aLexeme, aFormat)
|
213
|
-
|
214
|
-
|
215
|
-
|
214
|
+
literal = aLexeme.downcase
|
215
|
+
prefix_pattern = /^#[dx]/
|
216
|
+
matching = literal.match(prefix_pattern)
|
217
|
+
if matching
|
218
|
+
case matching[0]
|
219
|
+
when '#d'
|
220
|
+
format = :base10
|
221
|
+
when '#x'
|
222
|
+
format = :base16
|
223
|
+
end
|
224
|
+
literal = matching.post_match
|
225
|
+
else
|
226
|
+
format = :default
|
227
|
+
end
|
228
|
+
|
229
|
+
case format
|
230
|
+
when :default, :base10
|
231
|
+
value = literal.to_i
|
232
|
+
when :base16
|
233
|
+
value = literal.to_i(16)
|
216
234
|
end
|
217
235
|
|
218
236
|
value
|
data/lib/skeem/version.rb
CHANGED
@@ -755,6 +755,96 @@ SKEEM
|
|
755
755
|
end
|
756
756
|
end # context
|
757
757
|
|
758
|
+
context 'Character procedures:' do
|
759
|
+
it 'should implement the char? procedure' do
|
760
|
+
checks = [
|
761
|
+
['(char? #f)', false],
|
762
|
+
["(char? 'a)", false],
|
763
|
+
['(char? #\a)', true],
|
764
|
+
['(char? "a")', false],
|
765
|
+
["(char? '(#\\a 1))", false]
|
766
|
+
]
|
767
|
+
compare_to_predicted(checks)
|
768
|
+
end
|
769
|
+
|
770
|
+
it 'should implement the char->integer procedure' do
|
771
|
+
checks = [
|
772
|
+
['(char->integer #\space)', 0x20],
|
773
|
+
['(char->integer #\newline)', 0x0a],
|
774
|
+
['(char->integer #\a)', ?a.ord],
|
775
|
+
['(char->integer #\x05a)', 0x5a]
|
776
|
+
]
|
777
|
+
compare_to_predicted(checks)
|
778
|
+
end
|
779
|
+
|
780
|
+
it 'should implement the integer->char procedure' do
|
781
|
+
checks = [
|
782
|
+
['(integer->char #x20)', ?\s],
|
783
|
+
['(integer->char 48)', ?0],
|
784
|
+
['(integer->char #x0a)', ?\n],
|
785
|
+
['(integer->char #x3bb)', ?\u03bb]
|
786
|
+
]
|
787
|
+
compare_to_predicted(checks)
|
788
|
+
end
|
789
|
+
|
790
|
+
it 'should implement the char=? procedure' do
|
791
|
+
checks = [
|
792
|
+
['(char=? #\a)', true],
|
793
|
+
['(char=? #\a #\a)', true],
|
794
|
+
['(char=? #\a #\b)', false],
|
795
|
+
['(char=? #\space #\space #\space)', true],
|
796
|
+
['(char=? #\space #\space #\newline)', false]
|
797
|
+
]
|
798
|
+
compare_to_predicted(checks)
|
799
|
+
end
|
800
|
+
|
801
|
+
it 'should implement the char<? procedure' do
|
802
|
+
checks = [
|
803
|
+
['(char<? #\a)', true],
|
804
|
+
['(char<? #\a #\a)', false],
|
805
|
+
['(char<? #\a #\b)', true],
|
806
|
+
['(char<? #\a #\b #\c)', true],
|
807
|
+
['(char<? #\a #\c #\b)', false]
|
808
|
+
]
|
809
|
+
compare_to_predicted(checks)
|
810
|
+
end
|
811
|
+
|
812
|
+
it 'should implement the char>? procedure' do
|
813
|
+
checks = [
|
814
|
+
['(char>? #\b)', true],
|
815
|
+
['(char>? #\b #\b)', false],
|
816
|
+
['(char>? #\b #\a)', true],
|
817
|
+
['(char>? #\c #\b #\a)', true],
|
818
|
+
['(char>? #\c #\a #\b)', false]
|
819
|
+
]
|
820
|
+
compare_to_predicted(checks)
|
821
|
+
end
|
822
|
+
|
823
|
+
it 'should implement the char<=? procedure' do
|
824
|
+
checks = [
|
825
|
+
['(char<=? #\a)', true],
|
826
|
+
['(char<=? #\a #\a)', true],
|
827
|
+
['(char<=? #\b #\a)', false],
|
828
|
+
['(char<=? #\a #\b #\c)', true],
|
829
|
+
['(char<=? #\a #\c #\c)', true],
|
830
|
+
['(char<=? #\a #\c #\b)', false]
|
831
|
+
]
|
832
|
+
compare_to_predicted(checks)
|
833
|
+
end
|
834
|
+
|
835
|
+
it 'should implement the char>=? procedure' do
|
836
|
+
checks = [
|
837
|
+
['(char>=? #\a)', true],
|
838
|
+
['(char>=? #\a #\a)', true],
|
839
|
+
['(char>=? #\a #\b)', false],
|
840
|
+
['(char>=? #\c #\b #\a)', true],
|
841
|
+
['(char>=? #\c #\b #\b)', true],
|
842
|
+
['(char>=? #\c #\a #\b)', false]
|
843
|
+
]
|
844
|
+
compare_to_predicted(checks)
|
845
|
+
end
|
846
|
+
end # context
|
847
|
+
|
758
848
|
context 'Vector procedures:' do
|
759
849
|
it 'should implement the vector? procedure' do
|
760
850
|
checks = [
|
@@ -80,6 +80,33 @@ module Skeem
|
|
80
80
|
|
81
81
|
check_tokens(tests, 'INTEGER')
|
82
82
|
end
|
83
|
+
|
84
|
+
it 'should tokenize integers with explicit radix 10' do
|
85
|
+
tests = [
|
86
|
+
# couple [raw input, expected]
|
87
|
+
['#d0', 0],
|
88
|
+
['#D3', 3],
|
89
|
+
['#d+3 ', +3],
|
90
|
+
['#D-3', -3],
|
91
|
+
['#d-3.0', -3],
|
92
|
+
['#D-1234', -1234]
|
93
|
+
]
|
94
|
+
|
95
|
+
check_tokens(tests, 'INTEGER')
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'should tokenize integers in hexadecimal notation' do
|
99
|
+
tests = [
|
100
|
+
# couple [raw input, expected]
|
101
|
+
['#x0', 0],
|
102
|
+
['#Xf', 0xf],
|
103
|
+
['#x+F ', 0xf],
|
104
|
+
['#X-f', -0xf],
|
105
|
+
['#X-12Ac', -0x12ac]
|
106
|
+
]
|
107
|
+
|
108
|
+
check_tokens(tests, 'INTEGER')
|
109
|
+
end
|
83
110
|
end # context
|
84
111
|
|
85
112
|
context 'Rational literals recognition:' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: skeem
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.13
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dimitri Geshef
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-06-
|
11
|
+
date: 2019-06-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rley
|