@@ -38,6 +38,91 @@ import {
3838import { luaValueToJS } from "$common/space_lua/runtime.ts" ;
3939import { jsToLuaValue } from "$common/space_lua/runtime.ts" ;
4040
41+ function handleVarargSync ( env : LuaEnv ) : LuaValue [ ] | Promise < LuaValue [ ] > {
42+ const varargs = env . get ( "..." ) ;
43+ if ( varargs instanceof Promise ) {
44+ return handleVarargAsync ( varargs ) ;
45+ }
46+ if ( varargs instanceof LuaTable ) {
47+ const args = [ ] ;
48+ for ( let i = 1 ; i <= varargs . length ; i ++ ) {
49+ const val = varargs . get ( i ) ;
50+ if ( val instanceof Promise ) {
51+ return handleVarargAsync ( varargs ) ;
52+ }
53+ args . push ( val ) ;
54+ }
55+ return args ;
56+ }
57+ return [ ] ;
58+ }
59+
60+ async function handleVarargAsync (
61+ varargs : Promise < LuaValue > | LuaTable ,
62+ ) : Promise < LuaValue [ ] > {
63+ const resolvedVarargs = await varargs ;
64+ if ( resolvedVarargs instanceof LuaTable ) {
65+ const args = [ ] ;
66+ for ( let i = 1 ; i <= resolvedVarargs . length ; i ++ ) {
67+ args . push ( await resolvedVarargs . get ( i ) ) ;
68+ }
69+ return args ;
70+ }
71+ return [ ] ;
72+ }
73+
74+ function handleTableFieldSync (
75+ table : LuaTable ,
76+ field : any ,
77+ env : LuaEnv ,
78+ sf : LuaStackFrame ,
79+ ) : void | Promise < void > {
80+ switch ( field . type ) {
81+ case "PropField" : {
82+ const value = evalExpression ( field . value , env , sf ) ;
83+ if ( value instanceof Promise ) {
84+ return value . then ( ( v ) => table . set ( field . key , singleResult ( v ) , sf ) ) ;
85+ }
86+ table . set ( field . key , singleResult ( value ) , sf ) ;
87+ break ;
88+ }
89+ case "DynamicField" : {
90+ const key = evalExpression ( field . key , env , sf ) ;
91+ const value = evalExpression ( field . value , env , sf ) ;
92+ if ( key instanceof Promise || value instanceof Promise ) {
93+ return Promise . all ( [
94+ key instanceof Promise ? key : Promise . resolve ( key ) ,
95+ value instanceof Promise ? value : Promise . resolve ( value ) ,
96+ ] ) . then ( ( [ k , v ] ) => {
97+ table . set ( singleResult ( k ) , singleResult ( v ) , sf ) ;
98+ } ) ;
99+ }
100+ table . set ( singleResult ( key ) , singleResult ( value ) , sf ) ;
101+ break ;
102+ }
103+ case "ExpressionField" : {
104+ if ( field . value . type === "Variable" && field . value . name === "..." ) {
105+ const varargs = handleVarargSync ( env ) ;
106+ if ( varargs instanceof Promise ) {
107+ return varargs . then ( ( args ) => {
108+ args . forEach ( ( val , i ) => table . set ( i + 1 , val , sf ) ) ;
109+ } ) ;
110+ }
111+ varargs . forEach ( ( val , i ) => table . set ( i + 1 , val , sf ) ) ;
112+ } else {
113+ const value = evalExpression ( field . value , env , sf ) ;
114+ if ( value instanceof Promise ) {
115+ return value . then ( ( v ) =>
116+ table . set ( table . length + 1 , singleResult ( v ) , sf )
117+ ) ;
118+ }
119+ table . set ( table . length + 1 , singleResult ( value ) , sf ) ;
120+ }
121+ break ;
122+ }
123+ }
124+ }
125+
41126export function evalExpression (
42127 e : LuaExpression ,
43128 env : LuaEnv ,
@@ -138,132 +223,36 @@ export function evalExpression(
138223 return evalPrefixExpression ( e , env , sf ) ;
139224 case "TableConstructor" : {
140225 const table = new LuaTable ( ) ;
226+
141227 if (
142228 e . fields . length === 1 &&
143229 e . fields [ 0 ] . type === "ExpressionField" &&
144230 e . fields [ 0 ] . value . type === "Variable" &&
145231 e . fields [ 0 ] . value . name === "..."
146232 ) {
147- const varargs = env . get ( "..." ) ;
233+ const varargs = handleVarargSync ( env ) ;
148234 if ( varargs instanceof Promise ) {
149- return varargs . then ( ( resolvedVarargs ) => {
150- if ( resolvedVarargs instanceof LuaTable ) {
151- const newTable = new LuaTable ( ) ;
152- for ( let i = 1 ; i <= resolvedVarargs . length ; i ++ ) {
153- newTable . set ( i , resolvedVarargs . get ( i ) , sf ) ;
154- }
155- return newTable ;
156- }
235+ return varargs . then ( ( args ) => {
236+ args . forEach ( ( val , i ) => table . set ( i + 1 , val , sf ) ) ;
157237 return table ;
158238 } ) ;
159- } else if ( varargs instanceof LuaTable ) {
160- for ( let i = 1 ; i <= varargs . length ; i ++ ) {
161- table . set ( i , varargs . get ( i ) , sf ) ;
162- }
163239 }
240+ varargs . forEach ( ( val , i ) => table . set ( i + 1 , val , sf ) ) ;
164241 return table ;
165242 }
243+
166244 const promises : Promise < void > [ ] = [ ] ;
167245 for ( const field of e . fields ) {
168- switch ( field . type ) {
169- case "PropField" : {
170- const value = evalExpression ( field . value , env , sf ) ;
171- if ( value instanceof Promise ) {
172- promises . push ( value . then ( ( value ) => {
173- table . set (
174- field . key ,
175- singleResult ( value ) ,
176- sf ,
177- ) ;
178- } ) ) ;
179- } else {
180- table . set ( field . key , singleResult ( value ) , sf ) ;
181- }
182- break ;
183- }
184- case "DynamicField" : {
185- const key = evalExpression ( field . key , env , sf ) ;
186- const value = evalExpression ( field . value , env , sf ) ;
187- if (
188- key instanceof Promise || value instanceof Promise
189- ) {
190- promises . push (
191- Promise . all ( [
192- key instanceof Promise ? key : Promise . resolve ( key ) ,
193- value instanceof Promise ? value : Promise . resolve ( value ) ,
194- ] ) . then ( ( [ key , value ] ) => {
195- table . set (
196- singleResult ( key ) ,
197- singleResult ( value ) ,
198- sf ,
199- ) ;
200- } ) ,
201- ) ;
202- } else {
203- table . set (
204- singleResult ( key ) ,
205- singleResult ( value ) ,
206- sf ,
207- ) ;
208- }
209- break ;
210- }
211- case "ExpressionField" : {
212- const value = evalExpression ( field . value , env , sf ) ;
213- if ( value instanceof Promise ) {
214- promises . push ( value . then ( async ( value ) => {
215- if (
216- field . value . type === "Variable" &&
217- field . value . name === "..."
218- ) {
219- // Special handling for {...}
220- const varargs = await Promise . resolve ( env . get ( "..." ) ) ;
221- if ( varargs instanceof LuaTable ) {
222- // Copy all values from varargs table
223- for ( let i = 1 ; i <= varargs . length ; i ++ ) {
224- const val = await Promise . resolve ( varargs . get ( i ) ) ;
225- table . set ( i , val , sf ) ;
226- }
227- }
228- } else {
229- // Normal case
230- table . set ( table . length + 1 , singleResult ( value ) , sf ) ;
231- }
232- } ) ) ;
233- } else {
234- if (
235- field . value . type === "Variable" && field . value . name === "..."
236- ) {
237- // Special handling for {...}
238- const varargs = env . get ( "..." ) ;
239- if ( varargs instanceof LuaTable ) {
240- for ( let i = 1 ; i <= varargs . length ; i ++ ) {
241- const val = varargs . get ( i ) ;
242- if ( val instanceof Promise ) {
243- promises . push (
244- Promise . resolve ( val ) . then ( ( val ) => {
245- table . set ( i , val , sf ) ;
246- } ) ,
247- ) ;
248- } else {
249- table . set ( i , val , sf ) ;
250- }
251- }
252- }
253- } else {
254- // Normal case
255- table . set ( table . length + 1 , singleResult ( value ) , sf ) ;
256- }
257- }
258- break ;
259- }
246+ const result = handleTableFieldSync ( table , field , env , sf ) ;
247+ if ( result instanceof Promise ) {
248+ promises . push ( result ) ;
260249 }
261250 }
251+
262252 if ( promises . length > 0 ) {
263253 return Promise . all ( promises ) . then ( ( ) => table ) ;
264- } else {
265- return table ;
266254 }
255+ return table ;
267256 }
268257 case "FunctionDefinition" : {
269258 return new LuaFunction ( e . body , env ) ;
@@ -600,25 +589,19 @@ function luaOp(
600589 ctx : ASTCtx ,
601590 sf : LuaStackFrame ,
602591) : any {
603- const operatorHandler = operatorsMetaMethods [ op ] ;
604- if ( ! operatorHandler ) {
592+ const handler = operatorsMetaMethods [ op ] ;
593+ if ( ! handler ) {
605594 throw new LuaRuntimeError ( `Unknown operator ${ op } ` , sf . withCtx ( ctx ) ) ;
606595 }
607596
608- if ( operatorHandler . metaMethod ) {
609- const result = evalMetamethod (
610- left ,
611- right ,
612- operatorHandler . metaMethod ,
613- ctx ,
614- sf ,
615- ) ;
616- if ( result !== undefined ) {
617- return result ;
597+ if ( handler . metaMethod ) {
598+ const metaResult = evalMetamethod ( left , right , handler . metaMethod , ctx , sf ) ;
599+ if ( metaResult !== undefined ) {
600+ return metaResult ;
618601 }
619602 }
620603
621- return operatorHandler . nativeImplementation ( left , right , ctx , sf ) ;
604+ return handler . nativeImplementation ( left , right , ctx , sf ) ;
622605}
623606
624607async function evalExpressions (
0 commit comments