mirror of
https://gitee.com/Lyon1998/pikapython.git
synced 2025-01-15 17:02:53 +08:00
add compiler-rust as normal file
This commit is contained in:
parent
7e0b3b279f
commit
460733d914
2
pikascript-compiler-rust/.gitignore
vendored
Normal file
2
pikascript-compiler-rust/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/target
|
||||
/pikascript-api
|
27
pikascript-compiler-rust/.vscode/launch.json
vendored
Normal file
27
pikascript-compiler-rust/.vscode/launch.json
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "(gdb) Launch",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/target/debug/rust-msc",
|
||||
"args": [],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceFolder}",
|
||||
"environment": [],
|
||||
"externalConsole": false,
|
||||
"MIMode": "gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
11
pikascript-compiler-rust/Arm2D.py
Normal file
11
pikascript-compiler-rust/Arm2D.py
Normal file
@ -0,0 +1,11 @@
|
||||
from PikaObj import *
|
||||
|
||||
class Line(TinyObj):
|
||||
def new():
|
||||
pass
|
||||
|
||||
def delete():
|
||||
pass
|
||||
|
||||
def moveTo(x: int, y: int):
|
||||
pass
|
7
pikascript-compiler-rust/Cargo.lock
generated
Normal file
7
pikascript-compiler-rust/Cargo.lock
generated
Normal file
@ -0,0 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "rust-msc"
|
||||
version = "0.1.0"
|
7
pikascript-compiler-rust/Cargo.toml
Normal file
7
pikascript-compiler-rust/Cargo.toml
Normal file
@ -0,0 +1,7 @@
|
||||
[package]
|
||||
name = "rust-msc"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
[dependencies]
|
14
pikascript-compiler-rust/PikaObj.py
Normal file
14
pikascript-compiler-rust/PikaObj.py
Normal file
@ -0,0 +1,14 @@
|
||||
class TinyObj:
|
||||
pass
|
||||
|
||||
|
||||
class BaseObj(TinyObj):
|
||||
pass
|
||||
|
||||
|
||||
def print(val: any):
|
||||
pass
|
||||
|
||||
|
||||
def set(argPath: str, val: any):
|
||||
pass
|
27
pikascript-compiler-rust/PikaStdLib.py
Normal file
27
pikascript-compiler-rust/PikaStdLib.py
Normal file
@ -0,0 +1,27 @@
|
||||
from PikaObj import *
|
||||
|
||||
|
||||
class MemChecker(BaseObj):
|
||||
def max():
|
||||
pass
|
||||
|
||||
def now():
|
||||
pass
|
||||
|
||||
def resetMax():
|
||||
pass
|
||||
|
||||
|
||||
class SysObj(BaseObj):
|
||||
|
||||
def type(argPath: str):
|
||||
pass
|
||||
|
||||
def ls(objPath: str):
|
||||
pass
|
||||
|
||||
def remove(argPath: str):
|
||||
pass
|
||||
|
||||
def new(objPath: str, classPath: str):
|
||||
pass
|
39
pikascript-compiler-rust/PyInfo.py
Normal file
39
pikascript-compiler-rust/PyInfo.py
Normal file
@ -0,0 +1,39 @@
|
||||
class PyObj(BaseObj):
|
||||
|
||||
def importClass(className: str, fp: str):
|
||||
pass
|
||||
|
||||
def newObj(objName: str, className: str, fp: str):
|
||||
pass
|
||||
|
||||
def makeInlcude(fp: str):
|
||||
pass
|
||||
|
||||
def makeNewObj(fp: str):
|
||||
pass
|
||||
|
||||
def getInclude() -> str:
|
||||
pass
|
||||
|
||||
|
||||
class PyMethod (SysObj):
|
||||
def makeMethodFun(fp: str):
|
||||
pass
|
||||
|
||||
def makeMethodDeclear(fp: str):
|
||||
pass
|
||||
|
||||
def makeMethodDefine(fp: str):
|
||||
pass
|
||||
|
||||
class PyClass(SysObj):
|
||||
obj = PyObj()
|
||||
PyMethod()
|
||||
def setSuper(superClassName: str):
|
||||
pass
|
||||
|
||||
def makeApi(path: str):
|
||||
pass
|
||||
|
||||
def makeHead(path: str):
|
||||
pass
|
2
pikascript-compiler-rust/README.md
Normal file
2
pikascript-compiler-rust/README.md
Normal file
@ -0,0 +1,2 @@
|
||||
# pikascript-compiler-rust
|
||||
|
22
pikascript-compiler-rust/application.py
Normal file
22
pikascript-compiler-rust/application.py
Normal file
@ -0,0 +1,22 @@
|
||||
import PyInfo
|
||||
import Arm2D
|
||||
import PikaStdLib
|
||||
from PikaObj import *
|
||||
|
||||
class Compiler(PikaStdLib.SysObj):
|
||||
obj = PyInfo.PyObj()
|
||||
PyInfo.PyMethod()
|
||||
PyInfo.PyClass()
|
||||
line = Arm2D.Line()
|
||||
|
||||
def build(pythonApiPath: str, outputPath: str) -> int:
|
||||
pass
|
||||
|
||||
def analyzestr(pythonApiPath: str) -> int:
|
||||
pass
|
||||
|
||||
def analyzeLine(line: str) -> int:
|
||||
pass
|
||||
|
||||
class MyRoot(PikaStdLib.SysObj):
|
||||
compiler = Compiler()
|
2
pikascript-compiler-rust/init.sh
Normal file
2
pikascript-compiler-rust/init.sh
Normal file
@ -0,0 +1,2 @@
|
||||
rm pikascript-api -rf
|
||||
mkdir pikascript-api
|
7
pikascript-compiler-rust/main.py
Normal file
7
pikascript-compiler-rust/main.py
Normal file
@ -0,0 +1,7 @@
|
||||
import Arm2D
|
||||
import PyInfo
|
||||
|
||||
line = Arm2D.Line()
|
||||
res = line.on()
|
||||
line.off()
|
||||
line.moveTo(20)
|
96
pikascript-compiler-rust/src/arg_list.rs
Normal file
96
pikascript-compiler-rust/src/arg_list.rs
Normal file
@ -0,0 +1,96 @@
|
||||
use crate::my_string;
|
||||
use crate::py_arg::PyArg;
|
||||
use std::collections::BTreeMap;
|
||||
#[derive(Debug)]
|
||||
pub struct ArgList {
|
||||
py_arg_list: String,
|
||||
list: BTreeMap<String, PyArg>,
|
||||
}
|
||||
|
||||
impl ArgList {
|
||||
pub fn to_string(&self) -> String {
|
||||
return self.py_arg_list.clone();
|
||||
}
|
||||
pub fn new(py_arg_list: &Option<String>) -> Option<ArgList> {
|
||||
let py_arg_list = match py_arg_list {
|
||||
Some(x) => x,
|
||||
None => return None,
|
||||
};
|
||||
let mut arg_list = ArgList {
|
||||
py_arg_list: py_arg_list.clone(),
|
||||
list: BTreeMap::new(),
|
||||
};
|
||||
let py_arg_list = py_arg_list.replace(" ", "");
|
||||
let py_arg_list: Vec<&str> = py_arg_list.split(",").collect();
|
||||
for arg_define in py_arg_list.iter() {
|
||||
let arg_name = match my_string::get_first_token(&arg_define.to_string(), ':') {
|
||||
Some(name) => name,
|
||||
None => return None,
|
||||
};
|
||||
let type_name = match my_string::get_last_token(&arg_define.to_string(), ':') {
|
||||
Some(name) => name,
|
||||
None => return None,
|
||||
};
|
||||
arg_list
|
||||
.list
|
||||
.entry(arg_name.clone())
|
||||
.or_insert(PyArg::new(&arg_name, &type_name));
|
||||
}
|
||||
return Some(arg_list);
|
||||
}
|
||||
pub fn to_c(&self) -> String {
|
||||
let mut arg_list_in_c = String::from("");
|
||||
for (i, (_, py_arg)) in self.list.iter().enumerate() {
|
||||
let arg_name = py_arg.name();
|
||||
let type_name_in_c = py_arg.c_type();
|
||||
arg_list_in_c.push_str(&type_name_in_c);
|
||||
arg_list_in_c.push_str(" ");
|
||||
arg_list_in_c.push_str(&arg_name);
|
||||
if i < self.list.len() - 1 {
|
||||
arg_list_in_c.push_str(", ");
|
||||
}
|
||||
}
|
||||
return arg_list_in_c;
|
||||
}
|
||||
pub fn call_arg_list(&self) -> String {
|
||||
let mut call_arg_list = "".to_string();
|
||||
for (i, (_, py_arg)) in self.list.iter().enumerate() {
|
||||
let arg_name = py_arg.name();
|
||||
call_arg_list.push_str(&arg_name);
|
||||
if i < self.list.len() - 1 {
|
||||
call_arg_list.push_str(", ");
|
||||
}
|
||||
}
|
||||
return call_arg_list;
|
||||
}
|
||||
pub fn get_local_args(&self) -> String {
|
||||
let mut get_local_args = "".to_string();
|
||||
for (_, py_arg) in self.list.iter() {
|
||||
get_local_args.push_str(&py_arg.get_local_arg());
|
||||
}
|
||||
return get_local_args;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_arg_list() {
|
||||
let arg_list =
|
||||
ArgList::new(&Some(String::from("arg1: str, arg2: int, arg3: FILE"))).unwrap();
|
||||
let arg_list_in_c = arg_list.to_c();
|
||||
let call_arg_list = arg_list.call_arg_list();
|
||||
let get_local_args = arg_list.get_local_args();
|
||||
assert_eq! {arg_list_in_c,"char * arg1, int arg2, void * arg3"};
|
||||
assert_eq! {call_arg_list,"arg1, arg2, arg3"};
|
||||
assert_eq! {get_local_args," char * arg1 = args_getStr(args, \"arg1\");\n int arg2 = args_getInt(args, \"arg2\");\n void * arg3 = args_getPtr(args, \"arg3\");\n"};
|
||||
}
|
||||
#[test]
|
||||
fn test_arg_list_one_arg() {
|
||||
let arg_list = ArgList::new(&Some(String::from("argtest: str"))).unwrap();
|
||||
let arg_list_in_c = arg_list.to_c();
|
||||
assert_eq! {arg_list_in_c,"char * argtest"};
|
||||
}
|
||||
}
|
272
pikascript-compiler-rust/src/class_info.rs
Normal file
272
pikascript-compiler-rust/src/class_info.rs
Normal file
@ -0,0 +1,272 @@
|
||||
use crate::import_info::ImportInfo;
|
||||
use crate::method_info::MethodInfo;
|
||||
use crate::my_string;
|
||||
use crate::object_info::ObjectInfo;
|
||||
use crate::script::Script;
|
||||
use std::collections::BTreeMap;
|
||||
#[derive(Debug)]
|
||||
pub struct ClassInfo {
|
||||
pub this_class_name: String,
|
||||
pub super_class_name: String,
|
||||
pub method_list: BTreeMap<String, MethodInfo>,
|
||||
pub object_list: BTreeMap<String, ObjectInfo>,
|
||||
pub import_list: BTreeMap<String, ImportInfo>,
|
||||
pub script_list: Script,
|
||||
}
|
||||
|
||||
impl ClassInfo {
|
||||
pub fn add_file_profix(file_name: &String, class_name: &String) -> String {
|
||||
if file_name == "main" {
|
||||
return class_name.clone();
|
||||
} else if class_name == "BaseObj" || class_name == "TinyObj" {
|
||||
return class_name.clone();
|
||||
} else {
|
||||
return format!("{}_{}", file_name, class_name);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(file_name: &String, define: &String) -> Option<ClassInfo> {
|
||||
let define = define.strip_prefix("class ").unwrap().to_string();
|
||||
let define = define.replace(" ", "");
|
||||
let super_class_name = match my_string::cut(&define, '(', ')') {
|
||||
Some(s) => s,
|
||||
None => return None,
|
||||
};
|
||||
let super_class_name = match super_class_name.find(".") {
|
||||
None => ClassInfo::add_file_profix(&file_name, &super_class_name),
|
||||
Some(x) => super_class_name.replace(".", "_"),
|
||||
};
|
||||
let mut this_calss_name = match my_string::get_first_token(&define, '(') {
|
||||
Some(s) => s,
|
||||
None => return None,
|
||||
};
|
||||
this_calss_name = ClassInfo::add_file_profix(&file_name, &this_calss_name);
|
||||
let new_class_info = ClassInfo {
|
||||
this_class_name: this_calss_name,
|
||||
super_class_name: super_class_name,
|
||||
method_list: BTreeMap::new(),
|
||||
object_list: BTreeMap::new(),
|
||||
import_list: BTreeMap::new(),
|
||||
script_list: Script::new(),
|
||||
};
|
||||
return Some(new_class_info);
|
||||
}
|
||||
pub fn push_method(&mut self, method_define: String) {
|
||||
let method_info = match MethodInfo::new(&self.this_class_name, method_define) {
|
||||
Some(method) => method,
|
||||
None => return,
|
||||
};
|
||||
self.method_list
|
||||
.entry(method_info.name.clone())
|
||||
.or_insert(method_info);
|
||||
}
|
||||
pub fn push_import(&mut self, import_define: String, file_name: &String) {
|
||||
let import_info = match ImportInfo::new(&self.this_class_name, import_define, &file_name) {
|
||||
Some(import) => import,
|
||||
None => return,
|
||||
};
|
||||
self.import_list
|
||||
.entry(import_info.import_class_name.clone())
|
||||
.or_insert(import_info);
|
||||
}
|
||||
pub fn push_object(&mut self, object_define: String, file_name: &String) {
|
||||
let object_info = match ObjectInfo::new(&self.this_class_name, object_define, &file_name) {
|
||||
Some(object) => object,
|
||||
None => return,
|
||||
};
|
||||
self.object_list
|
||||
.entry(object_info.name.clone())
|
||||
.or_insert(object_info);
|
||||
}
|
||||
|
||||
pub fn include(&self) -> String {
|
||||
let mut include = String::new();
|
||||
include.push_str(&format!("#include \"{}.h\"\n", self.this_class_name));
|
||||
include.push_str(&format!("#include \"{}.h\"\n", self.super_class_name));
|
||||
for (_, import_info) in self.import_list.iter() {
|
||||
include.push_str(&format!(
|
||||
"#include \"{}.h\"\n",
|
||||
import_info.import_class_name
|
||||
));
|
||||
}
|
||||
for (_, object_info) in self.object_list.iter() {
|
||||
include.push_str(&format!(
|
||||
"#include \"{}.h\"\n",
|
||||
object_info.import_class_name
|
||||
));
|
||||
}
|
||||
return include;
|
||||
}
|
||||
|
||||
pub fn method_api_fn(&self) -> String {
|
||||
let mut method_impl = String::new();
|
||||
for (_, method_info) in self.method_list.iter() {
|
||||
method_impl.push_str(&method_info.method_fn_impl());
|
||||
}
|
||||
return method_impl;
|
||||
}
|
||||
|
||||
pub fn script_fn(&self) -> String {
|
||||
let mut script_fn = String::new();
|
||||
script_fn.push_str("PikaObj * pikaScriptInit(){\r\n");
|
||||
script_fn.push_str(" PikaObj * pikaMain = newRootObj(\"pikaMain\", New_PikaMain);\r\n");
|
||||
script_fn.push_str(&self.script_list.content);
|
||||
script_fn.push_str(" return pikaMain;\r\n");
|
||||
script_fn.push_str("}\r\n\r\n");
|
||||
return script_fn;
|
||||
}
|
||||
|
||||
pub fn new_class_fn(&self) -> String {
|
||||
let mut new_class_fn = String::new();
|
||||
let new_class_fn_head = format!("{}{{\n", self.new_class_fn_name());
|
||||
new_class_fn.push_str(&new_class_fn_head);
|
||||
let derive = format!(" PikaObj *self = New_{}(args);\n", self.super_class_name);
|
||||
new_class_fn.push_str(&derive);
|
||||
for (_, import_info) in self.import_list.iter() {
|
||||
new_class_fn.push_str(&import_info.import_fn());
|
||||
}
|
||||
|
||||
for (_, object_info) in self.object_list.iter() {
|
||||
new_class_fn.push_str(&object_info.new_object_fn());
|
||||
}
|
||||
|
||||
for (_, method_info) in self.method_list.iter() {
|
||||
new_class_fn.push_str(&method_info.get_define());
|
||||
}
|
||||
|
||||
new_class_fn.push_str(" return self;\n");
|
||||
new_class_fn.push_str("}\n");
|
||||
return new_class_fn;
|
||||
}
|
||||
|
||||
pub fn new_class_fn_name(&self) -> String {
|
||||
return format!("PikaObj *New_{}(Args *args)", self.this_class_name);
|
||||
}
|
||||
|
||||
pub fn method_impl_declear(&self) -> String {
|
||||
let mut method_fn_declear = String::new();
|
||||
for (_, method_info) in self.method_list.iter() {
|
||||
method_fn_declear.push_str(&method_info.method_impl_declear());
|
||||
}
|
||||
return method_fn_declear;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_analize() {
|
||||
assert_eq!(
|
||||
ClassInfo::new(
|
||||
&String::from("Pkg"),
|
||||
&String::from("class Test(SuperTest):")
|
||||
)
|
||||
.unwrap()
|
||||
.this_class_name,
|
||||
"Pkg_Test"
|
||||
);
|
||||
assert_eq!(
|
||||
ClassInfo::new(
|
||||
&String::from("Pkg"),
|
||||
&String::from("class Test(SuperTest):")
|
||||
)
|
||||
.unwrap()
|
||||
.super_class_name,
|
||||
"Pkg_SuperTest"
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn test_push_method() {
|
||||
let mut class_info = ClassInfo::new(
|
||||
&String::from("Pkg"),
|
||||
&String::from("class Test(SuperTest):"),
|
||||
)
|
||||
.unwrap();
|
||||
class_info.push_method(String::from("def test(data: str)-> str:"));
|
||||
assert_eq!(
|
||||
class_info.method_list.get("test").unwrap().class_name,
|
||||
"Pkg_Test"
|
||||
);
|
||||
assert_eq!(class_info.method_list.get("test").unwrap().name, "test");
|
||||
assert_eq!(
|
||||
class_info
|
||||
.method_list
|
||||
.get("test")
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.return_type
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
"str"
|
||||
);
|
||||
assert_eq!(
|
||||
class_info
|
||||
.method_list
|
||||
.get("test")
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.arg_list
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
"data:str"
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn test_push_object() {
|
||||
let mut class_info = ClassInfo::new(
|
||||
&String::from("Pkg"),
|
||||
&String::from("class Test(SuperTest):"),
|
||||
)
|
||||
.unwrap();
|
||||
class_info.push_object(String::from("testObj = TestObj()"), &"Pkg".to_string());
|
||||
assert_eq!(
|
||||
class_info.object_list.get("testObj").unwrap().class_name,
|
||||
"Pkg_Test"
|
||||
);
|
||||
assert_eq!(
|
||||
class_info.object_list.get("testObj").unwrap().name,
|
||||
"testObj"
|
||||
);
|
||||
assert_eq!(
|
||||
class_info
|
||||
.object_list
|
||||
.get("testObj")
|
||||
.unwrap()
|
||||
.import_class_name,
|
||||
"Pkg_TestObj"
|
||||
);
|
||||
assert_eq!(
|
||||
class_info.object_list.get("testObj").unwrap().name,
|
||||
"testObj"
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn test_push_import() {
|
||||
let mut class_info = ClassInfo::new(
|
||||
&String::from("Pkg"),
|
||||
&String::from("class Test(SuperTest):"),
|
||||
)
|
||||
.unwrap();
|
||||
class_info.push_import(String::from("TestObj()"), &"Pkg".to_string());
|
||||
assert_eq!(
|
||||
class_info
|
||||
.import_list
|
||||
.get("Pkg_TestObj")
|
||||
.unwrap()
|
||||
.class_name,
|
||||
"Pkg_Test"
|
||||
);
|
||||
assert_eq!(
|
||||
class_info
|
||||
.import_list
|
||||
.get("Pkg_TestObj")
|
||||
.unwrap()
|
||||
.import_class_name,
|
||||
"Pkg_TestObj"
|
||||
);
|
||||
}
|
||||
}
|
172
pikascript-compiler-rust/src/compiler.rs
Normal file
172
pikascript-compiler-rust/src/compiler.rs
Normal file
@ -0,0 +1,172 @@
|
||||
use crate::class_info::ClassInfo;
|
||||
use crate::script::Script;
|
||||
use std::collections::BTreeMap;
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
#[derive(Debug)]
|
||||
pub struct Compiler {
|
||||
pub dist_path: String,
|
||||
pub source_path: String,
|
||||
pub class_list: BTreeMap<String, ClassInfo>,
|
||||
pub class_now_name: Option<String>,
|
||||
}
|
||||
|
||||
impl Compiler {
|
||||
pub fn new(source_path: String, dist_path: String) -> Compiler {
|
||||
let compiler = Compiler {
|
||||
dist_path: dist_path.clone(),
|
||||
source_path: source_path.clone(),
|
||||
class_now_name: None,
|
||||
class_list: BTreeMap::new(),
|
||||
};
|
||||
return compiler;
|
||||
}
|
||||
pub fn analyze_main_line(mut compiler: Compiler, line: String) -> Compiler {
|
||||
let file_name = "main".to_string();
|
||||
let class_name = "PikaMain".to_string();
|
||||
let class_now = match compiler.class_list.get_mut(&"PikaMain".to_string()) {
|
||||
Some(class_now) => class_now,
|
||||
None => compiler.class_list.entry(class_name.clone()).or_insert(
|
||||
ClassInfo::new(
|
||||
&file_name,
|
||||
&"class PikaMain(PikaStdLib.SysObj):".to_string(),
|
||||
)
|
||||
.unwrap(),
|
||||
),
|
||||
};
|
||||
compiler.class_now_name = Some(class_name.clone());
|
||||
|
||||
if line.starts_with("def ") {
|
||||
class_now.push_method(line);
|
||||
return compiler;
|
||||
}
|
||||
if line.contains("(") && line.contains(")") && line.contains("=") {
|
||||
if Script::assert(class_now, &line) {
|
||||
class_now.script_list.add(&line);
|
||||
return compiler;
|
||||
}
|
||||
class_now.push_object(line, &file_name);
|
||||
return compiler;
|
||||
}
|
||||
if line.contains("(") && line.contains(")") {
|
||||
class_now.script_list.add(&line);
|
||||
}
|
||||
return compiler;
|
||||
}
|
||||
|
||||
pub fn analyze_file(mut compiler: Compiler, file_name: String) -> Compiler {
|
||||
println!("analyzing file: {}{}.py", compiler.source_path, file_name);
|
||||
let mut file = File::open(format!("{}{}.py", compiler.source_path, file_name)).unwrap();
|
||||
let mut file_str = String::new();
|
||||
file.read_to_string(&mut file_str).unwrap();
|
||||
let lines: Vec<&str> = file_str.split('\n').collect();
|
||||
/* analyze each line of pikascript-api.py */
|
||||
for line in lines.iter() {
|
||||
compiler = Compiler::analyze_line(compiler, line.to_string(), &file_name);
|
||||
}
|
||||
return compiler;
|
||||
}
|
||||
|
||||
pub fn analyze_line(mut compiler: Compiler, line: String, file_name: &String) -> Compiler {
|
||||
let line = line.replace("\r", "");
|
||||
if line.starts_with("import ") {
|
||||
let tokens: Vec<&str> = line.split(" ").collect();
|
||||
let file = tokens[1];
|
||||
return Compiler::analyze_file(compiler, file.to_string());
|
||||
}
|
||||
|
||||
if line.starts_with("#") {
|
||||
return compiler;
|
||||
}
|
||||
|
||||
if line.starts_with("class") {
|
||||
let class_now = match ClassInfo::new(&file_name, &line) {
|
||||
Some(s) => s,
|
||||
None => return compiler,
|
||||
};
|
||||
let class_name = class_now.this_class_name.clone();
|
||||
compiler
|
||||
.class_list
|
||||
.entry(class_name.clone())
|
||||
.or_insert(class_now);
|
||||
compiler.class_now_name = Some(class_name.clone());
|
||||
return compiler;
|
||||
}
|
||||
if line.starts_with(" def ") {
|
||||
let line = line.strip_prefix(" ").unwrap().to_string();
|
||||
let class_now = compiler
|
||||
.class_list
|
||||
.get_mut(&compiler.class_now_name.clone().unwrap())
|
||||
.unwrap();
|
||||
class_now.push_method(line);
|
||||
return compiler;
|
||||
}
|
||||
if line.starts_with(" ")
|
||||
&& line.contains("(")
|
||||
&& line.contains(")")
|
||||
&& line.contains("=")
|
||||
{
|
||||
let line = line.strip_prefix(" ").unwrap().to_string();
|
||||
let class_now = compiler
|
||||
.class_list
|
||||
.get_mut(&compiler.class_now_name.clone().unwrap())
|
||||
.unwrap();
|
||||
class_now.push_object(line, &file_name);
|
||||
return compiler;
|
||||
}
|
||||
if line.starts_with(" ") && line.contains("(") && line.contains(")") {
|
||||
let line = line.strip_prefix(" ").unwrap().to_string();
|
||||
let class_now = compiler
|
||||
.class_list
|
||||
.get_mut(&compiler.class_now_name.clone().unwrap())
|
||||
.unwrap();
|
||||
class_now.push_import(line, &file_name);
|
||||
return compiler;
|
||||
}
|
||||
|
||||
if file_name == "main" {
|
||||
return Compiler::analyze_main_line(compiler, line);
|
||||
}
|
||||
|
||||
return compiler;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
#[test]
|
||||
fn test_analyze() {
|
||||
let compiler = Compiler::new(String::from(""), String::from(""));
|
||||
let compiler = Compiler::analyze_line(
|
||||
compiler,
|
||||
String::from("class Test(SuperTest):"),
|
||||
&"Pkg".to_string(),
|
||||
);
|
||||
let compiler =
|
||||
Compiler::analyze_line(compiler, String::from(" def test()"), &"Pkg".to_string());
|
||||
let compiler = Compiler::analyze_line(
|
||||
compiler,
|
||||
String::from(" testObj = TestObj()"),
|
||||
&"Pkg".to_string(),
|
||||
);
|
||||
let compiler = Compiler::analyze_line(
|
||||
compiler,
|
||||
String::from(" TestImport()"),
|
||||
&"Pkg".to_string(),
|
||||
);
|
||||
|
||||
let class_info = compiler.class_list.get("Pkg_Test").unwrap();
|
||||
let method_info = class_info.method_list.get("test").unwrap();
|
||||
let object_info = class_info.object_list.get("testObj").unwrap();
|
||||
let import_info = class_info.import_list.get("Pkg_TestImport").unwrap();
|
||||
assert_eq!(class_info.this_class_name, "Pkg_Test");
|
||||
assert_eq!(class_info.super_class_name, "Pkg_SuperTest");
|
||||
assert_eq!(method_info.name, "test");
|
||||
assert_eq!(method_info.class_name, "Pkg_Test");
|
||||
assert_eq!(object_info.name, "testObj");
|
||||
assert_eq!(object_info.class_name, "Pkg_Test");
|
||||
assert_eq!(import_info.class_name, "Pkg_Test");
|
||||
assert_eq!(import_info.import_class_name, "Pkg_TestImport");
|
||||
}
|
||||
}
|
65
pikascript-compiler-rust/src/import_info.rs
Normal file
65
pikascript-compiler-rust/src/import_info.rs
Normal file
@ -0,0 +1,65 @@
|
||||
use crate::my_string;
|
||||
use crate::class_info;
|
||||
#[derive(Debug)]
|
||||
pub struct ImportInfo {
|
||||
pub class_name: String,
|
||||
pub import_class_name: String,
|
||||
}
|
||||
|
||||
impl ImportInfo {
|
||||
pub fn new(
|
||||
class_name: &String,
|
||||
input_define: String,
|
||||
file_name: &String,
|
||||
) -> Option<ImportInfo> {
|
||||
let define = input_define.replace(" ", "");
|
||||
let mut import_class_name = match my_string::get_first_token(&define, '(') {
|
||||
Some(token) => token,
|
||||
None => return None,
|
||||
};
|
||||
import_class_name = match import_class_name.find(".") {
|
||||
None => class_info::ClassInfo::add_file_profix(&file_name, &import_class_name),
|
||||
Some(x) => import_class_name.replace(".", "_"),
|
||||
};
|
||||
import_class_name = import_class_name.replace(".", "_");
|
||||
return Some(ImportInfo {
|
||||
class_name: class_name.clone(),
|
||||
import_class_name: import_class_name,
|
||||
});
|
||||
}
|
||||
pub fn import_fn(&self) -> String {
|
||||
return format!(
|
||||
" obj_import(self, \"{}\", New_{});\n",
|
||||
self.import_class_name, self.import_class_name
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_import_info() {
|
||||
assert_eq!(
|
||||
ImportInfo::new(
|
||||
&String::from("Test"),
|
||||
String::from("ImportTest()"),
|
||||
&"Pkg".to_string()
|
||||
)
|
||||
.unwrap()
|
||||
.import_class_name,
|
||||
String::from("Pkg_ImportTest")
|
||||
);
|
||||
assert_eq!(
|
||||
ImportInfo::new(
|
||||
&String::from("Test"),
|
||||
String::from("ImportTest()"),
|
||||
&"Pkg".to_string()
|
||||
)
|
||||
.unwrap()
|
||||
.class_name,
|
||||
String::from("Test")
|
||||
);
|
||||
}
|
||||
}
|
106
pikascript-compiler-rust/src/main.rs
Normal file
106
pikascript-compiler-rust/src/main.rs
Normal file
@ -0,0 +1,106 @@
|
||||
mod arg_list;
|
||||
mod class_info;
|
||||
mod compiler;
|
||||
mod import_info;
|
||||
mod method_info;
|
||||
mod my_string;
|
||||
mod object_info;
|
||||
mod py_arg;
|
||||
mod py_type;
|
||||
mod script;
|
||||
use compiler::*;
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
|
||||
fn main() {
|
||||
let mut compiler = Compiler::new(String::from(""), String::from("pikascript-api/"));
|
||||
compiler = Compiler::analyze_file(compiler, String::from("main"));
|
||||
/* write to compiler-info about the info */
|
||||
let mut compiler_info_file =
|
||||
File::create(format!("{}compiler-info.txt", compiler.dist_path)).unwrap();
|
||||
let compiler_info = format!("{:?}", compiler);
|
||||
compiler_info_file.write(compiler_info.as_bytes()).unwrap();
|
||||
/* make the api.c file for each python class */
|
||||
for (_, class_info) in compiler.class_list.iter() {
|
||||
let api_file_path = format!("{}{}-api.c", compiler.dist_path, class_info.this_class_name);
|
||||
let mut f = File::create(api_file_path).unwrap();
|
||||
f.write("/* ******************************** */\n".as_bytes())
|
||||
.unwrap();
|
||||
f.write("/* Warning! Don't modify this file! */\n".as_bytes())
|
||||
.unwrap();
|
||||
f.write("/* ******************************** */\n".as_bytes())
|
||||
.unwrap();
|
||||
f.write(class_info.include().as_bytes()).unwrap();
|
||||
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();
|
||||
f.write("\n".as_bytes()).unwrap();
|
||||
f.write(class_info.method_api_fn().as_bytes()).unwrap();
|
||||
f.write(class_info.new_class_fn().as_bytes()).unwrap();
|
||||
}
|
||||
/* make the .h file for each python class */
|
||||
for (_, class_info) in compiler.class_list.iter() {
|
||||
let api_file_path = format!("{}{}.h", compiler.dist_path, class_info.this_class_name);
|
||||
let mut f = File::create(api_file_path).unwrap();
|
||||
f.write("/* ******************************** */\n".as_bytes())
|
||||
.unwrap();
|
||||
f.write("/* Warning! Don't modify this file! */\n".as_bytes())
|
||||
.unwrap();
|
||||
f.write("/* ******************************** */\n".as_bytes())
|
||||
.unwrap();
|
||||
f.write(format!("#ifndef __{}__H\n", class_info.this_class_name).as_bytes())
|
||||
.unwrap();
|
||||
f.write(format!("#define __{}__H\n", class_info.this_class_name).as_bytes())
|
||||
.unwrap();
|
||||
f.write("#include <stdio.h>\n".as_bytes()).unwrap();
|
||||
f.write("#include <stdlib.h>\n".as_bytes()).unwrap();
|
||||
f.write("#include \"PikaObj.h\"\n".as_bytes()).unwrap();
|
||||
f.write("\n".as_bytes()).unwrap();
|
||||
let new_class_fn_declear = format!("{};\n", class_info.new_class_fn_name());
|
||||
f.write(new_class_fn_declear.as_bytes()).unwrap();
|
||||
f.write("\n".as_bytes()).unwrap();
|
||||
f.write(class_info.method_impl_declear().as_bytes())
|
||||
.unwrap();
|
||||
f.write("\n".as_bytes()).unwrap();
|
||||
f.write("#endif\n".as_bytes()).unwrap();
|
||||
}
|
||||
/* make the pikascript.c */
|
||||
let api_file_path = format!("{}pikaScript.c", compiler.dist_path);
|
||||
let mut f = File::create(api_file_path).unwrap();
|
||||
f.write("/* ******************************** */\n".as_bytes())
|
||||
.unwrap();
|
||||
f.write("/* Warning! Don't modify this file! */\n".as_bytes())
|
||||
.unwrap();
|
||||
f.write("/* ******************************** */\n".as_bytes())
|
||||
.unwrap();
|
||||
f.write("#include \"PikaMain.h\"\n".as_bytes()).unwrap();
|
||||
f.write("#include <stdio.h>\n".as_bytes()).unwrap();
|
||||
f.write("#include <stdlib.h>\n".as_bytes()).unwrap();
|
||||
f.write("\n".as_bytes()).unwrap();
|
||||
let pika_main = compiler
|
||||
.class_list
|
||||
.get_mut(&"PikaMain".to_string())
|
||||
.unwrap();
|
||||
f.write(pika_main.script_fn().as_bytes()).unwrap();
|
||||
/* make the pikascript.h */
|
||||
let api_file_path = format!("{}pikaScript.h", compiler.dist_path);
|
||||
let mut f = File::create(api_file_path).unwrap();
|
||||
f.write("/* ******************************** */\n".as_bytes())
|
||||
.unwrap();
|
||||
f.write("/* Warning! Don't modify this file! */\n".as_bytes())
|
||||
.unwrap();
|
||||
f.write("/* ******************************** */\n".as_bytes())
|
||||
.unwrap();
|
||||
f.write(format!("#ifndef __{}__H\n", "pikaScript").as_bytes())
|
||||
.unwrap();
|
||||
f.write(format!("#define __{}__H\n", "pikaScript").as_bytes())
|
||||
.unwrap();
|
||||
f.write("#include <stdio.h>\n".as_bytes()).unwrap();
|
||||
f.write("#include <stdlib.h>\n".as_bytes()).unwrap();
|
||||
f.write("#include \"PikaObj.h\"\n".as_bytes()).unwrap();
|
||||
f.write("#include \"PikaMain.h\"\n".as_bytes()).unwrap();
|
||||
f.write("\n".as_bytes()).unwrap();
|
||||
f.write("PikaObj * pikaScriptInit();\n".as_bytes()).unwrap();
|
||||
f.write("\n".as_bytes()).unwrap();
|
||||
f.write("#endif\n".as_bytes()).unwrap();
|
||||
}
|
237
pikascript-compiler-rust/src/method_info.rs
Normal file
237
pikascript-compiler-rust/src/method_info.rs
Normal file
@ -0,0 +1,237 @@
|
||||
use crate::arg_list::ArgList;
|
||||
use crate::my_string;
|
||||
use crate::py_type::PyType;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct MethodInfo {
|
||||
pub class_name: String,
|
||||
pub name: String,
|
||||
pub arg_list: Option<ArgList>,
|
||||
pub return_type: Option<PyType>,
|
||||
}
|
||||
|
||||
impl MethodInfo {
|
||||
pub fn new(class_name: &String, input_define: String) -> Option<MethodInfo> {
|
||||
let define = match input_define.strip_prefix("def ") {
|
||||
Some(define) => define.to_string(),
|
||||
None => return None,
|
||||
};
|
||||
let define = define.replace(" ", "");
|
||||
let name = match my_string::get_first_token(&define, '(') {
|
||||
Some(token) => token,
|
||||
None => return None,
|
||||
};
|
||||
let arg_list = my_string::cut(&define, '(', ')');
|
||||
let return_type = match my_string::cut(&define, '>', ':') {
|
||||
Some(py_type) => Some(PyType::new(&py_type)),
|
||||
None => None,
|
||||
};
|
||||
let method_info = MethodInfo {
|
||||
name: name,
|
||||
arg_list: ArgList::new(&arg_list),
|
||||
return_type: return_type,
|
||||
class_name: class_name.clone(),
|
||||
};
|
||||
return Some(method_info);
|
||||
}
|
||||
pub fn get_define(&self) -> String {
|
||||
let return_token = match &self.return_type {
|
||||
Some(s) => format!("->{}", s.to_string()),
|
||||
None => String::from(""),
|
||||
};
|
||||
let arg_list = match &self.arg_list {
|
||||
Some(t) => t.to_string(),
|
||||
None => String::from(""),
|
||||
};
|
||||
let define = format!(
|
||||
" class_defineMethod(self, \"{}({}){}\", {}_{}Method);\n",
|
||||
self.name, arg_list, return_token, self.class_name, self.name
|
||||
);
|
||||
return define;
|
||||
}
|
||||
pub fn method_api_name(&self) -> String {
|
||||
return format!(
|
||||
"void {}_{}Method(PikaObj *self, Args *args)",
|
||||
self.class_name, self.name
|
||||
);
|
||||
}
|
||||
pub fn method_impl_declear(&self) -> String {
|
||||
let return_type_in_c = match self.return_type.as_ref() {
|
||||
Some(x) => x.to_c_type(),
|
||||
None => String::from("void"),
|
||||
};
|
||||
let arg_list_in_c = match self.arg_list.as_ref() {
|
||||
Some(x) => format!(", {}", x.to_c()),
|
||||
None => String::from(""),
|
||||
};
|
||||
return format!(
|
||||
"{} {}_{}(PikaObj *self{});\n",
|
||||
return_type_in_c, self.class_name, self.name, arg_list_in_c,
|
||||
);
|
||||
}
|
||||
pub fn method_fn_impl(&self) -> String {
|
||||
let mut method_fn_impl = "".to_string();
|
||||
let method_fn_name = format!("{}{{\n", self.method_api_name());
|
||||
let get_local_args = match &self.arg_list {
|
||||
Some(x) => x.get_local_args(),
|
||||
None => "".to_string(),
|
||||
};
|
||||
let return_impl = match &self.return_type {
|
||||
Some(x) => format!(" {}(args, res);\n", x.return_fn()),
|
||||
None => "".to_string(),
|
||||
};
|
||||
let return_type_in_c = match &self.return_type {
|
||||
Some(x) => format!("{} res = ", x.to_c_type()),
|
||||
None => "".to_string(),
|
||||
};
|
||||
let call_arg_list = match &self.arg_list {
|
||||
Some(x) => format!(", {}", x.call_arg_list()),
|
||||
None => "".to_string(),
|
||||
};
|
||||
let call_method = format!(
|
||||
" {}{}_{}(self{});\n",
|
||||
return_type_in_c, self.class_name, self.name, call_arg_list
|
||||
);
|
||||
method_fn_impl.push_str(&method_fn_name);
|
||||
method_fn_impl.push_str(&get_local_args);
|
||||
method_fn_impl.push_str(&call_method);
|
||||
method_fn_impl.push_str(&return_impl);
|
||||
method_fn_impl.push_str("}\n\n");
|
||||
return method_fn_impl;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_get_local_declear() {
|
||||
let method_info = MethodInfo::new(
|
||||
&String::from("Test"),
|
||||
String::from("def test(test:str, test2:int)->str:"),
|
||||
);
|
||||
let define = method_info.as_ref().unwrap().method_impl_declear();
|
||||
let method_fn_impl = method_info.as_ref().unwrap().method_fn_impl();
|
||||
assert_eq!(define, "char * Test_test(PikaObj *self, char * test, int test2);\n");
|
||||
assert_eq!(
|
||||
method_fn_impl,
|
||||
"void Test_testMethod(PikaObj *self, Args *args){\n char * test = args_getStr(args, \"test\");\n int test2 = args_getInt(args, \"test2\");\n char * res = Test_test(self, test, test2);\n method_returnStr(args, res);\n}\n\n"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_analize() {
|
||||
assert_eq!(
|
||||
MethodInfo::new(
|
||||
&String::from("Test"),
|
||||
String::from("def test(test:str)->str:")
|
||||
)
|
||||
.unwrap()
|
||||
.name,
|
||||
String::from("test")
|
||||
);
|
||||
assert_eq!(
|
||||
MethodInfo::new(
|
||||
&String::from("Test"),
|
||||
String::from("def test(test:str)->str:")
|
||||
)
|
||||
.unwrap()
|
||||
.return_type
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
String::from("str")
|
||||
);
|
||||
assert_eq!(
|
||||
MethodInfo::new(
|
||||
&String::from("Test"),
|
||||
String::from("def test(test:str)->str:")
|
||||
)
|
||||
.unwrap()
|
||||
.arg_list
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
String::from("test:str")
|
||||
);
|
||||
assert_eq!(
|
||||
MethodInfo::new(
|
||||
&String::from("Test"),
|
||||
String::from("def test(test: str) ->str:")
|
||||
)
|
||||
.unwrap()
|
||||
.name,
|
||||
String::from("test")
|
||||
);
|
||||
assert_eq!(
|
||||
MethodInfo::new(
|
||||
&String::from("Test"),
|
||||
String::from("def test(test: str) ->str:")
|
||||
)
|
||||
.unwrap()
|
||||
.return_type
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
String::from("str")
|
||||
);
|
||||
assert_eq!(
|
||||
MethodInfo::new(
|
||||
&String::from("Test"),
|
||||
String::from("def test(test: str) ->str:")
|
||||
)
|
||||
.unwrap()
|
||||
.arg_list
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
String::from("test:str")
|
||||
);
|
||||
assert_eq!(
|
||||
MethodInfo::new(
|
||||
&String::from("Test"),
|
||||
String::from("def test(test: str, test2: int) ->str:")
|
||||
)
|
||||
.unwrap()
|
||||
.arg_list
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
String::from("test:str,test2:int")
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn test_get_define() {
|
||||
let method_info = MethodInfo::new(
|
||||
&String::from("Test"),
|
||||
String::from("def test(test:str, test2:int)->str:"),
|
||||
);
|
||||
let define = method_info.unwrap().get_define();
|
||||
assert_eq!(define, String::from(" class_defineMethod(self, \"test(test:str,test2:int)->str\", Test_testMethod);\n"));
|
||||
}
|
||||
#[test]
|
||||
fn test_get_define_no_return() {
|
||||
let method_info = MethodInfo::new(
|
||||
&String::from("Test"),
|
||||
String::from("def test(test:str, test2:int):"),
|
||||
);
|
||||
let define = method_info.unwrap().get_define();
|
||||
assert_eq!(
|
||||
define,
|
||||
String::from(
|
||||
" class_defineMethod(self, \"test(test:str,test2:int)\", Test_testMethod);\n"
|
||||
)
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn test_get_define_no_return_no_arg_list() {
|
||||
let method_info =
|
||||
MethodInfo::new(&String::from("Test"), String::from("def test():")).unwrap();
|
||||
let define = method_info.get_define();
|
||||
let method_fn_name = method_info.method_api_name();
|
||||
assert_eq!(
|
||||
define,
|
||||
String::from(" class_defineMethod(self, \"test()\", Test_testMethod);\n")
|
||||
);
|
||||
assert_eq!(
|
||||
method_fn_name,
|
||||
String::from("void Test_testMethod(PikaObj *self, Args *args)")
|
||||
);
|
||||
}
|
||||
}
|
53
pikascript-compiler-rust/src/my_string.rs
Normal file
53
pikascript-compiler-rust/src/my_string.rs
Normal file
@ -0,0 +1,53 @@
|
||||
pub fn cut(string: &String, start_char: char, end_char: char) -> Option<String> {
|
||||
let start_index = match string.find(start_char) {
|
||||
Some(i) => i,
|
||||
None => return None,
|
||||
};
|
||||
let end_index = match string.rfind(end_char) {
|
||||
Some(i) => i,
|
||||
None => return None,
|
||||
};
|
||||
if start_index + 1 == end_index {
|
||||
return None;
|
||||
}
|
||||
return Some(string[start_index + 1..end_index].to_string());
|
||||
}
|
||||
|
||||
pub fn get_first_token(string: &String, end_char: char) -> Option<String> {
|
||||
return match string.split_once(end_char) {
|
||||
Some(s) => Some(s.0.to_string()),
|
||||
None => None,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn get_last_token(string: &String, end_char: char) -> Option<String> {
|
||||
return match string.rsplit_once(end_char) {
|
||||
Some(s) => Some(s.1.to_string()),
|
||||
None => None,
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_my_string() {
|
||||
assert_eq!(
|
||||
cut(&String::from("(test)"), '(', ')'),
|
||||
Some(String::from("test"))
|
||||
);
|
||||
assert_eq!(
|
||||
get_first_token(&String::from("test,"), ',',),
|
||||
Some(String::from("test"))
|
||||
);
|
||||
assert_eq!(
|
||||
get_first_token(&String::from("test("), '(',),
|
||||
Some(String::from("test"))
|
||||
);
|
||||
assert_eq!(
|
||||
get_last_token(&String::from("test=Test"), '=',),
|
||||
Some(String::from("Test"))
|
||||
);
|
||||
}
|
||||
}
|
88
pikascript-compiler-rust/src/object_info.rs
Normal file
88
pikascript-compiler-rust/src/object_info.rs
Normal file
@ -0,0 +1,88 @@
|
||||
use crate::class_info;
|
||||
use crate::my_string;
|
||||
#[derive(Debug)]
|
||||
pub struct ObjectInfo {
|
||||
pub class_name: String,
|
||||
pub name: String,
|
||||
pub import_class_name: String,
|
||||
}
|
||||
|
||||
impl ObjectInfo {
|
||||
pub fn new(
|
||||
class_name: &String,
|
||||
input_define: String,
|
||||
file_name: &String,
|
||||
) -> Option<ObjectInfo> {
|
||||
let define = input_define.replace(" ", "");
|
||||
let name = match my_string::get_first_token(&define, '=') {
|
||||
Some(token) => token,
|
||||
None => return None,
|
||||
};
|
||||
let mut import_class_name = match my_string::cut(&define, '=', '(') {
|
||||
Some(token) => token,
|
||||
None => return None,
|
||||
};
|
||||
import_class_name = match import_class_name.find(".") {
|
||||
None => class_info::ClassInfo::add_file_profix(&file_name, &import_class_name),
|
||||
Some(x) => import_class_name.replace(".", "_"),
|
||||
};
|
||||
return Some(ObjectInfo {
|
||||
class_name: class_name.clone(),
|
||||
name: name,
|
||||
import_class_name: import_class_name,
|
||||
});
|
||||
}
|
||||
pub fn new_object_fn(&self) -> String {
|
||||
let mut new_object_fn = String::new();
|
||||
let import_fn = format!(
|
||||
" obj_import(self, \"{}\", New_{});\n",
|
||||
self.import_class_name, self.import_class_name
|
||||
);
|
||||
new_object_fn.push_str(&import_fn);
|
||||
let new_fn = format!(
|
||||
" obj_newObj(self, \"{}\", \"{}\");\n",
|
||||
self.name, self.import_class_name
|
||||
);
|
||||
new_object_fn.push_str(&new_fn);
|
||||
return new_object_fn;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_object_info() {
|
||||
assert_eq!(
|
||||
ObjectInfo::new(
|
||||
&String::from("Test"),
|
||||
String::from("test=ImportTest()"),
|
||||
&"Pkg".to_string()
|
||||
)
|
||||
.unwrap()
|
||||
.import_class_name,
|
||||
String::from("Pkg_ImportTest")
|
||||
);
|
||||
assert_eq!(
|
||||
ObjectInfo::new(
|
||||
&String::from("Test"),
|
||||
String::from("test=ImportTest()"),
|
||||
&"Pkg".to_string()
|
||||
)
|
||||
.unwrap()
|
||||
.name,
|
||||
String::from("test")
|
||||
);
|
||||
assert_eq!(
|
||||
ObjectInfo::new(
|
||||
&String::from("Test"),
|
||||
String::from("test=ImportTest()"),
|
||||
&"Pkg".to_string()
|
||||
)
|
||||
.unwrap()
|
||||
.class_name,
|
||||
String::from("Test")
|
||||
);
|
||||
}
|
||||
}
|
46
pikascript-compiler-rust/src/py_arg.rs
Normal file
46
pikascript-compiler-rust/src/py_arg.rs
Normal file
@ -0,0 +1,46 @@
|
||||
use crate::py_type::PyType;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PyArg {
|
||||
py_type: PyType,
|
||||
name: String,
|
||||
}
|
||||
|
||||
impl PyArg {
|
||||
pub fn new(name: &String, type_name: &String) -> PyArg {
|
||||
let py_arg = PyArg {
|
||||
name: name.clone(),
|
||||
py_type: PyType::new(type_name),
|
||||
};
|
||||
return py_arg;
|
||||
}
|
||||
pub fn name(&self) -> String {
|
||||
return self.name.clone();
|
||||
}
|
||||
pub fn c_type(&self) -> String {
|
||||
return self.py_type.to_c_type();
|
||||
}
|
||||
pub fn get_local_arg(&self) -> String {
|
||||
return format!(
|
||||
" {} {} = {}(args, \"{}\");\n",
|
||||
self.c_type(),
|
||||
self.name(),
|
||||
self.py_type.get_fn(),
|
||||
self.name()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_get_arg_to_local() {
|
||||
let arg = PyArg::new(&"arg".to_string(), &"str".to_string());
|
||||
assert_eq!(
|
||||
arg.get_local_arg(),
|
||||
" char * arg = args_getStr(args, \"arg\");\n"
|
||||
);
|
||||
}
|
||||
}
|
78
pikascript-compiler-rust/src/py_type.rs
Normal file
78
pikascript-compiler-rust/src/py_type.rs
Normal file
@ -0,0 +1,78 @@
|
||||
#[derive(Debug)]
|
||||
pub struct PyType {
|
||||
type_name: String,
|
||||
}
|
||||
|
||||
impl PyType {
|
||||
pub fn to_c_type(&self) -> String {
|
||||
if self.type_name == "int" {
|
||||
return "int".to_string();
|
||||
}
|
||||
if self.type_name == "float" {
|
||||
return "float".to_string();
|
||||
}
|
||||
if self.type_name == "pointer" {
|
||||
return "void *".to_string();
|
||||
}
|
||||
if self.type_name == "str" {
|
||||
return "char *".to_string();
|
||||
}
|
||||
if self.type_name == "" {
|
||||
return "void".to_string();
|
||||
}
|
||||
return "void *".to_string();
|
||||
}
|
||||
pub fn to_string(&self) -> String {
|
||||
return self.type_name.clone();
|
||||
}
|
||||
pub fn new(type_name: &String) -> PyType {
|
||||
return PyType {
|
||||
type_name: type_name.clone(),
|
||||
};
|
||||
}
|
||||
pub fn return_fn(&self) -> String {
|
||||
if self.type_name == "int" {
|
||||
return "method_returnInt".to_string();
|
||||
}
|
||||
if self.type_name == "float" {
|
||||
return "method_returnFloat".to_string();
|
||||
}
|
||||
if self.type_name == "pointer" {
|
||||
return "method_returnPtr".to_string();
|
||||
}
|
||||
if self.type_name == "str" {
|
||||
return "method_returnStr".to_string();
|
||||
}
|
||||
return "method_returnPtr".to_string();
|
||||
}
|
||||
pub fn set_fn(&self) -> String {
|
||||
if self.type_name == "int" {
|
||||
return "args_setInt".to_string();
|
||||
}
|
||||
if self.type_name == "float" {
|
||||
return "args_setFloat".to_string();
|
||||
}
|
||||
if self.type_name == "pointer" {
|
||||
return "args_setPtr".to_string();
|
||||
}
|
||||
if self.type_name == "str" {
|
||||
return "args_setStr".to_string();
|
||||
}
|
||||
return "args_setPtr".to_string();
|
||||
}
|
||||
pub fn get_fn(&self) -> String {
|
||||
if self.type_name == "int" {
|
||||
return "args_getInt".to_string();
|
||||
}
|
||||
if self.type_name == "float" {
|
||||
return "args_getFloat".to_string();
|
||||
}
|
||||
if self.type_name == "pointer" {
|
||||
return "args_getPtr".to_string();
|
||||
}
|
||||
if self.type_name == "str" {
|
||||
return "args_getStr".to_string();
|
||||
}
|
||||
return "args_getPtr".to_string();
|
||||
}
|
||||
}
|
35
pikascript-compiler-rust/src/script.rs
Normal file
35
pikascript-compiler-rust/src/script.rs
Normal file
@ -0,0 +1,35 @@
|
||||
use crate::class_info::ClassInfo;
|
||||
use crate::my_string;
|
||||
#[derive(Debug)]
|
||||
pub struct Script {
|
||||
pub content: String,
|
||||
}
|
||||
|
||||
impl Script {
|
||||
pub fn new() -> Script {
|
||||
return Script {
|
||||
content: String::new(),
|
||||
};
|
||||
}
|
||||
pub fn add(&mut self, content: &String) {
|
||||
self.content.push_str(&Script::obj_run(content));
|
||||
}
|
||||
pub fn assert(class_info: &ClassInfo, content: &String) -> bool {
|
||||
let cmd = my_string::cut(content, '=', '(').unwrap();
|
||||
let cmd = cmd.replace(" ", "");
|
||||
let called_first_object = match my_string::get_first_token(&cmd, '.') {
|
||||
Some(token) => token,
|
||||
None => cmd,
|
||||
};
|
||||
for (_, obj_info) in class_info.object_list.iter() {
|
||||
let obj_name = obj_info.name.clone();
|
||||
if called_first_object == obj_name {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
pub fn obj_run(cmd: &String) -> String {
|
||||
return format!(" obj_run(pikaMain, \"{}\");\r\n", cmd);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user