kumi 0.0.6 → 0.0.8
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/CLAUDE.md +34 -177
- data/README.md +41 -7
- data/docs/SYNTAX.md +2 -7
- data/docs/features/array-broadcasting.md +1 -1
- data/docs/schema_metadata/broadcasts.md +53 -0
- data/docs/schema_metadata/cascades.md +45 -0
- data/docs/schema_metadata/declarations.md +54 -0
- data/docs/schema_metadata/dependencies.md +57 -0
- data/docs/schema_metadata/evaluation_order.md +29 -0
- data/docs/schema_metadata/examples.md +95 -0
- data/docs/schema_metadata/inferred_types.md +46 -0
- data/docs/schema_metadata/inputs.md +86 -0
- data/docs/schema_metadata.md +108 -0
- data/examples/game_of_life.rb +1 -1
- data/examples/static_analysis_errors.rb +7 -7
- data/lib/kumi/analyzer.rb +20 -20
- data/lib/kumi/compiler.rb +44 -50
- data/lib/kumi/core/analyzer/analysis_state.rb +39 -0
- data/lib/kumi/core/analyzer/constant_evaluator.rb +59 -0
- data/lib/kumi/core/analyzer/passes/broadcast_detector.rb +248 -0
- data/lib/kumi/core/analyzer/passes/declaration_validator.rb +45 -0
- data/lib/kumi/core/analyzer/passes/dependency_resolver.rb +153 -0
- data/lib/kumi/core/analyzer/passes/input_collector.rb +139 -0
- data/lib/kumi/core/analyzer/passes/name_indexer.rb +26 -0
- data/lib/kumi/core/analyzer/passes/pass_base.rb +52 -0
- data/lib/kumi/core/analyzer/passes/semantic_constraint_validator.rb +111 -0
- data/lib/kumi/core/analyzer/passes/toposorter.rb +110 -0
- data/lib/kumi/core/analyzer/passes/type_checker.rb +162 -0
- data/lib/kumi/core/analyzer/passes/type_consistency_checker.rb +48 -0
- data/lib/kumi/core/analyzer/passes/type_inferencer.rb +236 -0
- data/lib/kumi/core/analyzer/passes/unsat_detector.rb +406 -0
- data/lib/kumi/core/analyzer/passes/visitor_pass.rb +44 -0
- data/lib/kumi/core/atom_unsat_solver.rb +396 -0
- data/lib/kumi/core/compiled_schema.rb +43 -0
- data/lib/kumi/core/constraint_relationship_solver.rb +641 -0
- data/lib/kumi/core/domain/enum_analyzer.rb +55 -0
- data/lib/kumi/core/domain/range_analyzer.rb +85 -0
- data/lib/kumi/core/domain/validator.rb +82 -0
- data/lib/kumi/core/domain/violation_formatter.rb +42 -0
- data/lib/kumi/core/error_reporter.rb +166 -0
- data/lib/kumi/core/error_reporting.rb +97 -0
- data/lib/kumi/core/errors.rb +120 -0
- data/lib/kumi/core/evaluation_wrapper.rb +40 -0
- data/lib/kumi/core/explain.rb +295 -0
- data/lib/kumi/core/export/deserializer.rb +41 -0
- data/lib/kumi/core/export/errors.rb +14 -0
- data/lib/kumi/core/export/node_builders.rb +142 -0
- data/lib/kumi/core/export/node_registry.rb +54 -0
- data/lib/kumi/core/export/node_serializers.rb +158 -0
- data/lib/kumi/core/export/serializer.rb +25 -0
- data/lib/kumi/core/export.rb +35 -0
- data/lib/kumi/core/function_registry/collection_functions.rb +202 -0
- data/lib/kumi/core/function_registry/comparison_functions.rb +33 -0
- data/lib/kumi/core/function_registry/conditional_functions.rb +38 -0
- data/lib/kumi/core/function_registry/function_builder.rb +95 -0
- data/lib/kumi/core/function_registry/logical_functions.rb +44 -0
- data/lib/kumi/core/function_registry/math_functions.rb +74 -0
- data/lib/kumi/core/function_registry/string_functions.rb +57 -0
- data/lib/kumi/core/function_registry/type_functions.rb +53 -0
- data/lib/kumi/{function_registry.rb → core/function_registry.rb} +28 -36
- data/lib/kumi/core/input/type_matcher.rb +97 -0
- data/lib/kumi/core/input/validator.rb +51 -0
- data/lib/kumi/core/input/violation_creator.rb +52 -0
- data/lib/kumi/core/json_schema/generator.rb +65 -0
- data/lib/kumi/core/json_schema/validator.rb +27 -0
- data/lib/kumi/core/json_schema.rb +16 -0
- data/lib/kumi/core/ruby_parser/build_context.rb +27 -0
- data/lib/kumi/core/ruby_parser/declaration_reference_proxy.rb +38 -0
- data/lib/kumi/core/ruby_parser/dsl.rb +14 -0
- data/lib/kumi/core/ruby_parser/dsl_cascade_builder.rb +138 -0
- data/lib/kumi/core/ruby_parser/expression_converter.rb +128 -0
- data/lib/kumi/core/ruby_parser/guard_rails.rb +45 -0
- data/lib/kumi/core/ruby_parser/input_builder.rb +127 -0
- data/lib/kumi/core/ruby_parser/input_field_proxy.rb +48 -0
- data/lib/kumi/core/ruby_parser/input_proxy.rb +31 -0
- data/lib/kumi/core/ruby_parser/nested_input.rb +17 -0
- data/lib/kumi/core/ruby_parser/parser.rb +71 -0
- data/lib/kumi/core/ruby_parser/schema_builder.rb +175 -0
- data/lib/kumi/core/ruby_parser/sugar.rb +263 -0
- data/lib/kumi/core/ruby_parser.rb +12 -0
- data/lib/kumi/core/schema_instance.rb +111 -0
- data/lib/kumi/core/types/builder.rb +23 -0
- data/lib/kumi/core/types/compatibility.rb +96 -0
- data/lib/kumi/core/types/formatter.rb +26 -0
- data/lib/kumi/core/types/inference.rb +42 -0
- data/lib/kumi/core/types/normalizer.rb +72 -0
- data/lib/kumi/core/types/validator.rb +37 -0
- data/lib/kumi/core/types.rb +66 -0
- data/lib/kumi/core/vectorization_metadata.rb +110 -0
- data/lib/kumi/errors.rb +1 -112
- data/lib/kumi/registry.rb +37 -0
- data/lib/kumi/schema.rb +13 -7
- data/lib/kumi/schema_metadata.rb +524 -0
- data/lib/kumi/syntax/array_expression.rb +6 -6
- data/lib/kumi/syntax/call_expression.rb +4 -4
- data/lib/kumi/syntax/cascade_expression.rb +4 -4
- data/lib/kumi/syntax/case_expression.rb +4 -4
- data/lib/kumi/syntax/declaration_reference.rb +4 -4
- data/lib/kumi/syntax/hash_expression.rb +4 -4
- data/lib/kumi/syntax/input_declaration.rb +5 -5
- data/lib/kumi/syntax/input_element_reference.rb +5 -5
- data/lib/kumi/syntax/input_reference.rb +5 -5
- data/lib/kumi/syntax/literal.rb +4 -4
- data/lib/kumi/syntax/node.rb +34 -34
- data/lib/kumi/syntax/root.rb +6 -6
- data/lib/kumi/syntax/trait_declaration.rb +4 -4
- data/lib/kumi/syntax/value_declaration.rb +4 -4
- data/lib/kumi/version.rb +1 -1
- data/lib/kumi.rb +14 -0
- data/migrate_to_core_iterative.rb +938 -0
- data/scripts/generate_function_docs.rb +9 -9
- metadata +85 -69
- data/lib/generators/trait_engine/templates/schema_spec.rb.erb +0 -27
- data/lib/kumi/analyzer/analysis_state.rb +0 -37
- data/lib/kumi/analyzer/constant_evaluator.rb +0 -57
- data/lib/kumi/analyzer/passes/broadcast_detector.rb +0 -251
- data/lib/kumi/analyzer/passes/declaration_validator.rb +0 -43
- data/lib/kumi/analyzer/passes/dependency_resolver.rb +0 -151
- data/lib/kumi/analyzer/passes/input_collector.rb +0 -137
- data/lib/kumi/analyzer/passes/name_indexer.rb +0 -24
- data/lib/kumi/analyzer/passes/pass_base.rb +0 -50
- data/lib/kumi/analyzer/passes/semantic_constraint_validator.rb +0 -110
- data/lib/kumi/analyzer/passes/toposorter.rb +0 -108
- data/lib/kumi/analyzer/passes/type_checker.rb +0 -162
- data/lib/kumi/analyzer/passes/type_consistency_checker.rb +0 -46
- data/lib/kumi/analyzer/passes/type_inferencer.rb +0 -232
- data/lib/kumi/analyzer/passes/unsat_detector.rb +0 -406
- data/lib/kumi/analyzer/passes/visitor_pass.rb +0 -42
- data/lib/kumi/atom_unsat_solver.rb +0 -394
- data/lib/kumi/compiled_schema.rb +0 -41
- data/lib/kumi/constraint_relationship_solver.rb +0 -638
- data/lib/kumi/domain/enum_analyzer.rb +0 -53
- data/lib/kumi/domain/range_analyzer.rb +0 -83
- data/lib/kumi/domain/validator.rb +0 -80
- data/lib/kumi/domain/violation_formatter.rb +0 -40
- data/lib/kumi/error_reporter.rb +0 -164
- data/lib/kumi/error_reporting.rb +0 -95
- data/lib/kumi/evaluation_wrapper.rb +0 -38
- data/lib/kumi/explain.rb +0 -281
- data/lib/kumi/export/deserializer.rb +0 -39
- data/lib/kumi/export/errors.rb +0 -12
- data/lib/kumi/export/node_builders.rb +0 -140
- data/lib/kumi/export/node_registry.rb +0 -52
- data/lib/kumi/export/node_serializers.rb +0 -156
- data/lib/kumi/export/serializer.rb +0 -23
- data/lib/kumi/export.rb +0 -33
- data/lib/kumi/function_registry/collection_functions.rb +0 -200
- data/lib/kumi/function_registry/comparison_functions.rb +0 -31
- data/lib/kumi/function_registry/conditional_functions.rb +0 -36
- data/lib/kumi/function_registry/function_builder.rb +0 -93
- data/lib/kumi/function_registry/logical_functions.rb +0 -42
- data/lib/kumi/function_registry/math_functions.rb +0 -72
- data/lib/kumi/function_registry/string_functions.rb +0 -54
- data/lib/kumi/function_registry/type_functions.rb +0 -51
- data/lib/kumi/input/type_matcher.rb +0 -95
- data/lib/kumi/input/validator.rb +0 -49
- data/lib/kumi/input/violation_creator.rb +0 -50
- data/lib/kumi/parser/build_context.rb +0 -25
- data/lib/kumi/parser/declaration_reference_proxy.rb +0 -36
- data/lib/kumi/parser/dsl.rb +0 -12
- data/lib/kumi/parser/dsl_cascade_builder.rb +0 -136
- data/lib/kumi/parser/expression_converter.rb +0 -126
- data/lib/kumi/parser/guard_rails.rb +0 -43
- data/lib/kumi/parser/input_builder.rb +0 -125
- data/lib/kumi/parser/input_field_proxy.rb +0 -46
- data/lib/kumi/parser/input_proxy.rb +0 -29
- data/lib/kumi/parser/nested_input.rb +0 -15
- data/lib/kumi/parser/parser.rb +0 -68
- data/lib/kumi/parser/schema_builder.rb +0 -173
- data/lib/kumi/parser/sugar.rb +0 -261
- data/lib/kumi/schema_instance.rb +0 -109
- data/lib/kumi/types/builder.rb +0 -21
- data/lib/kumi/types/compatibility.rb +0 -94
- data/lib/kumi/types/formatter.rb +0 -24
- data/lib/kumi/types/inference.rb +0 -40
- data/lib/kumi/types/normalizer.rb +0 -70
- data/lib/kumi/types/validator.rb +0 -35
- data/lib/kumi/types.rb +0 -64
- data/lib/kumi/vectorization_metadata.rb +0 -108
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Kumi
|
4
|
-
module Export
|
5
|
-
class Serializer
|
6
|
-
include NodeSerializers
|
7
|
-
|
8
|
-
def initialize(pretty: false, include_locations: false)
|
9
|
-
@pretty = pretty
|
10
|
-
@include_locations = include_locations
|
11
|
-
end
|
12
|
-
|
13
|
-
def serialize(syntax_root)
|
14
|
-
json_data = {
|
15
|
-
kumi_version: VERSION,
|
16
|
-
ast: serialize_root(syntax_root)
|
17
|
-
}
|
18
|
-
|
19
|
-
@pretty ? JSON.pretty_generate(json_data) : JSON.generate(json_data)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
data/lib/kumi/export.rb
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "json"
|
4
|
-
|
5
|
-
module Kumi
|
6
|
-
module Export
|
7
|
-
# Core interface - only depends on Syntax::Root
|
8
|
-
def self.to_json(syntax_root, **options)
|
9
|
-
Serializer.new(**options).serialize(syntax_root)
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.from_json(json_string, **options)
|
13
|
-
Deserializer.new(**options).deserialize(json_string)
|
14
|
-
end
|
15
|
-
|
16
|
-
# Convenience methods
|
17
|
-
def self.to_file(syntax_root, filepath, **options)
|
18
|
-
File.write(filepath, to_json(syntax_root, **options))
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.from_file(filepath, **options)
|
22
|
-
from_json(File.read(filepath), **options)
|
23
|
-
end
|
24
|
-
|
25
|
-
# Validation without import
|
26
|
-
def self.valid?(json_string)
|
27
|
-
from_json(json_string)
|
28
|
-
true
|
29
|
-
rescue StandardError
|
30
|
-
false
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
@@ -1,200 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Kumi
|
4
|
-
module FunctionRegistry
|
5
|
-
# Collection manipulation and query functions
|
6
|
-
module CollectionFunctions
|
7
|
-
def self.definitions
|
8
|
-
{
|
9
|
-
# Collection queries (these are reducers - they reduce arrays to scalars)
|
10
|
-
empty?: FunctionBuilder.collection_unary(:empty?, "Check if collection is empty", :empty?, reducer: true),
|
11
|
-
size: FunctionBuilder.collection_unary(:size, "Get collection size", :size, return_type: :integer, reducer: true),
|
12
|
-
length: FunctionBuilder.collection_unary(:length, "Get collection length", :length, return_type: :integer, reducer: true),
|
13
|
-
|
14
|
-
# Element access
|
15
|
-
first: FunctionBuilder::Entry.new(
|
16
|
-
fn: lambda(&:first),
|
17
|
-
arity: 1,
|
18
|
-
param_types: [Kumi::Types.array(:any)],
|
19
|
-
return_type: :any,
|
20
|
-
description: "Get first element of collection",
|
21
|
-
reducer: true
|
22
|
-
),
|
23
|
-
|
24
|
-
last: FunctionBuilder::Entry.new(
|
25
|
-
fn: lambda(&:last),
|
26
|
-
arity: 1,
|
27
|
-
param_types: [Kumi::Types.array(:any)],
|
28
|
-
return_type: :any,
|
29
|
-
description: "Get last element of collection",
|
30
|
-
reducer: true
|
31
|
-
),
|
32
|
-
|
33
|
-
# Mathematical operations on collections
|
34
|
-
sum: FunctionBuilder::Entry.new(
|
35
|
-
fn: lambda(&:sum),
|
36
|
-
arity: 1,
|
37
|
-
param_types: [Kumi::Types.array(:float)],
|
38
|
-
return_type: :float,
|
39
|
-
description: "Sum all numeric elements in collection",
|
40
|
-
reducer: true
|
41
|
-
),
|
42
|
-
|
43
|
-
min: FunctionBuilder::Entry.new(
|
44
|
-
fn: lambda(&:min),
|
45
|
-
arity: 1,
|
46
|
-
param_types: [Kumi::Types.array(:float)],
|
47
|
-
return_type: :float,
|
48
|
-
description: "Find minimum value in numeric collection",
|
49
|
-
reducer: true
|
50
|
-
),
|
51
|
-
|
52
|
-
max: FunctionBuilder::Entry.new(
|
53
|
-
fn: lambda(&:max),
|
54
|
-
arity: 1,
|
55
|
-
param_types: [Kumi::Types.array(:float)],
|
56
|
-
return_type: :float,
|
57
|
-
description: "Find maximum value in numeric collection",
|
58
|
-
reducer: true
|
59
|
-
),
|
60
|
-
|
61
|
-
# Collection operations
|
62
|
-
include?: FunctionBuilder::Entry.new(
|
63
|
-
fn: ->(collection, element) { collection.include?(element) },
|
64
|
-
arity: 2,
|
65
|
-
param_types: [Kumi::Types.array(:any), :any],
|
66
|
-
return_type: :boolean,
|
67
|
-
description: "Check if collection includes element"
|
68
|
-
),
|
69
|
-
|
70
|
-
reverse: FunctionBuilder::Entry.new(
|
71
|
-
fn: lambda(&:reverse),
|
72
|
-
arity: 1,
|
73
|
-
param_types: [Kumi::Types.array(:any)],
|
74
|
-
return_type: Kumi::Types.array(:any),
|
75
|
-
description: "Reverse collection order"
|
76
|
-
),
|
77
|
-
|
78
|
-
sort: FunctionBuilder::Entry.new(
|
79
|
-
fn: lambda(&:sort),
|
80
|
-
arity: 1,
|
81
|
-
param_types: [Kumi::Types.array(:any)],
|
82
|
-
return_type: Kumi::Types.array(:any),
|
83
|
-
description: "Sort collection"
|
84
|
-
),
|
85
|
-
|
86
|
-
unique: FunctionBuilder::Entry.new(
|
87
|
-
fn: lambda(&:uniq),
|
88
|
-
arity: 1,
|
89
|
-
param_types: [Kumi::Types.array(:any)],
|
90
|
-
return_type: Kumi::Types.array(:any),
|
91
|
-
description: "Remove duplicate elements from collection"
|
92
|
-
),
|
93
|
-
|
94
|
-
# Array transformation functions
|
95
|
-
flatten: FunctionBuilder::Entry.new(
|
96
|
-
fn: lambda(&:flatten),
|
97
|
-
arity: 1,
|
98
|
-
param_types: [Kumi::Types.array(:any)],
|
99
|
-
return_type: Kumi::Types.array(:any),
|
100
|
-
description: "Flatten nested arrays into a single array"
|
101
|
-
),
|
102
|
-
|
103
|
-
# Mathematical transformation functions
|
104
|
-
map_multiply: FunctionBuilder::Entry.new(
|
105
|
-
fn: ->(collection, factor) { collection.map { |x| x * factor } },
|
106
|
-
arity: 2,
|
107
|
-
param_types: [Kumi::Types.array(:float), :float],
|
108
|
-
return_type: Kumi::Types.array(:float),
|
109
|
-
description: "Multiply each element by factor"
|
110
|
-
),
|
111
|
-
|
112
|
-
map_add: FunctionBuilder::Entry.new(
|
113
|
-
fn: ->(collection, value) { collection.map { |x| x + value } },
|
114
|
-
arity: 2,
|
115
|
-
param_types: [Kumi::Types.array(:float), :float],
|
116
|
-
return_type: Kumi::Types.array(:float),
|
117
|
-
description: "Add value to each element"
|
118
|
-
),
|
119
|
-
|
120
|
-
# Conditional transformation functions
|
121
|
-
map_conditional: FunctionBuilder::Entry.new(
|
122
|
-
fn: lambda { |collection, condition_value, true_value, false_value|
|
123
|
-
collection.map { |x| x == condition_value ? true_value : false_value }
|
124
|
-
},
|
125
|
-
arity: 4,
|
126
|
-
param_types: %i[array any any any],
|
127
|
-
return_type: :array,
|
128
|
-
description: "Transform elements based on condition: if element == condition_value then true_value else false_value"
|
129
|
-
),
|
130
|
-
|
131
|
-
# Range/index functions for grid operations
|
132
|
-
build_array: FunctionBuilder::Entry.new(
|
133
|
-
fn: lambda { |size, &generator|
|
134
|
-
(0...size).map { |i| generator ? generator.call(i) : i }
|
135
|
-
},
|
136
|
-
arity: 1,
|
137
|
-
param_types: [:integer],
|
138
|
-
return_type: Kumi::Types.array(:any),
|
139
|
-
description: "Build array of given size with index values"
|
140
|
-
),
|
141
|
-
|
142
|
-
range: FunctionBuilder::Entry.new(
|
143
|
-
fn: ->(start, finish) { (start...finish).to_a },
|
144
|
-
arity: 2,
|
145
|
-
param_types: %i[integer integer],
|
146
|
-
return_type: Kumi::Types.array(:integer),
|
147
|
-
description: "Generate range of integers from start to finish (exclusive)"
|
148
|
-
),
|
149
|
-
|
150
|
-
# Array slicing and grouping for rendering
|
151
|
-
each_slice: FunctionBuilder::Entry.new(
|
152
|
-
fn: ->(array, size) { array.each_slice(size).to_a },
|
153
|
-
arity: 2,
|
154
|
-
param_types: %i[array integer],
|
155
|
-
return_type: Kumi::Types.array(:array),
|
156
|
-
description: "Group array elements into subarrays of given size"
|
157
|
-
),
|
158
|
-
|
159
|
-
join: FunctionBuilder::Entry.new(
|
160
|
-
fn: lambda { |array, separator = ""|
|
161
|
-
array.map(&:to_s).join(separator.to_s)
|
162
|
-
},
|
163
|
-
arity: 2,
|
164
|
-
param_types: %i[array string],
|
165
|
-
return_type: :string,
|
166
|
-
description: "Join array elements into string with separator"
|
167
|
-
),
|
168
|
-
|
169
|
-
# Transform each subarray to string and join the results
|
170
|
-
map_join_rows: FunctionBuilder::Entry.new(
|
171
|
-
fn: lambda { |array_of_arrays, row_separator = "", column_separator = "\n"|
|
172
|
-
array_of_arrays.map { |row| row.join(row_separator.to_s) }.join(column_separator.to_s)
|
173
|
-
},
|
174
|
-
arity: 3,
|
175
|
-
param_types: [Kumi::Types.array(:array), :string, :string],
|
176
|
-
return_type: :string,
|
177
|
-
description: "Join 2D array into string with row and column separators"
|
178
|
-
),
|
179
|
-
|
180
|
-
# Higher-order collection functions (limited to common patterns)
|
181
|
-
map_with_index: FunctionBuilder::Entry.new(
|
182
|
-
fn: ->(collection) { collection.map.with_index.to_a },
|
183
|
-
arity: 1,
|
184
|
-
param_types: [Kumi::Types.array(:any)],
|
185
|
-
return_type: Kumi::Types.array(:any),
|
186
|
-
description: "Map collection elements to [element, index] pairs"
|
187
|
-
),
|
188
|
-
|
189
|
-
indices: FunctionBuilder::Entry.new(
|
190
|
-
fn: ->(collection) { (0...collection.size).to_a },
|
191
|
-
arity: 1,
|
192
|
-
param_types: [Kumi::Types.array(:any)],
|
193
|
-
return_type: Kumi::Types.array(:integer),
|
194
|
-
description: "Generate array of indices for the collection"
|
195
|
-
)
|
196
|
-
}
|
197
|
-
end
|
198
|
-
end
|
199
|
-
end
|
200
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Kumi
|
4
|
-
module FunctionRegistry
|
5
|
-
# Comparison and equality functions
|
6
|
-
module ComparisonFunctions
|
7
|
-
def self.definitions
|
8
|
-
{
|
9
|
-
# Equality operators
|
10
|
-
:== => FunctionBuilder.equality(:==, "Equality comparison", :==),
|
11
|
-
:!= => FunctionBuilder.equality(:!=, "Inequality comparison", :!=),
|
12
|
-
|
13
|
-
# Comparison operators
|
14
|
-
:> => FunctionBuilder.comparison(:>, "Greater than comparison", :>),
|
15
|
-
:< => FunctionBuilder.comparison(:<, "Less than comparison", :<),
|
16
|
-
:>= => FunctionBuilder.comparison(:>=, "Greater than or equal comparison", :>=),
|
17
|
-
:<= => FunctionBuilder.comparison(:<=, "Less than or equal comparison", :<=),
|
18
|
-
|
19
|
-
# Range comparison
|
20
|
-
:between? => FunctionBuilder::Entry.new(
|
21
|
-
fn: ->(value, min, max) { value.between?(min, max) },
|
22
|
-
arity: 3,
|
23
|
-
param_types: %i[float float float],
|
24
|
-
return_type: :boolean,
|
25
|
-
description: "Check if value is between min and max"
|
26
|
-
)
|
27
|
-
}
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
@@ -1,36 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Kumi
|
4
|
-
module FunctionRegistry
|
5
|
-
# Conditional and control flow functions
|
6
|
-
module ConditionalFunctions
|
7
|
-
def self.definitions
|
8
|
-
{
|
9
|
-
conditional: FunctionBuilder::Entry.new(
|
10
|
-
fn: ->(condition, true_value, false_value) { condition ? true_value : false_value },
|
11
|
-
arity: 3,
|
12
|
-
param_types: %i[boolean any any],
|
13
|
-
return_type: :any,
|
14
|
-
description: "Ternary conditional operator"
|
15
|
-
),
|
16
|
-
|
17
|
-
if: FunctionBuilder::Entry.new(
|
18
|
-
fn: ->(condition, true_value, false_value = nil) { condition ? true_value : false_value },
|
19
|
-
arity: -1, # Variable arity (2 or 3)
|
20
|
-
param_types: %i[boolean any any],
|
21
|
-
return_type: :any,
|
22
|
-
description: "If-then-else conditional"
|
23
|
-
),
|
24
|
-
|
25
|
-
coalesce: FunctionBuilder::Entry.new(
|
26
|
-
fn: ->(*values) { values.find { |v| !v.nil? } },
|
27
|
-
arity: -1, # Variable arity
|
28
|
-
param_types: [:any],
|
29
|
-
return_type: :any,
|
30
|
-
description: "Return first non-nil value"
|
31
|
-
)
|
32
|
-
}
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
@@ -1,93 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Kumi
|
4
|
-
module FunctionRegistry
|
5
|
-
# Utility class to reduce repetition in function definitions
|
6
|
-
class FunctionBuilder
|
7
|
-
Entry = Struct.new(:fn, :arity, :param_types, :return_type, :description, :inverse, :reducer, keyword_init: true)
|
8
|
-
|
9
|
-
def self.comparison(_name, description, operation)
|
10
|
-
Entry.new(
|
11
|
-
fn: ->(a, b) { a.public_send(operation, b) },
|
12
|
-
arity: 2,
|
13
|
-
param_types: %i[float float],
|
14
|
-
return_type: :boolean,
|
15
|
-
description: description
|
16
|
-
)
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.equality(_name, description, operation)
|
20
|
-
Entry.new(
|
21
|
-
fn: ->(a, b) { a.public_send(operation, b) },
|
22
|
-
arity: 2,
|
23
|
-
param_types: %i[any any],
|
24
|
-
return_type: :boolean,
|
25
|
-
description: description
|
26
|
-
)
|
27
|
-
end
|
28
|
-
|
29
|
-
def self.math_binary(_name, description, operation, return_type: :float)
|
30
|
-
Entry.new(
|
31
|
-
fn: lambda { |a, b|
|
32
|
-
a.public_send(operation, b)
|
33
|
-
},
|
34
|
-
arity: 2,
|
35
|
-
param_types: %i[float float],
|
36
|
-
return_type: return_type,
|
37
|
-
description: description
|
38
|
-
)
|
39
|
-
end
|
40
|
-
|
41
|
-
def self.math_unary(_name, description, operation, return_type: :float)
|
42
|
-
Entry.new(
|
43
|
-
fn: proc(&operation),
|
44
|
-
arity: 1,
|
45
|
-
param_types: [:float],
|
46
|
-
return_type: return_type,
|
47
|
-
description: description
|
48
|
-
)
|
49
|
-
end
|
50
|
-
|
51
|
-
def self.string_unary(_name, description, operation)
|
52
|
-
Entry.new(
|
53
|
-
fn: ->(str) { str.to_s.public_send(operation) },
|
54
|
-
arity: 1,
|
55
|
-
param_types: [:string],
|
56
|
-
return_type: :string,
|
57
|
-
description: description
|
58
|
-
)
|
59
|
-
end
|
60
|
-
|
61
|
-
def self.string_binary(_name, description, operation, return_type: :string)
|
62
|
-
Entry.new(
|
63
|
-
fn: ->(str, arg) { str.to_s.public_send(operation, arg.to_s) },
|
64
|
-
arity: 2,
|
65
|
-
param_types: %i[string string],
|
66
|
-
return_type: return_type,
|
67
|
-
description: description
|
68
|
-
)
|
69
|
-
end
|
70
|
-
|
71
|
-
def self.logical_variadic(_name, description, operation)
|
72
|
-
Entry.new(
|
73
|
-
fn: ->(conditions) { conditions.public_send(operation) },
|
74
|
-
arity: -1,
|
75
|
-
param_types: [:boolean],
|
76
|
-
return_type: :boolean,
|
77
|
-
description: description
|
78
|
-
)
|
79
|
-
end
|
80
|
-
|
81
|
-
def self.collection_unary(_name, description, operation, return_type: :boolean, reducer: false)
|
82
|
-
Entry.new(
|
83
|
-
fn: proc(&operation),
|
84
|
-
arity: 1,
|
85
|
-
param_types: [Kumi::Types.array(:any)],
|
86
|
-
return_type: return_type,
|
87
|
-
description: description,
|
88
|
-
reducer: reducer
|
89
|
-
)
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Kumi
|
4
|
-
module FunctionRegistry
|
5
|
-
# Logical operations and boolean functions
|
6
|
-
module LogicalFunctions
|
7
|
-
def self.definitions
|
8
|
-
{
|
9
|
-
# Basic logical operations
|
10
|
-
and: FunctionBuilder::Entry.new(
|
11
|
-
fn: ->(*conditions) { conditions.all? },
|
12
|
-
arity: -1,
|
13
|
-
param_types: [:boolean],
|
14
|
-
return_type: :boolean,
|
15
|
-
description: "Logical AND of multiple conditions"
|
16
|
-
),
|
17
|
-
|
18
|
-
or: FunctionBuilder::Entry.new(
|
19
|
-
fn: ->(*conditions) { conditions.any? },
|
20
|
-
arity: -1,
|
21
|
-
param_types: [:boolean],
|
22
|
-
return_type: :boolean,
|
23
|
-
description: "Logical OR of multiple conditions"
|
24
|
-
),
|
25
|
-
|
26
|
-
not: FunctionBuilder::Entry.new(
|
27
|
-
fn: lambda(&:!),
|
28
|
-
arity: 1,
|
29
|
-
param_types: [:boolean],
|
30
|
-
return_type: :boolean,
|
31
|
-
description: "Logical NOT"
|
32
|
-
),
|
33
|
-
|
34
|
-
# Collection logical operations
|
35
|
-
all?: FunctionBuilder.collection_unary(:all?, "Check if all elements in collection are truthy", :all?),
|
36
|
-
any?: FunctionBuilder.collection_unary(:any?, "Check if any element in collection is truthy", :any?),
|
37
|
-
none?: FunctionBuilder.collection_unary(:none?, "Check if no elements in collection are truthy", :none?)
|
38
|
-
}
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
@@ -1,72 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Kumi
|
4
|
-
module FunctionRegistry
|
5
|
-
# Mathematical operations
|
6
|
-
module MathFunctions
|
7
|
-
def self.definitions
|
8
|
-
{
|
9
|
-
# Basic arithmetic
|
10
|
-
add: FunctionBuilder.math_binary(:add, "Add two numbers", :+),
|
11
|
-
subtract: FunctionBuilder.math_binary(:subtract, "Subtract second number from first", :-),
|
12
|
-
multiply: FunctionBuilder.math_binary(:multiply, "Multiply two numbers", :*),
|
13
|
-
divide: FunctionBuilder.math_binary(:divide, "Divide first number by second", :/),
|
14
|
-
modulo: FunctionBuilder.math_binary(:modulo, "Modulo operation", :%),
|
15
|
-
power: FunctionBuilder.math_binary(:power, "Raise first number to power of second", :**),
|
16
|
-
|
17
|
-
# Unary operations
|
18
|
-
abs: FunctionBuilder.math_unary(:abs, "Absolute value", :abs),
|
19
|
-
floor: FunctionBuilder.math_unary(:floor, "Floor of number", :floor, return_type: :integer),
|
20
|
-
ceil: FunctionBuilder.math_unary(:ceil, "Ceiling of number", :ceil, return_type: :integer),
|
21
|
-
|
22
|
-
# Special operations
|
23
|
-
round: FunctionBuilder::Entry.new(
|
24
|
-
fn: ->(a, precision = 0) { a.round(precision) },
|
25
|
-
arity: -1,
|
26
|
-
param_types: [:float],
|
27
|
-
return_type: :float,
|
28
|
-
description: "Round number to specified precision"
|
29
|
-
),
|
30
|
-
|
31
|
-
clamp: FunctionBuilder::Entry.new(
|
32
|
-
fn: ->(value, min, max) { value.clamp(min, max) },
|
33
|
-
arity: 3,
|
34
|
-
param_types: %i[float float float],
|
35
|
-
return_type: :float,
|
36
|
-
description: "Clamp value between min and max"
|
37
|
-
),
|
38
|
-
piecewise_sum: FunctionBuilder::Entry.new(
|
39
|
-
# Tiered / piece‑wise accumulator
|
40
|
-
fn: lambda do |value, breaks, rates|
|
41
|
-
raise ArgumentError, "breaks & rates size mismatch" unless breaks.size == rates.size
|
42
|
-
|
43
|
-
acc = 0.0
|
44
|
-
previous = 0.0
|
45
|
-
marginal = rates.last
|
46
|
-
|
47
|
-
breaks.zip(rates).each do |upper, rate|
|
48
|
-
if value <= upper
|
49
|
-
marginal = rate
|
50
|
-
acc += (value - previous) * rate
|
51
|
-
break
|
52
|
-
else
|
53
|
-
acc += (upper - previous) * rate
|
54
|
-
previous = upper
|
55
|
-
end
|
56
|
-
end
|
57
|
-
[acc, marginal] # => [sum, marginal_rate]
|
58
|
-
end,
|
59
|
-
arity: 3,
|
60
|
-
param_types: [
|
61
|
-
:float,
|
62
|
-
Kumi::Types.array(:float), # breaks
|
63
|
-
Kumi::Types.array(:float) # rates
|
64
|
-
],
|
65
|
-
return_type: Kumi::Types.array(:float), # 2‑element [sum, marginal]
|
66
|
-
description: "Accumulate over tiered ranges; returns [sum, marginal_rate]"
|
67
|
-
)
|
68
|
-
}
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
@@ -1,54 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Kumi
|
4
|
-
module FunctionRegistry
|
5
|
-
# String manipulation functions
|
6
|
-
module StringFunctions
|
7
|
-
def self.definitions
|
8
|
-
{
|
9
|
-
# String transformations
|
10
|
-
upcase: FunctionBuilder.string_unary(:upcase, "Convert string to uppercase", :upcase),
|
11
|
-
downcase: FunctionBuilder.string_unary(:downcase, "Convert string to lowercase", :downcase),
|
12
|
-
capitalize: FunctionBuilder.string_unary(:capitalize, "Capitalize first letter of string", :capitalize),
|
13
|
-
strip: FunctionBuilder.string_unary(:strip, "Remove leading and trailing whitespace", :strip),
|
14
|
-
|
15
|
-
# String queries
|
16
|
-
string_length: FunctionBuilder::Entry.new(
|
17
|
-
fn: ->(str) { str.to_s.length },
|
18
|
-
arity: 1,
|
19
|
-
param_types: [:string],
|
20
|
-
return_type: :integer,
|
21
|
-
description: "Get string length"
|
22
|
-
),
|
23
|
-
|
24
|
-
# Keep the original length for backward compatibility, but it will be overridden
|
25
|
-
length: FunctionBuilder::Entry.new(
|
26
|
-
fn: ->(str) { str.to_s.length },
|
27
|
-
arity: 1,
|
28
|
-
param_types: [:string],
|
29
|
-
return_type: :integer,
|
30
|
-
description: "Get string length"
|
31
|
-
),
|
32
|
-
|
33
|
-
# String inclusion using different name to avoid conflict with collection include?
|
34
|
-
string_include?: FunctionBuilder.string_binary(:include?, "Check if string contains substring", :include?, return_type: :boolean),
|
35
|
-
includes?: FunctionBuilder.string_binary(:include?, "Check if string contains substring", :include?, return_type: :boolean),
|
36
|
-
contains?: FunctionBuilder.string_binary(:include?, "Check if string contains substring", :include?, return_type: :boolean),
|
37
|
-
|
38
|
-
start_with?: FunctionBuilder.string_binary(:start_with?, "Check if string starts with prefix", :start_with?,
|
39
|
-
return_type: :boolean),
|
40
|
-
end_with?: FunctionBuilder.string_binary(:end_with?, "Check if string ends with suffix", :end_with?, return_type: :boolean),
|
41
|
-
|
42
|
-
# String building
|
43
|
-
concat: FunctionBuilder::Entry.new(
|
44
|
-
fn: ->(*strings) { strings.join },
|
45
|
-
arity: -1,
|
46
|
-
param_types: [:string],
|
47
|
-
return_type: :string,
|
48
|
-
description: "Concatenate multiple strings"
|
49
|
-
)
|
50
|
-
}
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
@@ -1,51 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Kumi
|
4
|
-
module FunctionRegistry
|
5
|
-
# Type checking and conversion functions
|
6
|
-
module TypeFunctions
|
7
|
-
def self.definitions
|
8
|
-
{
|
9
|
-
fetch: FunctionBuilder::Entry.new(
|
10
|
-
fn: ->(hash, key, default = nil) { hash.fetch(key, default) },
|
11
|
-
arity: -1, # Variable arity (2 or 3)
|
12
|
-
param_types: [Kumi::Types.hash(:any, :any), :any, :any],
|
13
|
-
return_type: :any,
|
14
|
-
description: "Fetch value from hash with optional default"
|
15
|
-
),
|
16
|
-
|
17
|
-
has_key?: FunctionBuilder::Entry.new(
|
18
|
-
fn: ->(hash, key) { hash.key?(key) },
|
19
|
-
arity: 2,
|
20
|
-
param_types: [Kumi::Types.hash(:any, :any), :any],
|
21
|
-
return_type: :boolean,
|
22
|
-
description: "Check if hash has the given key"
|
23
|
-
),
|
24
|
-
|
25
|
-
keys: FunctionBuilder::Entry.new(
|
26
|
-
fn: lambda(&:keys),
|
27
|
-
arity: 1,
|
28
|
-
param_types: [Kumi::Types.hash(:any, :any)],
|
29
|
-
return_type: Kumi::Types.array(:any),
|
30
|
-
description: "Get all keys from hash"
|
31
|
-
),
|
32
|
-
|
33
|
-
values: FunctionBuilder::Entry.new(
|
34
|
-
fn: lambda(&:values),
|
35
|
-
arity: 1,
|
36
|
-
param_types: [Kumi::Types.hash(:any, :any)],
|
37
|
-
return_type: Kumi::Types.array(:any),
|
38
|
-
description: "Get all values from hash"
|
39
|
-
),
|
40
|
-
at: FunctionBuilder::Entry.new(
|
41
|
-
fn: ->(array, index) { array[index] },
|
42
|
-
arity: 2,
|
43
|
-
param_types: [Kumi::Types.array(:any), :integer],
|
44
|
-
return_type: :any,
|
45
|
-
description: "Get element at index from array"
|
46
|
-
)
|
47
|
-
}
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|