diff --git a/src/ceval.h b/src/ceval.h index ebbe49b7..47660561 100644 --- a/src/ceval.h +++ b/src/ceval.h @@ -549,7 +549,7 @@ __NEXT_STEP:; TARGET(FORMAT_STRING) { _0 = POPX(); const Str& spec = CAST(Str&, co_consts[byte.arg]); - PUSH(VAR(format(spec, _0))); + PUSH(format(spec, _0)); } DISPATCH(); #if !PK_ENABLE_COMPUTED_GOTO #if DEBUG_EXTRA_CHECK diff --git a/src/vm.h b/src/vm.h index 0ed6cbc3..b10907f2 100644 --- a/src/vm.h +++ b/src/vm.h @@ -395,7 +395,7 @@ public: PyObject* getattr(PyObject* obj, StrName name, bool throw_err=true); PyObject* get_unbound_method(PyObject* obj, StrName name, PyObject** self, bool throw_err=true, bool fallback=false); void parse_int_slice(const Slice& s, int length, int& start, int& stop, int& step); - Str format(Str, PyObject*); + PyObject* format(Str, PyObject*); void setattr(PyObject* obj, StrName name, PyObject* value); template void bind_method(PyObject*, Str, NativeFuncC); @@ -642,24 +642,36 @@ inline PyObject* VM::asRepr(PyObject* obj){ return call_method(obj, __repr__); } -inline Str VM::format(Str spec, PyObject* obj){ - char type = spec.end()[-1]; - int dot = -1; - int width, precision; +inline PyObject* VM::format(Str spec, PyObject* obj){ + if(spec.empty()) return asStr(obj); + char type; + switch(spec.end()[-1]){ + case 'f': case 'd': case 's': + type = spec.end()[-1]; + spec = spec.substr(0, spec.length() - 1); + break; + default: type = ' '; break; + } + + char pad_c = ' '; + if(spec[0] == '0'){ + pad_c = '0'; + spec = spec.substr(1); + } char align; if(spec[0] == '>'){ align = '>'; spec = spec.substr(1); - dot = spec.index("."); }else if(spec[0] == '<'){ align = '<'; spec = spec.substr(1); - dot = spec.index("."); }else{ if(is_int(obj) || is_float(obj)) align = '>'; else align = '<'; } + int dot = spec.index("."); + int width, precision; try{ if(dot >= 0){ width = Number::stoi(spec.substr(0, dot).str()); @@ -689,11 +701,11 @@ inline Str VM::format(Str spec, PyObject* obj){ } if(width > ret.length()){ int pad = width - ret.length(); - std::string padding(pad, ' '); + std::string padding(pad, pad_c); if(align == '>') ret = padding.c_str() + ret; else ret = ret + padding.c_str(); } - return ret; + return VAR(ret); } inline PyObject* VM::new_module(StrName name) { diff --git a/tests/25_rawstring.py b/tests/25_rawstring.py index cb2b8dd1..b638acf2 100644 --- a/tests/25_rawstring.py +++ b/tests/25_rawstring.py @@ -38,6 +38,11 @@ assert f'{a:>10.2f}' == ' 10.00' assert f'{a:3d}' == ' 10' assert f'{a:10d}' == ' 10' assert f'{a:1d}' == '10' +assert f'{a:010}' == '0000000010' +assert f'{a:010d}' == '0000000010' +assert f'{a:010f}' == '010.000000' +assert f'{a:010.2f}' == '0000010.00' + b = '123' assert f'{b:10}' == '123 ' assert f'{b:>10}' == ' 123'