1
0

Method type distinction: numeric/quantity

This commit is contained in:
cryptogopher 2020-01-18 20:06:16 +01:00
parent 6ce02ba05a
commit 8e362ade79

View File

@ -8,8 +8,7 @@ class DemoBuilder < Ripper::SexpBuilder
super(*args)
@disallowed = Hash.new { |h,k| h[k] = Set.new }
@identifiers = Set.new
@paramed_formula = nil
@arguments = []
@parts = []
end
def errors
@ -22,7 +21,9 @@ class DemoBuilder < Ripper::SexpBuilder
private
METHODS = ['abs', 'nil?']
DECIMAL_METHODS = ['abs', 'nil?']
QUANTITY_METHODS = ['all', 'lastBefore']
METHODS = DECIMAL_METHODS + QUANTITY_METHODS
events = private_instance_methods(false).grep(/\Aon_/) {$'.to_sym}
(PARSER_EVENTS - events).each do |event|
@ -35,8 +36,8 @@ class DemoBuilder < Ripper::SexpBuilder
end
def on_program(stmts)
@paramed_formula = join_stmts(stmts)
[@identifiers, @paramed_formula, @arguments]
@parts << {type: :indexed, content: join_stmts(stmts)}
[@identifiers, @parts]
end
def on_string_content
@ -73,10 +74,8 @@ class DemoBuilder < Ripper::SexpBuilder
when :bt_quantity
"params['#{token}']"
when :bt_expression
# FIXME: 'token' expression has to be evaluated in block with _index and
# result stored in @arguments
@arguments << token
"args['#{@arguments.length - 1}']"
@parts << {type: :indexed, content: token}
"parts[#{@parts.length - 1}]"
else
raise NotImplementedError
end
@ -100,30 +99,53 @@ class DemoBuilder < Ripper::SexpBuilder
end
def on_call(left, dot, right)
[
:bt_method_call,
case left[0]
when :bt_quantity
"params['#{left[1]}']"
when :bt_method_call
"#{left[1]}"
else
raise NotImplementedError
end <<
dot.to_s <<
method, mtype =
case right[0]
when :bt_ident
@disallowed[:method] << right[1] unless METHODS.include?(right[1])
right[1]
case
when DECIMAL_METHODS.include?(right[1])
[right[1], :numeric_method]
when QUANTITY_METHODS.include?(right[1])
[right[1], :quantity_method]
else
@disallowed[:method] << right[1]
[right[1], :unknown_method]
end
else
raise NotImplementedError
end
case left[0]
when :bt_quantity
if mtype == :quantity_method
part_index = @parts.length
@parts << {type: :unindexed, content: "params['#{left[1]}']#{dot.to_s}#{method}"}
[:bt_quantity_method_call, "parts[#{part_index}]", part_index]
else
[:bt_numeric_method_call, "params['#{left[1]}'][_index]#{dot.to_s}#{method}"]
end
when :bt_quantity_method_call
if mtype == :quantity_method
@parts[left[2]][:content] << "#{dot.to_s}#{method}"
left
else
[:bt_numeric_method_call, "#{left[1]}#{dot.to_s}#{method}"]
end
when :bt_numeric_method_call
if mtype == :quantity_method
# TODO: add error reporting
raise NotImplementedError
else
[:bt_numeric_method_call, "#{left[1]}#{dot.to_s}#{method}"]
end
else
raise NotImplementedError
end
]
end
def on_fcall(token)
@disallowed[:method] = token[1]
[:bt_method, token[1]]
[:bt_numeric_method_call, token[1]]
end
def on_vcall(token)
@ -137,10 +159,15 @@ class DemoBuilder < Ripper::SexpBuilder
end
def on_method_add_arg(method, paren)
[
:bt_method_call,
"#{method[1]}#{paren}"
]
case method[0]
when :bt_quantity_method_call
@parts[method[2]][:content] << paren
method
when :bt_numeric_method_call
[:bt_numeric_method_call, "#{method[1]}#{paren}"]
else
raise NotImplementedError
end
end
def on_binary(left, op, right)
@ -206,4 +233,5 @@ pp Ripper.sexp_raw(src)
parser = DemoBuilder.new(src)
pp parser.parse
pp parser.errors
puts "(params['Weight'][_index]/params['Height'].all(args['0']).lastBefore(params['TakenAt'])^2)+2*params['Other'][_index]*params['Other'][_index]*params['other'][_index]"
puts src
puts " (params['Weight'][_index]/params['Height'].all(args['0']).lastBefore(params['TakenAt'])^2)+2*params['Other'][_index]*params['Other'][_index]*params['other'][_index]"