@@ -131,7 +131,7 @@ vst1_value(vcx::Validation1Context, st::SyntaxTree; need_value=true) = @stm st b
131131 [K " .=" l r] -> vst1_dotassign_lhs (vcx, l) & vst1_value (vcx, r)
132132 [K " .op=" l op r] -> vst1_dotassign_lhs (vcx, l) & vst1_ident (vcx, op) & vst1_value (vcx, r)
133133
134- [K " function" _... ] -> ! vcx. inner_cond || vcx . toplevel ? vst1_function (vcx, st) :
134+ [K " function" _... ] -> ! vcx. inner_cond ? vst1_function (vcx, st) :
135135 fail (vcx, st, " conditional inner method definitions are not supported; use `()->()` syntax instead" )
136136 [K " call" _... ] -> vst1_call (vcx, st)
137137 [K " dotcall" _... ] -> vst1_dotcall (vcx, st)
@@ -155,12 +155,10 @@ vst1_value(vcx::Validation1Context, st::SyntaxTree; need_value=true) = @stm st b
155155 [K " quote" x] -> vcx. unexpanded ? vst0_quoted (with (vcx, :quote_level => 1 ), x) :
156156 fail (vcx, st, " interpolating quote not valid in AST after macro expansion" )
157157 [K " $" x] -> fail (vcx, st, raw " `$` expression outside string or quote" )
158- [K " tuple" xs... [K " parameters" kws... ]] ->
159- allv (vst1_splat_or_val, vcx, xs) & allv (vst1_call_arg, vcx, kws)
160- [K " tuple" xs... ] -> allv (vst1_splat_or_val, vcx, xs)
158+ [K " tuple" _... ] -> vst1_value_tuple (vcx, st)
161159 [K " ." x y] -> vst1_value (vcx, x) & vst1_dot_rhs (vcx, y)
162160 [K " ." x] -> vst1_value (vcx, x)
163- [K " :" ] -> true # ast TODO : this doesn't need to be a kind. note a:b is a call, this is a[:] or just :
161+ [K " :" ] -> true # ast TODO : `a:b` is identifier, lone `:` should be identifier, ` a[:]` should be this kind
164162 [K " curly" t xs... ] -> vst1_value (vcx, t) & allv (vst1_value_curly_typevar, vcx, xs)
165163 [K " where" lhs rhs] -> vst1_value (vcx, lhs) & vst1_where_rhs (vcx, rhs)
166164 [K " string" xs... ] -> allv (vst1_value, vcx, xs)
@@ -216,15 +214,18 @@ vst1_value(vcx::Validation1Context, st::SyntaxTree; need_value=true) = @stm st b
216214 allv (vst1_ident, vcx, b1) &
217215 allv (vst1_ident, vcx, b2) &
218216 vst1_lam (vcx, st[3 ])
217+ [K " scope_block" x] -> vst1_value (vcx, x; need_value)
219218 [K " generated" ] -> true
220- ([K " foreigncall" f [K " static_eval" rt] [K " static_eval" argt_svec] args... ],
221- when= kind (f) in (K " Symbol" , K " Identifier" )) ->
222- vst1_value (vcx, rt) & vst1_value (vcx, argt_svec) & allv (vst1_value, vcx, args)
219+ # TODO : could probably be validated more
220+ [K " foreigncall" f [K " static_eval" rt] [K " static_eval" argt_svec] args... ] ->
221+ vst1_foreigncall_fname (vcx, f) & vst1_value (vcx, rt) &
222+ vst1_value (vcx, argt_svec) & allv (vst1_value, vcx, args)
223223 [K " cfunction" t [K " static_eval" fptr] [K " static_eval" rt] [K " static_eval" argt_svec] [K " Symbol" ]] ->
224- vst1_value (vcx, t) & vst1_value (vcx, fptr) & vst1_value (vcx, rt) & vst1_value (vcx, argt_svec)
224+ vst1_value (vcx, t) & vst1_value (vcx, fptr) &
225+ vst1_value (vcx, rt) & vst1_value (vcx, argt_svec)
225226 [K " cfunction" t fptr [K " static_eval" rt] [K " static_eval" argt_svec] [K " Symbol" ]] ->
226- vst1_value (vcx, t) & vst1_value (vcx, fptr) & vst1_value (vcx, rt) & vst1_value (vcx, argt_svec)
227- [ K " scope_block " x] -> vst1_value (vcx, x; need_value )
227+ vst1_value (vcx, t) & vst1_value (vcx, fptr) &
228+ vst1_value (vcx, rt) & vst1_value (vcx, argt_svec )
228229
229230 # Only from macro expansions producing Expr(:toplevel, ...). We don't want
230231 # to recurse on the contained expression since `K"escape"` can wrap nearly
@@ -283,6 +284,7 @@ vst1_stmt(vcx::Validation1Context, st::SyntaxTree) = @stm st begin
283284 ([K " global" xs... ], when= ! vcx. toplevel) -> allv (vst1_inner_global_decl, vcx, xs)
284285 [K " symbolic_label" ] -> true
285286 [K " symbolic_goto" ] -> true
287+ [K " latestworld_if_toplevel" ] -> true
286288
287289 (_, run= pass_or_err (vst1_toplevel_only_stmt, vcx, st), when= run. known) ->
288290 run. pass && (vcx. toplevel || fail (vcx, st, " this syntax is only allowed in top level code" ))
@@ -312,7 +314,6 @@ vst1_toplevel_only_stmt(vcx::Validation1Context, st::SyntaxTree) = @stm st begin
312314 [K " public" xs... ] -> allv (vst1_ident, vcx, xs)
313315 [K " export" xs... ] -> allv (vst1_ident, vcx, xs)
314316 [K " latestworld" ] -> true
315- [K " latestworld_if_toplevel" ] -> true
316317 _ -> false
317318end
318319
@@ -347,21 +348,33 @@ function vst1_importpath(vcx, st; dots_ok)
347348 return ok && seen_first
348349end
349350
351+ vst1_value_tuple (vcx, st) = @stm st begin
352+ [K " tuple" [K " parameters" kws... ]] -> allv (vst1_call_arg, vcx, kws)
353+ [K " tuple" _ _... [K " parameters" _ _... ]] ->
354+ fail (vcx, st[end ], " cannot mix tuple `(a,b,c)` and named tuple `(;a,b,c)` syntax" )
355+ [K " tuple" xs... ] -> allv (vst1_splat_or_val, vcx, xs)
356+ _ -> fail (vcx, st, " malformed tuple" )
357+ end
358+
350359vst1_block (vcx, st; need_value= true ) = @stm st begin
351360 [K " block" ] -> true
352361 ([K " block" xs... ], when= ! need_value) -> allv (vst1_stmt, vcx, xs)
353362 [K " block" xs... val] -> allv (vst1_stmt, vcx, xs) & vst1_value (vcx, val)
354363 _ -> fail (vcx, st, " expected `block`" )
355364end
356365
366+ # Usually block-wrapped, but not always.
357367vst1_else (vcx, st; need_value) = @stm st begin
358- [K "block " _ ... ] -> vst1_block (vcx, st ; need_value)
359- [K " elseif" cond t f] ->
360- vst1_value (vcx, cond) & vst1_block (vcx, t; need_value) & vst1_else (vcx, f; need_value)
368+ [K "elseif " cond t ] -> vst1_value (vcx, cond) & vst1_value (vcx, t ; need_value)
369+ [K " elseif" cond t f] -> vst1_value (vcx, cond) &
370+ vst1_value (vcx, t; need_value) & vst1_else (vcx, f; need_value)
361371 _ -> vst1_value (vcx, st; need_value)
362372end
363373
364374# TODO : catch and else are in value position
375+ # ast TODO : While the AST is more readable than Expr's try-catch, it's difficult
376+ # enough to unpack that we should consider changing it, especially if we intend
377+ # to support multiple catch-blocks at some point
365378vst1_try (vcx, st) = @stm st begin
366379 [K " try" _] -> fail (vcx, st, " try without catch or finally" )
367380 [K " try" b1 [K " catch" err body2... ]] ->
517530# assignments (interpreted as kwargs) must have a simple LHS, and splat is OK.
518531vst1_call_arg (vcx, st) = @stm st begin
519532 [K " =" id val] -> vst1_ident (vcx, id) & vst1_value (vcx, val)
520- [K " ..." x] -> vst1_value (vcx, x) # complex assignment in here is OK
521- _ -> vst1_value (vcx, st)
533+ _ -> vst1_splat_or_val (vcx, st) # complex assignment in `...` is OK
522534end
523535
524536# Arg to `parameters` (post-semicolon) in a call (not function decl) can be:
@@ -673,6 +685,7 @@ vst1_param_req_or_tuple(vcx, st) = @stm st begin
673685end
674686
675687vst1_simple_tuple_lhs (vcx, st) = @stm st begin
688+ [K " tuple" [K " parameters" kws... ]] -> allv (vst1_ident_lhs, vcx, kws)
676689 [K " tuple" xs... ] -> allv (vst1_simple_tuple_lhs, vcx, xs)
677690 _ -> vst1_ident_lhs (vcx, st)
678691end
@@ -748,6 +761,16 @@ vst1_struct_field(vcx, st) = @stm st begin
748761 _ -> vst1_stmt (vcx, st)
749762end
750763
764+ # TODO count(kind(x)===k for x in xs)
765+ # working around a revise bug that fails with anonymous functions
766+ function _num_of_kind (xs, k)
767+ n = 0
768+ for x in xs
769+ kind (x) === k && (n += 1 )
770+ end
771+ return n
772+ end
773+
751774# syntax TODO : (local/global (= lhs rhs)) forms should probably reject the same lhss as const (ref and .)
752775# TODO : We can do some destructuring checks here (e.g. fail `(a,b,c) = (1,2)`)
753776# compat:
@@ -758,7 +781,7 @@ vst1_assign_lhs(vcx, st; in_const=false, in_tuple=false, disallow_type=false) =
758781 [K " tuple" [K " parameters" xs... ]] -> allv (vst1_symdecl, vcx, xs)
759782 [K " tuple" xs... ] ->
760783 allv (vst1_assign_lhs, vcx, xs; in_const, in_tuple= true ) &
761- (count ( kind (x) === K " ..." for x in xs ) <= 1 ||
784+ (_num_of_kind (xs, K " ..." ) <= 1 ||
762785 fail (vcx, st, " multiple `...` in destructuring assignment are ambiguous" ))
763786 # Parser produces this in too many places
764787 # [K"call" _...] ->
@@ -815,9 +838,8 @@ vst1_arraylike(vcx, st) = @stm st begin
815838 _ -> false
816839end
817840
818- # TODO : Are there things we can rule out from appearing in `...`?
819841vst1_splat_or_val (vcx, st) = @stm st begin
820- [K " ..." x] -> vst1_value (vcx, x)
842+ [K " ..." x] -> vst1_splat_or_val (vcx, x)
821843 [K " ..." _... ] -> fail (" expected one argument to `...`" )
822844 _ -> vst1_value (vcx, st)
823845end
@@ -853,6 +875,14 @@ vst1_documented(vcx, st) = @stm st begin
853875 _ -> fail (vcx, st, " `$(kind (st)) ` cannot be annotated with a docstring" )
854876end
855877
878+ vst1_foreigncall_fname (vcx, st) = @stm st begin
879+ [K " Symbol" ] -> true
880+ [K " Identifier" ] -> true
881+ [K " static_eval" x] -> vst1_foreigncall_fname (vcx, x)
882+ [K " tuple" xs... ] -> allv (vst1_value, vcx, xs) # TODO
883+ _ -> fail (vcx, st, " invalid foreigncall function name" )
884+ end
885+
856886"""
857887For convenience, much of the validation code for st0 (non-macro-expanded trees) is
858888shared with that for st1 (macro-expanded trees). The main differences:
0 commit comments