diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e55238195a81a5e3ec6237f0e259933850c70fe..c2c692c61352a13bc8ab50470aaca7c3e6e4d562 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## 0.1.7 - chore: rename the language to "ix" +- feat: language manual gets a pleasing redesign - feat: allow any expression as a function body - fix: coerce `break` operands and implicit breaks to result type - fix: coerce results when `if` expression branches merge diff --git a/doc/language-manual.md b/doc/language-manual.md index ffca26d424414617bbe800242efbf1d5dc49b9b3..2b3563d1511bff5e23bc8943e4295e88d7677dd4 100644 --- a/doc/language-manual.md +++ b/doc/language-manual.md @@ -43,6 +43,14 @@ calling it when the program starts. > In the future, common APIs will be available in the standard library, such as > `std.log.info()`. For now, no such library exists. +## Module Scope and Declarations + +The top-level + +``` +let x = 1; +``` + ## Primitive Data Types | name | ts equivalent | description | @@ -61,19 +69,18 @@ calling it when the program starts. ### Built-in Constants -In addition to the above types being built-in constants, the following are -available. - | name | description | | ------- | ------------------------------------- | | `true` | boolean true (result of `1 == 1`) | | `false` | boolean false (result of `1 == 2`) | | `std` | handle to the standard library module | -These constants are reserved names, and it is an error to re-declare them. +These constants act as reserved names, and it is an error to re-declare them. +Note that primitive data types are also considered built-in constants. ```lang:build fn main { + let opaque = -5.2; let true = 1 == 0; } ``` @@ -185,7 +192,7 @@ The function body is a block, which may use implicit return to return. ```lang:run let print = @extern("console").log; -fn add(a: int, b: int) -> int { +fn add(a: int, b: int) { a + b } @@ -194,10 +201,6 @@ fn main { } ``` -> **Bug**: Return types are currently required. Omitting the `-> type` syntax -> currently makes the return type `void`, but this will be changed in the future -> to be an inferred return type. - The `return` expression can be used within functions to return early. ```lang:run @@ -296,69 +299,3 @@ fn main { print(Person{ name: "hello", age: 42 }); } ``` - -## A - -### B - -## C - -### a - -### somewhat long header name but still is within dave's reasonable-ish constraints - -#### Number Literals 2 - -TODO - -#### String Literals 2 - -TODO - -#### String WAdsafdsa - -TODO - -### hewwo - -cat - -### cat - -#### yeah - -## what - -## omg - -## Lorem ipsum dolor sit - -## amet, consectetur adipiscing - -## elit. Proin vulputate ligula - -## ac risus blandit, eu accumsan - -## rna feugiat. Phasellus quis - -## metus felis. Semper mattis - -## augue eu elementum. Sed nec odio - -## cursus neque fringilla rutrum. - -## Cras vestibulum bibendum hendrerit. - -## Duis porta, leo vel - -## sollicitudin rhoncus, arcu nulla - -## lobortis est, vitae interdum - -## quam ante eu ante. Integer luctus - -## justo a odio cursus auctor. Phasellus - -## blandit urna vitae quam dapibus - -## efficitur. Proin sagittis urna non diff --git a/src/core/Report.zig b/src/core/Report.zig index 8c485ec5132d66a1bb8cf08aad8be95eecf644fe..a24ea2b3b5924335cd6d76c444130094ad3957a6 100644 --- a/src/core/Report.zig +++ b/src/core/Report.zig @@ -5,8 +5,8 @@ //! //! Across the compiler, `Report.Builder`s' `.err` and `.warn` methods //! can add messages by ID. -errors: []Item, -warnings: []Item, +errors: []Item(Err), +warnings: []Item(Warn), string_bytes: []u8, pub const empty: Report = .{ @@ -18,23 +18,20 @@ pub const empty: Report = .{ pub var debug_show_report_trace: if (builtin.mode == .Debug) bool else void = if (builtin.mode == .Debug) false; -pub const Item = struct { - /// What is this diagnostic - data: union { @"error": Err, warn: Warn }, - - debug_stack_trace: DebugStoredTrace = .empty, - - /// Type is never stored, inferred from which list it is in. - pub const Type = enum { @"error", warn }; -}; +pub fn Item(T: type) type { + return struct { + data: T, + debug_stack_trace: DebugStoredTrace = .empty, + }; +} pub const Err = union(enum) { pub const FieldEnum = core.FieldEnum(Err); /// Constructs a `Report` with just a single error. pub fn toReport(err: Err, alloc: Allocator, trace: DebugStoredTrace) !Report { - const errors = try alloc.dupe(Item, &.{.{ - .data = .{ .@"error" = err }, + const errors = try alloc.dupe(Item(Err), &.{.{ + .data = err, .debug_stack_trace = trace, }}); return .{ .errors = errors, .warnings = &.{}, .string_bytes = &.{} }; @@ -641,7 +638,7 @@ pub fn dump(report: Report, ctx: DumpContext, out: core.OutStream) !void { const ast: *const Ast = switch (ctx) { .comp => |comp_ctx| // Ast cannot be queried if the error is in computing the Ast - if (report.errors.len > 0 and report.errors[0].data.@"error" == .ast) fake_ast: { + if (report.errors.len > 0 and report.errors[0].data == .ast) fake_ast: { fake_ast_data = .{ .utf8_source = (comp_ctx.file.getSource(comp_ctx.comp.gpa) catch { @panic("TODO"); @@ -695,18 +692,18 @@ pub fn dump(report: Report, ctx: DumpContext, out: core.OutStream) !void { }; for (report.errors) |item| { - try formatItem(item, .@"error", arena.allocator(), url, msg_ctx, out); + try formatItem(Err, item, arena.allocator(), url, msg_ctx, out); _ = arena.reset(.retain_capacity); } for (report.warnings) |item| { - try formatItem(item, .warn, arena.allocator(), url, msg_ctx, out); + try formatItem(Warn, item, arena.allocator(), url, msg_ctx, out); _ = arena.reset(.retain_capacity); } } fn formatItem( - item: Item, - item_type: Item.Type, + comptime T: type, + item: Item(T), arena: Allocator, url: []const u8, ctx_init: MsgContext, @@ -720,10 +717,8 @@ fn formatItem( ctx.components = ArrayListUnmanaged(Component).initCapacity(alloc, 16) catch unreachable; // stack-fallback allocator has enough space. - switch (item_type) { - inline else => |tag| switch (@field(item.data, @tagName(tag))) { - inline else => |payload| try payload.build(&ctx), - }, + switch (item.data) { + inline else => |payload| try payload.build(&ctx), } assert(ctx.components.items.len > 0); @@ -744,8 +739,10 @@ fn formatItem( for (ctx.components.items, 1..) |component, i| { const prefix: Prefix = if (i == 1) - switch (item_type) { - inline else => |tag| @field(Prefix, @tagName(tag)), + switch (T) { + Err => .@"error", + Warn => .warn, + else => @compileError(unreachable), } else .note; @@ -862,8 +859,8 @@ fn formatItem( pub const Builder = struct { gpa: Allocator, - errors: ArrayListUnmanaged(Item), - warnings: ArrayListUnmanaged(Item), + errors: ArrayListUnmanaged(Item(Err)), + warnings: ArrayListUnmanaged(Item(Warn)), string_bytes: ArrayListUnmanaged(u8), pub fn init(gpa: Allocator) Builder { @@ -890,7 +887,7 @@ pub const Builder = struct { return_address: usize, ) !void { try b.errors.append(b.gpa, .{ - .data = .{ .@"error" = @unionInit(Err, @tagName(kind), data) }, + .data = @unionInit(Err, @tagName(kind), data), .debug_stack_trace = DebugStoredTrace.capture(return_address), }); } @@ -902,7 +899,7 @@ pub const Builder = struct { return_address: usize, ) !void { try b.warnings.append(b.gpa, .{ - .data = .{ .warn = @unionInit(Warn, @tagName(kind), data) }, + .data = @unionInit(Warn, @tagName(kind), data), .debug_stack_trace = DebugStoredTrace.capture(return_address), }); } diff --git a/src/core/Sema.zig b/src/core/Sema.zig index ce5efa254618074d6fb1c0b16e30df1372d4bd02..b18358192c1a7dbd78d449a28c139f16143f8c01 100644 --- a/src/core/Sema.zig +++ b/src/core/Sema.zig @@ -46,7 +46,7 @@ instruction_step_lock: std.debug.SafetyLock, pub const Error = error{ /// The analysis of this branch or declaration has failed. - /// At least one error will be placed in the `Sema`'s report + /// At least one error will exist in `.report` AnalysisFail, /// There is a dependency on another declaration that we are waiting on. Interrupt,