Popup YouTube Video
Sheerpower Logo

A Guide for an AI when Vibe Coding


Sheerpower: A Guide for an AI when Vibe Coding

This guide is written for AI language models generating Sheerpower code. It focuses on the patterns most likely to produce incorrect output when models apply habits from C, Python, JavaScript, or Java — and shows the correct Sheerpower form alongside each trap.

Special note:

Generate only syntax that appears in this guide or in the official Sheerpower tutorials. When a statement, function name, parameter, or syntax rule cannot be confirmed from either source, do not invent a plausible-looking substitute. Instead, choose one of the following actions:

  • State the uncertainty in plain text.
    Example: I am not certain whether Sheerpower's string-search function is pos(), index(), or find(). Please confirm before I continue.
  • Request the relevant tutorial or reference material.
    Example: Before writing the file I/O section, I need to re-read the File I/O tutorial. Is it available?
  • Insert a clearly marked gap and continue around it.
    Example:
// UNVERIFIED: exact syntax for sorting a cluster array descending
// confirm against Cluster Sorting tutorial before running

A compile error on a marked gap is recoverable. A confabulated routine name buried in otherwise correct-looking code is not — it fails silently, erodes trust, and can take longer to track down than the original task.

Takeaway: Stop, mark, or ask — in that order. If a piece of Sheerpower syntax cannot be traced to this guide or the tutorials, that is the signal to pause, not proceed.

This document is structured around error patterns observed in generated code — not around language features.

The goal is simple: eliminate predictable errors in generated code before they reach execution.

Human readers will also find this a useful quick-reference for the rules that differ most from mainstream languages.

What this guide covers

  • Comment syntax — prefer //, but ! is okay for all new code.
  • Sheerpower routine calling syntax — no call prefix keyword, use named parameters.
  • All with arguments are read-only within the routine — compiler enforced.
  • Block terminators — the full list.
  • select case — always include case else.
  • Exception handling — attached vs. detached, retry vs. continue.
  • Loop control — do / repeat do / end do.
  • Variable suffixes — $, ?, and bare names.
  • sprintf$() format specifiers.
  • Cluster access and iteration.
  • collect cluster before for each.
  • findrow() for fast single-row lookup.
  • The VIEW statement.
  • CGI web handler patterns.
  • Common built-in idioms such as element$(), elements(), size(), str$(), and pass.
  • What does not exist in Sheerpower.
  • Unique IDs — _GID$ special variable.
  • Exception handler discipline — when a handler earns its place.
  • Routine ordering — major to minor, callers before the routines they call.

Sheerpower Source Code

To maximize portability, compatibility, and long-term maintainability, use only ASCII characters in all Sheerpower source code.

Sheerpower is case-insensitive. For consistency, write all code in lower-case and use snake_case for multi-word identifiers. Where ever possible, use meaningful variable names. This helps both code validation and code maintenance later on.

Calling Routines

This is the single most common error in AI-generated Sheerpower code. Sheerpower has no call prefix keyword when invoking routines. Routines are invoked by just their name, followed by with for inputs and returning for outputs. Sheerpower routine names cannot contain $ or ? characters. All with arguments are read-only within the routine — compiler enforced.

Problem: AI models trained on other languages generate call routine_name(args) or result = routine_name(args).

Solution: Use Sheerpower's named-parameter syntax. There is no call keyword and no parentheses on routine invocations.

Efficiency: Named parameters are passed by reference, so even large data structures cost nothing to pass.

Takeaway: Never write call. Never write result = routine_name(args). Use the with / returning syntax below.

Wrong (do not generate)

call calculate_tax(income, rate) tax = calculate_tax(income, rate) calculate_tax(income, rate, tax)

Correct

// Full syntax calculate_tax with income=my_income, rate=tax_rate, returning tax tax_due // Without "=" calculate_tax with income my_income, rate tax_rate, returning tax tax_due // Implied -- variable names match parameter names exactly calculate_tax with income, rate, returning tax

All three forms are equivalent. The implied form works when your local variable names exactly match the routine's parameter names.

Routine definition

routine calculate_tax with income, rate, returning tax tax = income * rate end routine

Parameters are read-only inside the routine by default. Do not attempt to assign to a with parameter — it is not allowed by the compiler.

No User-Defined Functions

Sheerpower does not support user-defined functions. Instead, use routines with returning parameter values.

This approach improves clarity, especially when multiple values need to be returned, and keeps all logic within a consistent routine-based structure.

Block Terminators — the Complete List

Every block in Sheerpower has an explicit named terminator. Missing or mismatching a terminator is a common AI error, especially when generating nested structures.

Problem: AI models omit terminators, use wrong keywords, or use braces from C-style habits.

Solution: Most blocks close with a two-word or three-word end ___ keyword — no braces.

Efficiency: Sheerpower's compiler reports the exact line of a missing terminator, making errors easy to find.

