-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathinferrer.go
161 lines (149 loc) · 4.41 KB
/
inferrer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
package main
// Inferer infers types
type Inferrer interface {
infer()
}
func inferTypes(globals []*ExprVariable, locals []Inferrer) {
//debugf(S("infering globals"))
for _, variable := range globals {
variable.infer()
}
//debugf(S("infering locals"))
for _, ast := range locals {
ast.infer()
}
}
// infer recursively all the types of global variables
func (variable *ExprVariable) infer() {
//debugf(S("infering ExprVariable"))
if variable.gtype.kind != G_DEPENDENT {
// done
return
}
e := variable.gtype.dependendson
dependType := e.getGtype()
if dependType.kind != G_DEPENDENT {
variable.gtype = dependType
return
}
rel, ok := e.(*Relation)
if !ok {
errorft(e.token(), "unexpected type %T", e)
}
vr, ok := rel.expr.(*ExprVariable)
vr.infer() // recursive call
variable.gtype = e.getGtype()
//debugf(S("infered type=%s"), variable.gtype)
}
// local decl infer
func (decl *DeclVar) infer() {
//debugf(S("infering DeclVar"))
gtype := decl.initval.getGtype()
assertNotNil(gtype != nil, decl.initval.token())
decl.variable.gtype = gtype
}
func (clause *ForRangeClause) infer() {
//debugf(S("infering ForRangeClause"))
collectionType := clause.rangeexpr.getGtype()
//debugf(S("collectionType = %s"), collectionType)
indexvarRel, ok := clause.indexvar.(*Relation)
assert(ok, nil, "ok")
indexvar, ok := indexvarRel.expr.(*ExprVariable)
assert(ok, nil, "ok")
var indexType *Gtype
switch collectionType.getKind() {
case G_ARRAY, G_SLICE:
indexType = gInt
case G_MAP:
indexType = collectionType.Underlying().mapKey
default:
// @TODO consider map etc.
TBI(clause.tok, "unable to handle %d ", collectionType.getKind())
}
indexvar.gtype = indexType
if clause.valuevar != nil {
valuevarRel, ok := clause.valuevar.(*Relation)
assert(ok, nil, "ok")
valuevar, ok := valuevarRel.expr.(*ExprVariable)
assert(ok, nil, "ok")
var elementType *Gtype
if collectionType.getKind() == G_ARRAY {
elementType = collectionType.Underlying().elementType
} else if collectionType.getKind() == G_SLICE {
elementType = collectionType.Underlying().elementType
} else if collectionType.getKind() == G_MAP {
elementType = collectionType.Underlying().mapValue
} else {
errorft(clause.token(), "internal error")
}
//debugf(S("for i, v %s := rannge %v"), elementType, collectionType)
valuevar.gtype = elementType
}
}
func (ast *StmtShortVarDecl) infer() {
//debugf(S("infering StmtShortVarDecl"))
var rightTypes []*Gtype
for _, rightExpr := range ast.rights {
switch rightExpr.(type) {
case *ExprFuncallOrConversion:
fcallOrConversion := rightExpr.(*ExprFuncallOrConversion)
if fcallOrConversion.rel.gtype != nil {
// Conversion
rightTypes = append(rightTypes, fcallOrConversion.rel.gtype)
} else {
fcall := fcallOrConversion
funcdef := fcall.getFuncDef()
if funcdef == nil {
errorft(fcall.token(), "funcdef of %s is not found", fcall.fname)
}
if funcdef == builtinLen {
rightTypes = append(rightTypes, gInt)
} else {
for _, gtype := range fcall.getFuncDef().rettypes {
rightTypes = append(rightTypes, gtype)
}
}
}
case *ExprMethodcall:
fcall := rightExpr.(*ExprMethodcall)
rettypes := fcall.getRettypes()
for _, gtype := range rettypes {
rightTypes = append(rightTypes, gtype)
}
case *ExprTypeAssertion:
assertion := rightExpr.(*ExprTypeAssertion)
rightTypes = append(rightTypes, assertion.gtype)
rightTypes = append(rightTypes, gBool)
case *ExprIndex:
e := rightExpr.(*ExprIndex)
gtype := e.getGtype()
assertNotNil(gtype != nil, e.tok)
rightTypes = append(rightTypes, gtype)
//debugf(S("rightExpr.gtype=%s"), gtype)
secondGtype := rightExpr.(*ExprIndex).getSecondGtype()
if secondGtype != nil {
rightTypes = append(rightTypes, secondGtype)
}
default:
if rightExpr == nil {
errorft(ast.token(), "rightExpr is nil")
}
gtype := rightExpr.getGtype()
if gtype == nil {
errorft(ast.token(), "rightExpr %T gtype is nil", rightExpr)
}
//debugf(S("infered type %s"), gtype)
rightTypes = append(rightTypes, gtype)
}
}
if len(ast.lefts) > len(rightTypes) {
// @TODO this check is too loose.
errorft(ast.tok, "number of lhs and rhs does not match (%d <=> %d)", len(ast.lefts), len(rightTypes))
}
for i, e := range ast.lefts {
rel := e.(*Relation) // a brand new rel
variable := rel.expr.(*ExprVariable)
rightType := rightTypes[i]
variable.gtype = rightType
}
}