Skip to content

Diagnose reserved BrightScript builtins used as values#1697

Open
chrisdp wants to merge 4 commits intomasterfrom
feature/diagnose-call-only-builtins
Open

Diagnose reserved BrightScript builtins used as values#1697
chrisdp wants to merge 4 commits intomasterfrom
feature/diagnose-call-only-builtins

Conversation

@chrisdp
Copy link
Copy Markdown
Contributor

@chrisdp chrisdp commented May 3, 2026

Summary

Adds a new diagnostic (reservedBuiltinUsedAsValue, code 1147) that fires when a reserved call-only BrightScript builtin appears in any non-call position. These builtins parse cleanly today but produce a device compile error (Syntax Error. Builtin function call expected, &h9d, or generic Syntax Error &h02 for some).

Builtins covered:

  • box, createobject, eval, getglobalaa
  • getlastruncompileerror, getlastrunruntimeerror
  • objfun, pos, run, tab, type

Before / after

Code Before After
x = ObjFun (no diagnostic — broke at device compile time) 'ObjFun' is a reserved builtin and can only be used as a function call (e.g. 'ObjFun(...)')
x = type (no diagnostic) same shape
x = eval (no diagnostic) same shape
print foo(Box, 2) (no diagnostic) flagged
ObjFun(), type(123), Box(1), eval(...) etc. (no diagnostic) unchanged — call sites are not flagged
m.type = 1, { type: 1 } (no diagnostic) unchanged — property access and AA keys not flagged
type Name = ... (BrighterScript type alias) (no diagnostic) unchanged — different parse path

Implementation

Why these specific builtins

Each was tested on a Roku device by writing the various forms (x = Foo, Foo(...), m.Foo = 1, { Foo: 1 }, function f(Foo)) and observing whether each form was a device compile error, runtime error, or successful execution. The 11 names above are the set where non-call usage is a hard compile error on device. eval is included because referencing it as a value has always been a compile error across firmware versions; its separate deprecation/removal lifecycle for call sites is handled in #1698.

Test plan

  • npm test — 2806 passing, 0 failing
  • npm run lint — clean
  • Per-builtin RHS-read flag tests + canonical-call no-flag tests (including eval)
  • Per-builtin parameter-name regression tests (existing 1045 already covers these)
  • Property-access / AA-key / BrighterScript-type-alias / case-insensitivity tests
  • Existing type statement regression test updated to expect the new diagnostic for return type

🤖 Generated with Claude Code

chrisdp added 2 commits May 3, 2026 11:31
Adds a new diagnostic (`reservedBuiltinUsedAsValue`, code 1147) that
fires when a reserved call-only BrightScript builtin appears in any
non-call position. These builtins compile cleanly today in the
brighterscript parser but produce a device compile error
(typically `Syntax Error. Builtin function call expected`, hex &h9d,
or `Syntax Error` &h02 depending on the builtin).

Builtins covered (all device-verified):
- box, createobject, getglobalaa
- getlastruncompileerror, getlastrunruntimeerror
- objfun, pos, run, tab, type

The check fires from `primary()` after an identifier match, gated on
`peek().kind !== LeftParen` so canonical call sites (e.g. `type(x)`,
`Box(1)`, `CreateObject("roSGNode", "Node")`) remain clean. Property
access (`m.type = 1`) and AA-literal keys (`{ type: 1 }`) are not
affected because they use different parse paths. BrighterScript's
`type Name = ...` statement is also unaffected.

Adds 38 tests:
- per-builtin RHS-read flag + canonical-call no-flag pairs (16)
- per-builtin parameter-name 1045 regression tests (10)
- ObjFun/type-specific edge cases: passed-as-arg, property access,
  AA-keys, type-statement, case-insensitivity (12)

`Eval` is intentionally excluded from this set. Its compile error
(&h90 RSG 1.2 deprecation) is a different concern and merits a
separate, more pointed diagnostic.
eval is a call-only builtin like the others here — referencing it as a
value (`x = eval`, etc.) is a device compile error.
Comment thread src/lexer/TokenKind.ts Outdated
Comment thread src/parser/Parser.ts Outdated
chrisdp and others added 2 commits May 5, 2026 16:06
Rename CallOnlyBuiltins to UnreferencableBuiltins and move the value-read
check from the parser into BrsFileValidator so plugin-injected AST nodes
are also caught.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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.

2 participants