mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 23:04:08 +10:00
While is working but untested, read more
* TODO: break and continue keywords need to be implemented * TODO: while-then needs testing * Fixed the parser not liking zero-length strings
This commit is contained in:
27
scripts/fizzbuzz.toy
Normal file
27
scripts/fizzbuzz.toy
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
|
||||||
|
//moment of truth
|
||||||
|
var counter: int = 1;
|
||||||
|
|
||||||
|
while (counter <= 100) {
|
||||||
|
var result: string = "";
|
||||||
|
|
||||||
|
if (counter % 3 == 0) {
|
||||||
|
result = result .. "fizz";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (counter % 5 == 0) {
|
||||||
|
result = result .. "buzz";
|
||||||
|
}
|
||||||
|
|
||||||
|
//finally
|
||||||
|
if (result == "") {
|
||||||
|
print counter;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print result;
|
||||||
|
}
|
||||||
|
|
||||||
|
counter += 1;
|
||||||
|
}
|
||||||
|
|
||||||
9
scripts/looping.toy
Normal file
9
scripts/looping.toy
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
var a: int = 0;
|
||||||
|
|
||||||
|
while(a < 10) {
|
||||||
|
print a;
|
||||||
|
a += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
print "Finished";
|
||||||
|
|
||||||
@@ -116,6 +116,16 @@ void Toy_private_emitAstIfThenElse(Toy_Bucket** bucketHandle, Toy_Ast** astHandl
|
|||||||
(*astHandle) = tmp;
|
(*astHandle) = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Toy_private_emitAstWhileThen(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_WHILE_THEN;
|
||||||
|
tmp->whileThen.condBranch = condBranch;
|
||||||
|
tmp->whileThen.thenBranch = thenBranch;
|
||||||
|
|
||||||
|
(*astHandle) = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
void Toy_private_emitAstPrint(Toy_Bucket** bucketHandle, Toy_Ast** astHandle) {
|
void Toy_private_emitAstPrint(Toy_Bucket** bucketHandle, Toy_Ast** astHandle) {
|
||||||
Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucketHandle, sizeof(Toy_Ast));
|
Toy_Ast* tmp = (Toy_Ast*)Toy_partitionBucket(bucketHandle, sizeof(Toy_Ast));
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ typedef enum Toy_AstType {
|
|||||||
|
|
||||||
TOY_AST_ASSERT,
|
TOY_AST_ASSERT,
|
||||||
TOY_AST_IF_THEN_ELSE,
|
TOY_AST_IF_THEN_ELSE,
|
||||||
|
TOY_AST_WHILE_THEN,
|
||||||
TOY_AST_PRINT,
|
TOY_AST_PRINT,
|
||||||
|
|
||||||
TOY_AST_VAR_DECLARE,
|
TOY_AST_VAR_DECLARE,
|
||||||
@@ -131,6 +132,12 @@ typedef struct Toy_AstIfThenElse {
|
|||||||
Toy_Ast* elseBranch;
|
Toy_Ast* elseBranch;
|
||||||
} Toy_AstIfThenElse;
|
} Toy_AstIfThenElse;
|
||||||
|
|
||||||
|
typedef struct Toy_AstWhileThen {
|
||||||
|
Toy_AstType type;
|
||||||
|
Toy_Ast* condBranch;
|
||||||
|
Toy_Ast* thenBranch;
|
||||||
|
} Toy_AstWhileThen;
|
||||||
|
|
||||||
typedef struct Toy_AstPrint {
|
typedef struct Toy_AstPrint {
|
||||||
Toy_AstType type;
|
Toy_AstType type;
|
||||||
Toy_Ast* child;
|
Toy_Ast* child;
|
||||||
@@ -177,6 +184,7 @@ union Toy_Ast { //32 | 64 BITNESS
|
|||||||
Toy_AstCompound compound; //16 | 24
|
Toy_AstCompound compound; //16 | 24
|
||||||
Toy_AstAssert assert; //16 | 24
|
Toy_AstAssert assert; //16 | 24
|
||||||
Toy_AstIfThenElse ifThenElse; //16 | 32
|
Toy_AstIfThenElse ifThenElse; //16 | 32
|
||||||
|
Toy_AstWhileThen whileThen; //16 | 24
|
||||||
Toy_AstPrint print; //8 | 16
|
Toy_AstPrint print; //8 | 16
|
||||||
Toy_AstVarDeclare varDeclare; //16 | 24
|
Toy_AstVarDeclare varDeclare; //16 | 24
|
||||||
Toy_AstVarAssign varAssign; //16 | 24
|
Toy_AstVarAssign varAssign; //16 | 24
|
||||||
@@ -198,6 +206,7 @@ void Toy_private_emitAstCompound(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_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_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_emitAstPrint(Toy_Bucket** bucketHandle, Toy_Ast** astHandle);
|
void Toy_private_emitAstPrint(Toy_Bucket** bucketHandle, Toy_Ast** astHandle);
|
||||||
|
|
||||||
void Toy_private_emitAstVariableDeclaration(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_String* name, Toy_Ast* expr);
|
void Toy_private_emitAstVariableDeclaration(Toy_Bucket** bucketHandle, Toy_Ast** astHandle, Toy_String* name, Toy_Ast* expr);
|
||||||
|
|||||||
@@ -352,8 +352,9 @@ static Toy_AstFlag literal(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_As
|
|||||||
case TOY_TOKEN_LITERAL_STRING: {
|
case TOY_TOKEN_LITERAL_STRING: {
|
||||||
char buffer[parser->previous.length + 1];
|
char buffer[parser->previous.length + 1];
|
||||||
unsigned int escapeCounter = 0;
|
unsigned int escapeCounter = 0;
|
||||||
|
|
||||||
unsigned int i = 0, o = 0;
|
unsigned int i = 0, o = 0;
|
||||||
|
|
||||||
|
if (parser->previous.length > 0) { //BUGFIX: compensate for zero-length strings
|
||||||
do {
|
do {
|
||||||
buffer[i] = parser->previous.lexeme[o];
|
buffer[i] = parser->previous.lexeme[o];
|
||||||
if (buffer[i] == '\\' && parser->previous.lexeme[++o]) {
|
if (buffer[i] == '\\' && parser->previous.lexeme[++o]) {
|
||||||
@@ -377,6 +378,7 @@ static Toy_AstFlag literal(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_As
|
|||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
} while (parser->previous.lexeme[o++] && i < parser->previous.length);
|
} while (parser->previous.lexeme[o++] && i < parser->previous.length);
|
||||||
|
}
|
||||||
|
|
||||||
buffer[i] = '\0';
|
buffer[i] = '\0';
|
||||||
unsigned int len = i - escapeCounter; //NOTE: len is ONLY the string length
|
unsigned int len = i - escapeCounter; //NOTE: len is ONLY the string length
|
||||||
@@ -699,6 +701,21 @@ static void makeIfThenElseStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, To
|
|||||||
Toy_private_emitAstIfThenElse(bucketHandle, rootHandle, condBranch, thenBranch, elseBranch);
|
Toy_private_emitAstIfThenElse(bucketHandle, rootHandle, condBranch, thenBranch, elseBranch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void makeWhileStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle) {
|
||||||
|
Toy_Ast* condBranch = NULL;
|
||||||
|
Toy_Ast* thenBranch = NULL;
|
||||||
|
|
||||||
|
//while (condBranch)
|
||||||
|
consume(parser, TOY_TOKEN_OPERATOR_PAREN_LEFT, "Expected '(' after 'while' keyword");
|
||||||
|
makeExpr(bucketHandle, parser, &condBranch);
|
||||||
|
consume(parser, TOY_TOKEN_OPERATOR_PAREN_RIGHT, "Expected ')' after 'while' condition");
|
||||||
|
|
||||||
|
// { thenBranch }
|
||||||
|
makeDeclarationStmt(bucketHandle, parser, &thenBranch);
|
||||||
|
|
||||||
|
Toy_private_emitAstWhileThen(bucketHandle, rootHandle, condBranch, thenBranch);
|
||||||
|
}
|
||||||
|
|
||||||
static void makePrintStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle) {
|
static void makePrintStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle) {
|
||||||
makeExpr(bucketHandle, parser, rootHandle);
|
makeExpr(bucketHandle, parser, rootHandle);
|
||||||
Toy_private_emitAstPrint(bucketHandle, rootHandle);
|
Toy_private_emitAstPrint(bucketHandle, rootHandle);
|
||||||
@@ -771,10 +788,15 @@ static void makeStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** ro
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: break & continue
|
||||||
|
|
||||||
//while-then
|
//while-then
|
||||||
|
else if (match(parser, TOY_TOKEN_KEYWORD_WHILE)) {
|
||||||
|
makeWhileStmt(bucketHandle, parser, rootHandle);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//for-pre-clause-post-then
|
//for-pre-clause-post-then
|
||||||
//break
|
|
||||||
//continue
|
|
||||||
//return
|
//return
|
||||||
//import
|
//import
|
||||||
|
|
||||||
|
|||||||
@@ -319,7 +319,7 @@ static unsigned int writeInstructionIfThenElse(Toy_Routine** rt, Toy_AstIfThenEl
|
|||||||
|
|
||||||
unsigned int thenEndAddr = SKIP_INT(rt, code); //parameter to be written later
|
unsigned int thenEndAddr = SKIP_INT(rt, code); //parameter to be written later
|
||||||
|
|
||||||
//emit then branch
|
//emit then-branch
|
||||||
writeRoutineCode(rt, ast.thenBranch);
|
writeRoutineCode(rt, ast.thenBranch);
|
||||||
|
|
||||||
if (ast.elseBranch != NULL) {
|
if (ast.elseBranch != NULL) {
|
||||||
@@ -349,6 +349,37 @@ static unsigned int writeInstructionIfThenElse(Toy_Routine** rt, Toy_AstIfThenEl
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned int writeInstructionWhileThen(Toy_Routine** rt, Toy_AstWhileThen ast) {
|
||||||
|
//TODO: begin
|
||||||
|
unsigned int beginAddr = CURRENT_ADDRESS(rt, code);
|
||||||
|
|
||||||
|
//cond-branch
|
||||||
|
writeRoutineCode(rt, ast.condBranch);
|
||||||
|
|
||||||
|
//emit the jump word (opcode, type, condition, padding)
|
||||||
|
EMIT_BYTE(rt, code, TOY_OPCODE_JUMP);
|
||||||
|
EMIT_BYTE(rt, code, TOY_OP_PARAM_JUMP_RELATIVE);
|
||||||
|
EMIT_BYTE(rt, code, TOY_OP_PARAM_JUMP_IF_FALSE);
|
||||||
|
EMIT_BYTE(rt, code, 0);
|
||||||
|
|
||||||
|
unsigned int endAddr = SKIP_INT(rt, code); //parameter to be written later
|
||||||
|
|
||||||
|
//emit then-branch
|
||||||
|
writeRoutineCode(rt, ast.thenBranch);
|
||||||
|
|
||||||
|
//jump to begin to repeat the conditional test
|
||||||
|
EMIT_BYTE(rt, code, TOY_OPCODE_JUMP);
|
||||||
|
EMIT_BYTE(rt, code, TOY_OP_PARAM_JUMP_RELATIVE);
|
||||||
|
EMIT_BYTE(rt, code, TOY_OP_PARAM_JUMP_ALWAYS);
|
||||||
|
EMIT_BYTE(rt, code, 0);
|
||||||
|
|
||||||
|
EMIT_INT(rt, code, beginAddr - (CURRENT_ADDRESS(rt, code) + 4)); //this sets a negative value
|
||||||
|
|
||||||
|
OVERWRITE_INT(rt, code, endAddr, CURRENT_ADDRESS(rt, code) - (endAddr + 4));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned int writeInstructionPrint(Toy_Routine** rt, Toy_AstPrint ast) {
|
static unsigned int writeInstructionPrint(Toy_Routine** rt, Toy_AstPrint ast) {
|
||||||
//the thing to print
|
//the thing to print
|
||||||
writeRoutineCode(rt, ast.child);
|
writeRoutineCode(rt, ast.child);
|
||||||
@@ -603,6 +634,10 @@ static unsigned int writeRoutineCode(Toy_Routine** rt, Toy_Ast* ast) {
|
|||||||
result += writeInstructionIfThenElse(rt, ast->ifThenElse);
|
result += writeInstructionIfThenElse(rt, ast->ifThenElse);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TOY_AST_WHILE_THEN:
|
||||||
|
result += writeInstructionWhileThen(rt, ast->whileThen);
|
||||||
|
break;
|
||||||
|
|
||||||
case TOY_AST_PRINT:
|
case TOY_AST_PRINT:
|
||||||
result += writeInstructionPrint(rt, ast->print);
|
result += writeInstructionPrint(rt, ast->print);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ int test_sizeof_ast_64bit() {
|
|||||||
TEST_SIZEOF(Toy_AstCompound, 24);
|
TEST_SIZEOF(Toy_AstCompound, 24);
|
||||||
TEST_SIZEOF(Toy_AstAssert, 24);
|
TEST_SIZEOF(Toy_AstAssert, 24);
|
||||||
TEST_SIZEOF(Toy_AstIfThenElse, 32);
|
TEST_SIZEOF(Toy_AstIfThenElse, 32);
|
||||||
|
TEST_SIZEOF(Toy_AstWhileThen, 24);
|
||||||
TEST_SIZEOF(Toy_AstPrint, 16);
|
TEST_SIZEOF(Toy_AstPrint, 16);
|
||||||
TEST_SIZEOF(Toy_AstVarDeclare, 24);
|
TEST_SIZEOF(Toy_AstVarDeclare, 24);
|
||||||
TEST_SIZEOF(Toy_AstVarAssign, 24);
|
TEST_SIZEOF(Toy_AstVarAssign, 24);
|
||||||
@@ -61,6 +62,7 @@ int test_sizeof_ast_32bit() {
|
|||||||
TEST_SIZEOF(Toy_AstCompound, 16);
|
TEST_SIZEOF(Toy_AstCompound, 16);
|
||||||
TEST_SIZEOF(Toy_AstAssert, 12);
|
TEST_SIZEOF(Toy_AstAssert, 12);
|
||||||
TEST_SIZEOF(Toy_AstIfThenElse, 16);
|
TEST_SIZEOF(Toy_AstIfThenElse, 16);
|
||||||
|
TEST_SIZEOF(Toy_AstWhileThen, 12);
|
||||||
TEST_SIZEOF(Toy_AstPrint, 8);
|
TEST_SIZEOF(Toy_AstPrint, 8);
|
||||||
TEST_SIZEOF(Toy_AstVarDeclare, 12);
|
TEST_SIZEOF(Toy_AstVarDeclare, 12);
|
||||||
TEST_SIZEOF(Toy_AstVarAssign, 16);
|
TEST_SIZEOF(Toy_AstVarAssign, 16);
|
||||||
|
|||||||
Reference in New Issue
Block a user