tataru 0.1.0 → 0.2.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 (102) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +5 -0
  3. data/bin/console +15 -0
  4. data/bin/setup +8 -0
  5. data/lib/tataru.rb +70 -12
  6. data/lib/tataru/base_resource.rb +49 -0
  7. data/lib/tataru/base_resource_desc.rb +35 -0
  8. data/lib/tataru/compiler.rb +100 -0
  9. data/lib/tataru/create_subroutines.rb +31 -0
  10. data/lib/tataru/delete_subroutines.rb +42 -0
  11. data/lib/tataru/flattener.rb +81 -0
  12. data/lib/tataru/init_hash_compiler.rb +41 -0
  13. data/lib/tataru/instruction.rb +52 -7
  14. data/lib/tataru/instruction_hash.rb +54 -0
  15. data/lib/tataru/instructions/call_instruction.rb +19 -0
  16. data/lib/tataru/instructions/check_create_instruction.rb +27 -0
  17. data/lib/tataru/instructions/check_delete_instruction.rb +20 -0
  18. data/lib/tataru/instructions/check_instruction.rb +26 -0
  19. data/lib/tataru/instructions/check_update_instruction.rb +27 -0
  20. data/lib/tataru/instructions/clear_instruction.rb +12 -0
  21. data/lib/tataru/instructions/compare_instruction.rb +16 -0
  22. data/lib/tataru/instructions/create_instruction.rb +20 -0
  23. data/lib/tataru/instructions/delete_instruction.rb +14 -0
  24. data/lib/tataru/instructions/end_instruction.rb +12 -0
  25. data/lib/tataru/instructions/goto_if_instruction.rb +26 -0
  26. data/lib/tataru/instructions/immediate_mode_instruction.rb +12 -0
  27. data/lib/tataru/instructions/init_instruction.rb +27 -0
  28. data/lib/tataru/instructions/key_instruction.rb +12 -0
  29. data/lib/tataru/instructions/mark_deletable_instruction.rb +13 -0
  30. data/lib/tataru/instructions/read_instruction.rb +28 -0
  31. data/lib/tataru/instructions/rescmp_instruction.rb +34 -0
  32. data/lib/tataru/instructions/resource_instruction.rb +15 -0
  33. data/lib/tataru/instructions/return_instruction.rb +16 -0
  34. data/lib/tataru/instructions/update_instruction.rb +16 -0
  35. data/lib/tataru/instructions/value_instruction.rb +15 -0
  36. data/lib/tataru/instructions/value_rom_instruction.rb +23 -0
  37. data/lib/tataru/instructions/value_update_instruction.rb +18 -0
  38. data/lib/tataru/memory.rb +16 -0
  39. data/lib/tataru/quest.rb +43 -0
  40. data/lib/tataru/representation.rb +22 -0
  41. data/lib/tataru/representations/array_representation.rb +18 -0
  42. data/lib/tataru/representations/hash_representation.rb +20 -0
  43. data/lib/tataru/representations/literal_representation.rb +9 -0
  44. data/lib/tataru/representations/output_representation.rb +19 -0
  45. data/lib/tataru/representations/resource_representation.rb +49 -0
  46. data/lib/tataru/resolver.rb +39 -0
  47. data/lib/tataru/resource_dsl.rb +21 -71
  48. data/lib/tataru/resource_type_pool.rb +22 -0
  49. data/lib/tataru/rom_reader.rb +47 -0
  50. data/lib/tataru/runner.rb +48 -0
  51. data/lib/tataru/sub_planner.rb +41 -0
  52. data/lib/tataru/subroutine_compiler.rb +52 -0
  53. data/lib/tataru/top_dsl.rb +35 -0
  54. data/lib/tataru/update_subroutines.rb +111 -0
  55. data/lib/tataru/version.rb +1 -1
  56. data/spec/compiler_spec.rb +181 -0
  57. data/spec/flattener_spec.rb +88 -0
  58. data/spec/init_hash_compiler_spec.rb +85 -0
  59. data/spec/instruction_hash_spec.rb +63 -0
  60. data/spec/instruction_spec.rb +36 -0
  61. data/spec/instructions/call_instruction_spec.rb +28 -0
  62. data/spec/instructions/check_create_instruction_spec.rb +67 -0
  63. data/spec/instructions/check_delete_instruction_spec.rb +47 -0
  64. data/spec/instructions/check_update_instruction_spec.rb +67 -0
  65. data/spec/instructions/clear_instruction_spec.rb +16 -0
  66. data/spec/instructions/compare_instruction_spec.rb +29 -0
  67. data/spec/instructions/create_instruction_spec.rb +62 -0
  68. data/spec/instructions/delete_instruction_spec.rb +20 -0
  69. data/spec/instructions/end_instruction_spec.rb +15 -0
  70. data/spec/instructions/goto_if_instruction_spec.rb +42 -0
  71. data/spec/instructions/init_instruction_spec.rb +16 -0
  72. data/spec/instructions/key_instruction_spec.rb +15 -0
  73. data/spec/instructions/mark_deletable_instruction_spec.rb +20 -0
  74. data/spec/instructions/read_instruction_spec.rb +34 -0
  75. data/spec/instructions/rescmp_instruction_spec.rb +113 -0
  76. data/spec/instructions/return_instruction_spec.rb +28 -0
  77. data/spec/instructions/update_instruction_spec.rb +39 -0
  78. data/spec/instructions/value_instruction_spec.rb +27 -0
  79. data/spec/instructions/value_rom_instruction_spec.rb +170 -0
  80. data/spec/instructions/value_update_instruction_spec.rb +35 -0
  81. data/spec/quest_spec.rb +9 -0
  82. data/spec/representations/array_representation_spec.rb +29 -0
  83. data/spec/representations/hash_representation_spec.rb +29 -0
  84. data/spec/representations/literal_representation_spec.rb +10 -0
  85. data/spec/representations/output_representation_spec.rb +11 -0
  86. data/spec/representations/resource_representation_spec.rb +50 -0
  87. data/spec/resource_dsl_spec.rb +71 -0
  88. data/spec/runner_spec.rb +99 -0
  89. data/spec/spec_helper.rb +401 -0
  90. data/spec/subroutine_compiler_spec.rb +39 -0
  91. data/spec/taru_spec.rb +616 -0
  92. data/spec/top_dsl_spec.rb +68 -0
  93. data/tataru.gemspec +45 -0
  94. metadata +145 -27
  95. data/Rakefile +0 -8
  96. data/lib/tataru/default_resource_finder.rb +0 -10
  97. data/lib/tataru/execution_step.rb +0 -79
  98. data/lib/tataru/planner.rb +0 -93
  99. data/lib/tataru/requirements.rb +0 -67
  100. data/lib/tataru/requirements_dsl.rb +0 -33
  101. data/lib/tataru/resource.rb +0 -52
  102. data/lib/tataru/state.rb +0 -64
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tataru
4
+ module Instructions
5
+ # puts remote id up for deletion
6
+ class MarkDeletableInstruction < ResourceInstruction
7
+ def run
8
+ remote_id = memory.hash[:remote_ids].delete(resource_name)
9
+ memory.hash[:remote_ids]["_deletable_#{resource_name}"] = remote_id
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tataru
4
+ module Instructions
5
+ # read properties of resource
6
+ class ReadInstruction < ResourceInstruction
7
+ def run
8
+ results = resource.read(fields)
9
+ memory.hash[:temp][resource_name] = {}
10
+ fields.each do |k|
11
+ memory.hash[:temp][resource_name][k] = results[k]
12
+ end
13
+ end
14
+
15
+ def resource_class
16
+ desc.resource_class
17
+ end
18
+
19
+ def resource
20
+ resource_class.new(memory.hash[:remote_ids][resource_name])
21
+ end
22
+
23
+ def fields
24
+ @fields ||= desc.immutable_fields + desc.mutable_fields
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tataru
4
+ module Instructions
5
+ # compares resource in temp and resource in top
6
+ class RescmpInstruction < ResourceInstruction
7
+ include RomReader
8
+
9
+ def run
10
+ raise 'Not found' unless rom.key? resource_name
11
+
12
+ update!
13
+ end
14
+
15
+ def update!
16
+ current = memory.hash[:temp][resource_name]
17
+ desired = resolve(rom[resource_name])
18
+
19
+ memory.hash[:update_action][resource_name] = compare(current, desired)
20
+ end
21
+
22
+ def compare(current, desired)
23
+ result = :no_change
24
+ desc.mutable_fields.each do |field|
25
+ result = :modify if current[field] != desired[field]
26
+ end
27
+ desc.immutable_fields.each do |field|
28
+ result = :recreate if current[field] != desired[field]
29
+ end
30
+ result
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tataru
4
+ module Instructions
5
+ # instructions that deal with resources
6
+ class ResourceInstruction < Instruction
7
+ expects :resource_name
8
+ expects :resource_desc
9
+
10
+ def desc
11
+ Kernel.const_get(resource_desc).new
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tataru
4
+ module Instructions
5
+ # pops the callstack and goes back
6
+ class ReturnInstruction < Instruction
7
+ def run
8
+ if memory.call_stack.count.zero?
9
+ return memory.error = 'At bottom of stack'
10
+ end
11
+
12
+ memory.program_counter = memory.call_stack.pop
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tataru
4
+ module Instructions
5
+ # update a resource
6
+ class UpdateInstruction < ResourceInstruction
7
+ expects :properties
8
+
9
+ def run
10
+ resource_class = desc.resource_class
11
+ resource = resource_class.new(memory.hash[:remote_ids][resource_name])
12
+ resource.update(properties)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tataru
4
+ module Instructions
5
+ # sets a hash entry based on whatever key was set
6
+ class ValueInstruction < ImmediateModeInstruction
7
+ def run
8
+ return memory.error = 'No key set' unless memory.hash[:temp].key? :_key
9
+
10
+ key = memory.hash[:temp].delete :_key
11
+ memory.hash[:temp][key] = @param
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tataru
4
+ module Instructions
5
+ # sets a hash entry and resolves from rom what was set
6
+ class ValueRomInstruction < ImmediateModeInstruction
7
+ include RomReader
8
+
9
+ def run
10
+ return memory.error = 'No key set' unless memory.hash[:temp].key? :_key
11
+
12
+ key = memory.hash[:temp].delete :_key
13
+ memory.hash[:temp][key] = resolve(rom_object)
14
+ end
15
+
16
+ def rom_object
17
+ raise 'Not found' unless rom.key? @param
18
+
19
+ rom[@param]
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tataru
4
+ module Instructions
5
+ # sets temp result
6
+ class ValueUpdateInstruction < ImmediateModeInstruction
7
+ def run
8
+ unless memory.hash[:update_action].key? @param
9
+ raise "No value set for '#{@param}'"
10
+ end
11
+
12
+ memory.hash[:temp] = {
13
+ result: memory.hash[:update_action][@param]
14
+ }
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tataru
4
+ # memory that can be manipulated by instructions
5
+ class Memory
6
+ attr_accessor :program_counter, :hash, :call_stack, :error, :end
7
+
8
+ def initialize
9
+ @program_counter = 0
10
+ @hash = { temp: {} }
11
+ @error = nil
12
+ @call_stack = []
13
+ @end = false
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tataru
4
+ # tataru
5
+ class Quest
6
+ attr_reader :dsl
7
+
8
+ def initialize(pool, current_state = {})
9
+ @pool = pool
10
+ @current_state = current_state
11
+ @dsl = TopDsl.new(pool)
12
+ end
13
+
14
+ def construct(&block)
15
+ @dsl.instance_eval(&block)
16
+ end
17
+
18
+ def extant_resources
19
+ @current_state.map do |resname, info|
20
+ [resname, info[:desc]]
21
+ end.to_h
22
+ end
23
+
24
+ def remote_ids
25
+ @current_state.map do |resname, info|
26
+ [resname, info[:name]]
27
+ end.to_h
28
+ end
29
+
30
+ def extant_dependencies
31
+ @current_state.map do |resname, info|
32
+ [resname, info[:dependencies]]
33
+ end.to_h
34
+ end
35
+
36
+ def instr_hash
37
+ c = Compiler.new(@dsl, extant_resources, extant_dependencies)
38
+ result = c.instr_hash
39
+ result[:init][:remote_ids] = remote_ids
40
+ result
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tataru
4
+ # base representation
5
+ class Representation
6
+ attr_reader :value
7
+
8
+ def initialize(value)
9
+ @value = value
10
+ end
11
+
12
+ def dependencies
13
+ []
14
+ end
15
+ end
16
+ end
17
+
18
+ require 'tataru/representations/hash_representation'
19
+ require 'tataru/representations/array_representation'
20
+ require 'tataru/representations/literal_representation'
21
+ require 'tataru/representations/output_representation'
22
+ require 'tataru/representations/resource_representation'
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tataru
4
+ module Representations
5
+ # representing arrays
6
+ class ArrayRepresentation < Representation
7
+ def initialize(value)
8
+ @value = value.map do |thing|
9
+ Resolver.new(thing).representation
10
+ end.to_a
11
+ end
12
+
13
+ def dependencies
14
+ @dependencies ||= @value.flat_map(&:dependencies)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tataru
4
+ module Representations
5
+ # representing hashes
6
+ class HashRepresentation < Representation
7
+ def initialize(value)
8
+ @value = value.map do |key, thing|
9
+ [key, Resolver.new(thing).representation]
10
+ end.to_h
11
+ end
12
+
13
+ def dependencies
14
+ @dependencies ||= @value.flat_map do |_key, rep|
15
+ rep.dependencies
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tataru
4
+ module Representations
5
+ # representing simple values
6
+ class LiteralRepresentation < Representation
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tataru
4
+ module Representations
5
+ # internal representation of output
6
+ class OutputRepresentation < Representation
7
+ attr_reader :resource_name, :output_field_name
8
+
9
+ def initialize(resource_name, output_field_name)
10
+ @resource_name = resource_name
11
+ @output_field_name = output_field_name
12
+ end
13
+
14
+ def dependencies
15
+ [@resource_name]
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tataru
4
+ module Representations
5
+ # internal representation of resources
6
+ class ResourceRepresentation < Representation
7
+ attr_reader :name, :properties, :desc
8
+
9
+ def initialize(name, desc, properties)
10
+ @name = name
11
+ @properties = properties
12
+ @desc = desc
13
+ check_late_deletability!
14
+ end
15
+
16
+ def check_late_deletability!
17
+ return unless @desc.delete_at_end? && !@desc.needs_remote_id?
18
+
19
+ raise 'must need remote id if deletes at end'
20
+ end
21
+
22
+ def check_required_fields!
23
+ @desc.required_fields.each do |field|
24
+ next if @properties.key? field
25
+
26
+ raise "Required field '#{field}' not provided in '#{@name}'"
27
+ end
28
+ end
29
+
30
+ def respond_to_missing?(name, *_args)
31
+ true if @desc.output_fields.include? name
32
+ end
33
+
34
+ def remote_id
35
+ OutputRepresentation.new(@name, :remote_id)
36
+ end
37
+
38
+ def method_missing(name, *args, &block)
39
+ return super unless @desc.output_fields.include? name
40
+
41
+ OutputRepresentation.new(@name, name)
42
+ end
43
+
44
+ def dependencies
45
+ [@name]
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tataru
4
+ # resolver for data
5
+ class Resolver
6
+ def initialize(expression)
7
+ @expression = expression
8
+ end
9
+
10
+ def representation
11
+ @representation ||= generate_representation
12
+ end
13
+
14
+ def dependencies
15
+ representation.dependencies
16
+ end
17
+
18
+ private
19
+
20
+ def generate_representation
21
+ case @expression
22
+ when String
23
+ Representations::LiteralRepresentation.new(@expression)
24
+ when Numeric
25
+ Representations::LiteralRepresentation.new(@expression)
26
+ when Array
27
+ Representations::ArrayRepresentation.new(@expression)
28
+ when Hash
29
+ Representations::HashRepresentation.new(@expression)
30
+ when Representations::ResourceRepresentation
31
+ @expression
32
+ when Representations::OutputRepresentation
33
+ @expression
34
+ else
35
+ raise "invalid value: #{@expression.inspect}"
36
+ end
37
+ end
38
+ end
39
+ end
@@ -1,86 +1,36 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Tataru
4
- module DoLater
5
- # delayed expression
6
- class Expression
7
- def requested_resources
8
- raise 'Abstract class'
9
- end
10
- end
11
-
12
- # placeholder for extern resource
13
- class ExternResourcePlaceholder < Expression
14
- def initialize(name)
15
- @name = name
16
- end
17
-
18
- def respond_to_missing?
19
- true
20
- end
21
-
22
- def method_missing(name, *_args)
23
- super if name.nil?
24
-
25
- MemberCallPlaceholder.new(self, name)
26
- end
27
-
28
- def requested_resources
29
- [@name]
30
- end
31
- end
4
+ # human representation of resources
5
+ class ResourceDsl
6
+ REPCLASS = Tataru::Representations::ResourceRepresentation
32
7
 
