Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Control Flow

ccalc supports multi-line control flow blocks in both the interactive REPL and in script/pipe mode. All block constructs use end as the closing keyword.

REPL multi-line input

The REPL detects unclosed blocks and buffers incoming lines, displaying a continuation prompt >> until the block is complete. Press Ctrl+C to cancel an incomplete block.

[ 0 ]:   for k = 1:3
  >>   fprintf('%d\n', k)
  >> end
1
2
3

if / elseif / else

score = 73;
if score >= 90
  grade = 'A';
elseif score >= 80
  grade = 'B';
elseif score >= 70
  grade = 'C';
elseif score >= 60
  grade = 'D';
else
  grade = 'F';
end
fprintf('score %d -> grade %s\n', score, grade)

A condition is truthy when:

Value typeTruthy when
Scalarnon-zero and not NaN
Matrixall elements non-zero and not NaN
Str/StringObjnon-empty
Voidnever

for

for var = range_expr
  % body
end

The range expression is evaluated once. Iteration is column-by-column:

  • Row vector → each element as a scalar
  • M×N matrix → each column as an M×1 column vector
% Simple range
for k = 1:5
  fprintf('%d\n', k)
end

% Step range
for k = 10:-2:0
  fprintf('%d ', k)   % 10 8 6 4 2 0
end

while

while cond
  % body
end
x = 1.0;
while abs(x ^ 2 - 2) > 1e-12
  x = (x + 2 / x) / 2;
end
fprintf('sqrt(2) ≈ %.15f\n', x)

break and continue

break exits the innermost loop immediately. continue skips to the next iteration.

for n = 1:20
  if mod(n, 2) == 0
    continue        % skip even numbers
  end
  if n > 9
    break           % stop after first odd > 9
  end
  fprintf('%d ', n)   % 1 3 5 7 9
end

Compound assignment operators

OperatorEquivalent to
x += ex = x + e
x -= ex = x - e
x *= ex = x * e
x /= ex = x / e
x++x = x + 1
x--x = x - 1
++xx = x + 1
--xx = x - 1

All forms desugar at parse time to a plain Stmt::Assign — no new AST nodes. The RHS is a full expression: x *= 2 + 3 desugars to x = x * (2 + 3).

Limitation: ++/-- are statement-level only. Using them inside a larger expression (b = a - b--) is not supported.

switch / case / otherwise

switch expr
  case val1
    % ...
  case val2
    % ...
  otherwise     % optional
    % ...
end

No fall-through — only the first matching case executes. Works with scalars (exact ==) and strings (Str/StringObj interchangeable). break/continue propagate to the nearest enclosing loop.

switch code
  case 200
    msg = 'OK';
  case 404
    msg = 'Not Found';
  otherwise
    msg = 'Unknown';
end
fprintf('%d: %s\n', code, msg)

do…until

Octave post-test loop — body always runs at least once:

do
  body
until (cond)

Parentheses around cond are optional. Closed by until, not end. break and continue work as in while.

x = 1;
do
  x *= 2;
until (x > 100)
fprintf('%d\n', x)   % 128

run() / source()

Execute a script file in the current workspace. Variables defined in the script persist in the caller’s scope (MATLAB run semantics — not a function call):

a = 252; b = 105;
run('euclid_helper')        % looks for euclid_helper.calc, then .m
fprintf('gcd = %d\n', g)    % g was set by the helper

source('euclid_helper')     % Octave alias — identical behaviour

Extension resolution for bare names: .calc is tried first (native ccalc format), then .m (Octave/MATLAB compatibility).

Examples

See the example scripts for self-contained demos:

ccalc examples/control_flow.calc           # if/for/while/break/continue
ccalc examples/extended_control_flow.calc  # switch/do-until/run/source