feat: specialize generic type and value parameters
This commit is contained in:
@@ -14,6 +14,7 @@ import "@source/lower"
|
||||
import "@source/loader"
|
||||
import "@source/ir"
|
||||
typecheck :: import "@source/sema/check"
|
||||
import "@source/sema/specialize"
|
||||
|
||||
#! identities are valid only within their owning compilation.
|
||||
SourceId :: alias diagnostics.SourceId
|
||||
@@ -350,7 +351,7 @@ compile proc(
|
||||
}
|
||||
imports := arraylist.init(sema.Import, compilation.allocator)
|
||||
defer arraylist.deinit(&imports)
|
||||
tree :: ast.view(&compilation.builder, compilation.module_root?)
|
||||
tree := ast.view(&compilation.builder, compilation.module_root?)
|
||||
for (compilation.imports.items) |link| {
|
||||
imported :: ast.import_decl(&tree, link.node)
|
||||
name := strpool.no_str
|
||||
@@ -392,7 +393,10 @@ compile proc(
|
||||
}
|
||||
resolution := try sema.resolve_packages(compilation.allocator, &tree, roots.items, imports.items, &compilation.strings, diagnostic_store)
|
||||
defer sema.deinit(&resolution)
|
||||
checked := try typecheck.check(compilation.allocator, &tree, &resolution, diagnostic_store)
|
||||
elaborated := try specialize.elaborate(compilation.allocator, &compilation.builder, compilation.module_root?, &resolution, diagnostic_store)
|
||||
defer specialize.deinit(&elaborated)
|
||||
tree = ast.view(&compilation.builder, compilation.module_root?)
|
||||
checked := try typecheck.check_elaborated(compilation.allocator, &tree, &resolution, elaborated.constraints.items, diagnostic_store)
|
||||
defer typecheck.deinit(&checked)
|
||||
return try lower.lower_package(compilation.allocator, &tree, &resolution, &checked, roots.items[usize(root_package)], diagnostic_store)
|
||||
}
|
||||
|
||||
@@ -68,6 +68,40 @@ keeps_package_declarations_distinct_and_ir_independent test {
|
||||
try testing.expect_equal(i64(6), right_result.value.data.integer)
|
||||
}
|
||||
|
||||
recompiles_specialized_calls_without_borrowing_previous_ir test {
|
||||
diagnostic_store := diagnostics.init(mem.c_allocator)
|
||||
defer diagnostics.deinit(&diagnostic_store)
|
||||
modules [2]mut ir.Module := undefined
|
||||
{
|
||||
session := init(mem.c_allocator)
|
||||
defer deinit(&session)
|
||||
root :: try add_package(&session)
|
||||
bytes := try owned_text(
|
||||
`identity proc($T type, value T) T { return value }
|
||||
`Box proc($T type) type { return struct { value T } }
|
||||
`main proc() i16 {
|
||||
` box Box(i16) :: { value = identity(i16, 40) }
|
||||
` return identity(box.value) + 2
|
||||
`}
|
||||
,
|
||||
)
|
||||
defer arraylist.deinit(&bytes)
|
||||
_ = try add_source(&session, root, "generic.hon", &bytes, &diagnostic_store)
|
||||
modules[0] = try compile(&session, root, &diagnostic_store)
|
||||
errdefer ir.deinit(&modules[0])
|
||||
modules[1] = try compile(&session, root, &diagnostic_store)
|
||||
}
|
||||
defer ir.deinit(&modules[0])
|
||||
defer ir.deinit(&modules[1])
|
||||
try testing.expect_equal(0, diagnostics.count(&diagnostic_store))
|
||||
for (0..modules.len) |index| {
|
||||
outcome := try interpreter.run(mem.c_allocator, &modules[index], &diagnostic_store)
|
||||
defer interpreter.deinit(&outcome)
|
||||
try testing.expect(outcome.trap == null)
|
||||
try testing.expect_equal(i64(42), outcome.value.data.integer)
|
||||
}
|
||||
}
|
||||
|
||||
dependency_traps_keep_original_spans_and_remain_demand_driven test {
|
||||
mains [2][]u8 :: [
|
||||
`dep :: import "../dependency"
|
||||
|
||||
Reference in New Issue
Block a user