From 24d4da89f0e71d7092c22b094014270d6b09fa58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E6=98=82?= Date: Wed, 13 Jul 2022 08:29:42 +0000 Subject: [PATCH] !51 Support bind .pyi from other *.py expect main.py * Support bind .pyi from other *.py expect main.py * update rust * fix suffix format * fix name case * supporting import pyi from other py * supporting import pyi from other py --- port/linux/.vscode/launch.json | 2 +- port/linux/package/pikascript/main.py | 10 +- src/PikaCompiler.c | 6 +- tools/pikaCompiler/main.py | 2 +- tools/pikaCompiler/src/compiler.rs | 199 ++++++++++++++++---------- tools/pikaCompiler/src/entry.rs | 10 +- tools/pikaCompiler/test.py | 1 + 7 files changed, 139 insertions(+), 91 deletions(-) create mode 100644 tools/pikaCompiler/test.py diff --git a/port/linux/.vscode/launch.json b/port/linux/.vscode/launch.json index 4f52fc4c8..60e21f8fd 100644 --- a/port/linux/.vscode/launch.json +++ b/port/linux/.vscode/launch.json @@ -11,7 +11,7 @@ "program": "${workspaceFolder}/build/test/pikascript_test", // "program": "${workspaceFolder}/build/boot/demo06-pikamain/pikascript_demo06-pikamain", "args": [ - // "--gtest_filter=parser.branket_issue3" + "--gtest_filter=PikaCV.test1" ], "stopAtEntry": false, "cwd": "${workspaceFolder}", diff --git a/port/linux/package/pikascript/main.py b/port/linux/package/pikascript/main.py index 562279814..2a9ba35f3 100644 --- a/port/linux/package/pikascript/main.py +++ b/port/linux/package/pikascript/main.py @@ -1,21 +1,17 @@ from PikaObj import * import PikaStdLib -import PikaStdData +import PikaStdDevice import ctypes import GTestTask import PikaMath -import PikaStdDevice import test_module1 import test_cmodule -import TempDevTest as dev -import TemplateDevice -import pika_cjson as cjson +import TempDevTest import cjson_test import test_module4 import pika_lua import import_test -import pika_configparser as configparser -from PikaStdData import String as S +import pika_configparser import PikaDebug import PikaCV diff --git a/src/PikaCompiler.c b/src/PikaCompiler.c index 7cee930d8..071d29a6f 100644 --- a/src/PikaCompiler.c +++ b/src/PikaCompiler.c @@ -371,7 +371,7 @@ int Lib_loadLibraryFileToArray(char* origin_file_name, char* out_folder) { FILE* fp = __platform_fopen(output_file_path, "wb+"); char* array_name = strsGetLastToken(&buffs, origin_file_name, '/'); array_name = strsReplace(&buffs, array_name, ".", "_"); - __platform_printf(" loading %s[]...\n", array_name); + __platform_printf(" loading %s[]...\n", array_name); pika_fputs("#include \"PikaPlatform.h\"\n", fp); pika_fputs("/* warning: auto generated file, please do not modify */\n", fp); @@ -404,7 +404,7 @@ static void __Maker_compileModuleWithInfo(PikaMaker* self, char* module_name) { char* input_file_name = strsAppend(&buffs, module_name, ".py"); char* input_file_path = strsAppend(&buffs, obj_getStr(self, "pwd"), input_file_name); - __platform_printf(" compiling %s...\r\n", input_file_name); + __platform_printf(" compiling %s...\r\n", input_file_name); char* output_file_name = strsAppend(&buffs, module_name, ".py.o"); char* output_file_path = NULL; output_file_path = @@ -591,7 +591,7 @@ void pikaMaker_linkCompiledModulesFullPath(PikaMaker* self, char* lib_path) { Args context = {0}; LibObj* lib = New_LibObj(NULL); Args buffs = {0}; - __platform_printf(" linking %s...\n", lib_path); + __platform_printf(" linking %s...\n", lib_path); args_setPtr(&context, "__lib", lib); args_setPtr(&context, "__maker", self); args_foreach(self->list, __foreach_handler_linkCompiledModules, &context); diff --git a/tools/pikaCompiler/main.py b/tools/pikaCompiler/main.py index 0be21ccb6..403f5ff2a 100644 --- a/tools/pikaCompiler/main.py +++ b/tools/pikaCompiler/main.py @@ -1,5 +1,5 @@ import PikaStdLib -import PyInfo +import test from pika_cjson import cJSON print('hello pikascript!') mem = PikaStdLib.MemChecker() diff --git a/tools/pikaCompiler/src/compiler.rs b/tools/pikaCompiler/src/compiler.rs index 47cb6e24c..0586c6df8 100644 --- a/tools/pikaCompiler/src/compiler.rs +++ b/tools/pikaCompiler/src/compiler.rs @@ -7,6 +7,14 @@ use std::fs; use std::fs::File; use std::io; use std::io::prelude::*; + +enum PackageType { + CPackageTop, + CPackageInner, + PyPackageTop, + PyPackageInner, +} + #[derive(Debug)] pub struct Compiler { pub dist_path: String, @@ -30,9 +38,17 @@ impl Compiler { return compiler; } - pub fn analyse_main_line(mut compiler: Compiler, line: &String) -> Compiler { - let file_name = "main".to_string(); - let class_name = "PikaMain".to_string(); + pub fn analyse_py_line(mut compiler: Compiler, line: &String, is_top_pkg: bool) -> Compiler { + let file_name = match is_top_pkg { + true => "main".to_string(), + false => "".to_string(), + }; + + let class_name = match is_top_pkg { + true => "PikaMain".to_string(), + false => "".to_string(), + }; + /* get class now or create one */ let class_now = match compiler.class_list.get_mut(&"PikaMain".to_string()) { Some(class_now) => class_now, @@ -53,40 +69,18 @@ impl Compiler { if package_name == "PikaObj" { return compiler; } - /* add to script */ - class_now.script_list.add(&line); - /* check file, break if *.py no found */ - match Compiler::open_file(format!("{}{}.pyi", compiler.source_path, package_name)) { - Ok(_) => {} - Err(_) => { - /* if *.py exits, not print warning */ - match Compiler::open_file(format!( - "{}{}.py", - compiler.source_path, package_name - )) { - Ok(_) => { - return compiler; - } - Err(_) => { - println!( - " [warning]: file: '{}{}.pyi' or '{}{}.py' no found", - compiler.source_path, - package_name, - compiler.source_path, - package_name - ); - return compiler; - } - }; - } - }; + if is_top_pkg { + /* add to script */ + class_now.script_list.add(&line); + } - let package_obj_define = format!("{} = {}()", package_name, package_name); - class_now.push_object(package_obj_define, &file_name); - return Compiler::analyse_top_package(compiler, package_name.to_string()); + return Compiler::analyse_package_from_py(compiler, package_name.to_string()); + } + + if is_top_pkg { + class_now.script_list.add(&line); } - class_now.script_list.add(&line); return compiler; } @@ -103,24 +97,66 @@ impl Compiler { return Err(std::io::Error::from(std::io::ErrorKind::NotFound)); } - pub fn analyse_top_package(self: Compiler, file_name: String) -> Compiler { - return self.__do_analyse_file(file_name, true); + pub fn analyse_py_package_main(self: Compiler, file_name: String) -> Compiler { + return self.__do_analyse_file(file_name, PackageType::PyPackageTop); } - pub fn analyse_inner_package(self: Compiler, file_name: String) -> Compiler { - return self.__do_analyse_file(file_name, false); + pub fn analyse_py_package_inner(self: Compiler, file_name: String) -> Compiler { + return self.__do_analyse_file(file_name, PackageType::PyPackageInner); } - fn __do_analyse_file(mut self: Compiler, file_name: String, is_top_pkg: bool) -> Compiler { + pub fn analyse_c_package_top(self: Compiler, file_name: String) -> Compiler { + return self.__do_analyse_file(file_name, PackageType::CPackageTop); + } + + pub fn analyse_c_package_inner(self: Compiler, file_name: String) -> Compiler { + return self.__do_analyse_file(file_name, PackageType::CPackageInner); + } + + pub fn analyse_package_from_py(mut self: Compiler, file_name: String) -> Compiler { + let suffix = String::from("pyi"); /* open file */ let file: std::result::Result; - if file_name == "main" { - /* only the main.py is the .py file */ - file = Compiler::open_file(format!("{}main.py", self.source_path)); - } else { - /* other module is CMoudle, which is .pyi file */ - file = Compiler::open_file(format!("{}{}.pyi", self.source_path, file_name)); - } + file = Compiler::open_file(format!("{}{}.{}", self.source_path, file_name, suffix)); + match file { + /* py import pyi => top_pyi */ + Ok(_) => { + let class_now = match self.class_list.get_mut(&"PikaMain".to_string()) { + Some(class_now) => class_now, + None => return self, + }; + + /* create constructor for PikaMain */ + let package_obj_define = format!("{} = {}()", file_name, file_name); + class_now.push_object(package_obj_define, &"main".to_string()); + + return Compiler::analyse_c_package_top(self, file_name); + } + Err(_) => { + /* py import py => inner_py */ + return self.analyse_py_package_inner(file_name.clone()); + } + }; + } + + fn __do_analyse_file(mut self: Compiler, file_name: String, pkg_type: PackageType) -> Compiler { + let is_top_c_pkg = match pkg_type { + PackageType::CPackageTop => true, + _ => false, + }; + + let is_top_py_pkg: bool = match pkg_type { + PackageType::PyPackageTop => true, + _ => false, + }; + + let suffix = match pkg_type { + PackageType::CPackageTop | PackageType::CPackageInner => "pyi", + PackageType::PyPackageTop | PackageType::PyPackageInner => "py", + }; + /* open file */ + let file: std::result::Result; + file = Compiler::open_file(format!("{}{}.{}", self.source_path, file_name, suffix)); /* If the .pyi no exist, check if the .py exist @@ -130,32 +166,41 @@ impl Compiler { let mut file = match file { Ok(file) => file, Err(_) => { - /* if *.py exits, not print warning */ - let file_py = Compiler::open_file(format!("{}{}.py", self.source_path, file_name)); - match file_py { - Ok(_) => { - return self; - } - Err(_) => { - println!( - " [warning]: file: '{}{}.pyi' or '{}{}.py' no found", - self.source_path, file_name, self.source_path, file_name - ); - return self; - } - }; + if suffix == "pyi" { + /* if .pyi no exist, check .py exist */ + return self.analyse_py_package_inner(file_name.clone()); + } + + /* .py no exist, error */ + println!( + " [warning]: file: '{}{}.pyi' or '{}{}.py' no found", + self.source_path, file_name, self.source_path, file_name + ); + return self; } }; let mut file_str = String::new(); file.read_to_string(&mut file_str).unwrap(); - /* check if compiled */ - if self.compiled_list.contains(&file_name) { - } else if file_name == "main" { - println!(" scaning {}{}.py...", self.source_path, file_name); - } else { - println!(" binding {}{}.pyi...", self.source_path, file_name); + /* return when compiled */ + if !self.compiled_list.contains(&file_name) { + /* print info */ + match suffix { + "py" => { + println!( + " scaning {}{}.{}...", + self.source_path, file_name, suffix + ); + } + "pyi" => { + println!( + " binding {}{}.{}...", + self.source_path, file_name, suffix + ); + } + _ => {} + } } /* push to compiled list, only compile once */ @@ -170,8 +215,10 @@ impl Compiler { object. To implament this, a [package]-api.c file is created to supply the class of static object. */ - if file_name != "main" && is_top_pkg { + + if is_top_c_pkg { /* + Push top C package to PikaMain. Solve the package as a class [Example]: class PikaStdDevice(TinyObj): @@ -187,18 +234,22 @@ impl Compiler { .or_insert(package_now); self.package_now_name = Some(package_name.clone()); } + let lines: Vec<&str> = file_str.split('\n').collect(); - /* analyse each line of .pyi */ + /* analyse each line */ for line in lines.iter() { let line = line.replace("\r", ""); /* replace \t with 4 spaces */ let line = line.replace("\t", " "); - if file_name == "main" { - self = Compiler::analyse_main_line(self, &line); - } else { - self = Compiler::analyse_pyi_line(self, line.to_string(), &file_name, is_top_pkg); - } + self = match pkg_type { + PackageType::CPackageTop | PackageType::CPackageInner => { + Compiler::analyse_pyi_line(self, line.to_string(), &file_name, is_top_c_pkg) + } + PackageType::PyPackageTop | PackageType::PyPackageInner => { + Compiler::analyse_py_line(self, &line, is_top_py_pkg) + } + }; } return self; } @@ -212,7 +263,7 @@ impl Compiler { if line.starts_with("import ") { let tokens: Vec<&str> = line.split(" ").collect(); let file = tokens[1]; - return Compiler::analyse_inner_package(compiler, file.to_string()); + return Compiler::analyse_c_package_inner(compiler, file.to_string()); } if line.starts_with("#") { diff --git a/tools/pikaCompiler/src/entry.rs b/tools/pikaCompiler/src/entry.rs index 527e72bf5..8a507c102 100644 --- a/tools/pikaCompiler/src/entry.rs +++ b/tools/pikaCompiler/src/entry.rs @@ -15,7 +15,7 @@ pub fn pika_compiler_entry() { let mut compiler = Compiler::new(String::from(""), String::from("pikascript-api/")); /* analyse file begin with main.py */ - compiler = Compiler::analyse_top_package(compiler, String::from("main")); + compiler = Compiler::analyse_py_package_main(compiler, String::from("main")); /* Compile packages in requestment.txt, solve the packages as the top packages. @@ -26,13 +26,13 @@ pub fn pika_compiler_entry() { if package_name == "pikascript-core" { continue; } - compiler = Compiler::analyse_top_package(compiler, String::from(package_name)); + compiler = Compiler::analyse_c_package_top(compiler, String::from(package_name)); } /* Compile packages in PikaStdLib */ - compiler = Compiler::analyse_top_package(compiler, String::from("PikaStdTask")); - compiler = Compiler::analyse_top_package(compiler, String::from("PikaStdData")); - compiler = Compiler::analyse_top_package(compiler, String::from("PikaDebug")); + compiler = Compiler::analyse_c_package_top(compiler, String::from("PikaStdTask")); + compiler = Compiler::analyse_c_package_top(compiler, String::from("PikaStdData")); + compiler = Compiler::analyse_c_package_top(compiler, String::from("PikaDebug")); // println!(); diff --git a/tools/pikaCompiler/test.py b/tools/pikaCompiler/test.py new file mode 100644 index 000000000..e8e23d7e9 --- /dev/null +++ b/tools/pikaCompiler/test.py @@ -0,0 +1 @@ +import PyInfo \ No newline at end of file