Takeaway: After generating any block, verify that its closing keyword appears in the list below.
end routine end handler end when end collect end do // one time loop loop // endless loop, use while or until or exit do, as needed end if end select end add

There are no braces. There is no endif as a single word — it must be written end if with a space.

for loops — both numeric and for each — close with next varname, not an end keyword.

// Numeric for loop for i = 1 to 10 print i next i // closes the for loop // For each over a cluster array for each orders print orders->customer$ next orders // closes the for each loop -- NOT "end for"

Nested structure example — correct terminators

routine process_orders with orders for each orders if orders->amount > 1000 then select case orders->region$ case "North" print "North: "; orders->amount case else print "Other: "; orders->amount end select end if next orders end routine

select case Requires case else

When generating a select case block, always include case else. If no case matches and there is no case else, the program can fail at runtime.

Problem: AI models often generate select case blocks with only the expected cases. This is fragile because real data can contain unexpected values.

Solution: Always include case else as the fallback branch.

Efficiency: A fallback branch makes the control flow explicit and prevents unexpected values from becoming runtime failures.

Takeaway: Every generated select case block should include case else.

Wrong

select case status$ case "open" print "Open" case "closed" print "Closed" end select

Correct

select case status$ case "open" print "Open" case "closed" print "Closed" case else print "Unknown status: "; status$ end select

Use VAL() as the Primary Way to Parse Numbers From Text

In Sheerpower, the primary way to extract numbers from text is VAL(). When numeric data appears inside a larger string, do not assume the text must be split apart first, and do not invent manual parsing helpers unless they are truly necessary.

Use VAL(string$) when the entire string should be a number. Use VAL(string$, Nth) when the string may contain embedded numbers and you want the first, second, third, or later numeric value. This makes VAL() the standard tool for parsing values from user input, reports, logs, messages, and mixed text.

For example, given the string "I need 5 widgets at $12.99 each", you can extract the numbers directly:

a$ = "I need 5 widgets at $12.99 each" qty = val(a$, 1) price = val(a$, 2) print qty, price

This extracts 5 and 12.99 without any manual parsing or string splitting.

If parsing may fail, check _integer immediately after the call. A value of 0 means no valid number was found. When needed, use the optional parsing options to handle separators, ignored characters, negative formats such as parentheses, or European number conventions.

In short: when an AI needs to get a number out of text in Sheerpower, it should think of VAL() first.

Exception Handling

Sheerpower has two forms of exception handler. The words retry and continue mean something specific here and must not be confused with loop control.

Attached handler (most common)

when exception in // protected code here x = 10 / y use if extype = exceptiontype("divby0") then y = 1 retry // re-executes the failing statement else print "Error: "; extext$ continue // resumes at the statement AFTER the one that failed end if end when

Detached handler

when exception use fix_divide_error average = total / count end when print "Average: "; average handler fix_divide_error average = 0 continue end handler
Problem: AI models confuse retry and continue, or use throw / raise / except from other languages.

Solution: Use only the Sheerpower keywords shown above. To raise an exception deliberately, use cause exception.

Efficiency: Sheerpower's stackless VM rewinds call depth on exception at near-zero cost, so exception handlers are not expensive.

Takeaway: retry = re-run the failing statement after fixing the cause. continue = skip the failing statement and move on. Never write throw, raise, except, or catch.

Exception introspection variables

_error // TRUE if an exception occurred extype // numeric exception type extext$ // plain-text description of the exception exlabel$ // source location where the exception occurred systext$ // OS-level error description // Compile-time constant folding -- zero runtime cost when literal string used: exceptiontype("divby0") // returns 3001 exceptiontype("filenotfound") // returns 7110

Causing an exception deliberately

// cause exception takes a numeric exception number if quantity < 1 then cause exception 1001 if quantity < 1 then cause exception exceptiontype("illnum")

Loop Control

Sheerpower's main loop construct is do / end do. The keyword that restarts the loop from the top is repeat do — not continue. The keyword that exits is exit do.

Problem: AI models write continue inside a loop intending to restart the iteration. In Sheerpower, continue is an exception-handler keyword only.

Solution: Use repeat do to restart a do loop. Use exit do to break out.

Efficiency: repeat do is explicit about intent — there is no ambiguity about which loop is being restarted in nested structures.

Takeaway: Inside a loop, never write continue. Write repeat do to cycle, exit do to leave.

Wrong (do not generate)

do input "Enter a positive number": n if n <= 0 then continue // WRONG -- continue is not loop control print n * 2 end do

Correct

do input "Enter a positive number": n if n <= 0 then print "Must be positive. Try again." repeat do // restart the loop end if print n * 2 end do

For loops and for-each

// Numeric for loop for i = 1 to 10 print i next i // Step for i = 10 to 1 step -1 print i next i // Open-ended for loop -- no upper bound; use "exit for" to leave for idx = 1 VIEW token$ INTO data$, PIECE ",", MATCH idx if token$ = '' then exit for print token$ next idx // For each over a cluster array for each orders print orders->customer$; ": "; orders->amount next orders // Exit a for loop early for i = 1 to 100 if results(i) = "done" then exit for next i

