mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 14:54:07 +10:00
Finished slice and dot notation, needs a lot of testing
This commit is contained in:
@@ -35,6 +35,8 @@ DONE: A way to check the type of a variable (typeOf keyword)
|
||||
|
||||
|
||||
TODO: slice and dot notation around the builtin _index and _dot functions
|
||||
//TODO: check this const-ness
|
||||
//TODO: add arithmetics
|
||||
|
||||
|
||||
TODO: ternary operator
|
||||
|
||||
@@ -1,8 +1,23 @@
|
||||
var week = ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"];
|
||||
|
||||
week[::-2] = ["first", "second", "third"];
|
||||
|
||||
print week;
|
||||
|
||||
|
||||
var str = "0123456789";
|
||||
|
||||
str[3:5:-2] = "abc";
|
||||
|
||||
print str;
|
||||
|
||||
|
||||
|
||||
str = "Hello world";
|
||||
|
||||
print str; //Hello world
|
||||
print str[::2]; //Hlowrd
|
||||
print str[::-2]; //drwolH
|
||||
|
||||
|
||||
|
||||
{
|
||||
fn f() {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,10 +289,16 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_UNARY:
|
||||
case NODE_UNARY: {
|
||||
//pass to the child node, then embed the unary command (print, negate, etc.)
|
||||
writeCompilerWithJumps(compiler, node->unary.child, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
Opcode override = writeCompilerWithJumps(compiler, node->unary.child, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
|
||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||
}
|
||||
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)node->unary.opcode; //1 byte
|
||||
}
|
||||
break;
|
||||
|
||||
//all infixes come here
|
||||
@@ -322,20 +328,28 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_GROUPING:
|
||||
case NODE_GROUPING: {
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)OP_GROUPING_BEGIN; //1 byte
|
||||
writeCompilerWithJumps(compiler, node->grouping.child, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
Opcode override = writeCompilerWithJumps(compiler, node->grouping.child, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||
}
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)OP_GROUPING_END; //1 byte
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_BLOCK:
|
||||
case NODE_BLOCK: {
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)OP_SCOPE_BEGIN; //1 byte
|
||||
|
||||
for (int i = 0; i < node->block.count; i++) {
|
||||
writeCompilerWithJumps(compiler, &(node->block.nodes[i]), breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
Opcode override = writeCompilerWithJumps(compiler, &(node->block.nodes[i]), breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||
}
|
||||
}
|
||||
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)OP_SCOPE_END; //1 byte
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_COMPOUND: {
|
||||
@@ -364,7 +378,10 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
|
||||
case NODE_VAR_DECL: {
|
||||
//first, embed the expression (leaves it on the stack)
|
||||
writeCompilerWithJumps(compiler, node->varDecl.expression, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
Opcode override = writeCompilerWithJumps(compiler, node->varDecl.expression, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||
}
|
||||
|
||||
//write each piece of the declaration to the bytecode
|
||||
int identifierIndex = findLiteralIndex(&compiler->literalCache, node->varDecl.identifier);
|
||||
@@ -400,7 +417,10 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
initCompiler(fnCompiler);
|
||||
writeCompiler(fnCompiler, node->fnDecl.arguments); //can be empty, but not NULL
|
||||
writeCompiler(fnCompiler, node->fnDecl.returns); //can be empty, but not NULL
|
||||
writeCompilerWithJumps(fnCompiler, node->fnDecl.block, NULL, NULL, -4); //can be empty, but not NULL
|
||||
Opcode override = writeCompilerWithJumps(fnCompiler, node->fnDecl.block, NULL, NULL, -4); //can be empty, but not NULL
|
||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||
}
|
||||
|
||||
//create the function in the literal cache (by storing the compiler object)
|
||||
Literal fnLiteral = TO_FUNCTION_LITERAL(fnCompiler, 0);
|
||||
@@ -450,7 +470,10 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
for (int i = 0; i < node->fnCall.arguments->fnCollection.count; i++) { //reverse order, to count from the beginning in the interpreter
|
||||
//sub-calls
|
||||
if (node->fnCall.arguments->fnCollection.nodes[i].type != NODE_LITERAL) {
|
||||
writeCompilerWithJumps(compiler, &node->fnCall.arguments->fnCollection.nodes[i], breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
Opcode override = writeCompilerWithJumps(compiler, &node->fnCall.arguments->fnCollection.nodes[i], breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -503,7 +526,10 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
|
||||
case NODE_PATH_IF: {
|
||||
//process the condition
|
||||
writeCompilerWithJumps(compiler, node->path.condition, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
Opcode override = writeCompilerWithJumps(compiler, node->path.condition, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||
}
|
||||
|
||||
//cache the point to insert the jump distance at
|
||||
compiler->bytecode[compiler->count++] = OP_IF_FALSE_JUMP; //1 byte
|
||||
@@ -511,7 +537,10 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
compiler->count += sizeof(unsigned short); //2 bytes
|
||||
|
||||
//write the then path
|
||||
writeCompilerWithJumps(compiler, node->path.thenPath, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
override = writeCompilerWithJumps(compiler, node->path.thenPath, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||
}
|
||||
|
||||
int jumpToEnd = 0;
|
||||
|
||||
@@ -527,7 +556,10 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
|
||||
if (node->path.elsePath) {
|
||||
//if there's an else path, write it and
|
||||
writeCompilerWithJumps(compiler, node->path.elsePath, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
Opcode override = writeCompilerWithJumps(compiler, node->path.elsePath, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||
}
|
||||
|
||||
//update the jumpToEnd to point here
|
||||
AS_USHORT(compiler->bytecode[jumpToEnd]) = compiler->count + jumpOffsets; //2 bytes
|
||||
@@ -547,7 +579,10 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
unsigned short jumpToStart = compiler->count;
|
||||
|
||||
//process the condition
|
||||
writeCompilerWithJumps(compiler, node->path.condition, &breakAddresses, &continueAddresses, jumpOffsets);
|
||||
Opcode override = writeCompilerWithJumps(compiler, node->path.condition, &breakAddresses, &continueAddresses, jumpOffsets);
|
||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||
}
|
||||
|
||||
//if false, jump to end
|
||||
compiler->bytecode[compiler->count++] = OP_IF_FALSE_JUMP; //1 byte
|
||||
@@ -555,7 +590,10 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
compiler->count += sizeof(unsigned short); //2 bytes
|
||||
|
||||
//write the body
|
||||
writeCompilerWithJumps(compiler, node->path.thenPath, &breakAddresses, &continueAddresses, jumpOffsets);
|
||||
override = writeCompilerWithJumps(compiler, node->path.thenPath, &breakAddresses, &continueAddresses, jumpOffsets);
|
||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||
}
|
||||
|
||||
//jump to condition
|
||||
compiler->bytecode[compiler->count++] = OP_JUMP; //1 byte
|
||||
@@ -596,11 +634,17 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
compiler->bytecode[compiler->count++] = OP_SCOPE_BEGIN; //1 byte
|
||||
|
||||
//initial setup
|
||||
writeCompilerWithJumps(compiler, node->path.preClause, &breakAddresses, &continueAddresses, jumpOffsets);
|
||||
Opcode override = writeCompilerWithJumps(compiler, node->path.preClause, &breakAddresses, &continueAddresses, jumpOffsets);
|
||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||
}
|
||||
|
||||
//conditional
|
||||
unsigned short jumpToStart = compiler->count;
|
||||
writeCompilerWithJumps(compiler, node->path.condition, &breakAddresses, &continueAddresses, jumpOffsets);
|
||||
override = writeCompilerWithJumps(compiler, node->path.condition, &breakAddresses, &continueAddresses, jumpOffsets);
|
||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||
}
|
||||
|
||||
//if false jump to end
|
||||
compiler->bytecode[compiler->count++] = OP_IF_FALSE_JUMP; //1 byte
|
||||
@@ -609,14 +653,20 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
|
||||
//write the body
|
||||
compiler->bytecode[compiler->count++] = OP_SCOPE_BEGIN; //1 byte
|
||||
writeCompilerWithJumps(compiler, node->path.thenPath, &breakAddresses, &continueAddresses, jumpOffsets);
|
||||
override = writeCompilerWithJumps(compiler, node->path.thenPath, &breakAddresses, &continueAddresses, jumpOffsets);
|
||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||
}
|
||||
compiler->bytecode[compiler->count++] = OP_SCOPE_END; //1 byte
|
||||
|
||||
//for-breaks actually jump to the bottom
|
||||
int jumpToIncrement = compiler->count;
|
||||
|
||||
//evaluate third clause, restart
|
||||
writeCompilerWithJumps(compiler, node->path.postClause, &breakAddresses, &continueAddresses, jumpOffsets);
|
||||
override = writeCompilerWithJumps(compiler, node->path.postClause, &breakAddresses, &continueAddresses, jumpOffsets);
|
||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||
}
|
||||
|
||||
compiler->bytecode[compiler->count++] = OP_JUMP; //1 byte
|
||||
AS_USHORT(compiler->bytecode[compiler->count]) = jumpToStart + jumpOffsets;
|
||||
@@ -685,7 +735,10 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
case NODE_PATH_RETURN: {
|
||||
//read each returned literal onto the stack, and return the number of values to return
|
||||
for (int i = 0; i < node->path.thenPath->fnCollection.count; i++) {
|
||||
writeCompilerWithJumps(compiler, &node->path.thenPath->fnCollection.nodes[i], breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
Opcode override = writeCompilerWithJumps(compiler, &node->path.thenPath->fnCollection.nodes[i], breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||
}
|
||||
}
|
||||
|
||||
//push the return, with the number of literals
|
||||
@@ -766,7 +819,10 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
writeLiteralToCompiler(compiler, TO_NULL_LITERAL);
|
||||
}
|
||||
else {
|
||||
writeCompilerWithJumps(compiler, node->index.first, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
Opcode override = writeCompilerWithJumps(compiler, node->index.first, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||
}
|
||||
}
|
||||
|
||||
//second
|
||||
@@ -774,7 +830,10 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
writeLiteralToCompiler(compiler, TO_NULL_LITERAL);
|
||||
}
|
||||
else {
|
||||
writeCompilerWithJumps(compiler, node->index.second, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
Opcode override = writeCompilerWithJumps(compiler, node->index.second, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||
}
|
||||
}
|
||||
|
||||
//third
|
||||
@@ -782,7 +841,10 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
writeLiteralToCompiler(compiler, TO_NULL_LITERAL);
|
||||
}
|
||||
else {
|
||||
writeCompilerWithJumps(compiler, node->index.third, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
Opcode override = writeCompilerWithJumps(compiler, node->index.third, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||
}
|
||||
}
|
||||
|
||||
// compiler->bytecode[compiler->count++] = (unsigned char)OP_INDEX; //1 byte
|
||||
@@ -797,7 +859,10 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
writeLiteralToCompiler(compiler, TO_NULL_LITERAL);
|
||||
}
|
||||
else {
|
||||
writeCompilerWithJumps(compiler, node->index.first, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
Opcode override = writeCompilerWithJumps(compiler, node->index.first, breakAddressesPtr, continueAddressesPtr, jumpOffsets);
|
||||
if (override != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)override; //1 byte
|
||||
}
|
||||
}
|
||||
|
||||
// compiler->bytecode[compiler->count++] = (unsigned char)OP_DOT; //1 byte
|
||||
@@ -813,8 +878,7 @@ static Opcode writeCompilerWithJumps(Compiler* compiler, Node* node, void* break
|
||||
void writeCompiler(Compiler* compiler, Node* node) {
|
||||
Opcode op = writeCompilerWithJumps(compiler, node, NULL, NULL, 0);
|
||||
|
||||
//compensate for indexing & dot notation being screwy
|
||||
if (op != OP_EOF) {
|
||||
if (op != OP_EOF) {//compensate for indexing & dot notation being screwy
|
||||
compiler->bytecode[compiler->count++] = (unsigned char)op; //1 byte
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1428,6 +1428,10 @@ static bool execDot(Interpreter* interpreter) {
|
||||
Literal first = popLiteralArray(&interpreter->stack);
|
||||
Literal compound = popLiteralArray(&interpreter->stack);
|
||||
|
||||
Literal tmp = first;
|
||||
first = TO_STRING_LITERAL(copyString(AS_IDENTIFIER(tmp), strlen(AS_IDENTIFIER(tmp))) , strlen(AS_IDENTIFIER(tmp)) );
|
||||
freeLiteral(tmp);
|
||||
|
||||
if (!IS_IDENTIFIER(compound)) {
|
||||
interpreter->errorOutput("Unknown literal found in dot notation\n");
|
||||
freeLiteral(first);
|
||||
@@ -1441,7 +1445,7 @@ static bool execDot(Interpreter* interpreter) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IS_ARRAY(compound) && !IS_DICTIONARY(compound) && !IS_STRING(compound)) {
|
||||
if (!IS_DICTIONARY(compound)) {
|
||||
interpreter->errorOutput("Unknown compound found in dot notation\n");
|
||||
freeLiteral(first);
|
||||
freeLiteral(compound);
|
||||
@@ -1527,6 +1531,18 @@ static bool execIndexAssign(Interpreter* interpreter) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//check const-ness of "first" within "compound"
|
||||
Literal type = getScopeType(interpreter->scope, idn);
|
||||
if ((AS_TYPE(type).typeOf == LITERAL_ARRAY && AS_TYPE(((Literal*)(AS_TYPE(type).subtypes))[0]).constant) || (AS_TYPE(type).typeOf == LITERAL_DICTIONARY && AS_TYPE(((Literal*)(AS_TYPE(type).subtypes))[1]).constant)) {
|
||||
interpreter->errorOutput("couldn't assign to constant within compound within index assigning notation\n");
|
||||
freeLiteral(assign);
|
||||
freeLiteral(first);
|
||||
freeLiteral(compound);
|
||||
freeLiteral(idn);
|
||||
freeLiteral(type);
|
||||
return false;
|
||||
}
|
||||
|
||||
//get the index function
|
||||
Literal func = TO_NULL_LITERAL;
|
||||
char* keyStr = "_index";
|
||||
@@ -1542,6 +1558,7 @@ static bool execIndexAssign(Interpreter* interpreter) {
|
||||
freeLiteral(idn);
|
||||
freeLiteral(func);
|
||||
freeLiteral(key);
|
||||
freeLiteral(type);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1578,6 +1595,7 @@ static bool execIndexAssign(Interpreter* interpreter) {
|
||||
freeLiteral(idn);
|
||||
freeLiteral(func);
|
||||
freeLiteral(key);
|
||||
freeLiteral(type);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1616,6 +1634,7 @@ static bool execIndexAssign(Interpreter* interpreter) {
|
||||
freeLiteral(func);
|
||||
freeLiteralArray(&arguments);
|
||||
freeLiteral(key);
|
||||
freeLiteral(type);
|
||||
freeLiteral(result);
|
||||
return false;
|
||||
}
|
||||
@@ -1631,6 +1650,7 @@ static bool execIndexAssign(Interpreter* interpreter) {
|
||||
freeLiteral(func);
|
||||
freeLiteralArray(&arguments);
|
||||
freeLiteral(key);
|
||||
freeLiteral(type);
|
||||
freeLiteral(result);
|
||||
|
||||
return true;
|
||||
@@ -1643,6 +1663,10 @@ static bool execDotAssign(Interpreter* interpreter) {
|
||||
Literal first = popLiteralArray(&interpreter->stack);
|
||||
Literal compound = popLiteralArray(&interpreter->stack);
|
||||
|
||||
Literal tmp = first;
|
||||
first = TO_STRING_LITERAL(copyString(AS_IDENTIFIER(tmp), strlen(AS_IDENTIFIER(tmp))) , strlen(AS_IDENTIFIER(tmp)) );
|
||||
freeLiteral(tmp);
|
||||
|
||||
if (!IS_IDENTIFIER(compound)) {
|
||||
interpreter->errorOutput("Unknown literal found in dot assigning notation\n");
|
||||
freeLiteral(assign);
|
||||
@@ -1661,7 +1685,7 @@ static bool execDotAssign(Interpreter* interpreter) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IS_ARRAY(compound) && !IS_DICTIONARY(compound) && !IS_STRING(compound)) {
|
||||
if (!IS_DICTIONARY(compound)) {
|
||||
interpreter->errorOutput("Unknown compound found in dot assigning notation\n");
|
||||
freeLiteral(assign);
|
||||
freeLiteral(first);
|
||||
@@ -1670,6 +1694,18 @@ static bool execDotAssign(Interpreter* interpreter) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//check const-ness of "first" within "compound"
|
||||
Literal type = getScopeType(interpreter->scope, idn);
|
||||
if (AS_TYPE(type).typeOf == LITERAL_DICTIONARY && AS_TYPE(((Literal*)(AS_TYPE(type).subtypes))[1]).constant) {
|
||||
interpreter->errorOutput("couldn't assign to constant within compound within dot assigning notation\n");
|
||||
freeLiteral(assign);
|
||||
freeLiteral(first);
|
||||
freeLiteral(compound);
|
||||
freeLiteral(idn);
|
||||
freeLiteral(type);
|
||||
return false;
|
||||
}
|
||||
|
||||
//get the index function
|
||||
Literal func = TO_NULL_LITERAL;
|
||||
char* keyStr = "_dot";
|
||||
@@ -1683,6 +1719,7 @@ static bool execDotAssign(Interpreter* interpreter) {
|
||||
freeLiteral(idn);
|
||||
freeLiteral(func);
|
||||
freeLiteral(key);
|
||||
freeLiteral(type);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1717,6 +1754,7 @@ static bool execDotAssign(Interpreter* interpreter) {
|
||||
freeLiteral(idn);
|
||||
freeLiteral(func);
|
||||
freeLiteral(key);
|
||||
freeLiteral(type);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1737,7 +1775,7 @@ static bool execDotAssign(Interpreter* interpreter) {
|
||||
|
||||
//save the result (assume top of the interpreter stack is the new compound value)
|
||||
Literal result = popLiteralArray(&interpreter->stack);
|
||||
if (!setScopeVariable(interpreter->scope, idn, result, true)) {//TODO: check this const-ness
|
||||
if (!setScopeVariable(interpreter->scope, idn, result, true)) {
|
||||
interpreter->errorOutput("Incorrect type assigned to compound member: ");
|
||||
printLiteralCustom(result, interpreter->errorOutput);
|
||||
interpreter->errorOutput("\n");
|
||||
@@ -1751,6 +1789,7 @@ static bool execDotAssign(Interpreter* interpreter) {
|
||||
freeLiteral(func);
|
||||
freeLiteralArray(&arguments);
|
||||
freeLiteral(key);
|
||||
freeLiteral(type);
|
||||
freeLiteral(result);
|
||||
return false;
|
||||
}
|
||||
@@ -1764,6 +1803,7 @@ static bool execDotAssign(Interpreter* interpreter) {
|
||||
freeLiteral(func);
|
||||
freeLiteralArray(&arguments);
|
||||
freeLiteral(key);
|
||||
freeLiteral(type);
|
||||
freeLiteral(result);
|
||||
|
||||
return true;
|
||||
|
||||
@@ -1,6 +1,30 @@
|
||||
#include "lib_builtin.h"
|
||||
|
||||
#include "memory.h"
|
||||
#include "literal.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
//static math utils
|
||||
static Literal addition(Literal lhs, Literal rhs) {
|
||||
//TODO
|
||||
}
|
||||
|
||||
static Literal subtraction(Literal lhs, Literal rhs) {
|
||||
//TODO
|
||||
}
|
||||
|
||||
static Literal multiplication(Literal lhs, Literal rhs) {
|
||||
//TODO
|
||||
}
|
||||
|
||||
static Literal division(Literal lhs, Literal rhs) {
|
||||
//TODO
|
||||
}
|
||||
|
||||
static Literal modulo(Literal lhs, Literal rhs) {
|
||||
//TODO
|
||||
}
|
||||
|
||||
int _index(Interpreter* interpreter, LiteralArray* arguments) {
|
||||
//_index(compound, first, second, third, assignValue, op)
|
||||
@@ -11,12 +35,528 @@ int _index(Interpreter* interpreter, LiteralArray* arguments) {
|
||||
Literal first = popLiteralArray(arguments);
|
||||
Literal compound = popLiteralArray(arguments);
|
||||
|
||||
printLiteralCustom(compound, interpreter->printOutput);
|
||||
printLiteralCustom(first, interpreter->printOutput);
|
||||
printLiteralCustom(second, interpreter->printOutput);
|
||||
printLiteralCustom(third, interpreter->printOutput);
|
||||
printLiteralCustom(op, interpreter->printOutput);
|
||||
printLiteralCustom(assign, interpreter->printOutput);
|
||||
Literal value = TO_NULL_LITERAL;
|
||||
|
||||
//dictionary - no slicing
|
||||
if (IS_DICTIONARY(compound)) {
|
||||
value = getLiteralDictionary(AS_DICTIONARY(compound), first);
|
||||
|
||||
//dictionary
|
||||
//dictionary
|
||||
if (IS_NULL(op)) {
|
||||
pushLiteralArray(&interpreter->stack, value);
|
||||
|
||||
freeLiteral(compound);
|
||||
freeLiteral(first);
|
||||
freeLiteral(second);
|
||||
freeLiteral(third);
|
||||
freeLiteral(op);
|
||||
freeLiteral(assign);
|
||||
freeLiteral(value);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
else if (!strcmp( AS_STRING(op), "=")) {
|
||||
setLiteralDictionary(AS_DICTIONARY(compound), first, assign);
|
||||
}
|
||||
|
||||
else if (!strcmp( AS_STRING(op), "+=")) {
|
||||
setLiteralDictionary(AS_DICTIONARY(compound), first, addition(value, assign));
|
||||
}
|
||||
|
||||
else if (!strcmp( AS_STRING(op), "-=")) {
|
||||
setLiteralDictionary(AS_DICTIONARY(compound), first, subtraction(value, assign));
|
||||
}
|
||||
|
||||
else if (!strcmp( AS_STRING(op), "*=")) {
|
||||
setLiteralDictionary(AS_DICTIONARY(compound), first, multiplication(value, assign));
|
||||
}
|
||||
|
||||
else if (!strcmp( AS_STRING(op), "/=")) {
|
||||
setLiteralDictionary(AS_DICTIONARY(compound), first, division(value, assign));
|
||||
}
|
||||
|
||||
else if (!strcmp( AS_STRING(op), "%=")) {
|
||||
setLiteralDictionary(AS_DICTIONARY(compound), first, modulo(value, assign));
|
||||
}
|
||||
}
|
||||
|
||||
//array - slicing
|
||||
if (IS_ARRAY(compound)) {
|
||||
value = getLiteralArray(AS_ARRAY(compound), first);
|
||||
|
||||
//array slice
|
||||
if (IS_NULL(op)) {
|
||||
//parse out the booleans & their defaults
|
||||
if (!IS_NULL(first)) {
|
||||
if (IS_BOOLEAN(first)) {
|
||||
freeLiteral(first);
|
||||
first = TO_INTEGER_LITERAL(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (!IS_NULL(second)) {
|
||||
if (IS_BOOLEAN(second)) {
|
||||
freeLiteral(second);
|
||||
second = TO_INTEGER_LITERAL(AS_ARRAY(compound)->count);
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_NULL(third) || IS_BOOLEAN(third)) {
|
||||
freeLiteral(third);
|
||||
third = TO_INTEGER_LITERAL(1);
|
||||
}
|
||||
|
||||
//handle each null case
|
||||
if (IS_NULL(first) || !IS_INTEGER(first)) {
|
||||
//something is weird - skip out
|
||||
freeLiteral(compound);
|
||||
freeLiteral(first);
|
||||
freeLiteral(second);
|
||||
freeLiteral(third);
|
||||
freeLiteral(op);
|
||||
freeLiteral(assign);
|
||||
freeLiteral(value);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (IS_NULL(second)) { //assign only a single character
|
||||
//get the "first" within the array, then skip out
|
||||
|
||||
value = getLiteralArray(AS_ARRAY(compound), first);
|
||||
pushLiteralArray(&interpreter->stack, value);
|
||||
|
||||
freeLiteral(compound);
|
||||
freeLiteral(first);
|
||||
freeLiteral(second);
|
||||
freeLiteral(third);
|
||||
freeLiteral(op);
|
||||
freeLiteral(assign);
|
||||
freeLiteral(value);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!IS_INTEGER(second) || (!IS_NULL(third) && !IS_INTEGER(third)) || AS_INTEGER(second) < 0 || AS_INTEGER(second) > AS_ARRAY(compound)->count || AS_INTEGER(third) == 0) {
|
||||
//something is weird - skip out
|
||||
freeLiteral(compound);
|
||||
freeLiteral(first);
|
||||
freeLiteral(second);
|
||||
freeLiteral(third);
|
||||
freeLiteral(op);
|
||||
freeLiteral(assign);
|
||||
freeLiteral(value);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//start building a new array from the old one
|
||||
LiteralArray* result = ALLOCATE(LiteralArray, 1);
|
||||
initLiteralArray(result);
|
||||
|
||||
int min = AS_INTEGER(third) > 0 ? 0 : AS_INTEGER(second) - 1;
|
||||
|
||||
//copy compound into result
|
||||
for (int i = min; i >= 0 && i <= AS_ARRAY(compound)->count && i >= AS_INTEGER(first) && i < AS_INTEGER(second); i += AS_INTEGER(third)) {
|
||||
Literal idx = TO_INTEGER_LITERAL(i);
|
||||
Literal tmp = getLiteralArray(AS_ARRAY(compound), idx);
|
||||
pushLiteralArray(result, tmp);
|
||||
|
||||
freeLiteral(idx);
|
||||
freeLiteral(tmp);
|
||||
}
|
||||
|
||||
//finally, swap out the compound for the result
|
||||
freeLiteral(compound);
|
||||
compound = TO_ARRAY_LITERAL(result);
|
||||
}
|
||||
|
||||
//array slice assignment
|
||||
else if (!strcmp( AS_STRING(op), "=")) {
|
||||
//parse out the booleans & their defaults
|
||||
if (!IS_NULL(first)) {
|
||||
if (IS_BOOLEAN(first)) {
|
||||
freeLiteral(first);
|
||||
first = TO_INTEGER_LITERAL(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (!IS_NULL(second)) {
|
||||
if (IS_BOOLEAN(second)) {
|
||||
freeLiteral(second);
|
||||
second = TO_INTEGER_LITERAL(AS_ARRAY(compound)->count);
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_NULL(third) || IS_BOOLEAN(third)) {
|
||||
freeLiteral(third);
|
||||
third = TO_INTEGER_LITERAL(1);
|
||||
}
|
||||
|
||||
//handle each null case
|
||||
if (IS_NULL(first) || !IS_INTEGER(first)) {
|
||||
//something is weird - skip out
|
||||
freeLiteral(compound);
|
||||
freeLiteral(first);
|
||||
freeLiteral(second);
|
||||
freeLiteral(third);
|
||||
freeLiteral(op);
|
||||
freeLiteral(assign);
|
||||
freeLiteral(value);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (IS_NULL(second)) {
|
||||
//set the "first" within the array, then skip out
|
||||
setLiteralArray(AS_ARRAY(compound), first, assign);
|
||||
|
||||
pushLiteralArray(&interpreter->stack, compound);
|
||||
|
||||
freeLiteral(compound);
|
||||
freeLiteral(first);
|
||||
freeLiteral(second);
|
||||
freeLiteral(third);
|
||||
freeLiteral(op);
|
||||
freeLiteral(assign);
|
||||
freeLiteral(value);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!IS_INTEGER(second) || (!IS_NULL(third) && !IS_INTEGER(third)) || AS_INTEGER(second) < 0 || AS_INTEGER(second) > AS_ARRAY(compound)->count || AS_INTEGER(third) == 0) {
|
||||
//something is weird - skip out
|
||||
freeLiteral(compound);
|
||||
freeLiteral(first);
|
||||
freeLiteral(second);
|
||||
freeLiteral(third);
|
||||
freeLiteral(op);
|
||||
freeLiteral(assign);
|
||||
freeLiteral(value);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//start building a new array from the old one
|
||||
LiteralArray* result = ALLOCATE(LiteralArray, 1);
|
||||
initLiteralArray(result);
|
||||
|
||||
//if third is abs(1), simply insert into the correct positions
|
||||
if (AS_INTEGER(third) == 1 || AS_INTEGER(third) == -1) {
|
||||
for (int i = 0; i < AS_INTEGER(first); i++) {
|
||||
Literal idx = TO_INTEGER_LITERAL(i);
|
||||
Literal tmp = getLiteralArray(AS_ARRAY(compound), idx);
|
||||
pushLiteralArray(result, tmp);
|
||||
|
||||
freeLiteral(idx);
|
||||
freeLiteral(tmp);
|
||||
}
|
||||
|
||||
int min = AS_INTEGER(third) > 0 ? 0 : AS_ARRAY(assign)->count - 1;
|
||||
|
||||
for (int i = min; i >= 0 && i < AS_ARRAY(assign)->count; i += AS_INTEGER(third)) {
|
||||
Literal idx = TO_INTEGER_LITERAL(i);
|
||||
Literal tmp = getLiteralArray(AS_ARRAY(assign), idx); //backwards
|
||||
|
||||
//set result
|
||||
pushLiteralArray(result, tmp);
|
||||
|
||||
freeLiteral(idx);
|
||||
freeLiteral(tmp);
|
||||
}
|
||||
|
||||
for (int i = AS_INTEGER(second) + 1; i < AS_ARRAY(compound)->count; i++) {
|
||||
Literal idx = TO_INTEGER_LITERAL(i);
|
||||
Literal tmp = getLiteralArray(AS_ARRAY(compound), idx);
|
||||
pushLiteralArray(result, tmp);
|
||||
|
||||
freeLiteral(idx);
|
||||
freeLiteral(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
//else override elements of the array instead
|
||||
else {
|
||||
//copy compound to result
|
||||
for (int i = 0; i < AS_ARRAY(compound)->count; i++) {
|
||||
Literal idx = TO_INTEGER_LITERAL(i);
|
||||
Literal tmp = getLiteralArray(AS_ARRAY(compound), idx);
|
||||
|
||||
pushLiteralArray(result, tmp);
|
||||
|
||||
freeLiteral(idx);
|
||||
freeLiteral(tmp);
|
||||
}
|
||||
|
||||
int min = AS_INTEGER(third) > 0 ? 0 : AS_ARRAY(compound)->count - 1;
|
||||
|
||||
int assignIndex = 0;
|
||||
for (int i = min; i >= 0 && i < AS_ARRAY(compound)->count && assignIndex < AS_ARRAY(assign)->count; i += AS_INTEGER(third)) {
|
||||
Literal idx = TO_INTEGER_LITERAL(i);
|
||||
Literal ai = TO_INTEGER_LITERAL(assignIndex++);
|
||||
Literal tmp = getLiteralArray(AS_ARRAY(assign), ai);
|
||||
|
||||
setLiteralArray(result, idx, tmp);
|
||||
|
||||
freeLiteral(idx);
|
||||
freeLiteral(ai);
|
||||
freeLiteral(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
//finally, swap out the compound for the result
|
||||
freeLiteral(compound);
|
||||
compound = TO_ARRAY_LITERAL(result);
|
||||
}
|
||||
|
||||
else if (IS_STRING(op) && !strcmp( AS_STRING(op), "+=")) {
|
||||
setLiteralArray(AS_ARRAY(compound), first, addition(value, assign));
|
||||
}
|
||||
|
||||
else if (IS_STRING(op) && !strcmp( AS_STRING(op), "-=")) {
|
||||
setLiteralArray(AS_ARRAY(compound), first, subtraction(value, assign));
|
||||
}
|
||||
|
||||
else if (IS_STRING(op) && !strcmp( AS_STRING(op), "*=")) {
|
||||
setLiteralArray(AS_ARRAY(compound), first, multiplication(value, assign));
|
||||
}
|
||||
|
||||
else if (IS_STRING(op) && !strcmp( AS_STRING(op), "/=")) {
|
||||
setLiteralArray(AS_ARRAY(compound), first, division(value, assign));
|
||||
}
|
||||
|
||||
else if (IS_STRING(op) && !strcmp( AS_STRING(op), "%=")) {
|
||||
setLiteralArray(AS_ARRAY(compound), first, modulo(value, assign));
|
||||
}
|
||||
}
|
||||
|
||||
//string - slicing
|
||||
if (IS_STRING(compound)) {
|
||||
//string slice
|
||||
if (IS_NULL(op)) {
|
||||
//parse out the booleans & their defaults
|
||||
if (!IS_NULL(first)) {
|
||||
if (IS_BOOLEAN(first)) {
|
||||
freeLiteral(first);
|
||||
first = TO_INTEGER_LITERAL(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (!IS_NULL(second)) {
|
||||
if (IS_BOOLEAN(second)) {
|
||||
freeLiteral(second);
|
||||
second = TO_INTEGER_LITERAL(strlen(AS_STRING(compound)));
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_NULL(third) || IS_BOOLEAN(third)) {
|
||||
freeLiteral(third);
|
||||
third = TO_INTEGER_LITERAL(1);
|
||||
}
|
||||
|
||||
//handle each null case
|
||||
if (IS_NULL(first) || !IS_INTEGER(first)) {
|
||||
//something is weird - skip out
|
||||
freeLiteral(compound);
|
||||
freeLiteral(first);
|
||||
freeLiteral(second);
|
||||
freeLiteral(third);
|
||||
freeLiteral(op);
|
||||
freeLiteral(assign);
|
||||
freeLiteral(value);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (IS_NULL(second)) { //assign only a single character
|
||||
char c = AS_STRING(compound)[AS_INTEGER(first)];
|
||||
|
||||
char buffer[16];
|
||||
snprintf(buffer, 16, "%c", c);
|
||||
|
||||
freeLiteral(value);
|
||||
value = TO_STRING_LITERAL(copyString(buffer, strlen(buffer)), strlen(buffer));
|
||||
|
||||
pushLiteralArray(&interpreter->stack, value);
|
||||
|
||||
freeLiteral(compound);
|
||||
freeLiteral(first);
|
||||
freeLiteral(second);
|
||||
freeLiteral(third);
|
||||
freeLiteral(op);
|
||||
freeLiteral(assign);
|
||||
freeLiteral(value);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!IS_INTEGER(second) || (!IS_NULL(third) && !IS_INTEGER(third)) || AS_INTEGER(second) < 0 || AS_INTEGER(second) > strlen(AS_STRING(compound)) || AS_INTEGER(third) == 0) {
|
||||
//something is weird - skip out
|
||||
freeLiteral(compound);
|
||||
freeLiteral(first);
|
||||
freeLiteral(second);
|
||||
freeLiteral(third);
|
||||
freeLiteral(op);
|
||||
freeLiteral(assign);
|
||||
freeLiteral(value);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//start building a new string from the old one
|
||||
char* result = ALLOCATE(char, MAX_STRING_LENGTH);
|
||||
|
||||
int min = AS_INTEGER(third) > 0 ? AS_INTEGER(first) : AS_INTEGER(second) - 1;
|
||||
|
||||
//copy compound into result
|
||||
int resultIndex = 0;
|
||||
for (int i = min; i >= AS_INTEGER(first) && i < AS_INTEGER(second); i += AS_INTEGER(third)) {
|
||||
result[ resultIndex++ ] = AS_STRING(compound)[ i ];
|
||||
}
|
||||
|
||||
result[ resultIndex++ ] = '\0';
|
||||
|
||||
//finally, swap out the compound for the result
|
||||
freeLiteral(compound);
|
||||
compound = TO_STRING_LITERAL(copyString(result, strlen(result)), strlen(result));
|
||||
|
||||
FREE_ARRAY(char, result, MAX_STRING_LENGTH);
|
||||
}
|
||||
|
||||
//string slice assignment
|
||||
else if (IS_STRING(op) && !strcmp( AS_STRING(op), "=")) {
|
||||
//parse out the booleans & their defaults
|
||||
if (!IS_NULL(first)) {
|
||||
if (IS_BOOLEAN(first)) {
|
||||
freeLiteral(first);
|
||||
first = TO_INTEGER_LITERAL(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (!IS_NULL(second)) {
|
||||
if (IS_BOOLEAN(second)) {
|
||||
freeLiteral(second);
|
||||
second = TO_INTEGER_LITERAL(strlen(AS_STRING(compound)));
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_NULL(third) || IS_BOOLEAN(third)) {
|
||||
freeLiteral(third);
|
||||
third = TO_INTEGER_LITERAL(1);
|
||||
}
|
||||
|
||||
//handle each null case
|
||||
if (IS_NULL(first) || !IS_INTEGER(first)) {
|
||||
//something is weird - skip out
|
||||
freeLiteral(compound);
|
||||
freeLiteral(first);
|
||||
freeLiteral(second);
|
||||
freeLiteral(third);
|
||||
freeLiteral(op);
|
||||
freeLiteral(assign);
|
||||
freeLiteral(value);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (IS_NULL(second)) { //assign only a single character
|
||||
//set the "first" within the array, then skip out
|
||||
if (strlen( AS_STRING(assign) ) != 1) {
|
||||
//something is weird - skip out
|
||||
|
||||
freeLiteral(compound);
|
||||
freeLiteral(first);
|
||||
freeLiteral(second);
|
||||
freeLiteral(third);
|
||||
freeLiteral(op);
|
||||
freeLiteral(assign);
|
||||
freeLiteral(value);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
AS_STRING(compound)[AS_INTEGER(first)] = AS_STRING(assign)[0];
|
||||
|
||||
pushLiteralArray(&interpreter->stack, compound);
|
||||
|
||||
freeLiteral(compound);
|
||||
freeLiteral(first);
|
||||
freeLiteral(second);
|
||||
freeLiteral(third);
|
||||
freeLiteral(op);
|
||||
freeLiteral(assign);
|
||||
freeLiteral(value);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!IS_INTEGER(second) || (!IS_NULL(third) && !IS_INTEGER(third)) || AS_INTEGER(second) < 0 || AS_INTEGER(second) > strlen(AS_STRING(compound)) || AS_INTEGER(third) == 0) {
|
||||
//something is weird - skip out
|
||||
freeLiteral(compound);
|
||||
freeLiteral(first);
|
||||
freeLiteral(second);
|
||||
freeLiteral(third);
|
||||
freeLiteral(op);
|
||||
freeLiteral(assign);
|
||||
freeLiteral(value);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//start building a new string from the old one
|
||||
char* result = ALLOCATE(char, MAX_STRING_LENGTH);
|
||||
|
||||
//if third is abs(1), simply insert into the correct positions
|
||||
int resultIndex = 0;
|
||||
if (AS_INTEGER(third) == 1 || AS_INTEGER(third) == -1) {
|
||||
for (int i = 0; i < AS_INTEGER(first); i++) {
|
||||
result[ resultIndex++ ] = AS_STRING(compound)[ i ];
|
||||
}
|
||||
|
||||
int min = AS_INTEGER(third) > 0 ? 0 : strlen(AS_STRING(assign)) - 1;
|
||||
|
||||
//TODO: optimize strlen(assign)
|
||||
for (int i = min; i >= 0 && i < strlen(AS_STRING(assign)); i += AS_INTEGER(third)) {
|
||||
result[ resultIndex++ ] = AS_STRING(assign)[ i ];
|
||||
}
|
||||
|
||||
for (int i = AS_INTEGER(second) + 1; i < strlen(AS_STRING(compound)); i++) {
|
||||
result[ resultIndex++ ] = AS_STRING(compound)[ i ];
|
||||
}
|
||||
}
|
||||
|
||||
//else override elements of the array instead
|
||||
else {
|
||||
//copy compound to result
|
||||
snprintf(result, MAX_STRING_LENGTH, AS_STRING(compound));
|
||||
|
||||
int min = AS_INTEGER(third) > 0 ? AS_INTEGER(first) : AS_INTEGER(second);
|
||||
|
||||
int assignIndex = 0;
|
||||
for (int i = min; i >= AS_INTEGER(first) && i <= AS_INTEGER(second) && assignIndex < strlen(AS_STRING(assign)); i += AS_INTEGER(third)) {
|
||||
result[ i ] = AS_STRING(assign)[ assignIndex++ ];
|
||||
resultIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
//finally, swap out the compound for the result
|
||||
freeLiteral(compound);
|
||||
compound = TO_STRING_LITERAL(copyString(result, strlen(result)), strlen(result));
|
||||
|
||||
FREE_ARRAY(char, result, MAX_STRING_LENGTH);
|
||||
}
|
||||
|
||||
else if (IS_STRING(op) && !strcmp( AS_STRING(op), "+=")) {
|
||||
Literal tmp = addition(compound, value);
|
||||
freeLiteral(compound);
|
||||
compound = tmp; //don't clear tmp
|
||||
}
|
||||
}
|
||||
|
||||
//leave the compound on the stack
|
||||
pushLiteralArray(&interpreter->stack, compound);
|
||||
|
||||
freeLiteral(compound);
|
||||
freeLiteral(first);
|
||||
@@ -24,8 +564,9 @@ int _index(Interpreter* interpreter, LiteralArray* arguments) {
|
||||
freeLiteral(third);
|
||||
freeLiteral(op);
|
||||
freeLiteral(assign);
|
||||
freeLiteral(value);
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _dot(Interpreter* interpreter, LiteralArray* arguments) {
|
||||
@@ -35,17 +576,51 @@ int _dot(Interpreter* interpreter, LiteralArray* arguments) {
|
||||
Literal first = popLiteralArray(arguments);
|
||||
Literal compound = popLiteralArray(arguments);
|
||||
|
||||
printLiteralCustom(compound, interpreter->printOutput);
|
||||
printLiteralCustom(first, interpreter->printOutput);
|
||||
printLiteralCustom(op, interpreter->printOutput);
|
||||
printLiteralCustom(assign, interpreter->printOutput);
|
||||
Literal value = getLiteralDictionary(AS_DICTIONARY(compound), first);
|
||||
|
||||
//dictionary
|
||||
if (IS_NULL(op)) {
|
||||
pushLiteralArray(&interpreter->stack, value);
|
||||
}
|
||||
|
||||
else if (!strcmp( AS_STRING(op), "=")) {
|
||||
setLiteralDictionary(AS_DICTIONARY(compound), first, assign);
|
||||
pushLiteralArray(&interpreter->stack, compound);
|
||||
}
|
||||
|
||||
else if (!strcmp( AS_STRING(op), "+=")) {
|
||||
setLiteralDictionary(AS_DICTIONARY(compound), first, addition(value, assign));
|
||||
pushLiteralArray(&interpreter->stack, compound);
|
||||
}
|
||||
|
||||
else if (!strcmp( AS_STRING(op), "-=")) {
|
||||
setLiteralDictionary(AS_DICTIONARY(compound), first, subtraction(value, assign));
|
||||
pushLiteralArray(&interpreter->stack, compound);
|
||||
}
|
||||
|
||||
else if (!strcmp( AS_STRING(op), "*=")) {
|
||||
setLiteralDictionary(AS_DICTIONARY(compound), first, multiplication(value, assign));
|
||||
pushLiteralArray(&interpreter->stack, compound);
|
||||
}
|
||||
|
||||
else if (!strcmp( AS_STRING(op), "/=")) {
|
||||
setLiteralDictionary(AS_DICTIONARY(compound), first, division(value, assign));
|
||||
pushLiteralArray(&interpreter->stack, compound);
|
||||
}
|
||||
|
||||
else if (!strcmp( AS_STRING(op), "%=")) {
|
||||
setLiteralDictionary(AS_DICTIONARY(compound), first, modulo(value, assign));
|
||||
pushLiteralArray(&interpreter->stack, compound);
|
||||
}
|
||||
|
||||
//cleanup
|
||||
freeLiteral(compound);
|
||||
freeLiteral(first);
|
||||
freeLiteral(op);
|
||||
freeLiteral(assign);
|
||||
freeLiteral(value);
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _set(Interpreter* interpreter, LiteralArray* arguments) {
|
||||
|
||||
@@ -65,3 +65,34 @@ int findLiteralIndex(LiteralArray* array, Literal literal) {
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool setLiteralArray(LiteralArray* array, Literal index, Literal value) {
|
||||
if (!IS_INTEGER(index)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int idx = AS_INTEGER(index);
|
||||
|
||||
if (idx < 0 || idx >= array->count) {
|
||||
return false;
|
||||
}
|
||||
|
||||
freeLiteral(array->literals[idx]);
|
||||
array->literals[idx] = copyLiteral(value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Literal getLiteralArray(LiteralArray* array, Literal index) {
|
||||
if (!IS_INTEGER(index)) {
|
||||
return TO_NULL_LITERAL;
|
||||
}
|
||||
|
||||
int idx = AS_INTEGER(index);
|
||||
|
||||
if (idx < 0 || idx >= array->count) {
|
||||
return TO_NULL_LITERAL;
|
||||
}
|
||||
|
||||
return copyLiteral(array->literals[idx]);
|
||||
}
|
||||
@@ -12,6 +12,7 @@ void initLiteralArray(LiteralArray* array);
|
||||
void freeLiteralArray(LiteralArray* array);
|
||||
int pushLiteralArray(LiteralArray* array, Literal literal);
|
||||
Literal popLiteralArray(LiteralArray* array);
|
||||
//TODO: set & get
|
||||
bool setLiteralArray(LiteralArray* array, Literal index, Literal value);
|
||||
Literal getLiteralArray(LiteralArray* array, Literal index);
|
||||
|
||||
int findLiteralIndex(LiteralArray* array, Literal literal);
|
||||
|
||||
@@ -726,31 +726,44 @@ static Opcode indexAccess(Parser* parser, Node** nodeHandle) {
|
||||
Node* second = NULL;
|
||||
Node* third = NULL;
|
||||
|
||||
//booleans indicate blank slice indexing
|
||||
emitNodeLiteral(&first, TO_BOOLEAN_LITERAL(true));
|
||||
emitNodeLiteral(&second, TO_BOOLEAN_LITERAL(true));
|
||||
emitNodeLiteral(&third, TO_BOOLEAN_LITERAL(true));
|
||||
|
||||
//eat the first
|
||||
if (!match(parser, TOKEN_COLON)) {
|
||||
freeNode(first);
|
||||
parsePrecedence(parser, &first, PREC_TERNARY);
|
||||
match(parser, TOKEN_COLON);
|
||||
}
|
||||
|
||||
if (match(parser, TOKEN_BRACKET_RIGHT)) {
|
||||
// freeNode(second);
|
||||
// freeNode(third);
|
||||
// second = NULL;
|
||||
// third = NULL;
|
||||
|
||||
emitNodeIndex(nodeHandle, first, second, third);
|
||||
return OP_INDEX;
|
||||
}
|
||||
|
||||
consume(parser, TOKEN_COLON, "Expected ':' in index notation");
|
||||
|
||||
//eat the second
|
||||
if (!match(parser, TOKEN_COLON)) {
|
||||
freeNode(second);
|
||||
parsePrecedence(parser, &second, PREC_TERNARY);
|
||||
match(parser, TOKEN_COLON);
|
||||
}
|
||||
|
||||
if (match(parser, TOKEN_BRACKET_RIGHT)) {
|
||||
// freeNode(third);
|
||||
// third = NULL;
|
||||
emitNodeIndex(nodeHandle, first, second, third);
|
||||
return OP_INDEX;
|
||||
}
|
||||
|
||||
consume(parser, TOKEN_COLON, "Expected ':' in index notation");
|
||||
|
||||
//eat the third
|
||||
freeNode(third);
|
||||
parsePrecedence(parser, &third, PREC_TERNARY);
|
||||
emitNodeIndex(nodeHandle, first, second, third);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user