Compare commits
1 Commits
750ebd1f99
...
v2
| Author | SHA1 | Date | |
|---|---|---|---|
| 813da3e1aa |
@@ -147,6 +147,16 @@ void Toy_private_emitAstWhileThen(Toy_Bucket** bucketHandle, Toy_Ast** astHandle
|
||||
(*astHandle) = tmp;
|
||||
}
|
||||
|
||||
void Toy_private_emitAstForThen(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_Ast* condBranch, Toy_Ast* thenBranch) {
|
||||
Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucketHandle, sizeof(Toy_Ast));
|
||||
|
||||
tmp->type = TOY_AST_FOR_THEN;
|
||||
tmp->forThen.condBranch = condBranch;
|
||||
tmp->forThen.thenBranch = thenBranch;
|
||||
|
||||
(*astHandle) = tmp;
|
||||
}
|
||||
|
||||
void Toy_private_emitAstBreak(Toy_Bucket** bucketHandle, Toy_Ast** astHandle) {
|
||||
Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucketHandle, sizeof(Toy_Ast));
|
||||
|
||||
@@ -244,6 +254,16 @@ void Toy_private_emitAstAttribute(Toy_Bucket** bucketHandle, Toy_Ast** astHandle
|
||||
(*astHandle) = tmp;
|
||||
}
|
||||
|
||||
void Toy_private_emitAstIterable(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_Ast* expr) {
|
||||
Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucketHandle, sizeof(Toy_Ast));
|
||||
|
||||
tmp->type = TOY_AST_ITERABLE;
|
||||
tmp->iterable.left = (*astHandle);
|
||||
tmp->iterable.right = expr;
|
||||
|
||||
(*astHandle) = tmp;
|
||||
}
|
||||
|
||||
void Toy_private_emitAstStackPop(Toy_Bucket** bucketHandle, Toy_Ast** astHandle) {
|
||||
Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucketHandle, sizeof(Toy_Ast));
|
||||
|
||||
@@ -293,6 +313,7 @@ const char* Toy_private_getAstTypeAsCString(Toy_AstType type) {
|
||||
case TOY_AST_ASSERT: return "ASSERT";
|
||||
case TOY_AST_IF_THEN_ELSE: return "IF_THEN_ELSE";
|
||||
case TOY_AST_WHILE_THEN: return "WHILE_THEN";
|
||||
case TOY_AST_FOR_THEN: return "FOR_THEN";
|
||||
case TOY_AST_BREAK: return "BREAK";
|
||||
case TOY_AST_CONTINUE: return "CONTINUE";
|
||||
case TOY_AST_RETURN: return "RETURN";
|
||||
@@ -305,6 +326,7 @@ const char* Toy_private_getAstTypeAsCString(Toy_AstType type) {
|
||||
case TOY_AST_FN_DECLARE: return "FN_DECLARE";
|
||||
case TOY_AST_FN_INVOKE: return "FN_INVOKE";
|
||||
case TOY_AST_ATTRIBUTE: return "ATTRIBUTE";
|
||||
case TOY_AST_ITERABLE: return "ITERABLE";
|
||||
|
||||
case TOY_AST_STACK_POP: return "STACK_POP";
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ typedef enum Toy_AstType {
|
||||
TOY_AST_ASSERT,
|
||||
TOY_AST_IF_THEN_ELSE,
|
||||
TOY_AST_WHILE_THEN,
|
||||
TOY_AST_FOR_THEN,
|
||||
TOY_AST_BREAK,
|
||||
TOY_AST_CONTINUE,
|
||||
TOY_AST_RETURN,
|
||||
@@ -34,6 +35,7 @@ typedef enum Toy_AstType {
|
||||
TOY_AST_FN_DECLARE,
|
||||
TOY_AST_FN_INVOKE,
|
||||
TOY_AST_ATTRIBUTE,
|
||||
TOY_AST_ITERABLE,
|
||||
|
||||
TOY_AST_STACK_POP, //BUGFIX: force a single stack pop for expression statements
|
||||
|
||||
@@ -171,6 +173,12 @@ typedef struct Toy_AstWhileThen {
|
||||
Toy_Ast* thenBranch;
|
||||
} Toy_AstWhileThen;
|
||||
|
||||
typedef struct Toy_AstForThen {
|
||||
Toy_AstType type;
|
||||
Toy_Ast* condBranch;
|
||||
Toy_Ast* thenBranch;
|
||||
} Toy_AstForThen;
|
||||
|
||||
typedef struct Toy_AstBreak {
|
||||
Toy_AstType type;
|
||||
} Toy_AstBreak;
|
||||
@@ -228,6 +236,12 @@ typedef struct Toy_AstAttribute {
|
||||
Toy_Ast* right;
|
||||
} Toy_AstAttribute;
|
||||
|
||||
typedef struct Toy_AstIterable {
|
||||
Toy_AstType type;
|
||||
Toy_Ast* left;
|
||||
Toy_Ast* right;
|
||||
} Toy_AstIterable;
|
||||
|
||||
typedef struct Toy_AstStackPop {
|
||||
Toy_AstType type;
|
||||
Toy_Ast* child;
|
||||
@@ -259,6 +273,7 @@ union Toy_Ast { //see 'test_ast.c' for bitness tests
|
||||
Toy_AstAssert assert;
|
||||
Toy_AstIfThenElse ifThenElse;
|
||||
Toy_AstWhileThen whileThen;
|
||||
Toy_AstForThen forThen;
|
||||
Toy_AstBreak breakPoint;
|
||||
Toy_AstContinue continuePoint;
|
||||
Toy_AstReturn fnReturn;
|
||||
@@ -269,6 +284,7 @@ union Toy_Ast { //see 'test_ast.c' for bitness tests
|
||||
Toy_AstFnDeclare fnDeclare;
|
||||
Toy_AstFnInvoke fnInvoke;
|
||||
Toy_AstAttribute attribute;
|
||||
Toy_AstIterable iterable;
|
||||
Toy_AstStackPop stackPop;
|
||||
Toy_AstPass pass;
|
||||
Toy_AstError error;
|
||||
@@ -290,6 +306,7 @@ void Toy_private_emitAstAggregate(Toy_Bucket** bucketHandle, Toy_Ast** astHandle
|
||||
void Toy_private_emitAstAssert(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_Ast* child, Toy_Ast* msg);
|
||||
void Toy_private_emitAstIfThenElse(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_Ast* condBranch, Toy_Ast* thenBranch, Toy_Ast* elseBranch);
|
||||
void Toy_private_emitAstWhileThen(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_Ast* condBranch, Toy_Ast* thenBranch);
|
||||
void Toy_private_emitAstForThen(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_Ast* condBranch, Toy_Ast* thenBranch);
|
||||
void Toy_private_emitAstBreak(Toy_Bucket** bucketHandle, Toy_Ast** rootHandle);
|
||||
void Toy_private_emitAstContinue(Toy_Bucket** bucketHandle, Toy_Ast** rootHandle);
|
||||
void Toy_private_emitAstReturn(Toy_Bucket** bucketHandle, Toy_Ast** astHandle);
|
||||
@@ -302,6 +319,7 @@ void Toy_private_emitAstVariableAccess(Toy_Bucket** bucketHandle, Toy_Ast** astH
|
||||
void Toy_private_emitAstFunctionDeclaration(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_String* name, Toy_Ast* params, Toy_Ast* body);
|
||||
void Toy_private_emitAstFunctionInvokation(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_Ast* params);
|
||||
void Toy_private_emitAstAttribute(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_Ast* expr);
|
||||
void Toy_private_emitAstIterable(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_Ast* expr);
|
||||
|
||||
void Toy_private_emitAstStackPop(Toy_Bucket** bucketHandle, Toy_Ast** astHandle);
|
||||
|
||||
|
||||
@@ -91,6 +91,7 @@ static void attr_arrayPopBack(Toy_VM* vm, Toy_FunctionNative* self) {
|
||||
}
|
||||
|
||||
static void attr_arrayForEach(Toy_VM* vm, Toy_FunctionNative* self) {
|
||||
//URGENT: replace with for-loop
|
||||
(void)self;
|
||||
|
||||
Toy_Value compound = Toy_popStack(&vm->stack);
|
||||
@@ -241,7 +242,7 @@ static void attr_tableForEach(Toy_VM* vm, Toy_FunctionNative* self) {
|
||||
(void)vm;
|
||||
(void)self;
|
||||
|
||||
//URGENT: attr_tableForEach
|
||||
//URGENT: replace with for-loop
|
||||
}
|
||||
|
||||
Toy_Value Toy_private_handleTableAttributes(Toy_VM* vm, Toy_Value compound, Toy_Value attribute) {
|
||||
|
||||
@@ -718,6 +718,15 @@ static unsigned int writeInstructionWhileThen(Toy_Bytecode** mb, Toy_AstWhileThe
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int writeInstructionForThen(Toy_Bytecode** mb, Toy_AstForThen ast) {
|
||||
//URGENT: WIP
|
||||
(void)mb;
|
||||
(void)ast;
|
||||
|
||||
(*mb)->panic = true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static unsigned int writeInstructionBreak(Toy_Bytecode** mb, Toy_AstBreak ast) {
|
||||
//unused
|
||||
(void)ast;
|
||||
@@ -1244,6 +1253,10 @@ static unsigned int writeBytecodeFromAst(Toy_Bytecode** mb, Toy_Ast* ast) {
|
||||
result += writeInstructionWhileThen(mb, ast->whileThen);
|
||||
break;
|
||||
|
||||
case TOY_AST_FOR_THEN:
|
||||
result += writeInstructionForThen(mb, ast->forThen);
|
||||
break;
|
||||
|
||||
case TOY_AST_BREAK:
|
||||
result += writeInstructionBreak(mb, ast->breakPoint);
|
||||
break;
|
||||
@@ -1284,6 +1297,12 @@ static unsigned int writeBytecodeFromAst(Toy_Bytecode** mb, Toy_Ast* ast) {
|
||||
result += writeInstructionAttribute(mb, ast->attribute);
|
||||
break;
|
||||
|
||||
case TOY_AST_ITERABLE:
|
||||
//the 'in' keyword is only valid within a for-loop's condition
|
||||
fprintf(stderr, TOY_CC_ERROR "COMPILER ERROR: the 'in' keyword is only valid within a for-loop's condition\n" TOY_CC_RESET);
|
||||
(*mb)->panic = true;
|
||||
break;
|
||||
|
||||
case TOY_AST_STACK_POP:
|
||||
result += writeInstructionStackPop(mb, ast->stackPop);
|
||||
break;
|
||||
|
||||
@@ -12,6 +12,7 @@ typedef enum Toy_OpcodeType {
|
||||
TOY_OPCODE_ACCESS,
|
||||
TOY_OPCODE_INVOKE, //for calling functions
|
||||
TOY_OPCODE_ATTRIBUTE, //for accessing parts of compounds
|
||||
TOY_OPCODE_ITERABLE, //for operating on all members of a compound
|
||||
TOY_OPCODE_DUPLICATE, //duplicate the top of the stack
|
||||
TOY_OPCODE_ELIMINATE, //remove the top of the stack
|
||||
|
||||
|
||||
+37
-2
@@ -122,6 +122,7 @@ static Toy_AstFlag aggregate(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_
|
||||
static Toy_AstFlag unaryPostfix(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle);
|
||||
static Toy_AstFlag invoke(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle);
|
||||
static Toy_AstFlag attribute(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle);
|
||||
static Toy_AstFlag iterable(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle);
|
||||
|
||||
//precedence definitions
|
||||
static ParsingTuple parsingRulesetTable[] = {
|
||||
@@ -156,7 +157,7 @@ static ParsingTuple parsingRulesetTable[] = {
|
||||
{PREC_NONE,NULL,NULL},// TOY_TOKEN_KEYWORD_FUNCTION,
|
||||
{PREC_NONE,NULL,NULL},// TOY_TOKEN_KEYWORD_IF,
|
||||
{PREC_NONE,NULL,NULL},// TOY_TOKEN_KEYWORD_IMPORT,
|
||||
{PREC_NONE,NULL,NULL},// TOY_TOKEN_KEYWORD_IN,
|
||||
{PREC_CALL,NULL,iterable},// TOY_TOKEN_KEYWORD_IN,
|
||||
{PREC_NONE,NULL,NULL},// TOY_TOKEN_KEYWORD_OF,
|
||||
{PREC_NONE,NULL,NULL},// TOY_TOKEN_KEYWORD_PASS,
|
||||
{PREC_NONE,NULL,NULL},// TOY_TOKEN_KEYWORD_PRINT,
|
||||
@@ -760,6 +761,19 @@ static Toy_AstFlag attribute(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_
|
||||
}
|
||||
}
|
||||
|
||||
static Toy_AstFlag iterable(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle) {
|
||||
//infix must advance
|
||||
advance(parser);
|
||||
|
||||
Toy_Ast* expr = NULL;
|
||||
parsePrecedence(bucketHandle, parser, &expr, PREC_CALL);
|
||||
Toy_private_emitAstIterable(bucketHandle, rootHandle, expr);
|
||||
|
||||
//TODO: check for var declare without assignment
|
||||
|
||||
return TOY_AST_FLAG_NONE;
|
||||
}
|
||||
|
||||
//grammar rules
|
||||
static void parsePrecedence(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle, ParsingPrecedence precRule) {
|
||||
//'step over' the token to parse
|
||||
@@ -891,6 +905,23 @@ static void makeWhileStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast
|
||||
Toy_private_emitAstWhileThen(bucketHandle, rootHandle, condBranch, thenBranch);
|
||||
}
|
||||
|
||||
static void makeForStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle) {
|
||||
Toy_Ast* condBranch = NULL;
|
||||
Toy_Ast* thenBranch = NULL;
|
||||
|
||||
//for (condBranch)
|
||||
consume(parser, TOY_TOKEN_OPERATOR_PAREN_LEFT, "Expected '(' after 'for' keyword");
|
||||
makeExpr(bucketHandle, parser, &condBranch);
|
||||
consume(parser, TOY_TOKEN_OPERATOR_PAREN_RIGHT, "Expected ')' after 'for' condition");
|
||||
|
||||
//TODO: check for an iterable node
|
||||
|
||||
//{ thenBranch }
|
||||
makeDeclarationStmt(bucketHandle, parser, &thenBranch, true);
|
||||
|
||||
Toy_private_emitAstForThen(bucketHandle, rootHandle, condBranch, thenBranch);
|
||||
}
|
||||
|
||||
static void makeBreakStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle) {
|
||||
Toy_private_emitAstBreak(bucketHandle, rootHandle);
|
||||
consume(parser, TOY_TOKEN_OPERATOR_SEMICOLON, "Expected ';' at the end of break statement");
|
||||
@@ -1070,7 +1101,11 @@ static void makeStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** ro
|
||||
return;
|
||||
}
|
||||
|
||||
//URGENT: for-pre-clause-post-then
|
||||
//for
|
||||
else if (match(parser, TOY_TOKEN_KEYWORD_FOR)) {
|
||||
makeForStmt(bucketHandle, parser, rootHandle);
|
||||
return;
|
||||
}
|
||||
|
||||
//break
|
||||
else if (match(parser, TOY_TOKEN_KEYWORD_BREAK)) {
|
||||
|
||||
@@ -29,7 +29,7 @@ typedef enum Toy_TokenType {
|
||||
TOY_TOKEN_KEYWORD_DO, //unused
|
||||
TOY_TOKEN_KEYWORD_ELSE,
|
||||
TOY_TOKEN_KEYWORD_EXPORT, //unused
|
||||
TOY_TOKEN_KEYWORD_FOR, //unused
|
||||
TOY_TOKEN_KEYWORD_FOR,
|
||||
TOY_TOKEN_KEYWORD_FOREACH, //unused
|
||||
TOY_TOKEN_KEYWORD_FUNCTION, //remapped 'fn'
|
||||
TOY_TOKEN_KEYWORD_IF,
|
||||
|
||||
@@ -1060,6 +1060,7 @@ static unsigned int process(Toy_VM* vm) {
|
||||
processIndex(vm);
|
||||
break;
|
||||
|
||||
case TOY_OPCODE_ITERABLE: //tmp
|
||||
case TOY_OPCODE_UNUSED:
|
||||
case TOY_OPCODE_PASS:
|
||||
case TOY_OPCODE_ERROR:
|
||||
|
||||
Reference in New Issue
Block a user