Loop control keywords — complete list

Problem: AI models use continue inside for loops to skip to the next iteration or break to exit. Neither keyword exists for loop control in Sheerpower.

Solution: Use the keywords below. Each one is specific to its loop type.

Efficiency: Explicit keywords make it unambiguous which loop is being controlled in nested structures.

Takeaway: iterate for skips to the next for iteration. repeat do restarts a do loop. Never use continue or break for loop control.
// DO loop control repeat do // skip remaining body, restart from top of do loop exit do // exit the do loop entirely // FOR loop control iterate for // skip remaining body, advance to next for iteration exit for // exit the for loop entirely

Early exit from a routine

There is no return statement in Sheerpower. To exit a routine before reaching its end, use exit routine.

routine validate_amount with amount, returning ok? ok? = false if amount <= 0 then exit routine // early exit -- ok? stays false if amount > 1_000_000 then exit routine ok? = true end routine

Variable Naming and Type Suffixes

Sheerpower uses visual suffixes to declare variable type implicitly. These are part of the variable name, not operators.

name$ // STRING -- ends with $ is_active? // BOOLEAN -- ends with ? total // REAL -- no suffix (default numeric type) count // REAL -- REAL holds integers accurately too
Problem: AI models omit the ? suffix on boolean variables, generating is_active = true instead of is_active? = true.

Solution: Any variable holding a boolean value must end with ? when declared implicitly. Without the suffix, Sheerpower creates a REAL variable and true stores as 1.

Efficiency: Suffix-based typing means no var, let, int, or float declarations needed for most cases.

Takeaway: Check every boolean variable name for the ? suffix. Check every string variable name for the $ suffix.

Explicit declarations when needed

declare string shipping_address // explicit string, no $ suffix needed declare real salary // explicit real declare boolean is_manager // explicit boolean, no ? suffix needed declare dynamic x // type determined at first use

Constants

const max_retries = 5 const app_name$ = "OrderSystem"

String Literals — No Escape Sequences

Sheerpower string literals are treated as raw text. There are no escape sequences inside strings.

Problem: AI models trained on C, Python, or JavaScript generate escape sequences such as \n, \t, or \\, or double-escape backslashes unnecessarily.

Solution: In Sheerpower, a string stores exactly the characters written. A backslash is just a backslash. There are no escape rules to apply.

Efficiency: This eliminates an entire class of bugs related to incorrect escaping and double-escaping across systems.

Takeaway: What you type is what is stored. Do not insert extra backslashes. Do not interpret escape sequences.

Example

a$ = "\" // a$ contains exactly one character: "\" b$ = "\n" // contains two characters: "\" and "n"

Do not apply escape rules from other languages. Write exactly the characters you want stored in the string.

Date and Time Functions

Sheerpower has its own date and time functions, and these should be used for all date and time manipulation.

Do not assume date or time syntax from other programming languages.

Before writing any date or time code, note these specific patterns that AIs frequently get wrong in Sheerpower:

  • SECONDS() requires a full datetime string, not just a date. A variable containing only YYYY-MM-DD will cause an illegal time format error.
  • Do not invent formatting helper routines such as format_duration(). Use the built-in date and time functions instead.
  • Do not assume date arithmetic syntax from Python, JavaScript, or any other language.
  • If your code touches dates, times, durations, or time arithmetic in any form, re-read the Date and Time Functions tutorial before writing that section.

To avoid common AI confabulations, read this tutorial carefully before writing or explaining any Sheerpower code that works with dates or times:

Date and Time Functions Tutorial

The "90% IEEE Trap" and Exact REALs

Problem: In most mainstream languages (Python, Java, JavaScript, C++), numeric calculations use IEEE 754 binary floating-point. These values cannot exactly represent many decimal numbers. This leads to small but visible errors in results (for example, 0.1 + 0.2 = 0.30000000000000004).

Because of this, AI-generated code often adds round(), floor(), or similar adjustments after calculations to "correct" the result.

Sheerpower Difference: Sheerpower uses Exact REAL values stored in a decimal-accurate format. Decimal values are represented exactly, so calculations produce correct results without adjustment.

Instruction for AI:
Do not add rounding to compensate for floating-point error. In Sheerpower, the result of a calculation is already correct. For example, 0.1 + 0.2 evaluates exactly to 0.3.

Business Logic Only:
Apply rounding only when it is explicitly required by the business rules, for example, "round tax to the nearest cent." Do not round as a defensive habit.

Trust the VM:
Sheerpower's Virtual Machine is designed for precise decimal arithmetic. You can rely on the direct result of any numeric expression.

Takeaway:
If you are about to write round(total, 2) just to ensure cents are correct, stop. In Sheerpower, the cents are already correct.

