mirror of
https://github.com/erg-lang/erg.git
synced 2025-10-02 21:44:34 +00:00
Add Str <-> Int, Nat convertors
This commit is contained in:
parent
592a77caab
commit
287a65276e
6 changed files with 63 additions and 4 deletions
|
@ -143,6 +143,7 @@ pub struct PyCodeGenerator {
|
||||||
record_type_loaded: bool,
|
record_type_loaded: bool,
|
||||||
module_type_loaded: bool,
|
module_type_loaded: bool,
|
||||||
control_loaded: bool,
|
control_loaded: bool,
|
||||||
|
convertors_loaded: bool,
|
||||||
abc_loaded: bool,
|
abc_loaded: bool,
|
||||||
unit_size: usize,
|
unit_size: usize,
|
||||||
units: PyCodeGenStack,
|
units: PyCodeGenStack,
|
||||||
|
@ -160,6 +161,7 @@ impl PyCodeGenerator {
|
||||||
record_type_loaded: false,
|
record_type_loaded: false,
|
||||||
module_type_loaded: false,
|
module_type_loaded: false,
|
||||||
control_loaded: false,
|
control_loaded: false,
|
||||||
|
convertors_loaded: false,
|
||||||
abc_loaded: false,
|
abc_loaded: false,
|
||||||
unit_size: 0,
|
unit_size: 0,
|
||||||
units: PyCodeGenStack::empty(),
|
units: PyCodeGenStack::empty(),
|
||||||
|
@ -436,6 +438,7 @@ impl PyCodeGenerator {
|
||||||
|
|
||||||
fn emit_load_const<C: Into<ValueObj>>(&mut self, cons: C) {
|
fn emit_load_const<C: Into<ValueObj>>(&mut self, cons: C) {
|
||||||
let value: ValueObj = cons.into();
|
let value: ValueObj = cons.into();
|
||||||
|
let is_str = value.is_str();
|
||||||
let is_int = value.is_int();
|
let is_int = value.is_int();
|
||||||
let is_nat = value.is_nat();
|
let is_nat = value.is_nat();
|
||||||
let is_bool = value.is_bool();
|
let is_bool = value.is_bool();
|
||||||
|
@ -449,8 +452,12 @@ impl PyCodeGenerator {
|
||||||
} else if is_int {
|
} else if is_int {
|
||||||
self.emit_push_null();
|
self.emit_push_null();
|
||||||
self.emit_load_name_instr(Identifier::public("Int"));
|
self.emit_load_name_instr(Identifier::public("Int"));
|
||||||
|
} else if is_str {
|
||||||
|
self.emit_push_null();
|
||||||
|
self.emit_load_name_instr(Identifier::public("Str"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let wrapped = is_str || is_int; // is_int => is_nat and is_bool
|
||||||
let idx = self
|
let idx = self
|
||||||
.mut_cur_block_codeobj()
|
.mut_cur_block_codeobj()
|
||||||
.consts
|
.consts
|
||||||
|
@ -463,8 +470,7 @@ impl PyCodeGenerator {
|
||||||
self.write_instr(LOAD_CONST);
|
self.write_instr(LOAD_CONST);
|
||||||
self.write_arg(idx);
|
self.write_arg(idx);
|
||||||
self.stack_inc();
|
self.stack_inc();
|
||||||
if !self.cfg.no_std && is_int {
|
if !self.cfg.no_std && wrapped {
|
||||||
// is_int => is_nat and is_bool
|
|
||||||
self.emit_call_instr(1, Name);
|
self.emit_call_instr(1, Name);
|
||||||
self.stack_dec();
|
self.stack_dec();
|
||||||
}
|
}
|
||||||
|
@ -632,8 +638,14 @@ impl PyCodeGenerator {
|
||||||
fn emit_load_name_instr(&mut self, ident: Identifier) {
|
fn emit_load_name_instr(&mut self, ident: Identifier) {
|
||||||
log!(info "entered {}({ident})", fn_name!());
|
log!(info "entered {}({ident})", fn_name!());
|
||||||
let escaped = escape_name(ident);
|
let escaped = escape_name(ident);
|
||||||
if let "if__" | "for__" | "while__" | "with__" | "discard__" = &escaped[..] {
|
match &escaped[..] {
|
||||||
self.load_control();
|
"if__" | "for__" | "while__" | "with__" | "discard__" => {
|
||||||
|
self.load_control();
|
||||||
|
}
|
||||||
|
"int__" | "nat__" => {
|
||||||
|
self.load_convertors();
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
let name = self
|
let name = self
|
||||||
.local_search(&escaped, Name)
|
.local_search(&escaped, Name)
|
||||||
|
@ -2797,6 +2809,12 @@ impl PyCodeGenerator {
|
||||||
self.control_loaded = true;
|
self.control_loaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn load_convertors(&mut self) {
|
||||||
|
let mod_name = Identifier::public("_erg_convertors");
|
||||||
|
self.emit_import_all_instr(mod_name);
|
||||||
|
self.convertors_loaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
fn load_prelude_py(&mut self) {
|
fn load_prelude_py(&mut self) {
|
||||||
self.emit_global_import_items(
|
self.emit_global_import_items(
|
||||||
Identifier::public("sys"),
|
Identifier::public("sys"),
|
||||||
|
|
|
@ -941,6 +941,12 @@ impl Context {
|
||||||
Immutable,
|
Immutable,
|
||||||
Public,
|
Public,
|
||||||
);
|
);
|
||||||
|
str_.register_builtin_impl(
|
||||||
|
"to_int",
|
||||||
|
fn_met(Str, vec![], None, vec![], or(Int, NoneType)),
|
||||||
|
Immutable,
|
||||||
|
Public,
|
||||||
|
);
|
||||||
let str_getitem_t = fn1_kw_met(Str, kw("idx", Nat), Str);
|
let str_getitem_t = fn1_kw_met(Str, kw("idx", Nat), Str);
|
||||||
str_.register_builtin_impl("__getitem__", str_getitem_t, Immutable, Public);
|
str_.register_builtin_impl("__getitem__", str_getitem_t, Immutable, Public);
|
||||||
let mut str_eq = Self::builtin_methods(Some(mono("Eq")), 2);
|
let mut str_eq = Self::builtin_methods(Some(mono("Eq")), 2);
|
||||||
|
@ -1731,6 +1737,7 @@ impl Context {
|
||||||
or(T, U),
|
or(T, U),
|
||||||
)
|
)
|
||||||
.quantify();
|
.quantify();
|
||||||
|
let t_int = nd_func(vec![kw("obj", Obj)], None, or(Int, NoneType));
|
||||||
let t_import = nd_func(
|
let t_import = nd_func(
|
||||||
vec![anon(tp_enum(Str, set! {Path.clone()}))],
|
vec![anon(tp_enum(Str, set! {Path.clone()}))],
|
||||||
None,
|
None,
|
||||||
|
@ -1769,6 +1776,7 @@ impl Context {
|
||||||
],
|
],
|
||||||
NoneType,
|
NoneType,
|
||||||
);
|
);
|
||||||
|
let t_nat = nd_func(vec![kw("obj", Obj)], None, or(Nat, NoneType));
|
||||||
// e.g. not(b: Bool!): Bool!
|
// e.g. not(b: Bool!): Bool!
|
||||||
let B = mono_q("B", subtypeof(Bool));
|
let B = mono_q("B", subtypeof(Bool));
|
||||||
let t_not = nd_func(vec![kw("b", B.clone())], None, B).quantify();
|
let t_not = nd_func(vec![kw("b", B.clone())], None, B).quantify();
|
||||||
|
@ -1808,6 +1816,7 @@ impl Context {
|
||||||
self.register_builtin_py_impl("discard", t_discard, Immutable, Private, Some("discard__"));
|
self.register_builtin_py_impl("discard", t_discard, Immutable, Private, Some("discard__"));
|
||||||
self.register_builtin_py_impl("exit", t_exit, Immutable, Private, Some("exit"));
|
self.register_builtin_py_impl("exit", t_exit, Immutable, Private, Some("exit"));
|
||||||
self.register_builtin_py_impl("if", t_if, Immutable, Private, Some("if__"));
|
self.register_builtin_py_impl("if", t_if, Immutable, Private, Some("if__"));
|
||||||
|
self.register_builtin_py_impl("int", t_int, Immutable, Private, Some("int__"));
|
||||||
self.register_builtin_py_impl("import", t_import, Immutable, Private, Some("__import__"));
|
self.register_builtin_py_impl("import", t_import, Immutable, Private, Some("__import__"));
|
||||||
self.register_builtin_py_impl(
|
self.register_builtin_py_impl(
|
||||||
"isinstance",
|
"isinstance",
|
||||||
|
@ -1825,6 +1834,7 @@ impl Context {
|
||||||
);
|
);
|
||||||
self.register_builtin_py_impl("len", t_len, Immutable, Private, Some("len"));
|
self.register_builtin_py_impl("len", t_len, Immutable, Private, Some("len"));
|
||||||
self.register_builtin_py_impl("log", t_log, Immutable, Private, Some("print"));
|
self.register_builtin_py_impl("log", t_log, Immutable, Private, Some("print"));
|
||||||
|
self.register_builtin_py_impl("nat", t_nat, Immutable, Private, Some("nat__"));
|
||||||
self.register_builtin_py_impl("not", t_not, Immutable, Private, None); // `not` is not a function in Python
|
self.register_builtin_py_impl("not", t_not, Immutable, Private, None); // `not` is not a function in Python
|
||||||
self.register_builtin_py_impl("oct", t_oct, Immutable, Private, Some("oct"));
|
self.register_builtin_py_impl("oct", t_oct, Immutable, Private, Some("oct"));
|
||||||
self.register_builtin_py_impl("ord", t_ord, Immutable, Private, Some("ord"));
|
self.register_builtin_py_impl("ord", t_ord, Immutable, Private, Some("ord"));
|
||||||
|
|
14
compiler/erg_compiler/lib/std/_erg_convertors.py
Normal file
14
compiler/erg_compiler/lib/std/_erg_convertors.py
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
from _erg_int import Int
|
||||||
|
from _erg_nat import Nat
|
||||||
|
|
||||||
|
def int__(i):
|
||||||
|
try:
|
||||||
|
return Int(i)
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def nat__(i):
|
||||||
|
try:
|
||||||
|
return Nat(i)
|
||||||
|
except:
|
||||||
|
return None
|
|
@ -1,4 +1,5 @@
|
||||||
from _erg_result import Error
|
from _erg_result import Error
|
||||||
|
from _erg_int import Int
|
||||||
|
|
||||||
class Str(str):
|
class Str(str):
|
||||||
def __instancecheck__(cls, obj):
|
def __instancecheck__(cls, obj):
|
||||||
|
@ -15,6 +16,8 @@ class Str(str):
|
||||||
return None
|
return None
|
||||||
def mutate(self):
|
def mutate(self):
|
||||||
return StrMut(self)
|
return StrMut(self)
|
||||||
|
def to_int(self):
|
||||||
|
return Int(self) if self.isdigit() else None
|
||||||
|
|
||||||
class StrMut(): # Inherits Str
|
class StrMut(): # Inherits Str
|
||||||
value: Str
|
value: Str
|
||||||
|
|
|
@ -227,6 +227,7 @@ pub struct ScriptGenerator {
|
||||||
range_ops_loaded: bool,
|
range_ops_loaded: bool,
|
||||||
builtin_types_loaded: bool,
|
builtin_types_loaded: bool,
|
||||||
builtin_control_loaded: bool,
|
builtin_control_loaded: bool,
|
||||||
|
convertors_loaded: bool,
|
||||||
prelude: String,
|
prelude: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,6 +242,7 @@ impl ScriptGenerator {
|
||||||
range_ops_loaded: false,
|
range_ops_loaded: false,
|
||||||
builtin_types_loaded: false,
|
builtin_types_loaded: false,
|
||||||
builtin_control_loaded: false,
|
builtin_control_loaded: false,
|
||||||
|
convertors_loaded: false,
|
||||||
prelude: String::new(),
|
prelude: String::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -317,6 +319,10 @@ impl ScriptGenerator {
|
||||||
self.prelude += include_str!("lib/std/_erg_control.py");
|
self.prelude += include_str!("lib/std/_erg_control.py");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn load_convertors(&mut self) {
|
||||||
|
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_convertors.py"));
|
||||||
|
}
|
||||||
|
|
||||||
fn escape_str(s: &str) -> String {
|
fn escape_str(s: &str) -> String {
|
||||||
s.replace('\n', "\\n")
|
s.replace('\n', "\\n")
|
||||||
.replace('\r', "\\r")
|
.replace('\r', "\\r")
|
||||||
|
@ -525,6 +531,10 @@ impl ScriptGenerator {
|
||||||
self.load_builtin_controls();
|
self.load_builtin_controls();
|
||||||
self.builtin_control_loaded = true;
|
self.builtin_control_loaded = true;
|
||||||
}
|
}
|
||||||
|
"int" | "nat" if !self.convertors_loaded => {
|
||||||
|
self.load_convertors();
|
||||||
|
self.convertors_loaded = true;
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
Self::transpile_ident(ident)
|
Self::transpile_ident(ident)
|
||||||
|
|
|
@ -677,6 +677,10 @@ impl ValueObj {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const fn is_str(&self) -> bool {
|
||||||
|
matches!(self, Self::Str(_))
|
||||||
|
}
|
||||||
|
|
||||||
pub const fn is_type(&self) -> bool {
|
pub const fn is_type(&self) -> bool {
|
||||||
matches!(self, Self::Type(_))
|
matches!(self, Self::Type(_))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue