Expose basic operators and add more builtins, list functions
This commit is contained in:
parent
4d05ca218c
commit
930b599e82
@ -426,10 +426,6 @@ void _createAndBind_builtins(void) {
|
||||
krk_finalizeClass(LicenseReader);
|
||||
krk_attachNamedObject(&vm.builtins->fields, "license", (KrkObj*)krk_newInstance(LicenseReader));
|
||||
|
||||
BUILTIN_FUNCTION("listOf", krk_list_of, "Convert argument sequence to list object.");
|
||||
BUILTIN_FUNCTION("dictOf", krk_dict_of, "Convert argument sequence to dict object.");
|
||||
BUILTIN_FUNCTION("tupleOf",krk_tuple_of,"Convert argument sequence to tuple object.");
|
||||
|
||||
BUILTIN_FUNCTION("isinstance", _isinstance, "Determine if an object is an instance of the given class or one if its subclasses.");
|
||||
BUILTIN_FUNCTION("globals", _globals, "Return a mapping of names in the current global namespace.");
|
||||
BUILTIN_FUNCTION("dir", _dir, "Return a list of known property names for a given object.");
|
||||
|
@ -335,6 +335,8 @@ void _createAndBind_dictClass(void) {
|
||||
krk_finalizeClass(dict);
|
||||
dict->docstring = S("Mapping of arbitrary keys to values.");
|
||||
|
||||
BUILTIN_FUNCTION("dictOf", krk_dict_of, "Convert argument sequence to dict object.");
|
||||
|
||||
KrkClass * dictitems = ADD_BASE_CLASS(vm.baseClasses.dictitemsClass, "dictitems", vm.objectClass);
|
||||
dictitems->allocSize = sizeof(struct DictItems);
|
||||
dictitems->_ongcscan = _dictitems_gcscan;
|
||||
|
116
src/obj_list.c
116
src/obj_list.c
@ -8,6 +8,11 @@
|
||||
if (index < 0) index += self->values.count; \
|
||||
if (index < 0 || index >= (krk_integer_type)self->values.count) return krk_runtimeError(vm.exceptions.indexError, "list index out of range: " PRIkrk_int, index)
|
||||
|
||||
#define LIST_WRAP_SOFT(val) \
|
||||
if (val < 0) val += self->values.count; \
|
||||
if (val < 0) val = 0; \
|
||||
if (val > (krk_integer_type)self->values.count) val = self->values.count
|
||||
|
||||
static void _list_gcscan(KrkInstance * self) {
|
||||
for (size_t i = 0; i < ((KrkList*)self)->values.count; ++i) {
|
||||
krk_markValue(((KrkList*)self)->values.values[i]);
|
||||
@ -227,6 +232,95 @@ KRK_METHOD(list,pop,{
|
||||
}
|
||||
})
|
||||
|
||||
KRK_METHOD(list,remove,{
|
||||
METHOD_TAKES_EXACTLY(1);
|
||||
for (size_t i = 0; i < self->values.count; ++i) {
|
||||
if (krk_valuesEqual(self->values.values[i], argv[1])) {
|
||||
return FUNC_NAME(list,pop)(2,(KrkValue[]){argv[0], INTEGER_VAL(i)},0);
|
||||
}
|
||||
}
|
||||
return krk_runtimeError(vm.exceptions.valueError, "not found");
|
||||
})
|
||||
|
||||
KRK_METHOD(list,clear,{
|
||||
METHOD_TAKES_NONE();
|
||||
krk_freeValueArray(&self->values);
|
||||
})
|
||||
|
||||
KRK_METHOD(list,index,{
|
||||
METHOD_TAKES_AT_LEAST(1);
|
||||
METHOD_TAKES_AT_MOST(3);
|
||||
|
||||
krk_integer_type min = 0;
|
||||
krk_integer_type max = self->values.count;
|
||||
|
||||
if (argc > 2) {
|
||||
if (IS_INTEGER(argv[2]))
|
||||
min = AS_INTEGER(argv[2]);
|
||||
else
|
||||
return krk_runtimeError(vm.exceptions.typeError, "min must be int, not '%s'", krk_typeName(argv[2]));
|
||||
}
|
||||
|
||||
if (argc > 3) {
|
||||
if (IS_INTEGER(argv[3]))
|
||||
max = AS_INTEGER(argv[3]);
|
||||
else
|
||||
return krk_runtimeError(vm.exceptions.typeError, "max must be int, not '%s'", krk_typeName(argv[3]));
|
||||
}
|
||||
|
||||
LIST_WRAP_SOFT(min);
|
||||
LIST_WRAP_SOFT(max);
|
||||
|
||||
for (krk_integer_type i = min; i < max; ++i) {
|
||||
if (krk_valuesEqual(self->values.values[i], argv[1])) return INTEGER_VAL(i);
|
||||
}
|
||||
|
||||
return krk_runtimeError(vm.exceptions.valueError, "not found");
|
||||
})
|
||||
|
||||
KRK_METHOD(list,count,{
|
||||
METHOD_TAKES_EXACTLY(1);
|
||||
krk_integer_type count = 0;
|
||||
|
||||
for (size_t i = 0; i < self->values.count; ++i) {
|
||||
if (krk_valuesEqual(self->values.values[i], argv[1])) count++;
|
||||
}
|
||||
|
||||
return INTEGER_VAL(count);
|
||||
})
|
||||
|
||||
KRK_METHOD(list,copy,{
|
||||
METHOD_TAKES_NONE();
|
||||
return krk_list_of(self->values.count, self->values.values);
|
||||
})
|
||||
|
||||
KRK_METHOD(list,reverse,{
|
||||
METHOD_TAKES_NONE();
|
||||
for (size_t i = 0; i < (self->values.count) / 2; i++) {
|
||||
KrkValue tmp = self->values.values[i];
|
||||
self->values.values[i] = self->values.values[self->values.count-i-1];
|
||||
self->values.values[self->values.count-i-1] = tmp;
|
||||
}
|
||||
return NONE_VAL();
|
||||
})
|
||||
|
||||
static int _list_sorter(const void * _a, const void * _b) {
|
||||
KrkValue a = *(KrkValue*)_a;
|
||||
KrkValue b = *(KrkValue*)_b;
|
||||
|
||||
KrkValue ltComp = krk_operator_lt(a,b);
|
||||
if (IS_NONE(ltComp) || (IS_BOOLEAN(ltComp) && AS_BOOLEAN(ltComp))) return -1;
|
||||
KrkValue gtComp = krk_operator_gt(a,b);
|
||||
if (IS_NONE(gtComp) || (IS_BOOLEAN(gtComp) && AS_BOOLEAN(gtComp))) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
KRK_METHOD(list,sort,{
|
||||
METHOD_TAKES_NONE();
|
||||
|
||||
qsort(self->values.values, self->values.count, sizeof(KrkValue), _list_sorter);
|
||||
})
|
||||
|
||||
FUNC_SIG(listiterator,__init__);
|
||||
|
||||
KRK_METHOD(list,__iter__,{
|
||||
@ -280,6 +374,18 @@ _corrupt:
|
||||
return krk_runtimeError(vm.exceptions.typeError, "Corrupt list iterator: %s", errorStr);
|
||||
})
|
||||
|
||||
|
||||
static KrkValue _sorted(int argc, KrkValue argv[], int hasKw) {
|
||||
if (argc != 1) return krk_runtimeError(vm.exceptions.argumentError,"%s() takes %s %d argument%s (%d given)","sorted","exactly",1,argc);
|
||||
KrkValue listOut = krk_list_of(0,NULL);
|
||||
krk_push(listOut);
|
||||
FUNC_NAME(list,extend)(2,(KrkValue[]){listOut,argv[0]},0);
|
||||
if (!IS_NONE(vm.currentException)) return NONE_VAL();
|
||||
FUNC_NAME(list,sort)(1,&listOut,0);
|
||||
if (!IS_NONE(vm.currentException)) return NONE_VAL();
|
||||
return krk_pop();
|
||||
}
|
||||
|
||||
_noexport
|
||||
void _createAndBind_listClass(void) {
|
||||
KrkClass * list = ADD_BASE_CLASS(vm.baseClasses.listClass, "list", vm.objectClass);
|
||||
@ -299,11 +405,21 @@ void _createAndBind_listClass(void) {
|
||||
BIND_METHOD(list,extend);
|
||||
BIND_METHOD(list,pop);
|
||||
BIND_METHOD(list,insert);
|
||||
BIND_METHOD(list,clear);
|
||||
BIND_METHOD(list,index);
|
||||
BIND_METHOD(list,count);
|
||||
BIND_METHOD(list,copy);
|
||||
BIND_METHOD(list,remove);
|
||||
BIND_METHOD(list,reverse);
|
||||
BIND_METHOD(list,sort);
|
||||
krk_defineNative(&list->methods, ".__delitem__", FUNC_NAME(list,pop));
|
||||
krk_defineNative(&list->methods, ".__str__", FUNC_NAME(list,__repr__));
|
||||
krk_finalizeClass(list);
|
||||
list->docstring = S("Mutable sequence of arbitrary values.");
|
||||
|
||||
BUILTIN_FUNCTION("listOf", krk_list_of, "Convert argument sequence to list object.");
|
||||
BUILTIN_FUNCTION("sorted", _sorted, "Return a sorted representation of an iterable.");
|
||||
|
||||
KrkClass * listiterator = ADD_BASE_CLASS(vm.baseClasses.listiteratorClass, "listiterator", vm.objectClass);
|
||||
BIND_METHOD(listiterator,__init__);
|
||||
BIND_METHOD(listiterator,__call__);
|
||||
|
@ -446,6 +446,7 @@ KRK_METHOD(str,__lt__,{
|
||||
if (!IS_STRING(argv[1])) {
|
||||
return KWARGS_VAL(0); /* represents 'not implemented' */
|
||||
}
|
||||
if (AS_STRING(argv[0]) == AS_STRING(argv[1])) return BOOLEAN_VAL(0);
|
||||
|
||||
size_t aLen = AS_STRING(argv[0])->length;
|
||||
size_t bLen = AS_STRING(argv[1])->length;
|
||||
@ -465,6 +466,7 @@ KRK_METHOD(str,__gt__,{
|
||||
if (!IS_STRING(argv[1])) {
|
||||
return KWARGS_VAL(0); /* represents 'not implemented' */
|
||||
}
|
||||
if (AS_STRING(argv[0]) == AS_STRING(argv[1])) return BOOLEAN_VAL(0);
|
||||
|
||||
size_t aLen = AS_STRING(argv[0])->length;
|
||||
size_t bLen = AS_STRING(argv[1])->length;
|
||||
|
@ -141,6 +141,8 @@ void _createAndBind_tupleClass(void) {
|
||||
krk_defineNative(&vm.baseClasses.tupleClass->methods, ".__eq__", _tuple_eq);
|
||||
krk_finalizeClass(vm.baseClasses.tupleClass);
|
||||
|
||||
BUILTIN_FUNCTION("tupleOf",krk_tuple_of,"Convert argument sequence to tuple object.");
|
||||
|
||||
ADD_BASE_CLASS(vm.baseClasses.tupleiteratorClass, "tupleiterator", vm.objectClass);
|
||||
vm.baseClasses.tupleiteratorClass->allocSize = sizeof(struct TupleIter);
|
||||
vm.baseClasses.tupleiteratorClass->_ongcscan = _tuple_iter_gcscan;
|
||||
|
@ -554,6 +554,7 @@ char * syn_krk_types[] = {
|
||||
"list","dict","range", /* builtin classes */
|
||||
"object","exception","isinstance","type","tuple",
|
||||
"print","set","any","all","bool","ord","chr","hex",
|
||||
"sorted","bytes",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
12
src/vm.c
12
src/vm.c
@ -1199,7 +1199,7 @@ static KrkValue tryBind(const char * name, KrkValue a, KrkValue b, const char *
|
||||
*/
|
||||
|
||||
#define MAKE_BIN_OP(name,operator) \
|
||||
static KrkValue operator_ ## name (KrkValue a, KrkValue b) { \
|
||||
KrkValue krk_operator_ ## name (KrkValue a, KrkValue b) { \
|
||||
if (IS_INTEGER(a) && IS_INTEGER(b)) return INTEGER_VAL(AS_INTEGER(a) operator AS_INTEGER(b)); \
|
||||
if (IS_FLOATING(a)) { \
|
||||
if (IS_INTEGER(b)) return FLOATING_VAL(AS_FLOATING(a) operator (double)AS_INTEGER(b)); \
|
||||
@ -1216,7 +1216,7 @@ MAKE_BIN_OP(mul,*)
|
||||
MAKE_BIN_OP(div,/)
|
||||
|
||||
#define MAKE_UNOPTIMIZED_BIN_OP(name,operator) \
|
||||
static KrkValue operator_ ## name (KrkValue a, KrkValue b) { \
|
||||
KrkValue krk_operator_ ## name (KrkValue a, KrkValue b) { \
|
||||
return tryBind("__" #name "__", a, b, "unsupported operand types for " #operator ": '%s' and '%s'"); \
|
||||
}
|
||||
|
||||
@ -1225,7 +1225,7 @@ MAKE_UNOPTIMIZED_BIN_OP(pow,**)
|
||||
/* Bit ops are invalid on doubles in C, so we can't use the same set of macros for them;
|
||||
* they should be invalid in Kuroko as well. */
|
||||
#define MAKE_BIT_OP(name,operator) \
|
||||
static KrkValue operator_ ## name (KrkValue a, KrkValue b) { \
|
||||
KrkValue krk_operator_ ## name (KrkValue a, KrkValue b) { \
|
||||
if (IS_INTEGER(a) && IS_INTEGER(b)) return INTEGER_VAL(AS_INTEGER(a) operator AS_INTEGER(b)); \
|
||||
return tryBind("__" #name "__", a, b, "unsupported operand types for " #operator ": '%s' and '%s'"); \
|
||||
}
|
||||
@ -1238,7 +1238,7 @@ MAKE_BIT_OP(rshift,>>)
|
||||
MAKE_BIT_OP(mod,%) /* not a bit op, but doesn't work on floating point */
|
||||
|
||||
#define MAKE_COMPARATOR(name, operator) \
|
||||
static KrkValue operator_ ## name (KrkValue a, KrkValue b) { \
|
||||
KrkValue krk_operator_ ## name (KrkValue a, KrkValue b) { \
|
||||
if (IS_INTEGER(a) && IS_INTEGER(b)) return BOOLEAN_VAL(AS_INTEGER(a) operator AS_INTEGER(b)); \
|
||||
if (IS_FLOATING(a)) { \
|
||||
if (IS_INTEGER(b)) return BOOLEAN_VAL(AS_FLOATING(a) operator AS_INTEGER(b)); \
|
||||
@ -1636,11 +1636,11 @@ static int valueDelProperty(KrkString * name) {
|
||||
}
|
||||
|
||||
#define READ_BYTE() (*frame->ip++)
|
||||
#define BINARY_OP(op) { KrkValue b = krk_pop(); KrkValue a = krk_pop(); krk_push(operator_ ## op (a,b)); break; }
|
||||
#define BINARY_OP(op) { KrkValue b = krk_pop(); KrkValue a = krk_pop(); krk_push(krk_operator_ ## op (a,b)); break; }
|
||||
#define BINARY_OP_CHECK_ZERO(op) { KrkValue b = krk_pop(); KrkValue a = krk_pop(); \
|
||||
if ((IS_INTEGER(b) && AS_INTEGER(b) == 0)) { krk_runtimeError(vm.exceptions.zeroDivisionError, "integer division or modulo by zero"); goto _finishException; } \
|
||||
else if ((IS_FLOATING(b) && AS_FLOATING(b) == 0.0)) { krk_runtimeError(vm.exceptions.zeroDivisionError, "float division by zero"); goto _finishException; } \
|
||||
krk_push(operator_ ## op (a,b)); break; }
|
||||
krk_push(krk_operator_ ## op (a,b)); break; }
|
||||
#define READ_CONSTANT(s) (frame->closure->function->chunk.constants.values[readBytes(frame,s)])
|
||||
#define READ_STRING(s) AS_STRING(READ_CONSTANT(s))
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user