do something more straightforward and useful for methods on non-objects

This commit is contained in:
K. Lange 2021-01-01 16:01:58 +09:00
parent 8e5ace5112
commit ae2e2be15d
11 changed files with 612 additions and 540 deletions

View File

@ -16,13 +16,14 @@ class list():
for v in i:
self.append(v)
return self.__len__()
def __repr__(self): return self.__str__()
def __str__(self):
let b="["
let l=self.__len__()
for i=0,i<l,i=i+1:
if i>0:
b+=", "
b=b+__builtins__.list_get(self._list,i)
b+=repr(__builtins__.list_get(self._list,i))
return b+"]"
def __iter__(self):
let m = self
@ -47,6 +48,7 @@ class dict():
return __builtins__.hash_get(self._map, ind)
def __set__(self, ind, val):
return __builtins__.hash_set(self._map, ind, val)
def __repr__(self): return self.__str__()
def __str__(self):
let out = "{"
let first = True
@ -54,7 +56,7 @@ class dict():
if not first:
out += ", "
first = False
out = out + v + ": " + self[v]
out += repr(v) + ": " + repr(self[v])
out += "}"
return out
def __len__(self):
@ -105,9 +107,11 @@ class range:
return makeIter(self.min)
def len(obj=None): return (obj and obj.__len__()) or 0
def str(obj=None): return (obj and ("" + obj)) or ""
def str(obj=None): return (obj and obj.__str__()) or ""
def repr(obj): return obj.__repr__()
def int(obj=None): return (obj and obj.__int__()) or 0
def float(obj=None): return (obj and obj.__float__()) or 0.0
def type(obj): return obj.__class__
def dir(obj): return obj.__dir__()
def help(obj=None):
@ -123,7 +127,7 @@ def help(obj=None):
except:
print "No docstring available for", obj
export list,dict,range,len,str,int,float,dir,help
export list,dict,range,len,str,repr,int,float,dir,help
__builtins__.module_paths = ["./","./modules/","/home/klange/Projects/kuroko/modules/","/usr/share/kuroko/"]

View File

