@@ -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)
429435end
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
436447cst1_assign (vcx, st) = @stm st begin
437448 [K " =" l r] -> vst1_assign_lhs (vcx, l) & vst1_value (vcx, r)
@@ -443,29 +454,26 @@ end
443454vst1_symdecl_or_assign (vcx, st) = cst1_assign (vcx, st) || vst1_symdecl (vcx, st)
444455
445456vst1_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 `::`" )
449460end
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
462475end
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...
471479vst1_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" )
622632end
623633
624634vst1_macro_calldecl_name (vcx, st) = @stm st begin
@@ -682,21 +692,21 @@ vst1_param_req_or_tuple(vcx, st) = @stm st begin
682692end
683693
684694vst1_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 )
688698end
689699
690700vst1_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 `::`" )
695705end
696706
697707vst1_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 `=`" )
700710end
701711
702712vst1_calldecl_kws (vcx, st) = @stm st begin
@@ -706,8 +716,8 @@ vst1_calldecl_kws(vcx, st) = @stm st begin
706716end
707717
708718vst1_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 `::`" )
713723end
@@ -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)
789799end
790800vst1_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
0 commit comments