33
- # placeholder for member call
34
- class MemberCallPlaceholder < ExternResourcePlaceholder
35
- def initialize(expr, member)
36
- @expr = expr
37
- @member = member
38
- end
39
-
40
- def requested_resources
41
- @expr.requested_resources
42
- end
8
+ def initialize(name, desc)
9
+ @properties = {}
10
+ @desc = desc
11
+ @fields = Set.new(@desc.mutable_fields + @desc.immutable_fields)
12
+ @name = name
13
+ @dependencies = Set.new
43
14
  end
44
- end
45
15
 
46
- # Resource DSL
47
- class ResourceDSL
48
- attr_reader :fields, :extern_refs
49
-
50
- def initialize(resource_inst)
51
- @resource_inst = resource_inst
52
- @fields = {}
53
- @extern_refs = {}
54
- end
55
-
56
- def respond_to_missing?
57
- true
16
+ def respond_to_missing?(name, *_args)
17
+ true if @fields.include? name
58
18
  end
59
19
 
60
20
  def method_missing(name, *args, &block)
61
- if @resource_inst.respond_to?("#{name}_change_action")
62
- @fields[name] = args[0]
63
- elsif name.to_s.start_with?(/[a-z]/)
64
- @extern_refs[name] ||= DoLater::ExternResourcePlaceholder.new(name)
65
- else
66
- super
67
- end
68
- end
21
+ return super unless @fields.include? name
69
22
 
70
- def errors
71
- (@resource_inst.states - @fields.keys).map do |x|
72
- { missing_state: x }
73
- end
23
+ resolver = Resolver.new(args[0])
24
+ @dependencies += resolver.dependencies
25
+ @properties[name] = if resolver.representation.is_a? REPCLASS
26
+ resolver.representation.remote_id
27
+ else
28
+ resolver.representation
29
+ end
74
30
  end
75
31
 
76
- def dependencies
77
- deps = []
78
- @fields.each do |_name, info|
79
- next unless info.is_a? DoLater::Expression
80
-
81
- deps += info.requested_resources
82
- end
83
- deps.map(&:to_s).uniq
32
+ def representation
33
+ REPCLASS.new(@name, @desc, @properties)
84
34
  end
85
35
  end
86
36
  end