Control flow

if / else if / else

if (x > 10) {
    Konsol:Print("big");
} else if (x > 5) {
    Konsol:Print("medium");
} else {
    Konsol:Print("small");
}

while

Var:Number i = 0;
while (i < 5) {
    Konsol:Print(i);
    i++;
}

for

for (Number i = 0; i < 10; i++) {
    Konsol:Print(i);
}

The init clause can use Number declaration or a plain assignment. The increment supports ++, --, and = expr.

break

while (true) {
    if (done == true) { break; }
}

continue

Skips the rest of the current iteration and jumps to the next. In a for loop the increment still runs.

for (Number i = 0; i < 10; i++) {
    if (i % 2 == 0) { continue; }
    Konsol:Print(i);   // prints odd numbers only
}

switch / case / default

Evaluates an expression and executes the matching case block. Works with numbers and strings. Supports fall-through (omit break) and a default branch.

switch (expr) {
    case value1:
        // statements
        break;
    case value2:
        // statements
        break;
    default:
        // statements
}

break exits the switch. continue inside a switch propagates to the enclosing loop.

Var:String day = "Wed";
switch (day) {
    case "Mon": Konsol:Print("Monday"); break;
    case "Wed": Konsol:Print("Wednesday"); break;
    default:    Konsol:Print("another day");
}

foreach

Iterate over a List, Array, Dictionary (yields keys, sorted), or String (yields characters) without a manual index counter.

foreach (Type varName in collectionName) { ... }          // Type = Number, String, Boolean, or a class name
foreach (List:Type varName in collectionName) { ... }     // element is itself a list
foreach (Array:Type varName in collectionName) { ... }    // element is itself an array
foreach (Dictionary:Something varName in collectionName) { ... } // element is itself a map

break and continue work the same as in for / while.

List:String fruits;
List:Push("apple", fruits);
List:Push("banana", fruits);

foreach (String item in fruits) {
    Konsol:Print(item);
}

// String - one character per iteration
Var:String word = "hi";
foreach (String ch in word) {
    Konsol:Print(ch);   // h  i
}

Block scope

Every { } block creates its own scope. Variables declared inside a block are not visible outside it:

if (x > 0) {
    Var:String label = "positive"   // scoped to this if block
}
// label is NOT accessible here

if and else have separate scopes - a variable declared in if { } is not visible in else { }:

if (cond) {
    Var:Number a = 1
} else {
    // a is NOT visible here
    Var:Number a = 2    // fine - independent variable
}

Variables declared in a for initialiser are scoped to the entire for block:

for (Var:Number i = 0; i < 10; i++) {
    Konsol:Print(i)     // i is available here
}
// i is NOT accessible here

Outer-scope variables remain visible and writable inside any nested block:

Var:Number total = 0
foreach (Var:Number x in nums) {
    total = total + x   // total is from the enclosing scope - works fine
}
Konsol:Print(total)     // correct sum

Examples

Control flow

// 03_control.ks - if/else if/else, while, for, break

Konsol:Print("=== Control Flow ===");

// if / else if / else
Var:Number score = 75;
Konsol:Print("score = ${score}");
if (score >= 90) {
    Konsol:Print("grade: A");
} else if (score >= 75) {
    Konsol:Print("grade: B");
} else if (score >= 60) {
    Konsol:Print("grade: C");
} else {
    Konsol:Print("grade: F");
}

// Nested if
Var:Boolean active = true;
Var:Number level = 5;
if (active == true) {
    if (level > 3) {
        Konsol:Print("active and high level");
    } else {
        Konsol:Print("active but low level");
    }
}

// while loop
Konsol:Print("--- while ---");
Var:Number i = 1;
while (i <= 5) {
    Konsol:Print("i = ${i}");
    i++;
}

// while with break
Konsol:Print("--- while + break ---");
Var:Number n = 0;
while (true) {
    n++;
    if (n == 4) { break; }
}
Konsol:Print("broke at n = ${n}");

// for loop
Konsol:Print("--- for ---");
for (Var:Number j = 0; j < 5; j++) {
    Konsol:Print("j = ${j}");
}

// for with compound increment
Konsol:Print("--- for step 2 ---");
for (Var:Number k = 0; k <= 10; k += 2) {
    Konsol:Print("k = ${k}");
}

