skeem 0.2.12 → 0.2.13

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d37e901cd3042b1b0b81e29aa885c78bcfd61494e015508687187380be313d5d
4
- data.tar.gz: 99918e85f8dafcd9a53465d77dfad99961786bafed16458d3d58eb2a36e39867
3
+ metadata.gz: 56bd360c4a30ba9dae003a18c922b150924fd0471fe74f1196e75967161ed767
4
+ data.tar.gz: 90a2af34b4aa7b327656d7f889c94cead17d7a906d5db36e31d7a4ab3af5e920
5
5
  SHA512:
6
- metadata.gz: e0834459d4d616c84b66ac0e261737388002ba972586a343767ca1f41e5c3d2c52ee31a2367a75362e6b9c9618baf2b69b4feff81fee7e71acd4948900ddb9e1
7
- data.tar.gz: 9653c511dd58eabbd15340becadbb4bd23d6bab4cd8ed454e6d98d9e4d304f7837d60775fd40b0528cac252958012a4a7c1c9e3421e3f28074033d21917c7a60
6
+ metadata.gz: 87827300a4e54068a2e885ef74b5aba42d21d3639a933cb4060b02b39f55b74cc15697098134ca341b1c1bceb6c027c67e1b113de9c10d4455f3b3fed0e0f009
7
+ data.tar.gz: 3875d43e7c46826a7b6246f5ea07da250401281d54479bb933e0fe73b3da610ac43e1104bdacf975ad658d1ef2834a34a895b24142545cb201b59e028ad5aaa9
@@ -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!`
@@ -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
 
@@ -53,6 +53,7 @@ module Skeem
53
53
  rule 'datum' => 'simple_datum'
54
54
  rule 'datum' => 'compound_datum'
55
55
  rule 'simple_datum' => 'BOOLEAN'
56
+ rule 'simple_datum' => 'CHAR'
56
57
  rule 'simple_datum' => 'number'
57
58
  rule 'simple_datum' => 'STRING_LIT'
58
59
  rule 'simple_datum' => 'symbol'
@@ -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
- all_same?(first_operand, arglist)
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
@@ -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
- case aFormat
214
- when :default, :base10
215
- value = aLexeme.to_i
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
@@ -1,3 +1,3 @@
1
1
  module Skeem
2
- VERSION = '0.2.12'.freeze
2
+ VERSION = '0.2.13'.freeze
3
3
  end
@@ -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.12
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-19 00:00:00.000000000 Z
11
+ date: 2019-06-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rley