nac3embedded: compile again

This commit is contained in:
Sebastien Bourdeauducq 2021-09-23 19:30:03 +08:00
parent a508baae20
commit edd60e3f9a
7 changed files with 286 additions and 189 deletions

158
Cargo.lock generated
View File

@ -65,15 +65,15 @@ checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "1.2.1" version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.68" version = "1.0.70"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787" checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
@ -155,16 +155,6 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
[[package]]
name = "ctor"
version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e98e2ad1a782e33928b96fc3948e7c355e5af34ba4de7670fe8bac2a3b2006d"
dependencies = [
"quote",
"syn",
]
[[package]] [[package]]
name = "diff" name = "diff"
version = "0.1.12" version = "0.1.12"
@ -224,22 +214,11 @@ dependencies = [
"wasi", "wasi",
] ]
[[package]]
name = "ghost"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a5bcf1bbeab73aa4cf2fde60a846858dc036163c7c33bec309f8d17de785479"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.9.1" version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
@ -252,9 +231,9 @@ dependencies = [
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "1.6.2" version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3" checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"hashbrown", "hashbrown",
@ -295,7 +274,7 @@ dependencies = [
[[package]] [[package]]
name = "inkwell" name = "inkwell"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/TheDan64/inkwell?branch=master#aa4de1d78471a3d2f0fda1f56801177ddf80f3bf" source = "git+https://github.com/TheDan64/inkwell?branch=master#d018ee22e4b5241dec2bc32ca67f3d4caaecee47"
dependencies = [ dependencies = [
"either", "either",
"inkwell_internals", "inkwell_internals",
@ -309,7 +288,7 @@ dependencies = [
[[package]] [[package]]
name = "inkwell_internals" name = "inkwell_internals"
version = "0.3.0" version = "0.3.0"
source = "git+https://github.com/TheDan64/inkwell?branch=master#aa4de1d78471a3d2f0fda1f56801177ddf80f3bf" source = "git+https://github.com/TheDan64/inkwell?branch=master#d018ee22e4b5241dec2bc32ca67f3d4caaecee47"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -318,35 +297,13 @@ dependencies = [
[[package]] [[package]]
name = "instant" name = "instant"
version = "0.1.9" version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" checksum = "bee0328b1209d157ef001c94dd85b4f8f64139adb0eac2659f4b08382b2f474d"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "inventory"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f0f7efb804ec95e33db9ad49e4252f049e37e8b0a4652e3cd61f7999f2eff7f"
dependencies = [
"ctor",
"ghost",
"inventory-impl",
]
[[package]]
name = "inventory-impl"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75c094e94816723ab936484666968f5b58060492e880f3c8d00489a1e244fa51"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "itertools" name = "itertools"
version = "0.10.1" version = "0.10.1"
@ -396,15 +353,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.97" version = "0.2.102"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6" checksum = "a2a5ac8f984bfcf3a823267e5fde638acc3325f6496633a5da6bb6eb2171e103"
[[package]] [[package]]
name = "llvm-sys" name = "llvm-sys"
version = "110.0.1" version = "110.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21ede189444b8c78907e5d36da5dabcf153170fcff9c1dba48afc4b33c7e19f0" checksum = "3b7cc88ba864d592f52132ed3a19a97118fe16c92a63961f54b0ab7279c5407f"
dependencies = [ dependencies = [
"cc", "cc",
"lazy_static", "lazy_static",
@ -415,9 +372,9 @@ dependencies = [
[[package]] [[package]]
name = "lock_api" name = "lock_api"
version = "0.4.4" version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0382880606dff6d15c9476c416d18690b72742aa7b605bb6dd6ec9030fbf07eb" checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109"
dependencies = [ dependencies = [
"scopeguard", "scopeguard",
] ]
@ -433,9 +390,9 @@ dependencies = [
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.4.0" version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
[[package]] [[package]]
name = "memoffset" name = "memoffset"
@ -454,7 +411,7 @@ dependencies = [
"indoc 1.0.3", "indoc 1.0.3",
"inkwell", "inkwell",
"itertools", "itertools",
"num-bigint 0.3.2", "num-bigint 0.3.3",
"num-traits", "num-traits",
"parking_lot", "parking_lot",
"rayon", "rayon",
@ -468,6 +425,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"inkwell", "inkwell",
"nac3core", "nac3core",
"parking_lot",
"pyo3", "pyo3",
"rustpython-parser", "rustpython-parser",
] ]
@ -490,9 +448,9 @@ checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
[[package]] [[package]]
name = "num-bigint" name = "num-bigint"
version = "0.3.2" version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d0a3d5e207573f948a9e5376662aa743a2ea13f7c50a554d7af443a73fbfeba" checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"num-integer", "num-integer",
@ -501,9 +459,9 @@ dependencies = [
[[package]] [[package]]
name = "num-bigint" name = "num-bigint"
version = "0.4.0" version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e0d047c1062aa51e256408c560894e5251f08925980e53cf1aa5bd00eec6512" checksum = "74e768dff5fb39a41b3bcd30bb25cf989706c90d028d1ad71971987aa309d535"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"num-integer", "num-integer",
@ -547,9 +505,9 @@ checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
[[package]] [[package]]
name = "parking_lot" name = "parking_lot"
version = "0.11.1" version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
dependencies = [ dependencies = [
"instant", "instant",
"lock_api", "lock_api",
@ -558,9 +516,9 @@ dependencies = [
[[package]] [[package]]
name = "parking_lot_core" name = "parking_lot_core"
version = "0.8.3" version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"instant", "instant",
@ -687,47 +645,57 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.27" version = "1.0.29"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d"
dependencies = [ dependencies = [
"unicode-xid", "unicode-xid",
] ]
[[package]] [[package]]
name = "pyo3" name = "pyo3"
version = "0.12.4" version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf6bbbe8f70d179260b3728e5d04eb012f4f0c7988e58c11433dd689cecaa72e" checksum = "35100f9347670a566a67aa623369293703322bb9db77d99d7df7313b575ae0c8"
dependencies = [ dependencies = [
"ctor", "cfg-if",
"indoc 0.3.6", "indoc 0.3.6",
"inventory",
"libc", "libc",
"parking_lot", "parking_lot",
"paste", "paste",
"pyo3cls", "pyo3-build-config",
"pyo3-macros",
"unindent", "unindent",
] ]
[[package]] [[package]]
name = "pyo3-derive-backend" name = "pyo3-build-config"
version = "0.12.4" version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10ecd0eb6ed7b3d9965b4f4370b5b9e99e3e5e8742000e1c452c018f8c2a322f" checksum = "d12961738cacbd7f91b7c43bc25cfeeaa2698ad07a04b3be0aa88b950865738f"
dependencies = [ dependencies = [
"proc-macro2", "once_cell",
]
[[package]]
name = "pyo3-macros"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc0bc5215d704824dfddddc03f93cb572e1155c68b6761c37005e1c288808ea8"
dependencies = [
"pyo3-macros-backend",
"quote", "quote",
"syn", "syn",
] ]
[[package]] [[package]]
name = "pyo3cls" name = "pyo3-macros-backend"
version = "0.12.4" version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d344fdaa6a834a06dd1720ff104ea12fe101dad2e8db89345af9db74c0bb11a0" checksum = "71623fc593224afaab918aa3afcaf86ed2f43d34f6afde7f3922608f253240df"
dependencies = [ dependencies = [
"pyo3-derive-backend", "proc-macro2",
"pyo3-build-config",
"quote", "quote",
"syn", "syn",
] ]
@ -808,9 +776,9 @@ dependencies = [
[[package]] [[package]]
name = "redox_syscall" name = "redox_syscall"
version = "0.2.9" version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee" checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
dependencies = [ dependencies = [
"bitflags", "bitflags",
] ]
@ -847,7 +815,7 @@ name = "rustpython-ast"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/pca006132/RustPython?branch=main#c6248660e33a2db8c2d745097ac4bff13598d955" source = "git+https://github.com/pca006132/RustPython?branch=main#c6248660e33a2db8c2d745097ac4bff13598d955"
dependencies = [ dependencies = [
"num-bigint 0.4.0", "num-bigint 0.4.2",
] ]
[[package]] [[package]]
@ -859,7 +827,7 @@ dependencies = [
"lalrpop", "lalrpop",
"lalrpop-util", "lalrpop-util",
"log", "log",
"num-bigint 0.4.0", "num-bigint 0.4.2",
"num-traits", "num-traits",
"phf", "phf",
"rustpython-ast", "rustpython-ast",
@ -900,9 +868,9 @@ dependencies = [
[[package]] [[package]]
name = "siphasher" name = "siphasher"
version = "0.3.5" version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbce6d4507c7e4a3962091436e56e95290cb71fa302d0d270e32130b75fbff27" checksum = "533494a8f9b724d33625ab53c6c4800f7cc445895924a8ef649222dcb76e938b"
[[package]] [[package]]
name = "smallvec" name = "smallvec"
@ -924,9 +892,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.73" version = "1.0.76"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7" checksum = "c6f107db402c2c2055242dbf4d2af0e69197202e9faacbef9571bbe47f5a1b84"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",

View File

@ -9,7 +9,8 @@ name = "nac3embedded"
crate-type = ["cdylib"] crate-type = ["cdylib"]
[dependencies] [dependencies]
pyo3 = { version = "0.12.4", features = ["extension-module"] } pyo3 = { version = "0.14", features = ["extension-module"] }
inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "master", features = ["llvm11-0"] }
rustpython-parser = { git = "https://github.com/pca006132/RustPython", branch = "main" } rustpython-parser = { git = "https://github.com/pca006132/RustPython", branch = "main" }
inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "master", features = ["llvm11-0"] }
parking_lot = "0.11"
nac3core = { path = "../nac3core" } nac3core = { path = "../nac3core" }

View File

@ -1,10 +1,11 @@
from language import * from language import *
@kernel
class Demo: class Demo:
@kernel @kernel
def run(self: bool) -> bool: def run(self):
return False pass
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -1,19 +1,29 @@
from inspect import isclass
from functools import wraps from functools import wraps
import nac3embedded import nac3embedded
__all__ = ["kernel", "portable"] __all__ = ["kernel"]
def kernel(function): nac3 = nac3embedded.NAC3()
@wraps(function) allow_class_registration = True
def run_on_core(self, *args, **kwargs):
nac3 = nac3embedded.NAC3()
nac3.register_host_object(self)
nac3.compile_method(self, function.__name__)
return run_on_core
def portable(function): def kernel(function_or_class):
return fn global allow_class_registration
if isclass(function_or_class):
assert allow_class_registration
nac3.register_class(function_or_class)
return function_or_class
else:
@wraps(function_or_class)
def run_on_core(self, *args, **kwargs):
global allow_class_registration
if allow_class_registration:
nac3.analyze()
allow_class_registration = False
nac3.compile_method(self.__class__.__name__, function_or_class.__name__)
return run_on_core

View File

@ -1,111 +1,177 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::collections::hash_map::Entry; use std::sync::Arc;
use std::path::Path;
use pyo3::prelude::*; use pyo3::prelude::*;
use pyo3::exceptions; use pyo3::exceptions;
use rustpython_parser::{ast, parser}; use rustpython_parser::parser;
use inkwell::context::Context; use inkwell::{
use inkwell::targets::*; passes::{PassManager, PassManagerBuilder},
targets::*,
OptimizationLevel,
};
use nac3core::CodeGen; use nac3core::typecheck::type_inferencer::PrimitiveStore;
use nac3core::{
codegen::{CodeGenTask, WithCall, WorkerRegistry},
symbol_resolver::SymbolResolver,
toplevel::{composer::TopLevelComposer, TopLevelContext, TopLevelDef},
typecheck::typedef::{FunSignature, FuncArg},
};
fn runs_on_core(decorator_list: &[ast::Expression]) -> bool { mod symbol_resolver;
for decorator in decorator_list.iter() { use symbol_resolver::*;
if let ast::ExpressionType::Identifier { name } = &decorator.node {
if name == "kernel" || name == "portable" {
return true
}
}
}
false
}
#[pyclass(name=NAC3)] // TODO: do we really want unsendable?
// TopLevelComposer causes a lot of problems for Send.
#[pyclass(unsendable,name="NAC3")]
struct Nac3 { struct Nac3 {
type_definitions: HashMap<i64, ast::Program>, primitive: PrimitiveStore,
host_objects: HashMap<i64, i64>, internal_resolver: Arc<ResolverInternal>,
resolver: Arc<Box<dyn SymbolResolver + Send + Sync>>,
composer: TopLevelComposer,
top_level: Option<Arc<TopLevelContext>>
} }
#[pymethods] #[pymethods]
impl Nac3 { impl Nac3 {
#[new] #[new]
fn new() -> Self { fn new() -> Self {
let primitive: PrimitiveStore = TopLevelComposer::make_primitives().0;
let (composer, builtins_def, builtins_ty) = TopLevelComposer::new(vec![
("output_int".into(), FunSignature {
args: vec![FuncArg {
name: "x".into(),
ty: primitive.int32,
default_value: None,
}],
ret: primitive.none,
vars: HashMap::new(),
}),
]);
let internal_resolver: Arc<ResolverInternal> = ResolverInternal {
id_to_type: builtins_ty.into(),
id_to_def: builtins_def.into(),
class_names: Default::default(),
}.into();
let resolver = Arc::new(
Box::new(Resolver(internal_resolver.clone())) as Box<dyn SymbolResolver + Send + Sync>
);
Nac3 { Nac3 {
type_definitions: HashMap::new(), primitive: primitive,
host_objects: HashMap::new(), internal_resolver: internal_resolver,
resolver: resolver,
composer: composer,
top_level: None
} }
} }
fn register_host_object(&mut self, obj: PyObject) -> PyResult<()> { fn register_class(&mut self, obj: PyObject) -> PyResult<()> {
Python::with_gil(|py| -> PyResult<()> { Python::with_gil(|py| -> PyResult<()> {
let obj: &PyAny = obj.extract(py)?; let obj: &PyAny = obj.extract(py)?;
let obj_type = obj.get_type();
let builtins = PyModule::import(py, "builtins")?; let source = PyModule::import(py, "inspect")?.getattr("getsource")?.call1((obj, ))?.extract()?;
let type_id = builtins.call1("id", (obj_type, ))?.extract()?; let parser_result = parser::parse_program(source).map_err(|e|
exceptions::PySyntaxError::new_err(format!("failed to parse host object source: {}", e)))?;
let entry = self.type_definitions.entry(type_id); for stmt in parser_result.into_iter() {
if let Entry::Vacant(entry) = entry { let (name, def_id, ty) = self.composer.register_top_level(
let source = PyModule::import(py, "inspect")?.call1("getsource", (obj_type, ))?; stmt,
let ast = parser::parse_program(source.extract()?).map_err(|e| Some(self.resolver.clone()),
exceptions::PySyntaxError::new_err(format!("failed to parse host object source: {}", e)))?; "__main__".into(),
entry.insert(ast); ).unwrap();
// TODO: examine AST and recursively register dependencies
};
let obj_id = builtins.call1("id", (obj, ))?.extract()?; self.internal_resolver.add_id_def(name.clone(), def_id);
match self.host_objects.entry(obj_id) { if let Some(ty) = ty {
Entry::Vacant(entry) => entry.insert(type_id), self.internal_resolver.add_id_type(name, ty);
Entry::Occupied(_) => return Err(
exceptions::PyValueError::new_err("host object registered twice")),
};
// TODO: collect other information about host object, e.g. value of fields
Ok(())
})
}
fn compile_method(&self, obj: PyObject, name: String) -> PyResult<()> {
Python::with_gil(|py| -> PyResult<()> {
let obj: &PyAny = obj.extract(py)?;
let builtins = PyModule::import(py, "builtins")?;
let obj_id = builtins.call1("id", (obj, ))?.extract()?;
let type_id = self.host_objects.get(&obj_id).ok_or_else(||
exceptions::PyKeyError::new_err("type of host object not found"))?;
let ast = self.type_definitions.get(&type_id).ok_or_else(||
exceptions::PyKeyError::new_err("type definition not found"))?;
if let ast::StatementType::ClassDef {
name: _,
body,
bases: _,
keywords: _,
decorator_list: _ } = &ast.statements[0].node {
for statement in body.iter() {
if let ast::StatementType::FunctionDef {
is_async: _,
name: funcdef_name,
args: _,
body: _,
decorator_list,
returns: _ } = &statement.node {
if runs_on_core(decorator_list) && funcdef_name == &name {
let context = Context::create();
let mut codegen = CodeGen::new(&context);
codegen.compile_toplevel(&body[0]).map_err(|e|
exceptions::PyRuntimeError::new_err(format!("compilation failed: {}", e)))?;
codegen.print_ir();
}
}
} }
} else {
return Err(exceptions::PyValueError::new_err("expected ClassDef for type definition"));
} }
Ok(()) Ok(())
}) })
} }
fn analyze(&mut self) -> PyResult<()> {
self.composer.start_analysis(true).unwrap();
self.top_level = Some(Arc::new(self.composer.make_top_level_context()));
Ok(())
}
fn compile_method(&mut self, class_name: String, method_name: String) -> PyResult<()> {
let top_level = self.top_level.as_ref().unwrap();
let instance = {
let defs = top_level.definitions.read();
let class_def = defs[self.resolver.get_identifier_def(&class_name).unwrap().0].write();
let mut method_def = if let TopLevelDef::Class { methods, .. } = &*class_def {
if let Some((_name, _unification_key, definition_id)) = methods.iter().find(|method| method.0 == method_name) {
defs[definition_id.0].write()
} else {
return Err(exceptions::PyValueError::new_err("method not found"));
}
} else {
return Err(exceptions::PyTypeError::new_err("parent object is not a class"));
};
// FIXME: what is this for? What happens if the kernel is called twice?
if let TopLevelDef::Function {
instance_to_stmt,
instance_to_symbol,
..
} = &mut *method_def
{
instance_to_symbol.insert("".to_string(), method_name.clone());
instance_to_stmt[""].clone()
} else {
unreachable!()
}
};
let signature = FunSignature {
args: vec![],
ret: self.primitive.none,
vars: HashMap::new(),
};
let task = CodeGenTask {
subst: Default::default(),
symbol_name: method_name,
body: instance.body,
signature,
resolver: self.resolver.clone(),
unifier: top_level.unifiers.read()[instance.unifier_id].clone(),
calls: instance.calls,
};
let f = Arc::new(WithCall::new(Box::new(move |module| {
let builder = PassManagerBuilder::create();
builder.set_optimization_level(OptimizationLevel::Aggressive);
let passes = PassManager::create(());
builder.populate_module_pass_manager(&passes);
passes.run_on(module);
let triple = TargetMachine::get_default_triple();
let target =
Target::from_triple(&triple).expect("couldn't create target from target triple");
let target_machine = target
.create_target_machine(
&triple,
"",
"",
OptimizationLevel::Default,
RelocMode::Default,
CodeModel::Default,
)
.expect("couldn't create target machine");
target_machine
.write_to_file(module, FileType::Object, Path::new(&format!("{}.o", module.get_name().to_str().unwrap())))
.expect("couldn't write module to file");
// println!("IR:\n{}", module.print_to_string().to_str().unwrap());
})));
let threads: Vec<String> = (0..4).map(|i| format!("module{}", i)).collect();
let threads: Vec<_> = threads.iter().map(|s| s.as_str()).collect();
let (registry, handles) = WorkerRegistry::create_workers(&threads, top_level.clone(), f);
registry.add_task(task);
registry.wait_tasks_complete(handles);
Ok(())
}
} }
#[pymodule] #[pymodule]

View File

@ -0,0 +1,51 @@
use nac3core::{
location::Location,
symbol_resolver::{SymbolResolver, SymbolValue},
toplevel::DefinitionId,
typecheck::{
type_inferencer::PrimitiveStore,
typedef::{Type, Unifier},
},
};
use parking_lot::Mutex;
use std::{collections::HashMap, sync::Arc};
pub struct ResolverInternal {
pub id_to_type: Mutex<HashMap<String, Type>>,
pub id_to_def: Mutex<HashMap<String, DefinitionId>>,
pub class_names: Mutex<HashMap<String, Type>>,
}
impl ResolverInternal {
pub fn add_id_def(&self, id: String, def: DefinitionId) {
self.id_to_def.lock().insert(id, def);
}
pub fn add_id_type(&self, id: String, ty: Type) {
self.id_to_type.lock().insert(id, ty);
}
}
pub struct Resolver(pub Arc<ResolverInternal>);
impl SymbolResolver for Resolver {
fn get_symbol_type(&self, _: &mut Unifier, _: &PrimitiveStore, str: &str) -> Option<Type> {
let ret = self.0.id_to_type.lock().get(str).cloned();
if ret.is_none() {
// println!("unknown here resolver {}", str);
}
ret
}
fn get_symbol_value(&self, _: &str) -> Option<SymbolValue> {
unimplemented!()
}
fn get_symbol_location(&self, _: &str) -> Option<Location> {
unimplemented!()
}
fn get_identifier_def(&self, id: &str) -> Option<DefinitionId> {
self.0.id_to_def.lock().get(id).cloned()
}
}

View File

@ -7,5 +7,5 @@ edition = "2018"
[dependencies] [dependencies]
inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "master", features = ["llvm11-0"] } inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "master", features = ["llvm11-0"] }
rustpython-parser = { git = "https://github.com/pca006132/RustPython", branch = "main" } rustpython-parser = { git = "https://github.com/pca006132/RustPython", branch = "main" }
parking_lot = "0.11.1" parking_lot = "0.11"
nac3core = { path = "../nac3core" } nac3core = { path = "../nac3core" }