code-ruby 0.11.0 → 0.12.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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +2 -2
  3. data/bin/code +6 -0
  4. data/lib/code/node/base_10.rb +2 -2
  5. data/lib/code/node/base_16.rb +1 -5
  6. data/lib/code/node/base_2.rb +1 -5
  7. data/lib/code/node/base_8.rb +1 -5
  8. data/lib/code/node/call.rb +4 -4
  9. data/lib/code/node/code.rb +2 -1
  10. data/lib/code/node/decimal.rb +1 -4
  11. data/lib/code/node/dictionary.rb +6 -2
  12. data/lib/code/node/function.rb +3 -3
  13. data/lib/code/node/function_parameter.rb +5 -1
  14. data/lib/code/node/if.rb +2 -1
  15. data/lib/code/node/list.rb +2 -1
  16. data/lib/code/node/statement.rb +23 -23
  17. data/lib/code/node/string.rb +2 -1
  18. data/lib/code/object/argument.rb +4 -3
  19. data/lib/code/object/boolean.rb +5 -4
  20. data/lib/code/object/class.rb +4 -3
  21. data/lib/code/object/code.rb +33 -0
  22. data/lib/code/object/context.rb +7 -5
  23. data/lib/code/object/date.rb +31 -6
  24. data/lib/code/object/decimal.rb +36 -31
  25. data/lib/code/object/dictionary.rb +4 -4
  26. data/lib/code/object/duration.rb +8 -5
  27. data/lib/code/object/function.rb +42 -26
  28. data/lib/code/object/global.rb +58 -38
  29. data/lib/code/object/integer.rb +23 -26
  30. data/lib/code/object/list.rb +5 -5
  31. data/lib/code/object/nothing.rb +2 -4
  32. data/lib/code/object/parameter.rb +43 -0
  33. data/lib/code/object/range.rb +13 -11
  34. data/lib/code/object/string.rb +7 -7
  35. data/lib/code/object/time.rb +15 -8
  36. data/lib/code/object.rb +102 -5
  37. data/lib/code/parser.rb +1 -1
  38. data/lib/code/type.rb +10 -2
  39. data/lib/code/version.rb +1 -1
  40. data/lib/code-ruby.rb +6 -0
  41. data/lib/code.rb +8 -5
  42. data/spec/code/object/dictionary_spec.rb +0 -2
  43. data/spec/code_spec.rb +122 -16
  44. metadata +4 -3
  45. data/lib/code/object/number.rb +0 -11
@@ -2,12 +2,30 @@
2
2
 
3
3
  class Code
4
4
  class Object
5
- class Function < ::Code::Object
5
+ class Function < Object
6
6
  attr_reader :parameters, :body
7
7
 
8
- def initialize(parameters:, body:)
9
- @parameters = parameters.presence || []
10
- @body = body.presence || Node::Code.new
8
+ def initialize(*args, **_kargs, &_block)
9
+ parameters = args.first.presence || List.new
10
+ parameters = parameters.raw if parameters.is_an?(Object)
11
+ @parameters = List.new(parameters)
12
+ @parameters.raw.map! do |parameter|
13
+ if parameter.is_a?(Node::FunctionParameter)
14
+ Parameter.new(
15
+ Dictionary.new({
16
+ String.new(:name) => String.new(parameter.name),
17
+ String.new(:keyword) => Boolean.new(parameter.keyword?),
18
+ String.new(:regular_splat) => Boolean.new(parameter.regular_splat?),
19
+ String.new(:keyword_splat) => Boolean.new(parameter.keyword_splat?),
20
+ String.new(:default) => Code.new(parameter.default),
21
+ })
22
+ )
23
+ else
24
+ Parameter.new(parameter)
25
+ end
26
+ end
27
+ @body = Code.new(args.second.presence || Nothing.new)
28
+ super
11
29
  end
12
30
 
13
31
  def self.name
@@ -17,7 +35,7 @@ class Code
17
35
  def call(**args)
