class Maxima::Command

Constants

GSUB_REGEX
MATCH_REGEX
OPTIONS

Attributes

assigned_variables[RW]
commands[RW]
dependencies[RW]
options[RW]

Public Class Methods

convert_output_to_variables(output_variable_map, raw_output) click to toggle source
# File lib/maxima/command.rb, line 129
def self.convert_output_to_variables(output_variable_map, raw_output)
  {}.tap do |result|
    output_variable_map.each_with_index do |(variable, klazz), index|
      output = raw_output[index]
      output = klazz.respond_to?(:parse) ? klazz.parse(output) : klazz.new(output)
      result[variable] = output
    end
  end
end
eol_maxima_characters(input) click to toggle source
# File lib/maxima/command.rb, line 162
def self.eol_maxima_characters(input)
  input.count("$") + input.count(";")
end
expand_output_variable_map(output_variable_map) click to toggle source
# File lib/maxima/command.rb, line 139
def self.expand_output_variable_map(output_variable_map)
  {}.tap do |expanded_output_variable_map|
    add_key = -> (k,v) {
      if expanded_output_variable_map.has_key?(k)
        throw :key_used_twice
      else
        expanded_output_variable_map[k] = v
      end
    }

    output_variable_map.each do |output_key, parsed_into_class|
      case output_key
      when Array
        output_key.each do |output_subkey|
          add_key.call(output_subkey, parsed_into_class)
        end
      else
        add_key.call(output_key, parsed_into_class)
      end
    end
  end
end
extract_outputs(output, eol_maxima_characters) click to toggle source
# File lib/maxima/command.rb, line 122
def self.extract_outputs(output, eol_maxima_characters)
  MATCH_REGEX.call(eol_maxima_characters)
    .match(output)[0]
    .gsub(GSUB_REGEX, "")
    .split("$")
end
new() click to toggle source
# File lib/maxima/command.rb, line 5
def initialize
  @dependencies = []
  @assigned_variables = Set.new()
  @commands = []
  @options = {}
end
output(*v) { |c| ... } click to toggle source
# File lib/maxima/command.rb, line 12
def self.output(*v)
  Command.new()
    .with_options(
      use_fast_arrays: true,
      float: true
    ).tap do |c|
    yield c
  end.output_variables(*v)
end

Public Instance Methods

<<(expression) click to toggle source
# File lib/maxima/command.rb, line 60
def <<(expression)
  @commands << expression
end
_apply_unary_operations(expression, *unary_operations, **unary_operations_options) click to toggle source
# File lib/maxima/command.rb, line 64
def _apply_unary_operations(expression, *unary_operations, **unary_operations_options)
  unary_operations = Set.new(unary_operations)
  unary_operations_options.map do |option, is_enabled|
    unary_operations.add(option) if is_enabled
  end

  [
    unary_operations.map { |unary_operation| "#{unary_operation}(" },
    Maxima.mformat(expression),
    ")" * unary_operations.count
  ].join()
end
_let(variable, expression) click to toggle source
# File lib/maxima/command.rb, line 56
def _let(variable, expression)
  @commands << "#{variable} : #{expression}"
end
add_variable(variable) click to toggle source
# File lib/maxima/command.rb, line 26
def add_variable(variable)
  case variable
  when Enumerable
    @assigned_variables.merge(variable)
  else
    @assigned_variables.add(variable)
  end
end
dependencies_input() click to toggle source
# File lib/maxima/command.rb, line 177
def dependencies_input
  @dependencies.map { |s| "load(#{s})" }
end
let(variable_or_variables, expression, *unary_operations, **unary_operations_options) click to toggle source
# File lib/maxima/command.rb, line 35
def let(variable_or_variables, expression, *unary_operations, **unary_operations_options)
  add_variable(variable_or_variables)


  variable   = Maxima.mformat(variable_or_variables)
  expression = _apply_unary_operations(expression, *unary_operations, **unary_operations_options)

  _let(variable, expression)
end
let_simplified(variable, expression, *unary_operations, **unary_operations_options) click to toggle source
# File lib/maxima/command.rb, line 45
def let_simplified(variable, expression, *unary_operations, **unary_operations_options)
  unary_operations_options[:expand] = true

  let(
    variable,
    expression,
    *unary_operations,
    **unary_operations_options
  )
end
options_commands() click to toggle source
# File lib/maxima/command.rb, line 83
def options_commands()
  [].tap do |commands|
    @options.each do |option, configuration|
      # warn that option is not applicable
      next unless OPTIONS[option]
      commands << OPTIONS[option].call(configuration)
    end
  end
end
output_variables(output_variable_map) click to toggle source
# File lib/maxima/command.rb, line 166
def output_variables(output_variable_map)
  output_variable_map = Command.expand_output_variable_map(output_variable_map)

  input, output = run_shell(output_variable_map.keys).values_at(:input, :output)

  eol_maxima_characters = Command.eol_maxima_characters(input)
  extracted_outputs = Command.extract_outputs(output, eol_maxima_characters)

  Command.convert_output_to_variables(output_variable_map, extracted_outputs)
end
run_shell(extract_variables = nil, debug: ENV["DEBUG_RB_MAXIMA"]) click to toggle source
# File lib/maxima/command.rb, line 93
def run_shell(extract_variables = nil, debug: ENV["DEBUG_RB_MAXIMA"])
  inputs = [*dependencies_input, *options_commands(), *@commands]

  inputs << "grind(#{extract_variables.join(', ')})" if extract_variables
  input = inputs.join("$\n") + "$\n"

  output = with_debug(debug, input) do
    Helper.spawn_silenced_shell_process("maxima --quiet --run-string '#{input}'")
  end

  {
    input:  input,
    output: output
  }
end
with_debug(debug, input) { || ... } click to toggle source
# File lib/maxima/command.rb, line 109
def with_debug(debug, input)
  return yield unless debug

  uuid = SecureRandom.uuid[0..6]
  puts input.lines.map { |s| "#{uuid}>>>\t#{s}" }.join

  yield.tap do |output|
    puts output.lines.map { |s| "#{uuid}<<<\t#{s}" }.join
  end
end
with_options(options) click to toggle source
# File lib/maxima/command.rb, line 22
def with_options(options)
  self.tap { @options.merge!(options) }
end