aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar zinc <zinc@downsta.ir> 2026-10-14 16:47:08 +0330
committerGravatar zinc <zinc@downsta.ir> 2026-10-14 16:47:08 +0330
commit4a96db860c95ed6ea8a03cb24c54ebfb9325ada8 (patch)
tree9fa3a1fe8a667661cbc7efffa278702e44842604
parentzc0umd: no recast uses a visible u/m/d as its tag (spec 1.6.3); spec: the fix... (diff)
globals: an integer constant initializing a float or f32 global converts to float (float g = 2; is 2.0)
-rw-r--r--docs/SPEC.md2
-rw-r--r--src/compiler/decl.zc3
-rw-r--r--tests/conformance/5-declarations/global_float_int_init.zc9
3 files changed, 12 insertions, 2 deletions
diff --git a/docs/SPEC.md b/docs/SPEC.md
index 3eda4f3..f53c469 100644
--- a/docs/SPEC.md
+++ b/docs/SPEC.md
@@ -703,7 +703,7 @@ a bare `name(params) { ... }` with no `fn` and no type is not a function declara
5.3.1 `T a = e, b, c[10];`, `let g = 1, buf[10];`, `int[10] buf;`, `point origin;`. storage is emitted in place, zero initialised.
-5.3.2 an initializer is: a constant expression (3.14), a word string, a byte string, or a brace list or compound literal for an array. anything else is an error: for `int a = f();` error: expected ';', found '('. a `float`, `f64` or `f32` global takes a float literal initializer (`float g = 1.5;`). a name of another global in the initializer evaluates to its address, not its value: `int a = 5; int b = a + 1;` gives `b` the value `&a + 1`.
+5.3.2 an initializer is: a constant expression (3.14), a word string, a byte string, or a brace list or compound literal for an array. anything else is an error: for `int a = f();` error: expected ';', found '('. a `float`, `f64` or `f32` global takes a float literal initializer (`float g = 1.5;`); an integer constant initializer converts to float (`float g = 2;` stores 2.0), as it does for a local. a name of another global in the initializer evaluates to its address, not its value: `int a = 5; int b = a + 1;` gives `b` the value `&a + 1`.
5.3.3 a global cannot be tagged (error: tags go on locals and parameters, not globals), cannot be `void`, and an array global needs a length or an initializer.
diff --git a/src/compiler/decl.zc b/src/compiler/decl.zc
index 371e8e8..e9500c4 100644
--- a/src/compiler/decl.zc
+++ b/src/compiler/decl.zc
@@ -484,7 +484,8 @@ int gdecl2(int t, int tg, int n) {
vv = tv; next(); if (t == tf32) vv = rt.zs2f(rt.zf2s(vv)); *(a + hdelta) = vv; // an f32 scalar is a rounded double
}
else {
- vv = cnorm(t, cexpr()); *(a + hdelta) = vv;
+ vv = cnorm(t, cexpr()); if (t && isfl(t)) { vv = vf_i2f(vv); if (t == tf32) vv = rt.zs2f(rt.zf2s(vv)); } // float g = 2; is 2.0
+ *(a + hdelta) = vv;
if (gok) { if (!gty) gty = tint; else if (gty != tint) gok = 0; }
}
} else if (gok) gok = 0; // no initializer: nothing says what it is
diff --git a/tests/conformance/5-declarations/global_float_int_init.zc b/tests/conformance/5-declarations/global_float_int_init.zc
new file mode 100644
index 0000000..ac0e187
--- /dev/null
+++ b/tests/conformance/5-declarations/global_float_int_init.zc
@@ -0,0 +1,9 @@
+// expect: 1/1/1/1/1/
+// spec 5.3.2: an integer constant initializing a float or f32 converts to float, for globals and locals
+include rt;
+void pn(int x) { rt.put_n(x); rt.put_c(10); }
+float g = 2;
+f32 h = 1 + 2;
+float n = -4;
+fn main() { float l = 2; f32 m = 3; pn(g == 2.0); pn(h == 3.0); pn(n == -4.0); pn(l == 2.0); pn(m == 3.0); return 0; }
+// zc0: skip