18
36
  operator = args.fetch(:operator, nil)
19
37
  arguments = args.fetch(:arguments, [])
20
- globals = multi_fetch(args, *::Code::GLOBALS)
38
+ globals = multi_fetch(args, *GLOBALS)
21
39
 
22
40
  case operator.to_s
23
41
  when "", "call"
@@ -29,27 +47,21 @@ class Code
29
47
  end
30
48
 
31
49
  def code_call(*arguments, **globals)
32
- context = Context.new({}, parent: globals[:context])
50
+ context = Context.new({}, globals[:context])
33
51
 
34
- parameters.each.with_index do |parameter, index|
35
- if parameter.regular?
36
- if parameter.regular_splat?
37
- context.code_set(
38
- parameter.name,
39
- List.new(arguments.select(&:regular?).map(&:value))
40
- )
41
- elsif parameter.keyword_splat?
42
- context.code_set(
43
- parameter.name,
44
- Dictionary.new(
45
- arguments.select(&:keyword?).map(&:name_value).to_h
46
- )
52
+ parameters.raw.each.with_index do |parameter, index|
53
+ if parameter.regular_splat?
54
+ context.code_set(
55
+ parameter.name,
56
+ List.new(arguments.select(&:regular?).map(&:value))
57
+ )
58
+ elsif parameter.keyword_splat?
59
+ context.code_set(
60
+ parameter.name,
61
+ Dictionary.new(
62
+ arguments.select(&:keyword?).map(&:name_value).to_h
47
63
  )
48
- else
49
- argument = arguments[index]&.value
50
- argument = parameter.evaluate(**globals) if argument.nil?
51
- context.code_set(parameter.name, argument)
52
- end
64
+ )
53
65
  elsif parameter.keyword?
54
66
  argument =
55
67
  arguments
@@ -57,6 +69,10 @@ class Code
57
69
  &.value
58
70
  argument = parameter.evaluate(**globals) if argument.nil?
59
71
  context.code_set(parameter.name, argument)
72
+ elsif parameter.regular?
73
+ argument = arguments[index]&.value
74
+ argument = parameter.evaluate(**globals) if argument.nil?
75
+ context.code_set(parameter.name, argument)
60
76
  end
61
77
  end
62
78
 
@@ -68,10 +84,10 @@ class Code
68
84
  end
69
85
 
70
86
  def signature_for_call
71
- parameters.inject([]) do |signature, parameter|
87
+ parameters.raw.inject([]) do |signature, parameter|
72
88
  if parameter.keyword?
73
89
  if signature.last.is_a?(::Hash)
74
- signature.last[parameter.name] = Object
90
+ signature.last.code_set(parameter.name, Object)
75
91
  signature
76
92
  else
77
93
  signature + [{ parameter.name => Object }]
@@ -2,11 +2,15 @@
2
2
 
3
3
  class Code
4
4
  class Object
5
- class Global < ::Code::Object
5
+ class Global < Object
6
6
  def self.name
7
7
  "Global"
8
8
  end
9
9
 
10
+ def initialize(...)
11
+ super
12
+ end
13
+
10
14
  def call(**args)
11
15
  operator = args.fetch(:operator, nil)
12
16
  arguments = args.fetch(:arguments, [])
@@ -14,62 +18,78 @@ class Code
14
18
  context = args.fetch(:context)
15
19
  globals = multi_fetch(args, *GLOBALS)
16
20
  value = arguments.first&.value
21
+ values = arguments.map(&:value)
17
22
 
18
23
  case operator.to_s
19
24
  when "Boolean"
20
- sig(args) { Object.maybe }
21
- value ? value.code_to_boolean : Class.new(Boolean)
25
+ sig(args) { Object.repeat }
26
+ value ? Boolean.new(*values) : Class.new(Boolean)
22
27
  when "break"
23
- sig(args) { Object.maybe }
28
+ sig(args) { Object.repeat }
24
29
  raise Error::Break, value || Nothing.new
25
30
  when "next"
26
- sig(args) { Object.maybe }
31
+ sig(args) { Object.repeat }
27
32
  raise Error::Next, value || Nothing.new
28
33
  when "Class"
29
- sig(args) { Object.maybe }
30
- value ? value.code_to_class : Class.new(Class)
34
+ sig(args) { Object.repeat }
35
+ value ? Class.new(*values) : Class.new(Class)
31
36
  when "Date"
32
- sig(args) { Object.maybe }
33
- value ? value.code_to_date : Class.new(Date)
37
+ sig(args) { Object.repeat }
38
+ value ? Date.new(*values) : Class.new(Date)
34
39
  when "Decimal"
35
- sig(args) { Object.maybe }
36
- value ? value.code_to_decimal : Class.new(Decimal)
40
+ sig(args) { Object.repeat }
41
+ value ? Decimal.new(*values) : Class.new(Decimal)
37
42
  when "Dictionary"
38
- sig(args) { Object.maybe }
39
- value ? value.code_to_dictionnary : Class.new(Dictionary)
40
- when "fetch"
41
- sig(args) { [Object, Function.maybe] }
42
- context.code_fetch(*arguments.map(&:value), **globals)
43
+ sig(args) { Object.repeat }
44
+ value ? Dictionary.new(*values) : Class.new(Dictionary)
45
+ when "Duration"
46
+ sig(args) { Object.repeat }
47
+ value ? Duration.new(*values) : Class.new(Duration)
43
48
  when "Function"
44
- sig(args) { Object.maybe }
45
- value ? value.code_to_function : Class.new(Function)
49
+ sig(args)
50
+ Class.new(Function)
46
51
  when "Integer"
47
- sig(args) { Object.maybe }
48
- value ? value.code_to_integer : Class.new(Integer)
52
+ sig(args) { Object.repeat }
53
+ value ? Integer.new(*values) : Class.new(Integer)
49
54
  when "List"
50
- sig(args) { Object.maybe }
51
- value ? value.code_to_list : Class.new(List)
55
+ sig(args) { Object.repeat }
56
+ value ? List.new(*values) : Class.new(List)
52
57
  when "Nothing"
53
- sig(args) { Object.maybe }
54
- value ? value.code_to_nothing : Class.new(Nothing)
55
- when "Number"
56
- sig(args) { Object.maybe }
57
- value ? value.code_to_number : Class.new(Number)
58
+ sig(args) { Object.repeat }
59
+ value ? Nothing.new(*values) : Class.new(Nothing)
60
+ when "context"
61
+ sig(args)
62
+ context
58
63
  when "Object"
59
- sig(args) { Object.maybe }
60
- value ? value.code_to_object : Class.new(Object)
64
+ sig(args)
65
+ Class.new(Object)
61
66
  when "Range"
62
- sig(args) { Object.maybe }
63
- value ? value.code_to_range : Class.new(Range)
67
+ sig(args) { Object.repeat }
68
+ value ? Range.new(*values) : Class.new(Range)
64
69
  when "String"
65
- sig(args) { Object.maybe }
66
- value ? value.code_to_string : Class.new(String)
70
+ sig(args) { Object.repeat }
71
+ value ? String.new(*values) : Class.new(String)
67
72
  when "Time"
68
- sig(args) { Object.maybe }
69
- value ? value.code_to_time : Class.new(Time)
70
- when "context"
71
- sig(args) { String.maybe }
72
- value ? context.code_get(value) || Nothing.new : context
73
+ sig(args) { Object.repeat }
74
+ value ? Time.new(*values) : Class.new(Time)
75
+ when "Context"
76
+ sig(args) { Object.repeat }
77
+ value ? Context.new(*values) : Class.new(Context)
78
+ when "Code"
79
+ sig(args) { Object.repeat }
80
+ value ? Code.new(*values) : Class.new(Code)
81
+ when "Argument"
82
+ sig(args) { Object.repeat }
83
+ value ? Argument.new(*values) : Class.new(Argument)
84
+ when "Parameter"
85
+ sig(args) { Object.repeat }
86
+ value ? Parameter.new(*values) : Class.new(Parameter)
87
+ when "Range"
88
+ sig(args) { Object.repeat }
89
+ value ? Range.new(*values) : Class.new(Range)
90
+ when "IdentifierList"
91
+ sig(args) { Object.repeat }
92
+ value ? IdentifierList.new(*values) : Class.new(IdentifierList)
73
93
  when "evaluate"
74
94
  sig(args) { Object }
75
95
  Code.evaluate(value.to_s)
@@ -2,18 +2,15 @@
2
2
 
3
3
  class Code
4
4
  class Object
5
- class Integer < Number
6
- attr_reader :raw
7
-
8
- def initialize(whole, exponent: nil)
9
- whole = whole.raw if whole.is_a?(Integer)
10
- @raw = whole.to_i
11
- return unless exponent
12
-
13
- exponent = exponent.raw if exponent.is_a?(Number)
14
- @raw *= 10**exponent
5
+ class Integer < Object
6
+ def initialize(*args, **_kargs, &_block)
7
+ whole = args.first || 0
8
+ exponent = args.second || 0
9
+ whole = whole.raw if whole.is_an?(Object)
10
+ exponent = exponent.raw if exponent.is_an?(Object)
11
+ @raw = whole.to_i * 10**exponent
15
12
  rescue FloatDomainError => e
16
- raise Error, e.message
13
+ raise Error, "#{decimal.inspect} * 10**#{exponent.inspect} is invalid"
17
14
  end
18
15
 
19
16
  def self.name
@@ -28,49 +25,49 @@ class Code
28
25
 
29
26
  case operator.to_s
30
27
  when "%", "modulo"
31
- sig(args) { Number }
28
+ sig(args) { Integer | Decimal }
32
29
  code_modulo(value)
33
30
  when "&", "bitwise_and"
34
- sig(args) { Number }
31
+ sig(args) { Integer | Decimal }
35
32
  code_bitwise_and(value)
36
33
  when "*", "multiplication", "×"
37
- sig(args) { Number | String }
34
+ sig(args) { Integer | Decimal | String }
38
35
  code_multiplication(value)
39
36
  when "**", "power"
40
- sig(args) { Number }
37
+ sig(args) { Integer | Decimal }
41
38
  code_power(value)
42
39
  when "+", "plus", "self"
43
40
  sig(args) { Object.maybe }
44
41
  value ? code_plus(value) : code_self
45
42
  when "-", "minus", "unary_minus"
46
- sig(args) { Number.maybe }
43
+ sig(args) { Integer | Decimal.maybe }
47
44
  value ? code_minus(value) : code_unary_minus
48
45
  when "/", "division", "÷"
49
- sig(args) { Number }
46
+ sig(args) { Integer | Decimal }
50
47
  code_division(value)
51
48
  when "<", "inferior"
52
- sig(args) { Number }
49
+ sig(args) { Integer | Decimal }
53
50
  code_inferior(value)
54
51
  when "<<", "left_shift"
55
- sig(args) { Number }
52
+ sig(args) { Integer | Decimal }
56
53
  code_left_shift(value)
57
54
  when "<=", "inferior_or_equal"
58
- sig(args) { Number }
55
+ sig(args) { Integer | Decimal }
59
56
  code_inferior_or_equal(value)
60
57
  when "<=>", "compare"
61
- sig(args) { Number }
58
+ sig(args) { Integer | Decimal }
62
59
  code_compare(value)
63
60
  when ">", "superior"
64
- sig(args) { Number }
61
+ sig(args) { Integer | Decimal }
65
62
  code_superior(value)
66
63
  when ">=", "superior_or_equal"
67
- sig(args) { Number }
64
+ sig(args) { Integer | Decimal }
68
65
  code_superior_or_equal(value)
69
66
  when ">>", "right_shift"
70
- sig(args) { Number }
67
+ sig(args) { Integer | Decimal }
71
68
  code_right_shift(value)
72
69
  when "^", "bitwise_xor"
73
- sig(args) { Number }
70
+ sig(args) { Integer | Decimal }
74
71
  code_bitwise_xor(value)
75
72
  when "abs"
76
73
  sig(args)
@@ -163,7 +160,7 @@ class Code
163
160
  sig(args)
164
161
  code_zero?
165
162
  when "|", "bitwise_or"
166
- sig(args) { Number }
163
+ sig(args) { Integer | Decimal }
167
164
  code_bitwise_or(value)
168
165
  else
169
166
  super
@@ -2,12 +2,12 @@
2
2
 
3
3
  class Code
4
4
  class Object
5
- class List < ::Code::Object
6
- attr_reader :raw
7
-
8
- def initialize(raw = [])
9
- raw = raw.raw if raw.is_a?(List)
5
+ class List < Object
6
+ def initialize(*args, **_kargs, &_block)
7
+ raw = args.first || Nothing.new
8
+ raw = raw.raw if raw.is_an?(Object)
10
9
  @raw = raw.to_a
10
+ super
11
11
  end
12
12
 
13
13
  def self.name
@@ -2,10 +2,8 @@
2
2
 
3
3
  class Code
4
4
  class Object
5
- class Nothing < ::Code::Object
6
- attr_reader :raw
7
-
8
- def initialize
5
+ class Nothing < Object
6
+ def initialize(*_args, **_kargs, &_block)
9
7
  @raw = nil
10
8
  end
11
9
 
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Code
4
+ class Object
5
+ class Parameter < Object
6
+ attr_reader :name, :keyword, :regular_splat, :keyword_splat, :default
7
+
8
+ def self.name
9
+ "Parameter"
10
+ end
11
+
12
+ def initialize(*args, **_kargs, &_block)
13
+ @raw = Dictionary.new(args.first.presence || {})
14
+ @name = String.new(@raw.code_get(String.new(:name)))
15
+ @keyword = Boolean.new(@raw.code_get(String.new(:keyword)))
16
+ @regular_splat = Boolean.new(@raw.code_get(String.new(:regular_splat)))
17
+ @keyword_splat = Boolean.new(@raw.code_get(String.new(:keyword_splat)))
18
+ @default = Code.new(@raw.code_get(String.new(:default)))
19
+ super
20
+ end
21
+
22
+ def evaluate(...)
23
+ default.evaluate(...)
24
+ end
25
+
26
+ def regular?
27
+ !keyword?
28
+ end
29
+
30
+ def keyword?
31
+ keyword.truthy?
32
+ end
33
+
34
+ def regular_splat?
35
+ regular_splat.truthy?
36
+ end
37
+
38
+ def keyword_splat?
39
+ keyword_splat.truthy?
40
+ end
41
+ end
42
+ end
43
+ end
@@ -3,13 +3,15 @@
3
3
  class Code
4
4
  class Object
5
5
  class Range < Object
6
- attr_reader :raw, :exclude_end, :left, :right
6
+ attr_reader :left, :right, :options, :exclude_end
7
7
 
8
- def initialize(left, right, exclude_end: false)
9
- @left = left
10
- @right = right
11
- @exclude_end = !exclude_end.nil?
12
- @raw = ::Range.new(left, right, exclude_end)
8
+ def initialize(*args, **_kargs, &_block)
9
+ @left = args.first.presence || Integer.new(0)
10
+ @right = args.second.presence || Integer.new(0)
11
+ @options = Dictionary.new(args.third.presence || Dictionary.new)
12
+ @exclude_end = Boolean.new(@options.code_get(String.new(:exclude_end)))
13
+ @raw = ::Range.new(left, right, exclude_end?)
14
+ super
13
15
  end
14
16
 
15
17
  def self.name
@@ -45,7 +47,7 @@ class Code
45
47
  sig(args) { Function }
46
48
  code_select(value, **globals)
47
49
  when "step"
48
- sig(args) { Number }
50
+ sig(args) { Integer | Decimal }
49
51
  code_step(value)
50
52
  when "to_list"
51
53
  sig(args)
@@ -102,6 +104,10 @@ class Code
102
104
  )
