Skip to content

Commit

Permalink
fix: python script backend bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
mtshiba committed Nov 1, 2023
1 parent 641a60b commit a205e2e
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 31 deletions.
86 changes: 55 additions & 31 deletions crates/erg_compiler/transpile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use crate::link_hir::HIRLinker;
use crate::module::SharedCompilerResource;
use crate::ty::typaram::OpKind;
use crate::ty::value::ValueObj;
use crate::ty::{Field, Type};
use crate::ty::{Field, Type, VisibilityModifier};
use crate::varinfo::{AbsLocation, VarInfo};

/// patch method -> function
Expand Down Expand Up @@ -489,7 +489,7 @@ impl PyScriptGenerator {
s.replace('\n', "\\n")
.replace('\r', "\\r")
.replace('\t', "\\t")
.replace('\'', "\\'")
// .replace('\'', "\\'")
.replace('\0', "\\0")
}

Expand Down Expand Up @@ -600,9 +600,9 @@ impl PyScriptGenerator {
if attr.body.block.len() > 1 {
let name = format!("instant_block_{}__", self.fresh_var_n);
self.fresh_var_n += 1;
let mut code = format!("def {name}():\n");
code += &self.transpile_block(attr.body.block, Return);
self.prelude += &code;
let mut instant = format!("def {name}():\n");
instant += &self.transpile_block(attr.body.block, Return);
self.prelude += &instant;
values += &format!("{name}(),");
} else {
let expr = attr.body.block.remove(0);
Expand Down Expand Up @@ -717,13 +717,17 @@ impl PyScriptGenerator {
todo!()
};
let non_default = block.params.non_defaults.get(0).unwrap();
let param = match &non_default.raw.pat {
let param_token = match &non_default.raw.pat {
ParamPattern::VarName(name) => name.token(),
ParamPattern::Discard(token) => token,
_ => unreachable!(),
};
code += &format!("{}__ ", replace_non_symbolic(&param.content));
code += &format!("in {}:\n", self.transpile_expr(iter));
code += &Self::transpile_name(
&VisibilityModifier::Private,
param_token.inspect(),
&non_default.vi,
);
code += &format!(" in {}:\n", self.transpile_expr(iter));
code += &self.transpile_block(block.body, Discard);
code
}
Expand Down Expand Up @@ -815,11 +819,11 @@ impl PyScriptGenerator {
let target = arm.params.non_defaults.get(0).unwrap();
match &target.raw.pat {
ParamPattern::VarName(param) => {
let param = if &param.token().content == "_" {
"_".to_string()
} else {
replace_non_symbolic(&param.token().content) + "__"
};
let param = Self::transpile_name(
&VisibilityModifier::Private,
param.inspect(),
&target.vi,
);
match target.raw.t_spec.as_ref().map(|t| &t.t_spec) {
Some(TypeSpec::Enum(enum_t)) => {
let values = ValueObj::vec_from_const_args(enum_t.clone());
Expand Down Expand Up @@ -927,15 +931,26 @@ impl PyScriptGenerator {
}

fn transpile_ident(ident: Identifier) -> String {
if let Some(py_name) = ident.vi.py_name {
return demangle(&py_name);
Self::transpile_name(ident.vis(), ident.inspect(), &ident.vi)
}

fn transpile_name(vis: &VisibilityModifier, name: &Str, vi: &VarInfo) -> String {
if let Some(py_name) = &vi.py_name {
return demangle(py_name);
}
let name = ident.inspect().to_string();
let name = replace_non_symbolic(&name);
if ident.vis().is_public() || &name == "_" {
name
let name = replace_non_symbolic(name);
if vis.is_public() || &name == "_" {
name.to_string()
} else {
format!("{name}__")
let def_line = vi.def_loc.loc.ln_begin().unwrap_or(0);
let def_col = vi.def_loc.loc.col_begin().unwrap_or(0);
let line_mangling = match (def_line, def_col) {
(0, 0) => "".to_string(),
(0, _) => format!("_C{def_col}"),
(_, 0) => format!("_L{def_line}"),
(_, _) => format!("_L{def_line}_C{def_col}"),
};
format!("{name}{line_mangling}")
}
}

Expand All @@ -944,7 +959,12 @@ impl PyScriptGenerator {
for non_default in params.non_defaults {
match non_default.raw.pat {
ParamPattern::VarName(param) => {
code += &format!("{}__,", replace_non_symbolic(&param.into_token().content));
code += &Self::transpile_name(
&VisibilityModifier::Private,
param.inspect(),
&non_default.vi,
);
code += ",";
}
ParamPattern::Discard(_) => {
code += &format!("_{},", self.fresh_var_n);
Expand All @@ -957,8 +977,12 @@ impl PyScriptGenerator {
match default.sig.raw.pat {
ParamPattern::VarName(param) => {
code += &format!(
"{}__ = {},",
replace_non_symbolic(&param.into_token().content),
"{} = {},",
Self::transpile_name(
&VisibilityModifier::Private,
param.inspect(),
&default.sig.vi
),
self.transpile_expr(default.default_val),
);
}
Expand Down Expand Up @@ -1034,10 +1058,10 @@ impl PyScriptGenerator {
if def.body.block.len() > 1 {
let name = format!("instant_block_{}__", self.fresh_var_n);
self.fresh_var_n += 1;
let mut code = format!("def {name}():\n");
code += &self.transpile_block(def.body.block, Return);
self.prelude += &code;
format!("{name}()")
let mut instant = format!("def {name}():\n");
instant += &self.transpile_block(def.body.block, Return);
self.prelude += &instant;
code + &format!("{name}()")
} else {
let expr = def.body.block.remove(0);
code += &self.transpile_expr(expr);
Expand Down Expand Up @@ -1108,10 +1132,10 @@ impl PyScriptGenerator {
if redef.block.len() > 1 {
let name = format!("instant_block_{}__", self.fresh_var_n);
self.fresh_var_n += 1;
let mut code = format!("def {name}():\n");
code += &self.transpile_block(redef.block, Return);
self.prelude += &code;
format!("{name}()")
let mut instant = format!("def {name}():\n");
instant += &self.transpile_block(redef.block, Return);
self.prelude += &instant;
code + &format!("{name}()")
} else {
let expr = redef.block.remove(0);
code += &self.transpile_expr(expr);
Expand Down
30 changes: 30 additions & 0 deletions tests/embed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,36 @@ print!(i, end:=\"\")
Ok(())
}

#[test]
fn test_transpiler_embedding4() -> Result<(), ()> {
if env_python_version().minor < Some(10) {
println!("skipped: {}", fn_name!());
return Ok(());
}
let mut trans = Transpiler::default();
let res = trans
.transpile(
"
func x, y =
z = 1 + y
x + z
z = 2
print! func(z, 0), end:=\"\"
print! z, end:=\"\"
"
.into(),
"exec",
)
.map_err(|es| {
es.errors.write_all_stderr();
})?;
let res = exec_py_code_with_output(res.object.code(), &[]).map_err(|_| ())?;
assert!(res.status.success());
assert_eq!(res.stdout, b"32");
Ok(())
}

#[test]
fn test_builder() -> Result<(), ()> {
let mods = ["math", "time"];
Expand Down

0 comments on commit a205e2e

Please sign in to comment.