// for with break
Konsol:Print("--- for + break ---");
for (Var:Number x = 0; x < 100; x++) {
    if (x == 3) { break; }
    Konsol:Print("x = ${x}");
}

// Logical conditions
Konsol:Print("--- logical ---");
Var:Number a = 5;
Var:Number b = 10;
if (a > 0 && b > 0) {
    Konsol:Print("both positive");
}
if (a > 100 || b > 5) {
    Konsol:Print("at least one condition true");
}

Block scope

// 48_block_scope.ks - block scoping: each { } has its own scope

// Outer variable accessible inside blocks
Konsol:Print("=== outer visible inside ===");
Var:Number counter = 0;
if (true) {
    counter = 10;       // outer variable, write works
}
Konsol:Print(counter);  // 10

// for init var is scoped to the for block
Konsol:Print("=== for var scoped to for ===");
Var:Number sum = 0;
for (Var:Number i = 1; i <= 5; i++) {
    sum = sum + i;
}
Konsol:Print(sum);      // 15

// while var declared outside stays accessible after
Konsol:Print("=== while outer var ===");
Var:Number n = 0;
while (n < 3) {
    n++;
}
Konsol:Print(n);        // 3

// foreach accumulator pattern (outer var modified inside)
Konsol:Print("=== foreach accumulator ===");
List:New nums:Number;
List:Push(2, nums);
List:Push(4, nums);
List:Push(6, nums);
Var:Number total = 0;
foreach (Var:Number x in nums) {
    total = total + x;
}
Konsol:Print(total);    // 12

// nested blocks - inner can read outer
Konsol:Print("=== nested blocks ===");
Var:Number outer = 99;
if (true) {
    if (true) {
        Konsol:Print(outer);    // 99
        outer = 100;
    }
}
Konsol:Print(outer);            // 100

// if body vars do not bleed into else - tested via separate outer var
Konsol:Print("=== if/else separate scopes ===");
Var:String result = "";
if (false) {
    Var:String msg = "from if";
    String:Set(msg, result);    // result = "from if" (never runs)
} else {
    Var:String msg = "from else";   // independent var, same name is fine
    String:Set(msg, result);
}
Konsol:Print(result);           // from else

Konsol:Print("done");

continue

// 21_continue.ks - continue statement in while and for loops

Konsol:Print("=== continue in while ===");
Var:Number i = 0;
while (i < 6) {
    i++;
    if (i == 3) { continue; }  // skip printing 3
    Konsol:Print(i);
}
// expected: 1 2 4 5 6

Konsol:Print("=== continue in for ===");
for (Var:Number j = 0; j < 8; j++) {
    if (j % 2 == 0) { continue; }  // skip even numbers
    Konsol:Print(j);
}
// expected: 1 3 5 7

Konsol:Print("=== continue with accumulator ===");
Var:Number sum = 0;
for (Var:Number k = 1; k <= 10; k++) {
    if (k == 5) { continue; }  // skip 5
    sum += k;
}
Konsol:Print(sum);
// expected: 50  (1+2+3+4+6+7+8+9+10)

switch / case

// 22_switch.ks - switch / case / default statement

Konsol:Print("=== basic switch (number) ===");
Var:Number x = 2;
switch (x) {
    case 1:
        Konsol:Print("one");
        break;
    case 2:
        Konsol:Print("two");
        break;
    case 3:
        Konsol:Print("three");
        break;
    default:
        Konsol:Print("other");
}
// expected: two

Konsol:Print("=== default branch ===");
Var:Number y = 99;
switch (y) {
    case 1:
        Konsol:Print("one");
        break;
    case 2:
        Konsol:Print("two");
        break;
    default:
        Konsol:Print("no match");
}
// expected: no match

Konsol:Print("=== switch on string ===");
Var:String day = "Wed";
switch (day) {
    case "Mon":
        Konsol:Print("Monday");
        break;
    case "Wed":
        Konsol:Print("Wednesday");
        break;
    case "Fri":
        Konsol:Print("Friday");
        break;
    default:
        Konsol:Print("other day");
}
// expected: Wednesday

