Skip to content

Commit 33f1c19

Browse files
committed
Implement process argument support and add std.cli.args library
1 parent 18e22f7 commit 33f1c19

13 files changed

Lines changed: 375 additions & 2 deletions

File tree

docs/getting_started.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ cd firescript
3434

3535
Install python
3636

37+
You will need some sort of C compiler, either GCC or Clang. We recommend GCC via MSYS2 for Windows users.
38+
3739
Install [GCC via MSYS2](https://www.msys2.org/):
3840

3941
Open the MSYS2 UCRT64 terminal and run:

docs/internal/ecosystem_roadmap.md

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
# firescript Ecosystem Roadmap
2+
3+
This document defines the planned tooling and ecosystem modules around firescript.
4+
5+
It focuses on:
6+
- Build and package workflows
7+
- Standard library growth
8+
- First-party installable packages
9+
10+
It does not define language syntax or compiler internals.
11+
12+
## Ecosystem Architecture
13+
14+
The ecosystem is organized into two layers:
15+
- Standard library modules under `@firescript/std` for stable, portable APIs
16+
- Installable packages for platform-specific or fast-evolving functionality
17+
18+
This split keeps the standard library small and dependable while allowing faster iteration for external integrations.
19+
20+
## kiln
21+
22+
`kiln` is the firescript build system and package manager.
23+
24+
### Responsibilities
25+
- Project initialization and scaffolding: `kiln init`
26+
- Dependency and lockfile management: `kiln add`, `kiln update`, `kiln sync` (after `std.net`)
27+
- Build and execution workflows: `kiln build`, `kiln run`, `kiln test`
28+
- Publishing workflows: `kiln publish`
29+
30+
## Planned Libraries and Packages
31+
32+
### 1. math.linalg (standard library)
33+
Namespace: `@firescript/std.math.linalg`
34+
35+
Scope:
36+
- Vectors and matrices
37+
- Core linear algebra operations
38+
- Common decompositions needed by graphics and simulation workloads
39+
40+
### 2. io.input (standard library)
41+
Namespace: `@firescript/std.io.input`
42+
43+
Scope:
44+
- Keyboard, mouse, and gamepad event handling
45+
- Input state polling APIs
46+
- Event stream interfaces for app and game loops
47+
48+
### 3. cli.args (standard library)
49+
Namespace: `@firescript/std.cli.args`
50+
51+
Scope:
52+
- Command-line argument tokenization and parsing
53+
- Positional arguments, flags, and typed option values
54+
- Validation and help/usage text generation
55+
56+
### 4. net (standard library)
57+
Namespace: `@firescript/std.net`
58+
59+
Scope:
60+
- TCP and UDP socket primitives
61+
- Client/server connection lifecycle APIs
62+
- Address parsing and endpoint helpers
63+
64+
### 5. window (installable package)
65+
Namespace: `@firescript/window`
66+
67+
Scope:
68+
- Window creation and lifecycle
69+
- Display mode, resizing, and window event management
70+
- Cross-platform runtime integration
71+
72+
### 6. graphics (installable package)
73+
Namespace: `@firescript/graphics`
74+
75+
Scope:
76+
- Graphics API bindings
77+
- Buffers, textures, shaders, and pipeline objects
78+
- Render pass and command submission primitives
79+
80+
## Current Baseline (April 2026)
81+
82+
### Confirmed working today
83+
- Compiler pipeline and native codegen run via `python firescript/main.py <source-file>`
84+
- Import parsing and module resolution for local modules
85+
- Standard library import path resolution for `@firescript/std...`
86+
- Existing std modules for `io`, `math`, `constraints`, and `types`
87+
- Broad test coverage for language features, imports, std usage, and semantic errors
88+
89+
### Confirmed missing today
90+
- No `kiln` implementation exists in the repository
91+
- External package imports (`@user/package`) are reserved but not supported
92+
- No `@firescript/std.math.linalg` module exists yet
93+
- `std.io` currently provides printing utilities, not input APIs
94+
- No `@firescript/std.cli.args` module exists yet
95+
- No runtime/std API currently exposes raw command-line arguments (`argv`) to firescript code
96+
- No `@firescript/std.net` module exists yet
97+
- No `@firescript/window` package exists yet
98+
- No `@firescript/graphics` package exists yet
99+
- No ecosystem-specific test suites for kiln, linalg, io.input, cli.args, std.net, window, or graphics
100+
101+
## Milestone Plan With Required Work
102+
103+
### Milestone 1: std.cli.args
104+
Target outcome:
105+
- `@firescript/std.cli.args` provides a stable parser for command-line applications.
106+
107+
Work required:
108+
- Add a runtime-backed std API to read raw process arguments (`argv`) from firescript.
109+
- Define argument value representation and ordering guarantees.
110+
- Define API for parser configuration (positional args, flags, options, defaults).
111+
- Implement tokenizer/parser for argv-style inputs.
112+
- Add typed conversion helpers with clear diagnostics.
113+
- Add help and usage text formatting APIs.
114+
115+
Dependencies and blockers:
116+
- Requires runtime/compiler plumbing to expose process args into firescript.
117+
- No external package or network dependency required.
118+
119+
Tests and validation:
120+
- Add tests validating raw argv access and ordering.
121+
- Add golden tests for common argument patterns.
122+
- Add invalid tests for missing values, unknown flags, and type conversion failures.
123+
- Add matching expected output/error files.
124+
125+
### Milestone 2: kiln foundations
126+
Target outcome:
127+
- A project can be initialized and built through kiln, without network-based package installation.
128+
129+
Work required:
130+
- Define package manifest format and lockfile format.
131+
- Implement local dependency resolution (path/workspace dependencies only).
132+
- Implement deterministic lockfile generation for local dependencies.
133+
- Implement `kiln build` and `kiln run` by invoking existing compiler workflows.
134+
- Integrate `std.cli.args` as the command surface for kiln CLI parsing.
135+
- Implement install/cache layout for reproducible restores.
136+
- Add clear diagnostics for invalid manifests and version conflicts.
137+
138+
Dependencies and blockers:
139+
- Depends on `std.cli.args` for CLI parsing ergonomics and consistency.
140+
- Network-based package installation is blocked until `std.net` exists.
141+
- Registry support also depends on enabling external imports in compiler/import resolution.
142+
143+
Tests and validation:
144+
- Add end-to-end CLI tests for `init`, local `add`, local `sync`, `build`, `run`.
145+
- Add lockfile determinism tests.
146+
- Add negative tests for invalid manifest and conflict handling.
147+
148+
### Milestone 3: std.math.linalg
149+
Target outcome:
150+
- `@firescript/std.math.linalg` exists with stable core vector/matrix functionality.
151+
152+
Work required:
153+
- Add `firescript/std/math/linalg` module structure.
154+
- Implement core operations: vector/matrix construction, dot product, matrix multiply, transpose.
155+
- Define dimension-mismatch behavior and diagnostics.
156+
- Document numeric behavior and precision expectations.
157+
158+
Dependencies and blockers:
159+
- No new package manager functionality required.
160+
- Can be implemented with existing language/compiler features.
161+
162+
Tests and validation:
163+
- Add positive golden tests for vector/matrix operations.
164+
- Add invalid tests for dimension mismatch and invalid construction.
165+
- Add matching expected output/error files.
166+
167+
### Milestone 4: std.io input APIs
168+
Target outcome:
169+
- `@firescript/std.io.input` provides baseline keyboard/mouse input APIs, then gamepad support.
170+
171+
Work required:
172+
- Design input API surface for polling and event-driven patterns.
173+
- Add runtime-level input abstraction for supported platforms.
174+
- Implement input state model (pressed/released/down, cursor position, wheel).
175+
- Define behavior for focus loss, key repeat, and event ordering.
176+
177+
Dependencies and blockers:
178+
- Requires runtime and std implementation work beyond current `print/println` support.
179+
- Must keep low-level directives constrained to std internals.
180+
181+
Tests and validation:
182+
- Add contract tests for state transitions.
183+
- Add integration tests with simulated input events where available.
184+
- Add platform smoke tests with explicit unsupported-platform handling.
185+
186+
### Milestone 5: std.net
187+
Target outcome:
188+
- `@firescript/std.net` provides baseline networking primitives for socket-based applications.
189+
190+
Work required:
191+
- Define API for socket creation, bind/listen/accept, connect, send/receive, and close.
192+
- Implement address and endpoint abstractions for IPv4/IPv6 where supported.
193+
- Define blocking/non-blocking behavior and timeout semantics.
194+
- Implement consistent networking error model and diagnostics.
195+
196+
Dependencies and blockers:
197+
- Requires runtime support for cross-platform socket operations.
198+
- Must define platform-compatibility policy for unsupported features.
199+
200+
Unlocks:
201+
- Enables network-based package installation and registry sync flows in kiln.
202+
203+
Tests and validation:
204+
- Add integration tests for loopback TCP client/server communication.
205+
- Add tests for UDP send/receive behavior.
206+
- Add failure-path tests for connection errors, timeouts, and invalid endpoints.
207+
208+
### Milestone 6: @firescript/window v0
209+
Target outcome:
210+
- Installable window package opens a window and processes lifecycle/events on one backend.
211+
212+
Work required:
213+
- Implement external package import path from source to compile.
214+
- Define package metadata needed for platform-specific artifacts.
215+
- Implement window lifecycle API (create, poll events, resize, close).
216+
- Integrate package build/test flows with kiln.
217+
218+
Dependencies and blockers:
219+
- Requires external package import support (currently not supported).
220+
- Requires packaging/distribution conventions from kiln milestone.
221+
222+
Tests and validation:
223+
- Add integration tests importing and using `@firescript/window`.
224+
- Add window lifecycle smoke tests.
225+
- Add failure tests for backend init and unsupported platforms.
226+
227+
### Milestone 7: @firescript/graphics v0
228+
Target outcome:
229+
- Installable graphics package renders a minimal frame through one backend.
230+
231+
Work required:
232+
- Define graphics API surface (device, buffer, texture, shader, pipeline, pass).
233+
- Implement resource lifetime behavior aligned with firescript ownership semantics.
234+
- Implement one backend and backend abstraction boundary.
235+
- Provide a minimal sample pipeline (clear + draw triangle).
236+
237+
Dependencies and blockers:
238+
- Depends on external package support and kiln package workflows.
239+
- Depends on windowing/surface integration.
240+
241+
Tests and validation:
242+
- Add compile-time API usage tests.
243+
- Add runtime smoke tests for device init and frame submission.
244+
- Add invalid tests for resource/pipeline misuse.
245+
246+
## Status
247+
248+
Planning in progress. Core language/compiler/test infrastructure is active, while ecosystem tooling and libraries in this roadmap are mostly not implemented yet.

firescript/codegen/base.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,16 @@ def __init__(self, ast: ASTNode, source_file: Optional[str] = None):
8080
# Stack of name scopes for nested functions/blocks
8181
self.name_scope_stack: list[dict[str, str]] = [{}]
8282
# Built-in functions that shouldn't be mangled
83-
self.builtin_names = {"stdout", "drop", "syscall_open", "syscall_read", "syscall_write", "syscall_close"}
83+
self.builtin_names = {
84+
"stdout",
85+
"drop",
86+
"process_argc",
87+
"process_argv_at",
88+
"syscall_open",
89+
"syscall_read",
90+
"syscall_write",
91+
"syscall_close",
92+
}
8493

8594
# Collect class names and metadata for constructors and methods
8695
self.class_names: set[str] = set()

firescript/codegen/generator.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,8 @@ def generate(self) -> str:
115115

116116
# Only generate wrapper main() if user didn't define one
117117
if not main_function_code:
118-
main_code = "int main(void) {\n"
118+
main_code = "int main(int argc, char **argv) {\n"
119+
main_code += " firescript_set_process_args(argc, argv);\n"
119120
if main_lines:
120121
indented_body = "\n".join(
121122
" " + line for line in "\n".join(main_lines).split("\n")

firescript/codegen/generics.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ def _infer_type_args_from_call(self, func_name: str, call_node: ASTNode) -> Opti
3232
logging.debug(f"Processing arg: {arg.node_type}, name={getattr(arg, 'name', None)}, is_array={getattr(arg, 'is_array', None)}")
3333
# Try to get the type from the argument node
3434
arg_type = getattr(arg, 'return_type', None) or getattr(arg, 'var_type', None)
35+
if not arg_type and arg.node_type in (NodeTypes.EQUALITY_EXPRESSION, NodeTypes.RELATIONAL_EXPRESSION):
36+
arg_type = "bool"
37+
if not arg_type:
38+
try:
39+
arg_type = self._type_check_node(arg, self.symbol_table)
40+
except Exception:
41+
arg_type = None
3542
# Check if it's an array identifier
3643
if arg.node_type == NodeTypes.IDENTIFIER and getattr(arg, 'is_array', False):
3744
# It's an array - append []

firescript/codegen/statements.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,24 @@ def _visit(self, node: ASTNode) -> str:
506506
arg = node.children[0]
507507
arg_code = self._visit(arg)
508508
return f'printf("%s", {arg_code})'
509+
elif node.name in ("process_argc", "process_argv_at"):
510+
# Check if process args intrinsics are enabled in the file where this call is made
511+
node_file_directives = self._directives_for_node(node)
512+
if "enable_process_args" not in node_file_directives:
513+
self.report_error(
514+
CodegenError(
515+
message=(
516+
f"{node.name}() is not available. Use 'directive enable_process_args;' "
517+
"in this file to enable it."
518+
)
519+
),
520+
node
521+
)
522+
return ""
523+
if node.name == "process_argc":
524+
return "firescript_argc()"
525+
arg_code = self._visit(node.children[0])
526+
return f"firescript_argv_at({arg_code})"
509527
elif node.name == "drop":
510528
# Fixed-size arrays are copyable; drop is a no-op
511529
return "/* drop noop */"
@@ -717,6 +735,8 @@ def _visit(self, node: ASTNode) -> str:
717735
or rightNode.var_type == "string"
718736
):
719737
node.return_type = "bool"
738+
if node.name == "!=":
739+
return f"(!firescript_strcmp({left}, {right}))"
720740
return f"firescript_strcmp({left}, {right})"
721741
else:
722742
self.report_error(CodegenError(message="Cannot compare string with non-string type"), node)

firescript/enums.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,4 @@ class CompilerDirective(Enum):
4545
ENABLE_SYSCALLS = "enable_syscalls"
4646
ENABLE_DROPS = "enable_drops"
4747
ENABLE_LOWLEVEL_STDOUT = "enable_lowlevel_stdout"
48+
ENABLE_PROCESS_ARGS = "enable_process_args"

firescript/parser/base.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ class ParserBase:
5656
builtin_functions: dict[str, str] = {
5757
"stdout": "void", # requires directive enable_lowlevel_stdout
5858
"drop": "void", # requires directive enable_drops
59+
"process_argc": "int32", # requires directive enable_process_args
60+
"process_argv_at": "string", # requires directive enable_process_args
5961
"syscall_open": "SyscallResult", # requires directive enable_syscalls
6062
"syscall_read": "SyscallResult", # requires directive enable_syscalls
6163
"syscall_write": "SyscallResult", # requires directive enable_syscalls

0 commit comments

Comments
 (0)