Class: Lisp::Format::Directives::BeginConditional

Inherits:
Directive show all
Defined in:
lib/carat/lisp-format.rb

Overview

Represents the ~[ (Begin conditional expression) directive. This is useful to choose among a set of directives depending on arguments and numbers.

Instance Attribute Summary

Attributes inherited from Directive

#pos

Instance Method Summary collapse

Methods inherited from Directive

#join

Constructor Details

#initialize(*args) ⇒ BeginConditional

Set up some variables and basically pass on to super.



1491
1492
1493
1494
1495
1496
1497
1498
1499
# File 'lib/carat/lisp-format.rb', line 1491

def initialize(*args)
  super(*args)
  if (colon_mod? or at_mod?) and @params.size > 0
    param_error 0, 'no parameters allowed together with' +
      ': and/or @ modifiers'
  end
  @clauses = []
  @default = -1
end

Instance Method Details

#connect(directives) ⇒ Object

Connect a set of directives to this conditional directive. A SyntaxError is raised if multiple clauses have been marked as ‘default’, or if too many clauses have been specified for a given set of modifiers.



1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
# File 'lib/carat/lisp-format.rb', line 1553

def connect(directives)
  @clauses = []
  clause = []
  directives.each do |d|
    if d.is_a? ClauseSeparator
      @clauses << clause
      clause = []
      if d.colon_mod?
        if @default == -1
          @default = @clauses.size
        else
          raise SyntaxError.new(d.pos),
            'default clause has already been set'
        end
      end
    elsif d.is_a? EndConditional
      @clauses << clause
      break
    else
      clause << d
    end
  end
  must = 'two' if colon_mod? and @clauses.size != 2
  must = 'one' if at_mod? and @clauses.size != 1
  unless must.nil?
    raise SyntaxError.new(@pos), "must specify exactly #{must} clauses"
  end
end

#execute(state) ⇒ Object

Process one of the given clauses, depending on the numeric value of the given argument, or a specified parameter. The full form is

~n[clause0~;clause1~:;clause2~]

or

~:[clause0~;clause1~]

or

~@[clause0~]

with the following interpretations

n (nil)

if given, this value will be used to choose a clause instead of reading an arguments value. This is only useful if n is in fact the arguments left parameter (#). An error is raised if this argument does not #respond_to? :to_int,

:

instead of choosing a clause by number, the argument is tested as a boolean value, and if false, then first clause is executed, else the second one is,

@

instead of choosing a clause by number, the argument is tested as a boolean value, and if true, the single clause is executed.



1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
# File 'lib/carat/lisp-format.rb', line 1521

def execute(state)
  test = state.next_arg if colon_mod? or at_mod?
  if colon_mod?
    c = test ? 1 : 0
  elsif at_mod?
    if test
      state.push_back_arg
      c = 0
    end
  else
    n = param(0, state, nil)
    if n.nil?
      arg = state.next_arg
      if arg.respond_to? :to_int
        n = arg.to_int
      else
        arg_error 'argument is not an integral value'
      end
    end
    if n < @clauses.size
      c = n
    elsif @default != -1
      c = @default
    end
  end
  Format.execute_directives(state, @clauses[c]) unless c.nil?
end