@@ -8,6 +8,9 @@ import strings
88
99// Stage for solving generics
1010
11+ const result_name = ast.result_name
12+ const option_name = ast.option_name
13+
1114pub struct Generics {
1215 pref & pref.Preferences
1316pub mut :
@@ -328,8 +331,19 @@ pub fn (mut g Generics) stmt(mut node ast.Stmt) ast.Stmt {
328331 return node
329332}
330333
334+ pub fn (mut g Generics) styp (t ast.Type) string {
335+ if ! t.has_option_or_result () {
336+ return g.base_type (t)
337+ } else if t.has_flag (.option) {
338+ // Register an optional if it's not registered yet
339+ return g.register_option (t)
340+ } else {
341+ return g.register_result (t)
342+ }
343+ }
344+
331345// incomplete implementation: TODO
332- pub fn (mut g Generics) styp (_t ast.Type) string {
346+ fn (mut g Generics) base_type (_t ast.Type) string {
333347 t := g.unwrap_generic (_t)
334348 if styp := g.styp_cache[t] {
335349 return styp
@@ -351,6 +365,62 @@ pub fn (mut g Generics) styp(_t ast.Type) string {
351365 return styp
352366}
353367
368+ // incomplete implementation: TODO
369+ fn (mut g Generics) register_option (t ast.Type) string {
370+ styp , _ := g.option_type_name (t)
371+ return if ! t.has_flag (.option_mut_param_t) { styp } else { '${styp }*' }
372+ }
373+
374+ // incomplete implementation: TODO
375+ fn (mut g Generics) register_result (t ast.Type) string {
376+ styp , _ := g.result_type_name (t)
377+ return styp
378+ }
379+
380+ // TODO: this really shouldn't be separate from typ
381+ // but I(emily) would rather have this generation
382+ // all unified in one place so that it doesn't break
383+ // if one location changes
384+ fn (mut g Generics) option_type_name (t ast.Type) (string , string ) {
385+ mut base := g.base_type (t)
386+ mut styp := ''
387+ sym := g.table.sym (t)
388+ if sym.info is ast.FnType {
389+ base = 'anon_fn_${g .table .fn_type_signature (sym .info .func )}'
390+ }
391+ if sym.language == .c && sym.kind == .struct {
392+ styp = '${option_name }_${base .replace (' ', '_ ')}'
393+ } else {
394+ styp = '${option_name }_${base }'
395+ }
396+ if t.has_flag (.generic) || t.is_ptr () {
397+ styp = styp.replace ('*' , '_ptr' )
398+ }
399+ return styp, base
400+ }
401+
402+ fn (mut g Generics) result_type_name (t ast.Type) (string , string ) {
403+ mut base := g.base_type (t)
404+ if t.has_flag (.option) {
405+ g.register_option (t)
406+ base = '_option_' + base
407+ }
408+ mut styp := ''
409+ sym := g.table.sym (t)
410+ if sym.info is ast.FnType {
411+ base = 'anon_fn_${g .table .fn_type_signature (sym .info .func )}'
412+ }
413+ if sym.language == .c && sym.kind == .struct {
414+ styp = '${result_name }_${base .replace (' ', '_ ')}'
415+ } else {
416+ styp = '${result_name }_${base }'
417+ }
418+ if t.has_flag (.generic) || t.is_ptr () {
419+ styp = styp.replace ('*' , '_ptr' )
420+ }
421+ return styp, base
422+ }
423+
354424// cc_type whether to prefix 'struct' or not (C__Foo -> struct Foo)
355425fn (mut g Generics) cc_type (typ ast.Type, is_prefix_struct bool ) string {
356426 sym := g.table.sym (g.unwrap_generic (typ))
@@ -382,12 +452,15 @@ fn (mut g Generics) cc_type(typ ast.Type, is_prefix_struct bool) string {
382452 return styp
383453}
384454
385- pub fn (mut g Generics) method_concrete_name (old_name string , concrete_types []ast.Type, receiver_type ast.Type) string {
455+ pub fn (mut g Generics) method_concrete_name (old_name string , concrete_types []ast.Type, _receiver_type ast.Type) string {
386456 mut name := old_name
387- if receiver_type != 0 {
388- info := g.table.sym (g.unwrap_generic (receiver_type)).info
389- if info is ast.Struct {
390- fn_conc_types := concrete_types[info.generic_types.len..] // concrete types without the generic types of the struct
457+ if _receiver_type != 0 {
458+ mut info := g.table.sym (g.unwrap_generic (_receiver_type)).info
459+ if mut info is ast.Alias {
460+ info = g.table.sym (g.table.unaliased_type (g.unwrap_generic (_receiver_type))).info
461+ }
462+ if mut info is ast.Struct {
463+ fn_conc_types := concrete_types#[info.generic_types.len..] // concrete types without the generic types of the struct
391464
392465 if fn_conc_types.len > 0 {
393466 name + = '_T'
@@ -397,7 +470,7 @@ pub fn (mut g Generics) method_concrete_name(old_name string, concrete_types []a
397470 g.styp (typ.set_nr_muls (0 ))
398471 }
399472 return name
400- } else if info is ast.Interface {
473+ } else if mut info is ast.Interface {
401474 return name
402475 }
403476 }
@@ -585,6 +658,10 @@ pub fn (mut g Generics) expr(mut node ast.Expr) ast.Expr {
585658 }
586659 }
587660 }
661+ mut receiver_type := g.unwrap_generic (node.receiver_type)
662+ if receiver_type.has_flag (.generic) {
663+ receiver_type = receiver_type.clear_flag (.generic)
664+ }
588665 return ast.Expr (ast.CallExpr{
589666 ...node
590667 name: if node.is_method {
@@ -593,7 +670,7 @@ pub fn (mut g Generics) expr(mut node ast.Expr) ast.Expr {
593670 g.concrete_name (node.name, all_concrete_types)
594671 }
595672 left_type: g.unwrap_generic (node.left_type)
596- receiver_type: g. unwrap_generic (node. receiver_type)
673+ receiver_type: receiver_type
597674 return_type: g.unwrap_generic (node.return_type)
598675 return_type_generic: ast.no_type
599676 fn_var_type: g.unwrap_generic (node.fn_var_type)
@@ -611,6 +688,13 @@ pub fn (mut g Generics) expr(mut node ast.Expr) ast.Expr {
611688 arg.expr = g.expr (mut arg.expr)
612689 }
613690 node.or_block = g.expr (mut node.or_block) as ast.OrExpr
691+ if node.is_method && g.table.sym (node.receiver_type).info is ast.Alias {
692+ // Workaround needed for markused
693+ unaliased_type := g.table.unaliased_type (g.unwrap_generic (node.receiver_type))
694+ if g.table.sym (unaliased_type).has_method (node.name) {
695+ node.receiver_type = unaliased_type
696+ }
697+ }
614698 if node.receiver_type.has_flag (.generic) {
615699 node.receiver_type = node.receiver_type.clear_flag (.generic)
616700 }
@@ -916,7 +1000,7 @@ pub fn (mut g Generics) expr(mut node ast.Expr) ast.Expr {
9161000 ast.MatchExpr {
9171001 if g.cur_concrete_types.len > 0 {
9181002 mut branches := node.branches.clone ()
919- for mut branch in node. branches {
1003+ for mut branch in branches {
9201004 branch.stmts = branch.stmts.clone ()
9211005 branch.exprs = branch.exprs.clone ()
9221006 branch.exprs = g.exprs (mut branch.exprs)
0 commit comments