Clusters — Access and Iteration

Clusters are Sheerpower's primary structured data type. The field-access operator is ->.

Scalar cluster (single record)

cluster employee: name$, age, real salary, position$ employee->name$ = "Maria Santos" employee->age = 34 employee->salary = 62_000 employee->position$ = "Senior Analyst" print employee->name$; " earns "; employee->salary

Cluster array (adding multiple rows)

cluster orders: customer$, amount, region$ add cluster orders orders->customer$ = "Acme Corp" orders->amount = 4500 orders->region$ = "North" end add add cluster orders orders->customer$ = "Beta LLC" orders->amount = 1200 orders->region$ = "South" end add add cluster orders orders->customer$ = "Acme LLC" orders->amount = 5500 orders->region$ = "East" end add add cluster orders orders->customer$ = "Alpha LLC" orders->amount = 2200 orders->region$ = "West" end add

Collecting and iterating

collect cluster orders include orders->amount > 1000 sort by orders->customer$ end collect for each orders print orders->customer$; tab(25); orders->amount next orders

Descending Sorting

collect cluster orders include orders->amount > 1000 sort descending by orders->amount // incorrect syntax is sort by orders->amount descending end collect for each orders print orders->customer$; tab(25); orders->amount next orders
Problem: AI models generate loop variables like for order in orders and then access fields as order->amount. There is no such iteration variable in Sheerpower.

Solution: Inside a for each loop, use the cluster name itself with -> to access fields: orders->amount.

Efficiency: for each iterates the collected result set directly with no temporary object allocation.

Takeaway: The cluster name is both the collection and the current-row accessor. There is no separate iterator variable.

Loading from a CSV file

cluster sales: date$, product$, amount, region$ cluster input name '@sales_2025.csv', headers 1: sales

Always collect Before for each

Before iterating a cluster array with for each, collect the cluster. This step prepares the current result set for iteration. Without a collect cluster, a for each loop may not iterate the rows you expect.

Problem: AI models trained on other languages expect collection iteration to work immediately. They generate for each loops without first collecting the cluster.

Solution: Use collect cluster before every for each iteration, even when no filtering or sorting is needed.

Efficiency: collect defines the active result set. It can also apply filtering, sorting, and selection before iteration begins.

Takeaway: In Sheerpower, collect is the required setup step before for each.

Wrong

for each orders print orders->customer$; " "; orders->amount next orders

Correct

collect cluster orders end collect for each orders print orders->customer$; " "; orders->amount next orders

Filtering and sorting before iteration

collect cluster orders include orders->amount > 1000 sort descending by orders->amount end collect for each orders print orders->customer$; " "; orders->amount next orders

Use findrow() for Single-Row Lookup

When looking up a single row in a cluster, use findrow(). Do not generate a full collect / include / for each / exit for loop just to find one matching row.

Problem: AI models often search for one row by generating a loop over the whole cluster. This is verbose and can be inefficient.

Solution: Use findrow() for direct lookup when the goal is to find one matching row.

Efficiency: findrow() is the idiomatic Sheerpower way to perform fast single-row lookup, rather than scanning rows manually.

Takeaway: If the intent is "find the row," reach for findrow() before writing a loop.

Wrong pattern

found? = false collect cluster foods include foods->id$ = wanted_id$ end collect for each foods found? = true exit for next foods

Correct pattern

row = findrow(foods, foods->id$ = wanted_id$) if row = 0 then print "Food not found" else print foods(row)->name$ end if

The VIEW Statement

VIEW creates a zero-copy window into a source string. It does not allocate a new string — it references a position and length within the original buffer. The clauses must appear in the correct order.

Problem: AI models either omit VIEW entirely and generate slow substring loops, or get the clause ordering wrong.

Solution: Use the clause order shown below. INTO names the source. The remaining clauses such as MID, PIECE, MATCH, and related options describe how to locate the window.

Efficiency: No string copy occurs. For large files parsed line-by-line, this is orders of magnitude faster than building substrings in a loop.

Takeaway: When parsing delimited text, reach for VIEW before reaching for mid$() or string concatenation.

Extracting a segment using MID

data$ = "hello" VIEW v$ INTO data$, MID 2, 3 // character positions 2, 3, and 4 // v$ hasn't calculated offsets yet PRINT v$ // NOW it evaluates to "ell" and caches it PRINT v$ // Reuses cached offsets -- no recalculation! data$ = "world" PRINT v$ // Re-evaluates to "orl" because source changed

Extracting a delimited piece

csv_line$ = "Alice,Santos,42,Manila" VIEW first_name$ INTO csv_line$, PIECE ",", MATCH 1 VIEW last_name$ INTO csv_line$, PIECE ",", MATCH 2 VIEW age$ INTO csv_line$, PIECE ",", MATCH 3 print first_name$; " "; last_name$; " age "; val(age$)

