feat(lang): backtick raw-identifier escape + #import c foreign-name exemption [F0.6]
Reserved type-name spellings (s1, s2, u8, …) can now be used as value identifiers two ways, resolving issue 0089: 1. Backtick raw identifier: a leading backtick (`s2) lexes to an .identifier token carrying a new Token.is_raw flag, with the backtick excluded from the text. A raw identifier is never type-classified — the parser skips Type.fromName for it — so it is always a value identifier. The flag threads to VarDecl.is_raw / Param.is_raw at binding sites, and the reserved-type-name check (UnknownTypeChecker) skips raw bindings. Because the token tag stays .identifier, the escape works in every position (local, global, param, field, fn name, struct member, later reference) with no per-site parser change. 2. #import c exemption: c_import.zig synthesizes foreign decls with Param.is_raw = true, so generated C param names that collide with reserved type names (s1, s2) import unedited. A bare reserved-name binding in sx still errors (issue 0076 preserved): the is_raw-gated skip only fires for backtick / foreign names, and a raw binding's address-of / autoref lowering stays correct because every occurrence is an .identifier, never a .type_expr. Tests: examples/0151 (backtick, every position), examples/1220 (foreign exemption, compiled+run), lexer unit tests. 1119 (bare-binding rejection) stays green. specs.md + readme.md updated.
This commit is contained in:
33
examples/0151-types-backtick-raw-identifier.sx
Normal file
33
examples/0151-types-backtick-raw-identifier.sx
Normal file
@@ -0,0 +1,33 @@
|
||||
// Backtick raw-identifier escape: a leading backtick makes the following
|
||||
// identifier RAW — its text excludes the backtick and it is NEVER
|
||||
// type-classified, so a reserved type-name spelling (`s2`, `u8`, …) can be
|
||||
// used as a value identifier. Exercised in every position: global, local,
|
||||
// param, struct field + member access, function name + call, and a later
|
||||
// reference. A *bare* `s2` is still the reserved type name (see
|
||||
// examples/1119), so the escape is the only way to spell these as values.
|
||||
// Regression (issue 0089).
|
||||
#import "modules/std.sx";
|
||||
|
||||
// Global named with a reserved type spelling.
|
||||
`u8 := 100;
|
||||
|
||||
// Function whose name is a reserved type spelling, with a reserved-name param.
|
||||
`s2 :: (`s1: s64) -> s64 { return `s1 * 2; }
|
||||
|
||||
Point :: struct {
|
||||
`s2: f64; // field name is a reserved type spelling
|
||||
`u16: s64;
|
||||
}
|
||||
|
||||
main :: () {
|
||||
// Local with a reserved type spelling; later reference resolves to it.
|
||||
`s64 := 7;
|
||||
`s64 = `s64 + 1;
|
||||
print("local = {}\n", `s64);
|
||||
|
||||
print("global = {}\n", `u8);
|
||||
print("fn = {}\n", `s2(21)); // calls the `s2 function
|
||||
|
||||
p := Point.{ `s2 = 2.5, `u16 = 9 };
|
||||
print("field = {} {}\n", p.`s2, p.`u16);
|
||||
}
|
||||
9
examples/1220-ffi-c-import-reserved-name-params.c
Normal file
9
examples/1220-ffi-c-import-reserved-name-params.c
Normal file
@@ -0,0 +1,9 @@
|
||||
#include "1220-ffi-c-import-reserved-name-params.h"
|
||||
|
||||
int ffi_pick(int s1, int s2, int which) {
|
||||
return which == 0 ? s1 : s2;
|
||||
}
|
||||
|
||||
int ffi_sum(int s1, int s2) {
|
||||
return s1 + s2;
|
||||
}
|
||||
5
examples/1220-ffi-c-import-reserved-name-params.h
Normal file
5
examples/1220-ffi-c-import-reserved-name-params.h
Normal file
@@ -0,0 +1,5 @@
|
||||
/* Foreign C declarations whose parameter names (`s1`, `s2`) collide with
|
||||
sx's reserved signed-int type spellings. The `#import c` exemption must
|
||||
accept these generated names unedited (issue 0089). */
|
||||
int ffi_pick(int s1, int s2, int which);
|
||||
int ffi_sum(int s1, int s2);
|
||||
20
examples/1220-ffi-c-import-reserved-name-params.sx
Normal file
20
examples/1220-ffi-c-import-reserved-name-params.sx
Normal file
@@ -0,0 +1,20 @@
|
||||
// `#import c` foreign-name exemption: a C header's parameter names `s1`/`s2`
|
||||
// collide with sx's reserved signed-int type spellings. Foreign decls are
|
||||
// treated as RAW — their names are never type-classified nor reserved-checked
|
||||
// — so the generated `#foreign` bindings import and call without hand-edits
|
||||
// (no backticks needed). Before issue 0089 this errored with "'s1' is a
|
||||
// reserved type name and cannot be used as an identifier".
|
||||
// Regression (issue 0089).
|
||||
#import "modules/std.sx";
|
||||
|
||||
#import c {
|
||||
#include "1220-ffi-c-import-reserved-name-params.h";
|
||||
#source "1220-ffi-c-import-reserved-name-params.c";
|
||||
};
|
||||
|
||||
main :: () -> s32 {
|
||||
print("pick(10,20,0) = {}\n", ffi_pick(10, 20, 0));
|
||||
print("pick(10,20,1) = {}\n", ffi_pick(10, 20, 1));
|
||||
print("sum(10,20) = {}\n", ffi_sum(10, 20));
|
||||
0
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
local = 8
|
||||
global = 100
|
||||
fn = 42
|
||||
field = 2.500000 9
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
pick(10,20,0) = 10
|
||||
pick(10,20,1) = 20
|
||||
sum(10,20) = 30
|
||||
Reference in New Issue
Block a user