mirror of
https://github.com/roc-lang/roc.git
synced 2025-12-23 08:48:03 +00:00
commit
092cf67728
67 changed files with 2098 additions and 882 deletions
|
|
@ -149,11 +149,18 @@ fn replaceStrIsEmptyWithLowLevel(env: *ModuleEnv) !std.ArrayList(CIR.Def.Idx) {
|
|||
if (env.common.findIdent("Builtin.Str.is_empty")) |str_is_empty_ident| {
|
||||
try low_level_map.put(str_is_empty_ident, .str_is_empty);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.List.len")) |list_len_ident| {
|
||||
try low_level_map.put(list_len_ident, .list_len);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.List.is_empty")) |list_is_empty_ident| {
|
||||
try low_level_map.put(list_is_empty_ident, .list_is_empty);
|
||||
}
|
||||
if (env.common.findIdent("list_get_unsafe")) |list_get_unsafe_ident| {
|
||||
try low_level_map.put(list_get_unsafe_ident, .list_get_unsafe);
|
||||
}
|
||||
if (env.common.findIdent("Builtin.Set.is_empty")) |set_is_empty_ident| {
|
||||
try low_level_map.put(set_is_empty_ident, .set_is_empty);
|
||||
}
|
||||
|
||||
// Bool operations
|
||||
if (env.common.findIdent("Builtin.Bool.is_eq")) |bool_is_eq_ident| {
|
||||
try low_level_map.put(bool_is_eq_ident, .bool_is_eq);
|
||||
}
|
||||
|
|
@ -637,7 +644,8 @@ fn compileModule(
|
|||
const box_ident = try module_env.insertIdent(base.Ident.for_text("Box"));
|
||||
|
||||
// Use provided bool_stmt and try_stmt if available, otherwise use undefined
|
||||
const common_idents: Check.CommonIdents = .{
|
||||
// For Builtin module, these will be found after canonicalization and updated before type checking
|
||||
var common_idents: Check.CommonIdents = .{
|
||||
.module_name = module_ident,
|
||||
.list = list_ident,
|
||||
.box = box_ident,
|
||||
|
|
@ -668,19 +676,7 @@ fn compileModule(
|
|||
return error.ParseError;
|
||||
}
|
||||
|
||||
// 4. Create module imports map (for cross-module references)
|
||||
var module_envs = std.AutoHashMap(base.Ident.Idx, Can.AutoImportedType).init(gpa);
|
||||
defer module_envs.deinit();
|
||||
|
||||
// Add dependencies (e.g., Dict for Set, Bool for Str)
|
||||
// IMPORTANT: Use the module's own ident store, not a temporary one,
|
||||
// because auto-import lookups will use the module's ident store
|
||||
for (deps) |dep| {
|
||||
const dep_ident = try module_env.insertIdent(base.Ident.for_text(dep.name));
|
||||
try module_envs.put(dep_ident, .{ .env = dep.env });
|
||||
}
|
||||
|
||||
// 5. Canonicalize
|
||||
// 4. Canonicalize
|
||||
try module_env.initCIRFields(gpa, module_name);
|
||||
|
||||
var can_result = try gpa.create(Can);
|
||||
|
|
@ -689,7 +685,8 @@ fn compileModule(
|
|||
gpa.destroy(can_result);
|
||||
}
|
||||
|
||||
can_result.* = try Can.init(module_env, parse_ast, &module_envs);
|
||||
// When compiling Builtin itself, pass null for module_envs so setupAutoImportedBuiltinTypes doesn't run
|
||||
can_result.* = try Can.init(module_env, parse_ast, null);
|
||||
|
||||
try can_result.canonicalizeFile();
|
||||
try can_result.validateForChecking();
|
||||
|
|
@ -705,6 +702,10 @@ fn compileModule(
|
|||
const type_name = module_env.getIdentText(d.name);
|
||||
std.debug.print(" - Undeclared type: {s}\n", .{type_name});
|
||||
},
|
||||
.ident_not_in_scope => |d| {
|
||||
const ident_name = module_env.getIdentText(d.ident);
|
||||
std.debug.print(" - Ident not in scope: {s}\n", .{ident_name});
|
||||
},
|
||||
.nested_value_not_found => |d| {
|
||||
const parent = module_env.getIdentText(d.parent_name);
|
||||
const nested = module_env.getIdentText(d.nested_name);
|
||||
|
|
@ -770,6 +771,22 @@ fn compileModule(
|
|||
eval_order_ptr.* = eval_order;
|
||||
module_env.evaluation_order = eval_order_ptr;
|
||||
}
|
||||
|
||||
// Find Bool and Try statements before type checking
|
||||
// When compiling Builtin, bool_stmt and try_stmt are initially undefined,
|
||||
// but they must be set before type checking begins
|
||||
const found_bool_stmt = findTypeDeclaration(module_env, "Bool") catch {
|
||||
std.debug.print("Error: Could not find Bool type in Builtin module\n", .{});
|
||||
return error.TypeDeclarationNotFound;
|
||||
};
|
||||
const found_try_stmt = findTypeDeclaration(module_env, "Try") catch {
|
||||
std.debug.print("Error: Could not find Try type in Builtin module\n", .{});
|
||||
return error.TypeDeclarationNotFound;
|
||||
};
|
||||
|
||||
// Update common_idents with the found statement indices
|
||||
common_idents.bool_stmt = found_bool_stmt;
|
||||
common_idents.try_stmt = found_try_stmt;
|
||||
}
|
||||
|
||||
// 6. Type check
|
||||
|
|
@ -782,6 +799,9 @@ fn compileModule(
|
|||
try imported_envs.append(gpa, dep.env);
|
||||
}
|
||||
|
||||
var module_envs = std.AutoHashMap(base.Ident.Idx, Can.AutoImportedType).init(gpa);
|
||||
defer module_envs.deinit();
|
||||
|
||||
var checker = try Check.init(
|
||||
gpa,
|
||||
&module_env.types,
|
||||
|
|
|
|||
|
|
@ -7,14 +7,18 @@ Builtin := [].{
|
|||
}
|
||||
|
||||
List := [ProvidedByCompiler].{
|
||||
len : List(a) -> U64
|
||||
len = |_| 0
|
||||
len : List(_elem) -> U64
|
||||
is_empty : List(_elem) -> Bool
|
||||
|
||||
is_empty : List(a) -> Bool
|
||||
is_empty = |_| True
|
||||
first : List(elem) -> Try(elem, [ListWasEmpty])
|
||||
first = |list| List.get(list, 0)
|
||||
|
||||
first : List(a) -> Try(a, [ListWasEmpty])
|
||||
first = |_| Err(ListWasEmpty)
|
||||
get : List(elem), U64 -> Try(elem, [ListWasEmpty])
|
||||
get = |list, index| if index < List.len(list) {
|
||||
Try.Ok(list_get_unsafe(list, index))
|
||||
} else {
|
||||
Try.Err(ListWasEmpty)
|
||||
}
|
||||
|
||||
map : List(a), (a -> b) -> List(b)
|
||||
map = |_, _| []
|
||||
|
|
@ -335,3 +339,7 @@ Builtin := [].{
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Private top-level function for unsafe list access
|
||||
# This is a low-level operation that gets replaced by the compiler
|
||||
list_get_unsafe : List(elem), U64 -> elem
|
||||
|
|
|
|||
|
|
@ -375,6 +375,28 @@ pub fn listIncref(list: RocList, amount: isize, elements_refcounted: bool) callc
|
|||
list.incref(amount, elements_refcounted);
|
||||
}
|
||||
|
||||
/// Get the number of elements in the list.
|
||||
pub fn listLen(list: RocList) callconv(.c) usize {
|
||||
return list.len();
|
||||
}
|
||||
|
||||
/// Check if the list is empty.
|
||||
pub fn listIsEmpty(list: RocList) callconv(.c) bool {
|
||||
return list.isEmpty();
|
||||
}
|
||||
|
||||
/// Get a pointer to an element at the given index without bounds checking.
|
||||
/// UNSAFE: No bounds checking is performed. Index must be < list.len().
|
||||
/// This is intended for internal use by low-level operations only.
|
||||
/// Returns a pointer to the element at the given index.
|
||||
pub fn listGetUnsafe(list: RocList, index: u64, element_width: usize) callconv(.c) ?[*]u8 {
|
||||
if (list.bytes) |bytes| {
|
||||
const byte_offset = @as(usize, @intCast(index)) * element_width;
|
||||
return bytes + byte_offset;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Decrement reference count and deallocate when no longer shared.
|
||||
pub fn listDecref(
|
||||
list: RocList,
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -387,6 +387,11 @@ pub const Expr = union(enum) {
|
|||
// String operations
|
||||
str_is_empty,
|
||||
|
||||
// List operations
|
||||
list_len,
|
||||
list_is_empty,
|
||||
list_get_unsafe,
|
||||
|
||||
// Set operations
|
||||
set_is_empty,
|
||||
|
||||
|
|
|
|||
|
|
@ -1587,9 +1587,12 @@ pub const Serialized = struct {
|
|||
// Overwrite ourself with the deserialized version, and return our pointer after casting it to Self.
|
||||
const env = @as(*Self, @ptrFromInt(@intFromPtr(self)));
|
||||
|
||||
// Deserialize common env first so we can look up identifiers
|
||||
const common = self.common.deserialize(offset, source).*;
|
||||
|
||||
env.* = Self{
|
||||
.gpa = gpa,
|
||||
.common = self.common.deserialize(offset, source).*,
|
||||
.common = common,
|
||||
.types = self.types.deserialize(offset, gpa).*,
|
||||
.module_kind = self.module_kind,
|
||||
.all_defs = self.all_defs,
|
||||
|
|
@ -1604,11 +1607,11 @@ pub const Serialized = struct {
|
|||
.store = self.store.deserialize(offset, gpa).*,
|
||||
.evaluation_order = null, // Not serialized, will be recomputed if needed
|
||||
// Well-known identifiers for type checking - look them up in the deserialized common env
|
||||
.from_int_digits_ident = env.common.findIdent(Ident.FROM_INT_DIGITS_METHOD_NAME) orelse unreachable,
|
||||
.from_dec_digits_ident = env.common.findIdent(Ident.FROM_DEC_DIGITS_METHOD_NAME) orelse unreachable,
|
||||
.try_ident = env.common.findIdent("Try") orelse unreachable,
|
||||
.out_of_range_ident = env.common.findIdent("OutOfRange") orelse unreachable,
|
||||
.builtin_module_ident = env.common.findIdent("Builtin") orelse unreachable,
|
||||
.from_int_digits_ident = common.findIdent(Ident.FROM_INT_DIGITS_METHOD_NAME) orelse unreachable,
|
||||
.from_dec_digits_ident = common.findIdent(Ident.FROM_DEC_DIGITS_METHOD_NAME) orelse unreachable,
|
||||
.try_ident = common.findIdent("Try") orelse unreachable,
|
||||
.out_of_range_ident = common.findIdent("OutOfRange") orelse unreachable,
|
||||
.builtin_module_ident = common.findIdent("Builtin") orelse unreachable,
|
||||
};
|
||||
|
||||
return env;
|
||||
|
|
|
|||
|
|
@ -339,15 +339,15 @@ test "exposed_items is populated correctly" {
|
|||
.canonicalizeFile();
|
||||
// Check that exposed_items contains the correct number of items
|
||||
// The exposed items were added during canonicalization
|
||||
// Should have exactly 3 entries (duplicates not stored)
|
||||
try testing.expectEqual(@as(usize, 3), env.common.exposed_items.count());
|
||||
// Check that exposed_items contains all exposed items
|
||||
// Should have exactly 2 value entries (duplicates not stored, types not included)
|
||||
// Types are not stored in exposed_items - they are handled by the type system
|
||||
try testing.expectEqual(@as(usize, 2), env.common.exposed_items.count());
|
||||
// Check that exposed_items contains all exposed values (not types)
|
||||
const foo_idx = env.common.idents.findByString("foo").?;
|
||||
const bar_idx = env.common.idents.findByString("bar").?;
|
||||
const mytype_idx = env.common.idents.findByString("MyType").?;
|
||||
try testing.expect(env.common.exposed_items.containsById(env.gpa, @bitCast(foo_idx)));
|
||||
try testing.expect(env.common.exposed_items.containsById(env.gpa, @bitCast(bar_idx)));
|
||||
try testing.expect(env.common.exposed_items.containsById(env.gpa, @bitCast(mytype_idx)));
|
||||
// MyType is not in exposed_items because it's a type, not a value
|
||||
}
|
||||
|
||||
test "exposed_items persists after canonicalization" {
|
||||
|
|
|
|||
|
|
@ -591,7 +591,7 @@ fn updateVar(self: *Self, target_var: Var, content: types_mod.Content, rank: typ
|
|||
// file //
|
||||
|
||||
/// Check the types for all defs
|
||||
/// Copy builtin types (Bool, Result) from their modules into the current module's type store
|
||||
/// Copy builtin types from their modules into the current module's type store
|
||||
/// This is necessary because type variables are module-specific - we can't use Vars from
|
||||
/// other modules directly. The Bool and Result types are used in language constructs like
|
||||
/// `if` conditions and need to be available in every module's type store.
|
||||
|
|
@ -618,9 +618,6 @@ pub fn checkFile(self: *Self) std.mem.Allocator.Error!void {
|
|||
|
||||
try ensureTypeStoreIsFilled(self);
|
||||
|
||||
// Copy builtin types (Bool, Result) into this module's type store
|
||||
try self.copyBuiltinTypes();
|
||||
|
||||
// First, iterate over the builtin statements, generating types for each type declaration
|
||||
const builtin_stmts_slice = self.cir.store.sliceStatements(self.cir.builtin_statements);
|
||||
for (builtin_stmts_slice) |builtin_stmt_idx| {
|
||||
|
|
@ -638,6 +635,11 @@ pub fn checkFile(self: *Self) std.mem.Allocator.Error!void {
|
|||
try self.generateStmtTypeDeclType(stmt_idx);
|
||||
}
|
||||
|
||||
// Copy builtin types into this module's type store
|
||||
// This must happen AFTER type declarations are generated so that when compiling
|
||||
// Builtin itself, the Bool and Try types have already been created
|
||||
try self.copyBuiltinTypes();
|
||||
|
||||
// First pass: assign placeholder type vars
|
||||
const defs_slice = self.cir.store.sliceDefs(self.cir.all_defs);
|
||||
for (defs_slice) |def_idx| {
|
||||
|
|
@ -689,7 +691,7 @@ pub fn checkFile(self: *Self) std.mem.Allocator.Error!void {
|
|||
pub fn checkExprRepl(self: *Self, expr_idx: CIR.Expr.Idx) std.mem.Allocator.Error!void {
|
||||
try ensureTypeStoreIsFilled(self);
|
||||
|
||||
// Copy builtin types (Bool, Result) into this module's type store
|
||||
// Copy builtin types into this module's type store
|
||||
try self.copyBuiltinTypes();
|
||||
|
||||
// First, iterate over the statements, generating types for each type declaration
|
||||
|
|
@ -948,7 +950,7 @@ fn generateAnnotationType(self: *Self, annotation_idx: CIR.Annotation.Idx) std.m
|
|||
try self.generateAnnoTypeInPlace(annotation.anno, .annotation);
|
||||
|
||||
// Redirect the root annotation to inner annotation
|
||||
_ = try self.types.setVarRedirect(ModuleEnv.varFrom(annotation_idx), ModuleEnv.varFrom(annotation.anno));
|
||||
try self.types.setVarRedirect(ModuleEnv.varFrom(annotation_idx), ModuleEnv.varFrom(annotation.anno));
|
||||
}
|
||||
|
||||
/// Given a where clause, generate static dispatch constraints and add to scratch_static_dispatch_constraints
|
||||
|
|
@ -2453,9 +2455,9 @@ fn checkExpr(self: *Self, expr_idx: CIR.Expr.Idx, rank: types_mod.Rank, expected
|
|||
// We never instantiate rigid variables
|
||||
if (resolved_pat.rank == Rank.generalized and resolved_pat.content != .rigid) {
|
||||
const instantiated = try self.instantiateVar(pat_var, rank, .use_last_var);
|
||||
_ = try self.types.setVarRedirect(expr_var, instantiated);
|
||||
try self.types.setVarRedirect(expr_var, instantiated);
|
||||
} else {
|
||||
_ = try self.types.setVarRedirect(expr_var, pat_var);
|
||||
try self.types.setVarRedirect(expr_var, pat_var);
|
||||
}
|
||||
|
||||
// Unify this expression with the referenced pattern
|
||||
|
|
@ -2647,7 +2649,7 @@ fn checkExpr(self: *Self, expr_idx: CIR.Expr.Idx, rank: types_mod.Rank, expected
|
|||
},
|
||||
.e_closure => |closure| {
|
||||
does_fx = try self.checkExpr(closure.lambda_idx, rank, expected) or does_fx;
|
||||
_ = try self.types.setVarRedirect(expr_var, ModuleEnv.varFrom(closure.lambda_idx));
|
||||
try self.types.setVarRedirect(expr_var, ModuleEnv.varFrom(closure.lambda_idx));
|
||||
},
|
||||
// function calling //
|
||||
.e_call => |call| {
|
||||
|
|
@ -2796,7 +2798,7 @@ fn checkExpr(self: *Self, expr_idx: CIR.Expr.Idx, rank: types_mod.Rank, expected
|
|||
}
|
||||
|
||||
// Redirect the expr to the function's return type
|
||||
_ = try self.types.setVarRedirect(expr_var, func.ret);
|
||||
try self.types.setVarRedirect(expr_var, func.ret);
|
||||
} else {
|
||||
// TODO(jared): Better arity difference error message
|
||||
|
||||
|
|
@ -2813,7 +2815,7 @@ fn checkExpr(self: *Self, expr_idx: CIR.Expr.Idx, rank: types_mod.Rank, expected
|
|||
try self.var_pool.addVarToRank(call_func_var, rank);
|
||||
|
||||
_ = try self.unify(func_var, call_func_var, rank);
|
||||
_ = try self.types.setVarRedirect(expr_var, call_func_ret);
|
||||
try self.types.setVarRedirect(expr_var, call_func_ret);
|
||||
}
|
||||
} else {
|
||||
// We get here if the type of expr being called
|
||||
|
|
@ -2841,7 +2843,7 @@ fn checkExpr(self: *Self, expr_idx: CIR.Expr.Idx, rank: types_mod.Rank, expected
|
|||
// Then, we set the root expr to redirect to the return
|
||||
// type of that function, since a call expr ultimate
|
||||
// resolve to the returned type
|
||||
_ = try self.types.setVarRedirect(expr_var, call_func_ret);
|
||||
try self.types.setVarRedirect(expr_var, call_func_ret);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -2966,7 +2968,7 @@ fn checkExpr(self: *Self, expr_idx: CIR.Expr.Idx, rank: types_mod.Rank, expected
|
|||
},
|
||||
.e_dbg => |dbg| {
|
||||
does_fx = try self.checkExpr(dbg.expr, rank, expected) or does_fx;
|
||||
_ = try self.types.setVarRedirect(expr_var, ModuleEnv.varFrom(dbg.expr));
|
||||
try self.types.setVarRedirect(expr_var, ModuleEnv.varFrom(dbg.expr));
|
||||
},
|
||||
.e_expect => |expect| {
|
||||
does_fx = try self.checkExpr(expect.body, rank, expected) or does_fx;
|
||||
|
|
@ -2979,14 +2981,14 @@ fn checkExpr(self: *Self, expr_idx: CIR.Expr.Idx, rank: types_mod.Rank, expected
|
|||
// For annotation-only expressions, the type comes from the annotation.
|
||||
// This case should only occur when the expression has an annotation (which is
|
||||
// enforced during canonicalization), so the expected type should be set.
|
||||
// The type will be unified with the expected type in the code below.
|
||||
switch (expected) {
|
||||
.no_expectation => {
|
||||
// This shouldn't happen since we always create e_anno_only with an annotation
|
||||
try self.updateVar(expr_var, .err, rank);
|
||||
},
|
||||
.expected => {
|
||||
// The expr_var will be unified with the annotation var below
|
||||
.expected => |expected_type| {
|
||||
// Redirect expr_var to the annotation var so that lookups get the correct type
|
||||
try self.types.setVarRedirect(expr_var, expected_type.var_);
|
||||
},
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -40,4 +40,5 @@ test "check tests" {
|
|||
std.testing.refAllDecls(@import("test/let_polymorphism_integration_test.zig"));
|
||||
std.testing.refAllDecls(@import("test/num_type_inference_test.zig"));
|
||||
std.testing.refAllDecls(@import("test/num_type_requirements_test.zig"));
|
||||
std.testing.refAllDecls(@import("test/builtin_scope_test.zig"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -215,21 +215,21 @@ pub fn initWithImport(module_name: []const u8, source: []const u8, other_module_
|
|||
.builtin_module = other_test_env.builtin_module.env,
|
||||
};
|
||||
|
||||
// Build imported_envs array dynamically based on module_env.imports order
|
||||
// This matches the production approach in compile_package.zig
|
||||
const import_count = module_env.imports.imports.items.items.len;
|
||||
var imported_envs = try std.ArrayList(*const ModuleEnv).initCapacity(gpa, import_count);
|
||||
// Build imported_envs array
|
||||
// Always include the builtin module for auto-imported types (Bool, Str, etc.)
|
||||
var imported_envs = try std.ArrayList(*const ModuleEnv).initCapacity(gpa, 2);
|
||||
defer imported_envs.deinit(gpa);
|
||||
|
||||
// Add builtin module unconditionally (needed for auto-imported types)
|
||||
try imported_envs.append(gpa, other_test_env.builtin_module.env);
|
||||
|
||||
// Process explicit imports
|
||||
const import_count = module_env.imports.imports.items.items.len;
|
||||
for (module_env.imports.imports.items.items[0..import_count]) |str_idx| {
|
||||
const import_name = module_env.getString(str_idx);
|
||||
if (std.mem.eql(u8, import_name, "Builtin")) {
|
||||
try imported_envs.append(gpa, other_test_env.builtin_module.env);
|
||||
} else if (std.mem.eql(u8, import_name, other_module_name)) {
|
||||
if (std.mem.eql(u8, import_name, other_module_name)) {
|
||||
// Cross-module import - append the other test module's env
|
||||
try imported_envs.append(gpa, other_test_env.module_env);
|
||||
} else {
|
||||
std.debug.print("WARNING: Unknown import in test: {s}\n", .{import_name});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -331,22 +331,13 @@ pub fn init(module_name: []const u8, source: []const u8) !TestEnv {
|
|||
.builtin_module = builtin_module.env,
|
||||
};
|
||||
|
||||
// Build imported_envs array dynamically based on module_env.imports order
|
||||
// This matches the production approach in compile_package.zig
|
||||
const import_count = module_env.imports.imports.items.items.len;
|
||||
var imported_envs = try std.ArrayList(*const ModuleEnv).initCapacity(gpa, import_count);
|
||||
// Build imported_envs array
|
||||
// Always include the builtin module for auto-imported types (Bool, Str, etc.)
|
||||
var imported_envs = try std.ArrayList(*const ModuleEnv).initCapacity(gpa, 2);
|
||||
defer imported_envs.deinit(gpa);
|
||||
|
||||
for (module_env.imports.imports.items.items[0..import_count]) |str_idx| {
|
||||
const import_name = module_env.getString(str_idx);
|
||||
// For tests, all imports are to the Builtin module
|
||||
if (std.mem.eql(u8, import_name, "Builtin")) {
|
||||
try imported_envs.append(gpa, builtin_module.env);
|
||||
} else {
|
||||
// If there are other imports in the future, handle them here
|
||||
std.debug.print("WARNING: Unknown import in test: {s}\n", .{import_name});
|
||||
}
|
||||
}
|
||||
// Add builtin module unconditionally (needed for auto-imported types)
|
||||
try imported_envs.append(gpa, builtin_module.env);
|
||||
|
||||
// Type Check - Pass the imported modules in other_modules parameter
|
||||
var checker = try Check.init(
|
||||
|
|
|
|||
98
src/check/test/builtin_scope_test.zig
Normal file
98
src/check/test/builtin_scope_test.zig
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
//! Tests verifying that "Builtin" is not in scope and cannot be imported,
|
||||
//! but that nested types like Str, List, etc. are available.
|
||||
|
||||
const TestEnv = @import("./TestEnv.zig");
|
||||
const testing = @import("std").testing;
|
||||
const std = @import("std");
|
||||
|
||||
test "cannot import Builtin module" {
|
||||
const src =
|
||||
\\import Builtin
|
||||
\\
|
||||
\\x = 5
|
||||
;
|
||||
|
||||
var test_env = try TestEnv.init("Test", src);
|
||||
defer test_env.deinit();
|
||||
|
||||
// Should have a canonicalization problem because Builtin is not a module that can be imported
|
||||
const diagnostics = try test_env.module_env.getDiagnostics();
|
||||
defer test_env.module_env.gpa.free(diagnostics);
|
||||
|
||||
// Expect at least one diagnostic (module not found error)
|
||||
try testing.expect(diagnostics.len > 0);
|
||||
}
|
||||
|
||||
test "can define userspace type named Builtin" {
|
||||
const src =
|
||||
\\Test := [A, B, C]
|
||||
\\
|
||||
\\Builtin := [D, E, F]
|
||||
\\
|
||||
\\x : Builtin
|
||||
\\x = D
|
||||
;
|
||||
|
||||
var test_env = try TestEnv.init("Test", src);
|
||||
defer test_env.deinit();
|
||||
|
||||
// Should have no problems - Builtin is a valid userspace name
|
||||
try test_env.assertDefType("x", "Builtin");
|
||||
}
|
||||
|
||||
test "builtin types are still available without import" {
|
||||
const src =
|
||||
\\Test := [Whatever]
|
||||
\\
|
||||
\\x : Str
|
||||
\\x = "hello"
|
||||
\\
|
||||
\\y : List(U64)
|
||||
\\y = [1, 2, 3]
|
||||
;
|
||||
|
||||
var test_env = try TestEnv.init("Test", src);
|
||||
defer test_env.deinit();
|
||||
|
||||
// Builtin types like Str and List should work without importing Builtin
|
||||
try test_env.assertDefType("x", "Str");
|
||||
try test_env.assertDefType("y", "List(Num(Int(Unsigned64)))");
|
||||
}
|
||||
|
||||
test "can import userspace Builtin module" {
|
||||
const builtin_module_src =
|
||||
\\Builtin := [D, E, F]
|
||||
\\
|
||||
\\value : Builtin
|
||||
\\value = D
|
||||
;
|
||||
|
||||
var builtin_module = try TestEnv.init("Builtin", builtin_module_src);
|
||||
defer builtin_module.deinit();
|
||||
|
||||
const main_src =
|
||||
\\Main := [Whatever]
|
||||
\\
|
||||
\\import Builtin
|
||||
\\
|
||||
\\x : Builtin
|
||||
\\x = Builtin.value
|
||||
;
|
||||
|
||||
var main_module = try TestEnv.initWithImport("Main", main_src, "Builtin", &builtin_module);
|
||||
defer main_module.deinit();
|
||||
|
||||
// Should successfully import the userspace Builtin module without "module not found" error
|
||||
const diagnostics = try main_module.module_env.getDiagnostics();
|
||||
defer main_module.module_env.gpa.free(diagnostics);
|
||||
|
||||
// Check that there's no "module not found" error for "Builtin"
|
||||
for (diagnostics) |diag| {
|
||||
if (diag == .module_not_found) {
|
||||
const module_name = main_module.module_env.getIdent(diag.module_not_found.module_name);
|
||||
if (std.mem.eql(u8, module_name, "Builtin")) {
|
||||
try testing.expect(false); // Should not have module_not_found for Builtin
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2109,16 +2109,97 @@ pub const Interpreter = struct {
|
|||
switch (op) {
|
||||
.str_is_empty => {
|
||||
// Str.is_empty : Str -> Bool
|
||||
if (args.len != 1) return error.TypeMismatch;
|
||||
std.debug.assert(args.len == 1); // low-level .str_is_empty expects 1 argument
|
||||
|
||||
const str_arg = args[0];
|
||||
if (str_arg.ptr == null) return error.TypeMismatch;
|
||||
std.debug.assert(str_arg.ptr != null); // low-level .str_is_empty expects non-null string pointer
|
||||
|
||||
const roc_str: *const RocStr = @ptrCast(@alignCast(str_arg.ptr.?));
|
||||
const result = builtins.str.isEmpty(roc_str.*);
|
||||
|
||||
return try self.makeSimpleBoolValue(result);
|
||||
},
|
||||
.list_len => {
|
||||
// List.len : List(a) -> U64
|
||||
// Note: listLen returns usize, but List.len always returns U64.
|
||||
// We need to cast usize -> u64 for 32-bit targets (e.g. wasm32).
|
||||
std.debug.assert(args.len == 1); // low-level .list_len expects 1 argument
|
||||
|
||||
const list_arg = args[0];
|
||||
std.debug.assert(list_arg.ptr != null); // low-level .list_len expects non-null list pointer
|
||||
|
||||
const roc_list: *const builtins.list.RocList = @ptrCast(@alignCast(list_arg.ptr.?));
|
||||
const len_usize = builtins.list.listLen(roc_list.*);
|
||||
const len_u64: u64 = @intCast(len_usize);
|
||||
|
||||
const result_layout = layout.Layout.int(.u64);
|
||||
var out = try self.pushRaw(result_layout, 0);
|
||||
out.is_initialized = false;
|
||||
out.setInt(@intCast(len_u64));
|
||||
out.is_initialized = true;
|
||||
return out;
|
||||
},
|
||||
.list_is_empty => {
|
||||
// List.is_empty : List(a) -> Bool
|
||||
std.debug.assert(args.len == 1); // low-level .list_is_empty expects 1 argument
|
||||
|
||||
const list_arg = args[0];
|
||||
std.debug.assert(list_arg.ptr != null); // low-level .list_is_empty expects non-null list pointer
|
||||
|
||||
const roc_list: *const builtins.list.RocList = @ptrCast(@alignCast(list_arg.ptr.?));
|
||||
const result = builtins.list.listIsEmpty(roc_list.*);
|
||||
|
||||
return try self.makeSimpleBoolValue(result);
|
||||
},
|
||||
.list_get_unsafe => {
|
||||
// Internal operation: Get element at index without bounds checking
|
||||
// Args: List(a), U64 (index)
|
||||
// Returns: a (the element)
|
||||
std.debug.assert(args.len == 2); // low-level .list_get_unsafe expects 2 arguments
|
||||
|
||||
const list_arg = args[0];
|
||||
const index_arg = args[1];
|
||||
|
||||
std.debug.assert(list_arg.ptr != null); // low-level .list_get_unsafe expects non-null list pointer
|
||||
|
||||
// Extract element layout from List(a)
|
||||
std.debug.assert(list_arg.layout.tag == .list or list_arg.layout.tag == .list_of_zst); // low-level .list_get_unsafe expects list layout
|
||||
|
||||
const roc_list: *const builtins.list.RocList = @ptrCast(@alignCast(list_arg.ptr.?));
|
||||
const index = index_arg.asI128(); // U64 stored as i128
|
||||
|
||||
// Get element layout
|
||||
const elem_layout_idx = list_arg.layout.data.list;
|
||||
const elem_layout = self.runtime_layout_store.getLayout(elem_layout_idx);
|
||||
const elem_size = self.runtime_layout_store.layoutSize(elem_layout);
|
||||
|
||||
if (elem_size == 0) {
|
||||
// ZST element - return zero-sized value
|
||||
return StackValue{
|
||||
.layout = elem_layout,
|
||||
.ptr = null,
|
||||
.is_initialized = true,
|
||||
};
|
||||
}
|
||||
|
||||
// Get pointer to element (no bounds checking!)
|
||||
const elem_ptr = builtins.list.listGetUnsafe(roc_list.*, @intCast(index), elem_size);
|
||||
|
||||
if (elem_ptr == null) {
|
||||
self.triggerCrash("list_get_unsafe: null pointer returned", false, roc_ops);
|
||||
return error.Crash;
|
||||
}
|
||||
|
||||
// Create StackValue pointing to the element
|
||||
const elem_value = StackValue{
|
||||
.layout = elem_layout,
|
||||
.ptr = @ptrCast(elem_ptr.?),
|
||||
.is_initialized = true,
|
||||
};
|
||||
|
||||
// Copy to new location and increment refcount
|
||||
return try self.pushCopy(elem_value, roc_ops);
|
||||
},
|
||||
.set_is_empty => {
|
||||
// TODO: implement Set.is_empty
|
||||
self.triggerCrash("Set.is_empty not yet implemented", false, roc_ops);
|
||||
|
|
@ -2128,7 +2209,7 @@ pub const Interpreter = struct {
|
|||
// Bool operations
|
||||
.bool_is_eq => {
|
||||
// Bool.is_eq : Bool, Bool -> Bool
|
||||
if (args.len != 2) return error.TypeMismatch;
|
||||
std.debug.assert(args.len == 2); // low-level .bool_is_eq expects 2 arguments
|
||||
const lhs = args[0].asBool();
|
||||
const rhs = args[1].asBool();
|
||||
const result = lhs == rhs;
|
||||
|
|
@ -2136,7 +2217,7 @@ pub const Interpreter = struct {
|
|||
},
|
||||
.bool_is_ne => {
|
||||
// Bool.is_ne : Bool, Bool -> Bool
|
||||
if (args.len != 2) return error.TypeMismatch;
|
||||
std.debug.assert(args.len == 2); // low-level .bool_is_ne expects 2 arguments
|
||||
const lhs = args[0].asBool();
|
||||
const rhs = args[1].asBool();
|
||||
const result = lhs != rhs;
|
||||
|
|
@ -2146,7 +2227,7 @@ pub const Interpreter = struct {
|
|||
// Numeric type checking operations
|
||||
.num_is_zero => {
|
||||
// num.is_zero : num -> Bool
|
||||
if (args.len != 1) return error.TypeMismatch;
|
||||
std.debug.assert(args.len == 1); // low-level .num_is_zero expects 1 argument
|
||||
const num_val = try self.extractNumericValue(args[0]);
|
||||
const result = switch (num_val) {
|
||||
.int => |i| i == 0,
|
||||
|
|
@ -2158,7 +2239,7 @@ pub const Interpreter = struct {
|
|||
},
|
||||
.num_is_negative => {
|
||||
// num.is_negative : num -> Bool (signed types only)
|
||||
if (args.len != 1) return error.TypeMismatch;
|
||||
std.debug.assert(args.len == 1); // low-level .num_is_negative expects 1 argument
|
||||
const num_val = try self.extractNumericValue(args[0]);
|
||||
const result = switch (num_val) {
|
||||
.int => |i| i < 0,
|
||||
|
|
@ -2170,7 +2251,7 @@ pub const Interpreter = struct {
|
|||
},
|
||||
.num_is_positive => {
|
||||
// num.is_positive : num -> Bool (signed types only)
|
||||
if (args.len != 1) return error.TypeMismatch;
|
||||
std.debug.assert(args.len == 1); // low-level .num_is_positive expects 1 argument
|
||||
const num_val = try self.extractNumericValue(args[0]);
|
||||
const result = switch (num_val) {
|
||||
.int => |i| i > 0,
|
||||
|
|
@ -2184,7 +2265,7 @@ pub const Interpreter = struct {
|
|||
// Numeric comparison operations
|
||||
.num_is_eq => {
|
||||
// num.is_eq : num, num -> Bool (all integer types + Dec, NOT F32/F64)
|
||||
if (args.len != 2) return error.TypeMismatch;
|
||||
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) {
|
||||
|
|
@ -2199,7 +2280,7 @@ pub const Interpreter = struct {
|
|||
},
|
||||
.num_is_ne => {
|
||||
// num.is_ne : num, num -> Bool (Dec only)
|
||||
if (args.len != 2) return error.TypeMismatch;
|
||||
std.debug.assert(args.len == 2); // low-level .num_is_ne expects 2 arguments
|
||||
const lhs = try self.extractNumericValue(args[0]);
|
||||
const rhs = try self.extractNumericValue(args[1]);
|
||||
const result = switch (lhs) {
|
||||
|
|
@ -2213,7 +2294,7 @@ pub const Interpreter = struct {
|
|||
},
|
||||
.num_is_gt => {
|
||||
// num.is_gt : num, num -> Bool
|
||||
if (args.len != 2) return error.TypeMismatch;
|
||||
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) {
|
||||
|
|
@ -2226,7 +2307,7 @@ pub const Interpreter = struct {
|
|||
},
|
||||
.num_is_gte => {
|
||||
// num.is_gte : num, num -> Bool
|
||||
if (args.len != 2) return error.TypeMismatch;
|
||||
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) {
|
||||
|
|
@ -2239,7 +2320,7 @@ pub const Interpreter = struct {
|
|||
},
|
||||
.num_is_lt => {
|
||||
// num.is_lt : num, num -> Bool
|
||||
if (args.len != 2) return error.TypeMismatch;
|
||||
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) {
|
||||
|
|
@ -2252,7 +2333,7 @@ pub const Interpreter = struct {
|
|||
},
|
||||
.num_is_lte => {
|
||||
// num.is_lte : num, num -> Bool
|
||||
if (args.len != 2) return error.TypeMismatch;
|
||||
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) {
|
||||
|
|
@ -2267,7 +2348,7 @@ pub const Interpreter = struct {
|
|||
// Numeric arithmetic operations
|
||||
.num_negate => {
|
||||
// num.negate : num -> num (signed types only)
|
||||
if (args.len != 1) return error.TypeMismatch;
|
||||
std.debug.assert(args.len == 1); // low-level .num_negate expects 1 argument
|
||||
const num_val = try self.extractNumericValue(args[0]);
|
||||
const result_layout = args[0].layout;
|
||||
|
||||
|
|
@ -2284,7 +2365,7 @@ pub const Interpreter = struct {
|
|||
return out;
|
||||
},
|
||||
.num_plus => {
|
||||
if (args.len != 2) return error.TypeMismatch;
|
||||
std.debug.assert(args.len == 2); // low-level .num_plus expects 2 arguments
|
||||
const lhs = try self.extractNumericValue(args[0]);
|
||||
const rhs = try self.extractNumericValue(args[1]);
|
||||
const result_layout = args[0].layout;
|
||||
|
|
@ -2302,7 +2383,7 @@ pub const Interpreter = struct {
|
|||
return out;
|
||||
},
|
||||
.num_minus => {
|
||||
if (args.len != 2) return error.TypeMismatch;
|
||||
std.debug.assert(args.len == 2); // low-level .num_minus expects 2 arguments
|
||||
const lhs = try self.extractNumericValue(args[0]);
|
||||
const rhs = try self.extractNumericValue(args[1]);
|
||||
const result_layout = args[0].layout;
|
||||
|
|
@ -2320,7 +2401,7 @@ pub const Interpreter = struct {
|
|||
return out;
|
||||
},
|
||||
.num_times => {
|
||||
if (args.len != 2) return error.TypeMismatch;
|
||||
std.debug.assert(args.len == 2); // low-level .num_times expects 2 arguments
|
||||
const lhs = try self.extractNumericValue(args[0]);
|
||||
const rhs = try self.extractNumericValue(args[1]);
|
||||
const result_layout = args[0].layout;
|
||||
|
|
@ -2338,7 +2419,7 @@ pub const Interpreter = struct {
|
|||
return out;
|
||||
},
|
||||
.num_div_by => {
|
||||
if (args.len != 2) return error.TypeMismatch;
|
||||
std.debug.assert(args.len == 2); // low-level .num_div_by expects 2 arguments
|
||||
const lhs = try self.extractNumericValue(args[0]);
|
||||
const rhs = try self.extractNumericValue(args[1]);
|
||||
const result_layout = args[0].layout;
|
||||
|
|
@ -2369,7 +2450,7 @@ pub const Interpreter = struct {
|
|||
return out;
|
||||
},
|
||||
.num_rem_by => {
|
||||
if (args.len != 2) return error.TypeMismatch;
|
||||
std.debug.assert(args.len == 2); // low-level .num_rem_by expects 2 arguments
|
||||
const lhs = try self.extractNumericValue(args[0]);
|
||||
const rhs = try self.extractNumericValue(args[1]);
|
||||
const result_layout = args[0].layout;
|
||||
|
|
|
|||
|
|
@ -210,3 +210,110 @@ test "e_anno_only - value only crashes when accessed (False branch)" {
|
|||
try testing.expectEqual(@as(u32, 2), summary.evaluated);
|
||||
try testing.expectEqual(@as(u32, 0), summary.crashed);
|
||||
}
|
||||
|
||||
test "List.first on nonempty list" {
|
||||
const src =
|
||||
\\result = List.first([1, 2, 3])
|
||||
;
|
||||
|
||||
var result = try parseCheckAndEvalModule(src);
|
||||
defer cleanupEvalModule(&result);
|
||||
|
||||
const summary = try result.evaluator.evalAll();
|
||||
|
||||
// Should evaluate 1 declaration with 0 crashes (List.first should succeed)
|
||||
try testing.expectEqual(@as(u32, 1), summary.evaluated);
|
||||
try testing.expectEqual(@as(u32, 0), summary.crashed);
|
||||
}
|
||||
|
||||
test "List.get with valid index returns Ok" {
|
||||
const src =
|
||||
\\result = List.get([1, 2, 3], 1)
|
||||
;
|
||||
|
||||
var result = try parseCheckAndEvalModule(src);
|
||||
defer cleanupEvalModule(&result);
|
||||
|
||||
const summary = try result.evaluator.evalAll();
|
||||
|
||||
// Should evaluate 1 declaration with 0 crashes (List.get should succeed)
|
||||
try testing.expectEqual(@as(u32, 1), summary.evaluated);
|
||||
try testing.expectEqual(@as(u32, 0), summary.crashed);
|
||||
}
|
||||
|
||||
test "List.get with invalid index returns Err" {
|
||||
const src =
|
||||
\\result = List.get([1, 2, 3], 10)
|
||||
;
|
||||
|
||||
var result = try parseCheckAndEvalModule(src);
|
||||
defer cleanupEvalModule(&result);
|
||||
|
||||
const summary = try result.evaluator.evalAll();
|
||||
|
||||
// Should evaluate 1 declaration with 0 crashes (List.get should return Err but not crash)
|
||||
try testing.expectEqual(@as(u32, 1), summary.evaluated);
|
||||
try testing.expectEqual(@as(u32, 0), summary.crashed);
|
||||
}
|
||||
|
||||
test "List.get on empty list returns Err" {
|
||||
const src =
|
||||
\\empty : List(U64)
|
||||
\\empty = []
|
||||
\\result = List.get(empty, 0)
|
||||
;
|
||||
|
||||
var result = try parseCheckAndEvalModule(src);
|
||||
defer cleanupEvalModule(&result);
|
||||
|
||||
const summary = try result.evaluator.evalAll();
|
||||
|
||||
// Should evaluate 2 declarations with 0 crashes (List.get should return Err but not crash)
|
||||
try testing.expectEqual(@as(u32, 2), summary.evaluated);
|
||||
try testing.expectEqual(@as(u32, 0), summary.crashed);
|
||||
}
|
||||
|
||||
test "List.get with different element types - Str" {
|
||||
const src =
|
||||
\\result = List.get(["foo", "bar", "baz"], 1)
|
||||
;
|
||||
|
||||
var result = try parseCheckAndEvalModule(src);
|
||||
defer cleanupEvalModule(&result);
|
||||
|
||||
const summary = try result.evaluator.evalAll();
|
||||
|
||||
// Should evaluate 1 declaration with 0 crashes
|
||||
try testing.expectEqual(@as(u32, 1), summary.evaluated);
|
||||
try testing.expectEqual(@as(u32, 0), summary.crashed);
|
||||
}
|
||||
|
||||
test "List.get with different element types - Bool" {
|
||||
const src =
|
||||
\\result = List.get([True, False, True], 2)
|
||||
;
|
||||
|
||||
var result = try parseCheckAndEvalModule(src);
|
||||
defer cleanupEvalModule(&result);
|
||||
|
||||
const summary = try result.evaluator.evalAll();
|
||||
|
||||
// Should evaluate 1 declaration with 0 crashes
|
||||
try testing.expectEqual(@as(u32, 1), summary.evaluated);
|
||||
try testing.expectEqual(@as(u32, 0), summary.crashed);
|
||||
}
|
||||
|
||||
test "List.get with nested lists" {
|
||||
const src =
|
||||
\\result = List.get([[1, 2], [3, 4], [5, 6]], 1)
|
||||
;
|
||||
|
||||
var result = try parseCheckAndEvalModule(src);
|
||||
defer cleanupEvalModule(&result);
|
||||
|
||||
const summary = try result.evaluator.evalAll();
|
||||
|
||||
// Should evaluate 1 declaration with 0 crashes
|
||||
try testing.expectEqual(@as(u32, 1), summary.evaluated);
|
||||
try testing.expectEqual(@as(u32, 0), summary.crashed);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,13 +19,19 @@ const ModuleEnv = can.ModuleEnv;
|
|||
const testing = std.testing;
|
||||
const test_allocator = testing.allocator;
|
||||
|
||||
/// Helper to parse, canonicalize, type-check, and run comptime evaluation on a full module
|
||||
fn parseCheckAndEvalModule(src: []const u8) !struct {
|
||||
const EvalModuleResult = struct {
|
||||
module_env: *ModuleEnv,
|
||||
evaluator: ComptimeEvaluator,
|
||||
problems: *check.problem.Store,
|
||||
builtin_module: builtin_loading.LoadedModule,
|
||||
} {
|
||||
};
|
||||
|
||||
/// Helper to parse, canonicalize, type-check, and run comptime evaluation on a full module
|
||||
fn parseCheckAndEvalModule(src: []const u8) !EvalModuleResult {
|
||||
return parseCheckAndEvalModuleWithName(src, "TestModule");
|
||||
}
|
||||
|
||||
fn parseCheckAndEvalModuleWithName(src: []const u8, module_name: []const u8) !EvalModuleResult {
|
||||
const gpa = test_allocator;
|
||||
|
||||
const module_env = try gpa.create(ModuleEnv);
|
||||
|
|
@ -34,7 +40,7 @@ fn parseCheckAndEvalModule(src: []const u8) !struct {
|
|||
errdefer module_env.deinit();
|
||||
|
||||
module_env.common.source = src;
|
||||
module_env.module_name = "TestModule";
|
||||
module_env.module_name = module_name;
|
||||
try module_env.common.calcLineStarts(module_env.gpa);
|
||||
|
||||
// Parse the source code
|
||||
|
|
@ -51,9 +57,9 @@ fn parseCheckAndEvalModule(src: []const u8) !struct {
|
|||
errdefer builtin_module.deinit();
|
||||
|
||||
// Initialize CIR fields in ModuleEnv
|
||||
try module_env.initCIRFields(gpa, "test");
|
||||
try module_env.initCIRFields(gpa, module_name);
|
||||
const common_idents: Check.CommonIdents = .{
|
||||
.module_name = try module_env.insertIdent(base.Ident.for_text("test")),
|
||||
.module_name = try module_env.insertIdent(base.Ident.for_text(module_name)),
|
||||
.list = try module_env.insertIdent(base.Ident.for_text("List")),
|
||||
.box = try module_env.insertIdent(base.Ident.for_text("Box")),
|
||||
.bool_stmt = builtin_indices.bool_type,
|
||||
|
|
@ -91,14 +97,16 @@ fn parseCheckAndEvalModule(src: []const u8) !struct {
|
|||
};
|
||||
}
|
||||
|
||||
/// Helper to parse, canonicalize, type-check, and run comptime evaluation with imported modules
|
||||
fn parseCheckAndEvalModuleWithImport(src: []const u8, import_name: []const u8, imported_module: *const ModuleEnv) !struct {
|
||||
const EvalModuleWithImportResult = struct {
|
||||
module_env: *ModuleEnv,
|
||||
evaluator: ComptimeEvaluator,
|
||||
problems: *check.problem.Store,
|
||||
other_envs: []const *const ModuleEnv,
|
||||
builtin_module: builtin_loading.LoadedModule,
|
||||
} {
|
||||
};
|
||||
|
||||
/// Helper to parse, canonicalize, type-check, and run comptime evaluation with imported modules
|
||||
fn parseCheckAndEvalModuleWithImport(src: []const u8, import_name: []const u8, imported_module: *const ModuleEnv) !EvalModuleWithImportResult {
|
||||
const gpa = test_allocator;
|
||||
|
||||
const module_env = try gpa.create(ModuleEnv);
|
||||
|
|
@ -138,6 +146,9 @@ fn parseCheckAndEvalModuleWithImport(src: []const u8, import_name: []const u8, i
|
|||
var module_envs = std.AutoHashMap(base.Ident.Idx, Can.AutoImportedType).init(gpa);
|
||||
defer module_envs.deinit();
|
||||
|
||||
// Populate module_envs with builtin types (like production does)
|
||||
try Can.populateModuleEnvs(&module_envs, module_env, builtin_module.env, builtin_indices);
|
||||
|
||||
// Convert import name to Ident.Idx using the MODULE's ident store (not a temporary one!)
|
||||
// This is important because the canonicalizer will look up identifiers in this same store
|
||||
const import_ident = try module_env.insertIdent(base.Ident.for_text(import_name));
|
||||
|
|
@ -382,7 +393,7 @@ test "comptime eval - cross-module crash is detected" {
|
|||
\\}
|
||||
;
|
||||
|
||||
var result_a = try parseCheckAndEvalModule(src_a);
|
||||
var result_a = try parseCheckAndEvalModuleWithName(src_a, "A");
|
||||
defer cleanupEvalModule(&result_a);
|
||||
|
||||
const summary_a = try result_a.evaluator.evalAll();
|
||||
|
|
|
|||
|
|
@ -137,9 +137,9 @@ foo = Json.parse(data)
|
|||
~~~clojure
|
||||
(inferred-types
|
||||
(defs
|
||||
(patt (type "Error"))
|
||||
(patt (type "Str"))
|
||||
(patt (type "Error")))
|
||||
(expressions
|
||||
(expr (type "Error"))
|
||||
(expr (type "Str"))
|
||||
(expr (type "Error"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -840,7 +840,7 @@ h = |x, y| {
|
|||
~~~clojure
|
||||
(inferred-types
|
||||
(defs
|
||||
(patt (type "Error"))
|
||||
(patt (type "e -> e"))
|
||||
(patt (type "[Z1((c, d)), Z2(c, f), Z3({ a: c, b: i }), Z4(List(c))]j, [Z1((c, d)), Z2(c, f), Z3({ a: c, b: i }), Z4(List(c))]j -> c")))
|
||||
(type_decls
|
||||
(alias (type "A(a)")
|
||||
|
|
@ -866,6 +866,6 @@ h = |x, y| {
|
|||
(alias (type "F")
|
||||
(ty-header (name "F"))))
|
||||
(expressions
|
||||
(expr (type "Error"))
|
||||
(expr (type "e -> e"))
|
||||
(expr (type "[Z1((c, d)), Z2(c, f), Z3({ a: c, b: i }), Z4(List(c))]j, [Z1((c, d)), Z2(c, f), Z3({ a: c, b: i }), Z4(List(c))]j -> c"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -76,6 +76,13 @@ NO CHANGE
|
|||
(d-let
|
||||
(p-assign (ident "a!"))
|
||||
(e-anno-only)
|
||||
(annotation
|
||||
(ty-fn (effectful true)
|
||||
(ty-lookup (name "Str") (builtin))
|
||||
(ty-lookup (name "Str") (builtin)))))
|
||||
(d-let
|
||||
(p-assign (ident "b!"))
|
||||
(e-anno-only)
|
||||
(annotation
|
||||
(ty-fn (effectful true)
|
||||
(ty-lookup (name "Str") (builtin))
|
||||
|
|
@ -85,7 +92,9 @@ NO CHANGE
|
|||
~~~clojure
|
||||
(inferred-types
|
||||
(defs
|
||||
(patt (type "Error")))
|
||||
(patt (type "Str => Str"))
|
||||
(patt (type "Str => Str")))
|
||||
(expressions
|
||||
(expr (type "Error"))))
|
||||
(expr (type "Str => Str"))
|
||||
(expr (type "Str => Str"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -93,6 +93,13 @@ NO CHANGE
|
|||
(d-let
|
||||
(p-assign (ident "a!"))
|
||||
(e-anno-only)
|
||||
(annotation
|
||||
(ty-fn (effectful true)
|
||||
(ty-lookup (name "Str") (builtin))
|
||||
(ty-lookup (name "Str") (builtin)))))
|
||||
(d-let
|
||||
(p-assign (ident "b!"))
|
||||
(e-anno-only)
|
||||
(annotation
|
||||
(ty-fn (effectful true)
|
||||
(ty-lookup (name "Str") (builtin))
|
||||
|
|
@ -102,7 +109,9 @@ NO CHANGE
|
|||
~~~clojure
|
||||
(inferred-types
|
||||
(defs
|
||||
(patt (type "Error")))
|
||||
(patt (type "Str => Str"))
|
||||
(patt (type "Str => Str")))
|
||||
(expressions
|
||||
(expr (type "Error"))))
|
||||
(expr (type "Str => Str"))
|
||||
(expr (type "Str => Str"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -197,11 +197,11 @@ PARSE ERROR - everything.md:56:37:56:38
|
|||
PARSE ERROR - everything.md:56:38:56:39
|
||||
PARSE ERROR - everything.md:56:39:56:40
|
||||
PARSE ERROR - everything.md:56:40:56:42
|
||||
MALFORMED WHERE CLAUSE - everything.md:56:12:56:17
|
||||
WHERE CLAUSE NOT ALLOWED IN TYPE DECLARATION - everything.md:12:1:13:7
|
||||
UNDECLARED TYPE - everything.md:43:5:43:6
|
||||
MODULE NOT FOUND - everything.md:2:1:5:2
|
||||
MODULE NOT FOUND - everything.md:6:1:9:2
|
||||
MALFORMED WHERE CLAUSE - everything.md:56:12:56:17
|
||||
UNUSED VARIABLE - everything.md:88:5:88:6
|
||||
UNUSED VARIABLE - everything.md:93:4:93:5
|
||||
UNUSED VARIABLE - everything.md:98:5:98:6
|
||||
|
|
@ -1174,6 +1174,17 @@ g : e -> e where module(e).A, module(e).B
|
|||
^^
|
||||
|
||||
|
||||
**MALFORMED WHERE CLAUSE**
|
||||
This where clause could not be parsed correctly.
|
||||
|
||||
**everything.md:56:12:56:17:**
|
||||
```roc
|
||||
g : e -> e where module(e).A, module(e).B
|
||||
```
|
||||
^^^^^
|
||||
|
||||
Check the syntax of your where clause.
|
||||
|
||||
**WHERE CLAUSE NOT ALLOWED IN TYPE DECLARATION**
|
||||
You cannot define a `where` clause inside a type declaration.
|
||||
|
||||
|
|
@ -1222,17 +1233,6 @@ import I2 exposing [
|
|||
```
|
||||
|
||||
|
||||
**MALFORMED WHERE CLAUSE**
|
||||
This where clause could not be parsed correctly.
|
||||
|
||||
**everything.md:56:12:56:17:**
|
||||
```roc
|
||||
g : e -> e where module(e).A, module(e).B
|
||||
```
|
||||
^^^^^
|
||||
|
||||
Check the syntax of your where clause.
|
||||
|
||||
**UNUSED VARIABLE**
|
||||
Variable `b` is not used anywhere in your code.
|
||||
|
||||
|
|
@ -1904,7 +1904,7 @@ h = |x, y| {
|
|||
~~~clojure
|
||||
(inferred-types
|
||||
(defs
|
||||
(patt (type "Error"))
|
||||
(patt (type "e -> e"))
|
||||
(patt (type "[Z1((c, d)), Z2(c, f), Z3({ a: c, b: i }), Z4(List(c))]j, [Z1((c, d)), Z2(c, f), Z3({ a: c, b: i }), Z4(List(c))]j -> c")))
|
||||
(type_decls
|
||||
(alias (type "A(a)")
|
||||
|
|
@ -1921,6 +1921,6 @@ h = |x, y| {
|
|||
(alias (type "F")
|
||||
(ty-header (name "F"))))
|
||||
(expressions
|
||||
(expr (type "Error"))
|
||||
(expr (type "e -> e"))
|
||||
(expr (type "[Z1((c, d)), Z2(c, f), Z3({ a: c, b: i }), Z4(List(c))]j, [Z1((c, d)), Z2(c, f), Z3({ a: c, b: i }), Z4(List(c))]j -> c"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -82,6 +82,13 @@ b! : Str => Str
|
|||
(d-let
|
||||
(p-assign (ident "a!"))
|
||||
(e-anno-only)
|
||||
(annotation
|
||||
(ty-fn (effectful true)
|
||||
(ty-lookup (name "Str") (builtin))
|
||||
(ty-lookup (name "Str") (builtin)))))
|
||||
(d-let
|
||||
(p-assign (ident "b!"))
|
||||
(e-anno-only)
|
||||
(annotation
|
||||
(ty-fn (effectful true)
|
||||
(ty-lookup (name "Str") (builtin))
|
||||
|
|
@ -91,7 +98,9 @@ b! : Str => Str
|
|||
~~~clojure
|
||||
(inferred-types
|
||||
(defs
|
||||
(patt (type "Error")))
|
||||
(patt (type "Str => Str"))
|
||||
(patt (type "Str => Str")))
|
||||
(expressions
|
||||
(expr (type "Error"))))
|
||||
(expr (type "Str => Str"))
|
||||
(expr (type "Str => Str"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -104,6 +104,13 @@ b! : Str => Str
|
|||
(d-let
|
||||
(p-assign (ident "a!"))
|
||||
(e-anno-only)
|
||||
(annotation
|
||||
(ty-fn (effectful true)
|
||||
(ty-lookup (name "Str") (builtin))
|
||||
(ty-lookup (name "Str") (builtin)))))
|
||||
(d-let
|
||||
(p-assign (ident "b!"))
|
||||
(e-anno-only)
|
||||
(annotation
|
||||
(ty-fn (effectful true)
|
||||
(ty-lookup (name "Str") (builtin))
|
||||
|
|
@ -113,7 +120,9 @@ b! : Str => Str
|
|||
~~~clojure
|
||||
(inferred-types
|
||||
(defs
|
||||
(patt (type "Error")))
|
||||
(patt (type "Str => Str"))
|
||||
(patt (type "Str => Str")))
|
||||
(expressions
|
||||
(expr (type "Error"))))
|
||||
(expr (type "Str => Str"))
|
||||
(expr (type "Str => Str"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -528,7 +528,7 @@ NO CHANGE
|
|||
~~~clojure
|
||||
(inferred-types
|
||||
(defs
|
||||
(patt (type "Error"))
|
||||
(patt (type "e -> e"))
|
||||
(patt (type "[Z1((c, d)), Z2(c, f), Z3({ a: c, b: i }), Z4(List(c))]j, [Z1((c, d)), Z2(c, f), Z3({ a: c, b: i }), Z4(List(c))]j -> c")))
|
||||
(type_decls
|
||||
(alias (type "A(a)")
|
||||
|
|
@ -554,6 +554,6 @@ NO CHANGE
|
|||
(alias (type "F")
|
||||
(ty-header (name "F"))))
|
||||
(expressions
|
||||
(expr (type "Error"))
|
||||
(expr (type "e -> e"))
|
||||
(expr (type "[Z1((c, d)), Z2(c, f), Z3({ a: c, b: i }), Z4(List(c))]j, [Z1((c, d)), Z2(c, f), Z3({ a: c, b: i }), Z4(List(c))]j -> c"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -70,6 +70,13 @@ NO CHANGE
|
|||
(d-let
|
||||
(p-assign (ident "a!"))
|
||||
(e-anno-only)
|
||||
(annotation
|
||||
(ty-fn (effectful true)
|
||||
(ty-lookup (name "Str") (builtin))
|
||||
(ty-lookup (name "Str") (builtin)))))
|
||||
(d-let
|
||||
(p-assign (ident "b!"))
|
||||
(e-anno-only)
|
||||
(annotation
|
||||
(ty-fn (effectful true)
|
||||
(ty-lookup (name "Str") (builtin))
|
||||
|
|
@ -79,7 +86,9 @@ NO CHANGE
|
|||
~~~clojure
|
||||
(inferred-types
|
||||
(defs
|
||||
(patt (type "Error")))
|
||||
(patt (type "Str => Str"))
|
||||
(patt (type "Str => Str")))
|
||||
(expressions
|
||||
(expr (type "Error"))))
|
||||
(expr (type "Str => Str"))
|
||||
(expr (type "Str => Str"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -77,6 +77,13 @@ NO CHANGE
|
|||
(d-let
|
||||
(p-assign (ident "a!"))
|
||||
(e-anno-only)
|
||||
(annotation
|
||||
(ty-fn (effectful true)
|
||||
(ty-lookup (name "Str") (builtin))
|
||||
(ty-lookup (name "Str") (builtin)))))
|
||||
(d-let
|
||||
(p-assign (ident "b!"))
|
||||
(e-anno-only)
|
||||
(annotation
|
||||
(ty-fn (effectful true)
|
||||
(ty-lookup (name "Str") (builtin))
|
||||
|
|
@ -86,7 +93,9 @@ NO CHANGE
|
|||
~~~clojure
|
||||
(inferred-types
|
||||
(defs
|
||||
(patt (type "Error")))
|
||||
(patt (type "Str => Str"))
|
||||
(patt (type "Str => Str")))
|
||||
(expressions
|
||||
(expr (type "Error"))))
|
||||
(expr (type "Str => Str"))
|
||||
(expr (type "Str => Str"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -641,7 +641,7 @@ h = |
|
|||
~~~clojure
|
||||
(inferred-types
|
||||
(defs
|
||||
(patt (type "Error"))
|
||||
(patt (type "e -> e"))
|
||||
(patt (type "[Z1((c, d)), Z2(c, f), Z3({ a: c, b: i }), Z4(List(c))]j, [Z1((c, d)), Z2(c, f), Z3({ a: c, b: i }), Z4(List(c))]j -> c")))
|
||||
(type_decls
|
||||
(alias (type "A(a)")
|
||||
|
|
@ -667,6 +667,6 @@ h = |
|
|||
(alias (type "F")
|
||||
(ty-header (name "F"))))
|
||||
(expressions
|
||||
(expr (type "Error"))
|
||||
(expr (type "e -> e"))
|
||||
(expr (type "[Z1((c, d)), Z2(c, f), Z3({ a: c, b: i }), Z4(List(c))]j, [Z1((c, d)), Z2(c, f), Z3({ a: c, b: i }), Z4(List(c))]j -> c"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -76,6 +76,13 @@ b! : Str => Str
|
|||
(d-let
|
||||
(p-assign (ident "a!"))
|
||||
(e-anno-only)
|
||||
(annotation
|
||||
(ty-fn (effectful true)
|
||||
(ty-lookup (name "Str") (builtin))
|
||||
(ty-lookup (name "Str") (builtin)))))
|
||||
(d-let
|
||||
(p-assign (ident "b!"))
|
||||
(e-anno-only)
|
||||
(annotation
|
||||
(ty-fn (effectful true)
|
||||
(ty-lookup (name "Str") (builtin))
|
||||
|
|
@ -85,7 +92,9 @@ b! : Str => Str
|
|||
~~~clojure
|
||||
(inferred-types
|
||||
(defs
|
||||
(patt (type "Error")))
|
||||
(patt (type "Str => Str"))
|
||||
(patt (type "Str => Str")))
|
||||
(expressions
|
||||
(expr (type "Error"))))
|
||||
(expr (type "Str => Str"))
|
||||
(expr (type "Str => Str"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -88,6 +88,13 @@ b! : Str => Str
|
|||
(d-let
|
||||
(p-assign (ident "a!"))
|
||||
(e-anno-only)
|
||||
(annotation
|
||||
(ty-fn (effectful true)
|
||||
(ty-lookup (name "Str") (builtin))
|
||||
(ty-lookup (name "Str") (builtin)))))
|
||||
(d-let
|
||||
(p-assign (ident "b!"))
|
||||
(e-anno-only)
|
||||
(annotation
|
||||
(ty-fn (effectful true)
|
||||
(ty-lookup (name "Str") (builtin))
|
||||
|
|
@ -97,7 +104,9 @@ b! : Str => Str
|
|||
~~~clojure
|
||||
(inferred-types
|
||||
(defs
|
||||
(patt (type "Error")))
|
||||
(patt (type "Str => Str"))
|
||||
(patt (type "Str => Str")))
|
||||
(expressions
|
||||
(expr (type "Error"))))
|
||||
(expr (type "Str => Str"))
|
||||
(expr (type "Str => Str"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -287,11 +287,18 @@ modu :
|
|||
~~~
|
||||
# CANONICALIZE
|
||||
~~~clojure
|
||||
(can-ir (empty true))
|
||||
(can-ir
|
||||
(d-let
|
||||
(p-assign (ident "modu"))
|
||||
(e-anno-only)
|
||||
(annotation
|
||||
(ty-malformed))))
|
||||
~~~
|
||||
# TYPES
|
||||
~~~clojure
|
||||
(inferred-types
|
||||
(defs)
|
||||
(expressions))
|
||||
(defs
|
||||
(patt (type "Error")))
|
||||
(expressions
|
||||
(expr (type "Error"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -83,11 +83,18 @@ b : S
|
|||
~~~
|
||||
# CANONICALIZE
|
||||
~~~clojure
|
||||
(can-ir (empty true))
|
||||
(can-ir
|
||||
(d-let
|
||||
(p-assign (ident "b"))
|
||||
(e-anno-only)
|
||||
(annotation
|
||||
(ty-malformed))))
|
||||
~~~
|
||||
# TYPES
|
||||
~~~clojure
|
||||
(inferred-types
|
||||
(defs)
|
||||
(expressions))
|
||||
(defs
|
||||
(patt (type "Error")))
|
||||
(expressions
|
||||
(expr (type "Error"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -2007,14 +2007,14 @@ expect {
|
|||
~~~clojure
|
||||
(inferred-types
|
||||
(defs
|
||||
(patt (type "Error"))
|
||||
(patt (type "()"))
|
||||
(patt (type "Bool -> num where [num.from_int_digits : List(U8) -> Try(num, [OutOfRange])]"))
|
||||
(patt (type "Error"))
|
||||
(patt (type "Bool -> Error"))
|
||||
(patt (type "[Blue]_others, [Tb]_others2 -> Error"))
|
||||
(patt (type "Error"))
|
||||
(patt (type "_arg -> [Stdo!(Error)]_others"))
|
||||
(patt (type "Error"))
|
||||
(patt (type "{ }"))
|
||||
(patt (type "{}"))
|
||||
(patt (type "Error")))
|
||||
(type_decls
|
||||
|
|
@ -2044,14 +2044,14 @@ expect {
|
|||
(ty-args
|
||||
(ty-rigid-var (name "a"))))))
|
||||
(expressions
|
||||
(expr (type "Error"))
|
||||
(expr (type "()"))
|
||||
(expr (type "Bool -> num where [num.from_int_digits : List(U8) -> Try(num, [OutOfRange])]"))
|
||||
(expr (type "Error"))
|
||||
(expr (type "Bool -> Error"))
|
||||
(expr (type "[Blue]_others, [Tb]_others2 -> Error"))
|
||||
(expr (type "Error"))
|
||||
(expr (type "_arg -> [Stdo!(Error)]_others"))
|
||||
(expr (type "Error"))
|
||||
(expr (type "{ }"))
|
||||
(expr (type "{}"))
|
||||
(expr (type "Error"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -1986,14 +1986,14 @@ expect {
|
|||
~~~clojure
|
||||
(inferred-types
|
||||
(defs
|
||||
(patt (type "Error"))
|
||||
(patt (type "()"))
|
||||
(patt (type "Bool -> num where [num.from_int_digits : List(U8) -> Try(num, [OutOfRange])]"))
|
||||
(patt (type "Error"))
|
||||
(patt (type "[Rum]_others -> Error"))
|
||||
(patt (type "[Blue]_others -> Error"))
|
||||
(patt (type "Error"))
|
||||
(patt (type "_arg -> [Stdo!(Error)]_others"))
|
||||
(patt (type "Error"))
|
||||
(patt (type "{ }"))
|
||||
(patt (type "{}"))
|
||||
(patt (type "Error")))
|
||||
(type_decls
|
||||
|
|
@ -2023,14 +2023,14 @@ expect {
|
|||
(ty-args
|
||||
(ty-rigid-var (name "a"))))))
|
||||
(expressions
|
||||
(expr (type "Error"))
|
||||
(expr (type "()"))
|
||||
(expr (type "Bool -> num where [num.from_int_digits : List(U8) -> Try(num, [OutOfRange])]"))
|
||||
(expr (type "Error"))
|
||||
(expr (type "[Rum]_others -> Error"))
|
||||
(expr (type "[Blue]_others -> Error"))
|
||||
(expr (type "Error"))
|
||||
(expr (type "_arg -> [Stdo!(Error)]_others"))
|
||||
(expr (type "Error"))
|
||||
(expr (type "{ }"))
|
||||
(expr (type "{}"))
|
||||
(expr (type "Error"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -245,7 +245,7 @@ ain! = |_| getUser(900)
|
|||
(inferred-types
|
||||
(defs
|
||||
(patt (type "Error"))
|
||||
(patt (type "Error"))
|
||||
(patt (type "UserId -> Str"))
|
||||
(patt (type "_arg -> Error"))
|
||||
(patt (type "_arg -> Error")))
|
||||
(type_decls
|
||||
|
|
@ -253,7 +253,7 @@ ain! = |_| getUser(900)
|
|||
(ty-header (name "UserId"))))
|
||||
(expressions
|
||||
(expr (type "Error"))
|
||||
(expr (type "Error"))
|
||||
(expr (type "UserId -> Str"))
|
||||
(expr (type "_arg -> Error"))
|
||||
(expr (type "_arg -> Error"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -269,6 +269,7 @@ DOES NOT EXIST - fuzz_crash_023.md:193:4:193:13
|
|||
UNUSED VARIABLE - fuzz_crash_023.md:164:2:164:18
|
||||
UNUSED VARIABLE - fuzz_crash_023.md:165:2:165:14
|
||||
UNUSED VARIABLE - fuzz_crash_023.md:178:2:178:8
|
||||
UNUSED VARIABLE - fuzz_crash_023.md:178:47:178:71
|
||||
UNUSED VARIABLE - fuzz_crash_023.md:180:2:180:17
|
||||
UNUSED VARIABLE - fuzz_crash_023.md:188:2:188:15
|
||||
UNUSED VARIABLE - fuzz_crash_023.md:189:2:189:23
|
||||
|
|
@ -846,6 +847,18 @@ The unused variable is declared here:
|
|||
^^^^^^
|
||||
|
||||
|
||||
**UNUSED VARIABLE**
|
||||
Variable `qux` is not used anywhere in your code.
|
||||
|
||||
If you don't need this variable, prefix it with an underscore like `_qux` to suppress this warning.
|
||||
The unused variable is declared here:
|
||||
**fuzz_crash_023.md:178:47:178:71:**
|
||||
```roc
|
||||
record = { foo: 123, bar: "Hello", ;az: tag, qux: Ok(world), punned }
|
||||
```
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
**UNUSED VARIABLE**
|
||||
Variable `multiline_tuple` is not used anywhere in your code.
|
||||
|
||||
|
|
@ -2211,6 +2224,11 @@ expect {
|
|||
(p-applied-tag)))
|
||||
(value
|
||||
(e-num (value "1000"))))))))))
|
||||
(d-let
|
||||
(p-assign (ident "qux"))
|
||||
(e-anno-only)
|
||||
(annotation
|
||||
(ty-malformed)))
|
||||
(d-let
|
||||
(p-assign (ident "main!"))
|
||||
(e-closure
|
||||
|
|
@ -2310,6 +2328,9 @@ expect {
|
|||
(p-assign (ident "tag"))))
|
||||
(s-expr
|
||||
(e-runtime-error (tag "expr_not_canonicalized")))
|
||||
(s-let
|
||||
(p-assign (ident "qux"))
|
||||
(e-anno-only))
|
||||
(s-let
|
||||
(p-assign (ident "tuple"))
|
||||
(e-tuple
|
||||
|
|
@ -2554,6 +2575,7 @@ expect {
|
|||
(patt (type "Bool -> num where [num.from_int_digits : List(U8) -> Try(num, [OutOfRange])]"))
|
||||
(patt (type "Num(Int(Unsigned64)) -> Num(Int(Unsigned64))"))
|
||||
(patt (type "[Red][Blue, Green]_others, _arg -> Error"))
|
||||
(patt (type "Error"))
|
||||
(patt (type "List(Error) -> Error"))
|
||||
(patt (type "{}"))
|
||||
(patt (type "Error")))
|
||||
|
|
@ -2600,6 +2622,7 @@ expect {
|
|||
(expr (type "Bool -> num where [num.from_int_digits : List(U8) -> Try(num, [OutOfRange])]"))
|
||||
(expr (type "Num(Int(Unsigned64)) -> Num(Int(Unsigned64))"))
|
||||
(expr (type "[Red][Blue, Green]_others, _arg -> Error"))
|
||||
(expr (type "Error"))
|
||||
(expr (type "List(Error) -> Error"))
|
||||
(expr (type "{}"))
|
||||
(expr (type "Error"))))
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -2249,7 +2249,7 @@ expect {
|
|||
~~~clojure
|
||||
(inferred-types
|
||||
(defs
|
||||
(patt (type "Error"))
|
||||
(patt (type "(Error, Error)"))
|
||||
(patt (type "Bool -> num where [num.from_int_digits : List(U8) -> Try(num, [OutOfRange])]"))
|
||||
(patt (type "Num(Int(Unsigned64)) -> Num(Int(Unsigned64))"))
|
||||
(patt (type "[Red, Blue]_others, _arg -> Error"))
|
||||
|
|
@ -2286,7 +2286,7 @@ expect {
|
|||
(ty-args
|
||||
(ty-rigid-var (name "a"))))))
|
||||
(expressions
|
||||
(expr (type "Error"))
|
||||
(expr (type "(Error, Error)"))
|
||||
(expr (type "Bool -> num where [num.from_int_digits : List(U8) -> Try(num, [OutOfRange])]"))
|
||||
(expr (type "Num(Int(Unsigned64)) -> Num(Int(Unsigned64))"))
|
||||
(expr (type "[Red, Blue]_others, _arg -> Error"))
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -455,11 +455,18 @@ pkg :
|
|||
~~~
|
||||
# CANONICALIZE
|
||||
~~~clojure
|
||||
(can-ir (empty true))
|
||||
(can-ir
|
||||
(d-let
|
||||
(p-assign (ident "pkg"))
|
||||
(e-anno-only)
|
||||
(annotation
|
||||
(ty-malformed))))
|
||||
~~~
|
||||
# TYPES
|
||||
~~~clojure
|
||||
(inferred-types
|
||||
(defs)
|
||||
(expressions))
|
||||
(defs
|
||||
(patt (type "Error")))
|
||||
(expressions
|
||||
(expr (type "Error"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -89,11 +89,18 @@ o :
|
|||
~~~
|
||||
# CANONICALIZE
|
||||
~~~clojure
|
||||
(can-ir (empty true))
|
||||
(can-ir
|
||||
(d-let
|
||||
(p-assign (ident "o"))
|
||||
(e-anno-only)
|
||||
(annotation
|
||||
(ty-malformed))))
|
||||
~~~
|
||||
# TYPES
|
||||
~~~clojure
|
||||
(inferred-types
|
||||
(defs)
|
||||
(expressions))
|
||||
(defs
|
||||
(patt (type "Error")))
|
||||
(expressions
|
||||
(expr (type "Error"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ import u.R}g:r->R.a.E
|
|||
~~~
|
||||
# EXPECTED
|
||||
PARSE ERROR - fuzz_crash_042.md:1:11:1:12
|
||||
MODULE NOT FOUND - fuzz_crash_042.md:1:1:1:11
|
||||
MODULE NOT IMPORTED - fuzz_crash_042.md:1:17:1:22
|
||||
MODULE NOT FOUND - fuzz_crash_042.md:1:1:1:11
|
||||
# PROBLEMS
|
||||
**PARSE ERROR**
|
||||
A parsing error occurred: `statement_unexpected_token`
|
||||
|
|
@ -23,17 +23,6 @@ import u.R}g:r->R.a.E
|
|||
^
|
||||
|
||||
|
||||
**MODULE NOT FOUND**
|
||||
The module `u.R` was not found in this Roc project.
|
||||
|
||||
You're attempting to use this module here:
|
||||
**fuzz_crash_042.md:1:1:1:11:**
|
||||
```roc
|
||||
import u.R}g:r->R.a.E
|
||||
```
|
||||
^^^^^^^^^^
|
||||
|
||||
|
||||
**MODULE NOT IMPORTED**
|
||||
There is no module with the name `R.a` imported into this Roc file.
|
||||
|
||||
|
|
@ -45,6 +34,17 @@ import u.R}g:r->R.a.E
|
|||
^^^^^
|
||||
|
||||
|
||||
**MODULE NOT FOUND**
|
||||
The module `u.R` was not found in this Roc project.
|
||||
|
||||
You're attempting to use this module here:
|
||||
**fuzz_crash_042.md:1:1:1:11:**
|
||||
```roc
|
||||
import u.R}g:r->R.a.E
|
||||
```
|
||||
^^^^^^^^^^
|
||||
|
||||
|
||||
# TOKENS
|
||||
~~~zig
|
||||
KwImport,LowerIdent,NoSpaceDotUpperIdent,CloseCurly,LowerIdent,OpColon,LowerIdent,OpArrow,UpperIdent,NoSpaceDotLowerIdent,NoSpaceDotUpperIdent,
|
||||
|
|
@ -70,12 +70,21 @@ g : r -> R.a.E
|
|||
# CANONICALIZE
|
||||
~~~clojure
|
||||
(can-ir
|
||||
(d-let
|
||||
(p-assign (ident "g"))
|
||||
(e-anno-only)
|
||||
(annotation
|
||||
(ty-fn (effectful false)
|
||||
(ty-rigid-var (name "r"))
|
||||
(ty-malformed))))
|
||||
(s-import (module "u.R")
|
||||
(exposes)))
|
||||
~~~
|
||||
# TYPES
|
||||
~~~clojure
|
||||
(inferred-types
|
||||
(defs)
|
||||
(expressions))
|
||||
(defs
|
||||
(patt (type "r -> Error")))
|
||||
(expressions
|
||||
(expr (type "r -> Error"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -102,11 +102,18 @@ o :
|
|||
~~~
|
||||
# CANONICALIZE
|
||||
~~~clojure
|
||||
(can-ir (empty true))
|
||||
(can-ir
|
||||
(d-let
|
||||
(p-assign (ident "o"))
|
||||
(e-anno-only)
|
||||
(annotation
|
||||
(ty-malformed))))
|
||||
~~~
|
||||
# TYPES
|
||||
~~~clojure
|
||||
(inferred-types
|
||||
(defs)
|
||||
(expressions))
|
||||
(defs
|
||||
(patt (type "Error")))
|
||||
(expressions
|
||||
(expr (type "Error"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -157,21 +157,28 @@ tag_tuple : Value((a, b, c))
|
|||
(ty-malformed))
|
||||
(ty-apply (name "Result") (builtin)
|
||||
(ty-record)
|
||||
(ty-underscore))))))
|
||||
(ty-underscore)))))
|
||||
(d-let
|
||||
(p-assign (ident "tag_tuple"))
|
||||
(e-anno-only)
|
||||
(annotation
|
||||
(ty-malformed))))
|
||||
~~~
|
||||
# TYPES
|
||||
~~~clojure
|
||||
(inferred-types
|
||||
(defs
|
||||
(patt (type "Num(Int(Unsigned64))"))
|
||||
(patt (type "Error"))
|
||||
(patt (type "Error"))
|
||||
(patt (type "Error"))
|
||||
(patt (type "Error"))
|
||||
(patt (type "(a, b, c)"))
|
||||
(patt (type "Num(Int(Unsigned8)), Num(Int(Unsigned16)) -> Num(Int(Unsigned32))"))
|
||||
(patt (type "List(Error) -> Try({ }, _d)"))
|
||||
(patt (type "Error")))
|
||||
(expressions
|
||||
(expr (type "Num(Int(Unsigned64))"))
|
||||
(expr (type "Error"))
|
||||
(expr (type "Error"))
|
||||
(expr (type "Error"))
|
||||
(expr (type "Error"))
|
||||
(expr (type "(a, b, c)"))
|
||||
(expr (type "Num(Int(Unsigned8)), Num(Int(Unsigned16)) -> Num(Int(Unsigned32))"))
|
||||
(expr (type "List(Error) -> Try({ }, _d)"))
|
||||
(expr (type "Error"))))
|
||||
~~~
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -45,11 +45,18 @@ b : r
|
|||
~~~
|
||||
# CANONICALIZE
|
||||
~~~clojure
|
||||
(can-ir (empty true))
|
||||
(can-ir
|
||||
(d-let
|
||||
(p-assign (ident "b"))
|
||||
(e-anno-only)
|
||||
(annotation
|
||||
(ty-rigid-var (name "r")))))
|
||||
~~~
|
||||
# TYPES
|
||||
~~~clojure
|
||||
(inferred-types
|
||||
(defs)
|
||||
(expressions))
|
||||
(defs
|
||||
(patt (type "r")))
|
||||
(expressions
|
||||
(expr (type "r"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -85,15 +85,15 @@ external = Foo.defaultBaz
|
|||
~~~clojure
|
||||
(can-ir
|
||||
(d-let
|
||||
(p-assign (ident "external"))
|
||||
(e-lookup-local
|
||||
(p-assign (ident "Foo.defaultBaz")))
|
||||
(p-assign (ident "nominal_associated_alias_within_block.Foo.defaultBaz"))
|
||||
(e-nominal (nominal "nominal_associated_alias_within_block.Foo.Bar")
|
||||
(e-tag (name "X")))
|
||||
(annotation
|
||||
(ty-lookup (name "Foo.Baz") (local))))
|
||||
(d-let
|
||||
(p-assign (ident "Foo.defaultBaz"))
|
||||
(e-nominal (nominal "Foo.Bar")
|
||||
(e-tag (name "X")))
|
||||
(p-assign (ident "external"))
|
||||
(e-lookup-local
|
||||
(p-assign (ident "nominal_associated_alias_within_block.Foo.defaultBaz")))
|
||||
(annotation
|
||||
(ty-lookup (name "Foo.Baz") (local))))
|
||||
(s-nominal-decl
|
||||
|
|
@ -101,29 +101,29 @@ external = Foo.defaultBaz
|
|||
(ty-tag-union
|
||||
(ty-tag-name (name "Whatever"))))
|
||||
(s-nominal-decl
|
||||
(ty-header (name "Foo.Bar"))
|
||||
(ty-header (name "nominal_associated_alias_within_block.Foo.Bar"))
|
||||
(ty-tag-union
|
||||
(ty-tag-name (name "X"))
|
||||
(ty-tag-name (name "Y"))
|
||||
(ty-tag-name (name "Z"))))
|
||||
(s-alias-decl
|
||||
(ty-header (name "Foo.Baz"))
|
||||
(ty-header (name "nominal_associated_alias_within_block.Foo.Baz"))
|
||||
(ty-lookup (name "Foo.Bar") (local))))
|
||||
~~~
|
||||
# TYPES
|
||||
~~~clojure
|
||||
(inferred-types
|
||||
(defs
|
||||
(patt (type "Foo.Baz"))
|
||||
(patt (type "Foo.Baz")))
|
||||
(patt (type "nominal_associated_alias_within_block.Foo.Baz"))
|
||||
(patt (type "nominal_associated_alias_within_block.Foo.Baz")))
|
||||
(type_decls
|
||||
(nominal (type "Foo")
|
||||
(ty-header (name "Foo")))
|
||||
(nominal (type "Foo.Bar")
|
||||
(ty-header (name "Foo.Bar")))
|
||||
(alias (type "Foo.Baz")
|
||||
(ty-header (name "Foo.Baz"))))
|
||||
(nominal (type "nominal_associated_alias_within_block.Foo.Bar")
|
||||
(ty-header (name "nominal_associated_alias_within_block.Foo.Bar")))
|
||||
(alias (type "nominal_associated_alias_within_block.Foo.Baz")
|
||||
(ty-header (name "nominal_associated_alias_within_block.Foo.Baz"))))
|
||||
(expressions
|
||||
(expr (type "Foo.Baz"))
|
||||
(expr (type "Foo.Baz"))))
|
||||
(expr (type "nominal_associated_alias_within_block.Foo.Baz"))
|
||||
(expr (type "nominal_associated_alias_within_block.Foo.Baz"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -110,6 +110,9 @@ deepType = C
|
|||
# CANONICALIZE
|
||||
~~~clojure
|
||||
(can-ir
|
||||
(d-let
|
||||
(p-assign (ident "Foo.Level1.Level2.Level3.value"))
|
||||
(e-num (value "42")))
|
||||
(d-let
|
||||
(p-assign (ident "deepValue"))
|
||||
(e-lookup-local
|
||||
|
|
@ -121,9 +124,6 @@ deepType = C
|
|||
(e-tag (name "C"))
|
||||
(annotation
|
||||
(ty-lookup (name "Foo.Level1.Level2.Level3") (local))))
|
||||
(d-let
|
||||
(p-assign (ident "Foo.Level1.Level2.Level3.value"))
|
||||
(e-num (value "42")))
|
||||
(s-nominal-decl
|
||||
(ty-header (name "Foo"))
|
||||
(ty-tag-union
|
||||
|
|
@ -146,8 +146,8 @@ deepType = C
|
|||
(inferred-types
|
||||
(defs
|
||||
(patt (type "Num(Int(Unsigned64))"))
|
||||
(patt (type "Foo.Level1.Level2.Level3"))
|
||||
(patt (type "Num(Int(Unsigned64))")))
|
||||
(patt (type "Num(Int(Unsigned64))"))
|
||||
(patt (type "Foo.Level1.Level2.Level3")))
|
||||
(type_decls
|
||||
(nominal (type "Foo")
|
||||
(ty-header (name "Foo")))
|
||||
|
|
@ -159,6 +159,6 @@ deepType = C
|
|||
(ty-header (name "Foo.Level1.Level2.Level3"))))
|
||||
(expressions
|
||||
(expr (type "Num(Int(Unsigned64))"))
|
||||
(expr (type "Foo.Level1.Level2.Level3"))
|
||||
(expr (type "Num(Int(Unsigned64))"))))
|
||||
(expr (type "Num(Int(Unsigned64))"))
|
||||
(expr (type "Foo.Level1.Level2.Level3"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -58,15 +58,15 @@ useBar = Foo.bar
|
|||
# CANONICALIZE
|
||||
~~~clojure
|
||||
(can-ir
|
||||
(d-let
|
||||
(p-assign (ident "Foo.bar"))
|
||||
(e-num (value "42")))
|
||||
(d-let
|
||||
(p-assign (ident "useBar"))
|
||||
(e-lookup-local
|
||||
(p-assign (ident "Foo.bar")))
|
||||
(annotation
|
||||
(ty-lookup (name "U64") (builtin))))
|
||||
(d-let
|
||||
(p-assign (ident "Foo.bar"))
|
||||
(e-num (value "42")))
|
||||
(s-nominal-decl
|
||||
(ty-header (name "Foo"))
|
||||
(ty-tag-union
|
||||
|
|
|
|||
|
|
@ -89,15 +89,6 @@ result = Foo.transform(Foo.defaultBar)
|
|||
# CANONICALIZE
|
||||
~~~clojure
|
||||
(can-ir
|
||||
(d-let
|
||||
(p-assign (ident "result"))
|
||||
(e-call
|
||||
(e-lookup-local
|
||||
(p-assign (ident "Foo.transform")))
|
||||
(e-lookup-local
|
||||
(p-assign (ident "Foo.defaultBar"))))
|
||||
(annotation
|
||||
(ty-lookup (name "Foo.Bar") (local))))
|
||||
(d-let
|
||||
(p-assign (ident "Foo.defaultBar"))
|
||||
(e-nominal (nominal "Foo.Bar")
|
||||
|
|
@ -113,6 +104,15 @@ result = Foo.transform(Foo.defaultBar)
|
|||
(ty-fn (effectful false)
|
||||
(ty-lookup (name "Foo.Bar") (local))
|
||||
(ty-lookup (name "Foo.Bar") (local)))))
|
||||
(d-let
|
||||
(p-assign (ident "result"))
|
||||
(e-call
|
||||
(e-lookup-local
|
||||
(p-assign (ident "Foo.transform")))
|
||||
(e-lookup-local
|
||||
(p-assign (ident "Foo.defaultBar"))))
|
||||
(annotation
|
||||
(ty-lookup (name "Foo.Bar") (local))))
|
||||
(s-nominal-decl
|
||||
(ty-header (name "Foo"))
|
||||
(ty-tag-union
|
||||
|
|
@ -129,8 +129,8 @@ result = Foo.transform(Foo.defaultBar)
|
|||
(inferred-types
|
||||
(defs
|
||||
(patt (type "Foo.Bar"))
|
||||
(patt (type "Foo.Bar"))
|
||||
(patt (type "Foo.Bar -> Foo.Bar")))
|
||||
(patt (type "Foo.Bar -> Foo.Bar"))
|
||||
(patt (type "Foo.Bar")))
|
||||
(type_decls
|
||||
(nominal (type "Foo")
|
||||
(ty-header (name "Foo")))
|
||||
|
|
@ -138,6 +138,6 @@ result = Foo.transform(Foo.defaultBar)
|
|||
(ty-header (name "Foo.Bar"))))
|
||||
(expressions
|
||||
(expr (type "Foo.Bar"))
|
||||
(expr (type "Foo.Bar"))
|
||||
(expr (type "Foo.Bar -> Foo.Bar"))))
|
||||
(expr (type "Foo.Bar -> Foo.Bar"))
|
||||
(expr (type "Foo.Bar"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -84,6 +84,9 @@ myNum = Foo.Bar.baz
|
|||
# CANONICALIZE
|
||||
~~~clojure
|
||||
(can-ir
|
||||
(d-let
|
||||
(p-assign (ident "Foo.Bar.baz"))
|
||||
(e-num (value "5")))
|
||||
(d-let
|
||||
(p-assign (ident "myType"))
|
||||
(e-tag (name "Something"))
|
||||
|
|
@ -95,9 +98,6 @@ myNum = Foo.Bar.baz
|
|||
(p-assign (ident "Foo.Bar.baz")))
|
||||
(annotation
|
||||
(ty-lookup (name "U64") (builtin))))
|
||||
(d-let
|
||||
(p-assign (ident "Foo.Bar.baz"))
|
||||
(e-num (value "5")))
|
||||
(s-nominal-decl
|
||||
(ty-header (name "Foo"))
|
||||
(ty-tag-union
|
||||
|
|
@ -111,8 +111,8 @@ myNum = Foo.Bar.baz
|
|||
~~~clojure
|
||||
(inferred-types
|
||||
(defs
|
||||
(patt (type "Foo.Bar"))
|
||||
(patt (type "Num(Int(Unsigned64))"))
|
||||
(patt (type "Foo.Bar"))
|
||||
(patt (type "Num(Int(Unsigned64))")))
|
||||
(type_decls
|
||||
(nominal (type "Foo")
|
||||
|
|
@ -120,7 +120,7 @@ myNum = Foo.Bar.baz
|
|||
(nominal (type "Foo.Bar")
|
||||
(ty-header (name "Foo.Bar"))))
|
||||
(expressions
|
||||
(expr (type "Foo.Bar"))
|
||||
(expr (type "Num(Int(Unsigned64))"))
|
||||
(expr (type "Foo.Bar"))
|
||||
(expr (type "Num(Int(Unsigned64))"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -101,12 +101,6 @@ external = Foo.defaultBar
|
|||
# CANONICALIZE
|
||||
~~~clojure
|
||||
(can-ir
|
||||
(d-let
|
||||
(p-assign (ident "external"))
|
||||
(e-lookup-local
|
||||
(p-assign (ident "Foo.defaultBar")))
|
||||
(annotation
|
||||
(ty-lookup (name "Foo.Bar") (local))))
|
||||
(d-let
|
||||
(p-assign (ident "Foo.defaultBar"))
|
||||
(e-tag (name "X"))
|
||||
|
|
@ -130,6 +124,12 @@ external = Foo.defaultBar
|
|||
(p-assign (ident "Foo.transform")))
|
||||
(e-lookup-local
|
||||
(p-assign (ident "Foo.defaultBar")))))
|
||||
(d-let
|
||||
(p-assign (ident "external"))
|
||||
(e-lookup-local
|
||||
(p-assign (ident "Foo.defaultBar")))
|
||||
(annotation
|
||||
(ty-lookup (name "Foo.Bar") (local))))
|
||||
(s-nominal-decl
|
||||
(ty-header (name "Foo"))
|
||||
(ty-tag-union
|
||||
|
|
@ -145,9 +145,9 @@ external = Foo.defaultBar
|
|||
~~~clojure
|
||||
(inferred-types
|
||||
(defs
|
||||
(patt (type "Foo.Bar"))
|
||||
(patt (type "Foo.Bar"))
|
||||
(patt (type "Foo.Bar -> Foo.Bar"))
|
||||
(patt (type "Foo.Bar"))
|
||||
(patt (type "Foo.Bar")))
|
||||
(type_decls
|
||||
(nominal (type "Foo")
|
||||
|
|
@ -155,8 +155,8 @@ external = Foo.defaultBar
|
|||
(nominal (type "Foo.Bar")
|
||||
(ty-header (name "Foo.Bar"))))
|
||||
(expressions
|
||||
(expr (type "Foo.Bar"))
|
||||
(expr (type "Foo.Bar"))
|
||||
(expr (type "Foo.Bar -> Foo.Bar"))
|
||||
(expr (type "Foo.Bar"))
|
||||
(expr (type "Foo.Bar"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ useMyBar = Foo.Bar.X
|
|||
(can-ir
|
||||
(d-let
|
||||
(p-assign (ident "useMyBar"))
|
||||
(e-nominal (nominal "Foo.Bar")
|
||||
(e-nominal (nominal "nominal_associated_type_alias.Foo.Bar")
|
||||
(e-tag (name "X")))
|
||||
(annotation
|
||||
(ty-lookup (name "MyBar") (local))))
|
||||
|
|
@ -85,7 +85,7 @@ useMyBar = Foo.Bar.X
|
|||
(ty-tag-union
|
||||
(ty-tag-name (name "Whatever"))))
|
||||
(s-nominal-decl
|
||||
(ty-header (name "Foo.Bar"))
|
||||
(ty-header (name "nominal_associated_type_alias.Foo.Bar"))
|
||||
(ty-tag-union
|
||||
(ty-tag-name (name "X"))
|
||||
(ty-tag-name (name "Y"))
|
||||
|
|
@ -102,8 +102,8 @@ useMyBar = Foo.Bar.X
|
|||
(type_decls
|
||||
(nominal (type "Foo")
|
||||
(ty-header (name "Foo")))
|
||||
(nominal (type "Foo.Bar")
|
||||
(ty-header (name "Foo.Bar")))
|
||||
(nominal (type "nominal_associated_type_alias.Foo.Bar")
|
||||
(ty-header (name "nominal_associated_type_alias.Foo.Bar")))
|
||||
(alias (type "MyBar")
|
||||
(ty-header (name "MyBar"))))
|
||||
(expressions
|
||||
|
|
|
|||
|
|
@ -73,10 +73,13 @@ result = myBar
|
|||
# CANONICALIZE
|
||||
~~~clojure
|
||||
(can-ir
|
||||
(d-let
|
||||
(p-assign (ident "nominal_associated_value_alias.Foo.bar"))
|
||||
(e-num (value "42")))
|
||||
(d-let
|
||||
(p-assign (ident "myBar"))
|
||||
(e-lookup-local
|
||||
(p-assign (ident "Foo.bar")))
|
||||
(p-assign (ident "nominal_associated_value_alias.Foo.bar")))
|
||||
(annotation
|
||||
(ty-lookup (name "U64") (builtin))))
|
||||
(d-let
|
||||
|
|
@ -85,9 +88,6 @@ result = myBar
|
|||
(p-assign (ident "myBar")))
|
||||
(annotation
|
||||
(ty-lookup (name "U64") (builtin))))
|
||||
(d-let
|
||||
(p-assign (ident "Foo.bar"))
|
||||
(e-num (value "42")))
|
||||
(s-nominal-decl
|
||||
(ty-header (name "Foo"))
|
||||
(ty-tag-union
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ useBar = Something
|
|||
(ty-tag-union
|
||||
(ty-tag-name (name "Whatever"))))
|
||||
(s-nominal-decl
|
||||
(ty-header (name "Foo.Bar"))
|
||||
(ty-header (name "nominal_associated_vs_module.Foo.Bar"))
|
||||
(ty-tag-union
|
||||
(ty-tag-name (name "Something")))))
|
||||
~~~
|
||||
|
|
@ -101,12 +101,12 @@ useBar = Something
|
|||
~~~clojure
|
||||
(inferred-types
|
||||
(defs
|
||||
(patt (type "Foo.Bar")))
|
||||
(patt (type "nominal_associated_vs_module.Foo.Bar")))
|
||||
(type_decls
|
||||
(nominal (type "Foo")
|
||||
(ty-header (name "Foo")))
|
||||
(nominal (type "Foo.Bar")
|
||||
(ty-header (name "Foo.Bar"))))
|
||||
(nominal (type "nominal_associated_vs_module.Foo.Bar")
|
||||
(ty-header (name "nominal_associated_vs_module.Foo.Bar"))))
|
||||
(expressions
|
||||
(expr (type "Foo.Bar"))))
|
||||
(expr (type "nominal_associated_vs_module.Foo.Bar"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ Foo := [A, B, C].{
|
|||
~~~clojure
|
||||
(can-ir
|
||||
(d-let
|
||||
(p-assign (ident "Foo.x"))
|
||||
(p-assign (ident "nominal_associated_with_final_expression.Foo.x"))
|
||||
(e-num (value "5")))
|
||||
(s-nominal-decl
|
||||
(ty-header (name "Foo"))
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ x = Foo.Bar.Baz.X
|
|||
(can-ir
|
||||
(d-let
|
||||
(p-assign (ident "x"))
|
||||
(e-nominal (nominal "Foo.Bar.Baz")
|
||||
(e-nominal (nominal "nominal_deeply_nested_tag.Foo.Bar.Baz")
|
||||
(e-tag (name "X")))
|
||||
(annotation
|
||||
(ty-lookup (name "Foo.Bar.Baz") (local))))
|
||||
|
|
@ -87,11 +87,11 @@ x = Foo.Bar.Baz.X
|
|||
(ty-tag-union
|
||||
(ty-tag-name (name "Whatever"))))
|
||||
(s-nominal-decl
|
||||
(ty-header (name "Foo.Bar"))
|
||||
(ty-header (name "nominal_deeply_nested_tag.Foo.Bar"))
|
||||
(ty-tag-union
|
||||
(ty-tag-name (name "Something"))))
|
||||
(s-nominal-decl
|
||||
(ty-header (name "Foo.Bar.Baz"))
|
||||
(ty-header (name "nominal_deeply_nested_tag.Foo.Bar.Baz"))
|
||||
(ty-tag-union
|
||||
(ty-tag-name (name "X"))
|
||||
(ty-tag-name (name "Y"))
|
||||
|
|
@ -101,14 +101,14 @@ x = Foo.Bar.Baz.X
|
|||
~~~clojure
|
||||
(inferred-types
|
||||
(defs
|
||||
(patt (type "Foo.Bar.Baz")))
|
||||
(patt (type "nominal_deeply_nested_tag.Foo.Bar.Baz")))
|
||||
(type_decls
|
||||
(nominal (type "Foo")
|
||||
(ty-header (name "Foo")))
|
||||
(nominal (type "Foo.Bar")
|
||||
(ty-header (name "Foo.Bar")))
|
||||
(nominal (type "Foo.Bar.Baz")
|
||||
(ty-header (name "Foo.Bar.Baz"))))
|
||||
(nominal (type "nominal_deeply_nested_tag.Foo.Bar")
|
||||
(ty-header (name "nominal_deeply_nested_tag.Foo.Bar")))
|
||||
(nominal (type "nominal_deeply_nested_tag.Foo.Bar.Baz")
|
||||
(ty-header (name "nominal_deeply_nested_tag.Foo.Bar.Baz"))))
|
||||
(expressions
|
||||
(expr (type "Foo.Bar.Baz"))))
|
||||
(expr (type "nominal_deeply_nested_tag.Foo.Bar.Baz"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ value = Foo.Bar.Baz.Qux.Y
|
|||
(can-ir
|
||||
(d-let
|
||||
(p-assign (ident "value"))
|
||||
(e-nominal (nominal "Foo.Bar.Baz.Qux")
|
||||
(e-nominal (nominal "nominal_four_level_nested_tag.Foo.Bar.Baz.Qux")
|
||||
(e-tag (name "Y")))
|
||||
(annotation
|
||||
(ty-lookup (name "Foo.Bar.Baz.Qux") (local))))
|
||||
|
|
@ -100,15 +100,15 @@ value = Foo.Bar.Baz.Qux.Y
|
|||
(ty-tag-union
|
||||
(ty-tag-name (name "A"))))
|
||||
(s-nominal-decl
|
||||
(ty-header (name "Foo.Bar"))
|
||||
(ty-header (name "nominal_four_level_nested_tag.Foo.Bar"))
|
||||
(ty-tag-union
|
||||
(ty-tag-name (name "B"))))
|
||||
(s-nominal-decl
|
||||
(ty-header (name "Foo.Bar.Baz"))
|
||||
(ty-header (name "nominal_four_level_nested_tag.Foo.Bar.Baz"))
|
||||
(ty-tag-union
|
||||
(ty-tag-name (name "C"))))
|
||||
(s-nominal-decl
|
||||
(ty-header (name "Foo.Bar.Baz.Qux"))
|
||||
(ty-header (name "nominal_four_level_nested_tag.Foo.Bar.Baz.Qux"))
|
||||
(ty-tag-union
|
||||
(ty-tag-name (name "X"))
|
||||
(ty-tag-name (name "Y"))
|
||||
|
|
@ -118,16 +118,16 @@ value = Foo.Bar.Baz.Qux.Y
|
|||
~~~clojure
|
||||
(inferred-types
|
||||
(defs
|
||||
(patt (type "Foo.Bar.Baz.Qux")))
|
||||
(patt (type "nominal_four_level_nested_tag.Foo.Bar.Baz.Qux")))
|
||||
(type_decls
|
||||
(nominal (type "Foo")
|
||||
(ty-header (name "Foo")))
|
||||
(nominal (type "Foo.Bar")
|
||||
(ty-header (name "Foo.Bar")))
|
||||
(nominal (type "Foo.Bar.Baz")
|
||||
(ty-header (name "Foo.Bar.Baz")))
|
||||
(nominal (type "Foo.Bar.Baz.Qux")
|
||||
(ty-header (name "Foo.Bar.Baz.Qux"))))
|
||||
(nominal (type "nominal_four_level_nested_tag.Foo.Bar")
|
||||
(ty-header (name "nominal_four_level_nested_tag.Foo.Bar")))
|
||||
(nominal (type "nominal_four_level_nested_tag.Foo.Bar.Baz")
|
||||
(ty-header (name "nominal_four_level_nested_tag.Foo.Bar.Baz")))
|
||||
(nominal (type "nominal_four_level_nested_tag.Foo.Bar.Baz.Qux")
|
||||
(ty-header (name "nominal_four_level_nested_tag.Foo.Bar.Baz.Qux"))))
|
||||
(expressions
|
||||
(expr (type "Foo.Bar.Baz.Qux"))))
|
||||
(expr (type "nominal_four_level_nested_tag.Foo.Bar.Baz.Qux"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ x = Foo.Bar.X
|
|||
(can-ir
|
||||
(d-let
|
||||
(p-assign (ident "x"))
|
||||
(e-nominal (nominal "Foo.Bar")
|
||||
(e-nominal (nominal "nominal_nested_type_ref.Foo.Bar")
|
||||
(e-tag (name "X")))
|
||||
(annotation
|
||||
(ty-lookup (name "Foo.Bar") (local))))
|
||||
|
|
@ -74,7 +74,7 @@ x = Foo.Bar.X
|
|||
(ty-tag-union
|
||||
(ty-tag-name (name "Whatever"))))
|
||||
(s-nominal-decl
|
||||
(ty-header (name "Foo.Bar"))
|
||||
(ty-header (name "nominal_nested_type_ref.Foo.Bar"))
|
||||
(ty-tag-union
|
||||
(ty-tag-name (name "X"))
|
||||
(ty-tag-name (name "Y"))
|
||||
|
|
@ -84,12 +84,12 @@ x = Foo.Bar.X
|
|||
~~~clojure
|
||||
(inferred-types
|
||||
(defs
|
||||
(patt (type "Foo.Bar")))
|
||||
(patt (type "nominal_nested_type_ref.Foo.Bar")))
|
||||
(type_decls
|
||||
(nominal (type "Foo")
|
||||
(ty-header (name "Foo")))
|
||||
(nominal (type "Foo.Bar")
|
||||
(ty-header (name "Foo.Bar"))))
|
||||
(nominal (type "nominal_nested_type_ref.Foo.Bar")
|
||||
(ty-header (name "nominal_nested_type_ref.Foo.Bar"))))
|
||||
(expressions
|
||||
(expr (type "Foo.Bar"))))
|
||||
(expr (type "nominal_nested_type_ref.Foo.Bar"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -60,14 +60,14 @@ x = Foo.Bar.X
|
|||
(can-ir
|
||||
(d-let
|
||||
(p-assign (ident "x"))
|
||||
(e-nominal (nominal "Foo.Bar")
|
||||
(e-nominal (nominal "nominal_simple_nested_tag.Foo.Bar")
|
||||
(e-tag (name "X"))))
|
||||
(s-nominal-decl
|
||||
(ty-header (name "Foo"))
|
||||
(ty-tag-union
|
||||
(ty-tag-name (name "Whatever"))))
|
||||
(s-nominal-decl
|
||||
(ty-header (name "Foo.Bar"))
|
||||
(ty-header (name "nominal_simple_nested_tag.Foo.Bar"))
|
||||
(ty-tag-union
|
||||
(ty-tag-name (name "X"))
|
||||
(ty-tag-name (name "Y"))
|
||||
|
|
@ -77,12 +77,12 @@ x = Foo.Bar.X
|
|||
~~~clojure
|
||||
(inferred-types
|
||||
(defs
|
||||
(patt (type "Foo.Bar")))
|
||||
(patt (type "nominal_simple_nested_tag.Foo.Bar")))
|
||||
(type_decls
|
||||
(nominal (type "Foo")
|
||||
(ty-header (name "Foo")))
|
||||
(nominal (type "Foo.Bar")
|
||||
(ty-header (name "Foo.Bar"))))
|
||||
(nominal (type "nominal_simple_nested_tag.Foo.Bar")
|
||||
(ty-header (name "nominal_simple_nested_tag.Foo.Bar"))))
|
||||
(expressions
|
||||
(expr (type "Foo.Bar"))))
|
||||
(expr (type "nominal_simple_nested_tag.Foo.Bar"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -63,11 +63,21 @@ multiplyInts : I64, I64 -> I64
|
|||
~~~
|
||||
# CANONICALIZE
|
||||
~~~clojure
|
||||
(can-ir (empty true))
|
||||
(can-ir
|
||||
(d-let
|
||||
(p-assign (ident "multiplyInts"))
|
||||
(e-anno-only)
|
||||
(annotation
|
||||
(ty-fn (effectful false)
|
||||
(ty-lookup (name "I64") (builtin))
|
||||
(ty-lookup (name "I64") (builtin))
|
||||
(ty-lookup (name "I64") (builtin))))))
|
||||
~~~
|
||||
# TYPES
|
||||
~~~clojure
|
||||
(inferred-types
|
||||
(defs)
|
||||
(expressions))
|
||||
(defs
|
||||
(patt (type "Num(Int(Signed64)), Num(Int(Signed64)) -> Num(Int(Signed64))")))
|
||||
(expressions
|
||||
(expr (type "Num(Int(Signed64)), Num(Int(Signed64)) -> Num(Int(Signed64))"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -61,11 +61,20 @@ processString : Str -> Str
|
|||
~~~
|
||||
# CANONICALIZE
|
||||
~~~clojure
|
||||
(can-ir (empty true))
|
||||
(can-ir
|
||||
(d-let
|
||||
(p-assign (ident "processString"))
|
||||
(e-anno-only)
|
||||
(annotation
|
||||
(ty-fn (effectful false)
|
||||
(ty-lookup (name "Str") (builtin))
|
||||
(ty-lookup (name "Str") (builtin))))))
|
||||
~~~
|
||||
# TYPES
|
||||
~~~clojure
|
||||
(inferred-types
|
||||
(defs)
|
||||
(expressions))
|
||||
(defs
|
||||
(patt (type "Str -> Str")))
|
||||
(expressions
|
||||
(expr (type "Str -> Str"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -317,6 +317,80 @@ main = {
|
|||
# CANONICALIZE
|
||||
~~~clojure
|
||||
(can-ir
|
||||
(d-let
|
||||
(p-assign (ident "Adv.to_str"))
|
||||
(e-closure
|
||||
(captures
|
||||
(capture (ident "s")))
|
||||
(e-lambda
|
||||
(args
|
||||
(p-nominal
|
||||
(p-applied-tag)))
|
||||
(e-lookup-local
|
||||
(p-assign (ident "s")))))
|
||||
(annotation
|
||||
(ty-fn (effectful false)
|
||||
(ty-lookup (name "Adv") (local))
|
||||
(ty-lookup (name "Str") (builtin)))))
|
||||
(d-let
|
||||
(p-assign (ident "Adv.to_u64"))
|
||||
(e-closure
|
||||
(captures
|
||||
(capture (ident "u")))
|
||||
(e-lambda
|
||||
(args
|
||||
(p-nominal
|
||||
(p-applied-tag)))
|
||||
(e-lookup-local
|
||||
(p-assign (ident "u")))))
|
||||
(annotation
|
||||
(ty-fn (effectful false)
|
||||
(ty-lookup (name "Adv") (local))
|
||||
(ty-lookup (name "U64") (builtin)))))
|
||||
(d-let
|
||||
(p-assign (ident "Adv.update_str"))
|
||||
(e-closure
|
||||
(captures
|
||||
(capture (ident "u64")))
|
||||
(e-lambda
|
||||
(args
|
||||
(p-nominal
|
||||
(p-applied-tag))
|
||||
(p-assign (ident "next_str")))
|
||||
(e-nominal (nominal "Adv")
|
||||
(e-tag (name "Val")
|
||||
(args
|
||||
(e-lookup-local
|
||||
(p-assign (ident "u64")))
|
||||
(e-lookup-local
|
||||
(p-assign (ident "next_str"))))))))
|
||||
(annotation
|
||||
(ty-fn (effectful false)
|
||||
(ty-lookup (name "Adv") (local))
|
||||
(ty-lookup (name "Str") (builtin))
|
||||
(ty-lookup (name "Adv") (local)))))
|
||||
(d-let
|
||||
(p-assign (ident "Adv.update_u64"))
|
||||
(e-closure
|
||||
(captures
|
||||
(capture (ident "str")))
|
||||
(e-lambda
|
||||
(args
|
||||
(p-nominal
|
||||
(p-applied-tag))
|
||||
(p-assign (ident "next_u64")))
|
||||
(e-nominal (nominal "Adv")
|
||||
(e-tag (name "Val")
|
||||
(args
|
||||
(e-lookup-local
|
||||
(p-assign (ident "next_u64")))
|
||||
(e-lookup-local
|
||||
(p-assign (ident "str"))))))))
|
||||
(annotation
|
||||
(ty-fn (effectful false)
|
||||
(ty-lookup (name "Adv") (local))
|
||||
(ty-lookup (name "U64") (builtin))
|
||||
(ty-lookup (name "Adv") (local)))))
|
||||
(d-let
|
||||
(p-assign (ident "mismatch"))
|
||||
(e-block
|
||||
|
|
@ -411,80 +485,6 @@ main = {
|
|||
(ty-tuple
|
||||
(ty-lookup (name "Str") (builtin))
|
||||
(ty-lookup (name "U64") (builtin)))))
|
||||
(d-let
|
||||
(p-assign (ident "Adv.to_str"))
|
||||
(e-closure
|
||||
(captures
|
||||
(capture (ident "s")))
|
||||
(e-lambda
|
||||
(args
|
||||
(p-nominal
|
||||
(p-applied-tag)))
|
||||
(e-lookup-local
|
||||
(p-assign (ident "s")))))
|
||||
(annotation
|
||||
(ty-fn (effectful false)
|
||||
(ty-lookup (name "Adv") (local))
|
||||
(ty-lookup (name "Str") (builtin)))))
|
||||
(d-let
|
||||
(p-assign (ident "Adv.to_u64"))
|
||||
(e-closure
|
||||
(captures
|
||||
(capture (ident "u")))
|
||||
(e-lambda
|
||||
(args
|
||||
(p-nominal
|
||||
(p-applied-tag)))
|
||||
(e-lookup-local
|
||||
(p-assign (ident "u")))))
|
||||
(annotation
|
||||
(ty-fn (effectful false)
|
||||
(ty-lookup (name "Adv") (local))
|
||||
(ty-lookup (name "U64") (builtin)))))
|
||||
(d-let
|
||||
(p-assign (ident "Adv.update_str"))
|
||||
(e-closure
|
||||
(captures
|
||||
(capture (ident "u64")))
|
||||
(e-lambda
|
||||
(args
|
||||
(p-nominal
|
||||
(p-applied-tag))
|
||||
(p-assign (ident "next_str")))
|
||||
(e-nominal (nominal "Adv")
|
||||
(e-tag (name "Val")
|
||||
(args
|
||||
(e-lookup-local
|
||||
(p-assign (ident "u64")))
|
||||
(e-lookup-local
|
||||
(p-assign (ident "next_str"))))))))
|
||||
(annotation
|
||||
(ty-fn (effectful false)
|
||||
(ty-lookup (name "Adv") (local))
|
||||
(ty-lookup (name "Str") (builtin))
|
||||
(ty-lookup (name "Adv") (local)))))
|
||||
(d-let
|
||||
(p-assign (ident "Adv.update_u64"))
|
||||
(e-closure
|
||||
(captures
|
||||
(capture (ident "str")))
|
||||
(e-lambda
|
||||
(args
|
||||
(p-nominal
|
||||
(p-applied-tag))
|
||||
(p-assign (ident "next_u64")))
|
||||
(e-nominal (nominal "Adv")
|
||||
(e-tag (name "Val")
|
||||
(args
|
||||
(e-lookup-local
|
||||
(p-assign (ident "next_u64")))
|
||||
(e-lookup-local
|
||||
(p-assign (ident "str"))))))))
|
||||
(annotation
|
||||
(ty-fn (effectful false)
|
||||
(ty-lookup (name "Adv") (local))
|
||||
(ty-lookup (name "U64") (builtin))
|
||||
(ty-lookup (name "Adv") (local)))))
|
||||
(s-nominal-decl
|
||||
(ty-header (name "Adv"))
|
||||
(ty-tag-union
|
||||
|
|
@ -496,24 +496,24 @@ main = {
|
|||
~~~clojure
|
||||
(inferred-types
|
||||
(defs
|
||||
(patt (type "_a"))
|
||||
(patt (type "_a"))
|
||||
(patt (type "_a"))
|
||||
(patt (type "(Str, Num(Int(Unsigned64)))"))
|
||||
(patt (type "Adv -> Str"))
|
||||
(patt (type "Adv -> Num(Int(Unsigned64))"))
|
||||
(patt (type "Adv, Str -> Adv"))
|
||||
(patt (type "Adv, Num(Int(Unsigned64)) -> Adv")))
|
||||
(patt (type "Adv, Num(Int(Unsigned64)) -> Adv"))
|
||||
(patt (type "_a"))
|
||||
(patt (type "_a"))
|
||||
(patt (type "_a"))
|
||||
(patt (type "(Str, Num(Int(Unsigned64)))")))
|
||||
(type_decls
|
||||
(nominal (type "Adv")
|
||||
(ty-header (name "Adv"))))
|
||||
(expressions
|
||||
(expr (type "_a"))
|
||||
(expr (type "_a"))
|
||||
(expr (type "_a"))
|
||||
(expr (type "(Str, Num(Int(Unsigned64)))"))
|
||||
(expr (type "Adv -> Str"))
|
||||
(expr (type "Adv -> Num(Int(Unsigned64))"))
|
||||
(expr (type "Adv, Str -> Adv"))
|
||||
(expr (type "Adv, Num(Int(Unsigned64)) -> Adv"))))
|
||||
(expr (type "Adv, Num(Int(Unsigned64)) -> Adv"))
|
||||
(expr (type "_a"))
|
||||
(expr (type "_a"))
|
||||
(expr (type "_a"))
|
||||
(expr (type "(Str, Num(Int(Unsigned64)))"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -167,6 +167,35 @@ main = (helper1(val), helper2(val))
|
|||
# CANONICALIZE
|
||||
~~~clojure
|
||||
(can-ir
|
||||
(d-let
|
||||
(p-assign (ident "Basic.to_str"))
|
||||
(e-closure
|
||||
(captures
|
||||
(capture (ident "s")))
|
||||
(e-lambda
|
||||
(args
|
||||
(p-nominal
|
||||
(p-applied-tag)))
|
||||
(e-lookup-local
|
||||
(p-assign (ident "s")))))
|
||||
(annotation
|
||||
(ty-fn (effectful false)
|
||||
(ty-lookup (name "Basic") (local))
|
||||
(ty-lookup (name "Str") (builtin)))))
|
||||
(d-let
|
||||
(p-assign (ident "Basic.to_str2"))
|
||||
(e-lambda
|
||||
(args
|
||||
(p-assign (ident "test")))
|
||||
(e-dot-access (field "to_str")
|
||||
(receiver
|
||||
(e-lookup-local
|
||||
(p-assign (ident "test"))))
|
||||
(args)))
|
||||
(annotation
|
||||
(ty-fn (effectful false)
|
||||
(ty-lookup (name "Basic") (local))
|
||||
(ty-lookup (name "Str") (builtin)))))
|
||||
(d-let
|
||||
(p-assign (ident "helper1"))
|
||||
(e-lambda
|
||||
|
|
@ -232,35 +261,6 @@ main = (helper1(val), helper2(val))
|
|||
(ty-tuple
|
||||
(ty-lookup (name "Str") (builtin))
|
||||
(ty-lookup (name "Str") (builtin)))))
|
||||
(d-let
|
||||
(p-assign (ident "Basic.to_str"))
|
||||
(e-closure
|
||||
(captures
|
||||
(capture (ident "s")))
|
||||
(e-lambda
|
||||
(args
|
||||
(p-nominal
|
||||
(p-applied-tag)))
|
||||
(e-lookup-local
|
||||
(p-assign (ident "s")))))
|
||||
(annotation
|
||||
(ty-fn (effectful false)
|
||||
(ty-lookup (name "Basic") (local))
|
||||
(ty-lookup (name "Str") (builtin)))))
|
||||
(d-let
|
||||
(p-assign (ident "Basic.to_str2"))
|
||||
(e-lambda
|
||||
(args
|
||||
(p-assign (ident "test")))
|
||||
(e-dot-access (field "to_str")
|
||||
(receiver
|
||||
(e-lookup-local
|
||||
(p-assign (ident "test"))))
|
||||
(args)))
|
||||
(annotation
|
||||
(ty-fn (effectful false)
|
||||
(ty-lookup (name "Basic") (local))
|
||||
(ty-lookup (name "Str") (builtin)))))
|
||||
(s-nominal-decl
|
||||
(ty-header (name "Basic"))
|
||||
(ty-tag-union
|
||||
|
|
@ -271,20 +271,20 @@ main = (helper1(val), helper2(val))
|
|||
~~~clojure
|
||||
(inferred-types
|
||||
(defs
|
||||
(patt (type "Basic -> Str"))
|
||||
(patt (type "Basic -> Str"))
|
||||
(patt (type "a -> b where [a.to_str : a -> b]"))
|
||||
(patt (type "a -> b where [a.to_str2 : a -> b]"))
|
||||
(patt (type "Basic"))
|
||||
(patt (type "(Str, Str)"))
|
||||
(patt (type "Basic -> Str"))
|
||||
(patt (type "Basic -> Str")))
|
||||
(patt (type "(Str, Str)")))
|
||||
(type_decls
|
||||
(nominal (type "Basic")
|
||||
(ty-header (name "Basic"))))
|
||||
(expressions
|
||||
(expr (type "Basic -> Str"))
|
||||
(expr (type "Basic -> Str"))
|
||||
(expr (type "a -> b where [a.to_str : a -> b]"))
|
||||
(expr (type "a -> b where [a.to_str2 : a -> b]"))
|
||||
(expr (type "Basic"))
|
||||
(expr (type "(Str, Str)"))
|
||||
(expr (type "Basic -> Str"))
|
||||
(expr (type "Basic -> Str"))))
|
||||
(expr (type "(Str, Str)"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -124,6 +124,27 @@ main = (helper1(val), helper2(val))
|
|||
# CANONICALIZE
|
||||
~~~clojure
|
||||
(can-ir
|
||||
(d-let
|
||||
(p-assign (ident "BasicNoAnno.to_str"))
|
||||
(e-closure
|
||||
(captures
|
||||
(capture (ident "s")))
|
||||
(e-lambda
|
||||
(args
|
||||
(p-nominal
|
||||
(p-applied-tag)))
|
||||
(e-lookup-local
|
||||
(p-assign (ident "s"))))))
|
||||
(d-let
|
||||
(p-assign (ident "BasicNoAnno.to_str2"))
|
||||
(e-lambda
|
||||
(args
|
||||
(p-assign (ident "test")))
|
||||
(e-dot-access (field "to_str")
|
||||
(receiver
|
||||
(e-lookup-local
|
||||
(p-assign (ident "test"))))
|
||||
(args))))
|
||||
(d-let
|
||||
(p-assign (ident "helper1"))
|
||||
(e-lambda
|
||||
|
|
@ -169,27 +190,6 @@ main = (helper1(val), helper2(val))
|
|||
(ty-tuple
|
||||
(ty-lookup (name "Str") (builtin))
|
||||
(ty-lookup (name "Str") (builtin)))))
|
||||
(d-let
|
||||
(p-assign (ident "BasicNoAnno.to_str"))
|
||||
(e-closure
|
||||
(captures
|
||||
(capture (ident "s")))
|
||||
(e-lambda
|
||||
(args
|
||||
(p-nominal
|
||||
(p-applied-tag)))
|
||||
(e-lookup-local
|
||||
(p-assign (ident "s"))))))
|
||||
(d-let
|
||||
(p-assign (ident "BasicNoAnno.to_str2"))
|
||||
(e-lambda
|
||||
(args
|
||||
(p-assign (ident "test")))
|
||||
(e-dot-access (field "to_str")
|
||||
(receiver
|
||||
(e-lookup-local
|
||||
(p-assign (ident "test"))))
|
||||
(args))))
|
||||
(s-nominal-decl
|
||||
(ty-header (name "BasicNoAnno"))
|
||||
(ty-tag-union
|
||||
|
|
@ -200,20 +200,20 @@ main = (helper1(val), helper2(val))
|
|||
~~~clojure
|
||||
(inferred-types
|
||||
(defs
|
||||
(patt (type "BasicNoAnno -> Str"))
|
||||
(patt (type "a -> b where [a.to_str : a -> b]"))
|
||||
(patt (type "a -> b where [a.to_str : a -> b]"))
|
||||
(patt (type "a -> b where [a.to_str2 : a -> b]"))
|
||||
(patt (type "BasicNoAnno"))
|
||||
(patt (type "(Str, Str)"))
|
||||
(patt (type "BasicNoAnno -> Str"))
|
||||
(patt (type "a -> b where [a.to_str : a -> b]")))
|
||||
(patt (type "(Str, Str)")))
|
||||
(type_decls
|
||||
(nominal (type "BasicNoAnno")
|
||||
(ty-header (name "BasicNoAnno"))))
|
||||
(expressions
|
||||
(expr (type "BasicNoAnno -> Str"))
|
||||
(expr (type "a -> b where [a.to_str : a -> b]"))
|
||||
(expr (type "a -> b where [a.to_str : a -> b]"))
|
||||
(expr (type "a -> b where [a.to_str2 : a -> b]"))
|
||||
(expr (type "BasicNoAnno"))
|
||||
(expr (type "(Str, Str)"))
|
||||
(expr (type "BasicNoAnno -> Str"))
|
||||
(expr (type "a -> b where [a.to_str : a -> b]"))))
|
||||
(expr (type "(Str, Str)"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -231,6 +231,47 @@ NO CHANGE
|
|||
# CANONICALIZE
|
||||
~~~clojure
|
||||
(can-ir
|
||||
(d-let
|
||||
(p-assign (ident "Container.get_value"))
|
||||
(e-closure
|
||||
(captures
|
||||
(capture (ident "s")))
|
||||
(e-lambda
|
||||
(args
|
||||
(p-nominal
|
||||
(p-applied-tag)))
|
||||
(e-lookup-local
|
||||
(p-assign (ident "s")))))
|
||||
(annotation
|
||||
(ty-fn (effectful false)
|
||||
(ty-lookup (name "Container") (local))
|
||||
(ty-lookup (name "Str") (builtin)))))
|
||||
(d-let
|
||||
(p-assign (ident "Container.transform"))
|
||||
(e-closure
|
||||
(captures
|
||||
(capture (ident "s")))
|
||||
(e-lambda
|
||||
(args
|
||||
(p-nominal
|
||||
(p-applied-tag))
|
||||
(p-assign (ident "fn")))
|
||||
(e-nominal (nominal "Container")
|
||||
(e-tag (name "Box")
|
||||
(args
|
||||
(e-call
|
||||
(e-lookup-local
|
||||
(p-assign (ident "fn")))
|
||||
(e-lookup-local
|
||||
(p-assign (ident "s")))))))))
|
||||
(annotation
|
||||
(ty-fn (effectful false)
|
||||
(ty-lookup (name "Container") (local))
|
||||
(ty-parens
|
||||
(ty-fn (effectful false)
|
||||
(ty-lookup (name "Str") (builtin))
|
||||
(ty-lookup (name "Str") (builtin))))
|
||||
(ty-lookup (name "Container") (local)))))
|
||||
(d-let
|
||||
(p-assign (ident "extract"))
|
||||
(e-lambda
|
||||
|
|
@ -351,47 +392,6 @@ NO CHANGE
|
|||
(ty-lookup (name "Str") (builtin))
|
||||
(ty-lookup (name "Str") (builtin))
|
||||
(ty-lookup (name "Str") (builtin)))))
|
||||
(d-let
|
||||
(p-assign (ident "Container.get_value"))
|
||||
(e-closure
|
||||
(captures
|
||||
(capture (ident "s")))
|
||||
(e-lambda
|
||||
(args
|
||||
(p-nominal
|
||||
(p-applied-tag)))
|
||||
(e-lookup-local
|
||||
(p-assign (ident "s")))))
|
||||
(annotation
|
||||
(ty-fn (effectful false)
|
||||
(ty-lookup (name "Container") (local))
|
||||
(ty-lookup (name "Str") (builtin)))))
|
||||
(d-let
|
||||
(p-assign (ident "Container.transform"))
|
||||
(e-closure
|
||||
(captures
|
||||
(capture (ident "s")))
|
||||
(e-lambda
|
||||
(args
|
||||
(p-nominal
|
||||
(p-applied-tag))
|
||||
(p-assign (ident "fn")))
|
||||
(e-nominal (nominal "Container")
|
||||
(e-tag (name "Box")
|
||||
(args
|
||||
(e-call
|
||||
(e-lookup-local
|
||||
(p-assign (ident "fn")))
|
||||
(e-lookup-local
|
||||
(p-assign (ident "s")))))))))
|
||||
(annotation
|
||||
(ty-fn (effectful false)
|
||||
(ty-lookup (name "Container") (local))
|
||||
(ty-parens
|
||||
(ty-fn (effectful false)
|
||||
(ty-lookup (name "Str") (builtin))
|
||||
(ty-lookup (name "Str") (builtin))))
|
||||
(ty-lookup (name "Container") (local)))))
|
||||
(s-nominal-decl
|
||||
(ty-header (name "Container"))
|
||||
(ty-tag-union
|
||||
|
|
@ -402,6 +402,8 @@ NO CHANGE
|
|||
~~~clojure
|
||||
(inferred-types
|
||||
(defs
|
||||
(patt (type "Container -> Str"))
|
||||
(patt (type "Container, Str -> Str -> Container"))
|
||||
(patt (type "a -> Str where [a.get_value : a -> Str]"))
|
||||
(patt (type "a, Str -> Str -> a where [a.transform : a, Str -> Str -> aa.transform : a, Str -> Str -> a]"))
|
||||
(patt (type "Container"))
|
||||
|
|
@ -409,13 +411,13 @@ NO CHANGE
|
|||
(patt (type "Str"))
|
||||
(patt (type "Str"))
|
||||
(patt (type "Container"))
|
||||
(patt (type "(Str, Str, Str)"))
|
||||
(patt (type "Container -> Str"))
|
||||
(patt (type "Container, Str -> Str -> Container")))
|
||||
(patt (type "(Str, Str, Str)")))
|
||||
(type_decls
|
||||
(nominal (type "Container")
|
||||
(ty-header (name "Container"))))
|
||||
(expressions
|
||||
(expr (type "Container -> Str"))
|
||||
(expr (type "Container, Str -> Str -> Container"))
|
||||
(expr (type "a -> Str where [a.get_value : a -> Str]"))
|
||||
(expr (type "a, Str -> Str -> a where [a.transform : a, Str -> Str -> aa.transform : a, Str -> Str -> a]"))
|
||||
(expr (type "Container"))
|
||||
|
|
@ -423,7 +425,5 @@ NO CHANGE
|
|||
(expr (type "Str"))
|
||||
(expr (type "Str"))
|
||||
(expr (type "Container"))
|
||||
(expr (type "(Str, Str, Str)"))
|
||||
(expr (type "Container -> Str"))
|
||||
(expr (type "Container, Str -> Str -> Container"))))
|
||||
(expr (type "(Str, Str, Str)"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ nums : List U8
|
|||
~~~
|
||||
# EXPECTED
|
||||
PARSE ERROR - type_annotation_missing_parens.md:2:1:2:1
|
||||
TOO FEW ARGS - type_annotation_missing_parens.md:1:8:1:12
|
||||
# PROBLEMS
|
||||
**PARSE ERROR**
|
||||
Type applications require parentheses around their type arguments.
|
||||
|
|
@ -33,6 +34,16 @@ Other valid examples:
|
|||
^
|
||||
|
||||
|
||||
**TOO FEW ARGS**
|
||||
The type _List_ expects argument, but got instead.
|
||||
**type_annotation_missing_parens.md:1:8:1:12:**
|
||||
```roc
|
||||
nums : List U8
|
||||
```
|
||||
^^^^
|
||||
|
||||
|
||||
|
||||
# TOKENS
|
||||
~~~zig
|
||||
LowerIdent,OpColon,UpperIdent,UpperIdent,
|
||||
|
|
@ -53,11 +64,18 @@ nums : List
|
|||
~~~
|
||||
# CANONICALIZE
|
||||
~~~clojure
|
||||
(can-ir (empty true))
|
||||
(can-ir
|
||||
(d-let
|
||||
(p-assign (ident "nums"))
|
||||
(e-anno-only)
|
||||
(annotation
|
||||
(ty-lookup (name "List") (builtin)))))
|
||||
~~~
|
||||
# TYPES
|
||||
~~~clojure
|
||||
(inferred-types
|
||||
(defs)
|
||||
(expressions))
|
||||
(defs
|
||||
(patt (type "Error")))
|
||||
(expressions
|
||||
(expr (type "Error"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -143,21 +143,28 @@ NO CHANGE
|
|||
(ty-malformed))
|
||||
(ty-apply (name "Result") (builtin)
|
||||
(ty-record)
|
||||
(ty-underscore))))))
|
||||
(ty-underscore)))))
|
||||
(d-let
|
||||
(p-assign (ident "tag_tuple"))
|
||||
(e-anno-only)
|
||||
(annotation
|
||||
(ty-malformed))))
|
||||
~~~
|
||||
# TYPES
|
||||
~~~clojure
|
||||
(inferred-types
|
||||
(defs
|
||||
(patt (type "Num(Int(Unsigned64))"))
|
||||
(patt (type "Error"))
|
||||
(patt (type "Error"))
|
||||
(patt (type "Error"))
|
||||
(patt (type "Error"))
|
||||
(patt (type "(_a, _b, _c)"))
|
||||
(patt (type "Num(Int(Unsigned8)), Num(Int(Unsigned16)) -> Num(Int(Unsigned32))"))
|
||||
(patt (type "List(Error) -> Try({ }, _a)"))
|
||||
(patt (type "Error")))
|
||||
(expressions
|
||||
(expr (type "Num(Int(Unsigned64))"))
|
||||
(expr (type "Error"))
|
||||
(expr (type "Error"))
|
||||
(expr (type "Error"))
|
||||
(expr (type "Error"))
|
||||
(expr (type "(_a, _b, _c)"))
|
||||
(expr (type "Num(Int(Unsigned8)), Num(Int(Unsigned16)) -> Num(Int(Unsigned32))"))
|
||||
(expr (type "List(Error) -> Try({ }, _a)"))
|
||||
(expr (type "Error"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -71,6 +71,18 @@ decode_things # After member name
|
|||
# CANONICALIZE
|
||||
~~~clojure
|
||||
(can-ir
|
||||
(d-let
|
||||
(p-assign (ident "decode_things"))
|
||||
(e-anno-only)
|
||||
(annotation
|
||||
(ty-fn (effectful false)
|
||||
(ty-apply (name "List") (builtin)
|
||||
(ty-apply (name "List") (builtin)
|
||||
(ty-lookup (name "U8") (builtin))))
|
||||
(ty-apply (name "List") (builtin)
|
||||
(ty-rigid-var (name "a"))))
|
||||
(where
|
||||
(alias (ty-rigid-var-lookup (ty-rigid-var (name "a"))) (name "Decode")))))
|
||||
(s-import (module "Decode")
|
||||
(exposes
|
||||
(exposed (name "Decode") (wildcard false)))))
|
||||
|
|
@ -78,6 +90,8 @@ decode_things # After member name
|
|||
# TYPES
|
||||
~~~clojure
|
||||
(inferred-types
|
||||
(defs)
|
||||
(expressions))
|
||||
(defs
|
||||
(patt (type "List(List(Num(Int(Unsigned8)))) -> List(a)")))
|
||||
(expressions
|
||||
(expr (type "List(List(Num(Int(Unsigned8)))) -> List(a)"))))
|
||||
~~~
|
||||
|
|
|
|||
|
|
@ -194,15 +194,29 @@ broken_fn3 : a -> b
|
|||
(ty-rigid-var (name "a"))
|
||||
(ty-rigid-var (name "b")))
|
||||
(where
|
||||
(malformed)))))
|
||||
(malformed))))
|
||||
(d-let
|
||||
(p-assign (ident "broken_fn3"))
|
||||
(e-anno-only)
|
||||
(annotation
|
||||
(ty-fn (effectful false)
|
||||
(ty-rigid-var (name "a"))
|
||||
(ty-rigid-var (name "b")))
|
||||
(where
|
||||
(method (ty-rigid-var (name "c")) (name "method")
|
||||
(args
|
||||
(ty-rigid-var-lookup (ty-rigid-var (name "c"))))
|
||||
(ty-rigid-var (name "d")))))))
|
||||
~~~
|
||||
# TYPES
|
||||
~~~clojure
|
||||
(inferred-types
|
||||
(defs
|
||||
(patt (type "Error"))
|
||||
(patt (type "Error")))
|
||||
(patt (type "a -> b"))
|
||||
(patt (type "a -> b"))
|
||||
(patt (type "a -> b")))
|
||||
(expressions
|
||||
(expr (type "Error"))
|
||||
(expr (type "Error"))))
|
||||
(expr (type "a -> b"))
|
||||
(expr (type "a -> b"))
|
||||
(expr (type "a -> b"))))
|
||||
~~~
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue