Class: Kumi::Core::RubyParser::SchemaBuilder

Inherits:
Object
  • Object
show all
Includes:
ErrorReporting, GuardRails, Syntax
Defined in:
lib/kumi/core/ruby_parser/schema_builder.rb

Constant Summary collapse

DSL_METHODS =
%i[value trait input ref literal fn select shift roll cross outer index import codegen
to_decimal to_integer to_float to_string].freeze

Constants included from GuardRails

GuardRails::RESERVED

Instance Method Summary collapse

Methods included from ErrorReporting

#inferred_location, #raise_localized_error, #raise_syntax_error, #raise_type_error, #report_enhanced_error, #report_error, #report_semantic_error, #report_syntax_error, #report_type_error

Methods included from GuardRails

#guard_rails_caller_location, included

Constructor Details

#initialize(context) ⇒ SchemaBuilder

Returns a new instance of SchemaBuilder.



14
15
16
17
# File 'lib/kumi/core/ruby_parser/schema_builder.rb', line 14

def initialize(context)
  @context = context
  @converter = ExpressionConverter.new(context)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *args) ⇒ Object



151
152
153
154
155
156
157
158
159
# File 'lib/kumi/core/ruby_parser/schema_builder.rb', line 151

def method_missing(method_name, *args, &)
  if args.empty? && !block_given?
    update_location
    # Create proxy for declaration references (traits/values)
    DeclarationReferenceProxy.new(method_name, @context)
  else
    super
  end
end

Instance Method Details

#codegen(**kwargs) ⇒ Object



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/kumi/core/ruby_parser/schema_builder.rb', line 77

def codegen(**kwargs)
  update_location
  unknown = kwargs.keys - %i[streaming]
  unless unknown.empty?
    raise_syntax_error(
      "unknown codegen option(s): #{unknown.map(&:inspect).join(', ')}",
      location: @context.current_location
    )
  end

  if kwargs.key?(:streaming) && ![true, false].include?(kwargs[:streaming])
    raise_syntax_error("codegen streaming: must be true or false", location: @context.current_location)
  end

  @context.merge_root_hint(:codegen, kwargs)
end

#cross(*args, **kwargs) ⇒ Object



124
125
126
127
# File 'lib/kumi/core/ruby_parser/schema_builder.rb', line 124

def cross(*args, **kwargs)
  args_expr = args.map { ensure_syntax(_1) }
  Kumi::Syntax::CallExpression.new(:cross, args_expr, kwargs, loc: @context.current_location)
end

#fn(fn_name, *args, **kwargs) ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
# File 'lib/kumi/core/ruby_parser/schema_builder.rb', line 94

def fn(fn_name, *args, **kwargs)
  update_location

  if args.empty? && !kwargs.empty? && @context.imported_names.include?(fn_name)
    mapping = build_import_mapping(kwargs)
    Kumi::Syntax::ImportCall.new(fn_name, mapping, loc: @context.current_location)
  else
    expr_args = args.map { ensure_syntax(_1) }
    Kumi::Syntax::CallExpression.new(fn_name, expr_args, kwargs, loc: @context.current_location)
  end
end

#import(*names, from:) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/kumi/core/ruby_parser/schema_builder.rb', line 62

def import(*names, from:)
  update_location

  unless from.is_a?(Module) || from.is_a?(Class)
    raise_syntax_error(
      "import 'from:' must reference a module or class",
      location: @context.current_location
    )
  end

  import_decl = Kumi::Syntax::ImportDeclaration.new(names, from, loc: @context.current_location)
  @context.imports << import_decl
  @context.imported_names.merge(names)
end

#index(name) ⇒ Object



129
130
131
132
# File 'lib/kumi/core/ruby_parser/schema_builder.rb', line 129

def index(name)
  update_location
  Kumi::Syntax::CallExpression.new(:index, [ensure_syntax(name)], {}, loc: @context.current_location)
end

#inputObject



41
42
43
44
45
46
47
48
49
50
# File 'lib/kumi/core/ruby_parser/schema_builder.rb', line 41

def input(&)
  return InputProxy.new(@context) unless block_given?

  raise_syntax_error("input block already defined", location: @context.current_location) if @context.input_block_defined?
  @context.mark_input_block_defined!

  update_location
  input_builder = InputBuilder.new(@context)
  input_builder.instance_eval(&)
