c interop type foundation
This commit is contained in:
@@ -5,6 +5,7 @@ import "../lexer"
|
||||
import "../parser"
|
||||
import "../source"
|
||||
import "../symbol"
|
||||
import "../types"
|
||||
import "core:mem"
|
||||
import "core:os"
|
||||
import "core:path/filepath"
|
||||
@@ -253,6 +254,92 @@ validate_imports :: proc(state: ^State) {
|
||||
}
|
||||
}
|
||||
|
||||
find_type_import :: proc(module: ^ast.Module, file: ast.File_Id, alias: symbol.Id) -> ast.Import_Id {
|
||||
for import_item, index in module.imports {
|
||||
if import_item.file == file && import_item.alias == alias {
|
||||
return ast.import_id(index)
|
||||
}
|
||||
}
|
||||
return ast.INVALID_IMPORT
|
||||
}
|
||||
|
||||
canonical_type :: proc(
|
||||
module: ^ast.Module,
|
||||
value: types.Type,
|
||||
mapping: []types.Type,
|
||||
visiting: []bool,
|
||||
) -> types.Type {
|
||||
if value < types.DYNAMIC_START {
|
||||
return value
|
||||
}
|
||||
index := int(value-types.DYNAMIC_START)
|
||||
if index < 0 || index >= len(mapping) {
|
||||
return value
|
||||
}
|
||||
if types.is_valid(mapping[index]) {
|
||||
return mapping[index]
|
||||
}
|
||||
if visiting[index] {
|
||||
return value
|
||||
}
|
||||
visiting[index] = true
|
||||
defer visiting[index] = false
|
||||
item := module.type_store.nodes[index]
|
||||
if item.kind == .Named {
|
||||
if item.qualifier != 0 {
|
||||
import_id := find_type_import(module, ast.File_Id(item.file), symbol.Id(item.qualifier))
|
||||
if import_id != ast.INVALID_IMPORT {
|
||||
module.imports[import_id].used = true
|
||||
import_item := module.imports[import_id]
|
||||
resolved := types.find_named(&module.type_store, u32(import_item.target), item.name)
|
||||
if types.is_valid(resolved) {
|
||||
mapping[index] = resolved
|
||||
return resolved
|
||||
}
|
||||
}
|
||||
}
|
||||
mapping[index] = value
|
||||
return value
|
||||
}
|
||||
if item.kind == .Struct {
|
||||
mapping[index] = value
|
||||
fields := types.fields_for(&module.type_store, value)
|
||||
for &field in fields {
|
||||
field.type = canonical_type(module, field.type, mapping, visiting)
|
||||
}
|
||||
return value
|
||||
}
|
||||
if types.is_valid(item.child) {
|
||||
item.child = canonical_type(module, item.child, mapping, visiting)
|
||||
}
|
||||
resolved := types.intern(&module.type_store, item)
|
||||
mapping[index] = resolved
|
||||
return resolved
|
||||
}
|
||||
|
||||
canonicalize_types :: proc(module: ^ast.Module, allocator: mem.Allocator) {
|
||||
original_count := len(module.type_store.nodes)
|
||||
mapping := make([]types.Type, original_count, allocator)
|
||||
visiting := make([]bool, original_count, allocator)
|
||||
defer delete(mapping, allocator)
|
||||
defer delete(visiting, allocator)
|
||||
for &function in module.functions {
|
||||
for ¶m in function.params {
|
||||
param.type = canonical_type(module, param.type, mapping, visiting)
|
||||
}
|
||||
function.result = canonical_type(module, function.result, mapping, visiting)
|
||||
}
|
||||
for &global in module.globals {
|
||||
global.type = canonical_type(module, global.type, mapping, visiting)
|
||||
}
|
||||
for &statement in module.statements {
|
||||
statement.type = canonical_type(module, statement.type, mapping, visiting)
|
||||
}
|
||||
for index := 0; index < original_count; index += 1 {
|
||||
_ = canonical_type(module, types.DYNAMIC_START+types.Type(index), mapping, visiting)
|
||||
}
|
||||
}
|
||||
|
||||
load :: proc(
|
||||
root_path: string,
|
||||
sources: ^source.Store,
|
||||
@@ -275,5 +362,6 @@ load :: proc(
|
||||
state.root_failed = true
|
||||
}
|
||||
validate_imports(&state)
|
||||
canonicalize_types(&module, allocator)
|
||||
return module, !state.root_failed
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user