Skip to content

tags:

  • control-flow
  • if-else
  • while
  • loops
  • ternary

Control Flow

Control flow statements determine the order in which code executes. EverSharp provides conditional statements and loops.


If Statement

Basic If

if (condition) {
  // Execute if condition is true
}

Example:

age = 25;

if (age >= 18) {
  $Log("Adult");
}

If-Else

if (condition) {
  // Execute if true
} else {
  // Execute if false
}

Example:

age = 15;

if (age >= 18) {
  status = "Adult";
} else {
  status = "Minor";
}

If-Else-If Chain

if (condition1) {
  // Execute if condition1 is true
} else if (condition2) {
  // Execute if condition2 is true
} else if (condition3) {
  // Execute if condition3 is true
} else {
  // Execute if all conditions are false
}

Example:

score = 85;

if (score >= 90) {
  grade = "A";
} else if (score >= 80) {
  grade = "B";
} else if (score >= 70) {
  grade = "C";
} else if (score >= 60) {
  grade = "D";
} else {
  grade = "F";
}

Single-Line If

Braces are optional for single statements:

if (isActive) status = "Active";

if (count > 0) $Log("Items found");

if (premium > maxPremium) premium = maxPremium;

Note: While allowed, braces are recommended for clarity.

Nested If

if (age >= 18) {
  if (hasLicense) {
    if (!hasSuspension) {
      canDrive = true;
    } else {
      canDrive = false;
    }
  }
}

Better with logical operators:

canDrive = age >= 18 && hasLicense && !hasSuspension;

Condition Requirements

The condition must evaluate to a boolean:

// CORRECT: Boolean conditions
if (age > 18) {
}
if (isActive) {
}
if (count == 0) {
}
if (name != null) {
}

// ERROR: Non-boolean conditions
// if (count) { }           // ERROR: number not boolean
// if (name) { }            // ERROR: string not boolean
// if (object) { }          // ERROR: object not boolean

While Loop

Basic While

while (condition) {
  // Execute repeatedly while condition is true
}

Example:

counter = 0;

while (counter < 5) {
  $Log(counter);
  counter++;
}
// Output: 0, 1, 2, 3, 4

Infinite Loop

while (true) {
  // Loops forever
  // Must have external mechanism to exit
}

Note: EverSharp has no break statement, so use with caution.

Loop with Complex Condition

attempts = 0;
maxAttempts = 3;
success = false;

while (attempts < maxAttempts && !success) {
  success = tryOperation();
  attempts++;
}

Manual Array Iteration

items = [10, 20, 30, 40, 50];
index = 0;

while (index < items.Length) {
  $Log(items[index]);
  index++;
}

Better alternative: Use array methods

items.ForEach((item) => $Log(item));

Exit Statement

Immediate Script Termination

The exit statement immediately terminates the entire script execution, regardless of where it's called:

exit;

Example - Basic Exit:

counter = 0;
counter = counter + 1;
exit;
counter = counter + 100; // Never executed

Exit in Conditionals

if (error) {
  $Log("Critical error detected");
  exit;
}
$Log("Continuing..."); // Not reached if error is true

Exit in Loops

i = 0;
total = 0;
while (i < 10) {
  total = total + i;
  if (i == 5) {
    exit; // Terminates entire script, not just loop
  }
  i = i + 1;
}

Exit vs Return

Key Differences:

Feature return exit
Scope Exits current function Exits entire script
Value Can return a value No return value
Usage Functions only Anywhere in script

Example:

function validate(data) {
  if (data == null) {
    exit; // Terminates entire script
  }
  return true; // Returns from function only
}

result = validate(myData);
$Log("After function"); // Not reached if exit was called

When to Use Exit

Good use cases:

  • Critical validation failures
  • Unrecoverable error conditions
  • Safety limits exceeded
  • Early termination based on business rules

Example - Safety Check:

if (premium > 1000000) {
  $Log("Premium exceeds maximum allowed");
  exit;
}

Throw Statement

Error Handling with Throw

The throw statement immediately terminates script execution and raises a runtime error with a custom message:

