Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
4fa054b
0.16.3 step 1: lazy CallerFnCollector + drop globals/start (WIP)
jasisz May 6, 2026
df911fd
0.16.3 step 2: __caller_fn_count + __caller_fn_name exports + host
jasisz May 6, 2026
26fdca7
0.16.3 step 2: rustfmt fix
jasisz May 6, 2026
87a1338
0.16.3: backend bugs 1-3 — record/sum list-hash + recursive sum eq
jasisz May 6, 2026
609ae43
0.16.3: rustfmt + clippy too_many_arguments allow
jasisz May 6, 2026
06b832f
0.16.3: bug 4 + 5 — transitive eq helpers + eqref ref.cast prologue
jasisz May 6, 2026
6d80dd7
0.16.3: lift nominal eq cap for collections + transitive helper register
jasisz May 6, 2026
40eba21
0.16.3: register_transitive guard + collection seed sweep
jasisz May 6, 2026
bf521d3
0.16.3: bug F + G — Option/Result/Tuple eq + carrier dispatch
jasisz May 6, 2026
9f053a3
0.16.3: perfect hash — __hash_<X> helpers + dispatch
jasisz May 6, 2026
1e7726c
0.16.3: Map<K,V> with carrier K — Option/Result/Tuple as map keys
jasisz May 6, 2026
cf66147
0.16.3: rustfmt fix
jasisz May 6, 2026
d9dec4f
0.16.3: List/Vector elements + Map keys close the eq/hash matrix
jasisz May 6, 2026
f97b558
0.16.3: Map structural eq + commutative hash + literal discovery
jasisz May 6, 2026
40fbb55
0.17 sweep [1/4]: drop Map.empty() — use {} literal
jasisz May 6, 2026
9066b09
0.17 sweep [2/4]: drop unreachable builtin aliases
jasisz May 6, 2026
7ef288b
0.17.0 "Purge" [3+4/4]: stdlib convention + version bump
jasisz May 6, 2026
5e3d214
0.17.0 "Purge" fix: dedup match arms after sed migration
jasisz May 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,46 @@ All notable changes to Aver are documented here. Starting with 0.10.0, minor rel

## Unreleased

## 0.17.0 "Purge" — 2026-05-06

> _What was never used is no longer in the way._

A stdlib sweep before the language gets harder to break. Eight redundant builtins removed, one renamed for symmetry, one rule for what stays: each operation has one obvious spelling. Literals for literals (`{}`, `[]`), operators for primitive composition (`+` on strings, arithmetic), `Target.fromSource` for conversions, interpolation for rendering, named functions only when they add semantics.

### Removed

- **`Map.empty()`** — redundant against the `{}` literal. Bidirectional inference propagates `Map<K, V>` from binding annotations into `{}`, and the discovery walker introduced in 0.16.3 picks up unannotated literals like `m = {a => 3}` from `expr.ty()`. Symmetric with `[]` for List (which never had a `List.empty` builtin).
- **`Int.parse`, `Float.parse`, `Int.rem`** — unreachable builtin aliases. Registered in 4 backend dispatch tables but never wired through typecheck or VM. Lean and dafny treated them as outright aliases for `Int.fromString` / `Float.fromString` / `Int.mod`.
- **`Int.toString`, `Float.toString`** — duplicates of `String.fromInt` / `String.fromFloat`. The convention `Target.fromSource` wins: result type leads (matters for code review and AI-generated code), and it scales (`Int.fromFloat`, `Float.fromInt`, `String.fromBool`, …). Interpolation `"{x}"` remains the primary idiom for rendering values into human-readable strings; `String.fromX` is for explicit data conversion (e.g. `"user:" + String.fromInt(id)`).
- **`Float.toInt`, `Int.toFloat`** — duplicates of `Int.fromFloat` / `Float.fromInt`. Same convention.
- **`String.concat(a, b)`** — literally `a + b`. Zero usage in examples (only in docs); not even dispatched in the wasm-gc backend. The `+` operator is the primary idiom for tail-recursive accumulators (`acc + sep + String.fromInt(head)`) and inline string composition; `String.join(parts, sep)` covers list-join (a different operation).

### Renamed

- **`Vector.toList(v)` → `List.fromVector(v)`** — paired with `Vector.fromList(l)` under the same `Target.fromSource` rule.

### Kept (deliberately)