Iterating all pieces in a string

data$ = "red,green,blue,yellow" for idx = 1 VIEW token$ INTO data$, PIECE ",", MATCH idx if token$ = '' then exit for print idx; ": "; token$ next idx

Parsing a file line by line

sep$ = chr$(13) + chr$(10) log$ = fileinfo$("@app.log", "contents") for idx = 1 VIEW line$ INTO log$, PIECE sep$, MATCH idx if line$ = '' then exit for if contains(line$, "error") then print line$ next idx

Keywords That Do Not Exist in Sheerpower

The following keywords are common in other languages. None of them exist in Sheerpower. Generating them will produce a compile error.

// These keywords do not exist in Sheerpower -- do not generate them: call // routines are invoked by name only return // use: exit routine, or the "returning" clause throw // use: cause exception raise // use: cause exception catch // use: when exception in ... use ... end when except // use: when exception in ... use ... end when continue // in loops, use: repeat do / iterate for new // no heap allocation; clusters and variables are declared, not constructed this // no object model; use cluster field access: clustername->field null // use '' for empty string, 0 for empty numeric void // routines with no returning clause simply have no return value function // use: routine ... with ... returning ... def // use: routine fn // use: routine break // use: exit do or exit for end for // for loops close with "next varname", not "end for" endif // must be written as two words: end if split // use element$(), elements(), VIEW, or VAL(), depending on the task

Print and Output

Output uses print. Items are separated by semicolons. A trailing semicolon suppresses the newline. Tab alignment uses tab(n).

print "Hello, "; name$ // basic output print "Total: "; total; " items" // mixed types -- no conversion needed print "Col1"; tab(20); "Col2"; tab(40); "Col3" // tabbed columns print // blank line print "No newline here"; // trailing semicolon suppresses newline print " -- continued on same line"

Formatted numeric output

print sprintf$("%m", 1234567.89) // output: 1,234,567.89 print sprintf$("%.2f", price) // output: 1234567.89 print sprintf$("$%.2m", amount) // output: $1,234,567.89

sprintf$() Format Specifiers

Sheerpower uses sprintf$() for formatted string output. Do not assume that Sheerpower format strings are the same as C printf, JavaScript template strings, or Python format strings.

Several Sheerpower format specifiers are especially important because they appear often in real programs and have no direct equivalent in mainstream languages.

Problem: AI models often treat sprintf$() as if it were C printf or Python formatting. This leads to wrong assumptions about substitution, pluralization, money formatting, and number-to-words output.

Solution: Use the Sheerpower format specifiers shown below. Do not invent C-style or Python-style alternatives.

Efficiency: Built-in formatting keeps common output logic compact and avoids hand-written pluralization, comma insertion, and check-writing routines.

Takeaway: When generating formatted output in Sheerpower, first check whether sprintf$() already has the needed format specifier.

Common Sheerpower Format Specifiers

// Bare % -- general substitution for any type print sprintf$("Name: %, Score: %", name$, score) // %p -- automatic pluralization print sprintf$("% %p", item_count, "item") // %m -- comma-separated numeric output print sprintf$("%m", 1234567.89) // %w -- number-to-words output amount = 1234.56 print sprintf$("%w", amount)

The %p format is used for automatic pluralization. It takes the count and the singular word:

print sprintf$("% %p", 1, "item") // 1 item print sprintf$("% %p", 3, "item") // 3 items

The bare % format is a general substitution marker. It is not limited to one data type.

The %m format is commonly used for comma-separated numeric output, especially money-style output.

The %w format outputs the written-in-words version of a number, useful for check-writing and business documents.

Input from the User

input "Enter your name": name$ // prompts, reads string or number line input "Enter a sentence": sentence$ // reads entire line including spaces

Use line input when the input may contain spaces or commas. Use input for simple values.

Additional Built-In Idioms AIs Often Miss

Several small built-in routines and statements are common in real Sheerpower programs. AI models often invent mainstream-language substitutes for them.

Delimited string parsing

Use element$() and elements() for common delimited string work. Do not invent split().

csv$ = "red,green,blue" count = elements(csv$, ",") first$ = element$(csv$, 1, ",") second$ = element$(csv$, 2, ",")

Cluster row count

Use size() to get the number of rows in a cluster.

total_orders = size(orders)

String conversion

Use str$() to convert a number to a string. In Sheerpower, str$() does not add leading spaces.

msg$ = "Total: " + str$(total)

Operating system commands

Use pass to run an operating system command.

pass "dir > listing.txt" print "Exit status: "; _integer

Routine Scoping Rules

Sheerpower has four routine scopes. Generating the wrong scope is a common AI error, especially confusing local and private.

routine name // global -- accessible from anywhere in the program private routine name // module-level -- accessible only within this file scoped routine name // block-scoped -- accessible only within its enclosing routine local routine name // shares the parent routine's variable scope entirely

