Skip to content

Commit 52499f7

Browse files
committed
fix: check types exist #74
1 parent 8a6e7c3 commit 52499f7

File tree

4 files changed

+156
-12
lines changed

4 files changed

+156
-12
lines changed

environment/environment.go

+1
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ func makeTypeKey(pkg, name string) string {
223223
}
224224

225225
func (e *Environment) GetType(pkg, name string) (Type, bool) {
226+
e.LoadPackageTypes(pkg)
226227
obj, ok := e.types[makeTypeKey(pkg, name)]
227228
if !ok && e.outer != nil {
228229
obj, ok = e.outer.GetType(pkg, name)

walker/types.go

+19
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,25 @@ type Function struct {
1313
arguments []ast.Types
1414
}
1515

16+
func (w *Walker) typesExist(types ast.Types) (*ast.Type, bool) {
17+
for _, t := range types {
18+
// bit hacky but NA, NULL, etc. have a blank type
19+
// need to fix upstream in parser
20+
if t.Name == "" {
21+
return nil, true
22+
}
23+
24+
_, te := w.env.GetType(t.Package, t.Name)
25+
_, fe := w.env.GetSignature(t.Name)
26+
27+
if !te && !fe {
28+
return t, false
29+
}
30+
}
31+
32+
return nil, true
33+
}
34+
1635
func (w *Walker) allTypesIdentical(types []*ast.Type) bool {
1736
if len(types) == 0 {
1837
return true

walker/walk.go

+106-6
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,19 @@ func (w *Walker) walkKnownCallTypeFactorExpression(node *ast.CallExpression, t e
300300
for _, v := range node.Arguments {
301301
at, _ := w.Walk(v.Value)
302302
w.checkIfIdentifier(v.Value)
303-
ok := w.typesValid(t.Type, at)
303+
304+
missingType, ok := w.typesExist(t.Type)
305+
306+
if !ok {
307+
w.addFatalf(
308+
node.Token,
309+
"type `%v` is not declared",
310+
missingType,
311+
)
312+
continue
313+
}
314+
315+
ok = w.typesValid(t.Type, at)
304316

305317
if !ok {
306318
w.addFatalf(
@@ -329,7 +341,18 @@ func (w *Walker) walkKnownCallTypeVectorExpression(node *ast.CallExpression, t e
329341
for _, v := range node.Arguments {
330342
at, _ := w.Walk(v.Value)
331343
w.checkIfIdentifier(v.Value)
332-
ok := w.typesValid(t.Type, at)
344+
missingType, ok := w.typesExist(t.Type)
345+
346+
if !ok {
347+
w.addFatalf(
348+
node.Token,
349+
"type `%v` is not declared",
350+
missingType,
351+
)
352+
continue
353+
}
354+
355+
ok = w.typesValid(t.Type, at)
333356

334357
if !ok {
335358
w.addFatalf(
@@ -357,7 +380,18 @@ func (w *Walker) walkKnownCallTypeVectorExpression(node *ast.CallExpression, t e
357380
func (w *Walker) walkKnownCallTypeListExpression(node *ast.CallExpression, t environment.Type) (ast.Types, ast.Node) {
358381
for _, v := range node.Arguments {
359382
at, _ := w.Walk(v.Value)
360-
ok := w.typesValid(t.Type, at)
383+
missingType, ok := w.typesExist(at)
384+
385+
if !ok {
386+
w.addFatalf(
387+
node.Token,
388+
"type `%v` is not declared",
389+
missingType,
390+
)
391+
continue
392+
}
393+
394+
ok = w.typesValid(t.Type, at)
361395

362396
if !ok {
363397
w.addFatalf(
@@ -403,7 +437,18 @@ func (w *Walker) walkKnownCallTypeStructExpression(node *ast.CallExpression, t e
403437
}
404438

405439
if i == 0 {
406-
ok := w.typesValid(t.Type, at)
440+
missingType, ok := w.typesExist(t.Type)
441+
442+
if !ok {
443+
w.addFatalf(
444+
node.Token,
445+
"type `%v` is not declared",
446+
missingType,
447+
)
448+
continue
449+
}
450+
451+
ok = w.typesValid(t.Type, at)
407452
if !ok {
408453
w.addFatalf(
409454
node.Token,
@@ -561,6 +606,17 @@ func (w *Walker) walkKnownCallExpression(node *ast.CallExpression, fn *ast.Funct
561606
param, _ = getFunctionElipsis(fn.Parameters)
562607
}
563608

609+
missingType, ok := w.typesExist(param.Type)
610+
611+
if !ok {
612+
w.addFatalf(
613+
param.Token,
614+
"type `%v` is not declared",
615+
missingType,
616+
)
617+
continue
618+
}
619+
564620
ok = w.typesValid(param.Type, argumentType)
565621

566622
if !ok && argument.Name == "" {
@@ -1054,7 +1110,19 @@ func (w *Walker) walkInfixExpressionEqual(node *ast.InfixExpression) (ast.Types,
10541110
}
10551111

10561112
rt, rn := w.Walk(node.Right)
1057-
ok := w.typesValid(lt, rt)
1113+
missingType, ok := w.typesExist(rt)
1114+
1115+
if !ok {
1116+
w.addFatalf(
1117+
rn.Item(),
1118+
"type `%v` is not declared",
1119+
missingType,
1120+
)
1121+
1122+
return rt, rn
1123+
}
1124+
1125+
ok = w.typesValid(lt, rt)
10581126
if !ok {
10591127
w.addFatalf(
10601128
node.Token,
@@ -1115,7 +1183,28 @@ func (w *Walker) walkLetStatement(node *ast.LetStatement) (ast.Types, ast.Node)
11151183
},
11161184
)
11171185

1186+
t, ok := w.typesExist(node.Type)
1187+
1188+
if !ok {
1189+
w.addFatalf(
1190+
node.Token,
1191+
"type `%v` is not declared",
1192+
t,
1193+
)
1194+
}
1195+
11181196
rt, rn := w.Walk(node.Value)
1197+
missingType, ok := w.typesExist(rt)
1198+
1199+
if !ok {
1200+
w.addFatalf(
1201+
rn.Item(),
1202+
"type `%v` is not declared",
1203+
missingType,
1204+
)
1205+
return rt, rn
1206+
}
1207+
11191208
ok = w.typesValid(node.Type, rt)
11201209

11211210
if !ok {
@@ -1177,7 +1266,18 @@ func (w *Walker) walkReturnStatement(node *ast.ReturnStatement) (ast.Types, ast.
11771266
w.checkIfIdentifier(n)
11781267

11791268
if w.env.ReturnType() != nil {
1180-
ok := w.typesValid(w.env.ReturnType(), t)
1269+
missingType, ok := w.typesExist(w.env.ReturnType())
1270+
1271+
if !ok {
1272+
w.addFatalf(
1273+
node.Token,
1274+
"type `%v` is not declared",
1275+
missingType,
1276+
)
1277+
return t, node
1278+
}
1279+
1280+
ok = w.typesValid(w.env.ReturnType(), t)
11811281
if !ok {
11821282
w.addFatalf(
11831283
node.Token,

walker/walk_test.go

+30-6
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,7 @@ func (p: any) meth(): null {}
509509
}
510510

511511
func TestBasic(t *testing.T) {
512-
code := `let x: int | na = 1
512+
code := `let x: int = 1
513513
514514
x = 2
515515
@@ -1216,17 +1216,14 @@ func TestEnvironment(t *testing.T) {
12161216
code := `
12171217
let z: int = 1
12181218
1219-
func addz(n: int = 1, y: int = 2): int | na {
1219+
func addz(n: int = 1, y: int = 2): int {
12201220
if(n == 1){
12211221
return NA
12221222
}
12231223
12241224
return n + y + z
12251225
}
12261226
1227-
# should fail, this can be na
1228-
let result: int = addz(1, 2)
1229-
12301227
# should fail, comparing wrong types
12311228
if (1 == "hello") {
12321229
print("1")
@@ -1256,7 +1253,6 @@ print(c)
12561253
w.Run(prog)
12571254

12581255
expected := diagnostics.Diagnostics{
1259-
{Severity: diagnostics.Fatal},
12601256
{Severity: diagnostics.Info},
12611257
{Severity: diagnostics.Fatal},
12621258
}
@@ -1356,3 +1352,31 @@ e(x = true)
13561352

13571353
w.testDiagnostics(t, expected)
13581354
}
1355+
1356+
func TestSymbols(t *testing.T) {
1357+
code := `
1358+
# should fail, type does not exist
1359+
let foo: bar = baz
1360+
1361+
# should fail, baz not found
1362+
foo = baz`
1363+
1364+
l := lexer.NewTest(code)
1365+
1366+
l.Run()
1367+
p := parser.New(l)
1368+
1369+
prog := p.Run()
1370+
1371+
environment.SetLibrary(r.LibPath())
1372+
w := New()
1373+
1374+
w.Run(prog)
1375+
1376+
expected := diagnostics.Diagnostics{
1377+
{Severity: diagnostics.Fatal},
1378+
{Severity: diagnostics.Warn},
1379+
}
1380+
1381+
w.testDiagnostics(t, expected)
1382+
}

0 commit comments

Comments
 (0)