Konsol:Print("=== fall-through (no break) ===");
Var:Number n = 1;
switch (n) {
    case 1:
        Konsol:Print("fell into 1");
    case 2:
        Konsol:Print("fell into 2");
        break;
    case 3:
        Konsol:Print("three");
        break;
}
// expected: fell into 1
//           fell into 2

Konsol:Print("=== switch inside loop ===");
for (Var:Number i = 0; i < 4; i++) {
    switch (i) {
        case 0:
            Konsol:Print("zero");
            break;
        case 2:
            Konsol:Print("two");
            break;
        default:
            Konsol:Print("odd");
    }
}
// expected: zero odd two odd

foreach

// 28_foreach.ks - foreach loop

// ── List ─────────────────────────────────────────────────────────────────────
Konsol:Print("=== List ===");
List:New fruits:String;
List:Push("apple", fruits);
List:Push("banana", fruits);
List:Push("cherry", fruits);

foreach (Var:String item in fruits) {
    Konsol:Print(item);     // apple  banana  cherry
}

// ── List with break ───────────────────────────────────────────────────────────
Konsol:Print("=== List break ===");
foreach (Var:String item in fruits) {
    if (item == "banana") { break; }
    Konsol:Print(item);     // apple
}

// ── List with continue ────────────────────────────────────────────────────────
Konsol:Print("=== List continue ===");
foreach (Var:String item in fruits) {
    if (item == "banana") { continue; }
    Konsol:Print(item);     // apple  cherry
}

// ── Array ─────────────────────────────────────────────────────────────────────
Konsol:Print("=== Array ===");
Array:New scores:Number = {10, 20, 30};
foreach (Var:Number n in scores) {
    Konsol:Print(n);        // 10  20  30
}

// ── Dictionary (keys, sorted) ─────────────────────────────────────────────────
Konsol:Print("=== Dictionary keys ===");
Dictionary:New info;
Dictionary:Set("city",    "Manila",      info);
Dictionary:Set("country", "Philippines", info);
Dictionary:Set("lang",    "Filipino",    info);

Var:String dictVal;
foreach (Var:String key in info) {
    Dictionary:Get(key, info, dictVal);
    Konsol:Print(key + " = " + dictVal);
}
// city = Manila   country = Philippines   lang = Filipino  (sorted by key)

// ── String (characters) ───────────────────────────────────────────────────────
Konsol:Print("=== String chars ===");
Var:String word = "hi";
foreach (Var:String ch in word) {
    Konsol:Print(ch);       // h  i
}

// ── Nested foreach ────────────────────────────────────────────────────────────
Konsol:Print("=== Nested ===");
List:New rows:String;
List:Push("A", rows);
List:Push("B", rows);
List:New cols:String;
List:Push("1", cols);
List:Push("2", cols);

foreach (Var:String r in rows) {
    foreach (Var:String c in cols) {
        Konsol:Print(r + c);    // A1 A2 B1 B2
    }
}

// ── Accumulate with foreach ───────────────────────────────────────────────────
Konsol:Print("=== Sum ===");
List:New nums:Number;
List:Push(5, nums);
List:Push(10, nums);
List:Push(15, nums);
Var:Number total = 0;
foreach (Var:Number n in nums) {
    total = total + n;
}
Konsol:Print(total);        // 30

// ── 2D List ───────────────────────────────────────────────────────────────────
Konsol:Print("=== 2D List ===");
List:New row1:String;
List:Push("a", row1);
List:Push("b", row1);
List:New row2:String;
List:Push("c", row2);
List:Push("d", row2);
List:New grid:String;
List:Push("row1", grid);
List:Push("row2", grid);

foreach (List:String innerRow in grid) {
    foreach (Var:String cell in innerRow) {
        Konsol:Print(cell);     // a  b  c  d
    }
}

// ── 2D Array ──────────────────────────────────────────────────────────────────
Konsol:Print("=== 2D Array ===");
Array:New vec1:Number = {1, 2};
Array:New vec2:Number = {3, 4};
Array:New matrix:String = {"vec1", "vec2"};

foreach (Array:Number innerVec in matrix) {
    foreach (Var:Number x in innerVec) {
        Konsol:Print(x);        // 1  2  3  4
    }
}

Konsol:Print("done");