Postfix '++' & '--' works (prefix & postfix are both tested)

This commit is contained in:
2025-01-09 18:33:10 +11:00
parent 6f16c31f24
commit 14696833fd
6 changed files with 140 additions and 16 deletions

View File

@@ -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;
} }

View File

@@ -11,3 +11,16 @@
print a; 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;
}

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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