@@ -65,271 +65,18 @@ vm.call("onStart", &[]).unwrap(); // call any top-level functi
6565
6666---
6767
68- ## Quick Start
69-
70- Add to your ` Cargo.toml ` :
71-
72- ``` toml
73- [dependencies ]
74- writ = " 0.1"
75- ```
76-
77- Or from git:
68+ ## Installation
7869
7970``` toml
8071[dependencies ]
8172writ = { git = " https://github.com/forge18/writ" }
8273```
8374
84- ``` rust
85- use writ :: Writ ;
86-
87- fn main () {
88- let mut vm = Writ :: new ();
89-
90- // Run a script inline
91- let result = vm . run (" return 1 + 2" ). unwrap ();
92- println! (" {result}" ); // 3
93-
94- // Register a host function
95- vm . register_host_fn (
96- " damage" ,
97- vec! [writ :: Type :: Float , writ :: Type :: Float ],
98- writ :: Type :: Float ,
99- writ :: fn2 (| hp : f64 , amount : f64 | -> Result <f64 , String > {
100- Ok (max (hp - amount , 0.0 ))
101- }),
102- );
103-
104- // Call a function defined in a script
105- vm . run (" func double(n: int) -> int { return n * 2 }" ). unwrap ();
106- let result = vm . call (" double" , & [writ :: Value :: I32 (21 )]). unwrap ();
107- println! (" {result}" ); // 42
108- }
109- ```
110-
11175---
11276
113- ## Language
114-
115- ### Variables
116-
117- ``` writ
118- const MAX_HEALTH = 100.0 // compile-time constant
119- let name = "Hero" // immutable at runtime
120- var health = 100.0 // mutable
121- ```
122-
123- ### Functions
124-
125- ``` writ
126- func takeDamage(amount: float) -> float {
127- return max(health - amount, 0.0)
128- }
129-
130- // Lambda
131- let double = (x: int) => x * 2
132- ```
133-
134- ### Structs
135-
136- Value types, copied on assignment.
137-
138- ``` writ
139- struct Vec2 {
140- x: float
141- y: float
142-
143- func length() -> float {
144- return sqrt(x * x + y * y)
145- }
146- }
147-
148- let v = Vec2(x: 3.0, y: 4.0)
149- print(v.length()) // 5.0
150- ```
151-
152- ### Classes
153-
154- Reference types with single inheritance and multiple traits.
155-
156- ``` writ
157- class Entity {
158- public id: int
159- public name: string
160- }
161-
162- class Player extends Entity {
163- public health: float = 100.0
164- set(value) { field = clamp(value, 0.0, 100.0) }
165-
166- public func takeDamage(amount: float) {
167- health -= amount
168- }
169- }
170- ```
171-
172- ### Control flow
173-
174- ``` writ
175- // if / else
176- if health <= 0 {
177- die()
178- } else if health < 20 {
179- playLowHealthSound()
180- }
181-
182- // for loop
183- for item in inventory {
184- print(item.name)
185- }
186-
187- // while
188- while health > 0 {
189- tick()
190- }
191-
192- // Pattern matching
193- when result {
194- is Success(value) => print(value)
195- is Error(msg) => print("Error: " .. msg)
196- }
197- ```
198-
199- ### Optionals and Results
200-
201- ``` writ
202- let target: Optional<Player> // may be absent
203-
204- // Safe access
205- let hp = target?.health ?? 0.0
206-
207- // Result propagation
208- func load(path: string) -> Result<Data> {
209- let raw = readFile(path)? // propagates error
210- return Success(parse(raw))
211- }
212- ```
213-
214- ### Coroutines
215-
216- ``` writ
217- func countdown(from: int) {
218- var n = from
219- while n > 0 {
220- print(n)
221- yield seconds(1.0)
222- n -= 1
223- }
224- }
225-
226- start countdown(from: 3) // non-blocking, runs across ticks
227- ```
228-
229- ---
230-
231- ## Embedding (detailed)
232-
233- ### Registering host types
234-
235- Implement ` WritObject ` on any Rust struct to expose it to scripts:
236-
237- ``` rust
238- use writ :: {WritObject , Value };
239-
240- struct Player { name : String , health : f32 }
241-
242- impl WritObject for Player {
243- fn type_name (& self ) -> & str { " Player" }
244-
245- fn get_field (& self , name : & str ) -> Result <Value , String > {
246- match name {
247- " name" => Ok (Value :: Str (self . name. clone (). into ())),
248- " health" => Ok (Value :: F32 (self . health)),
249- _ => Err (format! (" no field '{name}'" )),
250- }
251- }
252-
253- fn set_field (& mut self , name : & str , value : Value ) -> Result <(), String > {
254- match name {
255- " health" => { self . health = value . as_f64 () as f32 ; Ok (()) }
256- _ => Err (format! (" no field '{name}'" )),
257- }
258- }
259-
260- fn call_method (& mut self , name : & str , _args : & [Value ]) -> Result <Value , String > {
261- match name {
262- " greet" => Ok (Value :: Str (format! (" I'm {}!" , self . name). into ())),
263- _ => Err (format! (" no method '{name}'" )),
264- }
265- }
266-
267- fn as_any (& self ) -> & dyn std :: any :: Any { self }
268- }
269- ```
270-
271- Register a factory so scripts can construct instances:
272-
273- ``` rust
274- vm . register_type (" Player" , | args | {
275- let name = args [0 ]. as_str (). to_string ();
276- Ok (Box :: new (Player { name , health : 100.0 }))
277- });
278- ```
279-
280- ### Loading files
281-
282- ``` rust
283- // Load a file — top-level code runs, functions become callable
284- vm . load (" scripts/combat.writ" ). unwrap ();
285-
286- // Call a function defined in the file
287- let result = vm . call (" calculateDamage" , & [Value :: F32 (50.0 )]). unwrap ();
288-
289- // Hot-reload during development — swaps bytecode, preserves VM state
290- vm . reload (" scripts/combat.writ" ). unwrap ();
291- ```
292-
293- ### Coroutines
294-
295- ``` rust
296- // Tick the coroutine scheduler each frame
297- fn update (vm : & mut Writ , delta : f64 ) {
298- vm . tick (delta ). unwrap ();
299- }
300-
301- // When a game object is destroyed, clean up its coroutines
302- fn on_destroy (vm : & mut Writ , entity_id : u64 ) {
303- vm . cancel_coroutines_for_owner (entity_id );
304- }
305- ```
306-
307- ### Sandboxing
308-
309- ``` rust
310- let mut vm = Writ :: new ();
311-
312- // Limit script execution time
313- vm . set_instruction_limit (1_000_000 );
314-
315- // Block entire stdlib modules
316- vm . disable_module (" io" );
317- vm . disable_module (" noise" );
318- ```
319-
320- ---
321-
322- ## Optional Features
323-
324- ``` toml
325- [dependencies ]
326- writ = { version = " 0.1" , features = [" debug-hooks" ] }
327- ```
77+ ## Documentation
32878
329- | Feature | Description |
330- | ---| ---|
331- | ` debug-hooks ` | Breakpoints, line hooks, call/return hooks |
332- | ` mobile-aosoa ` | AoSoA memory layout for bulk entity operations |
79+ ** [ forge18.github.io/writ] ( https://forge18.github.io/writ ) ** — language reference, embedding guide, examples, and stdlib docs.
33380
33481---
33582
0 commit comments