-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexport.v
More file actions
202 lines (175 loc) · 6.01 KB
/
Copy pathexport.v
File metadata and controls
202 lines (175 loc) · 6.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
module compiler
import os
import strings
import compiler.builder
import compiler.repr
fn (c Compiler) collect_non_type_fragments() builder.ExportFragments {
mut fragments := builder.ExportFragments{}
c_emitter := CGenerator{
ext_name: c.ext_name
class_ce_by_type: c.class_ce_map()
class_php_by_type: c.class_php_map()
table: c.table
}
for el in c.elements {
if el is repr.PhpFuncRepr {
fragments.merge(c_emitter.build_func_export(el))
} else if el is repr.PhpConstRepr {
if el.has_php_const && el.const_type != 'struct' {
fragments.merge(c_emitter.build_global_constant(el).export_fragments())
}
}
}
return fragments
}
fn (c Compiler) collect_type_fragments() builder.ExportFragments {
mut fragments := builder.ExportFragments{}
c_emitter := CGenerator{
ext_name: c.ext_name
class_ce_by_type: c.class_ce_map()
class_php_by_type: c.class_php_map()
table: c.table
}
for el in c.elements {
if el is repr.PhpInterfaceRepr {
fragments.merge(c_emitter.build_interface_export(el))
}
}
for el in c.elements {
if el is repr.PhpClassRepr && !el.is_trait {
fragments.merge(c_emitter.build_class_export(el))
} else if el is repr.PhpEnumRepr {
fragments.merge(c_emitter.build_enum_export(el))
}
}
return fragments
}
// ==========================================
// 1. 总入口:由外部 build.v 调用
// ==========================================
pub fn (mut c Compiler) generate_all() ! {
c.generate_h()!
c.generate_c()!
c.generate_v_glue()!
}
// ==========================================
// 2. 生成 C 源文件 (php_bridge.c)
// ==========================================
fn (mut c Compiler) generate_c() ! {
mut res := strings.new_builder(2048)
res.write_string('/* ⚠️ VPHP Compiler Generated for ${c.ext_name} */\n')
res.write_string('#include "php_bridge.h"\n\n')
res.write_string('#include "../vphp/v_bridge.h"\n\n')
// 2. 模块层:初始化 ModuleBuilder 并收集功能点
mut mod_builder := builder.new_module_builder(c.ext_name, c.ext_version, c.ext_description)
mut fragments := c.collect_non_type_fragments()
mut type_fragments := c.collect_type_fragments()
for k, v in c.ini_entries {
mod_builder.add_ini_entry(k, v)
}
mod_builder.globals = c.globals_repr
res.write_string(mod_builder.render_declarations())
// 1. 业务逻辑层:写入每个导出单元的实例实现
for line in fragments.implementations {
res.write_string(line + '\n')
}
for line in type_fragments.implementations {
res.write_string(line + '\n')
}
for fn_builder in fragments.function_table {
mod_builder.add_function(fn_builder)
}
// 注入 MINIT 内容
for line in fragments.minit_lines {
mod_builder.add_minit_line(line)
}
for line in type_fragments.minit_lines {
mod_builder.add_minit_line(line)
}
for line in fragments.rinit_lines {
mod_builder.add_rinit_line(line)
}
for line in type_fragments.rinit_lines {
mod_builder.add_rinit_line(line)
}
// 3. 渲染各个 C 块
res.write_string(mod_builder.render_globals_struct())
res.write_string(mod_builder.render_ginit())
res.write_string(mod_builder.render_ini_entries())
res.write_string(mod_builder.render_functions_table())
res.write_string(mod_builder.render_minit())
res.write_string(mod_builder.render_mshutdown())
res.write_string(mod_builder.render_rinit())
res.write_string(mod_builder.render_rshutdown())
res.write_string(mod_builder.render_minfo())
res.write_string(mod_builder.render_globals_getter())
res.write_string(mod_builder.render_module_entry())
res.write_string(mod_builder.render_get_module())
os.write_file('php_bridge.c', res.str())!
}
// ==========================================
// 3. 生成 V 胶水代码 (_task_glue.v)
// ==========================================
fn (mut c Compiler) generate_v_glue() ! {
v_glue := VGenerator{
ext_name: c.ext_name
globals_repr: c.globals_repr
params_structs: c.params_structs
table: c.table
}
v_code := v_glue.generate(mut c.elements)
os.write_file(c.bridge_output_path(), v_code)!
v_glue.generate_modules(c.elements, c.target_files)!
}
fn (c Compiler) bridge_output_path() string {
if c.target_files.len == 0 {
return 'vphp_bridge.v'
}
mut target_dir := os.dir(c.target_files[0])
for file in c.target_files[1..] {
dir := os.dir(file)
if dir.len < target_dir.len {
target_dir = dir
}
}
if target_dir == '' {
return 'vphp_bridge.v'
}
return os.join_path(target_dir, 'vphp_bridge.v')
}
// ==========================================
// 4. 生成头文件 (php_bridge.h)
// ==========================================
fn (mut c Compiler) generate_h() ! {
mut res := strings.new_builder(1024)
// 1. 写入文件头和头文件保护 (Header Guard)
res.write_string('/* ⚠️ VPHP Compiler Generated,请勿手动修改 */\n')
guard := 'VPHP_EXT_${c.ext_name.to_upper()}_BRIDGE_H'
res.write_string('#ifndef ${guard}\n')
res.write_string('#define ${guard}\n\n')
// 2. 引入必要的 PHP 内核头文件
res.write_string('#include <php.h>\n')
res.write_string('#include <Zend/zend_attributes.h>\n')
res.write_string('#include <Zend/zend_enum.h>\n')
res.write_string('#include <ext/standard/info.h>\n\n')
res.write_string('#ifndef ZEND_ACC_READONLY_CLASS\n')
res.write_string('#define ZEND_ACC_READONLY_CLASS 0\n')
res.write_string('#endif\n\n')
// 3. 写入扩展模块入口声明
res.write_string('extern zend_module_entry ${c.ext_name}_module_entry;\n')
res.write_string('#define phpext_${c.ext_name}_ptr &${c.ext_name}_module_entry\n\n')
res.write_string('extern void* vphp_get_active_globals();\n\n')
fragments := c.collect_non_type_fragments()
type_fragments := c.collect_type_fragments()
for line in fragments.declarations {
res.write_string(line + '\n')
}
for line in type_fragments.declarations {
res.write_string(line + '\n')
}
// 6. 写入头文件保护结束
res.write_string('#endif\n')
// 7. 物理写入文件
os.write_file('php_bridge.h', res.str()) or { return error('无法写入 php_bridge.h: $err') }
println(' - [Generator] 已生成 php_bridge.h')
}