- **`+` on strings** — primary idiom for tail-recursive string accumulators and inline composition. Forcing only interpolation `"{a}{b}"` would be awkward in `acc + " " + String.fromInt(head)` patterns.
- **`Bool.and` / `Bool.or` / `Bool.not`** — *intentionally not added* as `&&` / `||` / `!` operators. Aver tracks effects deterministically (record/replay/proof export); short-circuit on `a && f!()` would require deciding whether the effect of `f` may or may not fire depending on `a`, which complicates trace recording and Lean export. Strict-FP eager evaluation matches the rest of the language. Pattern-matching `(x > 0, y > 0)` covers most idiomatic AND/OR cases. Not a "later language decision" — a settled non-feature.
- **`Char.toCode` / `Char.fromCode`, `Byte.toHex` / `Byte.fromHex`, `Option.toResult`, `String.toLower` / `String.toUpper`** — encoding semantics or semantic conversions, not type-to-type. Not duplicates.

### Migration

Programs using removed builtins:

```aver
-- before
m = Map.empty() -- → {}
s = Int.toString(42) -- → String.fromInt(42) or "{42}"
n = Float.toInt(3.7) -- → Int.fromFloat(3.7)
f = Int.toFloat(5) -- → Float.fromInt(5)
xs = Vector.toList(v) -- → List.fromVector(v)
greeting = String.concat("hi, ", name) -- → "hi, " + name
```

Examples in `examples/` and `tools/website/` migrated; vera-bench solutions checked (zero usage of any removed builtin, no companion PR needed). All 621 lib tests pass. The full sweep landed in four self-contained commits on the 0.17 branch.

## 0.16.2 — 2026-05-06

> _Record/replay correctness across all three backends — and a tidier wasm-gc imports tree along the way._
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ exclude = ["tools/wasm-runner"]

[package]
name = "aver-lang"
version = "0.16.2"
version = "0.17.0"
edition = "2024"
default-run = "aver"
description = "VM and transpiler for Aver, a statically-typed language designed for AI-assisted development"
Expand Down
2 changes: 1 addition & 1 deletion aver-lsp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ name = "aver-lsp"
path = "src/main.rs"

[dependencies]
aver = { path = "..", version = "=0.16.2", package = "aver-lang" }
aver = { path = "..", version = "=0.17.0", package = "aver-lang" }
tower-lsp-server = "0.23"
tokio = { version = "1", features = ["full"] }
serde_json = "1"
4 changes: 2 additions & 2 deletions docs/language.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Duplicate binding of the same name in the same scope is a type error.

## Operators

Arithmetic: `+`, `-`, `*`, `/` — operands must match (`Int+Int`, `Float+Float`, `String+String`). No implicit promotion; use `Int.toFloat` / `Float.fromInt` to convert.
Arithmetic: `+`, `-`, `*`, `/` — operands must match (`Int+Int`, `Float+Float`, `String+String`). No implicit promotion; use `Float.fromInt` / `Int.fromFloat` to convert.
Comparison: `==`, `!=`, `<`, `>`, `<=`, `>=`.
Error propagation: `expr?` — unwraps `Result.Ok`, propagates `Result.Err` as a `RuntimeError`.
Independent products: `(a, b)!` — product of independent computations. `(a, b)?!` — same, with Result unwrapping (all must succeed or first error propagates). Elements cannot reference each other; independence is structural. Composes recursively for fan-out parallelism. See [independence.md](independence.md).
Expand Down Expand Up @@ -245,7 +245,7 @@ Most application code in Aver stays first-order and explicit. Use function param
Aver has no dedicated `Set` type. The idiomatic way to express a set is `Map<T, Unit>` — a map whose values carry no information. All `Map.*` operations work on sets:

