~mna/snow

52bcc1d48284779e83bf6179de04b9b4f87828a6 — Martin Angers 1 year, 8 months ago 2f3d3e4 wip-struct-generics
pkg/codegen: fix the complex generic struct case
M pkg/codegen/mangle.go => pkg/codegen/mangle.go +10 -15
@@ 94,16 94,13 @@ func mangle(unit *semantic.Unit) *nameResolver {
		return true
	})

	genNames := make(map[*semantic.GenericInst]string)
	typesSets := make(map[semantic.Decl][][]semantic.Type)
	return &nameResolver{names: names, genNames: genNames, typesSets: typesSets}
	return &nameResolver{names: names, typesSets: typesSets}
}

type nameResolver struct {
	// mangled names for declarations
	names map[semantic.Decl]string
	// mangled names for generic instantiations
	genNames map[*semantic.GenericInst]string
	// map of generic declaration to list of instantiation types, to mangle unique
	// names per identical instantiation.
	typesSets map[semantic.Decl][][]semantic.Type


@@ 117,27 114,25 @@ func (r *nameResolver) NameForDecl(n semantic.Decl) string {
	return nm
}

func (r *nameResolver) NameForStructType(st *semantic.StructType) string {
func (r *nameResolver) NameForStructType(st *semantic.StructType, resolve map[*semantic.GenericType]semantic.Type) string {
	if !st.Decl.IsGeneric() {
		return r.NameForDecl(st.Decl)
	}
	return r.NameForGenericDeclAndTypes(st.Decl, st.Inst)
	return r.NameForGenericDeclAndTypes(st.Decl, st.Inst, resolve)
}

func (r *nameResolver) NameForGenericInst(gi *semantic.GenericInst) string {
	if nm, ok := r.genNames[gi]; ok {
		return nm
	}

func (r *nameResolver) NameForGenericInst(gi *semantic.GenericInst, resolve map[*semantic.GenericType]semantic.Type) string {
	gd := gi.GenericDecl.Ref.(semantic.GenericDecl)
	_, insts := gd.GenInsts()
	types := insts[gi]

	r.genNames[gi] = r.NameForGenericDeclAndTypes(gd, types)
	return r.genNames[gi]
	return r.NameForGenericDeclAndTypes(gd, types, resolve)
}

func (r *nameResolver) NameForGenericDeclAndTypes(decl semantic.Decl, types []semantic.Type) string {
func (r *nameResolver) NameForGenericDeclAndTypes(decl semantic.Decl, types []semantic.Type, resolve map[*semantic.GenericType]semantic.Type) string {
	for i, typ := range types {
		types[i] = typ.ResolveGeneric(resolve)
	}

	var b fmtBuilder
	b.withPrefixFor(decl)
	typesID := r.idForGenericInst(decl, types)

M pkg/codegen/testdata/struct_complex_generic.snow => pkg/codegen/testdata/struct_complex_generic.snow +8 -3
@@ 17,10 17,15 @@ fn integer(i: int) -> int {

fn main() {
  var a = A[int, string] (bb: A.B[string](ffb: str), ffa: integer)
  println(a)
  println(a.bb.ffb("ok"))
  printiln(a.ffa(3))
}

@extern(import: "fmt", symbol: "Println")
fn println(v: A[int, string])
fn println(v: string)

#=x
@extern(import: "fmt", symbol: "Println")
fn printiln(v: int)

#=ok
#=3

A pkg/codegen/testdata/struct_complex_generic.snow.err => pkg/codegen/testdata/struct_complex_generic.snow.err +0 -0
A pkg/codegen/testdata/struct_complex_generic.snow.want => pkg/codegen/testdata/struct_complex_generic.snow.want +71 -0
@@ 0,0 1,71 @@
package main

import "fmt"

type _اAا0 struct {
	_اbb  _ا4اBا0
	_اffa func(
		int,
	) int
}

func _اAا0اnew(
	s _اAا0,
	m map[string]bool,
) _اAا0 {
	var r _اAا0
	if m["bb"] {
		r._اbb = s._اbb
	}
	if m["ffa"] {
		r._اffa = s._اffa
	}
	return r
}

func _اstr(
	s string,
) string {
	return s
}

func _اinteger(
	i int,
) int {
	return i
}

type _ا4اBا0 struct {
	_اffb func(
		string,
	) string
}

func _ا4اBا0اnew(
	s _ا4اBا0,
	m map[string]bool,
) _ا4اBا0 {
	var r _ا4اBا0
	if m["ffb"] {
		r._اffb = s._اffb
	}
	return r
}

func main() {
	var a _اAا0 = _اAا0اnew(_اAا0{_اbb: _ا4اBا0اnew(_ا4اBا0{_اffb: _اstr}, map[string]bool{"ffb": true}), _اffa: _اinteger}, map[string]bool{"bb": true, "ffa": true})
	_اprintln(a._اbb._اffb("ok"))
	_اprintiln(a._اffa(3))
}

func _اprintln(
	v string,
) {
	fmt.Println(v)
}

func _اprintiln(
	v int,
) {
	fmt.Println(v)
}

M pkg/codegen/translate.go => pkg/codegen/translate.go +3 -3
@@ 357,7 357,7 @@ func (t *translator) Visit(n semantic.Node) semantic.Visitor {

	case *semantic.GenericInst:
		// render this generic instantiation if not already rendered
		name := t.resolver.NameForGenericInst(n)
		name := t.resolver.NameForGenericInst(n, t.curGenInst)
		t.renderGenInst(n, name)
		t.generatedExpr = &goast.Ident{Name: name}



@@ 577,7 577,7 @@ func (t *translator) goTypeExprFor(T semantic.Type) goast.Expr {
		return st

	case *semantic.StructType:
		name := t.resolver.NameForStructType(T)
		name := t.resolver.NameForStructType(T, t.curGenInst)
		return &goast.Ident{Name: name}

	default:


@@ 674,7 674,7 @@ func (t *translator) callStructInit(c *semantic.Call) *goast.CallExpr {
	// The struct initializer has the signature (where S is the struct type):
	// func init(s S, m map[string]bool) S
	// The map m contains the labels (unmangled field names) set by the caller.
	strName := t.resolver.NameForStructType(semantic.AsStructType(c.Fun.Type()))
	strName := t.resolver.NameForStructType(semantic.AsStructType(c.Fun.Type()), t.curGenInst)
	ce := &goast.CallExpr{
		Fun:  &goast.Ident{Name: t.resolver.NameForStructInit(strName)},
		Args: make([]goast.Expr, 2),

M pkg/semantic/type.go => pkg/semantic/type.go +10 -8
@@ 17,8 17,10 @@ type Type interface {
	IdenticalTo(T Type) bool
	// Valid indicates if the type is valid. Unresolved types are invalid.
	Valid() bool
	// ResolveGeneric returns a Type where all generic types present in the
	// resolve map provided and resolved to their matching type.
	ResolveGeneric(map[*GenericType]Type) Type

	resolveGeneric(map[*GenericType]Type) Type
	fmt.Stringer
}



@@ 130,14 132,14 @@ func (u unresolvedType) AssignableTo(Type) bool                            { ret
func (u unresolvedType) IdenticalTo(T Type) bool                           { _, ok := T.(unresolvedType); return ok }
func (u unresolvedType) Valid() bool                                       { return false }
func (u unresolvedType) String() string                                    { return "unresolved" }
func (u unresolvedType) resolveGeneric(resolve map[*GenericType]Type) Type { return u }
func (u unresolvedType) ResolveGeneric(resolve map[*GenericType]Type) Type { return u }

// ========> implement Type for BasicType

func (b *BasicType) String() string                                    { return b.Kind.String() }
func (b *BasicType) IdenticalTo(T Type) bool                           { return IsBasicOfKind(T, b.Kind) }
func (b *BasicType) Valid() bool                                       { return b.Kind >= Void && b.Kind < kindEnd }
func (b *BasicType) resolveGeneric(resolve map[*GenericType]Type) Type { return b }
func (b *BasicType) ResolveGeneric(resolve map[*GenericType]Type) Type { return b }
func (b *BasicType) AssignableTo(T Type) bool {
	// implicit type coercion works when all values of the type can be
	// represented by the target type, i.e. the target is a superset


@@ 244,7 246,7 @@ func (s *SignatureType) Valid() bool {
	return true
}

func (s *SignatureType) resolveGeneric(resolve map[*GenericType]Type) Type {
func (s *SignatureType) ResolveGeneric(resolve map[*GenericType]Type) Type {
	var diff bool

	sigt := &SignatureType{


@@ 331,7 333,7 @@ func (t *TupleType) IdenticalTo(T Type) bool {
	return true
}

func (t *TupleType) resolveGeneric(resolve map[*GenericType]Type) Type {
func (t *TupleType) ResolveGeneric(resolve map[*GenericType]Type) Type {
	var diff bool

	tt := &TupleType{


@@ 394,7 396,7 @@ func (s *StructType) IdenticalTo(T Type) bool {
	return true
}

func (s *StructType) resolveGeneric(resolve map[*GenericType]Type) Type {
func (s *StructType) ResolveGeneric(resolve map[*GenericType]Type) Type {
	var diff bool
	strt := &StructType{
		Decl: s.Decl,


@@ 428,7 430,7 @@ func (s *StructType) typeOfSel(T Type) Type {
	if s.lookup == nil {
		s.lookup = makeGenericResolveMap(s.Decl.GenericParams, s.Inst)
	}
	return T.resolveGeneric(s.lookup)
	return T.ResolveGeneric(s.lookup)
}

func makeGenericResolveMap(gc *GenericClause, types []Type) map[*GenericType]Type {


@@ 445,7 447,7 @@ func makeGenericResolveMap(gc *GenericClause, types []Type) map[*GenericType]Typ
// ========> implement Type for GenericType

func (g *GenericType) String() string { return g.Name }
func (g *GenericType) resolveGeneric(resolve map[*GenericType]Type) Type {
func (g *GenericType) ResolveGeneric(resolve map[*GenericType]Type) Type {
	if newt := resolve[g]; newt != nil {
		return newt
	}

M pkg/semantic/typeassign_pass.go => pkg/semantic/typeassign_pass.go +1 -1
@@ 328,7 328,7 @@ func (t *typeassignVisitor) instantiateGeneric(gi *GenericInst, gen GenericDecl,
			gen.GenericInsts = make(map[*GenericInst][]Type)
		}
		gen.GenericInsts[gi] = types
		return gen.Type().resolveGeneric(resolve)
		return gen.Type().ResolveGeneric(resolve)
	case *Struct:
		if gen.GenericInsts == nil {
			gen.GenericInsts = make(map[*GenericInst][]Type)