kumi 0.0.7 → 0.0.9
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 +1 -1
- data/README.md +21 -5
- data/docs/AST.md +7 -0
- data/docs/features/README.md +7 -0
- data/docs/features/s-expression-printer.md +77 -0
- data/examples/game_of_life.rb +1 -1
- data/examples/static_analysis_errors.rb +7 -7
- data/lib/kumi/analyzer.rb +15 -15
- data/lib/kumi/compiler.rb +6 -6
- 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 +5 -5
- data/lib/kumi/schema_metadata.rb +3 -3
- data/lib/kumi/support/s_expression_printer.rb +161 -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/migrate_to_core_iterative.rb +938 -0
- data/scripts/generate_function_docs.rb +9 -9
- metadata +77 -72
- 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 -246
- 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 -109
- data/lib/kumi/analyzer/passes/toposorter.rb +0 -108
- data/lib/kumi/analyzer/passes/type_checker.rb +0 -160
- 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 -404
- 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 -293
- 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/json_schema/generator.rb +0 -63
- data/lib/kumi/json_schema/validator.rb +0 -25
- data/lib/kumi/json_schema.rb +0 -14
- data/lib/kumi/ruby_parser/build_context.rb +0 -25
- data/lib/kumi/ruby_parser/declaration_reference_proxy.rb +0 -36
- data/lib/kumi/ruby_parser/dsl.rb +0 -12
- data/lib/kumi/ruby_parser/dsl_cascade_builder.rb +0 -136
- data/lib/kumi/ruby_parser/expression_converter.rb +0 -126
- data/lib/kumi/ruby_parser/guard_rails.rb +0 -43
- data/lib/kumi/ruby_parser/input_builder.rb +0 -125
- data/lib/kumi/ruby_parser/input_field_proxy.rb +0 -46
- data/lib/kumi/ruby_parser/input_proxy.rb +0 -29
- data/lib/kumi/ruby_parser/nested_input.rb +0 -15
- data/lib/kumi/ruby_parser/parser.rb +0 -69
- data/lib/kumi/ruby_parser/schema_builder.rb +0 -173
- data/lib/kumi/ruby_parser/sugar.rb +0 -261
- data/lib/kumi/ruby_parser.rb +0 -10
- 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
@@ -0,0 +1,161 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kumi
|
4
|
+
module Support
|
5
|
+
class SExpressionPrinter
|
6
|
+
def initialize(indent: 0)
|
7
|
+
@indent = indent
|
8
|
+
end
|
9
|
+
|
10
|
+
def visit(node)
|
11
|
+
return node.inspect unless node.respond_to?(:class)
|
12
|
+
|
13
|
+
case node
|
14
|
+
when nil then "nil"
|
15
|
+
when Array then visit_array(node)
|
16
|
+
when Kumi::Syntax::Root then visit_root(node)
|
17
|
+
when Kumi::Syntax::ValueDeclaration then visit_value_declaration(node)
|
18
|
+
when Kumi::Syntax::TraitDeclaration then visit_trait_declaration(node)
|
19
|
+
when Kumi::Syntax::InputDeclaration then visit_input_declaration(node)
|
20
|
+
when Kumi::Syntax::CallExpression then visit_call_expression(node)
|
21
|
+
when Kumi::Syntax::ArrayExpression then visit_array_expression(node)
|
22
|
+
when Kumi::Syntax::CascadeExpression then visit_cascade_expression(node)
|
23
|
+
when Kumi::Syntax::CaseExpression then visit_case_expression(node)
|
24
|
+
when Kumi::Syntax::InputReference then visit_input_reference(node)
|
25
|
+
when Kumi::Syntax::InputElementReference then visit_input_element_reference(node)
|
26
|
+
when Kumi::Syntax::DeclarationReference then visit_declaration_reference(node)
|
27
|
+
when Kumi::Syntax::Literal then visit_literal(node)
|
28
|
+
when Kumi::Syntax::HashExpression then visit_hash_expression(node)
|
29
|
+
else visit_generic(node)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.print(node, indent: 0)
|
34
|
+
new(indent: indent).visit(node)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def visit_array(node)
|
40
|
+
return "[]" if node.empty?
|
41
|
+
|
42
|
+
elements = node.map { |child| child_printer.visit(child) }
|
43
|
+
"[\n#{indent_str(2)}#{elements.join("\n#{indent_str(2)}")}\n#{indent_str}]"
|
44
|
+
end
|
45
|
+
|
46
|
+
def visit_root(node)
|
47
|
+
fields = %i[inputs attributes traits].map do |field|
|
48
|
+
value = node.public_send(field)
|
49
|
+
"#{field}: #{child_printer.visit(value)}"
|
50
|
+
end.join("\n#{indent_str(2)}")
|
51
|
+
|
52
|
+
"(Root\n#{indent_str(2)}#{fields}\n#{indent_str})"
|
53
|
+
end
|
54
|
+
|
55
|
+
def visit_value_declaration(node)
|
56
|
+
"(ValueDeclaration :#{node.name}\n#{child_indent}#{child_printer.visit(node.expression)}\n#{indent_str})"
|
57
|
+
end
|
58
|
+
|
59
|
+
def visit_trait_declaration(node)
|
60
|
+
"(TraitDeclaration :#{node.name}\n#{child_indent}#{child_printer.visit(node.expression)}\n#{indent_str})"
|
61
|
+
end
|
62
|
+
|
63
|
+
def visit_input_declaration(node)
|
64
|
+
fields = [":#{node.name}"]
|
65
|
+
fields << ":#{node.type}" if node.respond_to?(:type) && node.type
|
66
|
+
fields << "domain: #{node.domain.inspect}" if node.respond_to?(:domain) && node.domain
|
67
|
+
|
68
|
+
if node.respond_to?(:children) && !node.children.empty?
|
69
|
+
children_str = child_printer.visit(node.children)
|
70
|
+
"(InputDeclaration #{fields.join(' ')}\n#{child_indent}#{children_str}\n#{indent_str})"
|
71
|
+
else
|
72
|
+
"(InputDeclaration #{fields.join(' ')})"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def visit_call_expression(node)
|
77
|
+
return "(CallExpression :#{node.fn_name})" if node.args.empty?
|
78
|
+
|
79
|
+
args = node.args.map { |arg| child_printer.visit(arg) }
|
80
|
+
"(CallExpression :#{node.fn_name}\n#{indent_str(2)}#{args.join("\n#{indent_str(2)}")}\n#{indent_str})"
|
81
|
+
end
|
82
|
+
|
83
|
+
def visit_array_expression(node)
|
84
|
+
return "(ArrayExpression)" if node.elements.empty?
|
85
|
+
|
86
|
+
elements = node.elements.map { |elem| child_printer.visit(elem) }
|
87
|
+
"(ArrayExpression\n#{indent_str(2)}#{elements.join("\n#{indent_str(2)}")}\n#{indent_str})"
|
88
|
+
end
|
89
|
+
|
90
|
+
def visit_cascade_expression(node)
|
91
|
+
cases = node.cases.map do |case_expr|
|
92
|
+
"(#{visit(case_expr.condition)} #{visit(case_expr.result)})"
|
93
|
+
end.join("\n#{indent_str(2)}")
|
94
|
+
|
95
|
+
"(CascadeExpression\n#{indent_str(2)}#{cases}\n#{indent_str})"
|
96
|
+
end
|
97
|
+
|
98
|
+
def visit_case_expression(node)
|
99
|
+
"(CaseExpression #{visit(node.condition)} #{visit(node.result)})"
|
100
|
+
end
|
101
|
+
|
102
|
+
def visit_input_reference(node)
|
103
|
+
"(InputReference :#{node.name})"
|
104
|
+
end
|
105
|
+
|
106
|
+
def visit_input_element_reference(node)
|
107
|
+
"(InputElementReference #{node.path.map(&:to_s).join('.')})"
|
108
|
+
end
|
109
|
+
|
110
|
+
def visit_declaration_reference(node)
|
111
|
+
"(DeclarationReference :#{node.name})"
|
112
|
+
end
|
113
|
+
|
114
|
+
def visit_literal(node)
|
115
|
+
"(Literal #{node.value.inspect})"
|
116
|
+
end
|
117
|
+
|
118
|
+
def visit_hash_expression(node)
|
119
|
+
return "(HashExpression)" if node.pairs.empty?
|
120
|
+
|
121
|
+
pairs = node.pairs.map do |pair|
|
122
|
+
"(#{visit(pair.key)} #{visit(pair.value)})"
|
123
|
+
end.join("\n#{indent_str(2)}")
|
124
|
+
|
125
|
+
"(HashExpression\n#{indent_str(2)}#{pairs}\n#{indent_str})"
|
126
|
+
end
|
127
|
+
|
128
|
+
def visit_generic(node)
|
129
|
+
class_name = node.class.name&.split('::')&.last || node.class.to_s
|
130
|
+
|
131
|
+
if node.respond_to?(:children) && !node.children.empty?
|
132
|
+
children = node.children.map { |child| child_printer.visit(child) }
|
133
|
+
"(#{class_name}\n#{indent_str(2)}#{children.join("\n#{indent_str(2)}")}\n#{indent_str})"
|
134
|
+
elsif node.respond_to?(:members)
|
135
|
+
fields = node.members.reject { |m| m == :loc }.map do |member|
|
136
|
+
value = node[member]
|
137
|
+
"#{member}: #{child_printer.visit(value)}"
|
138
|
+
end
|
139
|
+
|
140
|
+
return "(#{class_name})" if fields.empty?
|
141
|
+
|
142
|
+
"(#{class_name}\n#{indent_str(2)}#{fields.join("\n#{indent_str(2)}")}\n#{indent_str})"
|
143
|
+
else
|
144
|
+
"(#{class_name} #{node.inspect})"
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def child_printer
|
149
|
+
@child_printer ||= self.class.new(indent: @indent + 2)
|
150
|
+
end
|
151
|
+
|
152
|
+
def indent_str(extra = 0)
|
153
|
+
' ' * (@indent + extra)
|
154
|
+
end
|
155
|
+
|
156
|
+
def child_indent
|
157
|
+
indent_str(2)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
@@ -2,14 +2,14 @@
|
|
2
2
|
|
3
3
|
module Kumi
|
4
4
|
module Syntax
|
5
|
-
|
6
|
-
|
5
|
+
ArrayExpression = Struct.new(:elements) do
|
6
|
+
include Node
|
7
7
|
|
8
|
-
|
8
|
+
def children = elements
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
def size
|
11
|
+
elements.size
|
12
|
+
end
|
12
13
|
end
|
13
|
-
end
|
14
14
|
end
|
15
15
|
end
|
@@ -2,10 +2,10 @@
|
|
2
2
|
|
3
3
|
module Kumi
|
4
4
|
module Syntax
|
5
|
-
|
6
|
-
|
5
|
+
CaseExpression = Struct.new(:condition, :result) do
|
6
|
+
include Node
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
def children = [condition, result]
|
9
|
+
end
|
10
10
|
end
|
11
11
|
end
|
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
module Kumi
|
4
4
|
module Syntax
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
# For field metadata declarations inside input blocks
|
6
|
+
InputDeclaration = Struct.new(:name, :domain, :type, :children) do
|
7
|
+
include Node
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
def children = self[:children] || []
|
10
|
+
end
|
11
11
|
end
|
12
12
|
end
|
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
module Kumi
|
4
4
|
module Syntax
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
# For field usage/reference in expressions (input.field_name)
|
6
|
+
InputElementReference = Struct.new(:path) do
|
7
|
+
include Node
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
def children = []
|
10
|
+
end
|
11
11
|
end
|
12
12
|
end
|
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
module Kumi
|
4
4
|
module Syntax
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
# For field usage/reference in expressions (input.field_name)
|
6
|
+
InputReference = Struct.new(:name) do
|
7
|
+
include Node
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
def children = []
|
10
|
+
end
|
11
11
|
end
|
12
12
|
end
|
data/lib/kumi/syntax/literal.rb
CHANGED
data/lib/kumi/syntax/node.rb
CHANGED
@@ -2,45 +2,45 @@
|
|
2
2
|
|
3
3
|
module Kumi
|
4
4
|
module Syntax
|
5
|
-
|
6
|
-
|
5
|
+
# A struct to hold standardized source location information.
|
6
|
+
Location = Struct.new(:file, :line, :column, keyword_init: true)
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
# Base module included by all AST nodes to provide a standard
|
9
|
+
# interface for accessing source location information..
|
10
|
+
module Node
|
11
|
+
attr_accessor :loc
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
13
|
+
def initialize(*args, loc: nil, **kwargs)
|
14
|
+
@loc = loc
|
15
|
+
super(*args, **kwargs)
|
16
|
+
freeze
|
17
|
+
end
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
19
|
+
def ==(other)
|
20
|
+
other.is_a?(self.class) &&
|
21
|
+
# for Struct-based nodes
|
22
|
+
(if respond_to?(:members)
|
23
|
+
members.all? { |m| self[m] == other[m] }
|
24
|
+
else
|
25
|
+
instance_variables.reject { |iv| iv == :@loc }
|
26
|
+
.all? do |iv|
|
27
|
+
instance_variable_get(iv) ==
|
28
|
+
other.instance_variable_get(iv)
|
29
|
+
end
|
29
30
|
end
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
alias eql? ==
|
31
|
+
)
|
32
|
+
end
|
33
|
+
alias eql? ==
|
34
34
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
35
|
+
def hash
|
36
|
+
values = if respond_to?(:members)
|
37
|
+
members.map { |m| self[m] }
|
38
|
+
else
|
39
|
+
instance_variables.reject { |iv| iv == :@loc }
|
40
|
+
.map { |iv| instance_variable_get(iv) }
|
41
|
+
end
|
42
|
+
[self.class, *values].hash
|
43
|
+
end
|
43
44
|
end
|
44
|
-
end
|
45
45
|
end
|
46
46
|
end
|
data/lib/kumi/syntax/root.rb
CHANGED
@@ -2,12 +2,12 @@
|
|
2
2
|
|
3
3
|
module Kumi
|
4
4
|
module Syntax
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
# Represents the root of the Abstract Syntax Tree.
|
6
|
+
# It holds all the top-level declarations parsed from the source.
|
7
|
+
Root = Struct.new(:inputs, :attributes, :traits) do
|
8
|
+
include Node
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
def children = [inputs, attributes, traits]
|
11
|
+
end
|
12
12
|
end
|
13
13
|
end
|
@@ -2,10 +2,10 @@
|
|
2
2
|
|
3
3
|
module Kumi
|
4
4
|
module Syntax
|
5
|
-
|
6
|
-
|
5
|
+
TraitDeclaration = Struct.new(:name, :expression) do
|
6
|
+
include Node
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
def children = [expression]
|
9
|
+
end
|
10
10
|
end
|
11
11
|
end
|
@@ -2,10 +2,10 @@
|
|
2
2
|
|
3
3
|
module Kumi
|
4
4
|
module Syntax
|
5
|
-
|
6
|
-
|
5
|
+
ValueDeclaration = Struct.new(:name, :expression) do
|
6
|
+
include Node
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
def children = [expression]
|
9
|
+
end
|
10
10
|
end
|
11
11
|
end
|
data/lib/kumi/version.rb
CHANGED