support .h gen for every .pyi to avoid compile err

This commit is contained in:
Lyon 2023-07-16 14:59:19 +08:00
parent a61e393a9c
commit b0229741ec
4 changed files with 82 additions and 11 deletions

View File

@ -17,6 +17,7 @@ pub struct ClassInfo {
pub import_list: BTreeMap<String, ImportInfo>,
pub script_list: Script,
pub is_package: bool,
pub is_top: bool,
}
impl ClassInfo {
@ -68,6 +69,7 @@ impl ClassInfo {
import_list: BTreeMap::new(),
script_list: Script::new(),
is_package: is_package,
is_top: false,
};
return Some(new_class_info);
}

View File

@ -316,7 +316,7 @@ impl Compiler {
let mut file_str = String::new();
file.read_to_string(&mut file_str).unwrap();
if is_top_c_pkg {
if suffix == "pyi" {
/*
Push top C package to PikaMain.
Solve the package as a class
@ -324,15 +324,30 @@ impl Compiler {
class PikaStdDevice(TinyObj):
*/
let pkg_define = format!("class {}(TinyObj):", &file_name);
let package_now = match ClassInfo::new(&String::from(""), &pkg_define, true) {
let mut package_now = match ClassInfo::new(&String::from(""), &pkg_define, true) {
Some(s) => s,
None => return self,
};
let package_name = package_now.this_class_name.clone();
self.class_list
.entry(package_name.clone())
.or_insert(package_now);
self.package_name_now = Some(package_name.clone());
let package_name = file_name.clone();
// println!("package_name: {}", package_name);
if is_top_c_pkg {
self.package_name_now = Some(package_name.clone());
package_now.is_top = true;
println!("set top package: {}", package_name);
}
match self.class_list.entry(package_name.clone()) {
std::collections::btree_map::Entry::Occupied(mut entry) => {
// 如果 `package_now.is_top == true`,将 `class_list` 中对应项的 `is_top` 设为 `true`
if package_now.is_top {
let class_info = entry.get_mut();
// 需要确保 `ClassInfo` 结构体中存在 `is_top` 字段
class_info.is_top = true;
}
}
std::collections::btree_map::Entry::Vacant(entry) => {
entry.insert(package_now);
}
}
}
/* return when compiled */

View File

@ -1,7 +1,30 @@
use crate::compiler::*;
use crate::version_info::*;
use std::collections::HashSet;
use std::fs;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;
fn collect_pyi_files(dir: &Path) -> std::io::Result<Vec<String>> {
let mut result = Vec::new();
if dir.is_dir() {
for entry in fs::read_dir(dir)? {
let entry = entry?;
let path = entry.path();
if path.is_file() && path.extension() == Some(std::ffi::OsStr::new("pyi")) {
if let Some(file_name) = path.file_name() {
if let Some(file_name_str) = file_name.to_str() {
// remove extension
let file_name_str = file_name_str.split(".").collect::<Vec<&str>>()[0];
result.push(file_name_str.to_string());
}
}
}
}
}
Ok(result)
}
pub fn pika_compiler_entry() {
let head_info = "/*
@ -39,7 +62,7 @@ pub fn pika_compiler_entry() {
if package_name == "pikascript-core" {
continue;
}
compiler = Compiler::analyse_c_package_top(compiler, String::from(package_name));
compiler = Compiler::analyse_c_package_inner(compiler, String::from(package_name));
}
/* Compile packages in PikaStdLib */
@ -47,7 +70,17 @@ pub fn pika_compiler_entry() {
compiler = Compiler::analyse_c_package_top(compiler, String::from("PikaStdData"));
compiler = Compiler::analyse_c_package_top(compiler, String::from("PikaDebug"));
compiler = Compiler::analyse_c_package_top(compiler, String::from("builtins"));
/* search all *.pyi file and analyse */
let dir = Path::new(".");
let pyi_files = collect_pyi_files(&dir);
for file in pyi_files.unwrap() {
// skip PikaObj
if file == "PikaObj" {
continue;
}
// just generate *.h to support -lib compile
compiler = Compiler::analyse_c_package_inner(compiler, file);
}
/* clean pikascript-api/ */
compiler.clean_path();
@ -65,17 +98,38 @@ pub fn pika_compiler_entry() {
let mut f = File::create(api_file_path).unwrap();
f.write(head_info.as_bytes()).unwrap();
/* create include for calsses */
let mut written_includes = HashSet::new();
f.write("#include <stdio.h>\n".as_bytes()).unwrap();
f.write("#include <stdlib.h>\n".as_bytes()).unwrap();
f.write("#include \"BaseObj.h\"\n".as_bytes()).unwrap();
written_includes.insert(String::from("#include \"BaseObj.h\"\n"));
for (_, class_info) in compiler.class_list.iter() {
/* create include for calsses */
f.write(class_info.include().as_bytes()).unwrap();
let include = class_info.include();
// 将字符串按换行符分割成多个 include
let includes: Vec<&str> = include.split('\n').collect();
for include in includes {
// 如果这个 include 之前没有被写入过
if !written_includes.contains(include) {
// 写入文件
f.write(format!("{}\n", include).as_bytes()).unwrap();
// println!("{} has been inserted", include);
written_includes.insert(include.to_string());
} else {
// println!("{} has been written, skip", include);
}
}
}
f.write("\n".as_bytes()).unwrap();
for (_, class_info) in compiler.class_list.iter() {
if class_info.is_package && !class_info.is_top{
continue;
}
/* get module_name */
let mut module_name = class_info.this_file_name.clone();
if module_name == "" {