end

#let(name = nil, expr = nil, &blk) ⇒ Object



19
20
21
22
23
24
25
# File 'lib/kumi/core/ruby_parser/schema_builder.rb', line 19

def let(name = nil, expr = nil, &blk)
  update_location
  validate_value_args(name, expr, blk)

  expression = blk ? build_cascade(&blk) : ensure_syntax(expr)
  @context.values << Kumi::Syntax::ValueDeclaration.new(name, expression, hints: { inline: true }, loc: @context.current_location)
end

#literal(value) ⇒ Object



57
58
59
60
# File 'lib/kumi/core/ruby_parser/schema_builder.rb', line 57

def literal(value)
  update_location
  Kumi::Syntax::Literal.new(value, loc: @context.current_location)
end

#outer(*args, **kwargs) ⇒ Object

‘outer(v)` re-exposes a value from a DIFFERENT array as a fresh inner axis, so it can be paired all-pairs with the surrounding (outer) axis. Where `cross` self-joins one array (A x A’), ‘outer` joins two distinct arrays (A x B): `pixel_x - outer(light_x)` builds the (pixels x lights) grid, then `fn(:sum, …)` reduces the light axis back to per-pixel.



146
147
148
149
# File 'lib/kumi/core/ruby_parser/schema_builder.rb', line 146

def outer(*args, **kwargs)
  args_expr = args.map { ensure_syntax(_1) }
  Kumi::Syntax::CallExpression.new(:outer, args_expr, kwargs, loc: @context.current_location)
end

#ref(name) ⇒ Object



52
53
54
55
# File 'lib/kumi/core/ruby_parser/schema_builder.rb', line 52

def ref(name)
  update_location
  Kumi::Syntax::DeclarationReference.new(name, loc: @context.current_location)
end

#respond_to_missing?(_method_name, _include_private = false) ⇒ Boolean

Returns:

  • (Boolean)


161
162
163
# File 'lib/kumi/core/ruby_parser/schema_builder.rb', line 161

def respond_to_missing?(_method_name, _include_private = false)
  true
end

#roll(*args, **kwargs) ⇒ Object



114
115
116
117
# File 'lib/kumi/core/ruby_parser/schema_builder.rb', line 114

def roll(*args, **kwargs)
  args_expr = args.map { ensure_syntax(_1) }
  Kumi::Syntax::CallExpression.new(:roll, args_expr, kwargs, loc: @context.current_location)
end

#select(condition, value_when_true, value_when_false) ⇒ Object



106
107
108
109
110
111
112
# File 'lib/kumi/core/ruby_parser/schema_builder.rb', line 106

def select(condition, value_when_true, value_when_false)
  update_location
  condition_expr = ensure_syntax(condition)
  true_expr = ensure_syntax(value_when_true)
  false_expr = ensure_syntax(value_when_false)
  Kumi::Syntax::CallExpression.new(:__select__, [condition_expr, true_expr, false_expr], loc: @context.current_location)
end

#shift(*args, **kwargs) ⇒ Object



119
120
121
122
# File 'lib/kumi/core/ruby_parser/schema_builder.rb', line 119

def shift(*args, **kwargs)
  args_expr = args.map { ensure_syntax(_1) }
  Kumi::Syntax::CallExpression.new(:shift, args_expr, kwargs, loc: @context.current_location)
end

#trait(*args, **kwargs) ⇒ Object



35
36
37
38
39
# File 'lib/kumi/core/ruby_parser/schema_builder.rb', line 35

def trait(*args, **kwargs)
  update_location
  raise_syntax_error("keyword trait syntax not supported", location: @context.current_location) unless kwargs.empty?
  build_positional_trait(args)
end

#value(name = nil, expr = nil, &blk) ⇒ Object



27
28
29
30
31
32
33
# File 'lib/kumi/core/ruby_parser/schema_builder.rb', line 27

def value(name = nil, expr = nil, &blk)
  update_location
  validate_value_args(name, expr, blk)

  expression = blk ? build_cascade(&blk) : ensure_syntax(expr)
  @context.values << Kumi::Syntax::ValueDeclaration.new(name, expression, loc: @context.current_location)
end