throw "Error message";
throw;  // Throws "Runtime error"

Example - Basic Throw:

counter = 0;
counter = counter + 1;
throw "Something went wrong";
counter = counter + 100; // Never executed

Throw with Dynamic Messages

You can use any expression that evaluates to a value:

age = -5;
throw "Invalid age: " + age;
// Error: Invalid age: -5

errorCode = 404;
throw errorCode;
// Error: 404

value = -10;
throw value < 0 ? "Negative value" : "Positive value";
// Error: Negative value

Throw in Conditionals

if (age < 0) {
  throw "Age cannot be negative";
}

if (premium > maxPremium) {
  throw "Premium exceeds maximum: " + premium;
}

Throw in Loops

i = 0;
total = 0;
while (i < 10) {
  total = total + i;
  if (i == 5) {
    throw "Error at iteration " + i; // Terminates entire script
  }
  i = i + 1;
}

Throw in Functions

function validateAge(age) {
  if (age < 0) {
    throw "Age cannot be negative: " + age;
  }

  if (age > 150) {
    throw "Age is unrealistic: " + age;
  }

  return true;
}

// This will throw an error
result = validateAge(-5);
$Log("After validation"); // Not reached

Throw vs Exit vs Return

Key Differences:

Feature return exit throw
Scope Exits current function Exits entire script Exits entire script
Value Can return a value No return value Error message
Error No No Yes
Usage Functions only Anywhere in script Anywhere in script
Detection N/A Normal termination Adds error to Errors list

Example Comparison:

function processData(data) {
  // Return - exits function normally
  if (data == null) {
    return null;
  }

  // Exit - terminates script normally
  if (data.critical && !data.valid) {
    $Log("Critical data invalid, stopping");
    exit;
  }

  // Throw - terminates script with error
  if (data.value < 0) {
    throw "Data value cannot be negative: " + data.value;
  }

  return process(data);
}

When to Use Throw

Good use cases:

  • Input validation errors
  • Business rule violations
  • Invalid state detection
  • Constraint violations
  • Data integrity issues

Example - Validation Pattern:

function calculatePremium(age, coverage) {
  // Validate inputs
  if (age < 18) {
    throw "Applicant must be 18 or older";
  }

  if (age > 100) {
    throw "Age exceeds maximum: " + age;
  }

  if (coverage <= 0) {
    throw "Coverage amount must be positive";
  }

  if (coverage > 10000000) {
    throw "Coverage exceeds maximum: $10,000,000";
  }

  // Calculate premium
  basePremium = coverage * 0.001;
  ageFactor = age > 65 ? 1.5 : 1.0;

  return basePremium * ageFactor;
}

Error Detection in Host Application

When using EverSharpRunner, thrown errors can be detected:

