123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415 |
- package checker
- import (
- "kumachan/loader"
- "kumachan/transformer/node"
- "strings"
- )
- type GenericType struct {
- Params [] string
- Value TypeVal
- Node node.Node
- UnionIndex uint
- }
- type TypeVal interface { TypeVal() }
- func (impl Union) TypeVal() {}
- type Union struct {
- SubTypes [] loader.Symbol
- }
- func (impl Boxed) TypeVal() {}
- type Boxed struct {
- InnerType Type
- Protected bool
- Opaque bool
- }
- func (impl Native) TypeVal() {}
- type Native struct {}
- type Type interface { CheckerType() }
- func (impl ParameterType) CheckerType() {}
- type ParameterType struct {
- Index uint
- BeingInferred bool
- }
- func (impl NamedType) CheckerType() {}
- type NamedType struct {
- Name loader.Symbol
- Args [] Type
- }
- func (impl AnonymousType) CheckerType() {}
- type AnonymousType struct {
- Repr TypeRepr
- }
- type TypeRepr interface { TypeRepr() }
- func (impl Unit) TypeRepr() {}
- type Unit struct {}
- func (impl Tuple) TypeRepr() {}
- type Tuple struct {
- Elements [] Type
- }
- func (impl Bundle) TypeRepr() {}
- type Bundle struct {
- Fields map[string] Field
- }
- type Field struct {
- Type Type
- Index uint
- }
- func (impl Func) TypeRepr() {}
- type Func struct {
- Input Type
- Output Type
- }
- func GetSubtypeIndex(u Union, sym loader.Symbol) (uint, bool) {
- for index, subtype := range u.SubTypes {
- if subtype == sym {
- return uint(index), true
- }
- }
- return BadIndex, false
- }
- type TypeDescContext struct {
- ParamNames [] string
- UseInferred bool
- InferredNames [] string
- InferredTypes map[uint] Type
- }
- func DescribeTypeWithParams(type_ Type, params []string) string {
- return DescribeType(type_, TypeDescContext {
- ParamNames: params,
- UseInferred: false,
- })
- }
- func DescribeType(type_ Type, ctx TypeDescContext) string {
- switch t := type_.(type) {
- case ParameterType:
- if ctx.UseInferred {
- var inferred_t, exists = ctx.InferredTypes[t.Index]
- if exists {
- return DescribeType(inferred_t, ctx)
- } else {
- return ctx.InferredNames[t.Index]
- }
- } else {
- return ctx.ParamNames[t.Index]
- }
- case NamedType:
- var buf strings.Builder
- if loader.IsPreloadCoreSymbol(t.Name) {
- buf.WriteString(t.Name.SymbolName)
- } else {
- buf.WriteString(t.Name.String())
- }
- if len(t.Args) > 0 {
- buf.WriteRune('[')
- for i, arg := range t.Args {
- buf.WriteString(DescribeType(arg, ctx))
- if i != len(t.Args)-1 {
- buf.WriteString(", ")
- }
- }
- buf.WriteRune(']')
- }
- return buf.String()
- case AnonymousType:
- switch r := t.Repr.(type) {
- case Unit:
- return "()"
- case Tuple:
- var buf strings.Builder
- buf.WriteRune('(')
- for i, el := range r.Elements {
- buf.WriteString(DescribeType(el, ctx))
- if i != len(r.Elements)-1 {
- buf.WriteString(", ")
- }
- }
- buf.WriteRune(')')
- return buf.String()
- case Bundle:
- var buf strings.Builder
- buf.WriteString("{ ")
- for name, field := range r.Fields {
- buf.WriteString(name)
- buf.WriteString(": ")
- buf.WriteString(DescribeType(field.Type, ctx))
- }
- buf.WriteString(" }")
- return buf.String()
- case Func:
- var buf strings.Builder
- buf.WriteString("lambda")
- buf.WriteString(DescribeType(r.Input, ctx))
- buf.WriteString(" ")
- buf.WriteString(DescribeType(r.Output, ctx))
- return buf.String()
- default:
- panic("impossible branch")
- }
- default:
- panic("impossible branch")
- }
- }
- func IsLocalType (type_ Type, mod string) bool {
- switch t := type_.(type) {
- case ParameterType:
- return false
- case NamedType:
- if t.Name.ModuleName == mod {
- return true
- } else {
- for _, arg := range t.Args {
- if IsLocalType(arg, mod) {
- return true
- }
- }
- return false
- }
- case AnonymousType:
- switch r := t.Repr.(type) {
- case Unit:
- return false
- case Tuple:
- for _, el := range r.Elements {
- if IsLocalType(el, mod) {
- return true
- }
- }
- return false
- case Bundle:
- for _, f := range r.Fields {
- if IsLocalType(f.Type, mod) {
- return true
- }
- }
- return false
- case Func:
- if IsLocalType(r.Input, mod) {
- return true
- }
- if IsLocalType(r.Output, mod) {
- return true
- }
- return false
- default:
- panic("impossible branch")
- }
- default:
- panic("impossible branch")
- }
- }
- func AreTypesOverloadUnsafe (type1 Type, type2 Type) bool {
- // Are type1 and type2 equal in the context of function overloading
- switch t1 := type1.(type) {
- case ParameterType:
- return true // rough comparison
- case NamedType:
- switch t2 := type2.(type) {
- case NamedType:
- if t1.Name == t2.Name {
- var L1 = len(t1.Args)
- var L2 = len(t2.Args)
- if L1 != L2 { panic("type registration went wrong") }
- var L = L1
- for i := 0; i < L; i += 1 {
- if !(AreTypesOverloadUnsafe(t1.Args[i], t2.Args[i])) {
- return false
- }
- }
- return true
- } else {
- return false
- }
- default:
- return false
- }
- case AnonymousType:
- switch t2 := type2.(type) {
- case AnonymousType:
- switch r1 := t1.Repr.(type) {
- case Unit:
- switch t2.Repr.(type) {
- case Unit:
- return true
- default:
- return false
- }
- case Tuple:
- switch r2 := t2.Repr.(type) {
- case Tuple:
- var L1 = len(r1.Elements)
- var L2 = len(r2.Elements)
- if L1 == L2 {
- var L = L1
- for i := 0; i < L; i += 1 {
- if !(AreTypesOverloadUnsafe(r1.Elements[i], r2.Elements[i])) {
- return false
- }
- }
- return true
- } else {
- return false
- }
- default:
- return false
- }
- case Bundle:
- switch r2 := t2.Repr.(type) {
- case Bundle:
- var L1 = len(r1.Fields)
- var L2 = len(r2.Fields)
- if L1 == L2 {
- for name, f1 := range r1.Fields {
- var f2, exists = r2.Fields[name]
- if !exists || !(AreTypesOverloadUnsafe(f1.Type, f2.Type)) {
- return false
- }
- }
- return true
- } else {
- return false
- }
- default:
- return false
- }
- case Func:
- switch r2 := t2.Repr.(type) {
- case Func:
- if !(AreTypesOverloadUnsafe(r1.Input, r2.Input)) {
- return false
- }
- if !(AreTypesOverloadUnsafe(r1.Output, r2.Output)) {
- return false
- }
- return true
- default:
- return true
- }
- default:
- panic("impossible branch")
- }
- default:
- return false
- }
- default:
- panic("impossible branch")
- }
- }
- func AreTypesEqualInSameCtx (type1 Type, type2 Type) bool {
- switch t1 := type1.(type) {
- case ParameterType:
- switch t2 := type2.(type) {
- case ParameterType:
- return t1.Index == t2.Index
- default:
- return false
- }
- case NamedType:
- switch t2 := type2.(type) {
- case NamedType:
- if t1.Name == t2.Name {
- var L1 = len(t1.Args)
- var L2 = len(t2.Args)
- if L1 != L2 { panic("type registration went wrong") }
- var L = L1
- for i := 0; i < L; i += 1 {
- if !(AreTypesEqualInSameCtx(t1.Args[i], t2.Args[i])) {
- return false
- }
- }
- return true
- } else {
- return false
- }
- default:
- return false
- }
- case AnonymousType:
- switch t2 := type2.(type) {
- case AnonymousType:
- switch r1 := t1.Repr.(type) {
- case Unit:
- switch t2.Repr.(type) {
- case Unit:
- return true
- default:
- return false
- }
- case Tuple:
- switch r2 := t2.Repr.(type) {
- case Tuple:
- var L1 = len(r1.Elements)
- var L2 = len(r2.Elements)
- if L1 == L2 {
- var L = L1
- for i := 0; i < L; i += 1 {
- if !(AreTypesEqualInSameCtx(r1.Elements[i], r2.Elements[i])) {
- return false
- }
- }
- return true
- } else {
- return false
- }
- default:
- return false
- }
- case Bundle:
- switch r2 := t2.Repr.(type) {
- case Bundle:
- var L1 = len(r1.Fields)
- var L2 = len(r2.Fields)
- if L1 == L2 {
- for name, f1 := range r1.Fields {
- var f2, exists = r2.Fields[name]
- if !exists || !(AreTypesEqualInSameCtx(f1.Type, f2.Type)) {
- return false
- }
- }
- return true
- } else {
- return false
- }
- default:
- return false
- }
- case Func:
- switch r2 := t2.Repr.(type) {
- case Func:
- if !(AreTypesEqualInSameCtx(r1.Input, r2.Input)) {
- return false
- }
- if !(AreTypesEqualInSameCtx(r1.Output, r2.Output)) {
- return false
- }
- return true
- default:
- return true
- }
- default:
- panic("impossible branch")
- }
- default:
- return false
- }
- default:
- panic("impossible branch")
- }
- }
|