Sheerpower has no user-defined functions that return values. Instead, it has routines, each of which can return up to 16 values. Sheerpower has many dozens of built-in functions.

Problem: AI models use private when they mean local, or generate a with clause on a local routine that shares the parent's scope.

Solution: A local routine sees all of the parent routine's variables directly. It does not need parameters for data the parent already has. A private routine is isolated and must receive data through parameters.

Efficiency: Local routines avoid parameter overhead when decomposing a large routine into named steps.

Takeaway: If the sub-routine needs to read or write the parent's variables directly, use local. If it is a standalone reusable unit, use private or routine.
private routine process_invoice with inv total = 0 local validate_line_items local apply_discounts local format_output end routine local routine validate_line_items // sees inv, total directly from process_invoice's scope for each inv if inv->qty < 0 then inv->qty = 0 next inv end routine local routine apply_discounts if total > 10_000 then total = total * 0.95 end routine local routine format_output print "Invoice total: "; sprintf$("$%.2m", total) end routine

Unique IDs

Whenever you need a unique ID, use the _GID$ special variable. It returns a 30-character, browser-safe identifier that combines a date stamp and a unique ID. The result is both globally unique and sortable by creation date.

Because _gid$ includes a universally unique identifier, two instances of the same handler running simultaneously will never produce the same value, even when running on different systems. This eliminates the need for counters, sequence generators, or inter-process coordination.

add table todos todos(id) = _gid$ // globally unique, generated locally todos(status) = 'open' todos(priority) = priority$ todos(description) = desc$ todos(last_datetime) = fulltime$ end add

Exception Handlers

Only wrap code in a when exception in block when you intend to handle the error differently than Sheerpower would on its own. Sheerpower already stops on unhandled exceptions and automatically reports the error type, description, call stack, and source location.

A handler earns its place only when it does something Sheerpower's automatic crash report cannot — such as retrying with a fallback, logging before continuing, or allowing the program to recover and keep running.

No handler needed:
cluster input name '@fruits.csv', headers 1: fruits
Handler earns its place:
when exception in
  cluster input name '@fruits.csv', headers 1: fruits
use
  if extype = exceptiontype('filenotfound') then
    cluster input name '@fruits_default.csv', headers 1: fruits
  else
    stop
  end if
end when
Takeaway: A use block that only prints extext$ and stops gives the user less information than Sheerpower's automatic crash report. Delete it and let Sheerpower handle it.

Routine Ordering — Major to Minor

Order routines so that every routine appears before the routines it calls. The main logic area comes first, then the high-level routines it calls, then the lower-level routines those call, and so on down to leaf routines at the bottom.

Think of it as a newspaper article — headline first, detail later. A reader should be able to start at the top and follow the logic downward without ever needing to jump back up.

// Correct order -- each routine appears before what it calls routine process_orders // high-level: called from main routine validate_order // mid-level: called by process_orders routine save_orders // mid-level: called by process_orders routine format_order_row // low-level: called by save_orders
Problem: Routines written in the order they were created force readers to jump back and forth to follow the logic.

Solution: Order routines top-down. High-level orchestrating routines first, helpers and infrastructure last.

Efficiency: In a large application this makes the file structure encode the call graph. You always know where to look, and you always understand the context of a routine before you reach its implementation.

Takeaway: Before writing a routine, confirm that the routines which call it have already appeared earlier in the file.

CGI Web Handler Pattern

Sheerpower web applications commonly use a CGI-style handler pattern. This is not like Flask, Express, PHP, or browser-side JavaScript. Do not invent a web framework pattern from another language.

The common Sheerpower pattern is:

  • Open the CGI channel with open file cgi://.
  • Read request input with line input #cgi_ch.
  • Use getsymbol$() to read submitted values.
  • Use [[%spscript]] templates for generated output.
Problem: AI models have little or no training data for Sheerpower web handlers. They may invent routes, decorators, callbacks, request objects, JSON frameworks, or server APIs from other languages.

Solution: Use the Sheerpower CGI handler idiom shown in the relevant web tutorials and existing examples. Do not invent an Express-style, Flask-style, or PHP-style structure.

Efficiency: The CGI channel and template pattern keep request handling simple, direct, and easy to validate with the compiler.

Takeaway: For Sheerpower web code, follow the cgi://, line input, getsymbol$(), and [[%spscript]] pattern.

Pattern reminder

// CGI web handler pattern -- confirm details against the web tutorial open file cgi_ch: name "cgi://", access input line input #cgi_ch: request$ action$ = getsymbol$("action") // Use [[%spscript]] templates for generated web output.

Before generating a full Sheerpower web app, re-read the relevant web tutorial or a working web application. This pattern is a major Sheerpower idiom and should not be guessed from other languages.

Sheerpower Compiler Lifecycle

To write correct and efficient Sheerpower programs, it is important to understand how the compiler processes source code. The lifecycle is simple, deterministic, and designed for both speed and reliability.