@ -13,14 +13,14 @@ void krk_disassembleChunk(KrkChunk * chunk, const char * name) {
#define SIMPLE(opc) case opc: fprintf(stderr, "%s\n", #opc); return offset + 1;
#define CONSTANT(opc,more) case opc: { size_t constant = chunk->code[offset + 1]; \
fprintf(stderr, "%-16s %4d '", #opc, (int)constant); \
krk_printValue(stderr, chunk->constants.values[constant]); \
krk_printValueSafe(stderr, chunk->constants.values[constant]); \
fprintf(stderr,"' (type=%s)\n", krk_typeName(chunk->constants.values[constant])); \
more; \
return offset + 2; } \
case opc ## _LONG: { size_t constant = (chunk->code[offset + 1] << 16) | \
(chunk->code[offset + 2] << 8) | (chunk->code[offset + 3]); \
fprintf(stderr, "%-16s %4d '", #opc "_LONG", (int)constant); \
krk_printValue(stderr, chunk->constants.values[constant]); \
krk_printValueSafe(stderr, chunk->constants.values[constant]); \
fprintf(stderr,"' (type=%s)\n", krk_typeName(chunk->constants.values[constant])); \
more; \
return offset + 4; }
@ -81,6 +81,7 @@ size_t krk_disassembleInstruction(KrkChunk * chunk, size_t offset) {
SIMPLE(OP_BITAND)
SIMPLE(OP_SHIFTLEFT)
SIMPLE(OP_SHIFTRIGHT)
SIMPLE(OP_BITNEGATE)
OPERANDB(OP_DUP)
OPERANDB(OP_SWAP)
CONSTANT(OP_DEFINE_GLOBAL,(void)0)

View File

@ -61,52 +61,6 @@ KrkString * krk_copyString(const char * chars, size_t length) {
return allocateString(heapChars, length, hash);
}
#define NAME(obj) ((obj)->name ? obj->name->chars : "(unnamed)")
void krk_printObject(FILE * f, KrkValue value) {
switch (OBJECT_TYPE(value)) {
case OBJ_STRING:
fprintf(f,"\"");
for (char * c = AS_CSTRING(value); *c; ++c) {
switch (*c) {
/* XXX: Other non-printables should probably be escaped as well. */
case '\n': fprintf(f,"\\n"); break;
case '\r': fprintf(f,"\\r"); break;
case '\t': fprintf(f,"\\t"); break;
case '"': fprintf(f,"\\\""); break;
case '\033': fprintf(f,"\\["); break;
default: fprintf(f,"%c",*c); break;
}
}
fprintf(f,"\"");
break;
case OBJ_FUNCTION:
if (AS_FUNCTION(value)->name == NULL) fprintf(f, "<module>");
else fprintf(f, "<def %s>", NAME(AS_FUNCTION(value)));
break;
case OBJ_NATIVE:
fprintf(f, "<native bind>");
break;
case OBJ_CLOSURE:
fprintf(f, "<closure <def %s>>", NAME(AS_CLOSURE(value)->function));
break;
case OBJ_UPVALUE:
fprintf(f, "<upvalue>");
break;
case OBJ_CLASS:
fprintf(f, "<class %s>", NAME(AS_CLASS(value)));
break;
case OBJ_INSTANCE:
fprintf(f, "<instance of %s>", NAME(AS_INSTANCE(value)->_class));
break;
case OBJ_BOUND_METHOD:
fprintf(f, "<bound <def %s>>", (AS_BOUND_METHOD(value)->method->type == OBJ_CLOSURE) ?
NAME(((KrkClosure*)AS_BOUND_METHOD(value)->method)->function) : (
(AS_BOUND_METHOD(value)->method->type == OBJ_NATIVE) ? "<native>" : "<unknown>"
));
break;
}
}
KrkFunction * krk_newFunction() {
KrkFunction * function = ALLOCATE_OBJECT(KrkFunction, OBJ_FUNCTION);
function->requiredArgs = 0;
@ -118,10 +72,11 @@ KrkFunction * krk_newFunction() {
return function;
}
KrkNative * krk_newNative(NativeFn function) {
KrkNative * krk_newNative(NativeFn function, const char * name, int type) {
KrkNative * native = ALLOCATE_OBJECT(KrkNative, OBJ_NATIVE);
native->function = function;
native->isMethod = 0;
native->isMethod = type;
native->name = name;
return native;
}

View File

@ -97,6 +97,7 @@ typedef KrkValue (*NativeFn)(int argCount, KrkValue* args);
typedef struct {
KrkObj obj;
NativeFn function;
const char * name;
int isMethod;
} KrkNative;
@ -106,9 +107,8 @@ static inline int isObjType(KrkValue value, ObjType type) {
extern KrkString * krk_takeString(char * chars, size_t length);
extern KrkString * krk_copyString(const char * chars, size_t length);
extern void krk_printObject(FILE * f, KrkValue value);
extern KrkFunction * krk_newFunction();
extern KrkNative * krk_newNative(NativeFn function);
extern KrkNative * krk_newNative(NativeFn function, const char * name, int type);
extern KrkClosure * krk_newClosure(KrkFunction * function);
extern KrkUpvalue * krk_newUpvalue(int slot);
extern KrkClass * krk_newClass(KrkString * name);

View File

@ -540,9 +540,9 @@ char * syn_krk_keywords[] = {
char * syn_krk_types[] = {
/* built-in functions */
"self", "super", /* implicit in a class method */
"len", "str", "int", "float", "dir", /* global functions from __builtins__ */
"len", "str", "int", "float", "dir", "repr", /* global functions from __builtins__ */
"list","dict","range", /* builtin classes */
"object","exception","isinstance",
"object","exception","isinstance","type",
NULL
};

View File

@ -41,7 +41,17 @@ KrkValue krk_open(int argc, KrkValue argv[]) {
return NONE_VAL();
}
FILE * file = fopen(AS_CSTRING(argv[0]), AS_CSTRING(argv[1]));
KrkValue arg;
if (argc == 1) {
arg = OBJECT_VAL(S("r"));
krk_push(arg);
} else {
arg = argv[1];
krk_push(argv[1]);
}
FILE * file = fopen(AS_CSTRING(argv[0]), AS_CSTRING(arg));
if (!file) {
krk_runtimeError(vm.exceptions.ioError, "open: failed to open file; system returned: %s", strerror(errno));
return NONE_VAL();
@ -53,14 +63,28 @@ KrkValue krk_open(int argc, KrkValue argv[]) {
/* Let's put the filename in there somewhere... */
krk_attachNamedValue(&fileObject->fields, "filename", argv[0]);
krk_attachNamedValue(&fileObject->fields, "modestr", arg);
krk_attachNamedValue(&fileObject->fields, "_fileptr", INTEGER_VAL((long)(file))); /* Need a KrkNativePrivate or something... */
krk_pop();
krk_pop();
return OBJECT_VAL(fileObject);
}
#define BLOCK_SIZE 1024
static KrkValue krk_file_str(int argc, KrkValue argv[]) {
KrkInstance * fileObj = AS_INSTANCE(argv[0]);
KrkValue filename, modestr;
krk_tableGet(&fileObj->fields, OBJECT_VAL(S("filename")), &filename);
krk_tableGet(&fileObj->fields, OBJECT_VAL(S("modestr")), &modestr);
char * tmp = malloc(AS_STRING(filename)->length + AS_STRING(modestr)->length + 100); /* safety */
sprintf(tmp, "<open file '%s', mode '%s' at %p>", AS_CSTRING(filename), AS_CSTRING(modestr), (void*)fileObj);
KrkString * out = krk_copyString(tmp, strlen(tmp));
free(tmp);
return OBJECT_VAL(out);
}
static FILE * getFilePtr(KrkValue obj) {
KrkValue strFilePtr = OBJECT_VAL(S("_fileptr"));
krk_push(strFilePtr);
@ -243,6 +267,7 @@ KrkValue krk_module_onload_fileio(void) {
krk_defineNative(&FileClass->methods, ".close", krk_file_close);
krk_defineNative(&FileClass->methods, ".write", krk_file_write);
krk_defineNative(&FileClass->methods, ".flush", krk_file_flush);
krk_defineNative(&FileClass->methods, ".__str__", krk_file_str);
krk_defineNative(&FileClass->methods, ".__init__", krk_file_reject_init);
/* Make an instance for stdout, stderr, and stdin */

View File

@ -0,0 +1,4 @@
let x = 1
while x < 1000000:
print x
x++

56
value.c
View File

@ -2,6 +2,7 @@
#include "memory.h"
#include "value.h"
#include "object.h"
#include "vm.h"
void krk_initValueArray(KrkValueArray * array) {
array->values = NULL;
@ -25,19 +26,48 @@ void krk_freeValueArray(KrkValueArray * array) {
krk_initValueArray(array);
}
void krk_printValue(FILE * f, KrkValue value) {
if (IS_FLOATING(value)) {
fprintf(f, "%g", AS_FLOATING(value));
} else if (IS_INTEGER(value)) {
fprintf(f, "%ld", (long)AS_INTEGER(value));
} else if (IS_BOOLEAN(value)) {
fprintf(f, "%s", AS_BOOLEAN(value) ? "True" : "False");
} else if (IS_NONE(value)) {
fprintf(f, "None");
} else if (IS_HANDLER(value)) {
fprintf(f, "{try->%ld}", AS_HANDLER(value));
} else if (IS_OBJECT(value)) {
krk_printObject(f, value);
void krk_printValue(FILE * f, KrkValue printable) {
if (!IS_OBJECT(printable)) {
switch (printable.type) {
case VAL_INTEGER: fprintf(f, "%ld", AS_INTEGER(printable)); break;
case VAL_BOOLEAN: fprintf(f, "%s", AS_BOOLEAN(printable) ? "True" : "False"); break;
case VAL_FLOATING: fprintf(f, "%g", AS_FLOATING(printable)); break;
case VAL_NONE: fprintf(f, "None"); break;
case VAL_HANDLER: fprintf(f, "{try->%ld}", AS_HANDLER(printable)); break;
default: break;
}
return;
}
krk_push(printable);
if (krk_bindMethod(AS_CLASS(krk_typeOf(1,(KrkValue[]){printable})), AS_STRING(vm.specialMethodNames[METHOD_REPR]))) {
switch (krk_callValue(krk_peek(0), 0)) {
case 2: printable = krk_pop(); break;
case 1: printable = krk_runNext(); break;
default: fprintf(f, "[unable to print object at address %p]", (void*)AS_OBJECT(printable)); return;
}
fprintf(f, "%s", AS_CSTRING(printable));
} else {
krk_pop();
fprintf(f, "%s", krk_typeName(printable));
}
}
void krk_printValueSafe(FILE * f, KrkValue printable) {
if (!IS_OBJECT(printable)) {
krk_printValue(f,printable);
} else if (IS_STRING(printable)) {
fprintf(f, "\"%s\"", AS_CSTRING(printable));
} else {
switch (AS_OBJECT(printable)->type) {
case OBJ_CLASS: fprintf(f, "<class %s>", AS_CLASS(printable)->name->chars); break;
case OBJ_INSTANCE: fprintf(f, "<instance of %s>", AS_INSTANCE(printable)->_class->name->chars); break;
case OBJ_NATIVE: fprintf(f, "<nativefn %s>", ((KrkNative*)AS_OBJECT(printable))->name); break;
case OBJ_CLOSURE: fprintf(f, "<function %s>", AS_CLOSURE(printable)->function->name->chars); break;
case OBJ_BOUND_METHOD: fprintf(f, "<method %s>",
AS_BOUND_METHOD(printable)->method->type == OBJ_CLOSURE ? ((KrkClosure*)AS_BOUND_METHOD(printable)->method)->function->name->chars :
((KrkNative*)AS_BOUND_METHOD(printable)->method)->name); break;
default: fprintf(f, "<%s>", krk_typeName(printable)); break;
}
}
}

View File

@ -57,5 +57,6 @@ extern void krk_initValueArray(KrkValueArray * array);
extern void krk_writeValueArray(KrkValueArray * array, KrkValue value);
extern void krk_freeValueArray(KrkValueArray * array);
extern void krk_printValue(FILE * f, KrkValue value);
extern void krk_printValueSafe(FILE * f, KrkValue value);
extern int krk_valuesEqual(KrkValue a, KrkValue b);

983
vm.c

File diff suppressed because it is too large Load Diff

5
vm.h
View File

@ -19,6 +19,7 @@ typedef struct {
typedef enum {
METHOD_INIT,
METHOD_STR,
METHOD_REPR,
METHOD_GET,
METHOD_SET,
METHOD_CLASS,
@ -101,6 +102,7 @@ extern KrkValue krk_interpret(const char * src, int newScope, char *, char *);
extern KrkValue krk_runfile(const char * fileName, int newScope, char *, char *);
extern void krk_push(KrkValue value);
extern KrkValue krk_pop(void);
extern KrkValue krk_peek(int distance);
extern const char * krk_typeName(KrkValue value);
extern void krk_defineNative(KrkTable * table, const char * name, NativeFn function);
extern void krk_attachNamedObject(KrkTable * table, const char name[], KrkObj * obj);
@ -114,3 +116,6 @@ extern KrkValue krk_dictGet(KrkValue dictClass, KrkInstance * dict, KrkValue key
extern void krk_dictSet(KrkValue dictClass, KrkInstance * dict, KrkValue key, KrkValue value);
extern KrkInstance * krk_dictCreate(KrkValue * outClass);
extern KrkValue krk_runNext(void);
extern KrkValue krk_typeOf(int argc, KrkValue argv[]);
extern int krk_bindMethod(KrkClass * _class, KrkString * name);
extern int krk_callValue(KrkValue callee, int argCount);