Skip to content

Commit 933aa0e

Browse files
committed
Compile simple generic functions
1 parent 7809094 commit 933aa0e

File tree

3 files changed

+97
-25
lines changed

3 files changed

+97
-25
lines changed

src/consteval.pr

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,8 @@ export def walk_Def(node: &parser::Node, state: &typechecking::State) {
339339
node.inner_scope = scope::enter_function_scope(state.scope)
340340

341341
let prev_scope = state.scope
342-
state.scope = node.inner_scope
342+
let temp_scope = scope::enter_scope(node.inner_scope)
343+
state.scope = temp_scope
343344
for var i in 0..vector::length(params) {
344345
let param = params(i)
345346
assert param.kind == parser::NodeKind::PARAMETER

src/scope.pr

Lines changed: 56 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,27 @@ export type Scope = struct {
245245
polymorphics: &SMap(&Scope)
246246
}
247247

248+
export def print_scope(scope: &Scope) {
249+
print_scope(scope, "")
250+
}
251+
252+
def print_scope(scope: &Scope, indent: Str) {
253+
if not scope { return }
254+
print(indent, "Scope (module=", scope.module.module if scope.module else to_str("<null>"), "):\n")
255+
let keys = scope.fields.keys()
256+
for var i in 0..keys.size {
257+
let key = keys(i)
258+
let value = scope.fields(key)
259+
print(indent, " ", key, " -> ", typechecking::generic_to_string(value.tpe), " (", to_string(value.kind), ", ", to_string(value.phase), ")\n")
260+
}
261+
if scope.parents {
262+
for var parent in scope.parents {
263+
print(indent, "Parent:\n")
264+
print_scope(parent, indent + " ")
265+
}
266+
}
267+
}
268+
248269
export def parent(scope: &Scope) -> &Scope {
249270
if scope.parents and scope.parents.length > 0 {
250271
return scope.parents(0)
@@ -729,19 +750,32 @@ def find_function(scope: &Scope, node: &parser::Node, v: &Value, parameter_t: &V
729750
if v.kind != ValueKind::FUNCTION { return false, null }
730751

731752
var found: &Value = null
753+
var found_scope: &Scope = null
732754
var d = false
733755
loop {
734756
if not v { break }
735757
/*if v.node and v.state {
736758
v.tpe = typechecking::lookup_parameters(v.node, v.state)
737759
}*/
738760

739-
let s = typechecking::overload_score(v.fdef, parameter_t, context, false)
761+
var new_scope = context
762+
if typechecking::is_polymorph(v.fdef.parameter_t) {
763+
// Create temporary scope for type lookup
764+
// TODO Maybe cache it somewhere instead of creating a new one when creating a polymorphic instance
765+
let parents = vector::make(type weak &Scope)
766+
parents.push(scope)
767+
parents.push(context)
768+
new_scope = enter_scope(parents, scope.module)
769+
}
770+
let s = typechecking::overload_score(v.fdef, parameter_t, new_scope, false)
740771
//print(scope.module.module if scope.module else to_str("<unknown>"), " ", v.tpe.type_name, " ", s, "\n")
772+
//print_fdef(v.fdef)
773+
//print("\tscore: ", s, "\n")
741774
if s >= 0 {
742775
if s < @score {
743776
@score = s
744777
found = v
778+
found_scope = new_scope
745779
d = false
746780
} else if s == @score {
747781
d = true
@@ -764,7 +798,14 @@ def find_function(scope: &Scope, node: &parser::Node, v: &Value, parameter_t: &V
764798
if not dry_run { ambigous_reference(node) }
765799
return true, null
766800
}
767-
return found != null, found
801+
802+
if found != null {
803+
if found.phase == Phase::DEFINED and not dry_run {
804+
found = typecheck_function(found, parameter_t, found_scope)
805+
}
806+
return true, found
807+
}
808+
return false, null
768809
}
769810

770811
export def find_implicit_function(scope: &Scope, parameter_t: &Vector(typechecking::NamedParameter), ret: &typechecking::Type, force_compile: bool = true, context: &Scope = null) -> &Value {
@@ -903,6 +944,7 @@ export def remove(scope: &Scope, value: &Value) {
903944

904945
export def generate_function(scope: &Scope, node: &parser::Node, parameter_t: &Vector(typechecking::NamedParameter), dry_run: bool = false) -> &Value {
905946
let module = scope.module
947+
if not module { return null }
906948
scope = module.scope
907949

908950
let name = last_path_element(node)
@@ -1084,13 +1126,13 @@ export def create_underscore(scope: &Scope, name_node: &parser::Node, tpe: &type
10841126

10851127
export def typecheck_function(value: &Value, parameter_t: &Vector(typechecking::NamedParameter), context: &Scope) -> &Value {
10861128
assert value.kind == ValueKind::FUNCTION
1087-
value.phase = Phase::COMPILED
10881129
//let tpe = typechecking::lookup_parameters(value.node, value.state)
10891130
if typechecking::is_polymorph(value.fdef.parameter_t) {
10901131
let node = typechecking::walk_Def_with_type_argument(value.node, parameter_t, context, typechecking::make_state(value.module))
10911132
let value = node.value.def_.function.value
10921133
return value
10931134
} else {
1135+
value.phase = Phase::COMPILED
10941136
let state = typechecking::make_state(value.module)
10951137
state.context = value.node.scope
10961138
typechecking::walk_Def(value.node, state)
@@ -1101,7 +1143,6 @@ export def typecheck_function(value: &Value, parameter_t: &Vector(typechecking::
11011143

11021144
export def typecheck(value: &Value) {
11031145
if not value.node { return }
1104-
value.phase = Phase::COMPILED
11051146
let state = typechecking::make_state(value.module)
11061147
if value.node.kind == parser::NodeKind::DEF {
11071148
assert value.kind == ValueKind::FUNCTION
@@ -1110,9 +1151,11 @@ export def typecheck(value: &Value) {
11101151
if not typechecking::is_polymorph(fdef.parameter_t) {
11111152
state.context = value.node.scope
11121153
typechecking::walk_Def(value.node, state)
1154+
value.phase = Phase::COMPILED
11131155
value.tpe = typechecking::make_type_ref(value.node.tpe)
11141156
}
11151157
} else {
1158+
value.phase = Phase::COMPILED
11161159
typechecking::walk(value.node.parent, value.node, state)
11171160
}
11181161
}
@@ -1304,9 +1347,9 @@ export def get_function_check(
13041347
}
13051348
}
13061349

1307-
if value and value.phase == Phase::DEFINED and force_compile {
1308-
value = typecheck_function(value, parameter_t, context)
1309-
}
1350+
//if value and value.phase == Phase::DEFINED and force_compile {
1351+
// value = typecheck_function(value, parameter_t, context)
1352+
//}
13101353

13111354

13121355
return code, value
@@ -1416,9 +1459,9 @@ export def get(
14161459
var score = 0
14171460
let _, (value) = find_function(scope, id, value, id.value.identifier.types, *score, true, context)
14181461

1419-
if value and force_compile and value.phase == Phase::DEFINED {
1420-
value = typecheck_function(value, id.value.identifier.types, context)
1421-
}
1462+
//if value and force_compile and value.phase == Phase::DEFINED {
1463+
// value = typecheck_function(value, id.value.identifier.types, context)
1464+
//}
14221465
return value
14231466
} else if value.kind == ValueKind::FUNCTION and id.parent and id.parent.kind == parser::NodeKind::PTR and value.next {
14241467
if not dry_run { ambigous_reference(id) }
@@ -1446,9 +1489,9 @@ export def get(
14461489
if id.value.identifier.types {
14471490
var score = 0
14481491
let _, (value2) = find_function(scope, id, value2, id.value.identifier.types, *score, true, context)
1449-
if value2 and force_compile and value2.phase == Phase::DEFINED {
1450-
value2 = typecheck_function(value2, id.value.identifier.types, context)
1451-
}
1492+
//if value2 and force_compile and value2.phase == Phase::DEFINED {
1493+
// value2 = typecheck_function(value2, id.value.identifier.types, context)
1494+
//}
14521495
} else {
14531496
if force_compile and value2.phase == Phase::DEFINED {
14541497
typecheck(value2)

src/typechecking.pr

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ export type TypeKind = enum {
4646
// STUB
4747
// Placeholder for arguments with polymorphic type parameter in function definition
4848
TYPE_DEF
49+
// Reference to a type
50+
TYPE_REF
4951
BYREF // ref parameter
5052
RANGE // TODO Ranges should be a concrete Type defined by the stdlib
5153
RANGE_INC
@@ -279,7 +281,7 @@ export def kind(typeref: &TypeRef) -> TypeKind {
279281
if typeref.tpe {
280282
return typeref.tpe.resolve().kind
281283
} else if typeref.name {
282-
return TypeKind::TYPE
284+
return TypeKind::TYPE_REF
283285
} else if typeref.pattern {
284286
return typeref.pattern.kind
285287
}
@@ -458,8 +460,6 @@ def generic_to_string(generic: &Pattern) -> Str {
458460
return "[" + generic_to_string(generic.tpe) + "]"
459461
} else if generic.kind == TypeKind::STATIC_ARRAY {
460462
return "[" + generic.length + "; " + generic_to_string(generic.tpe) + "]"
461-
} else if generic.kind == TypeKind::TYPE_DEF {
462-
return "type " + generic.name
463463
} else if generic.kind == TypeKind::TYPE_CONSTRUCTOR {
464464
var res: StringBuffer = generic.name + "("
465465
let len = generic.return_t.length()
@@ -1187,6 +1187,25 @@ export type FunctionDef = struct {
11871187
parameter_t: &Vector(NamedParameterPre)
11881188
return_t: &Vector(&TypeRef)
11891189
}
1190+
export def print_fdef(fdef: FunctionDef) {
1191+
print(fdef.name + "(")
1192+
for var i in 0..fdef.parameter_t.length() {
1193+
let p = fdef.parameter_t(i)
1194+
print(p.name + ": ", generic_to_string(p.tpe))
1195+
if i < fdef.parameter_t.length() - 1 {
1196+
print(", ")
1197+
}
1198+
}
1199+
print(" -> ")
1200+
for var i in 0..fdef.return_t.length() {
1201+
let r = fdef.return_t(i)
1202+
print(generic_to_string(r))
1203+
if i < fdef.return_t.length() - 1 {
1204+
print(", ")
1205+
}
1206+
}
1207+
print(")\n")
1208+
}
11901209
export def hash(fdef: FunctionDef) -> uint64 {
11911210
var h: uint64
11921211
if fdef.parameter_t {
@@ -1297,7 +1316,7 @@ def callable_generic(kind: TypeKind, parameter_t: &Vector(NamedParameterPre), re
12971316

12981317
var pars = vector::make(NamedParameter)
12991318
for var par in parameter_t {
1300-
pars.push([ name = par.name, tpe = par.tpe.tpe, value = par.value, kw = par.kw, varargs = par.varargs, node = par.node ] !NamedParameter)
1319+
pars.push([ name = par.name, tpe = (par.tpe.tpe if par.tpe else 0), value = par.value, kw = par.kw, varargs = par.varargs, node = par.node ] !NamedParameter)
13011320
}
13021321

13031322
let rets = vector::make(TypeId)
@@ -1898,6 +1917,7 @@ export def shallow_copy(tpe: &Type) -> &Type {
18981917
*/
18991918

19001919
export def equals(a: &Type, b: &Type) -> bool {
1920+
if not a or not b { return false }
19011921
return a.id == b.id
19021922
}
19031923

@@ -2308,9 +2328,8 @@ def infer_interface_types(a: &Type, b: &Type, module: &toolchain::Module) -> &Ty
23082328

23092329
return tpe
23102330
}*/
2311-
23122331
export def convert_type_score(a: &TypeRef, b: &Type, scpe: &scope::Scope, impl: bool = true) -> int {
2313-
print(generic_to_string(a), " <-> ", debug::type_to_str(b), "\n")
2332+
if not a or not b { return 0 }
23142333
if a.pattern {
23152334
return convert_type_score(a.pattern, b, scpe, impl)
23162335
} else if a.name {
@@ -2823,6 +2842,13 @@ export def replace_type_defs(
28232842
left.tpe = make_type_ref(rtpe)
28242843
}
28252844
}
2845+
2846+
// Resolve return types
2847+
for var i in 0..vector::length(return_t) {
2848+
let cpy = @return_t(i) !&TypeRef
2849+
let rtpe = resolve(cpy, scpe)
2850+
return_t(i) = make_type_ref(rtpe)
2851+
}
28262852
}
28272853

28282854
export def overload_score(
@@ -3661,6 +3687,8 @@ def do_type_lookup(node: &parser::Node, state: &State, is_type: bool = false) ->
36613687
let name = node.value.type_constructor.name
36623688

36633689
var type_constructor = resolve(type_lookup(name, state, is_type).tpe)
3690+
assert type_constructor
3691+
36643692
if type_constructor.kind != TypeKind::TYPE_CONSTRUCTOR {
36653693
errors::errorn(node, "Not a type constructor")
36663694
return null
@@ -6996,7 +7024,7 @@ export def walk_Def_with_type_argument(node: &parser::Node, args: &Vector(NamedP
69967024
let extern = node.value.def_.extern
69977025

69987026
let old_node = node
6999-
let fun = @node.value.def_.function // Copy
7027+
let fun = @node.value.def_.function !&compiler::Function // Copy
70007028

70017029
node = parser::deep_copy_node(node)
70027030
//node.value.def_.function = null
@@ -7006,16 +7034,16 @@ export def walk_Def_with_type_argument(node: &parser::Node, args: &Vector(NamedP
70067034
fun.locals = map::make(TypeId)
70077035
fun.scope = state.scope
70087036
fun.captures = vector::make(type weak &scope::Value)
7009-
fun.inner_scope = node.inner_scope = scope::enter_function_scope(node.scope)
7037+
fun.inner_scope = node.inner_scope = scope::enter_function_scope(context)
70107038
fun.module = context.module
70117039

70127040
node.value.def_.function = fun
70137041

70147042
//node.tpe = lookup_parameters(node, state)
70157043

70167044
// Unbox
7017-
let module = context.module
7018-
context = module.scope
7045+
//let module = context.module
7046+
//context = module.scope
70197047

70207048
/*var in_context = false
70217049
var super_scope = node.scope
@@ -7114,7 +7142,7 @@ export def walk_Def_with_type_argument(node: &parser::Node, args: &Vector(NamedP
71147142

71157143
fun.fdef = function_def(
71167144
parser::identifier_to_str(name),
7117-
fdef.parameter_t, fdef.return_t, state.module,
7145+
parameter_t, return_t, state.module,
71187146
extern, test, context.module
71197147
)
71207148
node.fdef = fun.fdef !&FunctionDef

0 commit comments

Comments
 (0)