This commit is contained in:
blueloveTH 2024-07-01 18:48:57 +08:00
parent f22191faa6
commit 6befe661b7
6 changed files with 155 additions and 131 deletions

View File

@ -14,39 +14,13 @@ typedef struct pk_SStream {
c11_vector data;
} pk_SStream;
typedef struct pk_AnyStr {
int type;
union {
int _int;
int64_t _i64;
float _float;
double _double;
char _char;
const py_Str* _str;
c11_string _sv;
const char* _cstr;
void* _ptr;
};
} pk_AnyStr;
PK_INLINE pk_AnyStr pk_AnyStr__int(int x) { pk_AnyStr s; s.type = 1; s._int = x; return s; }
PK_INLINE pk_AnyStr pk_AnyStr__i64(int64_t x) { pk_AnyStr s; s.type = 2; s._i64 = x; return s; }
PK_INLINE pk_AnyStr pk_AnyStr__float(float x) { pk_AnyStr s; s.type = 3; s._float = x; return s; }
PK_INLINE pk_AnyStr pk_AnyStr__double(double x) { pk_AnyStr s; s.type = 4; s._double = x; return s; }
PK_INLINE pk_AnyStr pk_AnyStr__char(char x) { pk_AnyStr s; s.type = 5; s._char = x; return s; }
PK_INLINE pk_AnyStr pk_AnyStr__str(const py_Str* x) { pk_AnyStr s; s.type = 6; s._str = x; return s; }
PK_INLINE pk_AnyStr pk_AnyStr__sv(c11_string x) { pk_AnyStr s; s.type = 7; s._sv = x; return s; }
PK_INLINE pk_AnyStr pk_AnyStr__cstr(const char* x) { pk_AnyStr s; s.type = 8; s._cstr = x; return s; }
PK_INLINE pk_AnyStr pk_AnyStr__ptr(void* x) { pk_AnyStr s; s.type = 9; s._ptr = x; return s; }
void pk_SStream__ctor(pk_SStream* self);
void pk_SStream__ctor2(pk_SStream* self, int capacity);
void pk_SStream__dtor(pk_SStream* self);
void pk_SStream__write_int(pk_SStream* self, int);
void pk_SStream__write_i64(pk_SStream* self, int64_t);
void pk_SStream__write_float(pk_SStream* self, float, int precision);
void pk_SStream__write_double(pk_SStream* self, double, int precision);
void pk_SStream__write_f64(pk_SStream* self, double, int precision);
void pk_SStream__write_char(pk_SStream* self, char);
void pk_SStream__write_Str(pk_SStream* self, const py_Str*);
void pk_SStream__write_sv(pk_SStream* self, c11_string);
@ -54,35 +28,11 @@ void pk_SStream__write_cstr(pk_SStream* self, const char*);
void pk_SStream__write_cstrn(pk_SStream* self, const char*, int);
void pk_SStream__write_hex(pk_SStream* self, unsigned char, bool non_zero);
void pk_SStream__write_ptr(pk_SStream* self, void*);
void pk_SStream__write_any(pk_SStream* self, const char* fmt, const pk_AnyStr* args, int n);
const char* pk_format_any(const char* fmt, const pk_AnyStr* args, int n);
// Submit the stream and return the final string. The stream becomes invalid after this call
py_Str pk_SStream__submit(pk_SStream* self);
#define pk__anystr(x) _Generic((x), \
int: pk_AnyStr__int, \
int64_t: pk_AnyStr__i64, \
float: pk_AnyStr__float, \
double: pk_AnyStr__double, \
char: pk_AnyStr__char, \
const py_Str*: pk_AnyStr__str, \
c11_string: pk_AnyStr__sv, \
const char*: pk_AnyStr__cstr, \
void*: pk_AnyStr__ptr \
)(x)
#define pk__anystr_list_1(a) (pk_AnyStr[]){pk__anystr(a)}, 1
#define pk__anystr_list_2(a, b) (pk_AnyStr[]){pk__anystr(a), pk__anystr(b)}, 2
#define pk__anystr_list_3(a, b, c) (pk_AnyStr[]){pk__anystr(a), pk__anystr(b), pk__anystr(c)}, 3
#define pk__anystr_list_4(a, b, c, d) (pk_AnyStr[]){pk__anystr(a), pk__anystr(b), pk__anystr(c), pk__anystr(d)}, 4
#define pk__anystr_list_dispatcher(...) PK_NARGS_SEQ(__VA_ARGS__, pk__anystr_list_4, pk__anystr_list_3, pk__anystr_list_2, pk__anystr_list_1, 0)
#define pk__anystr_list(...) pk__anystr_list_dispatcher(__VA_ARGS__)(__VA_ARGS__)
#define pk_SStream__write(self, fmt, ...) pk_SStream__write_any(self, fmt, pk__anystr_list(__VA_ARGS__))
#define pk_format(fmt, ...) pk_format_any(fmt, pk__anystr_list(__VA_ARGS__))
void pk_vsprintf(pk_SStream* ss, const char* fmt, va_list args);
void pk_sprintf(pk_SStream* ss, const char* fmt, ...);
#ifdef __cplusplus
}

View File

@ -2,6 +2,7 @@
#include <stdint.h>
#include <stdbool.h>
#include <stdarg.h>
/************* Public Types *************/
typedef struct py_TValue py_TValue;
@ -141,7 +142,6 @@ void py_bindmethod2(py_Type type, const char* name, py_CFunction f, BindType bt)
void py_bindnativefunc(py_Ref obj, const char* name, py_CFunction f);
/// Get the reference to the i-th register.
/// @lifespan: Permanent.
py_GlobalRef py_reg(int i);
/// Get the reference of the object's `__dict__`.
@ -302,14 +302,26 @@ typedef struct pk_TypeInfo pk_TypeInfo;
pk_TypeInfo* pk_tpinfo(const py_Ref self);
/// Search the magic method from the given type to the base type.
/// Returns the reference or NULL if not found.
/// @lifespan: Permanent.
/// Return the reference or NULL if not found.
py_GlobalRef py_tpfindmagic(py_Type, py_Name name);
/// Get the type object of the given type.
/// @lifespan: Permanent.
py_GlobalRef py_tpobject(py_Type type);
/// Get the type name.
const char* py_tpname(py_Type type);
/// Python favored string formatting.
/// %d: int
/// %i: py_i64 (int64_t)
/// %f: py_f64 (double)
/// %s: const char*
/// %c: char
/// %p: void*
/// %t: py_Type
/// %n: py_Name
const char* py_fmt(const char* fmt, ...);
#define MAGIC_METHOD(x) extern uint16_t x;
#include "pocketpy/xmacros/magics.h"
#undef MAGIC_METHOD

View File

@ -5,10 +5,10 @@
#include <string.h>
static void pk_SourceData__ctor(struct pk_SourceData* self,
const char* source,
const char* filename,
enum CompileMode mode,
bool is_dynamic) {
const char* source,
const char* filename,
enum CompileMode mode,
bool is_dynamic) {
py_Str__ctor(&self->filename, filename);
self->mode = mode;
c11_vector__ctor(&self->line_starts, sizeof(const char*));
@ -19,7 +19,7 @@ static void pk_SourceData__ctor(struct pk_SourceData* self,
// Drop all '\r'
pk_SStream ss;
pk_SStream__ctor(&ss);
while(true){
while(true) {
char c = *source;
if(c == '\0') break;
if(c != '\r') pk_SStream__write_char(&ss, c);
@ -36,21 +36,27 @@ static void pk_SourceData__dtor(struct pk_SourceData* self) {
py_Str__dtor(&self->source);
c11_vector__dtor(&self->line_starts);
for(int i=0; i<self->_precompiled_tokens.count; i++){
for(int i = 0; i < self->_precompiled_tokens.count; i++) {
py_Str__dtor(c11__at(py_Str, &self->_precompiled_tokens, i));
}
c11_vector__dtor(&self->_precompiled_tokens);
}
pk_SourceData_ pk_SourceData__rcnew(const char* source, const char* filename, enum CompileMode mode, bool is_dynamic) {
pk_SourceData_ pk_SourceData__rcnew(const char* source,
const char* filename,
enum CompileMode mode,
bool is_dynamic) {
pk_SourceData_ self = malloc(sizeof(struct pk_SourceData));
pk_SourceData__ctor(self, source, filename, mode, is_dynamic);
self->rc.count = 1;
self->rc.dtor = (void(*)(void*))pk_SourceData__dtor;
self->rc.dtor = (void (*)(void*))pk_SourceData__dtor;
return self;
}
bool pk_SourceData__get_line(const struct pk_SourceData* self, int lineno, const char** st, const char** ed) {
bool pk_SourceData__get_line(const struct pk_SourceData* self,
int lineno,
const char** st,
const char** ed) {
if(self->is_precompiled || lineno == -1) { return false; }
lineno -= 1;
if(lineno < 0) lineno = 0;
@ -64,7 +70,10 @@ bool pk_SourceData__get_line(const struct pk_SourceData* self, int lineno, const
return true;
}
py_Str pk_SourceData__snapshot(const struct pk_SourceData* self, int lineno, const char* cursor, const char* name) {
py_Str pk_SourceData__snapshot(const struct pk_SourceData* self,
int lineno,
const char* cursor,
const char* name) {
pk_SStream ss;
pk_SStream__ctor(&ss);
@ -73,11 +82,13 @@ py_Str pk_SourceData__snapshot(const struct pk_SourceData* self, int lineno, con
// pk_SStream__write_cstr(&ss, "\", line ");
// pk_SStream__write_int(&ss, lineno);
pk_SStream__write(&ss,
" File \"{}\", line {}",
&self->filename,
lineno
);
// pk_SStream__write(&ss,
// " File \"{}\", line {}",
// &self->filename,
// lineno
// );
pk_sprintf(&ss, " File \"%S\", line %d", &self->filename, lineno);
if(name && *name) {
pk_SStream__write_cstr(&ss, ", in ");

View File

@ -1,31 +1,27 @@
#include "pocketpy/common/sstream.h"
#include "pocketpy/common/config.h"
#include "pocketpy/common/utils.h"
#include "pocketpy/pocketpy.h"
#include <stdarg.h>
#include <stdio.h>
#include <assert.h>
#include <ctype.h>
#include <math.h>
void pk_SStream__ctor(pk_SStream* self) {
c11_vector__ctor(&self->data, sizeof(char));
}
void pk_SStream__ctor(pk_SStream* self) { c11_vector__ctor(&self->data, sizeof(char)); }
void pk_SStream__ctor2(pk_SStream* self, int capacity) {
c11_vector__ctor(&self->data, sizeof(char));
c11_vector__reserve(&self->data, capacity);
}
void pk_SStream__dtor(pk_SStream* self) {
c11_vector__dtor(&self->data);
}
void pk_SStream__dtor(pk_SStream* self) { c11_vector__dtor(&self->data); }
void pk_SStream__write_char(pk_SStream* self, char c) {
c11_vector__push(char, &self->data, c);
}
void pk_SStream__write_char(pk_SStream* self, char c) { c11_vector__push(char, &self->data, c); }
void pk_SStream__write_int(pk_SStream* self, int i) {
char buf[12]; // sign + 10 digits + null terminator
char buf[12]; // sign + 10 digits + null terminator
snprintf(buf, sizeof(buf), "%d", i);
pk_SStream__write_cstr(self, buf);
}
@ -34,16 +30,16 @@ void pk_SStream__write_i64(pk_SStream* self, int64_t val) {
// sign + 21 digits + null terminator
// str(-2**64).__len__() == 21
c11_vector__reserve(&self->data, self->data.count + 23);
if(val == 0){
if(val == 0) {
pk_SStream__write_char(self, '0');
return;
}
if(val < 0){
if(val < 0) {
pk_SStream__write_char(self, '-');
val = -val;
}
int start = self->data.count;
while(val){
while(val) {
c11_vector__push(char, &self->data, '0' + val % 10);
val /= 10;
}
@ -51,11 +47,7 @@ void pk_SStream__write_i64(pk_SStream* self, int64_t val) {
c11_vector__reverse(char, &self->data, start, end);
}
void pk_SStream__write_float(pk_SStream* self, float val, int precision){
pk_SStream__write_double(self, val, precision);
}
void pk_SStream__write_double(pk_SStream* self, double val, int precision){
void pk_SStream__write_f64(pk_SStream* self, double val, int precision) {
if(isinf(val)) {
pk_SStream__write_cstr(self, val > 0 ? "inf" : "-inf");
return;
@ -75,8 +67,11 @@ void pk_SStream__write_double(pk_SStream* self, double val, int precision){
}
pk_SStream__write_cstr(self, b);
bool all_is_digit = true;
for(int i = 1; i < size; i++){
if(!isdigit(b[i])){ all_is_digit = false; break; }
for(int i = 1; i < size; i++) {
if(!isdigit(b[i])) {
all_is_digit = false;
break;
}
}
if(all_is_digit) pk_SStream__write_cstr(self, ".0");
}
@ -124,53 +119,103 @@ void pk_SStream__write_ptr(pk_SStream* self, void* p) {
}
}
void pk_SStream__write_any(pk_SStream* self, const char* fmt, const pk_AnyStr* args, int n){
int i = 0;
while(*fmt){
if(*fmt == '{' && fmt[1] == '}'){
assert(i < n);
switch(args[i].type){
case 1: pk_SStream__write_int(self, args[i]._int); break;
case 2: pk_SStream__write_i64(self, args[i]._i64); break;
case 3: pk_SStream__write_float(self, args[i]._float, -1); break;
case 4: pk_SStream__write_double(self, args[i]._double, -1); break;
case 5: pk_SStream__write_char(self, args[i]._char); break;
case 6: pk_SStream__write_Str(self, args[i]._str); break;
case 7: pk_SStream__write_sv(self, args[i]._sv); break;
case 8: pk_SStream__write_cstr(self, args[i]._cstr); break;
case 9: pk_SStream__write_ptr(self, args[i]._ptr); break;
default: assert(0); break;
}
fmt += 2;
i++;
}else{
pk_SStream__write_char(self, *fmt);
fmt++;
}
}
}
py_Str pk_SStream__submit(pk_SStream* self) {
c11_vector__push(char, &self->data, '\0');
c11_array a = c11_vector__submit(&self->data);
// TODO: optimize c11__isascii
py_Str retval = {
.size = a.count - 1,
.is_ascii = c11__isascii((char*)a.data, a.count),
.is_sso = false,
._ptr = (char*)a.data
};
py_Str retval = {.size = a.count - 1,
.is_ascii = c11__isascii((char*)a.data, a.count),
.is_sso = false,
._ptr = (char*)a.data};
return retval;
}
const char* pk_format_any(const char* fmt, const pk_AnyStr* args, int n){
void pk_vsprintf(pk_SStream* ss, const char* fmt, va_list args) {
while(fmt) {
char c = *fmt;
if(c != '%') {
pk_SStream__write_char(ss, c);
fmt++;
continue;
}
fmt++;
c = *fmt;
switch(c) {
case 'd': {
int i = va_arg(args, int);
pk_SStream__write_int(ss, i);
break;
}
case 'i': {
int64_t i = va_arg(args, int64_t);
pk_SStream__write_i64(ss, i);
break;
}
case 'f': {
double d = va_arg(args, double);
pk_SStream__write_f64(ss, d, -1);
break;
}
case 's': {
const char* s = va_arg(args, const char*);
pk_SStream__write_cstr(ss, s);
break;
}
case 'S': {
const py_Str* s = va_arg(args, const py_Str*);
pk_SStream__write_Str(ss, s);
break;
}
case 'c': {
char c = va_arg(args, int);
pk_SStream__write_char(ss, c);
break;
}
case 'p': {
void* p = va_arg(args, void*);
pk_SStream__write_ptr(ss, p);
break;
}
case 't': {
py_Type t = va_arg(args, int);
pk_SStream__write_cstr(ss, py_tpname(t));
break;
}
case 'n': {
py_Name n = va_arg(args, int);
pk_SStream__write_cstr(ss, py_name2str(n));
break;
}
case '%': pk_SStream__write_char(ss, '%'); break;
default:
pk_SStream__write_char(ss, c);
assert(false); // invalid format
break;
}
fmt++;
}
}
void pk_sprintf(pk_SStream* ss, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
pk_vsprintf(ss, fmt, args);
va_end(args);
}
const char* py_fmt(const char* fmt, ...) {
PK_THREAD_LOCAL pk_SStream ss;
if(ss.data.elem_size == 0){
pk_SStream__ctor2(&ss, 128);
}else{
if(ss.data.elem_size == 0) {
pk_SStream__ctor2(&ss, 256);
} else {
c11_vector__clear(&ss.data);
}
pk_SStream__write_any(&ss, fmt, args, n);
va_list args;
va_start(args, fmt);
pk_vsprintf(&ss, fmt, args);
va_end(args);
pk_SStream__write_char(&ss, '\0');
return (const char*)ss.data.data;
}

View File

@ -823,7 +823,7 @@ Error* pk_Lexer__process_and_dump(pk_SourceData_ src, py_Str* out) {
break;
case TokenValue_F64:
pk_SStream__write_char(&ss, 'F');
pk_SStream__write_float(&ss, token->value._f64, -1);
pk_SStream__write_f64(&ss, token->value._f64, -1);
break;
case TokenValue_STR: {
pk_SStream__write_char(&ss, 'S');

View File

@ -87,6 +87,12 @@ py_Ref py_tpobject(py_Type type) {
return &c11__at(pk_TypeInfo, &vm->types, type)->self;
}
const char* py_tpname(py_Type type) {
pk_VM* vm = pk_current_vm;
py_Name name = c11__at(pk_TypeInfo, &vm->types, type)->name;
return py_name2str(name);
}
bool py_callmagic(py_Name name, int argc, py_Ref argv) {
assert(argc >= 1);
assert(py_ismagicname(name));