Fixed invoking functions within function arguments

Somewhat similar to c9d4b9965c
This commit is contained in:
2026-05-19 13:21:41 +10:00
parent a0d75b3c70
commit f55f27726c
10 changed files with 115 additions and 47 deletions
+31
View File
@@ -0,0 +1,31 @@
//WARN: This is just a scratch pad, don't use it
//for (var i in array) print i;
//for (var i in range(10)) print i;
//example of a `range` function
fn range(limit: Int) {
var counter: Int = 0;
fn next() {
if (counter >= limit) {
return null;
}
else return counter++;
}
return next;
}
var next = range(10);
fn log(x) {
if (x == null) return;
print x;
}
while (true) {
log(next());
}
+7 -7
View File
@@ -1,12 +1,12 @@
if (true) {
print "Who?";
fn a(x) {
print x;
}
else if (true) {
print "What?";
}
else {
print "IDK";
fn b() {
return 42;
}
a(b(), b());
+1
View File
@@ -76,6 +76,7 @@ typedef enum Toy_AstFlag {
TOY_AST_FLAG_COLLECTION = 32,
TOY_AST_FLAG_PAIR = 33,
TOY_AST_FLAG_INDEX = 34,
TOY_AST_FLAG_FN_ARGUMENTS = 35,
//unary flags
TOY_AST_FLAG_NEGATE = 40,
+14 -2
View File
@@ -580,6 +580,18 @@ static unsigned int writeInstructionAggregate(Toy_Bytecode** mb, Toy_AstAggregat
return 1; //leaves only 1 value on the stack
}
else if (ast.flag == TOY_AST_FLAG_FN_ARGUMENTS) {
//BUGFIX: invoking a function as an argument gets messy, so re-count the aggregate elements and discard 'result'
int count = ast.left != NULL ? 2 : 1;
Toy_Ast* iter = ast.right;
while (iter != NULL && iter->type == TOY_AST_AGGREGATE) {
iter = iter->aggregate.right;
count++;
}
return count;
}
else {
fprintf(stderr, TOY_CC_ERROR "ERROR: Invalid AST aggregate flag found\n" TOY_CC_RESET);
exit(-1);
@@ -776,7 +788,7 @@ static unsigned int writeInstructionReturn(Toy_Bytecode** mb, Toy_AstReturn ast)
EMIT_BYTE(mb, code,0);
EMIT_BYTE(mb, code,0);
return 0;
return retCount;
}
static unsigned int writeInstructionPrint(Toy_Bytecode** mb, Toy_AstPrint ast) {
@@ -1114,7 +1126,7 @@ static unsigned int writeInstructionFnInvoke(Toy_Bytecode** mb, Toy_AstFnInvoke
EMIT_BYTE(mb, code, TOY_OPCODE_INVOKE);
EMIT_BYTE(mb, code, TOY_VALUE_FUNCTION);
EMIT_BYTE(mb, code, (unsigned char)argCount);
EMIT_BYTE(mb, code, 0); //IDK how many returns
EMIT_BYTE(mb, code, 0); //BUG: IDK how many returns
return chainedInvoke ? 1 : 0;
}
+6 -2
View File
@@ -724,7 +724,7 @@ static Toy_AstFlag invoke(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast
parsePrecedence(bucketHandle, parser, &ast, PREC_GROUP);
//add to the args aggregate (is added backwards, because weird)
Toy_private_emitAstAggregate(bucketHandle, &args, TOY_AST_FLAG_COLLECTION, ast);
Toy_private_emitAstAggregate(bucketHandle, &args, TOY_AST_FLAG_FN_ARGUMENTS, ast);
}
consume(parser, TOY_TOKEN_OPERATOR_PAREN_RIGHT, "Expected ')' at the end of argument list");
@@ -902,11 +902,15 @@ static void makeContinueStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_
}
static void makeReturnStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle) {
if (match(parser, TOY_TOKEN_OPERATOR_SEMICOLON)) {
Toy_private_emitAstReturn(bucketHandle, rootHandle);
}
else {
parsePrecedence(bucketHandle, parser, rootHandle, PREC_GROUP); //expect an aggregate
Toy_private_emitAstReturn(bucketHandle, rootHandle);
consume(parser, TOY_TOKEN_OPERATOR_SEMICOLON, "Expected ';' at the end of return statement");
}
}
static void makePrintStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle) {
makeExpr(bucketHandle, parser, rootHandle);
+32 -32
View File
@@ -20,28 +20,28 @@ typedef enum Toy_TokenType {
TOY_TOKEN_TYPE_ANY,
//keywords and reserved words
TOY_TOKEN_KEYWORD_AS,
TOY_TOKEN_KEYWORD_AS, //unused
TOY_TOKEN_KEYWORD_ASSERT,
TOY_TOKEN_KEYWORD_BREAK,
TOY_TOKEN_KEYWORD_CLASS,
TOY_TOKEN_KEYWORD_CLASS, //unused
TOY_TOKEN_KEYWORD_CONST,
TOY_TOKEN_KEYWORD_CONTINUE,
TOY_TOKEN_KEYWORD_DO,
TOY_TOKEN_KEYWORD_DO, //unused
TOY_TOKEN_KEYWORD_ELSE,
TOY_TOKEN_KEYWORD_EXPORT,
TOY_TOKEN_KEYWORD_FOR,
TOY_TOKEN_KEYWORD_FOREACH,
TOY_TOKEN_KEYWORD_FUNCTION,
TOY_TOKEN_KEYWORD_EXPORT, //unused
TOY_TOKEN_KEYWORD_FOR, //unused
TOY_TOKEN_KEYWORD_FOREACH, //unused
TOY_TOKEN_KEYWORD_FUNCTION, //remapped 'fn'
TOY_TOKEN_KEYWORD_IF,
TOY_TOKEN_KEYWORD_IMPORT,
TOY_TOKEN_KEYWORD_IN,
TOY_TOKEN_KEYWORD_OF,
TOY_TOKEN_KEYWORD_IMPORT, //unused
TOY_TOKEN_KEYWORD_IN, //unused
TOY_TOKEN_KEYWORD_OF, //unused
TOY_TOKEN_KEYWORD_PASS,
TOY_TOKEN_KEYWORD_PRINT,
TOY_TOKEN_KEYWORD_RETURN,
TOY_TOKEN_KEYWORD_VAR,
TOY_TOKEN_KEYWORD_WHILE,
TOY_TOKEN_KEYWORD_YIELD,
TOY_TOKEN_KEYWORD_YIELD, //unused
//literal values
TOY_TOKEN_LITERAL_TRUE,
@@ -51,19 +51,19 @@ typedef enum Toy_TokenType {
TOY_TOKEN_LITERAL_STRING,
//math operators
TOY_TOKEN_OPERATOR_ADD,
TOY_TOKEN_OPERATOR_SUBTRACT,
TOY_TOKEN_OPERATOR_MULTIPLY,
TOY_TOKEN_OPERATOR_DIVIDE,
TOY_TOKEN_OPERATOR_MODULO,
TOY_TOKEN_OPERATOR_ADD_ASSIGN,
TOY_TOKEN_OPERATOR_SUBTRACT_ASSIGN,
TOY_TOKEN_OPERATOR_MULTIPLY_ASSIGN,
TOY_TOKEN_OPERATOR_DIVIDE_ASSIGN,
TOY_TOKEN_OPERATOR_MODULO_ASSIGN,
TOY_TOKEN_OPERATOR_INCREMENT,
TOY_TOKEN_OPERATOR_DECREMENT,
TOY_TOKEN_OPERATOR_ASSIGN,
TOY_TOKEN_OPERATOR_ADD, // +
TOY_TOKEN_OPERATOR_SUBTRACT, // -
TOY_TOKEN_OPERATOR_MULTIPLY, // *
TOY_TOKEN_OPERATOR_DIVIDE, // /
TOY_TOKEN_OPERATOR_MODULO, // %
TOY_TOKEN_OPERATOR_ADD_ASSIGN, // +=
TOY_TOKEN_OPERATOR_SUBTRACT_ASSIGN, // -=
TOY_TOKEN_OPERATOR_MULTIPLY_ASSIGN, // *=
TOY_TOKEN_OPERATOR_DIVIDE_ASSIGN, // /=
TOY_TOKEN_OPERATOR_MODULO_ASSIGN, // %=
TOY_TOKEN_OPERATOR_INCREMENT, // ++
TOY_TOKEN_OPERATOR_DECREMENT, // --
TOY_TOKEN_OPERATOR_ASSIGN, // =
//comparator operators
TOY_TOKEN_OPERATOR_COMPARE_EQUAL, // ==
@@ -74,12 +74,12 @@ typedef enum Toy_TokenType {
TOY_TOKEN_OPERATOR_COMPARE_GREATER_EQUAL, // >=
//structural operators
TOY_TOKEN_OPERATOR_PAREN_LEFT,
TOY_TOKEN_OPERATOR_PAREN_RIGHT,
TOY_TOKEN_OPERATOR_BRACKET_LEFT,
TOY_TOKEN_OPERATOR_BRACKET_RIGHT,
TOY_TOKEN_OPERATOR_BRACE_LEFT,
TOY_TOKEN_OPERATOR_BRACE_RIGHT,
TOY_TOKEN_OPERATOR_PAREN_LEFT, // (
TOY_TOKEN_OPERATOR_PAREN_RIGHT, // )
TOY_TOKEN_OPERATOR_BRACKET_LEFT, // [
TOY_TOKEN_OPERATOR_BRACKET_RIGHT, // ]
TOY_TOKEN_OPERATOR_BRACE_LEFT, // {
TOY_TOKEN_OPERATOR_BRACE_RIGHT, // }
//other operators
TOY_TOKEN_OPERATOR_AND, // &&
@@ -100,7 +100,7 @@ typedef enum Toy_TokenType {
TOY_TOKEN_OPERATOR_PIPE, // |
//meta tokens
TOY_TOKEN_ERROR,
TOY_TOKEN_EOF,
TOY_TOKEN_ERROR, //meta
TOY_TOKEN_EOF, //meta
} Toy_TokenType;
+1 -1
View File
@@ -718,7 +718,7 @@ static void processAssert(Toy_VM* vm) {
//determine the args
if (count == 1) {
message = TOY_VALUE_FROM_STRING(Toy_toString(&vm->memoryBucket, "assertion failed"));
message = TOY_VALUE_FROM_STRING(Toy_toString(&vm->memoryBucket, "assertion failed")); //TODO: better default error message
value = Toy_popStack(&vm->stack);
}
else if (count == 2) {
@@ -0,0 +1,11 @@
fn a(x) {
assert x == 42;
}
fn b() {
return 42;
}
a(b());
+1
View File
@@ -0,0 +1 @@
pass;
+8
View File
@@ -0,0 +1,8 @@
fn empty() { //BUG: there's an extra return in the bytecode
return;
}
fn full() {
return 42;
}