```aver
seen: Map<String, Unit> = Map.empty()
seen: Map<String, Unit> = {}
seen2 = Map.set(seen, "alice", Unit)
Map.has(seen2, "alice") // true
Map.len(seen2) // 1
Expand Down
10 changes: 5 additions & 5 deletions docs/services.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Vector is a persistent indexed sequence — use it for grids, buffers, lookup ta
| `Vector.set` | `(Vector<T>, Int, T) -> Option<Vector<T>>` | O(1) COW update; `None` if out of bounds |
| `Vector.len` | `Vector<T> -> Int` | |
| `Vector.fromList` | `List<T> -> Vector<T>` | Convert list to vector |
| `Vector.toList` | `Vector<T> -> List<T>` | Convert vector to list |
| `List.fromVector` | `Vector<T> -> List<T>` | Convert vector to list |

### `Result` namespace

Expand Down Expand Up @@ -75,8 +75,8 @@ Source: `src/types/int.rs`
|---|---|
| `Int.fromString` | `String -> Result<Int, String>` |
| `Int.fromFloat` | `Float -> Int` |
| `Int.toString` | `Int -> String` |
| `Int.toFloat` | `Int -> Float` |
| `String.fromInt` | `Int -> String` |
| `Float.fromInt` | `Int -> Float` |
| `Int.abs` | `Int -> Int` |
| `Int.min` | `(Int, Int) -> Int` |
| `Int.max` | `(Int, Int) -> Int` |
Expand All @@ -90,7 +90,7 @@ Source: `src/types/float.rs`
|---|---|
| `Float.fromString` | `String -> Result<Float, String>` |
| `Float.fromInt` | `Int -> Float` |
| `Float.toString` | `Float -> String` |
| `String.fromFloat` | `Float -> String` |
| `Float.abs` | `Float -> Float` |
| `Float.floor` | `Float -> Int` |
| `Float.ceil` | `Float -> Int` |
Expand Down Expand Up @@ -134,7 +134,7 @@ Source: `src/types/map.rs`

| Function | Signature | Notes |
|---|---|---|
| `Map.empty` | `() -> Map<K, V>` | |
| `{}` (literal) | — | The empty map; type from context (annotation or expected type). No `Map.empty()` builtin since 0.17 — symmetric with `[]` for List. |
| `Map.fromList` | `List<(K, V)> -> Map<K, V>` | Keys must be hashable (Int, Float, String, Bool) |
| `Map.set` | `(Map<K, V>, K, V) -> Map<K, V>` | Returns new map with key set |
| `Map.get` | `(Map<K, V>, K) -> Option<V>` | |
Expand Down
2 changes: 1 addition & 1 deletion docs/vm.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ The point of `v2` is not only compactness. It is to keep the common Aver shapes
- `Bool`, `Unit`, and `None` are pure inline singletons
- `Some(true)`, `Ok(Unit)`, `Err(None)` stay inline
- `Some(42)`, `Ok(-7)`, `Err(0)` stay inline as long as the int fits the wrapper-inline range
- `[]` and `Map.empty()` are real values under their normal collection tags, not exceptions hidden in `Immediate`
- `[]` and `{}` are real values under their normal collection tags, not exceptions hidden in `Immediate`
- strings up to 5 UTF-8 bytes stay inline under `TAG_STRING`
- nullary variants such as `Status.Todo` or `Color.Red` travel as `Symbol` handles instead of arena entries

Expand Down
12 changes: 6 additions & 6 deletions examples/data/date.av
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ verify parse
fn padTwo(n: Int) -> String
? "Pad a single-digit number with a leading zero."
match n < 10
true -> "0{Int.toString(n)}"
false -> Int.toString(n)
true -> "0{String.fromInt(n)}"
false -> String.fromInt(n)

verify padTwo
padTwo(0) => "00"
Expand All @@ -54,7 +54,7 @@ verify padTwo

fn format(d: Date) -> String
? "Format a Date as YYYY-MM-DD HH:MM:SS."
y = Int.toString(d.year)
y = String.fromInt(d.year)
m = padTwo(d.month)
da = padTwo(d.day)
h = padTwo(d.hour)
Expand Down Expand Up @@ -82,6 +82,6 @@ fn main()
d = parse(now)
Console.print("Raw: {now}")
Console.print("Parsed: {format(d)}")
Console.print("Year: {Int.toString(d.year)}")
Console.print("Month: {Int.toString(d.month)}")
Console.print("Day: {Int.toString(d.day)}")
Console.print("Year: {String.fromInt(d.year)}")
Console.print("Month: {String.fromInt(d.month)}")
Console.print("Day: {String.fromInt(d.day)}")
2 changes: 1 addition & 1 deletion examples/data/fibonacci.av
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ fn goldenApprox(n: Int) -> Result<Float, String>
? "Approximates golden ratio as F(n+1)/F(n). Requires n >= 1."
match n < 1
true -> Result.Err("Need n >= 1")
false -> Result.Ok(Int.toFloat(fib(n + 1)) / Int.toFloat(fib(n)))
false -> Result.Ok(Float.fromInt(fib(n + 1)) / Float.fromInt(fib(n)))

verify goldenApprox
goldenApprox(0) => Result.Err("Need n >= 1")
Expand Down
2 changes: 1 addition & 1 deletion examples/data/json.av
Original file line number Diff line number Diff line change
Expand Up @@ -1081,7 +1081,7 @@ verify parseArrayNext

fn emptyJsonMap() -> Map<String, Json>
? "JSON helper: emptyJsonMap."
Map.empty()
{}

fn parseObject(s: String, pos: Int) -> ParseResult
? "JSON helper: parseObject."
Expand Down
10 changes: 5 additions & 5 deletions examples/data/map.av
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ module MapExample

fn emptyCounts() -> Map<String, Int>
? "Creates an empty word-count map."
Map.empty()
{}

fn incCount(counts: Map<String, Int>, word: String) -> Map<String, Int>
? "Increments the counter for one word."
Expand All @@ -16,16 +16,16 @@ fn incCount(counts: Map<String, Int>, word: String) -> Map<String, Int>
Option.None -> Map.set(counts, word, 1)

verify incCount
incCount(Map.empty(), "a") => {"a" => 1}
incCount({}, "a") => {"a" => 1}
incCount({"a" => 1}, "a") => {"a" => 2}

verify incCount law keyPresent
given counts: Map<String, Int> = [Map.empty(), {"a" => 1}, {"x" => 2, "y" => 4}]
given counts: Map<String, Int> = [{}, {"a" => 1}, {"x" => 2, "y" => 4}]
given word: String = ["a", "z", "new"]
Map.has(incCount(counts, word), word) => true

verify incCount law trackedCountStepsByOne
given counts: Map<String, Int> = [Map.empty(), {"a" => 1}, {"a" => 5, "x" => 2}]
given counts: Map<String, Int> = [{}, {"a" => 1}, {"a" => 5, "x" => 2}]
given word: String = ["a", "new"]
Option.withDefault(Map.get(incCount(counts, word), word), 0) => Option.withDefault(Map.get(counts, word), 0) + 1

Expand All @@ -36,7 +36,7 @@ fn countWords(words: List<String>) -> Map<String, Int>
[word, ..rest] -> incCount(countWords(rest), word)

verify countWords
countWords([]) => Map.empty()
countWords([]) => {}
countWords(["a", "b", "a"]) => {"a" => 2, "b" => 1}

verify countWords law presenceMatchesContains
Expand Down
2 changes: 1 addition & 1 deletion examples/formal/law_auto.av
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ fn incCount(counts: Map<String, Int>, word: String) -> Map<String, Int>
Option.None -> Map.set(counts, word, 1)

verify incCount law keyPresent
given counts: Map<String, Int> = [Map.empty(), {"a" => 1}, {"x" => 2, "y" => 4}]
given counts: Map<String, Int> = [{}, {"a" => 1}, {"x" => 2, "y" => 4}]
given word: String = ["a", "z", "new"]
Map.has(incCount(counts, word), word) => true

Expand Down
16 changes: 8 additions & 8 deletions examples/games/checkers/main.av
Original file line number Diff line number Diff line change
Expand Up @@ -210,11 +210,11 @@ fn renderAiPanel(result: AiResult) -> Unit
! [Terminal.moveTo, Terminal.print, Terminal.resetColor, Terminal.setColor]
Terminal.moveTo(22, 1)
Terminal.setColor("cyan")
Terminal.print("AI depth={Int.toString(result.depth)} {Int.toString(result.thinkMs)}ms")
Terminal.print("AI depth={String.fromInt(result.depth)} {String.fromInt(result.thinkMs)}ms")
Terminal.resetColor()
Terminal.moveTo(22, 2)
Terminal.setColor("yellow")
Terminal.print("root-parallel x{Int.toString(Ai.rootParallelWidth())} | {Int.toString(List.len(result.candidates))} moves")
Terminal.print("root-parallel x{String.fromInt(Ai.rootParallelWidth())} | {String.fromInt(List.len(result.candidates))} moves")
Terminal.resetColor()
renderCandidates(result.candidates, result.move, 0)

Expand Down Expand Up @@ -242,15 +242,15 @@ fn renderChosenCandidate(sm: ScoredMove, i: Int) -> Unit
Terminal.setColor("green")
Terminal.print("★ ")
Terminal.print(moveLabel(sm.move))
Terminal.print(" {Int.toString(sm.score)}")
Terminal.print(" {String.fromInt(sm.score)}")
Terminal.resetColor()

fn renderOtherCandidate(sm: ScoredMove, i: Int) -> Unit
? "Render non-chosen candidate in white"
! [Terminal.print]
Terminal.print(" ")
Terminal.print(moveLabel(sm.move))
Terminal.print(" {Int.toString(sm.score)}")
Terminal.print(" {String.fromInt(sm.score)}")

fn isChosenMove(a: List<Point>, b: List<Point>) -> Bool
? "True if two moves are the same (compare first and last points)"
Expand Down Expand Up @@ -295,7 +295,7 @@ fn moveLabel(move: List<Point>) -> String
? "Human-readable label for a move path"
match firstPoint(move)
Option.Some(from) -> match lastPoint(move)
Option.Some(to) -> "{colChar(from.x)}{Int.toString(8 - from.y)}→{colChar(to.x)}{Int.toString(8 - to.y)}"
Option.Some(to) -> "{colChar(from.x)}{String.fromInt(8 - from.y)}→{colChar(to.x)}{String.fromInt(8 - to.y)}"
Option.None -> "?"
Option.None -> "?"

Expand All @@ -307,7 +307,7 @@ fn renderHelp(state: GameState) -> Unit
! [Terminal.moveTo, Terminal.print, Terminal.resetColor, Terminal.setColor]
Terminal.moveTo(0, 14)
Terminal.setColor("green")
Terminal.print(" You (black) vs AI (white) · depth {Int.toString(state.searchDepth)} · +/- to change")
Terminal.print(" You (black) vs AI (white) · depth {String.fromInt(state.searchDepth)} · +/- to change")
Terminal.resetColor()
Terminal.moveTo(0, 15)
match state.selected
Expand Down Expand Up @@ -415,7 +415,7 @@ fn aiPhase(state: GameState) -> Result<String, String>
]
renderFrame(state)
Terminal.moveTo(0, 14)
Terminal.print("AI thinking (depth {Int.toString(state.searchDepth)}, root-parallel x{Int.toString(Ai.rootParallelWidth())})...")
Terminal.print("AI thinking (depth {String.fromInt(state.searchDepth)}, root-parallel x{String.fromInt(Ai.rootParallelWidth())})...")
Terminal.flush()
t0 = Time.unixMs()
aiState = handleAiTurn(state)
Expand Down Expand Up @@ -443,7 +443,7 @@ fn gameOverResult(state: GameState) -> Result<String, String>
Terminal.print("Game over!")
Terminal.flush()
Time.sleep(2000)
Result.Ok("Game over! Move {Int.toString(state.moveNum)}")
Result.Ok("Game over! Move {String.fromInt(state.moveNum)}")

fn gameTurn(state: GameState) -> Result<String, String>
? "Dispatch to player or AI"
Expand Down
6 changes: 3 additions & 3 deletions examples/games/checkers/render.av
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ fn renderRowLabelsNext(r: Int) -> Unit

fn rowLabel(r: Int) -> String
? "Row label: row 0 = 8, row 7 = 1"
Int.toString(8 - r)
String.fromInt(8 - r)

verify rowLabel
rowLabel(0) => "8"
Expand Down Expand Up @@ -281,7 +281,7 @@ fn renderStatus(currentPlayer: Color, moveNum: Int) -> Unit
Terminal.setColor(playerColor(currentPlayer))
Terminal.print("{colorName(currentPlayer)}")
Terminal.resetColor()
Terminal.print(" to move | Move #{Int.toString(moveNum)}")
Terminal.print(" to move | Move #{String.fromInt(moveNum)}")

fn renderAiTrace(move: List<Point>, score: Int, alternatives: Int, depth: Int) -> Unit
? "Show AI decision trace"
Expand All @@ -290,4 +290,4 @@ fn renderAiTrace(move: List<Point>, score: Int, alternatives: Int, depth: Int) -
Terminal.setColor("cyan")
Terminal.print("AI: ")
Terminal.resetColor()
Terminal.print("score={Int.toString(score)} alts={Int.toString(alternatives)} depth={Int.toString(depth)}")
Terminal.print("score={String.fromInt(score)} alts={String.fromInt(alternatives)} depth={String.fromInt(depth)}")
8 changes: 4 additions & 4 deletions examples/games/doom/enemy.av
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ fn ghostTeleport(enemy: Enemy, seed: Int, levelMap: List<String>) -> Enemy
? "Teleport ghost to a random nearby floor tile"
s1 = Rng.nextSeed(seed)
s2 = Rng.nextSeed(s1)
dx = Int.toFloat(Rng.seedToRange(s1, 0 - 4, 4))
dy = Int.toFloat(Rng.seedToRange(s2, 0 - 4, 4))
dx = Float.fromInt(Rng.seedToRange(s1, 0 - 4, 4))
dy = Float.fromInt(Rng.seedToRange(s2, 0 - 4, 4))
nx = enemy.x + dx
ny = enemy.y + dy
match Level.isWall(levelMap, Float.floor(nx), Float.floor(ny))
Expand Down Expand Up @@ -251,7 +251,7 @@ fn applyShotVec(enemies: Vector<Enemy>, idx: Int) -> (List<Enemy>, String)
? "Apply 5 damage to enemy at index using indexed vector access"
match Vector.get(enemies, idx)
Option.Some(e) -> applyDamageToEnemyVec(enemies, idx, e)
Option.None -> (Vector.toList(enemies), "Shot missed!")
Option.None -> (List.fromVector(enemies), "Shot missed!")

verify applyShotVec
applyShotVec(Vector.fromList([]), 0) => ([], "Shot missed!")
Expand All @@ -268,7 +268,7 @@ fn applyDamageToEnemyVec(enemies: Vector<Enemy>, idx: Int, e: Enemy) -> (List<En
newHp = e.hp - 5
match newHp < 1
true -> (removeEnemyVec(enemies, idx, 0, []), "Killed {Types.enemyGlyph(e.kind)}!")
false -> (replaceEnemyVec(enemies, idx, Enemy.update(e, hp = newHp), 0, []), "Hit {Types.enemyGlyph(e.kind)}! ({Int.toString(newHp)} HP)")
false -> (replaceEnemyVec(enemies, idx, Enemy.update(e, hp = newHp), 0, []), "Hit {Types.enemyGlyph(e.kind)}! ({String.fromInt(newHp)} HP)")

verify applyDamageToEnemyVec
applyDamageToEnemyVec(Vector.fromList([Types.mkEnemy(1.0, 1.0, EnemyKind.Imp, 3)]), 0, Types.mkEnemy(1.0, 1.0, EnemyKind.Imp, 3)) => ([], "Killed !!")
Expand Down
2 changes: 1 addition & 1 deletion examples/games/doom/level.av
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ verify roomFromSeed

fn roomCenter(room: Room) -> (Float, Float)
? "Center of a room as float coordinates"
(Int.toFloat(room.x + room.w / 2) + 0.5, Int.toFloat(room.y + room.h / 2) + 0.5)
(Float.fromInt(room.x + room.w / 2) + 0.5, Float.fromInt(room.y + room.h / 2) + 0.5)

verify roomCenter
roomCenter(Room(x = 4, y = 4, w = 6, h = 6)) => (7.5, 7.5)
Expand Down
6 changes: 3 additions & 3 deletions examples/games/doom/main.av
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ verify turnSpeed
fn spawnInRoom(room: Level.Room, seed: Int) -> Enemy
? "Spawn an enemy at the center of a room"
kind = pickKind(seed)
cx = Int.toFloat(room.x + room.w / 2) + 0.5
cy = Int.toFloat(room.y + room.h / 2) + 0.5
cx = Float.fromInt(room.x + room.w / 2) + 0.5
cy = Float.fromInt(room.y + room.h / 2) + 0.5
Types.mkEnemy(cx, cy, kind, Types.enemyMaxHp(kind))

verify spawnInRoom
Expand Down Expand Up @@ -214,7 +214,7 @@ fn updateTurn(state: GameState) -> GameState
msgs = match isOver
true -> ["You died!"]
false -> match damaged.hp < state.player.hp
true -> List.concat(state.messages, ["Ouch! HP: {Int.toString(damaged.hp)}"])
true -> List.concat(state.messages, ["Ouch! HP: {String.fromInt(damaged.hp)}"])
false -> state.messages
trimmedMsgs = trimMessages(msgs)
GameState.update(state, enemies = newEnemies, player = damaged, turnCount = state.turnCount + 1, gameOver = isOver, messages = trimmedMsgs)
Expand Down
2 changes: 1 addition & 1 deletion examples/games/doom/math.av
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ verify radToDeg
fn normalizeAngle(a: Float) -> Float
? "Wrap angle to [0, 2*pi)"
twoPi = Float.pi() * 2.0
rem = a - Int.toFloat(Float.floor(a / twoPi)) * twoPi
rem = a - Float.fromInt(Float.floor(a / twoPi)) * twoPi
match rem < 0.0
true -> rem + twoPi
false -> rem
Expand Down
Loading
Loading