luaur_compiler/functions/
fold_interp_string.rs1use alloc::vec::Vec;
2use core::ffi::c_char;
3use luaur_ast::records::ast_expr::AstExpr;
4use luaur_ast::records::ast_expr_interp_string::AstExprInterpString;
5use luaur_ast::records::ast_name::AstName;
6use luaur_ast::records::ast_name_table::AstNameTable;
7use luaur_ast::records::ast_node::AstNode;
8use luaur_common::macros::luau_assert::LUAU_ASSERT;
9use luaur_common::records::dense_hash_map::DenseHashMap;
10
11use crate::enums::type_constant_folding::Type;
12use crate::records::constant::Constant;
13
14pub fn fold_interp_string(
15 result: &mut Constant,
16 expr: *mut AstExprInterpString,
17 constants: &mut DenseHashMap<*mut AstExpr, Constant>,
18 string_table: &mut AstNameTable,
19) {
20 let expr = unsafe { &*expr };
21 LUAU_ASSERT!(expr.strings.len() == expr.expressions.len() + 1);
22
23 let mut result_length: usize = 0;
24 for index in 0..expr.strings.len() {
25 let string = expr.strings.as_slice()[index];
26 result_length += string.len();
27 if index < expr.expressions.len() {
28 let expr_ptr = expr.expressions.as_slice()[index];
29 let c = constants.find(&expr_ptr);
30 LUAU_ASSERT!(c.is_some());
31 let c = c.unwrap();
32 LUAU_ASSERT!(c.r#type == Type::Type_String);
33 result_length += c.string_length as usize;
34 }
35 }
36
37 const K_CONSTANT_FOLD_STRING_LIMIT: usize = 4096;
38 if result_length > K_CONSTANT_FOLD_STRING_LIMIT {
39 return;
40 }
41
42 result.r#type = Type::Type_String;
43 result.string_length = result_length as u32;
44
45 if result_length == 0 {
46 unsafe {
50 result.data.value_string = c"".as_ptr();
51 }
52 return;
53 }
54
55 let mut tmp = Vec::with_capacity(result_length);
56
57 for index in 0..expr.strings.len() {
58 let string = expr.strings.as_slice()[index];
59 let slice = unsafe {
60 core::slice::from_raw_parts(string.as_slice().as_ptr() as *const u8, string.len())
61 };
62 tmp.extend_from_slice(slice);
63 if index < expr.expressions.len() {
64 let expr_ptr = expr.expressions.as_slice()[index];
65 let c = constants.find(&expr_ptr);
66 LUAU_ASSERT!(c.is_some());
67 let c = c.unwrap();
68 let string_slice = c.get_string();
69 let string_bytes = unsafe {
70 core::slice::from_raw_parts(
71 string_slice.as_slice().as_ptr() as *const u8,
72 string_slice.len(),
73 )
74 };
75 tmp.extend_from_slice(string_bytes);
76 }
77 }
78
79 result.r#type = Type::Type_String;
80 result.string_length = result_length as u32;
81 let name = string_table.get_or_add(tmp.as_ptr() as *const c_char, tmp.len());
82 unsafe {
83 result.data.value_string = name.value;
84 }
85}