Skip to content

Commit f02493f

Browse files
committed
check for naming errors earlier so later steps don't fail. fixes #815
1 parent ce54d3d commit f02493f

File tree

3 files changed

+75
-51
lines changed

3 files changed

+75
-51
lines changed

src/arr/compiler/compile-lib.arr

+59-51
Original file line numberDiff line numberDiff line change
@@ -384,62 +384,70 @@ fun compile-module(locator :: Locator, provide-map :: SD.StringDict<CS.Provides>
384384
imported := nothing
385385
add-phase("Desugared scope", scoped)
386386
var named-result = RS.resolve-names(scoped.ast, env)
387-
var any-errors = scoped.errors
387+
var any-errors = scoped.errors + named-result.errors
388388
scoped := nothing
389-
add-phase("Resolved names", named-result)
390-
var provides = AU.get-named-provides(named-result, locator.uri(), env)
391-
# Once name resolution has happened, any newly-created s-binds must be added to bindings...
392-
var desugared = D.desugar(named-result.ast)
393-
named-result.bindings.merge-now(desugared.new-binds)
394-
# ...in order to be checked for bad assignments here
395-
any-errors := any-errors + named-result.errors
396-
+ RS.check-unbound-ids-bad-assignments(desugared.ast, named-result, env)
397-
add-phase("Fully desugared", desugared.ast)
398-
var type-checked =
399-
if options.type-check:
400-
type-checked = T.type-check(desugared.ast, env, modules)
401-
if CS.is-ok(type-checked) block:
402-
provides := AU.get-typed-provides(type-checked.code, locator.uri(), env)
403-
CS.ok(type-checked.code.ast)
389+
if is-link(any-errors) block:
390+
{ module-as-string(dummy-provides(locator.uri()), env, CS.err(any-errors));
391+
if options.collect-all or options.collect-times:
392+
phase("Result", named-result.ast, time-now(), ret).tolist()
404393
else:
405-
type-checked
406-
end
407-
else: CS.ok(desugared.ast)
408-
end
409-
desugared := nothing
410-
add-phase("Type Checked", type-checked)
411-
cases(CS.CompileResult) type-checked block:
412-
| ok(_) =>
413-
var tc-ast = type-checked.code
414-
type-checked := nothing
415-
var dp-ast = DP.desugar-post-tc(tc-ast, env)
416-
tc-ast := nothing
417-
var cleaned = dp-ast
418-
dp-ast := nothing
419-
cleaned := cleaned.visit(AU.letrec-visitor)
420-
.visit(AU.inline-lams)
421-
.visit(AU.set-recursive-visitor)
422-
.visit(AU.set-tail-visitor)
423-
add-phase("Cleaned AST", cleaned)
424-
{final-provides; cr} = if is-empty(any-errors):
425-
JSP.trace-make-compiled-pyret(add-phase, cleaned, env, named-result.bindings, provides, options)
426-
else:
427-
if options.collect-all and options.ignore-unbound:
428-
JSP.trace-make-compiled-pyret(add-phase, cleaned, env, options)
394+
empty
395+
end }
396+
else:
397+
add-phase("Resolved names", named-result)
398+
var provides = AU.get-named-provides(named-result, locator.uri(), env)
399+
# Once name resolution has happened, any newly-created s-binds must be added to bindings...
400+
var desugared = D.desugar(named-result.ast)
401+
named-result.bindings.merge-now(desugared.new-binds)
402+
# ...in order to be checked for bad assignments here
403+
any-errors := RS.check-unbound-ids-bad-assignments(desugared.ast, named-result, env)
404+
add-phase("Fully desugared", desugared.ast)
405+
var type-checked =
406+
if options.type-check:
407+
type-checked = T.type-check(desugared.ast, env, modules)
408+
if CS.is-ok(type-checked) block:
409+
provides := AU.get-typed-provides(type-checked.code, locator.uri(), env)
410+
CS.ok(type-checked.code.ast)
429411
else:
430-
{provides; add-phase("Result", CS.err(any-errors))}
412+
type-checked
431413
end
414+
else: CS.ok(desugared.ast)
432415
end
433-
cleaned := nothing
434-
canonical-provides = AU.canonicalize-provides(final-provides, env)
435-
mod-result = module-as-string(canonical-provides, env, cr)
436-
{mod-result; if options.collect-all or options.collect-times: ret.tolist() else: empty end}
437-
| err(_) =>
438-
{ module-as-string(dummy-provides(locator.uri()), env, type-checked);
439-
if options.collect-all or options.collect-times:
440-
phase("Result", type-checked, time-now(), ret).tolist()
441-
else: empty
442-
end }
416+
desugared := nothing
417+
add-phase("Type Checked", type-checked)
418+
cases(CS.CompileResult) type-checked block:
419+
| ok(_) =>
420+
var tc-ast = type-checked.code
421+
type-checked := nothing
422+
var dp-ast = DP.desugar-post-tc(tc-ast, env)
423+
tc-ast := nothing
424+
var cleaned = dp-ast
425+
dp-ast := nothing
426+
cleaned := cleaned.visit(AU.letrec-visitor)
427+
.visit(AU.inline-lams)
428+
.visit(AU.set-recursive-visitor)
429+
.visit(AU.set-tail-visitor)
430+
add-phase("Cleaned AST", cleaned)
431+
{final-provides; cr} = if is-empty(any-errors):
432+
JSP.trace-make-compiled-pyret(add-phase, cleaned, env, named-result.bindings, provides, options)
433+
else:
434+
if options.collect-all and options.ignore-unbound:
435+
JSP.trace-make-compiled-pyret(add-phase, cleaned, env, options)
436+
else:
437+
{provides; add-phase("Result", CS.err(any-errors))}
438+
end
439+
end
440+
cleaned := nothing
441+
canonical-provides = AU.canonicalize-provides(final-provides, env)
442+
mod-result = module-as-string(canonical-provides, env, cr)
443+
{mod-result; if options.collect-all or options.collect-times: ret.tolist() else: empty end}
444+
| err(_) =>
445+
{ module-as-string(dummy-provides(locator.uri()), env, type-checked);
446+
if options.collect-all or options.collect-times:
447+
phase("Result", type-checked, time-now(), ret).tolist()
448+
else: empty
449+
end }
450+
end
443451
end
444452
| err(_) =>
445453
{ module-as-string(dummy-provides(locator.uri()), env, wf) ;

tests/pyret/regression.arr

+1
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@ import file("./regression/string-dict-equality.arr") as _
1717
import file("./regression/stack-safe-each-loop.arr") as _
1818
import file("./regression/proto-fields.arr") as _
1919
import file("./regression/toplevel-data.arr") as _
20+
import file("./regression/bogus-global-type-name.arr") as _
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import file("../test-compile-helper.arr") as C
2+
import file("../../../src/arr/compiler/compile-structs.arr") as CS
3+
4+
run-str = C.run-str
5+
output = C.output
6+
compile-error = C.compile-error
7+
8+
check "https://github.com/brownplt/pyret-lang/issues/815":
9+
run-str("x :: Bool = true")
10+
is%(output) compile-error(CS.is-unbound-type-id)
11+
run-str("fun f(x :: Bool): x end")
12+
is%(output) compile-error(CS.is-unbound-type-id)
13+
run-str("x :: { y :: Num } = {y: 5}")
14+
is%(output) compile-error(CS.is-unbound-type-id)
15+
end

0 commit comments

Comments
 (0)