Add support for iterators
This commit is contained in:
parent
1d3368861b
commit
0f508c38dc
83
compiler.c
83
compiler.c
@ -443,6 +443,18 @@ static void block(int indentation) {
|
|||||||
declaration();
|
declaration();
|
||||||
if (check(TOKEN_EOL)) endOfLine();
|
if (check(TOKEN_EOL)) endOfLine();
|
||||||
} while (check(TOKEN_INDENTATION));
|
} while (check(TOKEN_INDENTATION));
|
||||||
|
#ifdef ENABLE_DEBUGGING
|
||||||
|
if (vm.enableDebugging) {
|
||||||
|
fprintf(stderr, "On line %d, ", (int)parser.current.line);
|
||||||
|
if (check(TOKEN_INDENTATION)) {
|
||||||
|
fprintf(stderr, "Exiting block from %d to %d\n",
|
||||||
|
(int)currentIndentation, (int)parser.current.length);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Exiting block from %d to something that isn't indentation.\n",
|
||||||
|
(int)currentIndentation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
errorAtCurrent("Expected indentation for block");
|
errorAtCurrent("Expected indentation for block");
|
||||||
}
|
}
|
||||||
@ -691,26 +703,71 @@ static void forStatement() {
|
|||||||
/* For now this is going to be kinda broken */
|
/* For now this is going to be kinda broken */
|
||||||
beginScope();
|
beginScope();
|
||||||
|
|
||||||
/* actually should be `for NAME in ITERABLE` ... */
|
ssize_t loopInd = current->localCount;
|
||||||
varDeclaration();
|
varDeclaration();
|
||||||
|
|
||||||
consume(TOKEN_COMMA,"expect ,");
|
int loopStart;
|
||||||
|
int exitJump;
|
||||||
|
|
||||||
int loopStart = currentChunk()->count;
|
if (match(TOKEN_IN)) {
|
||||||
expression(); /* condition */
|
defineVariable(loopInd);
|
||||||
int exitJump = emitJump(OP_JUMP_IF_FALSE);
|
|
||||||
emitByte(OP_POP);
|
|
||||||
|
|
||||||
if (check(TOKEN_COMMA)) {
|
KrkToken _it = syntheticToken("__loop_iter");
|
||||||
advance();
|
KrkToken _iter = syntheticToken("__iter__");
|
||||||
int bodyJump = emitJump(OP_JUMP);
|
size_t indLoopIter, indIterCall;
|
||||||
int incrementStart = currentChunk()->count;
|
|
||||||
|
/* __loop_iter = */
|
||||||
|
indLoopIter = current->localCount;
|
||||||
|
addLocal(_it);
|
||||||
|
defineVariable(indLoopIter);
|
||||||
|
|
||||||
|
/* ITERABLE.__iter__() */
|
||||||
expression();
|
expression();
|
||||||
|
ssize_t ind = identifierConstant(&_iter);
|
||||||
|
EMIT_CONSTANT_OP(OP_GET_PROPERTY, ind);
|
||||||
|
emitBytes(OP_CALL, 0);
|
||||||
|
|
||||||
|
/* assign */
|
||||||
|
EMIT_CONSTANT_OP(OP_SET_LOCAL, indLoopIter);
|
||||||
|
|
||||||
|
/* LOOP STARTS HERE */
|
||||||
|
loopStart = currentChunk()->count;
|
||||||
|
emitByte(0xFF);
|
||||||
|
|
||||||
|
/* Call the iterator */
|
||||||
|
EMIT_CONSTANT_OP(OP_GET_LOCAL, indLoopIter);
|
||||||
|
emitBytes(OP_CALL, 0);
|
||||||
|
|
||||||
|
/* Assign the result to our loop index */
|
||||||
|
EMIT_CONSTANT_OP(OP_SET_LOCAL, loopInd);
|
||||||
|
|
||||||
|
/* Get the loop iterator again */
|
||||||
|
EMIT_CONSTANT_OP(OP_GET_LOCAL, indLoopIter);
|
||||||
|
emitByte(OP_EQUAL);
|
||||||
|
emitByte(OP_NOT);
|
||||||
|
exitJump = emitJump(OP_JUMP_IF_FALSE);
|
||||||
emitByte(OP_POP);
|
emitByte(OP_POP);
|
||||||
|
|
||||||
emitLoop(loopStart);
|
} else {
|
||||||
loopStart = incrementStart;
|
consume(TOKEN_COMMA,"expect ,");
|
||||||
patchJump(bodyJump);
|
loopStart = currentChunk()->count;
|
||||||
|
|
||||||
|
|
||||||
|
expression(); /* condition */
|
||||||
|
exitJump = emitJump(OP_JUMP_IF_FALSE);
|
||||||
|
emitByte(OP_POP);
|
||||||
|
|
||||||
|
if (check(TOKEN_COMMA)) {
|
||||||
|
advance();
|
||||||
|
int bodyJump = emitJump(OP_JUMP);
|
||||||
|
int incrementStart = currentChunk()->count;
|
||||||
|
expression();
|
||||||
|
emitByte(OP_POP);
|
||||||
|
|
||||||
|
emitLoop(loopStart);
|
||||||
|
loopStart = incrementStart;
|
||||||
|
patchJump(bodyJump);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
consume(TOKEN_COLON,"expect :");
|
consume(TOKEN_COLON,"expect :");
|
||||||
|
4
rline.c
4
rline.c
@ -749,12 +749,12 @@ int syn_py_calculate(struct syntax_state * state) {
|
|||||||
case 0:
|
case 0:
|
||||||
if (charat() == '#') {
|
if (charat() == '#') {
|
||||||
paint_comment(state);
|
paint_comment(state);
|
||||||
} else if (state->i == 0 && match_and_paint(state, "import", FLAG_PRAGMA, c_keyword_qualifier)) {
|
#if 0
|
||||||
return 0;
|
|
||||||
} else if (charat() == '@') {
|
} else if (charat() == '@') {
|
||||||
paint(1, FLAG_PRAGMA);
|
paint(1, FLAG_PRAGMA);
|
||||||
while (c_keyword_qualifier(charat())) paint(1, FLAG_PRAGMA);
|
while (c_keyword_qualifier(charat())) paint(1, FLAG_PRAGMA);
|
||||||
return 0;
|
return 0;
|
||||||
|
#endif
|
||||||
} else if (charat() == '"') {
|
} else if (charat() == '"') {
|
||||||
if (nextchar() == '"' && charrel(2) == '"') {
|
if (nextchar() == '"' && charrel(2) == '"') {
|
||||||
paint(3, FLAG_STRING);
|
paint(3, FLAG_STRING);
|
||||||
|
33
system.krk
33
system.krk
@ -36,11 +36,44 @@ class List:
|
|||||||
base = base + ", "
|
base = base + ", "
|
||||||
base = base + self._get(self._list,i)
|
base = base + self._get(self._list,i)
|
||||||
return base + "]"
|
return base + "]"
|
||||||
|
def __iter__(self):
|
||||||
|
let me = self
|
||||||
|
def makeIter(ind):
|
||||||
|
let l = me
|
||||||
|
let len = l.length()
|
||||||
|
let i = ind
|
||||||
|
def iter():
|
||||||
|
if i >= len:
|
||||||
|
return iter
|
||||||
|
let out = l[i]
|
||||||
|
i = i + 1
|
||||||
|
return out
|
||||||
|
return iter
|
||||||
|
return makeIter(0)
|
||||||
|
|
||||||
|
class Range:
|
||||||
|
def __init__(self, min, max):
|
||||||
|
self.min = min
|
||||||
|
self.max = max
|
||||||
|
def __iter__(self):
|
||||||
|
let me = self
|
||||||
|
def makeIter(ind):
|
||||||
|
let l = me
|
||||||
|
let i = ind
|
||||||
|
def iter():
|
||||||
|
if i >= l.max:
|
||||||
|
return iter
|
||||||
|
let out = i
|
||||||
|
i = i + 1
|
||||||
|
return out
|
||||||
|
return iter
|
||||||
|
return makeIter(self.min)
|
||||||
|
|
||||||
let module = SystemModule()
|
let module = SystemModule()
|
||||||
module.sleep = __krk_builtin_sleep
|
module.sleep = __krk_builtin_sleep
|
||||||
|
|
||||||
module.HashMap = HashMap
|
module.HashMap = HashMap
|
||||||
module.List = List
|
module.List = List
|
||||||
|
module.Range = Range
|
||||||
|
|
||||||
return module
|
return module
|
||||||
|
13
testList.krk
Normal file
13
testList.krk
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import system
|
||||||
|
|
||||||
|
let l = system.List()
|
||||||
|
|
||||||
|
l.append(1)
|
||||||
|
l.append(2)
|
||||||
|
l.append("string")
|
||||||
|
l.append(3.14159)
|
||||||
|
|
||||||
|
for v in l:
|
||||||
|
print v
|
||||||
|
|
||||||
|
return 0
|
4
value.c
4
value.c
@ -49,7 +49,9 @@ int krk_valuesEqual(KrkValue a, KrkValue b) {
|
|||||||
case VAL_FLOATING: return AS_FLOATING(a) == AS_FLOATING(b);
|
case VAL_FLOATING: return AS_FLOATING(a) == AS_FLOATING(b);
|
||||||
case VAL_OBJECT: {
|
case VAL_OBJECT: {
|
||||||
if (IS_STRING(a) && IS_STRING(b)) return AS_OBJECT(a) == AS_OBJECT(b);
|
if (IS_STRING(a) && IS_STRING(b)) return AS_OBJECT(a) == AS_OBJECT(b);
|
||||||
/* otherwise we need to do... fun stuff (push, call compare, etc.)*/
|
/* If their pointers are equal, assume they are always equivalent */
|
||||||
|
if (AS_OBJECT(a) == AS_OBJECT(b)) return 1;
|
||||||
|
/* TODO: __eq__ */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
default: return 0;
|
default: return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user