@@ -20,88 +20,6 @@ use emmylua_parser::{
2020 LuaNameExpr , LuaUnaryExpr , LuaVarExpr ,
2121} ;
2222
23- //======================================================================================
24- // Helper functions
25- //======================================================================================
26-
27- /// Check if an expression is a vararg (...) literal
28- fn is_vararg_expr ( expr : & LuaExpr ) -> bool {
29- if let LuaExpr :: LiteralExpr ( lit) = expr {
30- matches ! ( lit. get_literal( ) , Some ( LuaLiteralToken :: Dots ( _) ) )
31- } else {
32- false
33- }
34- }
35-
36- /// Result of parsing a Lua number literal
37- #[ derive( Debug , Clone , Copy ) ]
38- enum ParsedNumber {
39- /// Successfully parsed as integer
40- Int ( i64 ) ,
41- /// Number is too large for i64, use float instead
42- Float ( f64 ) ,
43- }
44-
45- /// Parse a Lua integer literal from text, handling hex numbers that overflow i64
46- /// Lua treats 0xFFFFFFFFFFFFFFFF as -1 (two's complement interpretation)
47- /// For decimal numbers that overflow i64 range, returns Float instead
48- fn parse_lua_int ( text : & str ) -> ParsedNumber {
49- let text = text. trim ( ) ;
50- if text. starts_with ( "0x" ) || text. starts_with ( "0X" ) {
51- // Hex number - parse as u64 first, then reinterpret as i64
52- // This handles the case like 0xFFFFFFFFFFFFFFFF which should be -1
53- let hex_part = & text[ 2 ..] ;
54- // Remove any trailing decimal part (e.g., 0xFF.0)
55- let hex_part = hex_part. split ( '.' ) . next ( ) . unwrap_or ( hex_part) ;
56- if let Ok ( val) = u64:: from_str_radix ( hex_part, 16 ) {
57- return ParsedNumber :: Int ( val as i64 ) ; // Reinterpret bits as signed
58- }
59- }
60- // Decimal case: parse as i64 only, if overflow use float
61- // (Unlike hex, decimal numbers should NOT be reinterpreted as two's complement)
62- if let Ok ( val) = text. parse :: < i64 > ( ) {
63- return ParsedNumber :: Int ( val) ;
64- }
65- // Decimal number is too large for i64, parse as float
66- if let Ok ( val) = text. parse :: < f64 > ( ) {
67- return ParsedNumber :: Float ( val) ;
68- }
69- // Default fallback
70- ParsedNumber :: Int ( 0 )
71- }
72-
73- /// Lua left shift: x << n (returns 0 if |n| >= 64)
74- /// Negative n means right shift
75- #[ inline( always) ]
76- fn lua_shl ( l : i64 , r : i64 ) -> i64 {
77- if r >= 64 || r <= -64 {
78- 0
79- } else if r >= 0 {
80- ( l as u64 ) . wrapping_shl ( r as u32 ) as i64
81- } else {
82- // Negative shift means right shift (logical)
83- ( l as u64 ) . wrapping_shr ( ( -r) as u32 ) as i64
84- }
85- }
86-
87- /// Lua right shift: x >> n (logical shift, returns 0 if |n| >= 64)
88- /// Negative n means left shift
89- #[ inline( always) ]
90- fn lua_shr ( l : i64 , r : i64 ) -> i64 {
91- if r >= 64 || r <= -64 {
92- 0
93- } else if r >= 0 {
94- ( l as u64 ) . wrapping_shr ( r as u32 ) as i64
95- } else {
96- // Negative shift means left shift
97- ( l as u64 ) . wrapping_shl ( ( -r) as u32 ) as i64
98- }
99- }
100-
101- //======================================================================================
102- // NEW API: ExpDesc-based expression compilation (Lua 5.4 compatible)
103- //======================================================================================
104-
10523/// Core function: Compile expression and return ExpDesc
10624/// This is the NEW primary API that replaces the old u32-based compile_expr
10725pub fn compile_expr_desc ( c : & mut Compiler , expr : & LuaExpr ) -> Result < ExpDesc , String > {
@@ -2357,7 +2275,6 @@ pub fn compile_call_expr_with_returns_and_dest(
23572275 } else {
23582276 false
23592277 } ;
2360-
23612278 // Track if we need to move return values back to original dest
23622279 let mut need_move_to_dest = false ;
23632280 let original_dest = dest;
@@ -3086,7 +3003,7 @@ fn compile_table_expr_to(
30863003 while c. freereg < array_values_end {
30873004 alloc_register ( c) ;
30883005 }
3089- let mut has_call_at_end = false ;
3006+ let mut call_at_end_idx : Option < usize > = None ;
30903007
30913008 // Process all fields in source order
30923009 // Array elements are loaded to registers, hash fields are set immediately
@@ -3107,7 +3024,7 @@ fn compile_table_expr_to(
31073024 } else if is_last_field && is_call {
31083025 // Call as last element: returns multiple values
31093026 // Will be handled after all hash fields
3110- has_call_at_end = true ;
3027+ call_at_end_idx = Some ( field_idx ) ;
31113028 continue ;
31123029 }
31133030
@@ -3339,15 +3256,32 @@ fn compile_table_expr_to(
33393256 return Ok ( reg) ;
33403257 }
33413258
3342- if has_call_at_end {
3343- // Call as last element - for now treat as single value
3344- // TODO: handle multiple return values properly
3259+ if let Some ( idx) = call_at_end_idx {
3260+ // Call as last element: compile call with all return values
33453261 let target_reg = values_start + array_idx;
3262+ eprintln ! ( "[DEBUG] call_at_end: target_reg={}, freereg={}, values_start={}, array_idx={}" , target_reg, c. freereg, values_start, array_idx) ;
33463263 while c. freereg <= target_reg {
33473264 alloc_register ( c) ;
33483265 }
3349- // Simplified: just count as one more array element
3350- array_idx += 1 ;
3266+
3267+ // Get the call expression and compile it
3268+ if let Some ( field) = fields. get ( idx) {
3269+ if let Some ( value_expr) = field. get_value_expr ( ) {
3270+ if let LuaExpr :: CallExpr ( call_expr) = value_expr {
3271+ // Compile the call with all return values (usize::MAX means all)
3272+ eprintln ! ( "[DEBUG] before compile_call_expr" ) ;
3273+ compile_call_expr_with_returns_and_dest ( c, & call_expr, usize:: MAX , Some ( target_reg) ) ?;
3274+ eprintln ! ( "[DEBUG] after compile_call_expr" ) ;
3275+ }
3276+ }
3277+ }
3278+
3279+ // SetList with B=0 (all remaining values including call returns)
3280+ let c_param = ( array_idx as usize / 50 ) as u32 ;
3281+ emit ( c, Instruction :: encode_abc ( OpCode :: SetList , reg, 0 , c_param) ) ;
3282+
3283+ c. freereg = reg + 1 ;
3284+ return Ok ( reg) ;
33513285 }
33523286
33533287 // Emit SETLIST for all array elements at the end
0 commit comments