Skip to content

Commit ecdaffc

Browse files
committed
v3: keep fastc AST-free
1 parent f9810de commit ecdaffc

28 files changed

Lines changed: 483 additions & 65835 deletions

cmd/v/macos_v3_args.c.v

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ fn is_macos_v3_compiler_bootstrap(normalized_path string) bool {
4444
// invocation to the embedded V3 compiler. It gates on `-old-compiler`
4545
// precedence, options/modes V3 cannot honor yet, and whether the command is an
4646
// actual compilation command (never `test` or external tools). Compiler bootstrap
47-
// targets normally stay on V1, but explicit `-b fastc` owns those targets too: its
48-
// complete lane uses V3's checked frontend and full fastc generator for the compiler source.
47+
// targets normally stay on V1, but explicit `-b fastc` still routes to V3 so its
48+
// AST-free parser can report unsupported source instead of silently selecting V1.
4949
// Both the Darwin dispatcher (where it overrides the default heuristic) and the
5050
// non-macOS dispatcher (where it is the sole gate) rely on it, so it must stay
5151
// platform neutral.
@@ -59,7 +59,7 @@ fn macos_v3_force_requested(command string, prefs &pref.Preferences) bool {
5959
}
6060
if prefs.autofree && prefs.is_run && !macos_v3_fastc_requested(prefs) {
6161
// V1 still owns the established `v -autofree run ...` orchestration.
62-
// FastC promotes autofree programs to its checked C lane.
62+
// Explicit FastC stays on V3 and reports this mode as unsupported.
6363
return false
6464
}
6565
if prefs.path == '' || command == 'test' || macos_v3_non_compilation_command(command)
@@ -99,8 +99,8 @@ fn macos_v3_fastc_incompatibility(prefs &pref.Preferences) ?string {
9999
// macos_v3_test_ownership_uses_v1 keeps ownership/autofree test binaries on
100100
// V1. vtest marks its per-file compilations with `-skip-running`; compiling an
101101
// autofree test through the ownership-enabled V3 tool can consume far more
102-
// memory than the test itself. Direct V3 ownership builds remain available;
103-
// fastc uses the same checked ownership lane as the C backend.
102+
// memory than the test itself. Explicit FastC is never diverted to an AST-based
103+
// ownership compiler; its parser reports the unsupported mode itself.
104104
fn macos_v3_test_ownership_uses_v1(prefs &pref.Preferences, args []string) bool {
105105
return prefs.skip_running && !macos_v3_fastc_requested(prefs)
106106
&& (prefs.autofree || '-ownership' in args)

cmd/v/macos_v3_darwin.c.v

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ fn is_macos_v3_relevant_command(command string, prefs &pref.Preferences) bool {
9191
if prefs.autofree && prefs.is_run && !macos_v3_fastc_requested(prefs) {
9292
// V1 still owns the established `v -autofree run ...` orchestration.
9393
// Direct autofree builds are selected earlier by the ownership dispatcher.
94-
// FastC promotes autofree programs to its checked C lane.
94+
// Explicit FastC stays on V3 and reports this mode as unsupported.
9595
return false
9696
}
9797
if command == 'test' {

cmd/v/v.v

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,11 @@ fn invoke_help_and_exit(remaining []string) {
219219
fn maybe_delegate_to_ownership(command string, prefs &pref.Preferences, merged_args []string) {
220220
is_ownership := '-ownership' in merged_args
221221
is_autofree := prefs.autofree
222+
if prefs.is_fastc {
223+
// FastC owns its whole invocation and must never launch the AST-based
224+
// ownership compiler. Its direct parser reports unsupported modes.
225+
return
226+
}
222227
$if macos {
223228
if macos_v3_test_ownership_uses_v1(prefs, merged_args) {
224229
return

vlib/v/help/build/build.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ NB: the build flags are shared with the run command too:
4343
Specifies the backend that will be used for building the executable.
4444
Current list of supported backends:
4545
* `c` (default) - V outputs C source code, which is then passed to a C compiler.
46-
* `fastc` - V outputs C with the experimental FastC backend.
46+
* `fastc` - V parses supported source directly to C without an AST.
4747
* `go` - V outputs Go source code, which is then passed to a Go compiler.
4848
* `js` - V outputs JS source code which can be passed to NodeJS to be ran.
4949
* `js_browser` - V outputs JS source code ready for the browser.

vlib/v3/README.md

Lines changed: 27 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -90,46 +90,32 @@ physical footprint immediately after RSS.
9090

9191
## Fast C backend
9292

93-
`-b fastc` selects the embedded V3 driver and a speculative single-file backend for the shortest
94-
edit-run cycle. It scans the source once and emits GNU C while consuming tokens. This path does
95-
not create a flat AST itself. Before accepting its speculative output, the driver runs the normal
96-
parser and semantic checker over the V source, then asks bundled TinyCC to validate the complete
97-
translation unit. A successful direct build skips transform, type annotation, and mark-used.
98-
99-
FastC's direct lane currently emits primitive functions and parameters, inferred local
100-
declarations, ordinary expressions, `if`/`else`, and condition, C-style, infinite, and
101-
integer-range `for` loops. GNU
102-
`typeof` carries `:=` declarations into C without V type inference. Unsupported syntax promotes
103-
the source to fastc's complete lane, which uses the parser, checker, transformer, and mark-used
104-
pass, then emits C with its own `v3.gen.fastc.FlatGen` backend. That backend is a full fork of the
105-
V3 C generator rather than an alias or a runtime switch to `v3.gen.c`. A TinyCC error is also
106-
discarded and the original V source is compiled by the checked fastc lane, so the user receives V
107-
parser or type-checker diagnostics rather than a speculative C diagnostic. The complete lane has
108-
the same language and ownership/autofree coverage as the C backend. A successfully compiled `run`
109-
program keeps its exit status and is never retried.
110-
111-
Integer-range bounds in the direct lane are evaluated once, from left to right. Float printing,
112-
C-string and embedded-NUL string literals, assertions, `sizeof`, comparison/logical, shift,
113-
division, and modulo expressions, and functions with narrow integer signatures are promoted to
114-
the complete lane. Expressions containing decimal `2147483648`, including composite minimum-`int`
115-
expressions, are promoted as well, as are hexadecimal and binary literals above the signed 32-bit
116-
range. Parallel assignments and indexing expressions are promoted, preserving
117-
simultaneous assignment, V layouts, inferred types, element types, and bounds checks. Together these
118-
promotions preserve V's formatting, byte-length, diagnostics, boolean typing, integer-wrapping,
119-
safe-shift, and zero-divisor behavior instead of relying on incompatible raw C semantics.
120-
121-
The direct path is limited to host-target, non-debug, non-production, non-test, non-shared
122-
single-file builds. Compiler/self-host, strict C, and other non-direct modes enter the complete lane
123-
before source scanning.
124-
`-o file.c` emits the standalone fast C translation unit when the direct lane supports the input;
125-
otherwise it emits the complete `v3.gen.fastc` translation unit. Direct C-only output is published
126-
only after both V semantic checking and TinyCC validation succeed.
127-
128-
`v self -b fastc` and direct compiler builds such as `v -b fastc -o v2 cmd/v` are routed to V3.
129-
Self-host builds enter fastc's complete lane directly. The checked frontend feeds the independent
130-
`v3.gen.fastc.FlatGen` implementation, so the resulting compiler supports the full V3 source tree
131-
and retains both fastc lanes for user programs, including when its output has a custom filename in
132-
the V checkout. The fastc integration test exercises five successive self-host generations.
93+
`-b fastc` selects the embedded V3 driver and its AST-free single-file parser for the shortest
94+
edit-run cycle. FastC scans the source once and emits GNU C while consuming tokens. It never invokes
95+
the flat parser, semantic checker, transformer, mark-used pass, or conventional C generator.
96+
Bundled TinyCC validates the emitted translation unit before any C file or executable is published.
97+
Unsupported V syntax and TinyCC errors are reported directly; FastC never retries through an
98+
AST-based backend.
99+
100+
FastC currently emits primitive functions and parameters, inferred local declarations, ordinary
101+
expressions, `if`/`else`, and condition, C-style, infinite, and integer-range `for` loops. GNU
102+
`typeof` carries `:=` declarations into C without V type inference. Integer-range bounds are
103+
evaluated once, from left to right. The parser also rejects mutation of immutable or unknown local
104+
names instead of relying on C's weaker assignment rules.
105+
106+
Syntax whose V semantics require type or runtime information is rejected until FastC can lower it
107+
directly. This includes float printing, C-string and embedded-NUL string literals, runes,
108+
assertions, `sizeof`, comparison/logical, shift, division, modulo, indexing, parallel assignment,
109+
mixed-precedence expressions, narrow integer signatures, oversized decimal literals, and
110+
high-bit hexadecimal or binary literals. Rejecting these constructs avoids silently applying
111+
incompatible C formatting, inference, wrapping, shift, bounds, and zero-divisor behavior.
112+
113+
FastC requires exactly one `.v` input. Executables are host-target only; `-o file.c` also permits an
114+
explicit cross target and publishes C after TinyCC validation. Production, test, shared/live,
115+
ownership/autofree, self-host, object-file, profiling/coverage, strict C, custom compiler,
116+
custom-builtin, `no_main`, translated, and REPL modes are currently rejected. Explicit FastC
117+
compiler builds still route to V3 so the FastC parser reports the unsupported input rather than
118+
silently selecting V1.
133119

134120
Generated C represents `thread` values with a typed wrapper around `pthread_t`. `spawn` and
135121
detached standard-library workers use the target's default thread stack (8 MiB on 64-bit targets
@@ -212,8 +198,7 @@ the plan and run the complete diagnostic and generation pipeline normally.
212198
## Architecture
213199

214200
```
215-
source -> fastc scanner/emitter -> TinyCC
216-
\-> on unsupported syntax or TinyCC error: normal pipeline below
201+
source -> scanner -> fastc parser/C emitter -> TinyCC
217202
218203
source + vlib/builtin -> scanner -> flat parser -> flat AST -> imports
219204
-> check -> transform -> annotate types -> markused -> gen C -> cc

0 commit comments

Comments
 (0)