v2 / vlib / v / gen / js / deep_copy.v
245 lines · 223 sloc · 7.23 KB · 99f141f741b643327a2628963d95998c862c7ed2
Raw
1module js
2
3import v.ast
4import strings
5import v.util
6
7@[inline]
8fn styp_to_copy_fn_name(styp string) string {
9 return styp.replace_each(['*', '', '.', '__', ' ', '__']) + '_\$copy'
10}
11
12fn (mut g JsGen) get_copy_fn(typ ast.Type) string {
13 mut unwrapped := g.unwrap_generic(typ).set_nr_muls(0).clear_flag(.variadic)
14 if g.pref.nofloat {
15 if typ == ast.f32_type {
16 unwrapped = ast.u32_type
17 } else if typ == ast.f64_type {
18 unwrapped = ast.u64_type
19 }
20 }
21 if typ.has_flag(.option) {
22 unwrapped.set_flag(.option)
23 }
24 styp := g.styp(unwrapped)
25 mut sym := g.table.sym(unwrapped)
26 mut copy_fn_name := styp_to_copy_fn_name(styp)
27 if mut sym.info is ast.Alias {
28 if sym.info.is_import {
29 sym = g.table.sym(sym.info.parent_type)
30 copy_fn_name = styp_to_copy_fn_name(sym.name)
31 }
32 }
33 g.copy_types << StrType{
34 typ: unwrapped
35 styp: styp
36 }
37 return copy_fn_name
38}
39
40fn (mut g JsGen) gen_copy_for_option(_typ ast.Type, _styp string, copy_fn_name string) {
41 g.definitions.writeln('function ${copy_fn_name}(it) { return it; }')
42}
43
44fn (mut g JsGen) gen_copy_for_alias(info ast.Alias, _styp string, copy_fn_name string) {
45 parent_copy_fn_name := g.get_str_fn(info.parent_type)
46
47 g.definitions.writeln('function ${copy_fn_name}(it) {')
48 g.definitions.writeln('\tlet res = ${parent_copy_fn_name}(it);')
49 g.definitions.writeln('\treturn res;')
50 g.definitions.writeln('}')
51}
52
53fn (mut g JsGen) gen_copy_for_multi_return(info ast.MultiReturn, _styp string, copy_fn_name string) {
54 mut fn_builder := strings.new_builder(512)
55 fn_builder.writeln('function ${copy_fn_name}(a) {')
56 fn_builder.writeln('\tlet arr = []')
57 for i, typ in info.types {
58 sym := g.table.sym(typ)
59 arg_copy_fn_name := g.get_copy_fn(typ)
60
61 if sym.kind in [.f32, .f64] {
62 if sym.kind == .f32 {
63 fn_builder.writeln('\tarr.push(new f32(a[${i}].val));')
64 } else {
65 fn_builder.writeln('\tarr.push(new f64(a[${i}].val));')
66 }
67 } else if sym.kind == .string {
68 fn_builder.writeln('\tarr.push(new string(a[${i}].str +""));')
69 } else if sym.kind == .function {
70 fn_builder.writeln('\tarr.push(a[${i}]);')
71 } else {
72 fn_builder.writeln('\tarr.push(${arg_copy_fn_name}(a[${i}]));')
73 }
74 }
75 fn_builder.writeln('\treturn arr;')
76 fn_builder.writeln('}')
77 g.definitions.writeln(fn_builder.str())
78}
79
80fn (mut g JsGen) gen_copy_for_enum(_info ast.Enum, _styp string, copy_fn_name string) {
81 g.definitions.writeln('function ${copy_fn_name}(it) { return it; }')
82}
83
84fn (mut g JsGen) gen_copy_for_union_sum_type(info ast.SumType, _styp string, copy_fn_name string) {
85 mut fn_builder := strings.new_builder(512)
86 fn_builder.writeln('function ${copy_fn_name}(x) {')
87 for typ in info.variants {
88 typ_str := g.styp(typ)
89 mut func_name := g.get_copy_fn(typ)
90 fn_builder.writeln('if (x instanceof ${typ_str}) { return ${func_name}(x); }')
91 }
92 fn_builder.writeln('builtin__panic(new string("unknown sum type value"));\n}')
93 g.definitions.writeln(fn_builder.str())
94}
95
96fn (mut g JsGen) gen_copy_for_interface(_info ast.Interface, styp string, copy_fn_name string) {
97 mut fn_builder := strings.new_builder(512)
98 mut clean_interface_v_type_name := styp.replace('__', '.')
99 if styp.ends_with('*') {
100 clean_interface_v_type_name = '&' + clean_interface_v_type_name.replace('*', '')
101 }
102 if clean_interface_v_type_name.contains('_T_') {
103 clean_interface_v_type_name =
104 clean_interface_v_type_name.replace('Array_', '[]').replace('_T_', '<').replace('_', ', ') +
105 '>'
106 }
107 clean_interface_v_type_name = util.strip_main_name(clean_interface_v_type_name)
108 fn_builder.writeln('function ${copy_fn_name}(x) { return x; }')
109 /*
110 for typ in info.types {
111 subtype := g.table.sym(typ)
112 mut func_name := g.get_copy_fn(typ)
113 if typ == ast.string_type {
114
115 fn_builder.write_string('\tif (x instanceof string)')
116 fn_builder.write_string(' return new string(x.str + "");')
117 } else {
118 /*
119 mut val := '${func_name}(${deref}(${subtype.cname}*)x._${subtype.cname}'
120 if should_use_indent_func(subtype.kind) && !sym_has_str_method {
121 val += ', indent_count'
122 }
123 val += ')'
124 val = val
125 */
126 res := '"TODO'
127 fn_builder.write_string('\tif (x instanceof ${g.styp(typ)})')
128 fn_builder.write_string(' return ${func_name}(x);\n')
129 }
130 }
131 fn_builder.writeln('\tbuiltin__panic("unknown interface value");')
132 fn_builder.writeln('}')*/
133 g.definitions.writeln(fn_builder.str())
134}
135
136fn (mut g JsGen) gen_copy_for_fn_type(_info ast.FnType, _styp string, copy_fn_name string) {
137 g.definitions.writeln('function ${copy_fn_name} (x) { return x; }')
138}
139
140fn (mut g JsGen) gen_copy_for_array(_info ast.Array, _styp string, copy_fn_name string) {
141 g.definitions.writeln('function ${copy_fn_name} (x) { return x; }')
142}
143
144fn (mut g JsGen) gen_copy_for_array_fixed(_info ast.ArrayFixed, _styp string, copy_fn_name string) {
145 g.definitions.writeln('function ${copy_fn_name} (x) { return x; }')
146}
147
148fn (mut g JsGen) gen_copy_for_map(_info ast.Map, _styp string, copy_fn_name string) {
149 g.definitions.writeln('function ${copy_fn_name} (x) { return x; }')
150}
151
152fn (mut g JsGen) gen_copy_for_struct(_info ast.Struct, _styp string, copy_fn_name string) {
153 mut fn_builder := strings.new_builder(512)
154 defer {
155 g.definitions.writeln(fn_builder.str())
156 }
157
158 fn_builder.writeln('function ${copy_fn_name}(it) { return it }')
159
160 /*
161 tmp := g.new_tmp_var()
162 fn_builder.writeln('\tlet ${tmp} = new ${styp}({});')
163 for field in info.fields {
164 println(field)
165 if field.name == '' {
166
167 } else {
168 mut shall_copy := true
169 for attr in field.attrs {
170 if attr.name == 'noinit' {
171 shall_copy = false
172 break
173 }
174 }
175 if shall_copy {
176 func_name := g.get_copy_fn(field.typ)
177 fn_builder.writeln('\t${tmp}.${field.name} = ${func_name}(it.${field.name});')
178 } else {
179 fn_builder.writeln('\t${tmp}.${field.name} = it.${field.name}')
180 }
181 }
182 }
183 fn_builder.writeln('\treturn ${tmp};\n}')*/
184}
185
186fn (mut g JsGen) final_gen_copy(typ StrType) {
187 if typ in g.generated_copy_fns {
188 return
189 }
190 g.generated_copy_fns << typ
191 sym := g.table.sym(typ.typ)
192 if sym.has_method('\$copy') && !typ.typ.has_flag(.option) {
193 return
194 }
195 styp := typ.styp
196 copy_fn_name := styp_to_copy_fn_name(styp)
197 if typ.typ.has_flag(.option) {
198 g.gen_copy_for_option(typ.typ, styp, copy_fn_name)
199 return
200 }
201 match styp {
202 'byte', 'u8', 'u16', 'u32', 'u64', 'i16', 'i32', 'int', 'i64', 'isize', 'usize', 'bool',
203 'char', 'rune', 'int_literal', 'float_literal', 'f32', 'f64', 'voidptr' {
204 g.definitions.writeln('function ${sym.cname}_\$copy(it) { return new ${sym.cname}(it.val); }')
205 return
206 }
207 else {}
208 }
209
210 match sym.info {
211 ast.Alias {
212 g.gen_copy_for_alias(sym.info, styp, copy_fn_name)
213 }
214 ast.Array {
215 g.gen_copy_for_array(sym.info, styp, copy_fn_name)
216 }
217 ast.ArrayFixed {
218 g.gen_copy_for_array_fixed(sym.info, styp, copy_fn_name)
219 }
220 ast.Enum {
221 g.gen_copy_for_enum(sym.info, styp, copy_fn_name)
222 }
223 ast.FnType {
224 g.gen_copy_for_fn_type(sym.info, styp, copy_fn_name)
225 }
226 ast.Struct {
227 g.gen_copy_for_struct(sym.info, styp, copy_fn_name)
228 }
229 ast.Map {
230 g.gen_copy_for_map(sym.info, styp, copy_fn_name)
231 }
232 ast.MultiReturn {
233 g.gen_copy_for_multi_return(sym.info, styp, copy_fn_name)
234 }
235 ast.SumType {
236 g.gen_copy_for_union_sum_type(sym.info, styp, copy_fn_name)
237 }
238 ast.Interface {
239 g.gen_copy_for_interface(sym.info, styp, copy_fn_name)
240 }
241 else {
242 verror("could not generate string method ${copy_fn_name} for type '${styp}'")
243 }
244 }
245}
246