diff --git a/src/canonicalize/Can.zig b/src/canonicalize/Can.zig index 252f21c3ed..d9efb51e9f 100644 --- a/src/canonicalize/Can.zig +++ b/src/canonicalize/Can.zig @@ -5070,13 +5070,171 @@ pub fn canonicalizeExpr( const free_vars_span = self.scratch_free_vars.spanFrom(free_vars_start); return CanonicalizedExpr{ .idx = expr_idx, .free_vars = if (free_vars_span.len > 0) free_vars_span else null }; }, - .suffix_single_question => |_| { - const feature = try self.env.insertString("canonicalize suffix_single_question expression"); - const expr_idx = try self.env.pushMalformed(Expr.Idx, Diagnostic{ .not_implemented = .{ - .feature = feature, - .region = Region.zero(), - } }); - return CanonicalizedExpr{ .idx = expr_idx, .free_vars = null }; + .suffix_single_question => |unary| { + // Desugar `expr?` into: + // match expr { + // Ok(#ok) => #ok, + // Err(#err) => return Err(#err), + // } + const region = self.parse_ir.tokenizedRegionToRegion(unary.region); + + const free_vars_start = self.scratch_free_vars.top(); + + // Canonicalize the inner expression (the expression before `?`) + const can_cond = try self.canonicalizeExpr(unary.expr) orelse return null; + + // Use pre-interned identifiers for the Ok/Err values and tag names + const ok_val_ident = self.env.idents.question_ok; + const err_val_ident = self.env.idents.question_err; + const ok_tag_ident = self.env.idents.ok; + const err_tag_ident = self.env.idents.err; + + // Mark the start of scratch match branches + const scratch_top = self.env.store.scratchMatchBranchTop(); + + // === Branch 1: Ok(#ok) => #ok === + { + // Enter a new scope for this branch + try self.scopeEnter(self.env.gpa, false); + defer self.scopeExit(self.env.gpa) catch {}; + + // Create the assign pattern for the Ok value + const ok_assign_pattern_idx = try self.env.addPattern(Pattern{ + .assign = .{ .ident = ok_val_ident }, + }, region); + + // Introduce the pattern into scope + _ = try self.scopeIntroduceInternal(self.env.gpa, .ident, ok_val_ident, ok_assign_pattern_idx, false, true); + + // Create pattern span for Ok tag argument + const ok_patterns_start = self.env.store.scratchPatternTop(); + try self.env.store.addScratchPattern(ok_assign_pattern_idx); + const ok_args_span = try self.env.store.patternSpanFrom(ok_patterns_start); + + // Create the Ok tag pattern: Ok(#ok) + const ok_tag_pattern_idx = try self.env.addPattern(Pattern{ + .applied_tag = .{ + .name = ok_tag_ident, + .args = ok_args_span, + }, + }, region); + + // Create branch pattern + const branch_pat_scratch_top = self.env.store.scratchMatchBranchPatternTop(); + const ok_branch_pattern_idx = try self.env.addMatchBranchPattern(Expr.Match.BranchPattern{ + .pattern = ok_tag_pattern_idx, + .degenerate = false, + }, region); + try self.env.store.addScratchMatchBranchPattern(ok_branch_pattern_idx); + const ok_branch_pat_span = try self.env.store.matchBranchPatternSpanFrom(branch_pat_scratch_top); + + // Create the branch body: lookup #ok + const ok_lookup_idx = try self.env.addExpr(CIR.Expr{ .e_lookup_local = .{ + .pattern_idx = ok_assign_pattern_idx, + } }, region); + // Mark the pattern as used + try self.used_patterns.put(self.env.gpa, ok_assign_pattern_idx, {}); + + // Create the Ok branch + const ok_branch_idx = try self.env.addMatchBranch( + Expr.Match.Branch{ + .patterns = ok_branch_pat_span, + .value = ok_lookup_idx, + .guard = null, + .redundant = @enumFromInt(0), + }, + region, + ); + try self.env.store.addScratchMatchBranch(ok_branch_idx); + } + + // === Branch 2: Err(#err) => return Err(#err) === + { + // Enter a new scope for this branch + try self.scopeEnter(self.env.gpa, false); + defer self.scopeExit(self.env.gpa) catch {}; + + // Create the assign pattern for the Err value + const err_assign_pattern_idx = try self.env.addPattern(Pattern{ + .assign = .{ .ident = err_val_ident }, + }, region); + + // Introduce the pattern into scope + _ = try self.scopeIntroduceInternal(self.env.gpa, .ident, err_val_ident, err_assign_pattern_idx, false, true); + + // Create pattern span for Err tag argument + const err_patterns_start = self.env.store.scratchPatternTop(); + try self.env.store.addScratchPattern(err_assign_pattern_idx); + const err_args_span = try self.env.store.patternSpanFrom(err_patterns_start); + + // Create the Err tag pattern: Err(#err) + const err_tag_pattern_idx = try self.env.addPattern(Pattern{ + .applied_tag = .{ + .name = err_tag_ident, + .args = err_args_span, + }, + }, region); + + // Create branch pattern + const branch_pat_scratch_top = self.env.store.scratchMatchBranchPatternTop(); + const err_branch_pattern_idx = try self.env.addMatchBranchPattern(Expr.Match.BranchPattern{ + .pattern = err_tag_pattern_idx, + .degenerate = false, + }, region); + try self.env.store.addScratchMatchBranchPattern(err_branch_pattern_idx); + const err_branch_pat_span = try self.env.store.matchBranchPatternSpanFrom(branch_pat_scratch_top); + + // Create the branch body: return Err(#err) + // First, create lookup for #err + const err_lookup_idx = try self.env.addExpr(CIR.Expr{ .e_lookup_local = .{ + .pattern_idx = err_assign_pattern_idx, + } }, region); + // Mark the pattern as used + try self.used_patterns.put(self.env.gpa, err_assign_pattern_idx, {}); + + // Create Err(#err) tag expression + const err_tag_args_start = self.env.store.scratchExprTop(); + try self.env.store.addScratchExpr(err_lookup_idx); + const err_tag_args_span = try self.env.store.exprSpanFrom(err_tag_args_start); + + const err_tag_expr_idx = try self.env.addExpr(CIR.Expr{ + .e_tag = .{ + .name = err_tag_ident, + .args = err_tag_args_span, + }, + }, region); + + // Create return Err(#err) expression + const return_expr_idx = try self.env.addExpr(CIR.Expr{ .e_return = .{ + .expr = err_tag_expr_idx, + } }, region); + + // Create the Err branch + const err_branch_idx = try self.env.addMatchBranch( + Expr.Match.Branch{ + .patterns = err_branch_pat_span, + .value = return_expr_idx, + .guard = null, + .redundant = @enumFromInt(0), + }, + region, + ); + try self.env.store.addScratchMatchBranch(err_branch_idx); + } + + // Create span from scratch branches + const branches_span = try self.env.store.matchBranchSpanFrom(scratch_top); + + // Create the match expression + const match_expr = Expr.Match{ + .cond = can_cond.idx, + .branches = branches_span, + .exhaustive = @enumFromInt(0), // Will be set during type checking + }; + const expr_idx = try self.env.addExpr(CIR.Expr{ .e_match = match_expr }, region); + + const free_vars_span = self.scratch_free_vars.spanFrom(free_vars_start); + return CanonicalizedExpr{ .idx = expr_idx, .free_vars = if (free_vars_span.len > 0) free_vars_span else null }; }, .unary_op => |unary| { const region = self.parse_ir.tokenizedRegionToRegion(unary.region); @@ -6348,21 +6506,63 @@ fn canonicalizePattern( .string => |e| { const region = self.parse_ir.tokenizedRegionToRegion(e.region); - // resolve to a string slice from the source - const token_text = self.parse_ir.resolve(e.string_tok); + // Get the string expression which contains the actual string parts + const str_expr = self.parse_ir.store.getExpr(e.expr); - // TODO: Handle escape sequences - // For now, just intern the raw string - const literal = try self.env.insertString(token_text); + switch (str_expr) { + .string => |se| { + // Get the parts of the string expression + const parts = self.parse_ir.store.exprSlice(se.parts); - const str_pattern = Pattern{ - .str_literal = .{ - .literal = literal, + // For simple string literals, there should be exactly one string_part + if (parts.len == 1) { + const part = self.parse_ir.store.getExpr(parts[0]); + switch (part) { + .string_part => |sp| { + // Get the actual string content from the string_part token + const part_text = self.parse_ir.resolve(sp.token); + + // Process escape sequences + const processed_text = try processEscapeSequences(self.env.gpa, part_text); + defer if (processed_text.ptr != part_text.ptr) { + self.env.gpa.free(processed_text); + }; + + const literal = try self.env.insertString(processed_text); + + const str_pattern = Pattern{ + .str_literal = .{ + .literal = literal, + }, + }; + const pattern_idx = try self.env.addPattern(str_pattern, region); + + return pattern_idx; + }, + else => {}, + } + } + + // For string patterns with interpolation or multiple parts, + // we need more complex handling (not yet supported) + const malformed = try self.env.pushMalformed(Pattern.Idx, Diagnostic{ + .not_implemented = .{ + .feature = try self.env.insertString("string patterns with interpolation"), + .region = region, + }, + }); + return malformed; }, - }; - const pattern_idx = try self.env.addPattern(str_pattern, region); - - return pattern_idx; + else => { + // Unexpected expression type in string pattern + const malformed = try self.env.pushMalformed(Pattern.Idx, Diagnostic{ + .pattern_arg_invalid = .{ + .region = region, + }, + }); + return malformed; + }, + } }, .single_quote => |e| { return try self.canonicalizeSingleQuote(e.region, e.token, Pattern.Idx); diff --git a/src/canonicalize/ModuleEnv.zig b/src/canonicalize/ModuleEnv.zig index 6a6bdcc5ad..639812fa02 100644 --- a/src/canonicalize/ModuleEnv.zig +++ b/src/canonicalize/ModuleEnv.zig @@ -163,6 +163,9 @@ pub const CommonIdents = extern struct { // from_utf8 error payload fields (BadUtf8 record) problem: Ident.Idx, index: Ident.Idx, + // Synthetic identifiers for ? operator desugaring + question_ok: Ident.Idx, + question_err: Ident.Idx, /// Insert all well-known identifiers into a CommonEnv. /// Use this when creating a fresh ModuleEnv from scratch. @@ -228,6 +231,9 @@ pub const CommonIdents = extern struct { // from_utf8 error payload fields (BadUtf8 record) .problem = try common.insertIdent(gpa, Ident.for_text("problem")), .index = try common.insertIdent(gpa, Ident.for_text("index")), + // Synthetic identifiers for ? operator desugaring + .question_ok = try common.insertIdent(gpa, Ident.for_text("#ok")), + .question_err = try common.insertIdent(gpa, Ident.for_text("#err")), }; } @@ -296,6 +302,9 @@ pub const CommonIdents = extern struct { // from_utf8 error payload fields (BadUtf8 record) .problem = common.findIdent("problem") orelse unreachable, .index = common.findIdent("index") orelse unreachable, + // Synthetic identifiers for ? operator desugaring + .question_ok = common.findIdent("#ok") orelse unreachable, + .question_err = common.findIdent("#err") orelse unreachable, }; } }; diff --git a/src/cli/test/fx_platform_test.zig b/src/cli/test/fx_platform_test.zig index b38ebba3cf..1fdf2acd18 100644 --- a/src/cli/test/fx_platform_test.zig +++ b/src/cli/test/fx_platform_test.zig @@ -681,3 +681,67 @@ test "fx platform run from different cwd" { // Verify stdout contains expected messages try testing.expect(std.mem.indexOf(u8, run_result.stdout, "Hello from stdout!") != null); } + +test "question mark operator" { + // Tests the `?` operator for error propagation. + const allocator = testing.allocator; + + try ensureRocBinary(allocator); + + const run_result = try std.process.Child.run(.{ + .allocator = allocator, + .argv = &[_][]const u8{ + "./zig-out/bin/roc", + "test/fx/question_mark_operator.roc", + }, + }); + defer allocator.free(run_result.stdout); + defer allocator.free(run_result.stderr); + + // The ? operator should unwrap Ok values and return "hello" + try testing.expect(std.mem.indexOf(u8, run_result.stdout, "hello") != null); +} + +test "numeric fold" { + // Tests List.fold with numeric accumulators. + const allocator = testing.allocator; + + try ensureRocBinary(allocator); + + const run_result = try std.process.Child.run(.{ + .allocator = allocator, + .argv = &[_][]const u8{ + "./zig-out/bin/roc", + "test/fx/numeric_fold.roc", + }, + }); + defer allocator.free(run_result.stdout); + defer allocator.free(run_result.stderr); + + // Verify we get the correct sum: 1+2+3+4+5 = 15 + try testing.expect(std.mem.indexOf(u8, run_result.stdout, "Sum: 15") != null); +} + +test "string literal pattern matching" { + // Tests pattern matching on string literals in match expressions. + const allocator = testing.allocator; + + try ensureRocBinary(allocator); + + const run_result = try std.process.Child.run(.{ + .allocator = allocator, + .argv = &[_][]const u8{ + "./zig-out/bin/roc", + "test/fx/string_pattern_matching.roc", + }, + }); + defer allocator.free(run_result.stdout); + defer allocator.free(run_result.stderr); + + // Verify string patterns match correctly + const has_alice = std.mem.indexOf(u8, run_result.stdout, "Hello Alice!") != null; + const has_bob = std.mem.indexOf(u8, run_result.stdout, "Hey Bob!") != null; + + try testing.expect(has_alice); + try testing.expect(has_bob); +} diff --git a/src/eval/interpreter.zig b/src/eval/interpreter.zig index 69fd6264d2..6b462106f9 100644 --- a/src/eval/interpreter.zig +++ b/src/eval/interpreter.zig @@ -2034,9 +2034,17 @@ pub const Interpreter = struct { std.debug.assert(args.len == 2); // low-level .num_is_eq expects 2 arguments const lhs = try self.extractNumericValue(args[0]); const rhs = try self.extractNumericValue(args[1]); - const result = switch (lhs) { - .int => |l| l == rhs.int, - .dec => |l| l.num == rhs.dec.num, + const result: bool = switch (lhs) { + .int => |l| switch (rhs) { + .int => |r| l == r, + .dec => |r| l == @divTrunc(r.num, RocDec.one_point_zero_i128), + else => return error.TypeMismatch, + }, + .dec => |l| switch (rhs) { + .dec => |r| l.num == r.num, + .int => |r| l.num == @as(i128, r) * RocDec.one_point_zero_i128, + else => return error.TypeMismatch, + }, .f32, .f64 => { self.triggerCrash("Equality comparison not supported for F32/F64 due to floating point imprecision", false, roc_ops); return error.Crash; @@ -2049,11 +2057,27 @@ pub const Interpreter = struct { std.debug.assert(args.len == 2); // low-level .num_is_gt expects 2 arguments const lhs = try self.extractNumericValue(args[0]); const rhs = try self.extractNumericValue(args[1]); - const result = switch (lhs) { - .int => |l| l > rhs.int, - .f32 => |l| l > rhs.f32, - .f64 => |l| l > rhs.f64, - .dec => |l| l.num > rhs.dec.num, + const result: bool = switch (lhs) { + .int => |l| switch (rhs) { + .int => |r| l > r, + // Int vs Dec: convert Dec to Int for comparison + .dec => |r| l > @divTrunc(r.num, RocDec.one_point_zero_i128), + else => return error.TypeMismatch, + }, + .f32 => |l| switch (rhs) { + .f32 => |r| l > r, + else => return error.TypeMismatch, + }, + .f64 => |l| switch (rhs) { + .f64 => |r| l > r, + else => return error.TypeMismatch, + }, + .dec => |l| switch (rhs) { + .dec => |r| l.num > r.num, + // Dec vs Int: convert Int to Dec for comparison + .int => |r| l.num > @as(i128, r) * RocDec.one_point_zero_i128, + else => return error.TypeMismatch, + }, }; return try self.makeBoolValue(result); }, @@ -2062,11 +2086,25 @@ pub const Interpreter = struct { std.debug.assert(args.len == 2); // low-level .num_is_gte expects 2 arguments const lhs = try self.extractNumericValue(args[0]); const rhs = try self.extractNumericValue(args[1]); - const result = switch (lhs) { - .int => |l| l >= rhs.int, - .f32 => |l| l >= rhs.f32, - .f64 => |l| l >= rhs.f64, - .dec => |l| l.num >= rhs.dec.num, + const result: bool = switch (lhs) { + .int => |l| switch (rhs) { + .int => |r| l >= r, + .dec => |r| l >= @divTrunc(r.num, RocDec.one_point_zero_i128), + else => return error.TypeMismatch, + }, + .f32 => |l| switch (rhs) { + .f32 => |r| l >= r, + else => return error.TypeMismatch, + }, + .f64 => |l| switch (rhs) { + .f64 => |r| l >= r, + else => return error.TypeMismatch, + }, + .dec => |l| switch (rhs) { + .dec => |r| l.num >= r.num, + .int => |r| l.num >= @as(i128, r) * RocDec.one_point_zero_i128, + else => return error.TypeMismatch, + }, }; return try self.makeBoolValue(result); }, @@ -2075,11 +2113,25 @@ pub const Interpreter = struct { std.debug.assert(args.len == 2); // low-level .num_is_lt expects 2 arguments const lhs = try self.extractNumericValue(args[0]); const rhs = try self.extractNumericValue(args[1]); - const result = switch (lhs) { - .int => |l| l < rhs.int, - .f32 => |l| l < rhs.f32, - .f64 => |l| l < rhs.f64, - .dec => |l| l.num < rhs.dec.num, + const result: bool = switch (lhs) { + .int => |l| switch (rhs) { + .int => |r| l < r, + .dec => |r| l < @divTrunc(r.num, RocDec.one_point_zero_i128), + else => return error.TypeMismatch, + }, + .f32 => |l| switch (rhs) { + .f32 => |r| l < r, + else => return error.TypeMismatch, + }, + .f64 => |l| switch (rhs) { + .f64 => |r| l < r, + else => return error.TypeMismatch, + }, + .dec => |l| switch (rhs) { + .dec => |r| l.num < r.num, + .int => |r| l.num < @as(i128, r) * RocDec.one_point_zero_i128, + else => return error.TypeMismatch, + }, }; return try self.makeBoolValue(result); }, @@ -2088,11 +2140,25 @@ pub const Interpreter = struct { std.debug.assert(args.len == 2); // low-level .num_is_lte expects 2 arguments const lhs = try self.extractNumericValue(args[0]); const rhs = try self.extractNumericValue(args[1]); - const result = switch (lhs) { - .int => |l| l <= rhs.int, - .f32 => |l| l <= rhs.f32, - .f64 => |l| l <= rhs.f64, - .dec => |l| l.num <= rhs.dec.num, + const result: bool = switch (lhs) { + .int => |l| switch (rhs) { + .int => |r| l <= r, + .dec => |r| l <= @divTrunc(r.num, RocDec.one_point_zero_i128), + else => return error.TypeMismatch, + }, + .f32 => |l| switch (rhs) { + .f32 => |r| l <= r, + else => return error.TypeMismatch, + }, + .f64 => |l| switch (rhs) { + .f64 => |r| l <= r, + else => return error.TypeMismatch, + }, + .dec => |l| switch (rhs) { + .dec => |r| l.num <= r.num, + .int => |r| l.num <= @as(i128, r) * RocDec.one_point_zero_i128, + else => return error.TypeMismatch, + }, }; return try self.makeBoolValue(result); }, @@ -2126,10 +2192,24 @@ pub const Interpreter = struct { out.is_initialized = false; switch (lhs) { - .int => |l| try out.setInt(l + rhs.int), - .f32 => |l| out.setF32(l + rhs.f32), - .f64 => |l| out.setF64(l + rhs.f64), - .dec => |l| out.setDec(RocDec.add(l, rhs.dec, roc_ops)), + .int => |l| switch (rhs) { + .int => |r| try out.setInt(l + r), + .dec => |r| try out.setInt(l + @divTrunc(r.num, RocDec.one_point_zero_i128)), + else => return error.TypeMismatch, + }, + .f32 => |l| switch (rhs) { + .f32 => |r| out.setF32(l + r), + else => return error.TypeMismatch, + }, + .f64 => |l| switch (rhs) { + .f64 => |r| out.setF64(l + r), + else => return error.TypeMismatch, + }, + .dec => |l| switch (rhs) { + .dec => |r| out.setDec(RocDec.add(l, r, roc_ops)), + .int => |r| out.setDec(RocDec.add(l, RocDec{ .num = @as(i128, r) * RocDec.one_point_zero_i128 }, roc_ops)), + else => return error.TypeMismatch, + }, } out.is_initialized = true; return out; @@ -2144,10 +2224,24 @@ pub const Interpreter = struct { out.is_initialized = false; switch (lhs) { - .int => |l| try out.setInt(l - rhs.int), - .f32 => |l| out.setF32(l - rhs.f32), - .f64 => |l| out.setF64(l - rhs.f64), - .dec => |l| out.setDec(RocDec.sub(l, rhs.dec, roc_ops)), + .int => |l| switch (rhs) { + .int => |r| try out.setInt(l - r), + .dec => |r| try out.setInt(l - @divTrunc(r.num, RocDec.one_point_zero_i128)), + else => return error.TypeMismatch, + }, + .f32 => |l| switch (rhs) { + .f32 => |r| out.setF32(l - r), + else => return error.TypeMismatch, + }, + .f64 => |l| switch (rhs) { + .f64 => |r| out.setF64(l - r), + else => return error.TypeMismatch, + }, + .dec => |l| switch (rhs) { + .dec => |r| out.setDec(RocDec.sub(l, r, roc_ops)), + .int => |r| out.setDec(RocDec.sub(l, RocDec{ .num = @as(i128, r) * RocDec.one_point_zero_i128 }, roc_ops)), + else => return error.TypeMismatch, + }, } out.is_initialized = true; return out; @@ -2162,10 +2256,24 @@ pub const Interpreter = struct { out.is_initialized = false; switch (lhs) { - .int => |l| try out.setInt(l * rhs.int), - .f32 => |l| out.setF32(l * rhs.f32), - .f64 => |l| out.setF64(l * rhs.f64), - .dec => |l| out.setDec(RocDec.mul(l, rhs.dec, roc_ops)), + .int => |l| switch (rhs) { + .int => |r| try out.setInt(l * r), + .dec => |r| try out.setInt(l * @divTrunc(r.num, RocDec.one_point_zero_i128)), + else => return error.TypeMismatch, + }, + .f32 => |l| switch (rhs) { + .f32 => |r| out.setF32(l * r), + else => return error.TypeMismatch, + }, + .f64 => |l| switch (rhs) { + .f64 => |r| out.setF64(l * r), + else => return error.TypeMismatch, + }, + .dec => |l| switch (rhs) { + .dec => |r| out.setDec(RocDec.mul(l, r, roc_ops)), + .int => |r| out.setDec(RocDec.mul(l, RocDec{ .num = @as(i128, r) * RocDec.one_point_zero_i128 }, roc_ops)), + else => return error.TypeMismatch, + }, } out.is_initialized = true; return out; @@ -2180,21 +2288,43 @@ pub const Interpreter = struct { out.is_initialized = false; switch (lhs) { - .int => |l| { - if (rhs.int == 0) return error.DivisionByZero; - try out.setInt(@divTrunc(l, rhs.int)); + .int => |l| switch (rhs) { + .int => |r| { + if (r == 0) return error.DivisionByZero; + try out.setInt(@divTrunc(l, r)); + }, + .dec => |r| { + const r_int = @divTrunc(r.num, RocDec.one_point_zero_i128); + if (r_int == 0) return error.DivisionByZero; + try out.setInt(@divTrunc(l, r_int)); + }, + else => return error.TypeMismatch, }, - .f32 => |l| { - if (rhs.f32 == 0) return error.DivisionByZero; - out.setF32(l / rhs.f32); + .f32 => |l| switch (rhs) { + .f32 => |r| { + if (r == 0) return error.DivisionByZero; + out.setF32(l / r); + }, + else => return error.TypeMismatch, }, - .f64 => |l| { - if (rhs.f64 == 0) return error.DivisionByZero; - out.setF64(l / rhs.f64); + .f64 => |l| switch (rhs) { + .f64 => |r| { + if (r == 0) return error.DivisionByZero; + out.setF64(l / r); + }, + else => return error.TypeMismatch, }, - .dec => |l| { - if (rhs.dec.num == 0) return error.DivisionByZero; - out.setDec(RocDec.div(l, rhs.dec, roc_ops)); + .dec => |l| switch (rhs) { + .dec => |r| { + if (r.num == 0) return error.DivisionByZero; + out.setDec(RocDec.div(l, r, roc_ops)); + }, + .int => |r| { + if (r == 0) return error.DivisionByZero; + const r_dec = RocDec{ .num = @as(i128, r) * RocDec.one_point_zero_i128 }; + out.setDec(RocDec.div(l, r_dec, roc_ops)); + }, + else => return error.TypeMismatch, }, } out.is_initialized = true; @@ -2210,22 +2340,44 @@ pub const Interpreter = struct { out.is_initialized = false; switch (lhs) { - .int => |l| { - if (rhs.int == 0) return error.DivisionByZero; - try out.setInt(@divTrunc(l, rhs.int)); + .int => |l| switch (rhs) { + .int => |r| { + if (r == 0) return error.DivisionByZero; + try out.setInt(@divTrunc(l, r)); + }, + .dec => |r| { + const r_int = @divTrunc(r.num, RocDec.one_point_zero_i128); + if (r_int == 0) return error.DivisionByZero; + try out.setInt(@divTrunc(l, r_int)); + }, + else => return error.TypeMismatch, }, - .f32 => |l| { - if (rhs.f32 == 0) return error.DivisionByZero; - out.setF32(@trunc(l / rhs.f32)); + .f32 => |l| switch (rhs) { + .f32 => |r| { + if (r == 0) return error.DivisionByZero; + out.setF32(@trunc(l / r)); + }, + else => return error.TypeMismatch, }, - .f64 => |l| { - if (rhs.f64 == 0) return error.DivisionByZero; - out.setF64(@trunc(l / rhs.f64)); + .f64 => |l| switch (rhs) { + .f64 => |r| { + if (r == 0) return error.DivisionByZero; + out.setF64(@trunc(l / r)); + }, + else => return error.TypeMismatch, }, - .dec => |l| { - // For Dec, div and div_trunc are the same since it's already integer-like - if (rhs.dec.num == 0) return error.DivisionByZero; - out.setDec(RocDec.div(l, rhs.dec, roc_ops)); + .dec => |l| switch (rhs) { + .dec => |r| { + // For Dec, div and div_trunc are the same since it's already integer-like + if (r.num == 0) return error.DivisionByZero; + out.setDec(RocDec.div(l, r, roc_ops)); + }, + .int => |r| { + if (r == 0) return error.DivisionByZero; + const r_dec = RocDec{ .num = @as(i128, r) * RocDec.one_point_zero_i128 }; + out.setDec(RocDec.div(l, r_dec, roc_ops)); + }, + else => return error.TypeMismatch, }, } out.is_initialized = true; @@ -2241,21 +2393,43 @@ pub const Interpreter = struct { out.is_initialized = false; switch (lhs) { - .int => |l| { - if (rhs.int == 0) return error.DivisionByZero; - try out.setInt(@rem(l, rhs.int)); + .int => |l| switch (rhs) { + .int => |r| { + if (r == 0) return error.DivisionByZero; + try out.setInt(@rem(l, r)); + }, + .dec => |r| { + const r_int = @divTrunc(r.num, RocDec.one_point_zero_i128); + if (r_int == 0) return error.DivisionByZero; + try out.setInt(@rem(l, r_int)); + }, + else => return error.TypeMismatch, }, - .f32 => |l| { - if (rhs.f32 == 0) return error.DivisionByZero; - out.setF32(@rem(l, rhs.f32)); + .f32 => |l| switch (rhs) { + .f32 => |r| { + if (r == 0) return error.DivisionByZero; + out.setF32(@rem(l, r)); + }, + else => return error.TypeMismatch, }, - .f64 => |l| { - if (rhs.f64 == 0) return error.DivisionByZero; - out.setF64(@rem(l, rhs.f64)); + .f64 => |l| switch (rhs) { + .f64 => |r| { + if (r == 0) return error.DivisionByZero; + out.setF64(@rem(l, r)); + }, + else => return error.TypeMismatch, }, - .dec => |l| { - if (rhs.dec.num == 0) return error.DivisionByZero; - out.setDec(RocDec.rem(l, rhs.dec, roc_ops)); + .dec => |l| switch (rhs) { + .dec => |r| { + if (r.num == 0) return error.DivisionByZero; + out.setDec(RocDec.rem(l, r, roc_ops)); + }, + .int => |r| { + if (r == 0) return error.DivisionByZero; + const r_dec = RocDec{ .num = @as(i128, r) * RocDec.one_point_zero_i128 }; + out.setDec(RocDec.rem(l, r_dec, roc_ops)); + }, + else => return error.TypeMismatch, }, } out.is_initialized = true; @@ -4338,6 +4512,36 @@ pub const Interpreter = struct { if (lhs.layout.tag == .scalar and rhs.layout.tag == .scalar) { const lhs_scalar = lhs.layout.data.scalar; const rhs_scalar = rhs.layout.data.scalar; + + // Handle numeric type mismatches (Int vs Dec) + const lhs_is_numeric = lhs_scalar.tag == .int or lhs_scalar.tag == .frac; + const rhs_is_numeric = rhs_scalar.tag == .int or rhs_scalar.tag == .frac; + if (lhs_is_numeric and rhs_is_numeric) { + // Allow comparing Int with Dec by converting + const lhs_num = self.extractNumericValue(lhs) catch return error.TypeMismatch; + const rhs_num = self.extractNumericValue(rhs) catch return error.TypeMismatch; + return switch (lhs_num) { + .int => |l| switch (rhs_num) { + .int => |r| l == r, + .dec => |r| l == @divTrunc(r.num, RocDec.one_point_zero_i128), + else => false, + }, + .dec => |l| switch (rhs_num) { + .dec => |r| l.num == r.num, + .int => |r| l.num == @as(i128, r) * RocDec.one_point_zero_i128, + else => false, + }, + .f32 => |l| switch (rhs_num) { + .f32 => |r| l == r, + else => false, + }, + .f64 => |l| switch (rhs_num) { + .f64 => |r| l == r, + else => false, + }, + }; + } + if (lhs_scalar.tag != rhs_scalar.tag) return error.TypeMismatch; switch (lhs_scalar.tag) { @@ -5655,14 +5859,15 @@ pub const Interpreter = struct { try self.ensureVarLayoutCapacity(idx + 1); const slot_ptr = &self.var_to_layout_slot.items[idx]; - // If we have a flex var, default it to Dec - // This is the interpreter-time defaulting for numeric literals + // If we have a flex var, default it to I64 (not Dec) + // This is the interpreter-time defaulting for unresolved numeric types. + // Integer literals should default to I64, not Dec. if (resolved.desc.content == .flex) { - // Directly return Dec's scalar layout - const dec_layout = layout.Layout.frac(types.Frac.Precision.dec); - const dec_layout_idx = try self.runtime_layout_store.insertLayout(dec_layout); - slot_ptr.* = @intFromEnum(dec_layout_idx) + 1; - return dec_layout; + // Default to I64 for better compatibility with integer operations + const i64_layout = layout.Layout.int(types.Int.Precision.i64); + const i64_layout_idx = try self.runtime_layout_store.insertLayout(i64_layout); + slot_ptr.* = @intFromEnum(i64_layout_idx) + 1; + return i64_layout; } if (slot_ptr.* != 0) { const layout_idx_plus_one = slot_ptr.*; @@ -7242,18 +7447,87 @@ pub const Interpreter = struct { }; // Get LHS and RHS type info + // Note: Both operands should be unified to the same type by the type checker const lhs_ct_var = can.ModuleEnv.varFrom(binop.lhs); - var lhs_rt_var = try self.translateTypeVar(self.env, lhs_ct_var); + const lhs_rt_var = try self.translateTypeVar(self.env, lhs_ct_var); const rhs_ct_var = can.ModuleEnv.varFrom(binop.rhs); const rhs_rt_var = try self.translateTypeVar(self.env, rhs_ct_var); - // Resolve the lhs type - if flex/rigid, default to Dec + // Ensure both operands have the same numeric type. + // Strategy: + // - If one operand is concrete (not flex/rigid), unify the other with it + // - If both are unresolved (flex/rigid), default both to Dec const lhs_resolved = self.runtime_types.resolveVar(lhs_rt_var); - if (lhs_resolved.desc.content == .flex or lhs_resolved.desc.content == .rigid) { + const rhs_resolved = self.runtime_types.resolveVar(rhs_rt_var); + const lhs_is_flex = lhs_resolved.desc.content == .flex or lhs_resolved.desc.content == .rigid; + const rhs_is_flex = rhs_resolved.desc.content == .flex or rhs_resolved.desc.content == .rigid; + + if (lhs_is_flex and rhs_is_flex) { + // Both unresolved - default both to Dec const dec_content = try self.mkNumberTypeContentRuntime("Dec"); const dec_var = try self.runtime_types.freshFromContent(dec_content); - lhs_rt_var = dec_var; + _ = try unify.unify( + self.env, + self.runtime_types, + &self.problems, + &self.snapshots, + &self.unify_scratch, + &self.unify_scratch.occurs_scratch, + unify.ModuleEnvLookup{ + .interpreter_lookup_ctx = @ptrCast(&self.module_envs), + .interpreter_lookup_fn = interpreterLookupModuleEnv, + }, + lhs_rt_var, + dec_var, + ); + _ = try unify.unify( + self.env, + self.runtime_types, + &self.problems, + &self.snapshots, + &self.unify_scratch, + &self.unify_scratch.occurs_scratch, + unify.ModuleEnvLookup{ + .interpreter_lookup_ctx = @ptrCast(&self.module_envs), + .interpreter_lookup_fn = interpreterLookupModuleEnv, + }, + rhs_rt_var, + dec_var, + ); + } else if (lhs_is_flex and !rhs_is_flex) { + // LHS is flex, RHS is concrete - unify LHS with RHS + _ = try unify.unify( + self.env, + self.runtime_types, + &self.problems, + &self.snapshots, + &self.unify_scratch, + &self.unify_scratch.occurs_scratch, + unify.ModuleEnvLookup{ + .interpreter_lookup_ctx = @ptrCast(&self.module_envs), + .interpreter_lookup_fn = interpreterLookupModuleEnv, + }, + lhs_rt_var, + rhs_rt_var, + ); + } else if (!lhs_is_flex and rhs_is_flex) { + // RHS is flex, LHS is concrete - unify RHS with LHS + _ = try unify.unify( + self.env, + self.runtime_types, + &self.problems, + &self.snapshots, + &self.unify_scratch, + &self.unify_scratch.occurs_scratch, + unify.ModuleEnvLookup{ + .interpreter_lookup_ctx = @ptrCast(&self.module_envs), + .interpreter_lookup_fn = interpreterLookupModuleEnv, + }, + rhs_rt_var, + lhs_rt_var, + ); } + // If both are concrete, they should already match (type checker ensures this) // For != we need to negate the result of is_eq const negate_result = binop.op == .ne; diff --git a/test/fx/numeric_fold.roc b/test/fx/numeric_fold.roc new file mode 100644 index 0000000000..0c54d77478 --- /dev/null +++ b/test/fx/numeric_fold.roc @@ -0,0 +1,10 @@ +app [main!] { pf: platform "./platform/main.roc" } + +import pf.Stdout + +# Tests List.fold with numeric accumulators. + +main! = || { + sum = [1, 2, 3, 4, 5].fold(0, |acc, n| acc + n) + Stdout.line!("Sum: ${I64.to_str(sum)}") +} diff --git a/test/fx/question_mark_operator.roc b/test/fx/question_mark_operator.roc new file mode 100644 index 0000000000..6c9bbb9eae --- /dev/null +++ b/test/fx/question_mark_operator.roc @@ -0,0 +1,19 @@ +app [main!] { pf: platform "./platform/main.roc" } + +import pf.Stdout + +# Tests the `?` operator for error propagation. +# The operator unwraps Ok values or early-returns Err values. + +get_greeting : {} -> Try(Str, [ListWasEmpty]) +get_greeting = |{}| { + first = List.first(["hello"])? + Ok(first) +} + +main! = || { + match get_greeting({}) { + Ok(greeting) => Stdout.line!(greeting) + Err(ListWasEmpty) => Stdout.line!("List was empty!") + } +} diff --git a/test/fx/string_pattern_matching.roc b/test/fx/string_pattern_matching.roc new file mode 100644 index 0000000000..5e1c200308 --- /dev/null +++ b/test/fx/string_pattern_matching.roc @@ -0,0 +1,19 @@ +app [main!] { pf: platform "./platform/main.roc" } + +import pf.Stdout + +# Tests pattern matching on string literals in match expressions. + +main! = || { + greet("Alice") + greet("Bob") +} + +greet = |name| { + message = match name { + "Alice" => "Hello Alice!" + "Bob" => "Hey Bob!" + _ => "Hello stranger!" + } + Stdout.line!(message) +} diff --git a/test/snapshots/fuzz_crash/fuzz_crash_007.md b/test/snapshots/fuzz_crash/fuzz_crash_007.md index 37149f6747..e69de29bb2 100644 --- a/test/snapshots/fuzz_crash/fuzz_crash_007.md +++ b/test/snapshots/fuzz_crash/fuzz_crash_007.md @@ -1,89 +0,0 @@ -# META -~~~ini -description=fuzz crash -type=file -~~~ -# SOURCE -~~~roc -ff8.8.d -~~~ -# EXPECTED -PARSE ERROR - fuzz_crash_007.md:1:1:1:4 -PARSE ERROR - fuzz_crash_007.md:1:4:1:6 -PARSE ERROR - fuzz_crash_007.md:1:6:1:8 -MISSING MAIN! FUNCTION - fuzz_crash_007.md:1:1:1:8 -# PROBLEMS -**PARSE ERROR** -A parsing error occurred: `statement_unexpected_token` -This is an unexpected parsing error. Please check your syntax. - -**fuzz_crash_007.md:1:1:1:4:** -```roc -ff8.8.d -``` -^^^ - - -**PARSE ERROR** -A parsing error occurred: `statement_unexpected_token` -This is an unexpected parsing error. Please check your syntax. - -**fuzz_crash_007.md:1:4:1:6:** -```roc -ff8.8.d -``` - ^^ - - -**PARSE ERROR** -A parsing error occurred: `statement_unexpected_token` -This is an unexpected parsing error. Please check your syntax. - -**fuzz_crash_007.md:1:6:1:8:** -```roc -ff8.8.d -``` - ^^ - - -**MISSING MAIN! FUNCTION** -Default app modules must have a `main!` function. - -No `main!` function was found. - -Add a main! function like: -`main! = |arg| { ... }` -**fuzz_crash_007.md:1:1:1:8:** -```roc -ff8.8.d -``` -^^^^^^^ - - -# TOKENS -~~~zig -LowerIdent,NoSpaceDotInt,NoSpaceDotLowerIdent, -EndOfFile, -~~~ -# PARSE -~~~clojure -(file - (type-module) - (statements - (s-malformed (tag "statement_unexpected_token")) - (s-malformed (tag "statement_unexpected_token")) - (s-malformed (tag "statement_unexpected_token")))) -~~~ -# FORMATTED -~~~roc -~~~ -# CANONICALIZE -~~~clojure -(can-ir (empty true)) -~~~ -# TYPES -~~~clojure -(inferred-types - (defs) - (expressions)) -~~~ diff --git a/test/snapshots/fuzz_crash/fuzz_crash_019.md b/test/snapshots/fuzz_crash/fuzz_crash_019.md index 194405d97b..e69de29bb2 100644 --- a/test/snapshots/fuzz_crash/fuzz_crash_019.md +++ b/test/snapshots/fuzz_crash/fuzz_crash_019.md @@ -1,2078 +0,0 @@ -# META -~~~ini -description=fuzz crash -type=file -~~~ -# SOURCE -~~~roc -# Thnt! -app [main!] { pf: platform "c" } - -import pf.Stdout exposing [line!] - -import Stdot - exposing [ #tem -Cust] - -import Bae as Gooe -import - Ba -Map(a, b) : Lis, (ab) -> List(b) -MapML( # Cb, -) # Ag - : # Aon - List( #rg - ), - (ab) -> # row - List( b ) #z) - -line : ( # Cm -) # Co -Som : { foo : O, bar : g } -Ml(a) : { # ld -} - -Soine(a) : { # -} # -Maybe(a) : [Somne] - -Mayine(a) : [ # -] #) - -ane = |num| if num 2 else 5 - -one : U6 -add = |num| { - 1 - if num { - dbg # bug - s exp0 - } else { - dbg 123 - r - } -} - -me = | - a, Tb, -| # As - match a {lue { - x - } - Blue=> {x - } - er #ent - 1 "for" => 20[1, ] # t - ment - [1, 2, 3,est]123 - [ - ] 23 - 3.1 314 - 3.14 | 6.28 => 314 - (1, ) => 123 - (1, 2, 3)123 - { } => 12 - Ok(123) => 12 - } - -expect # Cord - nt - -main! : Listlt({}, _) -ma= |_| { e - w = "d" - var er = 123 - expect blaue - return #d - tag - - # - ... - me( - ..., # r - )crash ke"Unr!" #) - i= "H, ${d}" -t = [ - one(er, ), 456, # two -9, #ee - ] - for n in list { - line!("Ag ${n} to ${er}") - ber + n - } - rd = { foo: 123, bar: "H", baz: tag, qux: Ok(world),ned } - t = (123, "World", tag, O, (nd, t), [1, 2, 3]) - m ( - 123, - "World",ag1, - O, # nt - (ne, tuple), - [1, 2, 3], - ) - b?? 12 > 5 or 13 + 2 < 5 and 10 - 1 >= 16 or 12 <= 3 e_fn(arg1)?.od()?.ned()?.recd? - Stdo!( - "Ho${ # - r(nu) # xpr - } ", - ) -} # Cocl - -y : {} -e = {} - -t : V((a,c)) - -expect { - foo == 1 -h == foo -} -~~~ -# EXPECTED -PARSE ERROR - fuzz_crash_019.md:52:16:52:16 -PARSE ERROR - fuzz_crash_019.md:58:4:58:4 -PARSE ERROR - fuzz_crash_019.md:59:3:59:3 -PARSE ERROR - fuzz_crash_019.md:60:16:60:16 -PARSE ERROR - fuzz_crash_019.md:62:5:62:5 -PARSE ERROR - fuzz_crash_019.md:63:7:63:7 -PARSE ERROR - fuzz_crash_019.md:66:12:66:12 -UNDECLARED TYPE - fuzz_crash_019.md:13:13:13:16 -UNDECLARED TYPE VARIABLE - fuzz_crash_019.md:13:19:13:21 -UNDECLARED TYPE VARIABLE - fuzz_crash_019.md:19:4:19:6 -UNDECLARED TYPE VARIABLE - fuzz_crash_019.md:20:12:20:13 -UNDECLARED TYPE - fuzz_crash_019.md:24:15:24:16 -UNDECLARED TYPE VARIABLE - fuzz_crash_019.md:24:24:24:25 -MODULE NOT FOUND - fuzz_crash_019.md:4:1:4:34 -MODULE NOT FOUND - fuzz_crash_019.md:6:1:8:6 -MODULE NOT FOUND - fuzz_crash_019.md:10:1:10:19 -MODULE NOT FOUND - fuzz_crash_019.md:11:1:12:4 -UNDECLARED TYPE - fuzz_crash_019.md:37:7:37:9 -UNDEFINED VARIABLE - fuzz_crash_019.md:42:4:42:5 -UNDEFINED VARIABLE - fuzz_crash_019.md:42:6:42:10 -UNDEFINED VARIABLE - fuzz_crash_019.md:45:3:45:4 -UNDEFINED VARIABLE - fuzz_crash_019.md:53:2:53:3 -UNUSED VARIABLE - fuzz_crash_019.md:52:11:52:14 -UNDEFINED VARIABLE - fuzz_crash_019.md:55:11:55:12 -UNUSED VARIABLE - fuzz_crash_019.md:57:2:57:4 -UNDEFINED VARIABLE - fuzz_crash_019.md:59:3:59:7 -UNUSED VARIABLE - fuzz_crash_019.md:60:12:60:15 -UNDEFINED VARIABLE - fuzz_crash_019.md:72:2:72:4 -UNDECLARED TYPE - fuzz_crash_019.md:74:9:74:15 -UNDEFINED VARIABLE - fuzz_crash_019.md:78:9:78:14 -UNDEFINED VARIABLE - fuzz_crash_019.md:80:3:80:6 -CRASH EXPECTS STRING - fuzz_crash_019.md:86:3:86:11 -UNDEFINED VARIABLE - fuzz_crash_019.md:87:11:87:12 -UNDEFINED VARIABLE - fuzz_crash_019.md:92:11:92:15 -UNDEFINED VARIABLE - fuzz_crash_019.md:93:2:93:7 -UNDEFINED VARIABLE - fuzz_crash_019.md:94:3:94:6 -UNDEFINED VARIABLE - fuzz_crash_019.md:96:34:96:37 -UNDEFINED VARIABLE - fuzz_crash_019.md:96:47:96:52 -UNDEFINED VARIABLE - fuzz_crash_019.md:96:54:96:57 -DUPLICATE DEFINITION - fuzz_crash_019.md:97:2:97:3 -UNDEFINED VARIABLE - fuzz_crash_019.md:97:21:97:24 -UNDEFINED VARIABLE - fuzz_crash_019.md:97:30:97:32 -UNDEFINED VARIABLE - fuzz_crash_019.md:98:2:98:3 -UNDEFINED VARIABLE - fuzz_crash_019.md:100:11:100:14 -UNDEFINED VARIABLE - fuzz_crash_019.md:102:4:102:6 -UNDEFINED VARIABLE - fuzz_crash_019.md:102:8:102:13 -UNDEFINED VARIABLE - fuzz_crash_019.md:105:2:105:3 -NOT IMPLEMENTED - :0:0:0:0 -NOT IMPLEMENTED - :0:0:0:0 -UNDEFINED VARIABLE - fuzz_crash_019.md:108:4:108:5 -UNDEFINED VARIABLE - fuzz_crash_019.md:108:6:108:8 -UNUSED VARIABLE - fuzz_crash_019.md:76:2:76:3 -UNUSED VARIABLE - fuzz_crash_019.md:87:2:87:3 -UNUSED VARIABLE - fuzz_crash_019.md:96:2:96:4 -UNDECLARED TYPE - fuzz_crash_019.md:116:5:116:6 -UNDEFINED VARIABLE - fuzz_crash_019.md:119:2:119:5 -UNDEFINED VARIABLE - fuzz_crash_019.md:120:1:120:2 -UNDEFINED VARIABLE - fuzz_crash_019.md:120:6:120:9 -EXPOSED BUT NOT DEFINED - fuzz_crash_019.md:2:6:2:11 -TOO FEW ARGS - fuzz_crash_019.md:17:3:18:4 -UNUSED VALUE - fuzz_crash_019.md:39:2:39:3 -INCOMPATIBLE MATCH PATTERNS - fuzz_crash_019.md:52:2:52:2 -UNUSED VALUE - fuzz_crash_019.md:1:1:1:1 -TYPE MISMATCH - fuzz_crash_019.md:84:2:86:3 -UNUSED VALUE - fuzz_crash_019.md:84:2:86:3 -UNUSED VALUE - fuzz_crash_019.md:86:11:86:17 -MISSING METHOD - fuzz_crash_019.md:77:11:77:14 -UNUSED VALUE - fuzz_crash_019.md:98:4:104:3 -UNUSED VALUE - fuzz_crash_019.md:105:2:105:54 -UNUSED VALUE - fuzz_crash_019.md:105:55:105:85 -UNUSED VALUE - fuzz_crash_019.md:119:2:119:10 -# PROBLEMS -**PARSE ERROR** -A parsing error occurred: `match_branch_missing_arrow` -This is an unexpected parsing error. Please check your syntax. - -**fuzz_crash_019.md:52:16:52:16:** -```roc - match a {lue { -``` - ^ - - -**PARSE ERROR** -A parsing error occurred: `match_branch_missing_arrow` -This is an unexpected parsing error. Please check your syntax. - -**fuzz_crash_019.md:58:4:58:4:** -```roc - 1 "for" => 20[1, ] # t -``` - ^ - - -**PARSE ERROR** -A parsing error occurred: `match_branch_missing_arrow` -This is an unexpected parsing error. Please check your syntax. - -**fuzz_crash_019.md:59:3:59:3:** -```roc - ment -``` - ^ - - -**PARSE ERROR** -A parsing error occurred: `match_branch_missing_arrow` -This is an unexpected parsing error. Please check your syntax. - -**fuzz_crash_019.md:60:16:60:16:** -```roc - [1, 2, 3,est]123 -``` - ^ - - -**PARSE ERROR** -A parsing error occurred: `match_branch_missing_arrow` -This is an unexpected parsing error. Please check your syntax. - -**fuzz_crash_019.md:62:5:62:5:** -```roc - ] 23 -``` - ^ - - -**PARSE ERROR** -A parsing error occurred: `match_branch_missing_arrow` -This is an unexpected parsing error. Please check your syntax. - -**fuzz_crash_019.md:63:7:63:7:** -```roc - 3.1 314 -``` - ^ - - -**PARSE ERROR** -A parsing error occurred: `match_branch_missing_arrow` -This is an unexpected parsing error. Please check your syntax. - -**fuzz_crash_019.md:66:12:66:12:** -```roc - (1, 2, 3)123 -``` - ^ - - -**UNDECLARED TYPE** -The type _Lis_ is not declared in this scope. - -This type is referenced here: -**fuzz_crash_019.md:13:13:13:16:** -```roc -Map(a, b) : Lis, (ab) -> List(b) -``` - ^^^ - - -**UNDECLARED TYPE VARIABLE** -The type variable _ab_ is not declared in this scope. - -Type variables must be introduced in a type annotation before they can be used. - -This type variable is referenced here: -**fuzz_crash_019.md:13:19:13:21:** -```roc -Map(a, b) : Lis, (ab) -> List(b) -``` - ^^ - - -**UNDECLARED TYPE VARIABLE** -The type variable _ab_ is not declared in this scope. - -Type variables must be introduced in a type annotation before they can be used. - -This type variable is referenced here: -**fuzz_crash_019.md:19:4:19:6:** -```roc - (ab) -> # row -``` - ^^ - - -**UNDECLARED TYPE VARIABLE** -The type variable _b_ is not declared in this scope. - -Type variables must be introduced in a type annotation before they can be used. - -This type variable is referenced here: -**fuzz_crash_019.md:20:12:20:13:** -```roc - List( b ) #z) -``` - ^ - - -**UNDECLARED TYPE** -The type _O_ is not declared in this scope. - -This type is referenced here: -**fuzz_crash_019.md:24:15:24:16:** -```roc -Som : { foo : O, bar : g } -``` - ^ - - -**UNDECLARED TYPE VARIABLE** -The type variable _g_ is not declared in this scope. - -Type variables must be introduced in a type annotation before they can be used. - -This type variable is referenced here: -**fuzz_crash_019.md:24:24:24:25:** -```roc -Som : { foo : O, bar : g } -``` - ^ - - -**MODULE NOT FOUND** -The module `pf.Stdout` was not found in this Roc project. - -You're attempting to use this module here: -**fuzz_crash_019.md:4:1:4:34:** -```roc -import pf.Stdout exposing [line!] -``` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - -**MODULE NOT FOUND** -The module `Stdot` was not found in this Roc project. - -You're attempting to use this module here: -**fuzz_crash_019.md:6:1:8:6:** -```roc -import Stdot - exposing [ #tem -Cust] -``` - - -**MODULE NOT FOUND** -The module `Bae` was not found in this Roc project. - -You're attempting to use this module here: -**fuzz_crash_019.md:10:1:10:19:** -```roc -import Bae as Gooe -``` -^^^^^^^^^^^^^^^^^^ - - -**MODULE NOT FOUND** -The module `Ba` was not found in this Roc project. - -You're attempting to use this module here: -**fuzz_crash_019.md:11:1:12:4:** -```roc -import - Ba -``` - - -**UNDECLARED TYPE** -The type _U6_ is not declared in this scope. - -This type is referenced here: -**fuzz_crash_019.md:37:7:37:9:** -```roc -one : U6 -``` - ^^ - - -**UNDEFINED VARIABLE** -Nothing is named `s` in this scope. -Is there an `import` or `exposing` missing up-top? - -**fuzz_crash_019.md:42:4:42:5:** -```roc - s exp0 -``` - ^ - - -**UNDEFINED VARIABLE** -Nothing is named `exp0` in this scope. -Is there an `import` or `exposing` missing up-top? - -**fuzz_crash_019.md:42:6:42:10:** -```roc - s exp0 -``` - ^^^^ - - -**UNDEFINED VARIABLE** -Nothing is named `r` in this scope. -Is there an `import` or `exposing` missing up-top? - -**fuzz_crash_019.md:45:3:45:4:** -```roc - r -``` - ^ - - -**UNDEFINED VARIABLE** -Nothing is named `x` in this scope. -Is there an `import` or `exposing` missing up-top? - -**fuzz_crash_019.md:53:2:53:3:** -```roc - x -``` - ^ - - -**UNUSED VARIABLE** -Variable `lue` is not used anywhere in your code. - -If you don't need this variable, prefix it with an underscore like `_lue` to suppress this warning. -The unused variable is declared here: -**fuzz_crash_019.md:52:11:52:14:** -```roc - match a {lue { -``` - ^^^ - - -**UNDEFINED VARIABLE** -Nothing is named `x` in this scope. -Is there an `import` or `exposing` missing up-top? - -**fuzz_crash_019.md:55:11:55:12:** -```roc - Blue=> {x -``` - ^ - - -**UNUSED VARIABLE** -Variable `er` is not used anywhere in your code. - -If you don't need this variable, prefix it with an underscore like `_er` to suppress this warning. -The unused variable is declared here: -**fuzz_crash_019.md:57:2:57:4:** -```roc - er #ent -``` - ^^ - - -**UNDEFINED VARIABLE** -Nothing is named `ment` in this scope. -Is there an `import` or `exposing` missing up-top? - -**fuzz_crash_019.md:59:3:59:7:** -```roc - ment -``` - ^^^^ - - -**UNUSED VARIABLE** -Variable `est` is not used anywhere in your code. - -If you don't need this variable, prefix it with an underscore like `_est` to suppress this warning. -The unused variable is declared here: -**fuzz_crash_019.md:60:12:60:15:** -```roc - [1, 2, 3,est]123 -``` - ^^^ - - -**UNDEFINED VARIABLE** -Nothing is named `nt` in this scope. -Is there an `import` or `exposing` missing up-top? - -**fuzz_crash_019.md:72:2:72:4:** -```roc - nt -``` - ^^ - - -**UNDECLARED TYPE** -The type _Listlt_ is not declared in this scope. - -This type is referenced here: -**fuzz_crash_019.md:74:9:74:15:** -```roc -main! : Listlt({}, _) -``` - ^^^^^^ - - -**UNDEFINED VARIABLE** -Nothing is named `blaue` in this scope. -Is there an `import` or `exposing` missing up-top? - -**fuzz_crash_019.md:78:9:78:14:** -```roc - expect blaue -``` - ^^^^^ - - -**UNDEFINED VARIABLE** -Nothing is named `tag` in this scope. -Is there an `import` or `exposing` missing up-top? - -**fuzz_crash_019.md:80:3:80:6:** -```roc - tag -``` - ^^^ - - -**CRASH EXPECTS STRING** -The `crash` keyword expects a string literal as its argument. -For example: `crash "Something went wrong"` -**fuzz_crash_019.md:86:3:86:11:** -```roc - )crash ke"Unr!" #) -``` - ^^^^^^^^ - - -**UNDEFINED VARIABLE** -Nothing is named `d` in this scope. -Is there an `import` or `exposing` missing up-top? - -**fuzz_crash_019.md:87:11:87:12:** -```roc - i= "H, ${d}" -``` - ^ - - -**UNDEFINED VARIABLE** -Nothing is named `list` in this scope. -Is there an `import` or `exposing` missing up-top? - -**fuzz_crash_019.md:92:11:92:15:** -```roc - for n in list { -``` - ^^^^ - - -**UNDEFINED VARIABLE** -Nothing is named `line!` in this scope. -Is there an `import` or `exposing` missing up-top? - -**fuzz_crash_019.md:93:2:93:7:** -```roc - line!("Ag ${n} to ${er}") -``` - ^^^^^ - - -**UNDEFINED VARIABLE** -Nothing is named `ber` in this scope. -Is there an `import` or `exposing` missing up-top? - -**fuzz_crash_019.md:94:3:94:6:** -```roc - ber + n -``` - ^^^ - - -**UNDEFINED VARIABLE** -Nothing is named `tag` in this scope. -Is there an `import` or `exposing` missing up-top? - -**fuzz_crash_019.md:96:34:96:37:** -```roc - rd = { foo: 123, bar: "H", baz: tag, qux: Ok(world),ned } -``` - ^^^ - - -**UNDEFINED VARIABLE** -Nothing is named `world` in this scope. -Is there an `import` or `exposing` missing up-top? - -**fuzz_crash_019.md:96:47:96:52:** -```roc - rd = { foo: 123, bar: "H", baz: tag, qux: Ok(world),ned } -``` - ^^^^^ - - -**UNDEFINED VARIABLE** -Nothing is named `ned` in this scope. -Is there an `import` or `exposing` missing up-top? - -**fuzz_crash_019.md:96:54:96:57:** -```roc - rd = { foo: 123, bar: "H", baz: tag, qux: Ok(world),ned } -``` - ^^^ - - -**DUPLICATE DEFINITION** -The name `t` is being redeclared in this scope. - -The redeclaration is here: -**fuzz_crash_019.md:97:2:97:3:** -```roc - t = (123, "World", tag, O, (nd, t), [1, 2, 3]) -``` - ^ - -But `t` was already defined here: -**fuzz_crash_019.md:88:1:88:2:** -```roc -t = [ -``` -^ - - -**UNDEFINED VARIABLE** -Nothing is named `tag` in this scope. -Is there an `import` or `exposing` missing up-top? - -**fuzz_crash_019.md:97:21:97:24:** -```roc - t = (123, "World", tag, O, (nd, t), [1, 2, 3]) -``` - ^^^ - - -**UNDEFINED VARIABLE** -Nothing is named `nd` in this scope. -Is there an `import` or `exposing` missing up-top? - -**fuzz_crash_019.md:97:30:97:32:** -```roc - t = (123, "World", tag, O, (nd, t), [1, 2, 3]) -``` - ^^ - - -**UNDEFINED VARIABLE** -Nothing is named `m` in this scope. -Is there an `import` or `exposing` missing up-top? - -**fuzz_crash_019.md:98:2:98:3:** -```roc - m ( -``` - ^ - - -**UNDEFINED VARIABLE** -Nothing is named `ag1` in this scope. -Is there an `import` or `exposing` missing up-top? - -**fuzz_crash_019.md:100:11:100:14:** -```roc - "World",ag1, -``` - ^^^ - - -**UNDEFINED VARIABLE** -Nothing is named `ne` in this scope. -Is there an `import` or `exposing` missing up-top? - -**fuzz_crash_019.md:102:4:102:6:** -```roc - (ne, tuple), -``` - ^^ - - -**UNDEFINED VARIABLE** -Nothing is named `tuple` in this scope. -Is there an `import` or `exposing` missing up-top? - -**fuzz_crash_019.md:102:8:102:13:** -```roc - (ne, tuple), -``` - ^^^^^ - - -**UNDEFINED VARIABLE** -Nothing is named `b` in this scope. -Is there an `import` or `exposing` missing up-top? - -**fuzz_crash_019.md:105:2:105:3:** -```roc - b?? 12 > 5 or 13 + 2 < 5 and 10 - 1 >= 16 or 12 <= 3 e_fn(arg1)?.od()?.ned()?.recd? -``` - ^ - - -**NOT IMPLEMENTED** -This feature is not yet implemented: unsupported operator - -This error doesn't have a proper diagnostic report yet. Let us know if you want to help improve Roc's error messages! - -**NOT IMPLEMENTED** -This feature is not yet implemented: canonicalize suffix_single_question expression - -This error doesn't have a proper diagnostic report yet. Let us know if you want to help improve Roc's error messages! - -**UNDEFINED VARIABLE** -Nothing is named `r` in this scope. -Is there an `import` or `exposing` missing up-top? - -**fuzz_crash_019.md:108:4:108:5:** -```roc - r(nu) # xpr -``` - ^ - - -**UNDEFINED VARIABLE** -Nothing is named `nu` in this scope. -Is there an `import` or `exposing` missing up-top? - -**fuzz_crash_019.md:108:6:108:8:** -```roc - r(nu) # xpr -``` - ^^ - - -**UNUSED VARIABLE** -Variable `w` is not used anywhere in your code. - -If you don't need this variable, prefix it with an underscore like `_w` to suppress this warning. -The unused variable is declared here: -**fuzz_crash_019.md:76:2:76:3:** -```roc - w = "d" -``` - ^ - - -**UNUSED VARIABLE** -Variable `i` is not used anywhere in your code. - -If you don't need this variable, prefix it with an underscore like `_i` to suppress this warning. -The unused variable is declared here: -**fuzz_crash_019.md:87:2:87:3:** -```roc - i= "H, ${d}" -``` - ^ - - -**UNUSED VARIABLE** -Variable `rd` is not used anywhere in your code. - -If you don't need this variable, prefix it with an underscore like `_rd` to suppress this warning. -The unused variable is declared here: -**fuzz_crash_019.md:96:2:96:4:** -```roc - rd = { foo: 123, bar: "H", baz: tag, qux: Ok(world),ned } -``` - ^^ - - -**UNDECLARED TYPE** -The type _V_ is not declared in this scope. - -This type is referenced here: -**fuzz_crash_019.md:116:5:116:6:** -```roc -t : V((a,c)) -``` - ^ - - -**UNDEFINED VARIABLE** -Nothing is named `foo` in this scope. -Is there an `import` or `exposing` missing up-top? - -**fuzz_crash_019.md:119:2:119:5:** -```roc - foo == 1 -``` - ^^^ - - -**UNDEFINED VARIABLE** -Nothing is named `h` in this scope. -Is there an `import` or `exposing` missing up-top? - -**fuzz_crash_019.md:120:1:120:2:** -```roc -h == foo -``` -^ - - -**UNDEFINED VARIABLE** -Nothing is named `foo` in this scope. -Is there an `import` or `exposing` missing up-top? - -**fuzz_crash_019.md:120:6:120:9:** -```roc -h == foo -``` - ^^^ - - -**EXPOSED BUT NOT DEFINED** -The module header says that `main!` is exposed, but it is not defined anywhere in this module. - -**fuzz_crash_019.md:2:6:2:11:** -```roc -app [main!] { pf: platform "c" } -``` - ^^^^^ -You can fix this by either defining `main!` in this module, or by removing it from the list of exposed values. - -**TOO FEW ARGS** -The type _List_ expects argument, but got instead. -**fuzz_crash_019.md:17:3:18:4:** -```roc - List( #rg - ), -``` - - - -**UNUSED VALUE** -This expression produces a value, but it's not being used: -**fuzz_crash_019.md:39:2:39:3:** -```roc - 1 -``` - ^ - -It has the type: - _f where [f.from_numeral : Numeral -> Try(_j, [InvalidNumeral(Str)])]_ - -**INCOMPATIBLE MATCH PATTERNS** -The pattern in the fourth branch of this `match` differs from previous ones: -**fuzz_crash_019.md:52:2:** -```roc - match a {lue { - x - } - Blue=> {x - } - er #ent - 1 "for" => 20[1, ] # t - ment - [1, 2, 3,est]123 - [ - ] 23 - 3.1 314 - 3.14 | 6.28 => 314 - (1, ) => 123 - (1, 2, 3)123 - { } => 12 - Ok(123) => 12 - } -``` - ^^^^^ - -The fourth pattern has this type: - _Str_ - -But all the previous patterns have this type: - _[Blue][ProvidedByCompiler]_ - -All patterns in an `match` must have compatible types. - - - -**UNUSED VALUE** -This expression produces a value, but it's not being used: -**fuzz_crash_019.md:1:1:1:1:** -```roc -# Thnt! -``` -^ - -It has the type: - _f_ - -**TYPE MISMATCH** -This expression is used in an unexpected way: -**fuzz_crash_019.md:84:2:86:3:** -```roc - me( - ..., # r - )crash ke"Unr!" #) -``` - -It has the type: - __arg -> _ret_ - -But I expected it to be: - _[Blue][ProvidedByCompiler], [Tb]_others -> Error_ - -**UNUSED VALUE** -This expression produces a value, but it's not being used: -**fuzz_crash_019.md:84:2:86:3:** -```roc - me( - ..., # r - )crash ke"Unr!" #) -``` - -It has the type: - _f_ - -**UNUSED VALUE** -This expression produces a value, but it's not being used: -**fuzz_crash_019.md:86:11:86:17:** -```roc - )crash ke"Unr!" #) -``` - ^^^^^^ - -It has the type: - _Str_ - -**MISSING METHOD** -This **from_numeral** method is being called on a value whose type doesn't have that method: -**fuzz_crash_019.md:77:11:77:14:** -```roc - var er = 123 -``` - ^^^ - -The value's type, which does not have a method named **from_numeral**, is: - - _Str_ - -**Hint: **For this to work, the type would need to have a method named **from_numeral** associated with it in the type's declaration. - -**UNUSED VALUE** -This expression produces a value, but it's not being used: -**fuzz_crash_019.md:98:4:104:3:** -```roc - m ( - 123, - "World",ag1, - O, # nt - (ne, tuple), - [1, 2, 3], - ) -``` - -It has the type: - _(f, Str, Error, [O]_others, (Error, Error), List(j)) where [f.from_numeral : Numeral -> Try(_k, [InvalidNumeral(Str)]), j.from_numeral : Numeral -> Try(_l, [InvalidNumeral(Str)])]_ - -**UNUSED VALUE** -This expression produces a value, but it's not being used: -**fuzz_crash_019.md:105:2:105:54:** -```roc - b?? 12 > 5 or 13 + 2 < 5 and 10 - 1 >= 16 or 12 <= 3 e_fn(arg1)?.od()?.ned()?.recd? -``` - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -It has the type: - _Bool_ - -**UNUSED VALUE** -This expression produces a value, but it's not being used: -**fuzz_crash_019.md:105:55:105:85:** -```roc - b?? 12 > 5 or 13 + 2 < 5 and 10 - 1 >= 16 or 12 <= 3 e_fn(arg1)?.od()?.ned()?.recd? -``` - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -It has the type: - _f_ - -**UNUSED VALUE** -This expression produces a value, but it's not being used: -**fuzz_crash_019.md:119:2:119:10:** -```roc - foo == 1 -``` - ^^^^^^^^ - -It has the type: - _f_ - -# TOKENS -~~~zig -KwApp,OpenSquare,LowerIdent,CloseSquare,OpenCurly,LowerIdent,OpColon,KwPlatform,StringStart,StringPart,StringEnd,CloseCurly, -KwImport,LowerIdent,NoSpaceDotUpperIdent,KwExposing,OpenSquare,LowerIdent,CloseSquare, -KwImport,UpperIdent, -KwExposing,OpenSquare, -UpperIdent,CloseSquare, -KwImport,UpperIdent,KwAs,UpperIdent, -KwImport, -UpperIdent, -UpperIdent,NoSpaceOpenRound,LowerIdent,Comma,LowerIdent,CloseRound,OpColon,UpperIdent,Comma,OpenRound,LowerIdent,CloseRound,OpArrow,UpperIdent,NoSpaceOpenRound,LowerIdent,CloseRound, -UpperIdent,NoSpaceOpenRound, -CloseRound, -OpColon, -UpperIdent,NoSpaceOpenRound, -CloseRound,Comma, -OpenRound,LowerIdent,CloseRound,OpArrow, -UpperIdent,NoSpaceOpenRound,LowerIdent,CloseRound, -LowerIdent,OpColon,OpenRound, -CloseRound, -UpperIdent,OpColon,OpenCurly,LowerIdent,OpColon,UpperIdent,Comma,LowerIdent,OpColon,LowerIdent,CloseCurly, -UpperIdent,NoSpaceOpenRound,LowerIdent,CloseRound,OpColon,OpenCurly, -CloseCurly, -UpperIdent,NoSpaceOpenRound,LowerIdent,CloseRound,OpColon,OpenCurly, -CloseCurly, -UpperIdent,NoSpaceOpenRound,LowerIdent,CloseRound,OpColon,OpenSquare,UpperIdent,CloseSquare, -UpperIdent,NoSpaceOpenRound,LowerIdent,CloseRound,OpColon,OpenSquare, -CloseSquare, -LowerIdent,OpAssign,OpBar,LowerIdent,OpBar,KwIf,LowerIdent,Int,KwElse,Int, -LowerIdent,OpColon,UpperIdent, -LowerIdent,OpAssign,OpBar,LowerIdent,OpBar,OpenCurly, -Int, -KwIf,LowerIdent,OpenCurly, -KwDbg, -LowerIdent,LowerIdent, -CloseCurly,KwElse,OpenCurly, -KwDbg,Int, -LowerIdent, -CloseCurly, -CloseCurly, -LowerIdent,OpAssign,OpBar, -LowerIdent,Comma,UpperIdent,Comma, -OpBar, -KwMatch,LowerIdent,OpenCurly,LowerIdent,OpenCurly, -LowerIdent, -CloseCurly, -UpperIdent,OpFatArrow,OpenCurly,LowerIdent, -CloseCurly, -LowerIdent, -Int,StringStart,StringPart,StringEnd,OpFatArrow,Int,OpenSquare,Int,Comma,CloseSquare, -LowerIdent, -OpenSquare,Int,Comma,Int,Comma,Int,Comma,LowerIdent,CloseSquare,Int, -OpenSquare, -CloseSquare,Int, -Float,Int, -Float,OpBar,Float,OpFatArrow,Int, -OpenRound,Int,Comma,CloseRound,OpFatArrow,Int, -OpenRound,Int,Comma,Int,Comma,Int,CloseRound,Int, -OpenCurly,CloseCurly,OpFatArrow,Int, -UpperIdent,NoSpaceOpenRound,Int,CloseRound,OpFatArrow,Int, -CloseCurly, -KwExpect, -LowerIdent, -LowerIdent,OpColon,UpperIdent,NoSpaceOpenRound,OpenCurly,CloseCurly,Comma,Underscore,CloseRound, -LowerIdent,OpAssign,OpBar,Underscore,OpBar,OpenCurly,LowerIdent, -LowerIdent,OpAssign,StringStart,StringPart,StringEnd, -KwVar,LowerIdent,OpAssign,Int, -KwExpect,LowerIdent, -KwReturn, -LowerIdent, -TripleDot, -LowerIdent,NoSpaceOpenRound, -TripleDot,Comma, -CloseRound,KwCrash,LowerIdent,StringStart,StringPart,StringEnd, -LowerIdent,OpAssign,StringStart,StringPart,OpenStringInterpolation,LowerIdent,CloseStringInterpolation,StringPart,StringEnd, -LowerIdent,OpAssign,OpenSquare, -LowerIdent,NoSpaceOpenRound,LowerIdent,Comma,CloseRound,Comma,Int,Comma, -Int,Comma, -CloseSquare, -KwFor,LowerIdent,KwIn,LowerIdent,OpenCurly, -LowerIdent,NoSpaceOpenRound,StringStart,StringPart,OpenStringInterpolation,LowerIdent,CloseStringInterpolation,StringPart,OpenStringInterpolation,LowerIdent,CloseStringInterpolation,StringPart,StringEnd,CloseRound, -LowerIdent,OpPlus,LowerIdent, -CloseCurly, -LowerIdent,OpAssign,OpenCurly,LowerIdent,OpColon,Int,Comma,LowerIdent,OpColon,StringStart,StringPart,StringEnd,Comma,LowerIdent,OpColon,LowerIdent,Comma,LowerIdent,OpColon,UpperIdent,NoSpaceOpenRound,LowerIdent,CloseRound,Comma,LowerIdent,CloseCurly, -LowerIdent,OpAssign,OpenRound,Int,Comma,StringStart,StringPart,StringEnd,Comma,LowerIdent,Comma,UpperIdent,Comma,OpenRound,LowerIdent,Comma,LowerIdent,CloseRound,Comma,OpenSquare,Int,Comma,Int,Comma,Int,CloseSquare,CloseRound, -LowerIdent,OpenRound, -Int,Comma, -StringStart,StringPart,StringEnd,Comma,LowerIdent,Comma, -UpperIdent,Comma, -OpenRound,LowerIdent,Comma,LowerIdent,CloseRound,Comma, -OpenSquare,Int,Comma,Int,Comma,Int,CloseSquare,Comma, -CloseRound, -LowerIdent,OpDoubleQuestion,Int,OpGreaterThan,Int,OpOr,Int,OpPlus,Int,OpLessThan,Int,OpAnd,Int,OpBinaryMinus,Int,OpGreaterThanOrEq,Int,OpOr,Int,OpLessThanOrEq,Int,LowerIdent,NoSpaceOpenRound,LowerIdent,CloseRound,NoSpaceOpQuestion,NoSpaceDotLowerIdent,NoSpaceOpenRound,CloseRound,NoSpaceOpQuestion,NoSpaceDotLowerIdent,NoSpaceOpenRound,CloseRound,NoSpaceOpQuestion,NoSpaceDotLowerIdent,NoSpaceOpQuestion, -UpperIdent,NoSpaceOpenRound, -StringStart,StringPart,OpenStringInterpolation, -LowerIdent,NoSpaceOpenRound,LowerIdent,CloseRound, -CloseStringInterpolation,StringPart,StringEnd,Comma, -CloseRound, -CloseCurly, -LowerIdent,OpColon,OpenCurly,CloseCurly, -LowerIdent,OpAssign,OpenCurly,CloseCurly, -LowerIdent,OpColon,UpperIdent,NoSpaceOpenRound,NoSpaceOpenRound,LowerIdent,Comma,LowerIdent,CloseRound,CloseRound, -KwExpect,OpenCurly, -LowerIdent,OpEquals,Int, -LowerIdent,OpEquals,LowerIdent, -CloseCurly, -EndOfFile, -~~~ -# PARSE -~~~clojure -(file - (app - (provides - (exposed-lower-ident - (text "main!"))) - (record-field (name "pf") - (e-string - (e-string-part (raw "c")))) - (packages - (record-field (name "pf") - (e-string - (e-string-part (raw "c")))))) - (statements - (s-import (raw "pf.Stdout") - (exposing - (exposed-lower-ident - (text "line!")))) - (s-import (raw "Stdot") - (exposing - (exposed-upper-ident (text "Cust")))) - (s-import (raw "Bae") (alias "Gooe")) - (s-import (raw "Ba")) - (s-type-decl - (header (name "Map") - (args - (ty-var (raw "a")) - (ty-var (raw "b")))) - (ty-fn - (ty (name "Lis")) - (ty-tuple - (ty-var (raw "ab"))) - (ty-apply - (ty (name "List")) - (ty-var (raw "b"))))) - (s-type-decl - (header (name "MapML") - (args)) - (ty-fn - (ty-apply - (ty (name "List"))) - (ty-tuple - (ty-var (raw "ab"))) - (ty-apply - (ty (name "List")) - (ty-var (raw "b"))))) - (s-type-anno (name "line") - (ty-tuple)) - (s-type-decl - (header (name "Som") - (args)) - (ty-record - (anno-record-field (name "foo") - (ty (name "O"))) - (anno-record-field (name "bar") - (ty-var (raw "g"))))) - (s-type-decl - (header (name "Ml") - (args - (ty-var (raw "a")))) - (ty-record)) - (s-type-decl - (header (name "Soine") - (args - (ty-var (raw "a")))) - (ty-record)) - (s-type-decl - (header (name "Maybe") - (args - (ty-var (raw "a")))) - (ty-tag-union - (tags - (ty (name "Somne"))))) - (s-type-decl - (header (name "Mayine") - (args - (ty-var (raw "a")))) - (ty-tag-union - (tags))) - (s-decl - (p-ident (raw "ane")) - (e-lambda - (args - (p-ident (raw "num"))) - (e-if-then-else - (e-ident (raw "num")) - (e-int (raw "2")) - (e-int (raw "5"))))) - (s-type-anno (name "one") - (ty (name "U6"))) - (s-decl - (p-ident (raw "add")) - (e-lambda - (args - (p-ident (raw "num"))) - (e-block - (statements - (e-int (raw "1")) - (e-if-then-else - (e-ident (raw "num")) - (e-block - (statements - (s-dbg - (e-ident (raw "s"))) - (e-ident (raw "exp0")))) - (e-block - (statements - (s-dbg - (e-int (raw "123"))) - (e-ident (raw "r"))))))))) - (s-decl - (p-ident (raw "me")) - (e-lambda - (args - (p-ident (raw "a")) - (p-tag (raw "Tb"))) - (e-match - (e-ident (raw "a")) - (branches - (branch - (p-ident (raw "lue")) - (e-block - (statements - (e-ident (raw "x"))))) - (branch - (p-tag (raw "Blue")) - (e-block - (statements - (e-ident (raw "x"))))) - (branch - (p-ident (raw "er")) - (e-int (raw "1"))) - (branch - (p-string (raw """)) - (e-int (raw "20"))) - (branch - (p-list - (p-int (raw "1"))) - (e-ident (raw "ment"))) - (branch - (p-list - (p-int (raw "1")) - (p-int (raw "2")) - (p-int (raw "3")) - (p-ident (raw "est"))) - (e-int (raw "123"))) - (branch - (p-list) - (e-int (raw "23"))) - (branch - (p-frac (raw "3.1")) - (e-int (raw "314"))) - (branch - (p-alternatives - (p-frac (raw "3.14")) - (p-frac (raw "6.28"))) - (e-int (raw "314"))) - (branch - (p-tuple - (p-int (raw "1"))) - (e-int (raw "123"))) - (branch - (p-tuple - (p-int (raw "1")) - (p-int (raw "2")) - (p-int (raw "3"))) - (e-int (raw "123"))) - (branch - (p-record) - (e-int (raw "12"))) - (branch - (p-tag (raw "Ok") - (p-int (raw "123"))) - (e-int (raw "12"))))))) - (s-expect - (e-ident (raw "nt"))) - (s-type-anno (name "main!") - (ty-apply - (ty (name "Listlt")) - (ty-record) - (_))) - (s-decl - (p-ident (raw "ma")) - (e-lambda - (args - (p-underscore)) - (e-block - (statements - (e-ident (raw "e")) - (s-decl - (p-ident (raw "w")) - (e-string - (e-string-part (raw "d")))) - (s-var (name "er") - (e-int (raw "123"))) - (s-expect - (e-ident (raw "blaue"))) - (s-return - (e-ident (raw "tag"))) - (e-ellipsis) - (e-apply - (e-ident (raw "me")) - (e-ellipsis)) - (s-crash - (e-ident (raw "ke"))) - (e-string - (e-string-part (raw "Unr!"))) - (s-decl - (p-ident (raw "i")) - (e-string - (e-string-part (raw "H, ")) - (e-ident (raw "d")) - (e-string-part (raw "")))) - (s-decl - (p-ident (raw "t")) - (e-list - (e-apply - (e-ident (raw "one")) - (e-ident (raw "er"))) - (e-int (raw "456")) - (e-int (raw "9")))) - (s-for - (p-ident (raw "n")) - (e-ident (raw "list")) - (e-block - (statements - (e-apply - (e-ident (raw "line!")) - (e-string - (e-string-part (raw "Ag ")) - (e-ident (raw "n")) - (e-string-part (raw " to ")) - (e-ident (raw "er")) - (e-string-part (raw "")))) - (e-binop (op "+") - (e-ident (raw "ber")) - (e-ident (raw "n")))))) - (s-decl - (p-ident (raw "rd")) - (e-record - (field (field "foo") - (e-int (raw "123"))) - (field (field "bar") - (e-string - (e-string-part (raw "H")))) - (field (field "baz") - (e-ident (raw "tag"))) - (field (field "qux") - (e-apply - (e-tag (raw "Ok")) - (e-ident (raw "world")))) - (field (field "ned")))) - (s-decl - (p-ident (raw "t")) - (e-tuple - (e-int (raw "123")) - (e-string - (e-string-part (raw "World"))) - (e-ident (raw "tag")) - (e-tag (raw "O")) - (e-tuple - (e-ident (raw "nd")) - (e-ident (raw "t"))) - (e-list - (e-int (raw "1")) - (e-int (raw "2")) - (e-int (raw "3"))))) - (e-ident (raw "m")) - (e-tuple - (e-int (raw "123")) - (e-string - (e-string-part (raw "World"))) - (e-ident (raw "ag1")) - (e-tag (raw "O")) - (e-tuple - (e-ident (raw "ne")) - (e-ident (raw "tuple"))) - (e-list - (e-int (raw "1")) - (e-int (raw "2")) - (e-int (raw "3")))) - (e-binop (op "or") - (e-binop (op ">") - (e-binop (op "??") - (e-ident (raw "b")) - (e-int (raw "12"))) - (e-int (raw "5"))) - (e-binop (op "or") - (e-binop (op "and") - (e-binop (op "<") - (e-binop (op "+") - (e-int (raw "13")) - (e-int (raw "2"))) - (e-int (raw "5"))) - (e-binop (op ">=") - (e-binop (op "-") - (e-int (raw "10")) - (e-int (raw "1"))) - (e-int (raw "16")))) - (e-binop (op "<=") - (e-int (raw "12")) - (e-int (raw "3"))))) - (e-field-access - (e-field-access - (e-field-access - (e-question-suffix - (e-apply - (e-ident (raw "e_fn")) - (e-ident (raw "arg1")))) - (e-question-suffix - (e-apply - (e-ident (raw "od"))))) - (e-question-suffix - (e-apply - (e-ident (raw "ned"))))) - (e-question-suffix - (e-ident (raw "recd")))) - (e-apply - (e-tag (raw "Stdo!")) - (e-string - (e-string-part (raw "Ho")) - (e-apply - (e-ident (raw "r")) - (e-ident (raw "nu"))) - (e-string-part (raw " ")))))))) - (s-type-anno (name "y") - (ty-record)) - (s-decl - (p-ident (raw "e")) - (e-record)) - (s-type-anno (name "t") - (ty-apply - (ty (name "V")) - (ty-tuple - (ty-var (raw "a")) - (ty-var (raw "c"))))) - (s-expect - (e-block - (statements - (e-binop (op "==") - (e-ident (raw "foo")) - (e-int (raw "1"))) - (e-binop (op "==") - (e-ident (raw "h")) - (e-ident (raw "foo")))))))) -~~~ -# FORMATTED -~~~roc -# Thnt! -app [main!] { pf: platform "c" } - -import pf.Stdout exposing [line!] - -import Stdot - exposing [ # tem - Cust, - ] - -import Bae as Gooe -import - Ba -Map(a, b) : Lis, (ab) -> List(b) -MapML # Ag - : # Aon - List(), - (ab) -> # row - List(b) # z) - -line : () # Co -Som : { foo : O, bar : g } -Ml(a) : {} - -Soine(a) : {} # -Maybe(a) : [Somne] - -Mayine(a) : [] # ) - -ane = |num| if num 2 else 5 - -one : U6 -add = |num| { - 1 - if num { - dbg # bug - s - exp0 - } else { - dbg 123 - r - } -} - -me = | - a, - Tb, -| # As - match a { - lue => { - x - } - Blue => { - x - } - er # ent - => # ent - 1 - "for" => 20 - [ - 1, - ] # t - => # t - ment - [1, 2, 3, est] => 123 - [] => 23 - 3.1 => 314 - 3.14 | 6.28 => 314 - ( - 1, - ) => 123 - (1, 2, 3) => 123 - {} => 12 - Ok(123) => 12 - } - -expect # Cord - nt - -main! : Listlt({}, _) -ma = |_| { - e - w = "d" - var er = 123 - expect blaue - return # d - tag - - # - ... - me( - ..., # r - ) - crash ke - "Unr!" # ) - i = "H, ${d}" - t = [ - one( - er, - ), - 456, # two - 9, # ee - ] - for n in list { - line!("Ag ${n} to ${er}") - ber + n - } - rd = { foo: 123, bar: "H", baz: tag, qux: Ok(world), ned } - t = (123, "World", tag, O, (nd, t), [1, 2, 3]) - m - ( - 123, - "World", - ag1, - O, # nt - (ne, tuple), - [1, 2, 3], - ) - b ?? 12 > 5 or 13 + 2 < 5 and 10 - 1 >= 16 or 12 <= 3 - e_fn(arg1)?.od()?.ned()?.recd? - Stdo!( - "Ho${ # - r(nu) # xpr - } ", - ) -} # Cocl - -y : {} -e = {} - -t : V((a, c)) - -expect { - foo == 1 - h == foo -} -~~~ -# CANONICALIZE -~~~clojure -(can-ir - (d-let - (p-assign (ident "line")) - (e-anno-only) - (annotation - (ty-tuple))) - (d-let - (p-assign (ident "ane")) - (e-lambda - (args - (p-assign (ident "num"))) - (e-if - (if-branches - (if-branch - (e-lookup-local - (p-assign (ident "num"))) - (e-num (value "2")))) - (if-else - (e-num (value "5")))))) - (d-let - (p-assign (ident "one")) - (e-anno-only) - (annotation - (ty-malformed))) - (d-let - (p-assign (ident "add")) - (e-lambda - (args - (p-assign (ident "num"))) - (e-block - (s-expr - (e-num (value "1"))) - (e-if - (if-branches - (if-branch - (e-lookup-local - (p-assign (ident "num"))) - (e-block - (s-dbg - (e-runtime-error (tag "ident_not_in_scope"))) - (e-runtime-error (tag "ident_not_in_scope"))))) - (if-else - (e-block - (s-dbg - (e-num (value "123"))) - (e-runtime-error (tag "ident_not_in_scope")))))))) - (d-let - (p-assign (ident "me")) - (e-lambda - (args - (p-assign (ident "a")) - (p-applied-tag)) - (e-match - (match - (cond - (e-lookup-local - (p-assign (ident "a")))) - (branches - (branch - (patterns - (pattern (degenerate false) - (p-assign (ident "lue")))) - (value - (e-block - (e-runtime-error (tag "ident_not_in_scope"))))) - (branch - (patterns - (pattern (degenerate false) - (p-applied-tag))) - (value - (e-block - (e-runtime-error (tag "ident_not_in_scope"))))) - (branch - (patterns - (pattern (degenerate false) - (p-assign (ident "er")))) - (value - (e-num (value "1")))) - (branch - (patterns - (pattern (degenerate false) - (p-str (text """)))) - (value - (e-num (value "20")))) - (branch - (patterns - (pattern (degenerate false) - (p-list - (patterns - (p-num (value "1")))))) - (value - (e-runtime-error (tag "ident_not_in_scope")))) - (branch - (patterns - (pattern (degenerate false) - (p-list - (patterns - (p-num (value "1")) - (p-num (value "2")) - (p-num (value "3")) - (p-assign (ident "est")))))) - (value - (e-num (value "123")))) - (branch - (patterns - (pattern (degenerate false) - (p-list - (patterns)))) - (value - (e-num (value "23")))) - (branch - (patterns - (pattern (degenerate false) - (p-small-dec))) - (value - (e-num (value "314")))) - (branch - (patterns - (pattern (degenerate false) - (p-small-dec)) - (pattern (degenerate false) - (p-small-dec))) - (value - (e-num (value "314")))) - (branch - (patterns - (pattern (degenerate false) - (p-tuple - (patterns - (p-num (value "1")))))) - (value - (e-num (value "123")))) - (branch - (patterns - (pattern (degenerate false) - (p-tuple - (patterns - (p-num (value "1")) - (p-num (value "2")) - (p-num (value "3")))))) - (value - (e-num (value "123")))) - (branch - (patterns - (pattern (degenerate false) - (p-record-destructure - (destructs)))) - (value - (e-num (value "12")))) - (branch - (patterns - (pattern (degenerate false) - (p-applied-tag))) - (value - (e-num (value "12"))))))))) - (d-let - (p-assign (ident "main!")) - (e-anno-only) - (annotation - (ty-malformed))) - (d-let - (p-assign (ident "ma")) - (e-closure - (captures - (capture (ident "e")) - (capture (ident "me")) - (capture (ident "one"))) - (e-lambda - (args - (p-underscore)) - (e-block - (s-expr - (e-lookup-local - (p-assign (ident "e")))) - (s-let - (p-assign (ident "w")) - (e-string - (e-literal (string "d")))) - (s-var - (p-assign (ident "er")) - (e-num (value "123"))) - (s-expect - (e-runtime-error (tag "ident_not_in_scope"))) - (s-return - (e-runtime-error (tag "ident_not_in_scope"))) - (s-expr - (e-not-implemented)) - (s-expr - (e-call - (e-lookup-local - (p-assign (ident "me"))) - (e-not-implemented))) - (s-runtime-error (tag "crash_expects_string")) - (s-expr - (e-string - (e-literal (string "Unr!")))) - (s-let - (p-assign (ident "i")) - (e-string - (e-literal (string "H, ")) - (e-runtime-error (tag "ident_not_in_scope")) - (e-literal (string "")))) - (s-let - (p-assign (ident "t")) - (e-list - (elems - (e-call - (e-lookup-local - (p-assign (ident "one"))) - (e-lookup-local - (p-assign (ident "er")))) - (e-num (value "456")) - (e-num (value "9"))))) - (s-for - (p-assign (ident "n")) - (e-runtime-error (tag "ident_not_in_scope")) - (e-block - (s-expr - (e-call - (e-runtime-error (tag "ident_not_in_scope")) - (e-string - (e-literal (string "Ag ")) - (e-lookup-local - (p-assign (ident "n"))) - (e-literal (string " to ")) - (e-lookup-local - (p-assign (ident "er"))) - (e-literal (string ""))))) - (e-binop (op "add") - (e-runtime-error (tag "ident_not_in_scope")) - (e-lookup-local - (p-assign (ident "n")))))) - (s-let - (p-assign (ident "rd")) - (e-record - (fields - (field (name "foo") - (e-num (value "123"))) - (field (name "bar") - (e-string - (e-literal (string "H")))) - (field (name "baz") - (e-runtime-error (tag "ident_not_in_scope"))) - (field (name "qux") - (e-tag (name "Ok") - (args - (e-runtime-error (tag "ident_not_in_scope"))))) - (field (name "ned") - (e-runtime-error (tag "ident_not_in_scope")))))) - (s-let - (p-assign (ident "t")) - (e-tuple - (elems - (e-num (value "123")) - (e-string - (e-literal (string "World"))) - (e-runtime-error (tag "ident_not_in_scope")) - (e-tag (name "O")) - (e-tuple - (elems - (e-runtime-error (tag "ident_not_in_scope")) - (e-lookup-local - (p-assign (ident "t"))))) - (e-list - (elems - (e-num (value "1")) - (e-num (value "2")) - (e-num (value "3"))))))) - (s-expr - (e-runtime-error (tag "ident_not_in_scope"))) - (s-expr - (e-tuple - (elems - (e-num (value "123")) - (e-string - (e-literal (string "World"))) - (e-runtime-error (tag "ident_not_in_scope")) - (e-tag (name "O")) - (e-tuple - (elems - (e-runtime-error (tag "ident_not_in_scope")) - (e-runtime-error (tag "ident_not_in_scope")))) - (e-list - (elems - (e-num (value "1")) - (e-num (value "2")) - (e-num (value "3"))))))) - (s-expr - (e-binop (op "or") - (e-binop (op "gt") - (e-runtime-error (tag "not_implemented")) - (e-num (value "5"))) - (e-binop (op "or") - (e-binop (op "and") - (e-binop (op "lt") - (e-binop (op "add") - (e-num (value "13")) - (e-num (value "2"))) - (e-num (value "5"))) - (e-binop (op "ge") - (e-binop (op "sub") - (e-num (value "10")) - (e-num (value "1"))) - (e-num (value "16")))) - (e-binop (op "le") - (e-num (value "12")) - (e-num (value "3")))))) - (s-expr - (e-dot-access (field "unknown") - (receiver - (e-dot-access (field "unknown") - (receiver - (e-dot-access (field "unknown") - (receiver - (e-runtime-error (tag "not_implemented"))))))))) - (e-tag (name "Stdo!") - (args - (e-string - (e-literal (string "Ho")) - (e-call - (e-runtime-error (tag "ident_not_in_scope")) - (e-runtime-error (tag "ident_not_in_scope"))) - (e-literal (string " "))))))))) - (d-let - (p-assign (ident "y")) - (e-anno-only) - (annotation - (ty-record))) - (d-let - (p-assign (ident "e")) - (e-empty_record)) - (d-let - (p-assign (ident "t")) - (e-anno-only) - (annotation - (ty-malformed))) - (s-alias-decl - (ty-header (name "Map") - (ty-args - (ty-rigid-var (name "a")) - (ty-rigid-var (name "b")))) - (ty-fn (effectful false) - (ty-malformed) - (ty-malformed) - (ty-apply (name "List") (builtin) - (ty-rigid-var-lookup (ty-rigid-var (name "b")))))) - (s-alias-decl - (ty-header (name "MapML")) - (ty-fn (effectful false) - (ty-apply (name "List") (builtin)) - (ty-malformed) - (ty-apply (name "List") (builtin) - (ty-malformed)))) - (s-alias-decl - (ty-header (name "Som")) - (ty-record - (field (field "foo") - (ty-malformed)) - (field (field "bar") - (ty-malformed)))) - (s-alias-decl - (ty-header (name "Ml") - (ty-args - (ty-rigid-var (name "a")))) - (ty-record)) - (s-alias-decl - (ty-header (name "Soine") - (ty-args - (ty-rigid-var (name "a")))) - (ty-record)) - (s-alias-decl - (ty-header (name "Maybe") - (ty-args - (ty-rigid-var (name "a")))) - (ty-tag-union - (ty-tag-name (name "Somne")))) - (s-alias-decl - (ty-header (name "Mayine") - (ty-args - (ty-rigid-var (name "a")))) - (ty-tag-union)) - (s-import (module "pf.Stdout") - (exposes - (exposed (name "line!") (wildcard false)))) - (s-import (module "Stdot") - (exposes - (exposed (name "Cust") (wildcard false)))) - (s-import (module "Bae") - (exposes)) - (s-import (module "Ba") - (exposes)) - (s-expect - (e-runtime-error (tag "ident_not_in_scope"))) - (s-expect - (e-block - (s-expr - (e-binop (op "eq") - (e-runtime-error (tag "ident_not_in_scope")) - (e-num (value "1")))) - (e-binop (op "eq") - (e-runtime-error (tag "ident_not_in_scope")) - (e-runtime-error (tag "ident_not_in_scope")))))) -~~~ -# TYPES -~~~clojure -(inferred-types - (defs - (patt (type "()")) - (patt (type "Bool -> f where [f.from_numeral : Numeral -> Try(f, [InvalidNumeral(Str)])]")) - (patt (type "Error")) - (patt (type "Bool -> Error")) - (patt (type "[Blue][ProvidedByCompiler], [Tb]_others -> Error")) - (patt (type "Error")) - (patt (type "_arg -> Error")) - (patt (type "{ }")) - (patt (type "{}")) - (patt (type "Error"))) - (type_decls - (alias (type "Map(a, b)") - (ty-header (name "Map") - (ty-args - (ty-rigid-var (name "a")) - (ty-rigid-var (name "b"))))) - (alias (type "MapML") - (ty-header (name "MapML"))) - (alias (type "Som") - (ty-header (name "Som"))) - (alias (type "Ml(a)") - (ty-header (name "Ml") - (ty-args - (ty-rigid-var (name "a"))))) - (alias (type "Soine(a)") - (ty-header (name "Soine") - (ty-args - (ty-rigid-var (name "a"))))) - (alias (type "Maybe(a)") - (ty-header (name "Maybe") - (ty-args - (ty-rigid-var (name "a"))))) - (alias (type "Mayine(a)") - (ty-header (name "Mayine") - (ty-args - (ty-rigid-var (name "a")))))) - (expressions - (expr (type "()")) - (expr (type "Bool -> f where [f.from_numeral : Numeral -> Try(f, [InvalidNumeral(Str)])]")) - (expr (type "Error")) - (expr (type "Bool -> Error")) - (expr (type "[Blue][ProvidedByCompiler], [Tb]_others -> Error")) - (expr (type "Error")) - (expr (type "_arg -> Error")) - (expr (type "{ }")) - (expr (type "{}")) - (expr (type "Error")))) -~~~ diff --git a/test/snapshots/fuzz_crash/fuzz_crash_020.md b/test/snapshots/fuzz_crash/fuzz_crash_020.md index 604e12df46..908bef6a34 100644 --- a/test/snapshots/fuzz_crash/fuzz_crash_020.md +++ b/test/snapshots/fuzz_crash/fuzz_crash_020.md @@ -750,10 +750,27 @@ This feature is not yet implemented: unsupported operator This error doesn't have a proper diagnostic report yet. Let us know if you want to help improve Roc's error messages! -**NOT IMPLEMENTED** -This feature is not yet implemented: canonicalize suffix_single_question expression +**UNDEFINED VARIABLE** +Nothing is named `e_fn` in this scope. +Is there an `import` or `exposing` missing up-top? + +**fuzz_crash_020.md:105:55:105:59:** +```roc + b?? 12 > 5 or 13 + 2 < 5 and 10 - 1 >= 16 or 12 <= 3 e_fn(arg1)?.od()?.ned()?.recd? +``` + ^^^^ + + +**UNDEFINED VARIABLE** +Nothing is named `arg1` in this scope. +Is there an `import` or `exposing` missing up-top? + +**fuzz_crash_020.md:105:60:105:64:** +```roc + b?? 12 > 5 or 13 + 2 < 5 and 10 - 1 >= 16 or 12 <= 3 e_fn(arg1)?.od()?.ned()?.recd? +``` + ^^^^ -This error doesn't have a proper diagnostic report yet. Let us know if you want to help improve Roc's error messages! **UNDEFINED VARIABLE** Nothing is named `r` in this scope. @@ -1681,7 +1698,7 @@ expect { (branch (patterns (pattern (degenerate false) - (p-str (text """)))) + (p-str (text "for")))) (value (e-num (value "20")))) (branch @@ -1914,7 +1931,30 @@ expect { (receiver (e-dot-access (field "unknown") (receiver - (e-runtime-error (tag "not_implemented"))))))))) + (e-match + (match + (cond + (e-call + (e-runtime-error (tag "ident_not_in_scope")) + (e-runtime-error (tag "ident_not_in_scope")))) + (branches + (branch + (patterns + (pattern (degenerate false) + (p-applied-tag))) + (value + (e-lookup-local + (p-assign (ident "#ok"))))) + (branch + (patterns + (pattern (degenerate false) + (p-applied-tag))) + (value + (e-return + (e-tag (name "Err") + (args + (e-lookup-local + (p-assign (ident "#err")))))))))))))))))) (e-tag (name "Stdo!") (args (e-string diff --git a/test/snapshots/fuzz_crash/fuzz_crash_028.md b/test/snapshots/fuzz_crash/fuzz_crash_028.md index e75835434f..214248a39a 100644 Binary files a/test/snapshots/fuzz_crash/fuzz_crash_028.md and b/test/snapshots/fuzz_crash/fuzz_crash_028.md differ diff --git a/test/snapshots/fuzz_crash/fuzz_crash_043.md b/test/snapshots/fuzz_crash/fuzz_crash_043.md index 0643763136..e69de29bb2 100644 --- a/test/snapshots/fuzz_crash/fuzz_crash_043.md +++ b/test/snapshots/fuzz_crash/fuzz_crash_043.md @@ -1,119 +0,0 @@ -# META -~~~ini -description=fuzz crash -type=file -~~~ -# SOURCE -~~~roc -app[]{f:platform""}{ -o:0}0 -~~~ -# EXPECTED -PARSE ERROR - fuzz_crash_043.md:1:20:1:21 -UNEXPECTED TOKEN IN TYPE ANNOTATION - fuzz_crash_043.md:2:3:2:4 -PARSE ERROR - fuzz_crash_043.md:2:4:2:5 -PARSE ERROR - fuzz_crash_043.md:2:5:2:6 -MALFORMED TYPE - fuzz_crash_043.md:2:3:2:4 -# PROBLEMS -**PARSE ERROR** -A parsing error occurred: `statement_unexpected_token` -This is an unexpected parsing error. Please check your syntax. - -**fuzz_crash_043.md:1:20:1:21:** -```roc -app[]{f:platform""}{ -``` - ^ - - -**UNEXPECTED TOKEN IN TYPE ANNOTATION** -The token **0** is not expected in a type annotation. -Type annotations should contain types like _Str_, _Num a_, or _List U64_. - -**fuzz_crash_043.md:2:3:2:4:** -```roc -o:0}0 -``` - ^ - - -**PARSE ERROR** -A parsing error occurred: `statement_unexpected_token` -This is an unexpected parsing error. Please check your syntax. - -**fuzz_crash_043.md:2:4:2:5:** -```roc -o:0}0 -``` - ^ - - -**PARSE ERROR** -A parsing error occurred: `statement_unexpected_token` -This is an unexpected parsing error. Please check your syntax. - -**fuzz_crash_043.md:2:5:2:6:** -```roc -o:0}0 -``` - ^ - - -**MALFORMED TYPE** -This type annotation is malformed or contains invalid syntax. - -**fuzz_crash_043.md:2:3:2:4:** -```roc -o:0}0 -``` - ^ - - -# TOKENS -~~~zig -KwApp,OpenSquare,CloseSquare,OpenCurly,LowerIdent,OpColon,KwPlatform,StringStart,StringPart,StringEnd,CloseCurly,OpenCurly, -LowerIdent,OpColon,Int,CloseCurly,Int, -EndOfFile, -~~~ -# PARSE -~~~clojure -(file - (app - (provides) - (record-field (name "f") - (e-string - (e-string-part (raw "")))) - (packages - (record-field (name "f") - (e-string - (e-string-part (raw "")))))) - (statements - (s-malformed (tag "statement_unexpected_token")) - (s-type-anno (name "o") - (ty-malformed (tag "ty_anno_unexpected_token"))) - (s-malformed (tag "statement_unexpected_token")) - (s-malformed (tag "statement_unexpected_token")))) -~~~ -# FORMATTED -~~~roc -app [] { f: platform "" } - -o : -~~~ -# CANONICALIZE -~~~clojure -(can-ir - (d-let - (p-assign (ident "o")) - (e-anno-only) - (annotation - (ty-malformed)))) -~~~ -# TYPES -~~~clojure -(inferred-types - (defs - (patt (type "Error"))) - (expressions - (expr (type "Error")))) -~~~ diff --git a/test/snapshots/fuzz_crash/fuzz_crash_049.md b/test/snapshots/fuzz_crash/fuzz_crash_049.md index 6190c876af..2e60e0e40c 100644 Binary files a/test/snapshots/fuzz_crash/fuzz_crash_049.md and b/test/snapshots/fuzz_crash/fuzz_crash_049.md differ diff --git a/test/snapshots/match_expr/pattern_alternatives_mixed.md b/test/snapshots/match_expr/pattern_alternatives_mixed.md index eea2455b5b..d6cb73726d 100644 --- a/test/snapshots/match_expr/pattern_alternatives_mixed.md +++ b/test/snapshots/match_expr/pattern_alternatives_mixed.md @@ -142,9 +142,9 @@ NO CHANGE (branch (patterns (pattern (degenerate false) - (p-str (text """))) + (p-str (text "hello"))) (pattern (degenerate false) - (p-str (text """)))) + (p-str (text "world")))) (value (e-string (e-literal (string "greetings"))))) diff --git a/test/snapshots/record_access_multiline_formatting_1.md b/test/snapshots/record_access_multiline_formatting_1.md index 0e030a29dd..db11babe84 100644 --- a/test/snapshots/record_access_multiline_formatting_1.md +++ b/test/snapshots/record_access_multiline_formatting_1.md @@ -11,12 +11,30 @@ some_fn(arg1)? .record_field? ~~~ # EXPECTED -NOT IMPLEMENTED - :0:0:0:0 +UNDEFINED VARIABLE - record_access_multiline_formatting_1.md:1:1:1:8 +UNDEFINED VARIABLE - record_access_multiline_formatting_1.md:1:9:1:13 # PROBLEMS -**NOT IMPLEMENTED** -This feature is not yet implemented: canonicalize suffix_single_question expression +**UNDEFINED VARIABLE** +Nothing is named `some_fn` in this scope. +Is there an `import` or `exposing` missing up-top? + +**record_access_multiline_formatting_1.md:1:1:1:8:** +```roc +some_fn(arg1)? +``` +^^^^^^^ + + +**UNDEFINED VARIABLE** +Nothing is named `arg1` in this scope. +Is there an `import` or `exposing` missing up-top? + +**record_access_multiline_formatting_1.md:1:9:1:13:** +```roc +some_fn(arg1)? +``` + ^^^^ -This error doesn't have a proper diagnostic report yet. Let us know if you want to help improve Roc's error messages! # TOKENS ~~~zig @@ -56,7 +74,30 @@ NO CHANGE (receiver (e-dot-access (field "unknown") (receiver - (e-runtime-error (tag "not_implemented")))))))) + (e-match + (match + (cond + (e-call + (e-runtime-error (tag "ident_not_in_scope")) + (e-runtime-error (tag "ident_not_in_scope")))) + (branches + (branch + (patterns + (pattern (degenerate false) + (p-applied-tag))) + (value + (e-lookup-local + (p-assign (ident "#ok"))))) + (branch + (patterns + (pattern (degenerate false) + (p-applied-tag))) + (value + (e-return + (e-tag (name "Err") + (args + (e-lookup-local + (p-assign (ident "#err"))))))))))))))))) ~~~ # TYPES ~~~clojure diff --git a/test/snapshots/record_access_multiline_formatting_4.md b/test/snapshots/record_access_multiline_formatting_4.md index aa8b0e2fe5..4a07aee804 100644 --- a/test/snapshots/record_access_multiline_formatting_4.md +++ b/test/snapshots/record_access_multiline_formatting_4.md @@ -11,12 +11,30 @@ some_fn(arg1)? # Comment 1 .record_field? ~~~ # EXPECTED -NOT IMPLEMENTED - :0:0:0:0 +UNDEFINED VARIABLE - record_access_multiline_formatting_4.md:1:1:1:8 +UNDEFINED VARIABLE - record_access_multiline_formatting_4.md:1:9:1:13 # PROBLEMS -**NOT IMPLEMENTED** -This feature is not yet implemented: canonicalize suffix_single_question expression +**UNDEFINED VARIABLE** +Nothing is named `some_fn` in this scope. +Is there an `import` or `exposing` missing up-top? + +**record_access_multiline_formatting_4.md:1:1:1:8:** +```roc +some_fn(arg1)? # Comment 1 +``` +^^^^^^^ + + +**UNDEFINED VARIABLE** +Nothing is named `arg1` in this scope. +Is there an `import` or `exposing` missing up-top? + +**record_access_multiline_formatting_4.md:1:9:1:13:** +```roc +some_fn(arg1)? # Comment 1 +``` + ^^^^ -This error doesn't have a proper diagnostic report yet. Let us know if you want to help improve Roc's error messages! # TOKENS ~~~zig @@ -56,7 +74,30 @@ NO CHANGE (receiver (e-dot-access (field "unknown") (receiver - (e-runtime-error (tag "not_implemented")))))))) + (e-match + (match + (cond + (e-call + (e-runtime-error (tag "ident_not_in_scope")) + (e-runtime-error (tag "ident_not_in_scope")))) + (branches + (branch + (patterns + (pattern (degenerate false) + (p-applied-tag))) + (value + (e-lookup-local + (p-assign (ident "#ok"))))) + (branch + (patterns + (pattern (degenerate false) + (p-applied-tag))) + (value + (e-return + (e-tag (name "Err") + (args + (e-lookup-local + (p-assign (ident "#err"))))))))))))))))) ~~~ # TYPES ~~~clojure diff --git a/test/snapshots/static_dispatch_super_test.md b/test/snapshots/static_dispatch_super_test.md index fbdc6a0383..eaa4013734 100644 --- a/test/snapshots/static_dispatch_super_test.md +++ b/test/snapshots/static_dispatch_super_test.md @@ -8,12 +8,30 @@ type=expr some_fn(arg1)?.static_dispatch_method()?.next_static_dispatch_method()?.record_field? ~~~ # EXPECTED -NOT IMPLEMENTED - :0:0:0:0 +UNDEFINED VARIABLE - static_dispatch_super_test.md:1:1:1:8 +UNDEFINED VARIABLE - static_dispatch_super_test.md:1:9:1:13 # PROBLEMS -**NOT IMPLEMENTED** -This feature is not yet implemented: canonicalize suffix_single_question expression +**UNDEFINED VARIABLE** +Nothing is named `some_fn` in this scope. +Is there an `import` or `exposing` missing up-top? + +**static_dispatch_super_test.md:1:1:1:8:** +```roc +some_fn(arg1)?.static_dispatch_method()?.next_static_dispatch_method()?.record_field? +``` +^^^^^^^ + + +**UNDEFINED VARIABLE** +Nothing is named `arg1` in this scope. +Is there an `import` or `exposing` missing up-top? + +**static_dispatch_super_test.md:1:9:1:13:** +```roc +some_fn(arg1)?.static_dispatch_method()?.next_static_dispatch_method()?.record_field? +``` + ^^^^ -This error doesn't have a proper diagnostic report yet. Let us know if you want to help improve Roc's error messages! # TOKENS ~~~zig @@ -50,7 +68,30 @@ NO CHANGE (receiver (e-dot-access (field "unknown") (receiver - (e-runtime-error (tag "not_implemented")))))))) + (e-match + (match + (cond + (e-call + (e-runtime-error (tag "ident_not_in_scope")) + (e-runtime-error (tag "ident_not_in_scope")))) + (branches + (branch + (patterns + (pattern (degenerate false) + (p-applied-tag))) + (value + (e-lookup-local + (p-assign (ident "#ok"))))) + (branch + (patterns + (pattern (degenerate false) + (p-applied-tag))) + (value + (e-return + (e-tag (name "Err") + (args + (e-lookup-local + (p-assign (ident "#err"))))))))))))))))) ~~~ # TYPES ~~~clojure diff --git a/test/snapshots/syntax_grab_bag.md b/test/snapshots/syntax_grab_bag.md index a615352ca4..7f2070163c 100644 --- a/test/snapshots/syntax_grab_bag.md +++ b/test/snapshots/syntax_grab_bag.md @@ -697,15 +697,38 @@ This feature is not yet implemented: unsupported operator This error doesn't have a proper diagnostic report yet. Let us know if you want to help improve Roc's error messages! -**NOT IMPLEMENTED** -This feature is not yet implemented: canonicalize suffix_single_question expression +**UNDEFINED VARIABLE** +Nothing is named `some_fn` in this scope. +Is there an `import` or `exposing` missing up-top? -This error doesn't have a proper diagnostic report yet. Let us know if you want to help improve Roc's error messages! +**syntax_grab_bag.md:189:26:189:33:** +```roc + static_dispatch_style = some_fn(arg1)?.static_dispatch_method()?.next_static_dispatch_method()?.record_field? +``` + ^^^^^^^ -**NOT IMPLEMENTED** -This feature is not yet implemented: canonicalize suffix_single_question expression -This error doesn't have a proper diagnostic report yet. Let us know if you want to help improve Roc's error messages! +**UNDEFINED VARIABLE** +Nothing is named `arg1` in this scope. +Is there an `import` or `exposing` missing up-top? + +**syntax_grab_bag.md:189:34:189:38:** +```roc + static_dispatch_style = some_fn(arg1)?.static_dispatch_method()?.next_static_dispatch_method()?.record_field? +``` + ^^^^ + + +**UNDEFINED VARIABLE** +Nothing is named `line!` in this scope. +Is there an `import` or `exposing` missing up-top? + +**syntax_grab_bag.md:190:2:190:14:** +```roc + Stdout.line!(interpolated)? +``` + ^^^^^^^^^^^^ + **UNDEFINED VARIABLE** Nothing is named `line!` in this scope. @@ -740,18 +763,6 @@ The unused variable is declared here: ^^^^^^^^^^^^^^^^ -**UNUSED VARIABLE** -Variable `interpolated` is not used anywhere in your code. - -If you don't need this variable, prefix it with an underscore like `_interpolated` to suppress this warning. -The unused variable is declared here: -**syntax_grab_bag.md:165:2:165:14:** -```roc - interpolated = "Hello, ${world}" -``` - ^^^^^^^^^^^^ - - **UNUSED VARIABLE** Variable `record` is not used anywhere in your code. @@ -948,6 +959,17 @@ It has the type: But I expected it to be: _Str_ +**UNUSED VALUE** +This expression produces a value, but it's not being used: +**syntax_grab_bag.md:190:2:190:29:** +```roc + Stdout.line!(interpolated)? +``` + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +It has the type: + _d_ + **TYPE MISMATCH** This expression is used in an unexpected way: **syntax_grab_bag.md:144:9:196:2:** @@ -2043,15 +2065,15 @@ expect { (branch (patterns (pattern (degenerate false) - (p-str (text """)))) + (p-str (text "foo")))) (value (e-num (value "100")))) (branch (patterns (pattern (degenerate false) - (p-str (text """))) + (p-str (text "foo"))) (pattern (degenerate false) - (p-str (text """)))) + (p-str (text "bar")))) (value (e-num (value "200")))) (branch @@ -2390,9 +2412,56 @@ expect { (receiver (e-dot-access (field "unknown") (receiver - (e-runtime-error (tag "not_implemented"))))))))) + (e-match + (match + (cond + (e-call + (e-runtime-error (tag "ident_not_in_scope")) + (e-runtime-error (tag "ident_not_in_scope")))) + (branches + (branch + (patterns + (pattern (degenerate false) + (p-applied-tag))) + (value + (e-lookup-local + (p-assign (ident "#ok"))))) + (branch + (patterns + (pattern (degenerate false) + (p-applied-tag))) + (value + (e-return + (e-tag (name "Err") + (args + (e-lookup-local + (p-assign (ident "#err")))))))))))))))))) (s-expr - (e-runtime-error (tag "not_implemented"))) + (e-match + (match + (cond + (e-call + (e-runtime-error (tag "ident_not_in_scope")) + (e-lookup-local + (p-assign (ident "interpolated"))))) + (branches + (branch + (patterns + (pattern (degenerate false) + (p-applied-tag))) + (value + (e-lookup-local + (p-assign (ident "#ok"))))) + (branch + (patterns + (pattern (degenerate false) + (p-applied-tag))) + (value + (e-return + (e-tag (name "Err") + (args + (e-lookup-local + (p-assign (ident "#err")))))))))))) (e-call (e-runtime-error (tag "ident_not_in_scope")) (e-string