Problem:
Many developers assume a traditional multi-phase compiler with separate analysis, optimization, and linking stages. This leads to incorrect mental models, especially when reasoning about forward references, performance, and error behavior.

Solution:
Sheerpower uses a streamlined compilation model with four key stages: directive processing, incremental super-p-code generation, back-patching, and virtual machine execution.

Efficiency:
Because code is emitted as it is parsed, compilation is extremely fast. The final back-patching step resolves forward references without requiring multiple full passes or complex linking stages.

Takeaway:
Think of Sheerpower as a single-pass compiler with a lightweight fix-up phase. This mental model explains both its speed and its predictable behavior.

Compilation Stages

1. Directive Processing

Before compilation begins, directives such as %include, %debug, and related settings are processed. This stage determines which source files are merged and which compile-time behaviors are enabled.

The result is a fully assembled source stream that the compiler will process as a single, continuous program.

2. Incremental Super-P-Code Generation

As the compiler parses each statement, it immediately generates intermediate instructions, called super-p-code. There is no delayed code generation phase and no separate intermediate representation tree.

Problem:
Traditional virtual machines execute many small, low-level instructions, which increases interpretation overhead and reduces performance.

Solution:
Sheerpower uses super-p-code, where each instruction represents a higher-level operation, for example a full expression evaluation or data movement, rather than a single primitive step.

Efficiency:
By combining multiple low-level operations into a single instruction, the VM executes fewer steps, reducing dispatch overhead and improving runtime speed.

Takeaway:
Super-p-code is a "super-instruction" model: fewer, richer instructions that execute more work per step, making the VM both fast and predictable.

This direct emission model is a key reason Sheerpower can compile very large codebases in extremely short timeframes.

3. Back-Patching

After the initial pass, the compiler performs a fix-up phase known as back-patching. During this step, unresolved addresses are filled in for:

  • Routine calls made before the routine definition
  • Forward-referenced labels
  • Loop back-edges and control flow targets

This allows developers to write code in a natural top-down style without needing to predeclare or reorder definitions.

4. VM Execution

The finalized super-p-code is executed by the Sheerpower Virtual Machine. The VM uses highly optimized super-instructions to deliver consistent and predictable performance across platforms.

Because execution is handled by the VM, behavior remains stable and portable, independent of the underlying operating system.

Pre-Flight Check for Generated Code

Before submitting generated Sheerpower code, run through this checklist mentally:

  • No call keyword anywhere?
  • Routine invocations use with and returning?
  • Every block has a matching end ___ terminator?
  • For loops close with next varname — not end for?
  • Boolean variables end with ??
  • String variables end with $?
  • Loop restart uses repeat do for do loops or iterate for for for loops — not continue?
  • Loop exit uses exit do or exit for — not break?
  • Early routine exit uses exit routine — not return?
  • Exception handler uses retry or continue — not return?
  • for each loops access fields as clustername->field$?
  • collect cluster appears before every for each?
  • Every select case includes case else?
  • No throw, raise, catch, new, return, break, or end for?
  • VIEW clauses use target INTO source, PIECE delimiter, MATCH index?
  • Use VAL() first when parsing numbers from text?
  • Use element$() or elements() for delimited strings — not split()?
  • Use findrow() for single-row lookup instead of scanning a whole cluster?
  • Use size() for cluster row counts?
  • Use str$() for number-to-string conversion?
  • Use pass for operating system commands?
  • Use Sheerpower sprintf$() formats such as %, %p, %m, and %w?
  • CGI web handlers follow the cgi://, line input, getsymbol$(), and [[%spscript]] pattern?
  • Cluster routine parameters use root name only — no colon syntax?
  • No exception handler whose only action is print + stop?
  • Routines ordered major to minor — callers before the routines they call?
  • String literals have no escape sequences. "\n" is two characters: "\" and "n".

Vibe Coding Workflow: One Edit, One Compile, One Test

Vibe coding works best when the feedback loop is short. In Sheerpower, there is no reason to make a large batch of changes before checking the result. The compiler is fast enough that every meaningful code change should be followed immediately by validation.

Problem:
AI-generated code can contain small mistakes: a misspelled variable, a missing terminator, an incomplete statement, or a routine name that does not match the source. If many changes are made before compiling, these small mistakes become harder to isolate.

Solution:
Use a tight cycle: make one change, compile, read the result, fix the first error, and compile again. Do not guess blindly. Always read the compiler message and the source line it points to.

Efficiency:
Sheerpower compiles very quickly, so frequent validation is not a burden. It is the normal workflow. One edit followed by one compile keeps the AI, the programmer, and the source code aligned.

Takeaway:
For Sheerpower vibe coding, the rule is simple: one edit, one compile, one test. Keep the loop tight.

Compile After Every Code Change

After each code change, compile and validate immediately:

sp4gl "nutrition_lookup_web.spsrc" /validate /build | Out-File -Encoding utf8 "nutrition_lookup_build.txt"

