not exactly how modules work in Python, but, uh, good enough for us for now
This commit is contained in:
parent
0ca0564cd0
commit
1f754ebc01
2
chunk.h
2
chunk.h
@ -58,6 +58,8 @@ typedef enum {
|
||||
OP_GET_PROPERTY_LONG,
|
||||
OP_METHOD,
|
||||
OP_METHOD_LONG,
|
||||
OP_IMPORT,
|
||||
OP_IMPORT_LONG,
|
||||
} KrkOpCode;
|
||||
|
||||
/**
|
||||
|
14
compiler.c
14
compiler.c
@ -657,6 +657,14 @@ static void returnStatement() {
|
||||
}
|
||||
}
|
||||
|
||||
static void importStatement() {
|
||||
consume(TOKEN_IDENTIFIER, "Expected module name");
|
||||
declareVariable();
|
||||
size_t ind = identifierConstant(&parser.previous);
|
||||
EMIT_CONSTANT_OP(OP_IMPORT, ind);
|
||||
defineVariable(ind);
|
||||
}
|
||||
|
||||
static void statement() {
|
||||
if (check(TOKEN_EOL)) {
|
||||
return; /* Meaningless blank line */
|
||||
@ -680,6 +688,8 @@ static void statement() {
|
||||
forStatement();
|
||||
} else if (match(TOKEN_RETURN)) {
|
||||
returnStatement();
|
||||
} else if (match(TOKEN_IMPORT)) {
|
||||
importStatement();
|
||||
} else {
|
||||
expressionStatement();
|
||||
}
|
||||
@ -951,11 +961,13 @@ static ParseRule * getRule(KrkTokenType type) {
|
||||
return &rules[type];
|
||||
}
|
||||
|
||||
KrkFunction * krk_compile(const char * src) {
|
||||
KrkFunction * krk_compile(const char * src, int newScope) {
|
||||
krk_initScanner(src);
|
||||
Compiler compiler;
|
||||
initCompiler(&compiler, TYPE_MODULE);
|
||||
|
||||
if (newScope) beginScope();
|
||||
|
||||
parser.hadError = 0;
|
||||
parser.panicMode = 0;
|
||||
|
||||
|
@ -2,5 +2,5 @@
|
||||
|
||||
#include "object.h"
|
||||
|
||||
extern KrkFunction * krk_compile(const char * src);
|
||||
extern KrkFunction * krk_compile(const char * src, int newScope);
|
||||
extern void krk_markCompilerRoots(void);
|
||||
|
1
debug.c
1
debug.c
@ -80,6 +80,7 @@ size_t krk_disassembleInstruction(KrkChunk * chunk, size_t offset) {
|
||||
CONSTANT(OP_SET_PROPERTY, (void)0)
|
||||
CONSTANT(OP_METHOD, (void)0)
|
||||
CONSTANT(OP_CLOSURE, CLOSURE_MORE)
|
||||
CONSTANT(OP_IMPORT, (void)0)
|
||||
OPERANDL(OP_SET_LOCAL)
|
||||
OPERANDL(OP_GET_LOCAL)
|
||||
OPERANDL(OP_SET_UPVALUE)
|
||||
|
16
kuroko.c
16
kuroko.c
@ -8,21 +8,11 @@
|
||||
int main(int argc, char * argv[]) {
|
||||
krk_initVM();
|
||||
|
||||
FILE * f = fopen("test.krk","r");
|
||||
if (!f) return 1;
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t size = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
char * buf = malloc(size+1);
|
||||
fread(buf, 1, size, f);
|
||||
fclose(f);
|
||||
buf[size] = '\0';
|
||||
|
||||
krk_interpret(buf);
|
||||
KrkValue result = krk_runfile("test.krk",0);
|
||||
|
||||
krk_freeVM();
|
||||
|
||||
free(buf);
|
||||
if (IS_INTEGER(result)) return AS_INTEGER(result);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
11
object.c
11
object.c
@ -61,6 +61,7 @@ KrkString * 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:
|
||||
@ -68,25 +69,25 @@ void krk_printObject(FILE * f, KrkValue value) {
|
||||
break;
|
||||
case OBJ_FUNCTION:
|
||||
if (AS_FUNCTION(value)->name == NULL) fprintf(f, "<module>");
|
||||
else fprintf(f, "<def %s>", AS_FUNCTION(value)->name->chars);
|
||||
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>>", AS_CLOSURE(value)->function->name->chars);
|
||||
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>", AS_CLASS(value)->name->chars);
|
||||
fprintf(f, "<class %s>", NAME(AS_CLASS(value)));
|
||||
break;
|
||||
case OBJ_INSTANCE:
|
||||
fprintf(f, "<instance of %s>", AS_INSTANCE(value)->_class->name->chars);
|
||||
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->function->name->chars);
|
||||
fprintf(f, "<bound <def %s>>", NAME(AS_BOUND_METHOD(value)->method->function));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -183,6 +183,7 @@ static KrkTokenType identifierType() {
|
||||
case 'i': if (MORE(1)) switch (scanner.start[1]) {
|
||||
case 'f': return checkKeyword(2, "", TOKEN_IF);
|
||||
case 'n': return checkKeyword(2, "", TOKEN_IN);
|
||||
case 'm': return checkKeyword(2, "port", TOKEN_IMPORT);
|
||||
} break;
|
||||
case 'l': return checkKeyword(1, "et", TOKEN_LET);
|
||||
case 'n': return checkKeyword(1, "ot", TOKEN_NOT);
|
||||
|
@ -22,6 +22,7 @@ typedef enum {
|
||||
TOKEN_FALSE, /* False */
|
||||
TOKEN_FOR, /* for */
|
||||
TOKEN_IF, /* if */
|
||||
TOKEN_IMPORT,/* import */
|
||||
TOKEN_IN, /* in */
|
||||
TOKEN_LET, /* let */
|
||||
TOKEN_NONE, /* None */
|
||||
|
11
system.krk
Normal file
11
system.krk
Normal file
@ -0,0 +1,11 @@
|
||||
# This is a module
|
||||
class SystemModule:
|
||||
|
||||
let module = SystemModule()
|
||||
module.sleep = __krk_builtin_sleep
|
||||
|
||||
print "You imported the system module."
|
||||
print "It has a module: " + module
|
||||
print "Which has a function: " + module.sleep
|
||||
|
||||
return module
|
5
test.krk
5
test.krk
@ -1,3 +1,4 @@
|
||||
import system
|
||||
# You may want to look at this in an editor with the syntax highlighting
|
||||
# set to Python. Not even bim has a highlighter for Kuroko yet.
|
||||
|
||||
@ -59,10 +60,6 @@ print "The function call returned: " + result
|
||||
# figured something with arguments would be more useful? The purpose of this
|
||||
# language is to be used for writing syntax highlighters, configs, and also
|
||||
# plugins for bim, so native bindings are going to be very important.
|
||||
class SystemModule: # Blank class is supported, and basically makes a struct?
|
||||
let system = SystemModule()
|
||||
system.sleep = __krk_builtin_sleep
|
||||
|
||||
result = system.sleep(0.1)
|
||||
|
||||
print "Call to sleep returned: " + result
|
||||
|
50
vm.c
50
vm.c
@ -363,6 +363,9 @@ static KrkValue run() {
|
||||
return result;
|
||||
}
|
||||
vm.stackTop = frame->slots;
|
||||
if (vm.frameCount == vm.exitOnFrame) {
|
||||
return result;
|
||||
}
|
||||
krk_push(result);
|
||||
frame = &vm.frames[vm.frameCount - 1];
|
||||
break;
|
||||
@ -430,6 +433,25 @@ static KrkValue run() {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OP_IMPORT_LONG:
|
||||
case OP_IMPORT: {
|
||||
KrkString * name = READ_STRING((opcode == OP_IMPORT ? 1 : 3));
|
||||
KrkValue module;
|
||||
if (!krk_tableGet(&vm.modules, OBJECT_VAL(name), &module)) {
|
||||
/* Try to open it */
|
||||
char tmp[256];
|
||||
sprintf(tmp, "%s.krk", name->chars);
|
||||
vm.exitOnFrame = vm.frameCount;
|
||||
module = krk_runfile(tmp,1);
|
||||
vm.exitOnFrame = -1;
|
||||
if (!IS_OBJECT(module)) {
|
||||
runtimeError("Failed to import module - expected to receive an object, but got a %s instead.", typeName(module));
|
||||
}
|
||||
krk_tableSet(&vm.modules, OBJECT_VAL(name), module);
|
||||
}
|
||||
krk_push(module);
|
||||
break;
|
||||
}
|
||||
case OP_GET_LOCAL_LONG:
|
||||
case OP_GET_LOCAL: {
|
||||
uint32_t slot = readBytes(frame, (opcode == OP_GET_LOCAL ? 1 : 3));
|
||||
@ -553,8 +575,8 @@ static KrkValue run() {
|
||||
#undef READ_BYTE
|
||||
}
|
||||
|
||||
int krk_interpret(const char * src) {
|
||||
KrkFunction * function = krk_compile(src);
|
||||
KrkValue krk_interpret(const char * src, int newScope) {
|
||||
KrkFunction * function = krk_compile(src, newScope);
|
||||
|
||||
krk_push(OBJECT_VAL(function));
|
||||
KrkClosure * closure = newClosure(function);
|
||||
@ -563,6 +585,26 @@ int krk_interpret(const char * src) {
|
||||
krk_push(OBJECT_VAL(closure));
|
||||
callValue(OBJECT_VAL(closure), 0);
|
||||
|
||||
KrkValue result = run();
|
||||
return IS_NONE(result);
|
||||
return run();
|
||||
}
|
||||
|
||||
|
||||
KrkValue krk_runfile(const char * fileName, int newScope) {
|
||||
FILE * f = fopen(fileName,"r");
|
||||
if (!f) return NONE_VAL();
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t size = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
char * buf = malloc(size+1);
|
||||
fread(buf, 1, size, f);
|
||||
fclose(f);
|
||||
buf[size] = '\0';
|
||||
|
||||
KrkValue result = krk_interpret(buf, newScope);
|
||||
free(buf);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
5
vm.h
5
vm.h
@ -21,6 +21,7 @@ typedef struct {
|
||||
KrkValue * stackTop;
|
||||
KrkTable globals;
|
||||
KrkTable strings;
|
||||
KrkTable modules;
|
||||
KrkString * __init__;
|
||||
KrkUpvalue * openUpvalues;
|
||||
KrkObj * objects;
|
||||
@ -28,6 +29,7 @@ typedef struct {
|
||||
size_t nextGC;
|
||||
size_t grayCount;
|
||||
size_t grayCapacity;
|
||||
size_t exitOnFrame;
|
||||
KrkObj** grayStack;
|
||||
} KrkVM;
|
||||
|
||||
@ -35,7 +37,8 @@ extern KrkVM vm;
|
||||
|
||||
extern void krk_initVM(void);
|
||||
extern void krk_freeVM(void);
|
||||
extern int krk_interpret(const char * src);
|
||||
extern KrkValue krk_interpret(const char * src, int newScope);
|
||||
extern KrkValue krk_runfile(const char * fileName, int newScope);
|
||||
extern void krk_push(KrkValue value);
|
||||
extern KrkValue krk_pop(void);
|
||||
extern const char * typeName(KrkValue value);
|
||||
|
Loading…
Reference in New Issue
Block a user