feat(lang): L4 type checker between parse and emit
selfhost/check/ walks every function, the entry, tests, globals' initializers and @On listeners with real scopes, and refuses mixed number kinds, text and numbers, two record types, mismatched slices and fn types, wrong argument counts, wrong returns and wrong push elements - every mix-up at once, each at its line. LUDIC_CHECK_REPORT=1 lists them by category. pointer stays untyped (L7's). What it found is fixed: render3d's HDR scan calling the float-bits extern f_lt with floats; ludic.shooter's right-stick aim overflowing past half a push; prof.ludic storing longs in []int; extern arguments now coerced to their parameters. Text-returning runtime functions say string; Assets.ready says bool. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
0677aee93f
commit
57b66bdf47
52 changed files with 27005 additions and 11844 deletions
|
|
@ -25,8 +25,6 @@ function fr(n: int, d: int) -> float { return float(n) / float(d) }
|
|||
function f_neg1() -> float { return -1.0 }
|
||||
function f_clamp(x: float, lo: float, hi: float) -> float { return Math.min(Math.max(x, lo), hi) }
|
||||
function f_lerp(a: float, b: float, t: float) -> float { return a + (b - a) * t }
|
||||
function f_gt(a: float, b: float) -> bool { return f_lt(b, a) != 0 }
|
||||
function f_ls(a: float, b: float) -> bool { return f_lt(a, b) != 0 }
|
||||
function f_rad(deg: float) -> float { return deg * (PI / 180.0) }
|
||||
function f_fx(x: float) -> fixed { return fixed(x) }
|
||||
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ function gltf_mat_remember(name: string, diff: int, nrm: int, arm: int) -> void
|
|||
}
|
||||
|
||||
var gltf_cutout: bool = false # the material being loaded is alpha-blended (a cut-out atlas)
|
||||
function gltf_texture(uri: pointer, srgb: bool) -> int {
|
||||
function gltf_texture(uri: string, srgb: bool) -> int {
|
||||
if gltf_tex_paths == null { gltf_tex_paths = new []pointer; gltf_tex_ids = words(256) }
|
||||
var png: string = uri
|
||||
let n = len(uri)
|
||||
|
|
@ -82,7 +82,7 @@ function gltf_texture(uri: pointer, srgb: bool) -> int {
|
|||
}
|
||||
|
||||
# the image uri behind materials[m].<slot>.index, or null
|
||||
function gltf_mat_uri(mat: Val, slot: pointer) -> pointer {
|
||||
function gltf_mat_uri(mat: Val, slot: pointer) -> string {
|
||||
var holder = mat
|
||||
if slot == "baseColorTexture" or slot == "metallicRoughnessTexture" {
|
||||
if value_has(mat, "pbrMetallicRoughness") == 0 { return null }
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ function prof_bake_add(us: long) -> void { if prof_on { prof_bake_us_cur = prof_
|
|||
function prof_chunk(kind: int, band: int, count: int, us: long) -> void {
|
||||
if not prof_on { return }
|
||||
if prof_chunk_us == null {
|
||||
prof_chunk_us = new []int; prof_chunk_kind = new []int
|
||||
prof_chunk_us = new []long; prof_chunk_kind = new []int
|
||||
prof_chunk_band = new []int; prof_chunk_n = new []int
|
||||
}
|
||||
push(prof_chunk_us, us); push(prof_chunk_kind, kind)
|
||||
|
|
|
|||
|
|
@ -363,9 +363,9 @@ function hdr_decode(path: pointer) -> floats {
|
|||
out[o + 1] = Math.min(vg, 60000.0)
|
||||
out[o + 2] = Math.min(vb, 60000.0)
|
||||
let lum = vr + vg + vb
|
||||
if f_lt(maxl, lum) != 0 { maxl = lum; hdr_max_x = x; hdr_max_y = y }
|
||||
if maxl < lum { maxl = lum; hdr_max_x = x; hdr_max_y = y }
|
||||
if y < h / 2 { skye = skye + Math.min(vg, hdr_clip) * Math.cos((float(y) + 0.5) * dth) * domega }
|
||||
if f_lt(hdr_clip, vg) != 0 or f_lt(hdr_clip, vr) != 0 {
|
||||
if hdr_clip < vg or hdr_clip < vr {
|
||||
sr = sr + Math.max(vr - hdr_clip, 0.0) * domega
|
||||
sg = sg + Math.max(vg - hdr_clip, 0.0) * domega
|
||||
sb = sb + Math.max(vb - hdr_clip, 0.0) * domega
|
||||
|
|
|
|||
|
|
@ -417,7 +417,7 @@ function sh_half_w(e: int) -> int {
|
|||
if mode == AimMode.RightStick {
|
||||
let ax = Input.pad_axis(0, STICK_RIGHT_X)
|
||||
let ay = Input.pad_axis(0, STICK_RIGHT_Y)
|
||||
if (ax != 0) or (ay != 0) { target = sh_dir_angle(ax, ay); have = 1 }
|
||||
if (ax != 0) or (ay != 0) { target = sh_dir_angle_fx(ax, ay); have = 1 }
|
||||
}
|
||||
if mode == AimMode.MoveDirection { # from the movement intent
|
||||
let wx = td_get(e, "want_x")
|
||||
|
|
@ -473,6 +473,12 @@ function sh_dir_angle(dx: int, dy: int) -> int {
|
|||
let r = Math.atan2(fixed(dy), fixed(dx))
|
||||
return sh_wrap_deg(floor(Math.rad_to_deg(r)))
|
||||
}
|
||||
# a stick's deflection is already fixed: fixed(dy) on it would scale it by 65536 again and
|
||||
# overflow past half a push, turning the aim round
|
||||
function sh_dir_angle_fx(dx: fixed, dy: fixed) -> int {
|
||||
let r = Math.atan2(dy, dx)
|
||||
return sh_wrap_deg(floor(Math.rad_to_deg(r)))
|
||||
}
|
||||
function sh_wrap_deg(d: int) -> int {
|
||||
var a = d
|
||||
while a < 0 { a += 360 }
|
||||
|
|
@ -494,8 +500,9 @@ function sh_spawn_bullet(owner: int, fac: int, px: int, py: int, deg: int, speed
|
|||
pos_set(b, "x", px)
|
||||
pos_set(b, "y", py)
|
||||
let rad = Angle.from_degrees(fixed(deg))
|
||||
pr_set(b, "vx", Angle.cos(rad) * fixed(speed))
|
||||
pr_set(b, "vy", Angle.sin(rad) * fixed(speed))
|
||||
# World.set stores a field's raw word: a fixed field is handed its bits by name
|
||||
pr_set(b, "vx", as_int(Angle.cos(rad) * fixed(speed)))
|
||||
pr_set(b, "vy", as_int(Angle.sin(rad) * fixed(speed)))
|
||||
pr_set(b, "dir", deg)
|
||||
pr_set(b, "speed", speed)
|
||||
pr_set(b, "damage", dmg)
|
||||
|
|
@ -621,8 +628,8 @@ function sh_fire(owner: int, id: int) -> void {
|
|||
let rad = Angle.from_degrees(fixed(na))
|
||||
let nvx = Angle.cos(rad) * fixed(sp)
|
||||
let nvy = Angle.sin(rad) * fixed(sp)
|
||||
pr_set(e, "vx", nvx)
|
||||
pr_set(e, "vy", nvy)
|
||||
pr_set(e, "vx", as_int(nvx))
|
||||
pr_set(e, "vy", as_int(nvy))
|
||||
}
|
||||
}
|
||||
# integrate (Q16.16 with subpixel remainder)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue