mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 03:20:18 +00:00
Compare commits
3 Commits
f22191faa6
...
a9d6242a43
Author | SHA1 | Date | |
---|---|---|---|
|
a9d6242a43 | ||
|
7692899366 | ||
|
6befe661b7 |
@ -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
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
/************* Public Types *************/
|
||||
typedef struct py_TValue py_TValue;
|
||||
@ -104,6 +105,7 @@ bool py_tobool(const py_Ref);
|
||||
py_Type py_totype(const py_Ref);
|
||||
const char* py_tostr(const py_Ref);
|
||||
const char* py_tostrn(const py_Ref, int* size);
|
||||
const unsigned char* py_tobytes(const py_Ref, int* size);
|
||||
|
||||
void* py_touserdata(const py_Ref);
|
||||
|
||||
@ -141,7 +143,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 +303,27 @@ 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*
|
||||
/// %q: single quoted %s
|
||||
/// %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
|
||||
|
@ -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,20 +70,14 @@ 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);
|
||||
|
||||
// pk_SStream__write_cstr(&ss, " File \"");
|
||||
// pk_SStream__write_Str(&ss, &self->filename);
|
||||
// pk_SStream__write_cstr(&ss, "\", line ");
|
||||
// pk_SStream__write_int(&ss, 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 ");
|
||||
|
@ -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,113 @@ 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 'q': {
|
||||
const char* s = va_arg(args, const char*);
|
||||
py_Str tmp, tmp2;
|
||||
py_Str__ctor(&tmp, s);
|
||||
tmp2 = py_Str__escape(&tmp, '\'');
|
||||
pk_SStream__write_Str(ss, &tmp2);
|
||||
py_Str__dtor(&tmp);
|
||||
py_Str__dtor(&tmp2);
|
||||
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;
|
||||
}
|
||||
|
@ -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');
|
||||
|
@ -51,6 +51,13 @@ const char* py_tostrn(const py_Ref self, int* size){
|
||||
return py_Str__data(ud);
|
||||
}
|
||||
|
||||
const unsigned char* py_tobytes(const py_Ref self, int* size){
|
||||
assert(self->type == tp_bytes);
|
||||
int* ud = PyObject__value(self->_obj);
|
||||
*size = *ud;
|
||||
return (unsigned char*)(ud + 1);
|
||||
}
|
||||
|
||||
void* py_touserdata(const py_Ref self){
|
||||
assert(self && self->is_ptr);
|
||||
return PyObject__value(self->_obj);
|
||||
|
@ -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));
|
||||
@ -94,4 +100,4 @@ bool py_callmagic(py_Name name, int argc, py_Ref argv) {
|
||||
if(!tmp) return TypeError(name);
|
||||
if(tmp->type == tp_nativefunc) return tmp->_cfunc(argc, argv);
|
||||
return py_call(tmp, argc, argv);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user