Skip to content

feat(core): for loops via peepoJuice, plus lists - #27

Merged
ohnishant merged 4 commits into
mainfrom
feat/loops-and-lists
Aug 23, 2026
Merged

ohnishant merged 4 commits into
mainfrom
feat/loops-and-lists

Conversation

@ohnishant

Copy link
Copy Markdown
Owner

Two language features in two commits.

For loops

peepoJuice no longer means not. It opens a loop:

peepoJuice PepoG i 0. peepoLessThan i 3. peepoCookie i peepoFriendship i 1. Wokege
    peepoChat i.
Bedge

The init and step clauses are optional PepoG or peepoCookie statements; leave both out and the loop works as a while. The condition is required, so there is no accidental infinite form. Header clauses and the loop variable live in one scope for the whole loop; each body iteration gets a child scope of it.

One semantic change came with this: Environment.Set used to always write into the local scope, which meant a loop body could never update a variable declared outside it. A loop that cannot accumulate state can't do anything observable, so Set now rebinds the nearest existing binding and only creates local bindings for new names. Fresh names still stay scoped to their block (TestBlockScoping covers that).

The old not operator is removed in the same commit since peepoJuice was its keyword. #3 (prefix vs postfix) is closed as superseded; picking a replacement emote for negation is now #26.

Lists

Thinking1 and Thinking2 wrap list literals and index expressions:

PepoG xs Thinking1 3, 1, 4 Thinking2.
peepoChat xs Thinking1 0 Thinking2.   # 3

Both emotes come from towdan's set per your pick. They lex as single tokens because identifiers may now contain digits. Trade-off worth knowing: PepegaCredit5 used to lex as PepegaCredit then 5, and is now one identifier. The lexer test asserts the new behavior.

Lists nest, chained indexes dig into inner lists, indexing out of range or with a non-integer is a runtime error, and peepoMeasure accepts lists alongside strings. The playground renders both new keywords as emotes via emotefetch.

Tests

  • parser: header variants, round-trips through String(), malformed headers, unclosed brackets
  • evaluator: counting loops, while form, scoping of the loop variable, list literals including nesting, indexing chains, out-of-range and type errors, and a loop summing a list via peepoMeasure
  • lexer: digit-bearing identifiers, Thinking1/Thinking2 tokenization

go test ./..., go vet ./... and gofmt -l . are all clean.

peepoJuice now opens a loop: optional PepoG/peepoCookie init, a required
condition, an optional step clause, then a Wokege/Bedge body. With the
clauses left out it works as a while. The previous meaning (logical not,
both prefix and postfix per issue #3) is gone; a replacement keyword is
tracked separately.

Environment.Set now rebinds names found in enclosing scopes instead of
always shadowing them locally. Without this a loop body could not
accumulate into anything declared outside it, which made loops unable to
produce any observable state.
Thinking1 opens a list, Thinking2 closes it, and the same pair indexes:
xs Thinking1 0 Thinking2. Lists nest; chained index hunks dig into
inner lists. peepoMeasure now takes a list as well as a string.

Identifiers may contain digits so the new keyword names lex as single
tokens. Trade-off: PepegaCredit5 is no longer PepegaCredit followed by
5 but one identifier.

The playground picks up both emotes through emotefetch.
@github-actions

github-actions Bot commented Aug 23, 2026 •

Copy link
Copy Markdown

⚠️ Test files changed

This PR touches test code. Agents must not delete tests or remove
test cases without explicit owner approval.

before after
Test functions 40 58
Changed test files
M	cmd/evaluator/evaluator_test.go
M	cmd/lexer/lexer_test.go
M	cmd/parser/parser_test.go
M	cmd/repl/repl_test.go
M	cmd/token/token_keywords_test.go

- propagate body errors out of peepoJuice loops; a runtime error inside
  the block used to be discarded and the loop kept running
- recognize missing Thinking2 in the REPL continuation check so
  multi-line list literals keep reading instead of erroring, and make
  parseIndex emit the same wording at EOF
- route testEval through io.Discard so loop tests stop printing to the
  test log
- add README table of contents entries for Loops and Lists
Each test documents the limitation it locks in and what to flip when
the issue is fixed: identical lists comparing NOPERS (#28), index hunks
after higher-arity calls erroring with unknown expression while
zero-arity calls index fine (#29), and string indexing being rejected
(#30).
@ohnishant ohnishant changed the title for loops via peepoJuice, plus lists feat(core): for loops via peepoJuice, plus lists Aug 23, 2026
@ohnishant
ohnishant merged commit abb8ee3 into main Aug 23, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant