The casing conventions have not been set, but there is no universe where
we allow $ as a recommended identifier character. we had this initially
because JavaScript allows it, but in practice people just use it in
frameworks to mean "magic". (see jQuery, Svelte, Qwik, etc)4 files changed, 15 insertions(+), 23 deletions(-)
CHANGELOG.md+3-2| ... | ... | @@ -1,9 +1,10 @@ |
| 1 | 1 | ## 0.1.4 |
| 2 | 2 | |
| 3 | - feat: implement string identifiers | |
| 4 | - feat: implement basic struct types | |
| 3 | - feat: implement basic struct types (#42) | |
| 4 | - feat: implement string identifiers (#54) | |
| 5 | 5 | - feat: include a `README.html` alongside compiler with documentation and code samples. |
| 6 | 6 | - feat(transform): include a warning for leading zero in numbers |
| 7 | - feat(tokenizer): `$` is no longer valid in identifiers | |
| 7 | 8 | - fix(sema): miscompilation using left side of all binary expression for both sides |
| 8 | 9 | - fix(sema): handle recursive function calls |
| 9 | 10 | - fix(sema): quit block analysis when hitting `noreturn` |
src/core/Report.zig+1-6| ... | ... | @@ -1130,12 +1130,7 @@ fn formatIdImpl( |
| 1130 | 1130 | var i: usize = 0; |
| 1131 | 1131 | while (i < inner.len) { |
| 1132 | 1132 | switch (inner[i]) { |
| 1133 | 'a'...'z', | |
| 1134 | 'A'...'Z', | |
| 1135 | '0'...'9', | |
| 1136 | '_', | |
| 1137 | '$', | |
| 1138 | => { | |
| 1133 | 'a'...'z', 'A'...'Z', '0'...'9', '_' => { | |
| 1139 | 1134 | i += 1; |
| 1140 | 1135 | continue; |
| 1141 | 1136 | }, |
src/core/Tokenizer.zig+3-3| ... | ... | @@ -322,7 +322,7 @@ pub fn next(t: *Tokenizer) !?Token { |
| 322 | 322 | switch (t.byte()) { |
| 323 | 323 | ' ', '\t', '\n', '\r' => unreachable, // call skipWhitespace |
| 324 | 324 | |
| 325 | 'a'...'z', 'A'...'Z', '_', '$' => { | |
| 325 | 'a'...'z', 'A'...'Z', '_' => { | |
| 326 | 326 | const start = t.pos; |
| 327 | 327 | t.pos += 1; |
| 328 | 328 | return try t.tokenizeIdentifier(start); |
| ... | ... | @@ -563,7 +563,7 @@ fn codePoint(t: Tokenizer) !struct { u3, u21 } { |
| 563 | 563 | |
| 564 | 564 | fn isAtIdentifierStart(t: *Tokenizer) !bool { |
| 565 | 565 | switch (t.byte()) { |
| 566 | 'a'...'z', 'A'...'Z', '_', '$' => return true, | |
| 566 | 'a'...'z', 'A'...'Z', '_' => return true, | |
| 567 | 567 | else => return false, |
| 568 | 568 | 0x80...0xFF => { |
| 569 | 569 | _, const code_point = try t.codePoint(); |
| ... | ... | @@ -578,7 +578,7 @@ fn tokenizeIdentifier(t: *Tokenizer, start_byte: u32) !Token { |
| 578 | 578 | |
| 579 | 579 | while (true) { |
| 580 | 580 | switch (t.byte()) { |
| 581 | 'a'...'z', 'A'...'Z', '0'...'9', '_', '$' => { | |
| 581 | 'a'...'z', 'A'...'Z', '0'...'9', '_' => { | |
| 582 | 582 | t.pos += 1; |
| 583 | 583 | }, |
| 584 | 584 | 0x80...0xFF => { |
src/core/Transform.zig+8-12| ... | ... | @@ -6,8 +6,8 @@ |
| 6 | 6 | //! - Annotating expression statements with `.discard` and `.ensure_void` |
| 7 | 7 | //! - Flattening nested expressions into instruction sequences. |
| 8 | 8 | //! |
| 9 | //! Some trivial diagnostics such as unused variables, unknown result locations, and | |
| 10 | //! invalid assignment targets are also reported here. | |
| 9 | //! Some trivial diagnostics such as unused variables, unknown result types, | |
| 10 | //! invalid assignment targets, and other style issues are also reported here. | |
| 11 | 11 | gpa: Allocator, |
| 12 | 12 | ast: Ast, |
| 13 | 13 | insts: Inst.List = .{}, |
| ... | ... | @@ -22,9 +22,9 @@ scopes: std.ArrayListUnmanaged(Scope) = .{}, |
| 22 | 22 | report: Report.Builder, |
| 23 | 23 | |
| 24 | 24 | pub const Error = error{ |
| 25 | OutOfMemory, | |
| 25 | /// A `Report` will contain at least one error. | |
| 26 | 26 | TransformFail, |
| 27 | }; | |
| 27 | } || Allocator.Error; | |
| 28 | 28 | |
| 29 | 29 | pub fn transform( |
| 30 | 30 | ast: Ast, |
| ... | ... | @@ -61,7 +61,7 @@ pub fn transform( |
| 61 | 61 | |
| 62 | 62 | try t.insts.setCapacity(t.gpa, t.insts.len); |
| 63 | 63 | |
| 64 | return Teg{ | |
| 64 | return .{ | |
| 65 | 65 | .insts = t.insts.toOwnedSlice(), |
| 66 | 66 | .string_bytes = try t.string_bytes.toOwnedSlice(t.gpa), |
| 67 | 67 | .extra = try t.extra.toOwnedStore(t.gpa), |
| ... | ... | @@ -142,18 +142,14 @@ const Scope = struct { |
| 142 | 142 | } |
| 143 | 143 | }; |
| 144 | 144 | |
| 145 | const ScratchType = enum { | |
| 146 | ref, | |
| 147 | index, | |
| 148 | }; | |
| 149 | ||
| 150 | 145 | const BlockContext = struct { |
| 151 | 146 | node_base: i32, |
| 152 | 147 | return_target: ?*?Inst.Index = null, |
| 153 | 148 | break_target: ?*BreakTarget = null, |
| 154 | 149 | |
| 155 | /// This struct is always stored on the stack; the idea is to pass | |
| 156 | /// mutable pointers to it. When `break :brk` is encountered | |
| 150 | /// This struct is always stored on the stack; the idea is to pass mutable | |
| 151 | /// pointers to it. When `break :brk` is encountered, it will generate the | |
| 152 | /// block instruction. This way, redundant blocks are never created. | |
| 157 | 153 | const BreakTarget = struct { |
| 158 | 154 | label: ?[]const u8, |
| 159 | 155 | /// This allows `continue` as well as implicit break targeting. |