103
105
  end
104
106
 
107
+ def exclude_end?
108
+ exclude_end.truthy?
109
+ end
110
+
105
111
  def code_step(argument)
106
112
  list = List.new
107
113
  element = left
@@ -127,10 +133,6 @@ class Code
127
133
  List.new(raw.to_a)
128
134
  end
129
135
 
130
- def exclude_end?
131
- !!exclude_end
132
- end
133
-
134
136
  def inspect
135
137
  to_s
136
138
  end
@@ -3,11 +3,11 @@
3
3
  class Code
4
4
  class Object
5
5
  class String < Object
6
- attr_reader :raw
7
-
8
- def initialize(string)
9
- string = string.raw if string.is_a?(String)
10
- @raw = string.to_s
6
+ def initialize(*args, **_kargs, &_block)
7
+ raw = args.first || Nothing.new
8
+ raw = raw.raw if raw.is_a?(Object)
9
+ @raw = raw.to_s
10
+ super
11
11
  end
12
12
 
13
13
  def self.name
@@ -25,7 +25,7 @@ class Code
25
25
  sig(args)
26
26
  code_to_function(**globals)
27
27
  when "*"
28
- sig(args) { Number }
28
+ sig(args) { Integer | Decimal }
29
29
  code_multiplication(value)
30
30
  when "+"
