tataru 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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