Fixed invoking functions within function arguments
Somewhat similar to c9d4b9965c
This commit is contained in:
@@ -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());
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
|
||||
|
||||
|
||||
if (true) {
|
||||
print "Who?";
|
||||
fn a(x) {
|
||||
print x;
|
||||
}
|
||||
else if (true) {
|
||||
print "What?";
|
||||
|
||||
fn b() {
|
||||
return 42;
|
||||
}
|
||||
else {
|
||||
print "IDK";
|
||||
}
|
||||
|
||||
a(b(), b());
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
+9
-5
@@ -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,10 +902,14 @@ static void makeContinueStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_
|
||||
}
|
||||
|
||||
static void makeReturnStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle) {
|
||||
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");
|
||||
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) {
|
||||
|
||||
+32
-32
@@ -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
@@ -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());
|
||||
@@ -0,0 +1 @@
|
||||
pass;
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
fn empty() { //BUG: there's an extra return in the bytecode
|
||||
return;
|
||||
}
|
||||
|
||||
fn full() {
|
||||
return 42;
|
||||
}
|
||||
Reference in New Issue
Block a user