diff --git a/scripts/small.toy b/scripts/small.toy index 445f223..f80b992 100644 --- a/scripts/small.toy +++ b/scripts/small.toy @@ -1,5 +1,56 @@ -import standard as std; +fn _b(self) { + print "running _b"; + print self; + return self; +} -print std; +fn _c(self) { + print "running _c"; + print self; + return self; +} + +fn _d(self) { + print "running _d"; + print self; + return self; +} + +fn _e(self) { + print "running _e"; + print self; + return self; +} + +fn _f(self) { + print "running _f"; + print self; + return self; +} + + +fn b() { + print "running b"; +} + +fn c() { + print "running c"; +} + +fn d() { + print "running d"; +} + +fn e() { + print "running e"; +} + +fn f() { + print "running f"; +} + +var a = 42; + +print a.b().c().d().e().f(); \ No newline at end of file diff --git a/scripts/test/dot-chaining.toy b/scripts/test/dot-chaining.toy new file mode 100644 index 0000000..54401e0 --- /dev/null +++ b/scripts/test/dot-chaining.toy @@ -0,0 +1,22 @@ +//test function chaining with the dot operator + +fn _identity(self) { + return self; +} + +fn _check(self) { + assert self == 42, "dot chaining failed"; + return self; +} + +var val = 42; + +val + .identity() + .check() + .identity() + .check() + ; + + +print "All good"; diff --git a/source/parser.c b/source/parser.c index 97d6b3f..ad98533 100644 --- a/source/parser.c +++ b/source/parser.c @@ -799,8 +799,10 @@ static Opcode dot(Parser* parser, ASTNode** nodeHandle) { } //hijack the function call, and hack in an extra parameter - node->binary.right->fnCall.argumentCount++; - node->binary.opcode = OP_DOT; + if (node->binary.opcode == OP_FN_CALL) { + node->binary.right->fnCall.argumentCount++; + node->binary.opcode = OP_DOT; + } (*nodeHandle) = node; return OP_DOT; //signal that the function name and arguments are in the wrong order @@ -1083,6 +1085,17 @@ static bool calcStaticBinaryArithmetic(Parser* parser, ASTNode** nodeHandle) { return true; } +static void dottify(Parser* parser, ASTNode** nodeHandle) { + //only if this is chained from a higher binary "fn_call" + if ((*nodeHandle)->type == AST_NODEBINARY) { + if ((*nodeHandle)->binary.opcode == OP_FN_CALL) { + (*nodeHandle)->binary.opcode = OP_DOT; + } + dottify(parser, &(*nodeHandle)->binary.left); + dottify(parser, &(*nodeHandle)->binary.right); + } +} + static void parsePrecedence(Parser* parser, ASTNode** nodeHandle, PrecedenceRule rule) { //every valid expression has a prefix rule advance(parser); @@ -1116,6 +1129,11 @@ static void parsePrecedence(Parser* parser, ASTNode** nodeHandle, PrecedenceRule return; //we're done here } + //BUGFIX: dot-chaining + if (opcode == OP_DOT) { + dottify(parser, &rhsNode); + } + emitASTNodeBinary(nodeHandle, rhsNode, opcode); if (!calcStaticBinaryArithmetic(parser, nodeHandle)) { diff --git a/test/test_interpreter.c b/test/test_interpreter.c index 208aa45..403b04f 100644 --- a/test/test_interpreter.c +++ b/test/test_interpreter.c @@ -168,6 +168,7 @@ int main() { "coercions.toy", "comparisons.toy", "dot-and-matrix.toy", + "dot-chaining.toy", "functions.toy", "imports-and-exports.toy", "index-arrays.toy",