var runner = new EverSharpRunner();
runner.Run(@"
    age = -5;
    throw ""Invalid age: "" + age;
");

if (runner.HasErrors) {
    foreach (var error in runner.Errors) {
        Console.WriteLine($"Error: {error}");
        // Output: Error: Invalid age: -5
    }
}

No Break or Continue

EverSharp does not support break or continue statements.

Workarounds

Instead of break:

// Using flag
found = false;
index = 0;

while (index < items.Length && !found) {
  if (items[index] == target) {
    found = true;
  } else {
    index++;
  }
}

// Better: Use .Find()
item = items.Find((x) => x == target);

Instead of continue:

// Using conditional
index = 0;

while (index < items.Length) {
  if (items[index] % 2 == 0) {
    // Process even numbers
    process(items[index]);
  }
  index++;
}

// Better: Use .Filter()
items.Filter((x) => x % 2 == 0).ForEach((x) => process(x));

No For Loop

EverSharp does not have a for loop.

Alternatives

Use while:

// Traditional for-loop equivalent
i = 0;
while (i < 10) {
  $Log(i);
  i++;
}

Use array methods (preferred):

// Instead of for loop
numbers = [1, 2, 3, 4, 5];

// Map
doubled = numbers.Map((x) => x * 2);

// Filter
evens = numbers.Filter((x) => x % 2 == 0);

// ForEach
numbers.ForEach((n) => $Log(n));

// Reduce
sum = numbers.ReduceToNum((acc, x) => acc + x, 0);

Ternary Operator

A compact alternative to if-else for simple assignments:

result = condition ? valueIfTrue : valueIfFalse;

Examples:

// Simple assignment
status = age >= 18 ? "Adult" : "Minor";

// In calculations
discount = isPremium ? 0.2 : 0.1;
premium = basePremium * (age > 65 ? 1.25 : 1.0);

// With expressions
max = a > b ? a : b;
min = a < b ? a : b;

When to use:

  • Simple conditions
  • Single value assignment
  • Inline calculations

When to avoid:

  • Complex logic
  • Multiple statements
  • Nested ternaries (hard to read)

Block Statements

Blocks group multiple statements:

{
  statement1;
  statement2;
  statement3;
}

With if:

if (premium > threshold) {
  discount = premium * 0.1;
  premium = premium - discount;
  $Log("Discount applied: " + discount);
}

With while:

while (counter < 10) {
  value = counter * 2;
  $Log(value);
  counter++;
}

Standalone (creates new scope):

{
  tempValue = expensiveCalculation();
  result = processValue(tempValue);
  $Log("Processed: " + result);
}
// tempValue out of scope here

Common Patterns

Pattern 1: Range Checking

if (age >= 18 && age <= 65) {
  premium = standardPremium;
} else if (age < 18) {
  premium = youthPremium;
} else {
  premium = seniorPremium;
}

Pattern 2: Null Checking

if (object != null) {
  if (object.property != null) {
    value = object.property.value;
  }
}

// Or combined
if (object != null && object.property != null) {
  value = object.property.value;
}

Pattern 3: Validation

hasErrors = false;
errorMessage = "";

if (age < 18) {
  hasErrors = true;
  errorMessage = "Must be 18 or older";
} else if (premium > maxPremium) {
  hasErrors = true;
  errorMessage = "Premium exceeds maximum";
}

if (!hasErrors) {
  // Process
}

Pattern 4: Accumulation

total = 0;
index = 0;

while (index < items.Length) {
  total += items[index];
  index++;
}

Pattern 5: Early Return

function validate(data) {
  if (data == null) {
    return false;
  }

  if (data.age < 18) {
    return false;
  }

  if (data.premium > maxPremium) {
    return false;
  }

  return true;
}

Pattern 6: State Machine

state = "INIT";

while (state != "DONE") {
  if (state == "INIT") {
    initialize();
    state = "PROCESSING";
  } else if (state == "PROCESSING") {
    if (process()) {
      state = "COMPLETE";
    } else {
      state = "ERROR";
    }
  } else if (state == "COMPLETE") {
    finalize();
    state = "DONE";
  } else if (state == "ERROR") {
    handleError();
    state = "DONE";
  }
}

Control Flow with Functions

Conditional Execution

function processOrder(order) {
  if (order.total < minOrderAmount) {
    return null;
  }

  if (order.customer == null) {
    return null;
  }

  // Process order
  result = calculateTotal(order);
  return result;
}

Loop with Function

function sumArray(arr) {
  sum = 0;
  index = 0;

  while (index < arr.Length) {
    sum += arr[index];
    index++;
  }

  return sum;
}

Recursive Control Flow

function factorial(n) {
  if (n <= 1) {
    return 1;
  }

  return n * factorial(n - 1);
}

result = factorial(5); // 120

Best Practices

1. Use Array Methods Instead of Loops

// Less ideal
sum = 0;
i = 0;
while (i < numbers.Length) {
  sum += numbers[i];
  i++;
}

// Better
sum = numbers.ReduceToNum((acc, x) => acc + x, 0);

2. Keep Conditions Simple

// Complex
if ((age >= 18 && age <= 65 && hasLicense) || (age > 65 && hasSpecialPermit && !hasSuspension)) {
  // ...
}

// Better: break into parts
isStandardEligible = age >= 18 && age <= 65 && hasLicense;
isSeniorEligible = age > 65 && hasSpecialPermit && !hasSuspension;

if (isStandardEligible || isSeniorEligible) {
  // ...
}

3. Avoid Deep Nesting

// Deeply nested
if (a) {
  if (b) {
    if (c) {
      if (d) {
        // ...
      }
    }
  }
}

// Better: early returns
if (!a) return;
if (!b) return;
if (!c) return;
if (!d) return;
// ...

4. Use Ternary for Simple Cases

// Verbose
if (age >= 18) {
  status = "Adult";
} else {
  status = "Minor";
}

// Concise
status = age >= 18 ? "Adult" : "Minor";

5. Always Use Braces

// Risky
if (condition) doSomething();

// Safer
if (condition) {
  doSomething();
}

6. Check Boolean Conditions Explicitly

// Correct (EverSharp requires explicit boolean)
if (count > 0) {
}
if (name != null && name != "") {
}
if (isActive == true) {
} // Or just: if (isActive) { }

// Would be errors in EverSharp
// if (count) { }
// if (name) { }

Common Mistakes

Mistake 1: Using Non-Boolean Conditions

// ERROR
// if (value) { }

// CORRECT
if (value != null) {
}
if (value > 0) {
}

Mistake 2: Expecting Break/Continue

// ERROR: break doesn't exist
// while (true) {
//     if (found) break;
// }

// CORRECT: use flag
found = false;
while (!found) {
  if (condition) {
    found = true;
  }
}

Mistake 3: Using For Loop

// ERROR: for doesn't exist
// for (i = 0; i < 10; i++) {
//     $Log(i);
// }

// CORRECT: use while
i = 0;
while (i < 10) {
  $Log(i);
  i++;
}

Mistake 4: Forgetting Loop Increment

// ERROR: Infinite loop
// counter = 0;
// while (counter < 10) {
//     $Log(counter);
//     // Forgot: counter++;
// }

// CORRECT
counter = 0;
while (counter < 10) {
  $Log(counter);
  counter++; // Don't forget!
}

Mistake 5: Assignment in Condition

// ERROR: Assignment returns value, not boolean
// if (x = 10) { }

// CORRECT: Use comparison
if (x == 10) {
}

// Or if you meant assignment then check:
x = 10;
if (x > 5) {
}

Advanced Examples

Example 1: Premium Calculation

function calculatePremium(age, coverage, history) {
  basePremium = coverage * 0.01;

  // Age adjustment
  if (age < 25) {
    basePremium *= 1.5;
  } else if (age > 65) {
    basePremium *= 1.25;
  }

  // Coverage tier adjustment
  if (coverage > 500000) {
    basePremium *= 1.1;
  } else if (coverage < 100000) {
    basePremium *= 0.9;
  }

  // History adjustment
  if (history == "excellent") {
    basePremium *= 0.8;
  } else if (history == "poor") {
    basePremium *= 1.3;
  }

  return $Round(basePremium, 2);
}

Example 2: Data Validation

function validatePolicy(policy) {
  errors = [];

  if (policy == null) {
    errors.Push("Policy is null");
    return errors;
  }

  if (policy.number == null || policy.number == "") {
    errors.Push("Policy number required");
  }

  if (policy.premium <= 0) {
    errors.Push("Premium must be positive");
  }

  if (policy.customer == null) {
    errors.Push("Customer required");
  } else {
    if (policy.customer.age < 18) {
      errors.Push("Customer must be 18 or older");
    }
  }

  return errors;
}

errors = validatePolicy(myPolicy);

if (errors.Length > 0) {
  $Log("Validation errors:");
  errors.ForEach((err) => $Log("  - " + err));
}

Example 3: Batch Processing

function processBatch(items) {
  successCount = 0;
  failureCount = 0;
  index = 0;

  while (index < items.Length) {
    item = items[index];

    if (item != null && item.isValid) {
      if (processItem(item)) {
        successCount++;
      } else {
        failureCount++;
      }
    }

    index++;
  }

  return {
    success: successCount,
    failure: failureCount,
    total: items.Length,
  };
}

Next Steps