kumi 0.0.29 → 0.0.30
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 +4 -4
- data/.rubocop.yml +2 -1
- data/CHANGELOG.md +12 -0
- data/README.md +5 -6
- data/docs/DEVELOPMENT.md +23 -1
- data/docs/GOLDEN_QUICK_START.md +141 -0
- data/docs/GOLDEN_TESTS.md +240 -0
- data/golden/array_element/expected/schema_ruby.rb +1 -1
- data/golden/array_index/expected/schema_ruby.rb +1 -1
- data/golden/array_operations/expected/schema_ruby.rb +1 -1
- data/golden/cascade_logic/expected/schema_ruby.rb +1 -1
- data/golden/chained_fusion/expected/schema_ruby.rb +1 -1
- data/golden/decimal_explicit/expected/schema_ruby.rb +1 -1
- data/golden/element_arrays/expected/schema_ruby.rb +1 -1
- data/golden/empty_and_null_inputs/expected/schema_ruby.rb +1 -1
- data/golden/function_overload/expected/schema_ruby.rb +1 -1
- data/golden/game_of_life/expected/schema_ruby.rb +1 -1
- data/golden/hash_keys/expected/schema_ruby.rb +1 -1
- data/golden/hash_value/expected/schema_ruby.rb +1 -1
- data/golden/hierarchical_complex/expected/schema_ruby.rb +1 -1
- data/golden/inline_rename_scope_leak/expected/schema_ruby.rb +1 -1
- data/golden/input_reference/expected/schema_ruby.rb +1 -1
- data/golden/interleaved_fusion/expected/schema_ruby.rb +1 -1
- data/golden/let_inline/expected/schema_ruby.rb +1 -1
- data/golden/loop_fusion/expected/schema_ruby.rb +1 -1
- data/golden/min_reduce_scope/expected/schema_ruby.rb +1 -1
- data/golden/mixed_dimensions/expected/schema_ruby.rb +1 -1
- data/golden/multirank_hoisting/expected/schema_ruby.rb +1 -1
- data/golden/nested_hash/expected/schema_ruby.rb +1 -1
- data/golden/reduction_broadcast/expected/schema_ruby.rb +1 -1
- data/golden/roll/expected/schema_ruby.rb +1 -1
- data/golden/shift/expected/schema_ruby.rb +1 -1
- data/golden/shift_2d/expected/schema_ruby.rb +1 -1
- data/golden/simple_math/expected/schema_ruby.rb +1 -1
- data/golden/streaming_basics/expected/schema_ruby.rb +1 -1
- data/golden/tuples/expected/schema_ruby.rb +1 -1
- data/golden/tuples_and_arrays/expected/schema_ruby.rb +1 -1
- data/golden/us_tax_2024/expected/schema_ruby.rb +1 -1
- data/golden/with_constants/expected/schema_ruby.rb +1 -1
- data/lib/kumi/analyzer.rb +39 -79
- data/lib/kumi/core/analyzer/analysis_state.rb +2 -0
- data/lib/kumi/core/analyzer/constant_evaluator.rb +0 -2
- data/lib/kumi/core/analyzer/execution_phase.rb +24 -0
- data/lib/kumi/core/analyzer/execution_result.rb +38 -0
- data/lib/kumi/core/analyzer/pass_failure.rb +26 -0
- data/lib/kumi/core/analyzer/pass_manager.rb +136 -0
- data/lib/kumi/core/analyzer/passes/codegen/js/declaration_emitter.rb +1 -1
- data/lib/kumi/core/analyzer/passes/codegen/js_pass.rb +1 -1
- data/lib/kumi/core/analyzer/passes/codegen/ruby/declaration_emitter.rb +1 -1
- data/lib/kumi/core/analyzer/passes/codegen/ruby_pass.rb +1 -1
- data/lib/kumi/core/analyzer/passes/constant_folding_pass.rb +1 -1
- data/lib/kumi/core/analyzer/passes/formal_constraint_propagator.rb +13 -31
- data/lib/kumi/core/analyzer/passes/input_access_planner_pass.rb +1 -1
- data/lib/kumi/core/analyzer/passes/input_collector.rb +1 -1
- data/lib/kumi/core/analyzer/passes/input_form_schema_pass.rb +1 -1
- data/lib/kumi/core/analyzer/passes/lir/loop_invariant_code_motion_pass.rb +1 -1
- data/lib/kumi/core/analyzer/passes/lir/stencil_emitter.rb +0 -2
- data/lib/kumi/core/analyzer/passes/normalize_to_nast_pass.rb +5 -1
- data/lib/kumi/core/analyzer/passes/output_schema_pass.rb +2 -1
- data/lib/kumi/core/analyzer/passes/snast_pass.rb +1 -1
- data/lib/kumi/core/analyzer/passes/unsat_detector.rb +8 -10
- data/lib/kumi/core/compiler/access_planner_v2.rb +1 -2
- data/lib/kumi/core/functions/overload_resolver.rb +15 -19
- data/lib/kumi/core/functions/type_categories.rb +3 -3
- data/lib/kumi/core/functions/type_error_reporter.rb +1 -3
- data/lib/kumi/core/input/type_matcher.rb +1 -1
- data/lib/kumi/core/types/normalizer.rb +8 -10
- data/lib/kumi/core/types/validator.rb +1 -1
- data/lib/kumi/core/types/value_objects.rb +5 -2
- data/lib/kumi/core/types.rb +2 -4
- data/lib/kumi/dev/codegen.rb +1 -1
- data/lib/kumi/dev/golden/generator.rb +14 -10
- data/lib/kumi/dev/golden/reporter.rb +5 -5
- data/lib/kumi/dev/golden/representation.rb +1 -3
- data/lib/kumi/dev/golden/result.rb +1 -1
- data/lib/kumi/dev/golden/runtime_test.rb +0 -2
- data/lib/kumi/dev/golden/suite.rb +20 -4
- data/lib/kumi/dev/golden/value_normalizer.rb +1 -3
- data/lib/kumi/doc_generator/formatters/json.rb +11 -11
- data/lib/kumi/doc_generator/formatters/markdown.rb +35 -37
- data/lib/kumi/doc_generator/loader.rb +8 -6
- data/lib/kumi/doc_generator/merger.rb +12 -12
- data/lib/kumi/frontends/text.rb +4 -6
- data/lib/kumi/registry_v2/loader.rb +32 -33
- data/lib/kumi/schema.rb +2 -2
- data/lib/kumi/version.rb +1 -1
- metadata +13 -14
- data/debug_ordering.rb +0 -52
- data/examples/deep_schema_compilation_and_evaluation_benchmark.rb +0 -106
- data/examples/federal_tax_calculator_2024.rb +0 -115
- data/examples/game_of_life.rb +0 -95
- data/examples/simple_rpg_game.rb +0 -1000
- data/examples/static_analysis_errors.rb +0 -178
- data/examples/wide_schema_compilation_and_evaluation_benchmark.rb +0 -80
|
@@ -97,7 +97,7 @@ module Kumi
|
|
|
97
97
|
new_ops
|
|
98
98
|
end
|
|
99
99
|
|
|
100
|
-
def is_invariant(ins, defs_in_loop, prefix,
|
|
100
|
+
def is_invariant(ins, defs_in_loop, prefix, _depth)
|
|
101
101
|
prefix_inner = "#{prefix} "
|
|
102
102
|
debug "#{prefix_inner}- Checking: #{ins.result_register || '(no result)'} = #{ins.opcode}(#{ins.inputs.join(', ')})"
|
|
103
103
|
|
|
@@ -80,7 +80,11 @@ module Kumi
|
|
|
80
80
|
# Try to get the function to check if it's expandable
|
|
81
81
|
# For expandable functions, we need to resolve now
|
|
82
82
|
# For regular functions, we defer resolution to NASTDimensionalAnalyzerPass
|
|
83
|
-
func =
|
|
83
|
+
func = begin
|
|
84
|
+
@registry.function(fn_alias)
|
|
85
|
+
rescue StandardError
|
|
86
|
+
nil
|
|
87
|
+
end
|
|
84
88
|
rescue StandardError
|
|
85
89
|
# puts "MISSING_FUNCTION: #{node.fn_name.inspect}"
|
|
86
90
|
raise
|
|
@@ -5,7 +5,7 @@ module Kumi
|
|
|
5
5
|
module Analyzer
|
|
6
6
|
module Passes
|
|
7
7
|
class OutputSchemaPass < PassBase
|
|
8
|
-
def run(
|
|
8
|
+
def run(_errors)
|
|
9
9
|
snast_module = get_state(:snast_module)
|
|
10
10
|
return state unless snast_module
|
|
11
11
|
|
|
@@ -19,6 +19,7 @@ module Kumi
|
|
|
19
19
|
def build_output_schema(snast_module, hints)
|
|
20
20
|
snast_module.decls.each_with_object({}) do |(name, decl), acc|
|
|
21
21
|
next if hints[name][:inline]
|
|
22
|
+
|
|
22
23
|
acc[name] = build_output_field(decl)
|
|
23
24
|
end
|
|
24
25
|
end
|
|
@@ -176,7 +176,7 @@ module Kumi
|
|
|
176
176
|
m = meta_for(n)
|
|
177
177
|
# Use the function ID from metadata (already resolved with type awareness in NASTDimensionalAnalyzerPass)
|
|
178
178
|
fn_id = m[:function] || @registry.resolve_function(n.fn)
|
|
179
|
-
out
|
|
179
|
+
out = n.class.new(id: n.id, fn: fn_id.to_sym, args:, opts: n.opts, loc: n.loc)
|
|
180
180
|
stamp!(out, m[:result_scope], m[:result_type])
|
|
181
181
|
end
|
|
182
182
|
|
|
@@ -32,14 +32,14 @@ module Kumi
|
|
|
32
32
|
next if atoms.empty?
|
|
33
33
|
|
|
34
34
|
# Check for formal, obvious contradictions
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
35
|
+
next unless contradicting_equalities?(atoms) || domain_violations?(atoms, input_meta) ||
|
|
36
|
+
propagated_violations?(atoms, definitions, input_meta, registry)
|
|
37
|
+
|
|
38
|
+
report_error(
|
|
39
|
+
errors,
|
|
40
|
+
"conjunction `#{decl.name}` is impossible",
|
|
41
|
+
location: decl.loc
|
|
42
|
+
)
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
state
|
|
@@ -90,8 +90,6 @@ module Kumi
|
|
|
90
90
|
val == :unknown ? node.name : val
|
|
91
91
|
when InputReference
|
|
92
92
|
node.name
|
|
93
|
-
else
|
|
94
|
-
nil
|
|
95
93
|
end
|
|
96
94
|
end
|
|
97
95
|
|
|
@@ -29,8 +29,7 @@ module Kumi
|
|
|
29
29
|
axes << root_name.to_sym
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
# Emit normal plan for the root node
|
|
33
|
-
node_axes = [] # The root axes are always [], e.g. array :x (the container :x opens [:x], but is not inside that dim)
|
|
32
|
+
# Emit normal plan for the root node # The root axes are always [], e.g. array :x (the container :x opens [:x], but is not inside that dim)
|
|
34
33
|
walk([root_name.to_s], node, steps, axes, steps, [])
|
|
35
34
|
|
|
36
35
|
# If the root array defines an index, emit a *synthetic* index plan now
|
|
@@ -31,13 +31,12 @@ module Kumi
|
|
|
31
31
|
validate_arity!(s, arg_types)
|
|
32
32
|
fn = @functions[s]
|
|
33
33
|
score = match_score(fn.params, arg_types)
|
|
34
|
-
if score > 0
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
end
|
|
34
|
+
return s if score > 0
|
|
35
|
+
|
|
36
|
+
# Type constraints failed
|
|
37
|
+
raise ResolutionError,
|
|
38
|
+
"#{alias_or_id}(#{format_types(arg_types)}) - type mismatch"
|
|
39
|
+
|
|
41
40
|
end
|
|
42
41
|
|
|
43
42
|
# Get all candidate overloads for this alias
|
|
@@ -50,13 +49,12 @@ module Kumi
|
|
|
50
49
|
validate_arity!(fn_id, arg_types)
|
|
51
50
|
fn = @functions[fn_id]
|
|
52
51
|
score = match_score(fn.params, arg_types)
|
|
53
|
-
if score > 0
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
end
|
|
52
|
+
return fn_id if score > 0
|
|
53
|
+
|
|
54
|
+
# Type constraints failed for the only overload
|
|
55
|
+
raise ResolutionError,
|
|
56
|
+
"#{alias_or_id}(#{format_types(arg_types)}) - type mismatch"
|
|
57
|
+
|
|
60
58
|
end
|
|
61
59
|
|
|
62
60
|
# Multiple overloads - find best match by type constraints (prefer exact matches)
|
|
@@ -68,9 +66,7 @@ module Kumi
|
|
|
68
66
|
|
|
69
67
|
best_match, score = candidates_with_scores.max_by { |_, s| s }
|
|
70
68
|
|
|
71
|
-
if score > 0
|
|
72
|
-
return best_match
|
|
73
|
-
end
|
|
69
|
+
return best_match if score > 0
|
|
74
70
|
|
|
75
71
|
# No match found - provide helpful error
|
|
76
72
|
raise ResolutionError,
|
|
@@ -134,6 +130,7 @@ module Kumi
|
|
|
134
130
|
# Check if it's a type category
|
|
135
131
|
if TypeCategories.category?(constraint)
|
|
136
132
|
return false unless type_obj.is_a?(Kumi::Core::Types::ScalarType)
|
|
133
|
+
|
|
137
134
|
return TypeCategories.includes?(constraint, type_obj.kind)
|
|
138
135
|
end
|
|
139
136
|
|
|
@@ -160,6 +157,7 @@ module Kumi
|
|
|
160
157
|
# Check if it's a type category
|
|
161
158
|
if TypeCategories.category?(param_dtype_str)
|
|
162
159
|
return false unless arg_type.is_a?(Kumi::Core::Types::ScalarType)
|
|
160
|
+
|
|
163
161
|
return TypeCategories.includes?(param_dtype_str, arg_type.kind)
|
|
164
162
|
end
|
|
165
163
|
|
|
@@ -189,8 +187,6 @@ module Kumi
|
|
|
189
187
|
"function #{fn_id} expects #{fn.params.size} arguments, got #{arg_types.size}"
|
|
190
188
|
end
|
|
191
189
|
|
|
192
|
-
private
|
|
193
|
-
|
|
194
190
|
def format_types(arg_types)
|
|
195
191
|
arg_types.map(&:to_s).join(", ")
|
|
196
192
|
end
|
|
@@ -9,11 +9,11 @@ module Kumi
|
|
|
9
9
|
class TypeCategories
|
|
10
10
|
# Define type categories as unions of scalar kinds
|
|
11
11
|
CATEGORIES = {
|
|
12
|
-
numeric: [
|
|
13
|
-
comparable: [
|
|
12
|
+
numeric: %i[integer float decimal],
|
|
13
|
+
comparable: %i[integer float decimal string],
|
|
14
14
|
boolean: [:boolean],
|
|
15
15
|
stringable: [:string],
|
|
16
|
-
orderable: [
|
|
16
|
+
orderable: %i[integer float decimal string]
|
|
17
17
|
}.freeze
|
|
18
18
|
|
|
19
19
|
def self.expand(dtype_constraint)
|
|
@@ -103,14 +103,12 @@ module Kumi
|
|
|
103
103
|
error
|
|
104
104
|
end
|
|
105
105
|
|
|
106
|
-
private
|
|
107
|
-
|
|
108
106
|
def self.format_overload_error(alias_or_id, arg_types, available_overloads)
|
|
109
107
|
arg_types_str = arg_types.map(&:inspect).join(", ")
|
|
110
108
|
available_str = available_overloads.map { |id| "'#{id}'" }.join(", ")
|
|
111
109
|
|
|
112
110
|
"no overload of '#{alias_or_id}' matches argument types (#{arg_types_str}). " \
|
|
113
|
-
|
|
111
|
+
"Available overloads: #{available_str}"
|
|
114
112
|
end
|
|
115
113
|
end
|
|
116
114
|
end
|
|
@@ -14,18 +14,16 @@ module Kumi
|
|
|
14
14
|
# Already a Type object, return as-is
|
|
15
15
|
type_input
|
|
16
16
|
when Symbol
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
end
|
|
17
|
+
raise ArgumentError, "Invalid type symbol: #{type_input}" unless Validator.valid_kind?(type_input)
|
|
18
|
+
|
|
19
|
+
Kumi::Core::Types.scalar(type_input)
|
|
20
|
+
|
|
22
21
|
when String
|
|
23
22
|
symbol_type = type_input.to_sym
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
end
|
|
23
|
+
raise ArgumentError, "Invalid type string: #{type_input}" unless Validator.valid_kind?(symbol_type)
|
|
24
|
+
|
|
25
|
+
Kumi::Core::Types.scalar(symbol_type)
|
|
26
|
+
|
|
29
27
|
when Hash
|
|
30
28
|
raise ArgumentError, "Hash-based types no longer supported, use Type objects instead"
|
|
31
29
|
when Class
|
|
@@ -36,6 +36,7 @@ module Kumi
|
|
|
36
36
|
|
|
37
37
|
def ==(other)
|
|
38
38
|
return false unless other.is_a?(ScalarType)
|
|
39
|
+
|
|
39
40
|
@kind == other.kind
|
|
40
41
|
end
|
|
41
42
|
|
|
@@ -61,11 +62,12 @@ module Kumi
|
|
|
61
62
|
end
|
|
62
63
|
|
|
63
64
|
def inspect
|
|
64
|
-
"#<ArrayType:#{
|
|
65
|
+
"#<ArrayType:#{self}>"
|
|
65
66
|
end
|
|
66
67
|
|
|
67
68
|
def ==(other)
|
|
68
69
|
return false unless other.is_a?(ArrayType)
|
|
70
|
+
|
|
69
71
|
@element_type == other.element_type
|
|
70
72
|
end
|
|
71
73
|
|
|
@@ -91,11 +93,12 @@ module Kumi
|
|
|
91
93
|
end
|
|
92
94
|
|
|
93
95
|
def inspect
|
|
94
|
-
"#<TupleType:#{
|
|
96
|
+
"#<TupleType:#{self}>"
|
|
95
97
|
end
|
|
96
98
|
|
|
97
99
|
def ==(other)
|
|
98
100
|
return false unless other.is_a?(TupleType)
|
|
101
|
+
|
|
99
102
|
@element_types == other.element_types
|
|
100
103
|
end
|
|
101
104
|
|
data/lib/kumi/core/types.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative
|
|
3
|
+
require_relative "types/value_objects"
|
|
4
4
|
|
|
5
5
|
module Kumi
|
|
6
6
|
module Core
|
|
@@ -44,9 +44,7 @@ module Kumi
|
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
def self.tuple(element_types)
|
|
47
|
-
unless element_types.is_a?(Array)
|
|
48
|
-
raise ArgumentError, "tuple expects array of Type objects, got #{element_types.class}"
|
|
49
|
-
end
|
|
47
|
+
raise ArgumentError, "tuple expects array of Type objects, got #{element_types.class}" unless element_types.is_a?(Array)
|
|
50
48
|
|
|
51
49
|
# Convert any non-Type elements to Type objects
|
|
52
50
|
converted = element_types.map do |t|
|
data/lib/kumi/dev/codegen.rb
CHANGED
|
@@ -110,7 +110,7 @@ module Kumi
|
|
|
110
110
|
schema, = Kumi::Frontends.load(path: schema_path)
|
|
111
111
|
result = Kumi::Analyzer.analyze!(schema)
|
|
112
112
|
|
|
113
|
-
|
|
113
|
+
result.state[:ruby_codegen_files]["codegen.rb"]
|
|
114
114
|
|
|
115
115
|
File.write("#{output_dir}/schema_ruby.rb", ruby_code)
|
|
116
116
|
puts " ✓ Ruby code generated"
|
|
@@ -34,11 +34,13 @@ module Kumi
|
|
|
34
34
|
|
|
35
35
|
def update_representation(repr)
|
|
36
36
|
output = generate_output(repr)
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
unless output
|
|
38
|
+
return GenerationResult.new(
|
|
39
|
+
schema_name: schema_name,
|
|
40
|
+
representation: repr.name,
|
|
41
|
+
status: :skipped
|
|
42
|
+
)
|
|
43
|
+
end
|
|
42
44
|
|
|
43
45
|
expected_file = File.join(expected_dir, repr.filename)
|
|
44
46
|
|
|
@@ -73,11 +75,13 @@ module Kumi
|
|
|
73
75
|
|
|
74
76
|
def generate_representation(repr, output_dir)
|
|
75
77
|
output = generate_output(repr)
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
unless output
|
|
79
|
+
return GenerationResult.new(
|
|
80
|
+
schema_name: schema_name,
|
|
81
|
+
representation: repr.name,
|
|
82
|
+
status: :skipped
|
|
83
|
+
)
|
|
84
|
+
end
|
|
81
85
|
|
|
82
86
|
output_file = File.join(output_dir, repr.filename)
|
|
83
87
|
File.write(output_file, output)
|
|
@@ -79,11 +79,11 @@ module Kumi
|
|
|
79
79
|
def report_diff(results_by_schema)
|
|
80
80
|
results_by_schema.each do |schema_name, results|
|
|
81
81
|
results.each do |result|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
82
|
+
next unless result.failed? && result.diff
|
|
83
|
+
|
|
84
|
+
puts "=== #{schema_name}/#{result.representation}.* ==="
|
|
85
|
+
puts result.diff
|
|
86
|
+
puts
|
|
87
87
|
end
|
|
88
88
|
end
|
|
89
89
|
end
|
|
@@ -17,9 +17,7 @@ module Kumi
|
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def generate(schema_path)
|
|
20
|
-
unless PrettyPrinter.respond_to?(generator_method)
|
|
21
|
-
raise "Unknown generator method: #{generator_method}"
|
|
22
|
-
end
|
|
20
|
+
raise "Unknown generator method: #{generator_method}" unless PrettyPrinter.respond_to?(generator_method)
|
|
23
21
|
|
|
24
22
|
PrettyPrinter.send(generator_method, schema_path)
|
|
25
23
|
end
|
|
@@ -16,25 +16,41 @@ module Kumi
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def update(name = nil)
|
|
19
|
-
names =
|
|
19
|
+
names = if name
|
|
20
|
+
name.is_a?(Array) ? name : [name]
|
|
21
|
+
else
|
|
22
|
+
schema_names
|
|
23
|
+
end
|
|
20
24
|
results = update_schemas(names)
|
|
21
25
|
Reporter.new.report_update(results)
|
|
22
26
|
end
|
|
23
27
|
|
|
24
28
|
def verify(name = nil)
|
|
25
|
-
names =
|
|
29
|
+
names = if name
|
|
30
|
+
name.is_a?(Array) ? name : [name]
|
|
31
|
+
else
|
|
32
|
+
schema_names
|
|
33
|
+
end
|
|
26
34
|
results = verify_schemas(names)
|
|
27
35
|
Reporter.new.report_verify(results)
|
|
28
36
|
end
|
|
29
37
|
|
|
30
38
|
def diff(name = nil)
|
|
31
|
-
names =
|
|
39
|
+
names = if name
|
|
40
|
+
name.is_a?(Array) ? name : [name]
|
|
41
|
+
else
|
|
42
|
+
schema_names
|
|
43
|
+
end
|
|
32
44
|
results = diff_schemas(names)
|
|
33
45
|
Reporter.new.report_diff(results)
|
|
34
46
|
end
|
|
35
47
|
|
|
36
48
|
def test(name = nil)
|
|
37
|
-
names =
|
|
49
|
+
names = if name
|
|
50
|
+
name.is_a?(Array) ? name : [name]
|
|
51
|
+
else
|
|
52
|
+
schema_names
|
|
53
|
+
end
|
|
38
54
|
|
|
39
55
|
update_schemas(names)
|
|
40
56
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "bigdecimal"
|
|
4
4
|
|
|
5
5
|
module Kumi
|
|
6
6
|
module Dev
|
|
@@ -32,8 +32,6 @@ module Kumi
|
|
|
32
32
|
compare_values(norm_actual, norm_expected, language: language)
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
-
private
|
|
36
|
-
|
|
37
35
|
def self.decimal_string?(str)
|
|
38
36
|
# Match decimal number strings like "10.50", "123", "-45.67"
|
|
39
37
|
str.match?(/\A-?\d+(\.\d+)?\z/)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require
|
|
1
|
+
require "json"
|
|
2
2
|
|
|
3
3
|
module Kumi
|
|
4
4
|
module DocGenerator
|
|
@@ -10,16 +10,16 @@ module Kumi
|
|
|
10
10
|
|
|
11
11
|
def format
|
|
12
12
|
enriched = @docs.each_with_object({}) do |(alias_name, entry), acc|
|
|
13
|
-
kernel_ids = extract_kernel_ids(entry[
|
|
13
|
+
kernel_ids = extract_kernel_ids(entry["kernels"])
|
|
14
14
|
acc[alias_name] = {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
15
|
+
"id" => entry["id"],
|
|
16
|
+
"kind" => entry["kind"],
|
|
17
|
+
"arity" => entry["arity"],
|
|
18
|
+
"params" => entry["params"],
|
|
19
|
+
"kernels" => kernel_ids,
|
|
20
|
+
"dtype" => entry["dtype"],
|
|
21
|
+
"aliases" => entry["aliases"],
|
|
22
|
+
"reduction_strategy" => entry["reduction_strategy"]
|
|
23
23
|
}
|
|
24
24
|
end
|
|
25
25
|
|
|
@@ -30,7 +30,7 @@ module Kumi
|
|
|
30
30
|
|
|
31
31
|
def extract_kernel_ids(kernels)
|
|
32
32
|
kernels.each_with_object({}) do |(target, kernel), acc|
|
|
33
|
-
acc[target] = kernel.is_a?(Hash) ? kernel[
|
|
33
|
+
acc[target] = kernel.is_a?(Hash) ? kernel["id"] : kernel
|
|
34
34
|
end
|
|
35
35
|
end
|
|
36
36
|
end
|