File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -554,7 +554,13 @@ impl Compiler {
554554 // Expand macros in all function bodies.
555555 for decl in & mut decls {
556556 if let Decl :: Func ( ref mut fdecl) = decl {
557- fdecl. expand_macros ( & macros) ;
557+ if let Err ( ( loc, msg) ) = fdecl. expand_macros ( & macros) {
558+ if !self . quiet {
559+ print_error_with_context ( loc, & msg) ;
560+ }
561+ self . last_errors . push ( format_error ( loc, & msg) ) ;
562+ return false ;
563+ }
558564 }
559565 }
560566
Original file line number Diff line number Diff line change @@ -97,12 +97,25 @@ impl FuncDecl {
9797 }
9898
9999 /// Expand all macro invocations in this function's arena.
100- pub fn expand_macros ( & mut self , macros : & std:: collections:: HashMap < Name , FuncDecl > ) {
101- let n = self . arena . exprs . len ( ) ;
102- for i in 0 ..n {
100+ pub fn expand_macros (
101+ & mut self ,
102+ macros : & std:: collections:: HashMap < Name , FuncDecl > ,
103+ ) -> Result < ( ) , ( Loc , String ) > {
104+ let mut i = 0 ;
105+ let mut expansion_count = 0 ;
106+ while i < self . arena . exprs . len ( ) {
103107 if let Expr :: Macro ( name, ref args) = self . arena . exprs [ i] {
108+ let loc = self . arena . locs [ i] ;
104109 let args = args. clone ( ) ;
105110 if let Some ( mac) = macros. get ( & name) {
111+ expansion_count += 1 ;
112+ if expansion_count > 100_000 {
113+ return Err ( (
114+ loc,
115+ format ! ( "macro expansion limit exceeded while expanding {}" , name) ,
116+ ) ) ;
117+ }
118+
106119 let subst: Vec < ( Name , ExprID ) > = mac
107120 . params
108121 . iter ( )
@@ -115,9 +128,12 @@ impl FuncDecl {
115128
116129 self . arena . exprs [ i] = self . arena . exprs [ new_body] . clone ( ) ;
117130 self . arena . locs [ i] = self . arena . locs [ new_body] ;
131+ continue ;
118132 }
119133 }
134+ i += 1 ;
120135 }
136+ Ok ( ( ) )
121137 }
122138}
123139
Original file line number Diff line number Diff line change 1+ // expected stdout:
2+ // compilation successful
3+ // assert(true)
4+
5+ macro inc(x) {
6+ x = x + 1
7+ }
8+
9+ macro inc_twice(x) {
10+ @inc(x)
11+ @inc(x)
12+ }
13+
14+ main {
15+ var x = 0
16+ @inc_twice(x)
17+ assert(x == 2)
18+ }
You can’t perform that action at this time.
0 commit comments