feat(compiler): list literals, typed compound assignment, file:line diagnostics
- `[a, b, c]` list literals (E_LIST → emit_list); static_type learns slice-element, `new T`, list, string and literal kinds - `x op= y` lowers through the same path as `x = x op y` (emit_bin_vals): fixed `*=`/`/=` use the Q16.16 64-bit paths, string `+=` concatenates, int→long widens; unary `-` keeps a fixed operand's type (arith_ty) - one `unescape()` table for "strings", 'chars' and `interpolation`; `'\''`, `'\\'`, `'\"'` no longer read as 0; unterminated char literals and unexpected characters are errors instead of silently skipped - every diagnostic is `file:line: error: msg` (g_parse_file / g_err_file, Node.file + Node.line set by node()); tok_desc() in expectation errors; duplicate `function` names and unknown `phase` names are reported in source terms (phase_id used to default unknown phases to Overlay) - interpolation holes skip braces inside string literals - hand-IR preludes move from the user `@fn_` prefix to `@lp_` so a user `is_ws` / `str_eq` / `path_join` no longer collides at link time - `@ClearColor(expr)` accepts any constant expression; `Os.pid()` added (docs page + inventory); `str_starts()` in support/str - main.ludic: `else if` flag ladder, char literals, stale script comments - examples/lang/operators.ludic covers all of the above; os.ludic covers Os.pid; docs pages for Os.pid and the Overlay phase; ten changesets - reseeded: selfhost/ludicc.seed.ll is the new compiler's own fixpoint Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
ad548840c7
commit
647dfec334
88 changed files with 30081 additions and 29179 deletions
|
|
@ -1,13 +1,13 @@
|
|||
program T {
|
||||
function fib(n: int) -> int { if n < 2 { return n }; return fib(n-1) + fib(n-2) }
|
||||
function fib(n: int) -> int { if n < 2 { return n }; return fib(n - 1) + fib(n - 2) }
|
||||
entry {
|
||||
print(fib(10)) # 55
|
||||
var s = 0
|
||||
for i in 0 .. 10 { if i == 5 { break }; if i % 2 == 0 { continue }; s = s + i }
|
||||
for i in 0 .. 10 { if i == 5 { break }; if i % 2 == 0 { continue }; s += i }
|
||||
print(s) # 1+3 = 4
|
||||
var i = 0; var t = 0
|
||||
while true { i = i + 1; if i > 5 { break }; t = t + i }
|
||||
while true { i += 1; if i > 5 { break }; t += i }
|
||||
print(t) # 15
|
||||
if false and (1/0 == 0) { print(999) } else { print(1) } # short-circuit: no div by zero
|
||||
if false and (1 / 0 == 0) { print(999) } else { print(1) } # short-circuit: no div by zero
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ program T {
|
|||
let payload = "score=9001;level=12"
|
||||
let mac = Crypto.hmac_sha256(key, payload)
|
||||
if Crypto.verify_hmac(key, payload, mac) { print(1) } else { print(0) } # 1: untampered
|
||||
if Crypto.verify_hmac(key, "score=9999;level=12", mac) { print(1) } else { print(0) } # 0: tampered payload
|
||||
if Crypto.verify_hmac(key, "score=9999;level=12", mac) { print(1) } else { print(0) } # 0: tampered payload
|
||||
let forged = "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
if Crypto.verify_hmac(key, payload, forged) { print(1) } else { print(0) } # 0: forged mac
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ program T {
|
|||
entry {
|
||||
# Duration — spans in whole seconds
|
||||
print(Duration.hours(3)) # 10800
|
||||
print(Duration.minutes(5) + Duration.seconds(30)) # 330
|
||||
print(Duration.minutes(5) + Duration.seconds(30)) # 330
|
||||
print(Duration.days(2)) # 172800
|
||||
print(Duration.as_hours(10800)) # 3
|
||||
print(Duration.as_days(172800)) # 2
|
||||
|
|
@ -25,7 +25,7 @@ program T {
|
|||
let feb = Date.add_days(Date.new(2026, 1, 1), 31)
|
||||
print(Date.month(feb)) # 2
|
||||
print(Date.day(feb)) # 1
|
||||
print(Date.diff_days(Date.new(2026, 1, 1), Date.new(2025, 1, 1))) # 365
|
||||
print(Date.diff_days(Date.new(2026, 1, 1), Date.new(2025, 1, 1))) # 365
|
||||
|
||||
# DateTime — instant as seconds-since-1970
|
||||
let t = DateTime.from(2000, 1, 1, 12, 30, 15)
|
||||
|
|
@ -38,6 +38,6 @@ program T {
|
|||
print(DateTime.second(t)) # 15
|
||||
print(DateTime.weekday(t)) # 6
|
||||
print(DateTime.date(t)) # 10957
|
||||
print(DateTime.hour(DateTime.add(0, Duration.hours(1)))) # 1
|
||||
print(DateTime.hour(DateTime.add(0, Duration.hours(1)))) # 1
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ program T {
|
|||
print(DateTime.format(t, "DD/MM/YY")) # 30/08/26
|
||||
|
||||
# parse — round-trips to the same instant; missing fields default to midnight
|
||||
print(DateTime.parse("2026-08-30", "YYYY-MM-DD") - Date.to_epoch(Date.new(2026, 8, 30))) # 0
|
||||
print(DateTime.parse("2026-08-30", "YYYY-MM-DD") - Date.to_epoch(Date.new(2026, 8, 30))) # 0
|
||||
print(DateTime.parse("zz", "YYYY")) # -1 (non-digit -> parse fails)
|
||||
|
||||
# Clock — the game-controlled simulated clock
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ program T {
|
|||
let t = Portal(2, 40)
|
||||
match t {
|
||||
Empty, Wall => { print(100) }
|
||||
Portal(x, y) => { print(x * y) } # 80
|
||||
Portal(x, y) => { print(x * y) } # 80
|
||||
_ => { print(999) }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ program T {
|
|||
print(x > y) # 1
|
||||
print(y < x) # 1
|
||||
print(x == x) # 1
|
||||
print(0 - sq) # -1000000000000 (unary negate stays 64-bit)
|
||||
print(-sq) # -1000000000000 (unary negate stays 64-bit)
|
||||
print(big) # 1000000
|
||||
print(Text.length(string(sq))) # 13 — string(long) renders all 13 digits
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@ program T {
|
|||
# min / max / abs / clamp, now reachable under the Math namespace
|
||||
print(Math.min(3, 7)) # 3
|
||||
print(Math.max(3, 7)) # 7
|
||||
print(Math.abs(0 - 5)) # 5
|
||||
print(Math.abs(-5)) # 5
|
||||
print(Math.clamp(12, 0, 10)) # 10
|
||||
|
||||
# sign -> -1 / 0 / 1
|
||||
print(Math.sign(0 - 4)) # -1
|
||||
print(Math.sign(-4)) # -1
|
||||
print(Math.sign(0)) # 0
|
||||
print(Math.sign(9)) # 1
|
||||
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ program T {
|
|||
print(Math.floor(Math.dist2(0.0, 0.0, 3.0, 4.0))) # 25
|
||||
print(Math.floor(Math.deg_to_rad(180.0) * 1000.0)) # 3142
|
||||
print(Math.floor(Math.rad_to_deg(3.1415926))) # 180
|
||||
print(Math.posmod(0 - 1, 5)) # 4
|
||||
print(Math.posmod(-1, 5)) # 4
|
||||
print(Math.wrap(12, 0, 10)) # 2
|
||||
print(Math.ping_pong(13, 10)) # 7
|
||||
print(Math.floor(Math.snapped(2.3, 0.5) * 10.0)) # 25
|
||||
print(Math.floor(Math.move_toward(0.0, 10.0, 3.0) * 10.0)) # 30
|
||||
print(Math.floor(Math.smoothstep(0.0, 10.0, 5.0) * 1000.0)) # 500
|
||||
print(Math.floor(Math.smoothstep(0.0, 10.0, 5.0) * 1000.0)) # 500
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ program T {
|
|||
print(Math.round(Math.rad_to_deg(Math.atan2(1.0, 1.0)))) # 45
|
||||
print(Math.round(Math.rad_to_deg(Math.atan2(1.0, 0.0)))) # 90
|
||||
print(Math.round(Math.rad_to_deg(Math.atan2(0.0, 0.0 - 1.0)))) # 180
|
||||
print(Math.round(Math.rad_to_deg(Math.atan2(0.0 - 1.0, 0.0 - 1.0)))) # -135
|
||||
print(Math.round(Math.rad_to_deg(Math.atan2(0.0 - 1.0, 0.0 - 1.0)))) # -135
|
||||
print(Math.round(Math.rad_to_deg(Math.asin(0.5)))) # 30
|
||||
print(Math.round(Math.rad_to_deg(Math.acos(0.5)))) # 60
|
||||
print(Math.round(Math.rad_to_deg(Math.asin(1.0)))) # 90
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
program T {
|
||||
property P { x: int = 0, y: int = 7, next: P }
|
||||
function bump(p: P) -> void { p.x = p.x + 100 }
|
||||
function bump(p: P) -> void { p.x += 100 }
|
||||
entry {
|
||||
let a = new P
|
||||
print(a.y) # 7 default
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ program T {
|
|||
print(Math.round(Math.pow(2.0, 10.0))) # 1024 -> 1024
|
||||
print(Math.round(Math.pow(2.0, 0.5) * 1000)) # sqrt 2 -> 1414
|
||||
print(Math.round(Math.pow(9.0, 0.5))) # 3 -> 3
|
||||
print(Math.round(Math.pow(2.0, 0.0 - 2.0) * 1000)) # 0.25 -> 250
|
||||
print(Math.round(Math.pow(2.0, 0.0 - 2.0) * 1000)) # 0.25 -> 250
|
||||
print(Math.round(Ease.elastic(0.0) * 1000)) # anchored -> 0
|
||||
print(Math.round(Ease.elastic(1.0) * 1000)) # settles -> 1000
|
||||
print(Math.round(Ease.elastic(0.5) * 1000)) # overshoot -> 1016
|
||||
|
|
|
|||
|
|
@ -13,13 +13,13 @@ program T {
|
|||
print(floor(Vector.y(d))) # 2
|
||||
print(floor(Vector.dot(a, b))) # 11
|
||||
print(floor(Vector.distance(a, b))) # 2 (sqrt 8)
|
||||
print(floor(Vector.x(Vector.scale(a, 2.0)))) # 6
|
||||
print(floor(Vector.x(Vector.scale(a, 2.0)))) # 6
|
||||
let n = Vector.normalize(a)
|
||||
print(floor(Vector.length(n) * 1000)) # 999 (unit)
|
||||
print(floor(Vector.x(Vector.from_angle(0.0)) * 1000)) # 999 (cos 0)
|
||||
let r = Vector.rotate(Vector.make(1.0, 0.0), 1.5707963) # rotate 90 deg
|
||||
let r = Vector.rotate(Vector.make(1.0, 0.0), 1.5707963) # rotate 90 deg
|
||||
print(floor(Vector.y(r) * 1000)) # 999 (-> (0,1))
|
||||
print(floor(Vector.angle(Vector.make(0.0, 1.0)) * 1000)) # pi/2 -> 1570
|
||||
print(floor(Vector.angle(Vector.make(0.0, 1.0)) * 1000)) # pi/2 -> 1570
|
||||
let m = Vector.lerp(Vector.zero(), Vector.make(10.0, 20.0), 0.5)
|
||||
print(floor(Vector.x(m))) # 5
|
||||
print(floor(Vector.y(m))) # 10
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue