Skip to content

Commit 67b574a

Browse files
committed
More fixes (placeholders, tryfinally, some error msgs)
1 parent 8fcc8a1 commit 67b574a

File tree

2 files changed

+40
-30
lines changed

2 files changed

+40
-30
lines changed

src/validation.jl

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,10 @@ vst1_value(vcx::Validation1Context, st::SyntaxTree; need_value=true) = @stm st b
129129
[K".op=" l op r] -> vst1_dotassign_lhs(vcx, l) & vst1_ident(vcx, op) & vst1_value(vcx, r)
130130

131131
[K"function" _...] -> !vcx.inner_cond ? vst1_function(vcx, st) :
132-
fail(vcx, st, "conditional inner method definitions are not supported; use `()->()` syntax instead")
132+
# fail(vcx, st, "conditional inner method definitions are not supported; use `()->()` syntax instead")
133+
# lowering TODO: conditional nested function definitions are known to be
134+
# broken, but are not disallowed, and can be found in stdlibs.
135+
vst1_function(vcx, st)
133136
[K"call" _...] -> vst1_call(vcx, st)
134137
[K"dotcall" _...] -> vst1_dotcall(vcx, st)
135138
[K"return"] -> vcx.return_ok || fail(vcx, st, "`return` not allowed inside comprehension or generator")
@@ -223,6 +226,9 @@ vst1_value(vcx::Validation1Context, st::SyntaxTree; need_value=true) = @stm st b
223226
[K"cfunction" t fptr [K"static_eval" rt] [K"static_eval" argt_svec] [K"Symbol"]] ->
224227
vst1_value(vcx, t) & vst1_value(vcx, fptr) &
225228
vst1_value(vcx, rt) & vst1_value(vcx, argt_svec)
229+
# syntax TODO: lowering-internal form used to remove scope from try blocks.
230+
# probably shouldn't be allowed.
231+
[K"tryfinally" t f _...] -> vst1_value(vcx, t) & vst1_value(vcx, f)
226232

227233
# Only from macro expansions producing Expr(:toplevel, ...). We don't want
228234
# to recurse on the contained expression since `K"escape"` can wrap nearly
@@ -376,7 +382,7 @@ vst1_try(vcx, st) = @stm st begin
376382
[K"try" _] -> fail(vcx, st, "try without catch or finally")
377383
[K"try" b1 [K"catch" err body2...]] ->
378384
vst1_block(vcx, b1) &
379-
vst1_ident_lhs(vcx, err) &
385+
vst1_ident(vcx, err; lhs=true) &
380386
allv(vst1_stmt, vcx, body2)
381387
[K"try" b1 [K"else" body3...]] ->
382388
fail(vcx, st, "try without catch or finally")
@@ -385,20 +391,20 @@ vst1_try(vcx, st) = @stm st begin
385391
allv(vst1_stmt, vcx, body4)
386392
[K"try" b1 [K"catch" err body2...] [K"else" body3...]] ->
387393
vst1_block(vcx, b1) &
388-
vst1_ident_lhs(vcx, err) &
394+
vst1_ident(vcx, err; lhs=true) &
389395
allv(vst1_stmt, vcx, body2) &
390396
allv(vst1_stmt, vcx, body3)
391397
[K"try" b1 [K"catch" err body2...] [K"finally" body4...]] ->
392398
vst1_block(vcx, b1) &
393-
vst1_ident_lhs(vcx, err) &
399+
vst1_ident(vcx, err; lhs=true) &
394400
allv(vst1_stmt, vcx, body2) &
395401
allv(vst1_stmt, vcx, body4)
396402
[K"try" b1 [K"else" body3...] [K"finally" body4...]] ->
397403
vst1_block(vcx, b1) &
398404
allv(vst1_stmt, vcx, body4)
399405
[K"try" b1 [K"catch" err body2...] [K"else" body3...] [K"finally" body4...]] ->
400406
vst1_block(vcx, b1) &
401-
vst1_ident_lhs(vcx, err) &
407+
vst1_ident(vcx, err; lhs=true) &
402408
allv(vst1_stmt, vcx, body2) &
403409
allv(vst1_stmt, vcx, body3) &
404410
allv(vst1_stmt, vcx, body4)
@@ -428,10 +434,15 @@ vst1_dotpath(vcx, st) = @stm st begin
428434
lhs -> vst1_ident(vcx, lhs)
429435
end
430436

431-
vst1_dot_rhs(vcx, st) = (vcx.unexpanded ?
432-
kind(st) === K"Identifier" : kind(st) === K"Symbol") ||
433-
kind(st) === K"string" || # syntax TODO: disallow
434-
fail(vcx, st, "`(. a b)` requires symbol `b` after macro-expansion, or identifier before")
437+
# syntax TODO: all-underscore variables may be read from with dot syntax
438+
vst1_dot_rhs(vcx, st; lhs=false) = @stm st begin
439+
[K"Symbol"] -> true
440+
[K"Identifier"] -> vcx.unexpanded ||
441+
fail(vcx, st, "Identifier not valid on dot rhs after macro expansion")
442+
[K"string" _...] -> true # syntax TODO: disallow
443+
[K"core"] -> fail(vcx, st, "this is a reserved identifier")
444+
_ -> fail(vcx, st, "`a.b` requires symbol `b`")
445+
end
435446

436447
cst1_assign(vcx, st) = @stm st begin
437448
[K"=" l r] -> vst1_assign_lhs(vcx, l) & vst1_value(vcx, r)
@@ -443,29 +454,26 @@ end
443454
vst1_symdecl_or_assign(vcx, st) = cst1_assign(vcx, st) || vst1_symdecl(vcx, st)
444455

445456
vst1_symdecl(vcx, st) = @stm st begin
446-
(_, when=cst1_ident(vcx, st)) -> true
447-
[K"::" [K"Identifier"] t] -> vst1_value(vcx, t)
457+
(_, when=cst1_ident(vcx, st; lhs=true)) -> true
458+
[K"::" id t] -> vst1_ident(vcx, t; lhs=true) & vst1_value(vcx, t)
448459
_ -> fail(vcx, st, "expected identifier or `::`")
449460
end
450461

451462
# ast TODO: Omit the `var` container at the parser level. This would let us
452463
# delete these entirely and just match [K"Identifier"] instead.
453464
# TODO: A K"Value" globalref is often OK in place of an identifier; check usage
454465
# of this function
455-
vst1_ident(vcx, st) =
456-
cst1_ident(vcx, st) || fail(vcx, st, "expected identifier, got `$(kind(st))`")
457-
cst1_ident(vcx, st) = @stm st begin
466+
vst1_ident(vcx, st; lhs=false) =
467+
cst1_ident(vcx, st; lhs) || fail(vcx, st, "expected identifier, got `$(kind(st))`")
468+
cst1_ident(vcx, st; lhs=false) = @stm st begin
458469
[K"Identifier"] -> true
459470
[K"var" [K"Identifier"]] -> vcx.unexpanded ? true :
460471
fail(vcx, st, "`var` container not valid after macro expansion")
472+
[K"Placeholder"] -> lhs ||
473+
fail(vcx, st, "all-underscore identifiers are write-only and their values cannot be used in expressions")
461474
_ -> false
462475
end
463476

464-
vst1_ident_lhs(vcx, st) = @stm st begin
465-
[K"Placeholder"] -> true
466-
_ -> vst1_ident(vcx, st)
467-
end
468-
469477
# no kws in macrocalls, but `do` is OK.
470478
# TODO: we move `do` between st0 and st1...
471479
vst1_call(vcx, st) = @stm st begin
@@ -619,6 +627,8 @@ vst1_macro(vcx, st) = @stm st begin
619627
_calldecl_positionals(vcx, ps) &
620628
vst1_block(with(vcx; return_ok=true), body)
621629
end
630+
[K"macro" [K"where" _...] _...] ->
631+
fail(vcx, st[1], "`where` not allowed in macro signatures")
622632
end
623633

624634
vst1_macro_calldecl_name(vcx, st) = @stm st begin
@@ -682,21 +692,21 @@ vst1_param_req_or_tuple(vcx, st) = @stm st begin
682692
end
683693

684694
vst1_simple_tuple_lhs(vcx, st) = @stm st begin
685-
[K"tuple" [K"parameters" kws...]] -> allv(vst1_ident_lhs, vcx, kws)
695+
[K"tuple" [K"parameters" kws...]] -> allv(vst1_ident, vcx, kws; lhs=true)
686696
[K"tuple" xs...] -> allv(vst1_simple_tuple_lhs, vcx, xs)
687-
_ -> vst1_ident_lhs(vcx, st)
697+
_ -> vst1_ident(vcx, st; lhs=true)
688698
end
689699

690700
vst1_param_req(vcx, st) = @stm st begin
691-
(_, when=vst1_ident_lhs(with(vcx; speculative=true), st)) -> true
692-
[K"::" x t] -> vst1_ident_lhs(vcx, x) & vst1_value(vcx, t)
701+
(_, when=vst1_ident(with(vcx; speculative=true), st; lhs=true)) -> true
702+
[K"::" x t] -> vst1_ident(vcx, x; lhs=true) & vst1_value(vcx, t)
693703
[K"::" t] -> vst1_value(vcx, t)
694-
_ -> fail(vcx, st, "malformed positional param; expected identifier or `::`")
704+
_ -> fail(vcx, st, "expected identifier or `::`")
695705
end
696706

697707
vst1_param_opt(vcx, st) = @stm st begin
698708
[K"=" id val] -> vst1_param_req_or_tuple(vcx, id) & vst1_value(vcx, val)
699-
_ -> fail(vcx, st, "malformed optional positional param; expected `=`")
709+
_ -> fail(vcx, st, "malformed optional positional parameter; expected `=`")
700710
end
701711

702712
vst1_calldecl_kws(vcx, st) = @stm st begin
@@ -706,8 +716,8 @@ vst1_calldecl_kws(vcx, st) = @stm st begin
706716
end
707717

708718
vst1_param_kw(vcx, st) = @stm st begin
709-
(_, when=vst1_symdecl(with(vcx; speculative=true), st)) -> true
710-
[K"=" id val] -> vst1_symdecl(vcx, id) & vst1_value(vcx, val)
719+
[K"=" id val] -> vst1_param_req(vcx, id) & vst1_value(vcx, val)
720+
(_, when=vst1_param_req(with(vcx; speculative=true), st)) -> true
711721
[K"..." _...] -> fail(vcx, st, "`...` may only be used for the last keyword parameter")
712722
_ -> fail(vcx, st, "malformed keyword parameter; expected identifier, `=`, or `::`")
713723
end
@@ -788,7 +798,7 @@ vst1_assign_lhs(vcx, st; in_const=false, in_tuple=false, disallow_type=false) =
788798
_ -> vst1_assign_lhs_nontuple(vcx, st; in_const, in_tuple)
789799
end
790800
vst1_assign_lhs_nontuple(vcx, st; in_const=false, in_tuple=false, disallow_type=false) = @stm st begin
791-
(_, when=vst1_ident_lhs(with(vcx; speculative=true), st)) -> true
801+
(_, when=vst1_ident(with(vcx; speculative=true), st; lhs=true)) -> true
792802
(_, when=(in_const && kind(st) in (K".", K"ref"))) ->
793803
fail(vcx, st, "cannot declare this form constant")
794804
([K"Value"], when=st.value isa GlobalRef) -> true
@@ -801,7 +811,7 @@ vst1_assign_lhs_nontuple(vcx, st; in_const=false, in_tuple=false, disallow_type=
801811
vst1_assign_lhs(vcx, x; in_const, in_tuple)
802812
[K"ref" x is...] -> vst1_assign_lhs_nontuple(vcx, x; in_const, in_tuple) &
803813
allv(vst1_splat_or_val, vcx, is)
804-
[K"curly" t tvs...] -> vst1_ident_lhs(vcx, t) &
814+
[K"curly" t tvs...] -> vst1_ident(vcx, t; lhs=true) &
805815
allv(vst1_typevar_decl, vcx, tvs)
806816

807817
# errors

test/function_calls_ir.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,7 @@ end
594594
#---------------------
595595
LoweringError:
596596
function A.ccall()
597-
# └───┘ ── `(. a b)` requires symbol `b` after macro-expansion, or identifier before
597+
# └───┘ ── this is a reserved identifier
598598
end
599599

600600
########################################

0 commit comments

Comments
 (0)