31
31
  sig(args) { Object }
@@ -65,7 +65,7 @@ class Code
65
65
  end
66
66
 
67
67
  def code_to_function(**globals)
68
- Code::Node::Code.new(
68
+ Node::Code.new(
69
69
  [
70
70
  {
71
71
  function: {
@@ -5,13 +5,12 @@ class Code
5
5
  class Time < Object
6
6
  DEFAULT_ZONE = "Etc/UTC"
7
7
 
8
- attr_reader :raw
9
-
10
- def initialize(time)
8
+ def initialize(*args, **_kargs, &_block)
11
9
  ::Time.zone ||= DEFAULT_ZONE
12
- time = time.raw if time.is_a?(Time)
13
- time = time.to_s if time.is_a?(::Time)
14
- @raw = ::Time.zone.parse(time)
10
+ raw = args.first.presence || ::Time.zone.now
11
+ raw = raw.raw if raw.is_an?(Object)
12
+ @raw = ::Time.zone.parse(raw.to_s)
13
+ super
15
14
  end
16
15
 
17
16
  def self.name
@@ -28,6 +27,9 @@ class Code
28
27
  when "tomorrow"
29
28
  sig(args)
30
29
  code_tomorrow
30
+ when "yesterday"
31
+ sig(args)
32
+ code_yesterday
31
33
  else
32
34
  super
33
35
  end
@@ -35,12 +37,17 @@ class Code
35
37
 
36
38
  def self.code_tomorrow
37
39
  ::Time.zone ||= DEFAULT_ZONE
38
- new(::Time.zone.tomorrow.beginning_of_day)
40
+ new(::Time.zone.tomorrow)
41
+ end
42
+
43
+ def self.code_yesterday
44
+ ::Time.zone ||= DEFAULT_ZONE
45
+ new(::Time.zone.yesterday)
39
46
  end
40
47
 
41
48
  def self.code_now
42
49
  ::Time.zone ||= DEFAULT_ZONE
43
- new(::Time.zone.now.beginning_of_day)
50
+ new(::Time.zone.now)
44
51
  end
45
52
 
46
53
  def call(**args)