Fix builtin types methods

This commit is contained in:
Shunsuke Shibayama 2023-02-03 00:23:42 +09:00
parent c56ef64576
commit 8cdc735486
12 changed files with 180 additions and 7 deletions

View file

@ -475,6 +475,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_str = value.is_str();
let is_float = value.is_float();
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();
@ -488,12 +489,15 @@ 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_float {
self.emit_push_null();
self.emit_load_name_instr(Identifier::public("Float"));
} else if is_str { } else if is_str {
self.emit_push_null(); self.emit_push_null();
self.emit_load_name_instr(Identifier::public("Str")); self.emit_load_name_instr(Identifier::public("Str"));
} }
} }
let wrapped = is_str || is_int; // is_int => is_nat and is_bool let wrapped = is_str || is_float; // is_float => is_int && is_nat && is_bool
let idx = self let idx = self
.mut_cur_block_codeobj() .mut_cur_block_codeobj()
.consts .consts
@ -678,7 +682,7 @@ impl PyCodeGenerator {
"if__" | "for__" | "while__" | "with__" | "discard__" => { "if__" | "for__" | "while__" | "with__" | "discard__" => {
self.load_control(); self.load_control();
} }
"int__" | "nat__" => { "int__" | "nat__" | "str__" | "float__" => {
self.load_convertors(); self.load_convertors();
} }
_ => {} _ => {}

View file

@ -278,7 +278,7 @@ impl Context {
); );
self.register_builtin_py_impl(FUNC_ROUND, t_round, Immutable, vis, Some(FUNC_ROUND)); self.register_builtin_py_impl(FUNC_ROUND, t_round, Immutable, vis, Some(FUNC_ROUND));
self.register_builtin_py_impl(FUNC_SORTED, t_sorted, Immutable, vis, Some(FUNC_SORTED)); self.register_builtin_py_impl(FUNC_SORTED, t_sorted, Immutable, vis, Some(FUNC_SORTED));
self.register_builtin_py_impl(FUNC_STR, t_str, Immutable, vis, Some(FUNC_STR)); self.register_builtin_py_impl(FUNC_STR, t_str, Immutable, vis, Some(FUNC_STR__));
self.register_builtin_py_impl(FUNC_SUM, t_sum, Immutable, vis, Some(FUNC_SUM)); self.register_builtin_py_impl(FUNC_SUM, t_sum, Immutable, vis, Some(FUNC_SUM));
self.register_builtin_py_impl(FUNC_ZIP, t_zip, Immutable, vis, Some(FUNC_ZIP)); self.register_builtin_py_impl(FUNC_ZIP, t_zip, Immutable, vis, Some(FUNC_ZIP));
let name = if cfg!(feature = "py_compatible") { let name = if cfg!(feature = "py_compatible") {

View file

@ -225,6 +225,7 @@ const FUNC_INT__: &str = "int__";
const FUNC_FLOAT: &str = "float"; const FUNC_FLOAT: &str = "float";
const FUNC_BOOL: &str = "bool"; const FUNC_BOOL: &str = "bool";
const FUNC_STR: &str = "str"; const FUNC_STR: &str = "str";
const FUNC_STR__: &str = "str__";
const FUNC_TYPE: &str = "type"; const FUNC_TYPE: &str = "type";
const CODE_TYPE: &str = "CodeType"; const CODE_TYPE: &str = "CodeType";
const MODULE_TYPE: &str = "ModuleType"; const MODULE_TYPE: &str = "ModuleType";

View file

@ -19,3 +19,9 @@ def with__(obj, body):
def discard__(obj): def discard__(obj):
pass pass
def then__(x, f):
if x == None or x == NotImplemented:
return x
else:
return f(x)

View file

@ -1,5 +1,7 @@
from _erg_int import Int from _erg_int import Int
from _erg_nat import Nat from _erg_nat import Nat
from _erg_float import Float
from _erg_str import Str
def int__(i): def int__(i):
try: try:
@ -12,3 +14,15 @@ def nat__(i):
return Nat(i) return Nat(i)
except: except:
return None return None
def float__(f):
try:
return Float(f)
except:
return None
def str__(s):
try:
return Str(s)
except:
return None

View file

@ -0,0 +1,100 @@
from _erg_result import Error
from _erg_control import then__
class Float(float):
def try_new(i): # -> Result[Nat]
if isinstance(i, float):
Float(i)
else:
Error("not a float")
def mutate(self):
return FloatMut(self)
def __add__(self, other):
return then__(super().__add__(other), Float)
def __radd__(self, other):
return then__(super().__radd__(other), Float)
def __sub__(self, other):
return then__(super().__sub__(other), Float)
def __rsub__(self, other):
return then__(super().__rsub__(other), Float)
def __mul__(self, other):
return then__(super().__mul__(other), Float)
def __rmul__(self, other):
return then__(super().__rmul__(other), Float)
def __div__(self, other):
return then__(super().__div__(other), Float)
def __rdiv__(self, other):
return then__(super().__rdiv__(other), Float)
def __floordiv__(self, other):
return then__(super().__floordiv__(other), Float)
def __rfloordiv__(self, other):
return then__(super().__rfloordiv__(other), Float)
def __pow__(self, other):
return then__(super().__pow__(other), Float)
def __rpow__(self, other):
return then__(super().__rpow__(other), Float)
class FloatMut(): # inherits Float
value: Float
def __init__(self, i):
self.value = Float(i)
def __repr__(self):
return self.value.__repr__()
def __deref__(self):
return self.value
def __eq__(self, other):
if isinstance(other, Float):
return self.value == other
else:
return self.value == other.value
def __ne__(self, other):
if isinstance(other, Float):
return self.value != other
else:
return self.value != other.value
def __le__(self, other):
if isinstance(other, Float):
return self.value <= other
else:
return self.value <= other.value
def __ge__(self, other):
if isinstance(other, Float):
return self.value >= other
else:
return self.value >= other.value
def __lt__(self, other):
if isinstance(other, Float):
return self.value < other
else:
return self.value < other.value
def __gt__(self, other):
if isinstance(other, Float):
return self.value > other
else:
return self.value > other.value
def __add__(self, other):
if isinstance(other, Float):
return FloatMut(self.value + other)
else:
return FloatMut(self.value + other.value)
def __sub__(self, other):
if isinstance(other, Float):
return FloatMut(self.value - other)
else:
return FloatMut(self.value - other.value)
def __mul__(self, other):
if isinstance(other, Float):
return FloatMut(self.value * other)
else:
return FloatMut(self.value * other.value)
def __floordiv__(self, other):
if isinstance(other, Float):
return FloatMut(self.value // other)
else:
return FloatMut(self.value // other.value)
def __pow__(self, other):
if isinstance(other, Float):
return FloatMut(self.value ** other)
else:
return FloatMut(self.value ** other.value)

View file

@ -1,4 +1,5 @@
from _erg_result import Error from _erg_result import Error
from _erg_control import then__
class Int(int): class Int(int):
def try_new(i): # -> Result[Nat] def try_new(i): # -> Result[Nat]
@ -12,6 +13,30 @@ class Int(int):
return Int(self - 1) return Int(self - 1)
def mutate(self): def mutate(self):
return IntMut(self) return IntMut(self)
def __add__(self, other):
return then__(super().__add__(other), Int)
def __radd__(self, other):
return then__(super().__radd__(other), Int)
def __sub__(self, other):
return then__(super().__sub__(other), Int)
def __rsub__(self, other):
return then__(super().__rsub__(other), Int)
def __mul__(self, other):
return then__(super().__mul__(other), Int)
def __rmul__(self, other):
return then__(super().__rmul__(other), Int)
def __div__(self, other):
return then__(super().__div__(other), Int)
def __rdiv__(self, other):
return then__(super().__rdiv__(other), Int)
def __floordiv__(self, other):
return then__(super().__floordiv__(other), Int)
def __rfloordiv__(self, other):
return then__(super().__rfloordiv__(other), Int)
def __pow__(self, other):
return then__(super().__pow__(other), Int)
def __rpow__(self, other):
return then__(super().__rpow__(other), Int)
class IntMut(): # inherits Int class IntMut(): # inherits Int
value: Int value: Int

View file

@ -1,6 +1,6 @@
from _erg_result import Error from _erg_result import Error
from _erg_int import Int from _erg_int import Int, IntMut
from _erg_int import IntMut from _erg_control import then__
class Nat(Int): class Nat(Int):
def try_new(i): # -> Result[Nat] def try_new(i): # -> Result[Nat]
@ -20,6 +20,10 @@ class Nat(Int):
return 0 return 0
def mutate(self): def mutate(self):
return NatMut(self) return NatMut(self)
def __add__(self, other):
return then__(super().__add__(other), Nat)
def __mul__(self, other):
return then__(super().__mul__(other), Nat)
class NatMut(IntMut): # and Nat class NatMut(IntMut): # and Nat
value: Nat value: Nat

View file

@ -1,5 +1,6 @@
from _erg_range import Range, LeftOpenRange, RightOpenRange, OpenRange, ClosedRange, RangeIterator from _erg_range import Range, LeftOpenRange, RightOpenRange, OpenRange, ClosedRange, RangeIterator
from _erg_result import Result, Error, is_ok from _erg_result import Result, Error, is_ok
from _erg_float import Float, FloatMut
from _erg_int import Int, IntMut from _erg_int import Int, IntMut
from _erg_nat import Nat, NatMut from _erg_nat import Nat, NatMut
from _erg_bool import Bool from _erg_bool import Bool

View file

@ -1,5 +1,6 @@
from _erg_result import Error from _erg_result import Error
from _erg_int import Int from _erg_int import Int
from _erg_control import then__
class Str(str): class Str(str):
def __instancecheck__(cls, obj): def __instancecheck__(cls, obj):
@ -18,6 +19,14 @@ class Str(str):
return StrMut(self) return StrMut(self)
def to_int(self): def to_int(self):
return Int(self) if self.isdigit() else None return Int(self) if self.isdigit() else None
def __add__(self, other):
return then__(super().__add__(other), Str)
def __radd__(self, other):
return then__(super().__radd__(other), Str)
def __mul__(self, other):
return then__(super().__mul__(other), Str)
def __mod__(self, other):
return then__(super().__mod__(other), Str)
class StrMut(): # Inherits Str class StrMut(): # Inherits Str
value: Str value: Str

View file

@ -701,14 +701,23 @@ impl ValueObj {
ValueObj::Type(TypeObj::Generated(gen)) ValueObj::Type(TypeObj::Generated(gen))
} }
// TODO: add Complex
pub fn is_num(&self) -> bool { pub fn is_num(&self) -> bool {
match self { match self {
Self::Int(_) | Self::Nat(_) | Self::Float(_) | Self::Bool(_) => true, Self::Float(_) | Self::Int(_) | Self::Nat(_) | Self::Bool(_) => true,
Self::Mut(n) => n.borrow().is_num(), Self::Mut(n) => n.borrow().is_num(),
_ => false, _ => false,
} }
} }
pub fn is_float(&self) -> bool {
match self {
Self::Float(_) | Self::Int(_) | Self::Nat(_) | Self::Bool(_) => true,
Self::Mut(n) => n.borrow().is_float(),
_ => false,
}
}
pub fn is_int(&self) -> bool { pub fn is_int(&self) -> bool {
match self { match self {
Self::Int(_) | Self::Nat(_) | Self::Bool(_) => true, Self::Int(_) | Self::Nat(_) | Self::Bool(_) => true,

View file

@ -27,7 +27,7 @@ D""""#
); );
{ {
let output = eval("print 1"); let output = eval("print 1"); // print! is correct
assert_eq!(output.stdout, ""); assert_eq!(output.stdout, "");
assert!(!output.stderr.is_empty()); assert!(!output.stderr.is_empty());
assert_eq!(output.status_code, Some(1)); assert_eq!(output.status_code, Some(1));