Skip to content

Commit

Permalink
Arrays work
Browse files Browse the repository at this point in the history
  • Loading branch information
Victorious3 committed Jan 11, 2024
1 parent 82a0702 commit fd83254
Showing 1 changed file with 64 additions and 7 deletions.
71 changes: 64 additions & 7 deletions src/typechecking.pr
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,9 @@ export type Type = struct {

// Interface implementation
intf: &Type
// This gets set if it might also be a type argument, in that case we also consider the overload with a type
// As an example, consider [int], this might be an array of types or an array type
may_be_type: &Type
}

export def hash(tpe: &Type) -> uint64 {
Expand Down Expand Up @@ -1494,7 +1497,7 @@ export def convert_type_score(a: &Type, b: &Type, module: &toolchain::Module, is
if a.kind == TypeKind::TYPE_DEF {
return convert_type_score(a.tpe, b, module, true)
}
if a.kind == TypeKind::TYPE and equals(b, pointer(builtins::Type_)) {
if a.kind == TypeKind::TYPE and (equals(b, pointer(builtins::Type_)) or b.may_be_type) {
return 4
}
if (a.kind == TypeKind::POINTER or a.kind == TypeKind::REFERENCE or a.kind == TypeKind::WEAK_REF) and (@b).kind == TypeKind::NULL {
Expand Down Expand Up @@ -1942,9 +1945,11 @@ export def overload_score(
}
var score = -1
if lvalue and lvalue.kind == TypeKind::TYPE {
// TODO This is not documented and weird in more than one place
// I think the confusion comes from the fact that sometimes the type is stored in the NamedParameter
// and sometimes in the type directly. The latter would make more sense
if equals(right.tpe, pointer(builtins::Type_)) {
if left.value {
// TODO It's better to give TYPE a tpe, see below
if equals(left.value.value_tpe, right.tpe.tpe.tpe) {
score = 0
}
Expand All @@ -1963,6 +1968,13 @@ export def overload_score(
} else if left.tpe.tpe and right.tpe.tpe and equals(left.tpe.tpe, right.tpe.tpe) {
score = 0
}
} else if right.tpe.may_be_type {
// This is what it should look like for the others as well
if not left.tpe.tpe {
score = 4
} else if right.tpe.may_be_type.tpe and equals(left.tpe.tpe, right.tpe.may_be_type.tpe) {
score = 0
}
}
} else {
score = convert_type_score(lvalue, right.tpe, module, impl = impl)
Expand Down Expand Up @@ -2295,6 +2307,23 @@ export def type_lookup(node: &parser::Node, state: &State, current_type: &Type =
return tpe
}

def convert_ambiguous_expr_to_type(node: &parser::Node, state: &State) -> &Type {
if node.kind == parser::NodeKind::ARRAY_LIT {
var res = { kind = parser::NodeKind::ARRAY_T } !&parser::Node
res.value.t_parr.tpe = node.value.body[0]
res.value.t_parr.tpe.tpe = convert_ambiguous_expr_to_type(res.value.t_parr.tpe, state)
res.tpe = type_lookup(res, state)
let arr_tpe = make_type_raw(TypeKind::TYPE)
arr_tpe._tpe = res.tpe
res.tpe = arr_tpe
res.tpe.node = null

return res.tpe
} else if node.kind == parser::NodeKind::IDENTIFIER {
return type_lookup(node, state)
}
}

def lookup_field_type(node: &parser::Node, state: &State, current_type: &Type, cache: &map::SMap(&Type)) -> &Type {
if not node { return null }
node.scope = state.scope
Expand Down Expand Up @@ -3087,13 +3116,17 @@ def walk_Identifier(node: &parser::Node, state: &State) {

def implicit_conversion(node: &parser::Node, tpe: &Type, state: &State) {
if not tpe { return }
// TODO For integers we need to check the boundaries
// TODO What about stuff like --10? I mean its kinda useless but for completeness
if node.kind == parser::NodeKind::NULL and is_pointer(tpe) or
// Convert type
if tpe.kind == TypeKind::TYPE and node.tpe and node.tpe.may_be_type {
node.tpe = node.tpe.may_be_type
} else if node.kind == parser::NodeKind::NULL and is_pointer(tpe) or
is_arithmetic(tpe) and (node.kind == parser::NodeKind::INTEGER or
(node.kind == parser::NodeKind::USUB or node.kind == parser::NodeKind::UADD) and
(@node.value.expr).kind == parser::NodeKind::INTEGER) {

// TODO For integers we need to check the boundaries
// TODO What about stuff like --10? I mean its kinda useless but for completeness

node.tpe = tpe
} else if is_function_pointer(tpe) and
node.kind == parser::NodeKind::PTR and
Expand Down Expand Up @@ -5214,6 +5247,11 @@ def walk_ArrayLit(node: &parser::Node, state: &State) {
ret_tpe.size = len * (@tpe).size
ret_tpe.align = (@tpe).align

// Check if we have a type array, in this case it might also be a type
if equals(tpe, pointer(builtins::Type_)) or tpe.may_be_type {
ret_tpe.may_be_type = convert_ambiguous_expr_to_type(node, state)
}

node.tpe = ret_tpe
}

Expand Down Expand Up @@ -5594,7 +5632,14 @@ export def walk_Def_with_type_argument(node: &parser::Node, parameter_t: &Vector
}

if left and equals(left.tpe, builtins::type_) {
left.value = { kind = compiler::ValueKind::TYPE, tpe = builtins::type_, value_tpe = np.tpe.tpe.tpe } !&compiler::Value
if np.tpe and np.tpe.may_be_type {
np._tpe = np.tpe.may_be_type
left.value = { kind = compiler::ValueKind::TYPE, tpe = builtins::type_, value_tpe = np.tpe.tpe } !&compiler::Value
left.tpe = np.tpe.may_be_type
parameter_t[i] = np
} else {
left.value = { kind = compiler::ValueKind::TYPE, tpe = builtins::type_, value_tpe = np.tpe.tpe.tpe } !&compiler::Value
}
}
}

Expand Down Expand Up @@ -5624,7 +5669,19 @@ export def walk_Def_with_type_argument(node: &parser::Node, parameter_t: &Vector
let old_scope = state.scope
state.scope = node.inner_scope
node.value.def_.has_lookup = false
node.tpe = tpe = lookup_parameters(node, state)
node.tpe = lookup_parameters(node, state)

// Replace contextual type parameters
for var i in 0..node.tpe.parameter_t.length {
let left = node.tpe.parameter_t.get(i)
if i >= tpe.parameter_t.length { break }
let right = tpe.parameter_t.get(i)
if is_type(left.tpe) {
left._tpe._tpe = right.value.value_tpe
}
}

tpe = node.tpe

if vector::length(tpe.parameter_t) > 0 {
let first_param = tpe.parameter_t[0]
Expand Down

0 comments on commit fd83254

Please sign in to comment.