Always use PowerShell for this workflow, not bash. Bash can alter or mangle the line-delimited compiler output. The sp4gl command is expected to be on the system path, so a full path is not needed.

Use a build-output filename that matches the program name. For example, if the source file is:

weather_web.spsrc

then the build output should be:

weather_build.txt

This keeps build results easy to find and avoids overwriting results from other programs.

Check the Build Result

After compiling, check the exit code. If the build failed, read the build output:

sp4gl "weather_web.spsrc" /validate /build | Out-File -Encoding utf8 "weather_build.txt" if ($LASTEXITCODE -eq 0) { Write-Output "Clean build" } else { Get-Content "weather_build.txt" }

The build exit codes are:

  • 0 — clean build
  • 1 — compile error

A clean build looks like this:

$info |Build of C:\path\to\weather_web.spsrc $info |Generated 1K pcodes from 289 lines (28900/sec). $info | **** Clean build ****

When the Compile Fails

Compiler error lines follow this format:

$error |C:\path\to\file.spsrc |42 |7 |Unknown variable: totl_foods

The fields are:

  • filepath
  • line number
  • column number
  • error message

When a compile fails, follow this process:

  1. Read the build output and identify the first error.
  2. Read the source file at the reported line number.
  3. Also read a few lines before and after the reported line.
  4. Understand the problem from the error message and the nearby code.
  5. Fix the source file.
  6. Recompile and check the exit code again.

If there are multiple errors, focus on the first one. Later errors are often caused by the first error.

Do not guess at fixes blindly. The error message plus the surrounding source code is usually enough to show what went wrong.

For AI-assisted coding, never invent a fix based only on the error message. First inspect the source line, nearby lines, and the related variable or routine names. Then make the smallest correction that directly explains the compiler error.

Common Compile Errors

Error message Typical cause
Unknown variable Typo in a variable name
Unexpected end of statement Missing closing quote, parenthesis, or keyword
Expected end if Mismatched block structure, such as an if without end if
Unknown routine Typo in a routine name, or routine defined after stop

Example: Full Cycle with a Small Program

The following example shows the complete cycle: write, compile, fail, read the error, fix the source, recompile, run, and verify.

Step 1 — write the program:

// Hello World Example open file out_ch: name "@hello_world_result.txt", access output message$ = "Hello, world!" print #out_ch: mesage$ close #out_ch

Step 2 — compile the program:

sp4gl "hello_world.spsrc" /validate /build | Out-File -Encoding utf8 "hello_world_build.txt"

The exit code is 1. The build output contains:

$info |Build of C:\path\to\hello_world.spsrc $error |C:\path\to\hello_world.spsrc |5 |7 |Unknown variable: mesage$ $info | **** 1 error ****

Step 3 — read the source at line 5:

2 open file out_ch: name "@hello_world_result.txt", access output 3 message$ = "Hello, world!" 4 5 print #out_ch: mesage$ 6 close #out_ch

The problem is that mesage$ is misspelled. The variable created on line 3 is named message$. The fix is to use the same variable name in the print statement:

print #out_ch: message$

Step 4 — recompile. The build now succeeds:

$info |Build of C:\path\to\hello_world.spsrc $info |Generated 1K pcodes from 5 lines (5000/sec). $info | **** Clean build ****

Step 5 — run and verify:

sp4gl "hello_world.spsrc"

Then read hello_world_result.txt:

Hello, world!

The output is correct. The cycle is complete.

Testing Web Programs

After a clean build, test web programs in a browser. The compiler verifies code correctness, but only the browser reveals user-interface issues such as wrong layout, missing data, broken buttons, or incorrect error messages.

Most web programs begin by making sure the SPINS web server is running:

pass 'sp4gl ' + fileinfo$('@spins_startup.spsrc')

To run a web program:

sp4gl "nutrition_lookup_web.spsrc"

The program will print a URL to its GUI console, typically:

Nutrition Lookup ready. 7731 foods loaded. go to http://localhost/nutrition_lookup.html

Open that URL in a browser and test the main workflow and edge cases:

  • Does the page load correctly?
  • Do buttons and inputs work?
  • Does the data display correctly?
  • Do error states show the right messages?

The Vibe Coding Cycle

The full vibe coding cycle is:

  1. Make a change to the .spsrc file.
  2. Compile with /validate /build.
  3. Check the exit code.
  4. If the build fails, read the error, read the source line, fix the source, and recompile.
  5. If the build succeeds, test the output.
  6. For console programs, run the program and read the output.
  7. For web programs, run the program and test it in the browser.
  8. Repeat for each change.

One edit, one compile, one test. Keep the loop tight.


(Show/Hide Key Takeaways)
Hide Description

    

       


      

Enter or modify the code below, and then click on RUN

Looking for the full power of Sheerpower?
Check out the Sheerpower website. Free to download. Free to use.