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 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