@@ -11,9 +11,15 @@ static void emit_statement(FILE *out, const AstStmt *stmt, const FunctionTable *
1111static void emit_expression_raw (FILE * out , const AstExpr * expr , const FunctionTable * functions );
1212static void emit_expression_expected (FILE * out , const AstExpr * expr , const FunctionTable * functions , TypeKind expected_type );
1313static void emit_call (FILE * out , const AstExpr * expr , const FunctionTable * functions );
14+ static void emit_printf_call (FILE * out , const AstExpr * expr , const FunctionTable * functions );
15+ static void emit_puts_call (FILE * out , const AstExpr * expr , const FunctionTable * functions );
16+ static void emit_printf_args (FILE * out , const AstExpr * expr , const FunctionTable * functions );
17+ static void emit_string_literal_n (FILE * out , const char * value , size_t length );
18+ static void emit_string_literal (FILE * out , const char * value );
1419static const FunctionSignature * lookup_signature (const FunctionTable * functions , const char * name );
1520static const char * binary_op_token (AstBinaryOp op );
1621static void emit_indent (FILE * out , int indent );
22+ static int emit_builtin_expr_statement (FILE * out , const AstExpr * expr , const FunctionTable * functions , int indent );
1723
1824void codegen_lua_emit (FILE * out , const AstProgram * program , const FunctionTable * functions )
1925{
@@ -164,6 +170,10 @@ static void emit_statement(FILE *out, const AstStmt *stmt, const FunctionTable *
164170 case STMT_EXPR :
165171 if (stmt -> data .expr )
166172 {
173+ if (emit_builtin_expr_statement (out , stmt -> data .expr , functions , indent ))
174+ {
175+ break ;
176+ }
167177 emit_indent (out , indent );
168178 emit_expression_raw (out , stmt -> data .expr , functions );
169179 fputc ('\n' , out );
@@ -228,6 +238,9 @@ static void emit_expression_raw(FILE *out, const AstExpr *expr, const FunctionTa
228238 case EXPR_BOOL_LITERAL :
229239 fputs (expr -> data .bool_value ? "true" : "false" , out );
230240 break ;
241+ case EXPR_STRING_LITERAL :
242+ emit_string_literal (out , expr -> data .string_literal );
243+ break ;
231244 case EXPR_IDENTIFIER :
232245 fputs (expr -> data .identifier , out );
233246 break ;
@@ -264,6 +277,16 @@ static void emit_expression_raw(FILE *out, const AstExpr *expr, const FunctionTa
264277
265278static void emit_call (FILE * out , const AstExpr * expr , const FunctionTable * functions )
266279{
280+ if (strcmp (expr -> data .call .callee , "printf" ) == 0 )
281+ {
282+ emit_printf_call (out , expr , functions );
283+ return ;
284+ }
285+ if (strcmp (expr -> data .call .callee , "puts" ) == 0 )
286+ {
287+ emit_puts_call (out , expr , functions );
288+ return ;
289+ }
267290 const FunctionSignature * signature = lookup_signature (functions , expr -> data .call .callee );
268291 fputs (expr -> data .call .callee , out );
269292 fputc ('(' , out );
@@ -283,6 +306,126 @@ static void emit_call(FILE *out, const AstExpr *expr, const FunctionTable *funct
283306 fputc (')' , out );
284307}
285308
309+ static void emit_printf_call (FILE * out , const AstExpr * expr , const FunctionTable * functions )
310+ {
311+ fputs ("((print(string.format(" , out );
312+ emit_printf_args (out , expr , functions );
313+ fputs ("))) or 0)" , out );
314+ }
315+
316+ static void emit_puts_call (FILE * out , const AstExpr * expr , const FunctionTable * functions )
317+ {
318+ fputs ("((print(" , out );
319+ if (expr -> data .call .args .count > 0 )
320+ {
321+ emit_expression_raw (out , expr -> data .call .args .items [0 ], functions );
322+ }
323+ fputs (")) or 0)" , out );
324+ }
325+
326+ static void emit_printf_args (FILE * out , const AstExpr * expr , const FunctionTable * functions )
327+ {
328+ for (size_t i = 0 ; i < expr -> data .call .args .count ; ++ i )
329+ {
330+ if (i > 0 )
331+ {
332+ fputs (", " , out );
333+ }
334+ if (i == 0 && expr -> data .call .args .items [i ]-> kind == EXPR_STRING_LITERAL )
335+ {
336+ const char * raw = expr -> data .call .args .items [i ]-> data .string_literal ;
337+ size_t len = raw ? strlen (raw ) : 0 ;
338+ if (len > 0 && raw [len - 1 ] == '\n' )
339+ {
340+ emit_string_literal_n (out , raw , len - 1 );
341+ continue ;
342+ }
343+ }
344+ emit_expression_raw (out , expr -> data .call .args .items [i ], functions );
345+ }
346+ }
347+
348+ static void emit_string_literal_n (FILE * out , const char * value , size_t length )
349+ {
350+ if (!value )
351+ {
352+ fputs ("\"\"" , out );
353+ return ;
354+ }
355+ fputc ('"' , out );
356+ for (size_t i = 0 ; i < length ; ++ i )
357+ {
358+ unsigned char c = (unsigned char )value [i ];
359+ switch (c )
360+ {
361+ case '\\' :
362+ fputs ("\\\\" , out );
363+ break ;
364+ case '"' :
365+ fputs ("\\\"" , out );
366+ break ;
367+ case '\n' :
368+ fputs ("\\n" , out );
369+ break ;
370+ case '\r' :
371+ fputs ("\\r" , out );
372+ break ;
373+ case '\t' :
374+ fputs ("\\t" , out );
375+ break ;
376+ default :
377+ if (c < 32 || c == 127 )
378+ {
379+ fprintf (out , "\\x%02X" , c );
380+ }
381+ else
382+ {
383+ fputc (c , out );
384+ }
385+ break ;
386+ }
387+ }
388+ fputc ('"' , out );
389+ }
390+
391+ static void emit_string_literal (FILE * out , const char * value )
392+ {
393+ if (!value )
394+ {
395+ fputs ("\"\"" , out );
396+ return ;
397+ }
398+ emit_string_literal_n (out , value , strlen (value ));
399+ }
400+
401+ static int emit_builtin_expr_statement (FILE * out , const AstExpr * expr , const FunctionTable * functions , int indent )
402+ {
403+ if (!expr || expr -> kind != EXPR_CALL )
404+ {
405+ return 0 ;
406+ }
407+ if (strcmp (expr -> data .call .callee , "printf" ) == 0 )
408+ {
409+ emit_indent (out , indent );
410+ fputs ("print(string.format(" , out );
411+ emit_printf_args (out , expr , functions );
412+ fputs ("))\n" , out );
413+ return 1 ;
414+ }
415+ if (strcmp (expr -> data .call .callee , "puts" ) == 0 )
416+ {
417+ emit_indent (out , indent );
418+ fputs ("print(" , out );
419+ if (expr -> data .call .args .count > 0 )
420+ {
421+ emit_expression_raw (out , expr -> data .call .args .items [0 ], functions );
422+ }
423+ fputs (")\n" , out );
424+ return 1 ;
425+ }
426+ return 0 ;
427+ }
428+
286429static const FunctionSignature * lookup_signature (const FunctionTable * functions , const char * name )
287430{
288431 if (!functions || !name )
0 commit comments