121 lines
6.3 KiB
Plaintext
121 lines
6.3 KiB
Plaintext
用Python做一个适用于 自制操作系统 的 编译器,用于实现Python转C,使用ast抽象语法树的解析转换文件内容(C到Python用pycparser)
|
||
|
||
需要达到一下要求:
|
||
1.不需要支持第三方或自带的模块
|
||
2.需要支持全部内部的定义方法,包括关键字,比如if for while break continue等,语句判断需要支持and or not is == != >= <= > < 等。
|
||
3.需要支持乘法、除法加法减法和异或计算。
|
||
3.True 和 False 通过定义宏1/0实现。
|
||
4.class转换比较复杂(支持面向对象),而且不能使用任何库,转换为C的类内常量和类外函数,Python通过映射表映射到函数上。
|
||
5.你需要书写c.py和t.py,如果有导入xxx的库名为c或t直接忽略,这是py2c的内部语义库。
|
||
其它所有import xxx或from xxx import xxx统一都翻译为#include xxx
|
||
注意不能忽略,只有c和t可以忽略,其它的都要翻译为#include xxx,并且注释上原语句,在再次Python化时就可以直接套用原语句了
|
||
6.import 只需要 include对应的文件,import的文件应该已经一起被翻译成c或h了,
|
||
从别的模块导入的函数需要去掉模块名称,而且要加上namespce处理,注意代码缩进。
|
||
7.注意函数调用和结构体实例化的实现,还有value和key不准变成None。
|
||
8.请你实现,并且注意C的极端小众的表达,并想好如何在Python中语义化表达,比如asm,range简化,class简化,typedef 和其后缀,指针操作,define,宏。
|
||
9.有一些C中的极端语句,Python无法语义化,比如asm,指针操作等指令。
|
||
提供一个扩展库c.pyi,py2c在转化时直接忽略import c等相关语句,将c.*比如c.asm("""""", *args, ...)直接转为C asm具体语义,
|
||
比如 asm volatile (
|
||
"movb $0x0e, %%ah\n"
|
||
"int $0x10\n"
|
||
: : "a"(c)
|
||
);这种语句和类似特殊语句的实现
|
||
10.支持双向转换(py->c,c->py),对于不知道含义的函数就当没看见就好了,直接按照通用语义转换。
|
||
11.支持内存地址硬编码赋值等(c.py)
|
||
12.强制类型转换赋值
|
||
13.区分class xxx()和class xxx(c.class_point),普通结构体和结构体指针
|
||
14.支持结构体成员嵌套访问
|
||
15.支持结构体数组+指针索引访问,实现结构体数组的Python语义映射(l: c.class_list = [])
|
||
16.static 关键字支持(i: t.Static | t.CInt)
|
||
17.支持栈指针直接操作,ESP,语义映射
|
||
18.支持宏常量强制类型转换(依赖c.py)
|
||
19.支持高级位运算和多层嵌套逻辑或位运算组合
|
||
20.对于#define宏,使用t.CDefine(t.CType)作为类型表示
|
||
21.对于仅声明暂不定义的量,用xxx: xxx = c.State
|
||
22.对于Python的函数,要求其返回值和参数必须注解,def example(e1: t.CType) -> t.CType: xxx
|
||
这样才能正确转换为C函数,比如def xxx(e1: t.CChar) -> t.CInt: xxx转为int xxx(char e1) {xxx}。
|
||
若函数无返回值,可以写 def xxx(e1: t.CChar) -> None: xxx或def xxx(e1: t.CChar) -> t.CVoid: xxx 或不进行注解
|
||
对于语法,需要写在c.py。
|
||
对于类型,需要写在t.py,比如c_int、c_char等,而不是直接写int,不然会出现冲突。
|
||
c.py和t.py的定义都需要写元数据以及语法定义,通过元数据和元函数来实现具体的语法定义,以便于扩展,比如
|
||
class CInt(t.CType):
|
||
def __init__(self):
|
||
self.CName = 'int'
|
||
super().__init__()
|
||
def ...
|
||
23.对于C->Py和Py->C的翻译,更多地通过c.py和t.py中t.CType和c.CGrammar来实现,也就是在通过ast或pycparser解析后,
|
||
如果可以的话把数据类型交给t.CType委托处理,语法给c.CGrammar委托处理,而不是硬编码在Py2C主程序中。
|
||
24.禁止使用硬编码来偷懒!
|
||
对于需要多个类型的情况,比如 static char *str = "hello";
|
||
在 Python 中仅需定义 str: t.CStatic | t.Char | t.Ptr = "hello";
|
||
无需定义 t.CStaticCharPtr 这种复杂的类型,直接用 t.CStatic | t.Char | t.Ptr 即可。
|
||
允许使用元函数修改多种类型的组合方式,比如
|
||
class CStatic(t.CType):
|
||
def __init__(self):
|
||
self.CName = 'static char *'
|
||
super().__init__()
|
||
def __merge__(self, types: list):
|
||
# 此处 types 为多个父为 t.Ctypes,比如 [t.CStatic, t.Char, t.Ptr]
|
||
# 在此处我需要返回我修改后的 types,比如假设我与 t.Ptr 冲突(实际上并不冲突,只是作示例),那就返回 [t.CStatic, t.Char]
|
||
if t.Ptr in types:
|
||
types.remove(t.Ptr)
|
||
return types
|
||
以此类推,支持更多种类型。
|
||
你需要默认支持的类型:
|
||
char
|
||
int
|
||
short
|
||
long
|
||
float
|
||
double
|
||
void
|
||
unsigned char
|
||
unsigned int
|
||
unsigned short
|
||
unsigned long
|
||
signed char
|
||
struct
|
||
union
|
||
enum
|
||
typedef
|
||
auto
|
||
register
|
||
static
|
||
extern
|
||
const
|
||
volatile
|
||
size_t
|
||
int8_t
|
||
int16_t
|
||
int32_t
|
||
int64_t
|
||
uint8_t
|
||
uint16_t
|
||
uint32_t
|
||
uint64_t
|
||
intptr_t
|
||
uintptr_t
|
||
ptrdiff_t
|
||
wchar_t
|
||
char16_t
|
||
char32_t
|
||
bool
|
||
_Complex
|
||
_Imaginary
|
||
|
||
注意,转换后的python或c需要符合其语法规范,不能有语法错误。
|
||
还有就是,C中的所有函数,都请你当作普通函数(定义在其它h文件),也就是不需要考虑函数的定义和实现。
|
||
如果有-wh参数,后面会带着几个h文件,也就是这些函数的定义,你可以进行参考,如果没有就算了,按默认方法处理。
|
||
代码格式要求:所有命名都使用帕斯卡命名法,首字母大写,缩写大写,不需要注释,最简代码,但人类可读。
|
||
你可以写一个入口程序,再写多个小库在./lib中,来降低复杂度,./lib文件夹已创建,无需检查。
|
||
禁止使用硬编码偷懒!
|
||
|
||
执行方法:
|
||
python TransPyC.py -f test.py -o test.c
|
||
python TransPyC.py -f test.c -o test2.py -wh test.h
|
||
仅需一个Python文件
|
||
|
||
然后你需要尝试将test.c转为test.py并验证是否正确,再将test.py转为test2.c并验证是否和test.c语义相同。
|
||
test.c已存在,这是一个略微复杂的操作系统C程序,需要你进行完整转换。
|
||
我已经给了你example_test.py,作为目标转换结果的参考。
|
||
中文输出 |