@@ -159,8 +159,17 @@ pub enum Errors {
159159/// 带有错误前缀, 并且文本为红色的eprintln
160160macro_rules! err {
161161 ( $fmtter: expr $( , $args: expr) * $( , ) ? ) => {
162- eprintln! ( concat! ( " \x1b [1;31m" , "CompileError: \n " , $fmtter, " \x1b [22;39m" ) , $( $ args) , * ) ;
162+ err! ( None => $fmtter $ ( , $args) * ) ;
163163 } ;
164+ ( $loc: expr => $fmtter: expr $( , $args: expr) * $( , ) ? ) => {
165+ let err = format!( concat!( "CompileError:\n " , $fmtter) , $( $args) ,* ) ;
166+ eprintln!( "\x1b [1;31m{err}\x1b [22;39m" ) ;
167+ $crate:: LAST_ERR . replace( ( $loc. into( ) , err) ) ;
168+ } ;
169+ }
170+ thread_local ! {
171+ static LAST_ERR : Cell <( Option <( u32 , u32 ) >, String ) >
172+ = Cell :: new( ( None , String :: new( ) ) ) ;
164173}
165174
166175pub type Location = usize ;
@@ -322,7 +331,7 @@ impl TakeHandle for Value {
322331 } ,
323332 ref cmp @ Self :: Cmper ( Cmper ( ref loc) ) => {
324333 let loc = loc. location ( & meta. source ) ;
325- err ! (
334+ err ! ( loc =>
326335 "{}\n 最终未被展开的 Cmper, 位于: {}:{}\n {}" ,
327336 meta. err_info( ) . join( "\n " ) ,
328337 loc. 0 ,
@@ -3015,31 +3024,31 @@ impl Compile for ArgsRepeat {
30153024 Either :: Left ( count) => count,
30163025 Either :: Right ( value) => {
30173026 let Some ( ( n, _) ) = value. try_eval_const_num ( meta) else {
3018- let ( line , col ) = loc. location ( & meta. source ) ;
3019- err ! (
3027+ let loc = loc. location ( & meta. source ) ;
3028+ err ! ( loc =>
30203029 "{}\n 重复块次数不是数字, 位于: {}:{}\n {}" ,
30213030 meta. err_info( ) . join( "\n " ) ,
3022- line , col ,
3031+ loc . 0 , loc . 1 ,
30233032 value. display_src( meta) ,
30243033 ) ;
30253034 meta. exit ( 6 )
30263035 } ;
30273036 let n = n. round ( ) ;
30283037 if n < 0.0 || !n. is_finite ( ) {
3029- let ( line , col ) = loc. location ( & meta. source ) ;
3030- err ! (
3038+ let loc = loc. location ( & meta. source ) ;
3039+ err ! ( loc =>
30313040 "{}\n 重复块次数必须不小于0 ({}), 位于: {}:{}" ,
30323041 meta. err_info( ) . join( "\n " ) ,
3033- n, line , col ,
3042+ n, loc . 0 , loc . 1
30343043 ) ;
30353044 meta. exit ( 6 )
30363045 }
30373046 if n > 512.0 {
3038- let ( line , col ) = loc. location ( & meta. source ) ;
3039- err ! (
3047+ let loc = loc. location ( & meta. source ) ;
3048+ err ! ( loc =>
30403049 "{}\n 重复块次数过大 ({}), 位于: {}:{}" ,
30413050 meta. err_info( ) . join( "\n " ) ,
3042- n, line , col ,
3051+ n, loc . 0 , loc . 1
30433052 ) ;
30443053 meta. exit ( 6 )
30453054 }
@@ -3066,7 +3075,7 @@ impl Compile for ArgsRepeat {
30663075
30673076 if !meta. args_repeat_flags . last ( ) . unwrap ( ) { break }
30683077 if i >= meta. args_repeat_limit {
3069- err ! (
3078+ err ! ( loc . location ( & meta . source ) =>
30703079 "Maximum repeat limit exceeded ({})" ,
30713080 meta. args_repeat_limit,
30723081 ) ;
@@ -4175,9 +4184,12 @@ pub enum Emulate {
41754184 NakedBind ( Var ) ,
41764185}
41774186
4178- #[ derive( Debug ) ]
4187+ #[ derive( Debug , Default ) ]
41794188pub struct EmulateInfo {
41804189 pub exist_vars : Vec < ( Emulate , Var ) > ,
4190+ pub location : Option < ( u32 , u32 ) > ,
4191+ pub diagnostic : Option < String > ,
4192+ pub is_error : bool ,
41814193}
41824194
41834195pub struct CompileMeta {
@@ -4213,7 +4225,7 @@ pub struct CompileMeta {
42134225 log_count : usize ,
42144226 source : Rc < String > ,
42154227 pub is_emulated : bool ,
4216- pub emulate_infos : Vec < EmulateInfo > ,
4228+ pub emulate_infos : Cell < Vec < EmulateInfo > > ,
42174229}
42184230impl Debug for CompileMeta {
42194231 fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
@@ -4286,7 +4298,7 @@ impl CompileMeta {
42864298 log_count : 0 ,
42874299 source,
42884300 is_emulated : false ,
4289- emulate_infos : vec ! [ ] ,
4301+ emulate_infos : vec ! [ ] . into ( ) ,
42904302 } ;
42914303 let builtin = Var :: from ( Self :: BUILTIN_FUNCS_BINDER ) ;
42924304 for builtin_func in build_builtins ( ) {
@@ -4434,8 +4446,25 @@ impl CompileMeta {
44344446 & mut self . parse_lines
44354447 }
44364448
4449+ fn emulate ( & self , emulate_info : EmulateInfo ) {
4450+ if self . is_emulated {
4451+ let mut infos = self . emulate_infos . take ( ) ;
4452+ infos. push ( emulate_info) ;
4453+ self . emulate_infos . set ( infos) ;
4454+ }
4455+ }
4456+
44374457 fn exit ( & self , code : i32 ) -> ! {
44384458 if self . is_emulated {
4459+ let ( location, error) = LAST_ERR . take ( ) ;
4460+ if !error. is_empty ( ) {
4461+ self . emulate ( EmulateInfo {
4462+ location,
4463+ diagnostic : Some ( error) ,
4464+ is_error : true ,
4465+ ..Default :: default ( )
4466+ } ) ;
4467+ }
44394468 panic ! ( "exit code {code}" ) ;
44404469 } else {
44414470 std:: process:: exit ( code)
@@ -4457,7 +4486,7 @@ impl CompileMeta {
44574486 . for_each ( |( kind, var) | if printed. insert ( var) {
44584487 vars. push ( ( kind, var. clone ( ) ) ) ;
44594488 } ) ;
4460- self . emulate_infos . push ( EmulateInfo { exist_vars : vars } ) ;
4489+ self . emulate ( EmulateInfo { exist_vars : vars, .. Default :: default ( ) } ) ;
44614490 }
44624491
44634492 fn debug_binds_status ( & mut self , handle : & Var , name : & mut Var ) {
@@ -4481,7 +4510,7 @@ impl CompileMeta {
44814510 }
44824511 bind_vars
44834512 } ) ;
4484- self . emulate_infos . push ( EmulateInfo { exist_vars : bind_vars } ) ;
4513+ self . emulate ( EmulateInfo { exist_vars : bind_vars, .. Default :: default ( ) } ) ;
44854514 }
44864515
44874516 /// 进入一个拥有子命名空间的子块
@@ -4805,11 +4834,13 @@ impl CompileMeta {
48054834 pub fn err_info ( & self ) -> Vec < String > {
48064835 let mut res = Vec :: new ( ) ;
48074836
4808- let mut tag_lines = self . debug_tag_codes ( ) ;
4809- line_first_add ( & mut tag_lines, "\t " ) ;
4837+ if !self . is_emulated {
4838+ let mut tag_lines = self . debug_tag_codes ( ) ;
4839+ line_first_add ( & mut tag_lines, "\t " ) ;
48104840
4811- res. push ( "已生成代码:" . into ( ) ) ;
4812- res. extend ( tag_lines) ;
4841+ res. push ( "已生成代码:" . into ( ) ) ;
4842+ res. extend ( tag_lines) ;
4843+ }
48134844 res
48144845 }
48154846
@@ -4908,6 +4939,17 @@ impl CompileMeta {
49084939 self . env_args . pop ( ) . unwrap ( )
49094940 }
49104941
4942+ pub fn log_info_at ( & mut self , line : u32 , column : u32 , s : impl std:: fmt:: Display ) {
4943+ if self . is_emulated {
4944+ self . emulate ( EmulateInfo {
4945+ location : Some ( ( line, column) ) ,
4946+ diagnostic : Some ( s. to_string ( ) ) ,
4947+ ..Default :: default ( )
4948+ } ) ;
4949+ }
4950+ self . log_info ( format_args ! ( "{line}:{column} {s}" ) ) ;
4951+ }
4952+
49114953 pub fn log_info ( & mut self , s : impl std:: fmt:: Display ) {
49124954 self . log_count += 1 ;
49134955 eprintln ! ( "{}" , csi!( 1 ; 22 ; "[I] {}" ,
@@ -5078,9 +5120,7 @@ impl CompileMeta {
50785120 } else {
50795121 format ! ( "{no_effect:#?}" )
50805122 } ;
5081- self . log_info ( format_args ! (
5082- "{line}:{column} Take no effect: {no_effect}" ,
5083- ) ) ;
5123+ self . log_info_at ( line, column, format_args ! ( "Take no effect: {no_effect}" ) ) ;
50845124 }
50855125 }
50865126}
0 commit comments