mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 14:54:07 +10:00
Postfix '++' & '--' works (prefix & postfix are both tested)
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
//standard example, using 'while' instead of 'for', because it's not ready yet
|
//standard example, using 'while' instead of 'for', because it's not ready yet
|
||||||
|
|
||||||
var counter: int = 1;
|
var counter: int = 0;
|
||||||
|
|
||||||
while (counter <= 100) {
|
while (++counter <= 100) {
|
||||||
var result: string = "";
|
var result: string = "";
|
||||||
|
|
||||||
if (counter % 3 == 0) {
|
if (counter % 3 == 0) {
|
||||||
@@ -20,7 +20,5 @@ while (counter <= 100) {
|
|||||||
else {
|
else {
|
||||||
print counter;
|
print counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
counter += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,5 +9,18 @@
|
|||||||
assert --a == 42;
|
assert --a == 42;
|
||||||
assert a == 42;
|
assert a == 42;
|
||||||
|
|
||||||
|
print a;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//increment & decrement (postfix)
|
||||||
|
{
|
||||||
|
var a = 42;
|
||||||
|
assert a == 42;
|
||||||
|
assert a++ == 42;
|
||||||
|
assert a == 43;
|
||||||
|
assert a-- == 43;
|
||||||
|
assert a == 42;
|
||||||
|
|
||||||
print a;
|
print a;
|
||||||
}
|
}
|
||||||
@@ -46,6 +46,10 @@ typedef enum Toy_AstFlag {
|
|||||||
TOY_AST_FLAG_DIVIDE = 4,
|
TOY_AST_FLAG_DIVIDE = 4,
|
||||||
TOY_AST_FLAG_MODULO = 5,
|
TOY_AST_FLAG_MODULO = 5,
|
||||||
|
|
||||||
|
TOY_AST_FLAG_AND = 6,
|
||||||
|
TOY_AST_FLAG_OR = 7,
|
||||||
|
TOY_AST_FLAG_CONCAT = 8,
|
||||||
|
|
||||||
TOY_AST_FLAG_ASSIGN = 10,
|
TOY_AST_FLAG_ASSIGN = 10,
|
||||||
TOY_AST_FLAG_ADD_ASSIGN = 11,
|
TOY_AST_FLAG_ADD_ASSIGN = 11,
|
||||||
TOY_AST_FLAG_SUBTRACT_ASSIGN = 12,
|
TOY_AST_FLAG_SUBTRACT_ASSIGN = 12,
|
||||||
@@ -66,14 +70,12 @@ typedef enum Toy_AstFlag {
|
|||||||
TOY_AST_FLAG_PAIR = 33,
|
TOY_AST_FLAG_PAIR = 33,
|
||||||
TOY_AST_FLAG_INDEX = 34,
|
TOY_AST_FLAG_INDEX = 34,
|
||||||
|
|
||||||
TOY_AST_FLAG_AND = 40,
|
|
||||||
TOY_AST_FLAG_OR = 41,
|
|
||||||
TOY_AST_FLAG_CONCAT = 42,
|
|
||||||
|
|
||||||
//unary flags
|
//unary flags
|
||||||
TOY_AST_FLAG_NEGATE = 43,
|
TOY_AST_FLAG_NEGATE = 40,
|
||||||
TOY_AST_FLAG_PREFIX_INCREMENT = 44,
|
TOY_AST_FLAG_PREFIX_INCREMENT = 41,
|
||||||
TOY_AST_FLAG_PREFIX_DECREMENT = 45,
|
TOY_AST_FLAG_PREFIX_DECREMENT = 42,
|
||||||
|
TOY_AST_FLAG_POSTFIX_INCREMENT = 43,
|
||||||
|
TOY_AST_FLAG_POSTFIX_DECREMENT = 44,
|
||||||
|
|
||||||
// TOY_AST_FLAG_TERNARY,
|
// TOY_AST_FLAG_TERNARY,
|
||||||
} Toy_AstFlag;
|
} Toy_AstFlag;
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ static Toy_AstFlag binary(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast
|
|||||||
static Toy_AstFlag group(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle);
|
static Toy_AstFlag group(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle);
|
||||||
static Toy_AstFlag compound(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle);
|
static Toy_AstFlag compound(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle);
|
||||||
static Toy_AstFlag aggregate(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle);
|
static Toy_AstFlag aggregate(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle);
|
||||||
|
static Toy_AstFlag unaryPostfix(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle);
|
||||||
|
|
||||||
//precedence definitions
|
//precedence definitions
|
||||||
static ParsingTuple parsingRulesetTable[] = {
|
static ParsingTuple parsingRulesetTable[] = {
|
||||||
@@ -180,8 +181,8 @@ static ParsingTuple parsingRulesetTable[] = {
|
|||||||
{PREC_ASSIGNMENT,NULL,binary},// TOY_TOKEN_OPERATOR_MULTIPLY_ASSIGN,
|
{PREC_ASSIGNMENT,NULL,binary},// TOY_TOKEN_OPERATOR_MULTIPLY_ASSIGN,
|
||||||
{PREC_ASSIGNMENT,NULL,binary},// TOY_TOKEN_OPERATOR_DIVIDE_ASSIGN,
|
{PREC_ASSIGNMENT,NULL,binary},// TOY_TOKEN_OPERATOR_DIVIDE_ASSIGN,
|
||||||
{PREC_ASSIGNMENT,NULL,binary},// TOY_TOKEN_OPERATOR_MODULO_ASSIGN,
|
{PREC_ASSIGNMENT,NULL,binary},// TOY_TOKEN_OPERATOR_MODULO_ASSIGN,
|
||||||
{PREC_CALL,unary,NULL},// TOY_TOKEN_OPERATOR_INCREMENT,
|
{PREC_CALL,unary,unaryPostfix},// TOY_TOKEN_OPERATOR_INCREMENT,
|
||||||
{PREC_CALL,unary,NULL},// TOY_TOKEN_OPERATOR_DECREMENT,
|
{PREC_CALL,unary,unaryPostfix},// TOY_TOKEN_OPERATOR_DECREMENT,
|
||||||
{PREC_ASSIGNMENT,NULL,binary},// TOY_TOKEN_OPERATOR_ASSIGN,
|
{PREC_ASSIGNMENT,NULL,binary},// TOY_TOKEN_OPERATOR_ASSIGN,
|
||||||
|
|
||||||
//comparator operators
|
//comparator operators
|
||||||
@@ -223,6 +224,10 @@ static ParsingTuple parsingRulesetTable[] = {
|
|||||||
{PREC_NONE,NULL,NULL},// TOY_TOKEN_EOF,
|
{PREC_NONE,NULL,NULL},// TOY_TOKEN_EOF,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static ParsingTuple* getParsingRule(Toy_TokenType type) {
|
||||||
|
return &parsingRulesetTable[type];
|
||||||
|
}
|
||||||
|
|
||||||
static Toy_ValueType readType(Toy_Parser* parser) {
|
static Toy_ValueType readType(Toy_Parser* parser) {
|
||||||
advance(parser);
|
advance(parser);
|
||||||
|
|
||||||
@@ -429,7 +434,7 @@ static Toy_AstFlag unary(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast*
|
|||||||
|
|
||||||
//double check it's a name string within an access NOTE: doing some fiddling with the existing AST here
|
//double check it's a name string within an access NOTE: doing some fiddling with the existing AST here
|
||||||
if (primary->type != TOY_AST_VAR_ACCESS || primary->varAccess.child->type != TOY_AST_VALUE || TOY_VALUE_IS_STRING(primary->varAccess.child->value.value) != true || TOY_VALUE_AS_STRING(primary->varAccess.child->value.value)->info.type != TOY_STRING_NAME) {
|
if (primary->type != TOY_AST_VAR_ACCESS || primary->varAccess.child->type != TOY_AST_VALUE || TOY_VALUE_IS_STRING(primary->varAccess.child->value.value) != true || TOY_VALUE_AS_STRING(primary->varAccess.child->value.value)->info.type != TOY_STRING_NAME) {
|
||||||
printError(parser, parser->previous, "Unexpected non-name-string token in unary operator increment precedence rule");
|
printError(parser, parser->previous, "Unexpected non-name-string token in unary-prefix operator precedence rule");
|
||||||
Toy_private_emitAstError(bucketHandle, rootHandle);
|
Toy_private_emitAstError(bucketHandle, rootHandle);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -666,8 +671,41 @@ static Toy_AstFlag aggregate(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static ParsingTuple* getParsingRule(Toy_TokenType type) {
|
static Toy_AstFlag unaryPostfix(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** rootHandle) {
|
||||||
return &parsingRulesetTable[type];
|
//grab the var name, rejecting any other token types
|
||||||
|
if (parser->previous.type != TOY_TOKEN_NAME) {
|
||||||
|
printError(parser, parser->previous, "Unexpected parameter passed to unary-postfix precedence rule");
|
||||||
|
Toy_private_emitAstError(bucketHandle, rootHandle);
|
||||||
|
return TOY_AST_FLAG_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Ast* primary = NULL;
|
||||||
|
ParsingRule nameRule = getParsingRule(parser->previous.type)->prefix;
|
||||||
|
nameRule(bucketHandle, parser, &primary); //this is to skip the call to advance() at the beginning of parsePrecedence()
|
||||||
|
|
||||||
|
//double check it's a name string within an access NOTE: doing some fiddling with the existing AST here
|
||||||
|
if (primary->type != TOY_AST_VAR_ACCESS || primary->varAccess.child->type != TOY_AST_VALUE || TOY_VALUE_IS_STRING(primary->varAccess.child->value.value) != true || TOY_VALUE_AS_STRING(primary->varAccess.child->value.value)->info.type != TOY_STRING_NAME) {
|
||||||
|
printError(parser, parser->previous, "Unexpected non-name-string token in unary-postfix operator precedence rule");
|
||||||
|
Toy_private_emitAstError(bucketHandle, rootHandle);
|
||||||
|
return TOY_AST_FLAG_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*rootHandle) = primary->varAccess.child;
|
||||||
|
|
||||||
|
//output the postfix AST
|
||||||
|
if (match(parser, TOY_TOKEN_OPERATOR_INCREMENT)) {
|
||||||
|
Toy_private_emitAstUnary(bucketHandle, rootHandle, TOY_AST_FLAG_POSTFIX_INCREMENT);
|
||||||
|
return TOY_AST_FLAG_POSTFIX_INCREMENT;
|
||||||
|
}
|
||||||
|
else if (match(parser, TOY_TOKEN_OPERATOR_DECREMENT)) {
|
||||||
|
Toy_private_emitAstUnary(bucketHandle, rootHandle, TOY_AST_FLAG_POSTFIX_DECREMENT);
|
||||||
|
return TOY_AST_FLAG_POSTFIX_DECREMENT;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printError(parser, parser->previous, "Unexpected token passed to unary-postfix precedence rule");
|
||||||
|
Toy_private_emitAstError(bucketHandle, rootHandle);
|
||||||
|
return TOY_AST_FLAG_NONE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//grammar rules
|
//grammar rules
|
||||||
@@ -721,6 +759,10 @@ static void parsePrecedence(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_A
|
|||||||
else if (flag >= 30 && flag <= 39) {
|
else if (flag >= 30 && flag <= 39) {
|
||||||
Toy_private_emitAstAggregate(bucketHandle, rootHandle, flag, ptr);
|
Toy_private_emitAstAggregate(bucketHandle, rootHandle, flag, ptr);
|
||||||
}
|
}
|
||||||
|
else if (flag >= 40 && flag <= 49) {
|
||||||
|
(*rootHandle) = ptr;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
//BUGFIX: '&&' and '||' are special cases, with short-circuit logic
|
//BUGFIX: '&&' and '||' are special cases, with short-circuit logic
|
||||||
if (flag == TOY_AST_FLAG_AND || flag == TOY_AST_FLAG_OR) {
|
if (flag == TOY_AST_FLAG_AND || flag == TOY_AST_FLAG_OR) {
|
||||||
|
|||||||
@@ -224,6 +224,63 @@ static unsigned int writeInstructionUnary(Toy_Routine** rt, Toy_AstUnary ast) {
|
|||||||
result = 1;
|
result = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (ast.flag == TOY_AST_FLAG_POSTFIX_INCREMENT || ast.flag == TOY_AST_FLAG_POSTFIX_DECREMENT) { //NOTE: ditto
|
||||||
|
//read the var name onto the stack
|
||||||
|
Toy_String* name = TOY_VALUE_AS_STRING(ast.child->value.value);
|
||||||
|
|
||||||
|
EMIT_BYTE(rt, code, TOY_OPCODE_READ);
|
||||||
|
EMIT_BYTE(rt, code, TOY_VALUE_STRING);
|
||||||
|
EMIT_BYTE(rt, code, TOY_STRING_NAME);
|
||||||
|
EMIT_BYTE(rt, code, name->info.length); //store the length (max 255)
|
||||||
|
|
||||||
|
emitString(rt, name);
|
||||||
|
|
||||||
|
//access the value (postfix++ and postfix--)
|
||||||
|
EMIT_BYTE(rt, code, TOY_OPCODE_ACCESS);
|
||||||
|
EMIT_BYTE(rt, code,0);
|
||||||
|
EMIT_BYTE(rt, code,0);
|
||||||
|
EMIT_BYTE(rt, code,0);
|
||||||
|
|
||||||
|
//read the var name onto the stack (again)
|
||||||
|
name = TOY_VALUE_AS_STRING(ast.child->value.value);
|
||||||
|
|
||||||
|
EMIT_BYTE(rt, code, TOY_OPCODE_READ);
|
||||||
|
EMIT_BYTE(rt, code, TOY_VALUE_STRING);
|
||||||
|
EMIT_BYTE(rt, code, TOY_STRING_NAME);
|
||||||
|
EMIT_BYTE(rt, code, name->info.length); //store the length (max 255)
|
||||||
|
|
||||||
|
emitString(rt, name);
|
||||||
|
|
||||||
|
//duplicate the var name, then get the value
|
||||||
|
EMIT_BYTE(rt, code,TOY_OPCODE_DUPLICATE);
|
||||||
|
EMIT_BYTE(rt, code, TOY_OPCODE_ACCESS); //squeezed
|
||||||
|
EMIT_BYTE(rt, code,0);
|
||||||
|
EMIT_BYTE(rt, code,0);
|
||||||
|
|
||||||
|
//read the integer '1'
|
||||||
|
EMIT_BYTE(rt, code, TOY_OPCODE_READ);
|
||||||
|
EMIT_BYTE(rt, code, TOY_VALUE_INTEGER);
|
||||||
|
EMIT_BYTE(rt, code, 0);
|
||||||
|
EMIT_BYTE(rt, code, 0);
|
||||||
|
|
||||||
|
EMIT_INT(rt, code, 1);
|
||||||
|
|
||||||
|
//add (or subtract) the two values, then assign (pops the second duplicate, and leaves value on the stack)
|
||||||
|
EMIT_BYTE(rt, code, ast.flag == TOY_AST_FLAG_POSTFIX_INCREMENT ? TOY_OPCODE_ADD : TOY_OPCODE_SUBTRACT);
|
||||||
|
EMIT_BYTE(rt, code,TOY_OPCODE_ASSIGN); //squeezed
|
||||||
|
EMIT_BYTE(rt, code,0);
|
||||||
|
EMIT_BYTE(rt, code,0);
|
||||||
|
|
||||||
|
//remove the lingering value (yep, this is UGLY)
|
||||||
|
EMIT_BYTE(rt, code, TOY_OPCODE_ELIMINATE);
|
||||||
|
EMIT_BYTE(rt, code,0);
|
||||||
|
EMIT_BYTE(rt, code,0);
|
||||||
|
EMIT_BYTE(rt, code,0);
|
||||||
|
|
||||||
|
//leaves one value on the stack
|
||||||
|
result = 1;
|
||||||
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Invalid AST unary flag found\n" TOY_CC_RESET);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Invalid AST unary flag found\n" TOY_CC_RESET);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
|
|||||||
@@ -145,4 +145,16 @@ print !false; //true
|
|||||||
assert a == 42, "prefix increment & decrement 1.5";
|
assert a == 42, "prefix increment & decrement 1.5";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//increment & decrement (postfix)
|
||||||
|
{
|
||||||
|
var a = 42;
|
||||||
|
assert a == 42, "postfix increment & decrement 1.1";
|
||||||
|
assert a++ == 42, "postfix increment & decrement 1.2";
|
||||||
|
assert a == 43, "postfix increment & decrement 1.3";
|
||||||
|
assert a-- == 43, "postfix increment & decrement 1.4";
|
||||||
|
assert a == 42, "postfix increment & decrement 1.5";
|
||||||
|
|
||||||
|
print a;
|
||||||
|
}
|
||||||
|
|
||||||
//TODO: type casting
|
//TODO: type casting
|
||||||
|
|||||||
Reference in New Issue
Block a user