Skip to content

Compiler: $EXTERN C-symbol aliasing + shared string-expr dispatch - #4

Merged
evvaletov merged 1 commit into
mainfrom
feat/extern-followups
Jun 13, 2026
Merged

Compiler: $EXTERN C-symbol aliasing + shared string-expr dispatch#4
evvaletov merged 1 commit into
mainfrom
feat/extern-followups

Conversation

@evvaletov

@evvaletov evvaletov commented Jun 13, 2026

Copy link
Copy Markdown
Owner

Follow-ups to the Level 2 FFI pragma (closes 8329647).

C-symbol aliasing

'$EXTERN NAME(ARGS) AS RET = c_symbol maps a BASIC-legal call name to an arbitrary C symbol (e.g. underscores like sqlite3_open), so no hand-written wrapper is needed. A new c_name field carries the emitted symbol; matching stays on the BASIC name. A malformed alias (e.g. digit-first) falls back to the BASIC name rather than emitting invalid C.

Shared string-expr dispatch

Factors the string-vs-numeric identifier detection out of PRINT into a non-consuming peek_is_string_expr() helper, reused in INSTR's start-vs-haystack heuristic and WRITE's quoting. A string-returning extern now classifies correctly in all three, and this also fixes a pre-existing case where INSTR/WRITE treated FF/FE string functions (CHR$, LEFT$, ENVIRON$, ...) as numeric.

Review-driven

A codex + agy review caught that routing a parenthesized string to the string path would loop (the string-atom emitter does not parse a leading (). That handling was dropped and the limitation documented in Known Limitations; ( falls through to numeric as elsewhere. Pragma also rejects BASIC names not starting with a letter.

Tests

tests/ffi extended with the alias, a string-extern as an INSTR haystack, and a string comparison. 63/63 compiler tests and the FFI harness pass. (Local interpreter run shows 3 unrelated sound-test failures from a missing audio sink in this session, not touched by this compiler-only change.)

Summary by CodeRabbit

  • New Features

    • Added support for naming extern calls with a BASIC-friendly alias, so string-returning externs can be used more naturally in expressions like PRINT, WRITE, INSTR, and string comparisons.
  • Bug Fixes

    • Improved validation for extern call names.
    • Fixed handling of string expressions in output and string-search operations.
  • Documentation

    • Clarified extern call naming rules, supported return-value usage, and noted a workaround for a known expression-parsing limitation.
  • Tests

    • Expanded FFI coverage with a new string-returning extern example and updated expected results.

Follow-ups to the Level 2 FFI pragma (closes 8329647).

Add an optional "= c_symbol" alias to '$EXTERN so a BASIC-legal call name
can map to an arbitrary C symbol (e.g. one with underscores like
sqlite3_open), removing the need for a hand-written wrapper. A new c_name
field carries the emitted symbol; matching stays on the BASIC name.

Factor the string-vs-numeric identifier detection out of PRINT into a
shared peek_is_string_expr() helper and reuse it in INSTR's
start-vs-haystack heuristic and WRITE's string quoting. This makes a
string-returning extern classify correctly in all three, and also fixes a
pre-existing case where INSTR and WRITE treated FF/FE string functions
(CHR$, LEFT$, ENVIRON$, ...) as numeric.

The pragma now rejects BASIC names that do not start with a letter, and a
malformed alias (e.g. digit-first) falls back to the BASIC name rather than
emitting an invalid C symbol. Tests extended (alias, string-extern in INSTR,
string comparison); 63/63 compiler tests and the FFI harness pass.
@coderabbitai

coderabbitai Bot commented Jun 13, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

This PR adds $EXTERN C-symbol aliases, stores and emits the aliased symbol name, centralizes string-expression detection for INSTR/PRINT/WRITE, extends FFI coverage with a string-returning extern, and updates documentation and roadmap notes.

Changes

FFI extern alias and string-expression flow

Layer / File(s) Summary
Parse and store extern aliases
include/analysis.h, src/analysis.c, docs/getting-started.md
extern_func_t now stores both BASIC and C symbol names, $EXTERN parsing validates BASIC call names and optional = c_symbol aliases, and the getting-started docs describe the alias syntax and string-returning extern usage.
Use aliases during code generation
src/codegen.c, docs/roadmap.md
Codegen adds peek_is_string_expr(), uses it to classify INSTR, PRINT, and WRITE operands, and emits extern calls and prototypes with c_name; the roadmap notes the current parenthesized string-expression limitation.
Exercise aliased string externs
tests/ffi/extern_demo.bas, tests/ffi/extern_lib.c, tests/ffi/expected.txt, docs/roadmap.md
The FFI demo adds Rev = c_rev as a string-returning extern, the C fixture implements c_rev, expected output gains INSTR and comparison results, and roadmap text updates shipped/planned entries.

Sequence Diagram(s)

sequenceDiagram
  participant BASIC as BASIC program
  participant Analysis as parse_extern_pragma
  participant Codegen as code generator
  participant CLib as c_rev

  BASIC->>Analysis: declare $EXTERN Rev = c_rev AS STRING
  Analysis-->>Codegen: extern_func_t{name="Rev", c_name="c_rev"}
  BASIC->>Codegen: compile Rev("abXc") in INSTR / PRINT / comparison
  Codegen->>CLib: emit call to c_rev(...)
  CLib-->>Codegen: reversed string
  Codegen-->>BASIC: use string result in generated expression
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 I found a name beneath a name,
A BASIC hop, a C-side frame.
Rev now flips the string just right,
Through PRINT and INSTR into light.
Little aliases nibble and play—
Carrots for the FFI today.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely summarizes the two main changes: C-symbol aliasing for $EXTERN and the shared string-expression dispatch logic refactoring.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/extern-followups

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@evvaletov
evvaletov merged commit 7627185 into main Jun 13, 2026
2 of 3 checks passed
@evvaletov
evvaletov deleted the feat/extern-followups branch June 13, 2026 23:23
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