Fucking add else statement

This commit is contained in:
Mid 2025-08-14 18:22:31 +03:00
parent 5755e243a9
commit 5196026ed1
7 changed files with 115 additions and 46 deletions

View File

@ -50,8 +50,7 @@ loop {
} }
codePtr = codePtr + 1; codePtr = codePtr + 1;
} }
} } else {
if(data[dataPtr] != 0) {
stckPtr = stckPtr + 1; stckPtr = stckPtr + 1;
stck[stckPtr] = codePtr; stck[stckPtr] = codePtr;
} }
@ -62,8 +61,7 @@ loop {
if(code[codePtr] == 93) { if(code[codePtr] == 93) {
if(data[dataPtr] == 0) { if(data[dataPtr] == 0) {
stckPtr = stckPtr - 1; stckPtr = stckPtr - 1;
} } else {
if(data[dataPtr] != 0) {
codePtr = stck[stckPtr]; codePtr = stck[stckPtr];
} }
} }
@ -72,4 +70,4 @@ loop {
} }
codePtr = codePtr + 1; codePtr = codePtr + 1;
} }

View File

@ -2,4 +2,6 @@ u16 x: 5;
if(x != 0) { if(x != 0) {
x = 2; x = 2;
} else {
x = 5;
} }

137
src/ast.c
View File

@ -34,6 +34,9 @@ void generic_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chu, AST *tlc, v
} else if(n->nodeKind == AST_STMT_IF) { } else if(n->nodeKind == AST_STMT_IF) {
generic_visitor(&n->stmtIf.expression, stmt, stmtPrev, chu, tlc, ud, preHandler, postHandler); generic_visitor(&n->stmtIf.expression, stmt, stmtPrev, chu, tlc, ud, preHandler, postHandler);
generic_visitor(&n->stmtIf.then, stmt, stmtPrev, chu, tlc, ud, preHandler, postHandler); generic_visitor(&n->stmtIf.then, stmt, stmtPrev, chu, tlc, ud, preHandler, postHandler);
if(n->stmtIf.elss) {
generic_visitor(&n->stmtIf.elss, stmt, stmtPrev, chu, tlc, ud, preHandler, postHandler);
}
} else if(n->nodeKind == AST_STMT_LOOP) { } else if(n->nodeKind == AST_STMT_LOOP) {
generic_visitor(&n->stmtLoop.body, stmt, stmtPrev, chu, tlc, ud, preHandler, postHandler); generic_visitor(&n->stmtLoop.body, stmt, stmtPrev, chu, tlc, ud, preHandler, postHandler);
} else if(n->nodeKind == AST_STMT_BREAK) { } else if(n->nodeKind == AST_STMT_BREAK) {
@ -143,6 +146,13 @@ int ast_stmt_is_after(const AST *chunk, const AST *s1, const AST *s2) {
if(i == 1 || (i == 0 && s1 != NULL)) { if(i == 1 || (i == 0 && s1 != NULL)) {
return i; return i;
} }
if(s->stmtIf.elss) {
i = ast_stmt_is_after(s->stmtIf.elss, s1, s2);
if(i == 1 || (i == 0 && s1 != NULL)) {
return i;
}
}
} }
s = s->statement.next; s = s->statement.next;
@ -656,7 +666,14 @@ static char *ast_dumps(AST *tlc, AST *s) {
} else if(s->nodeKind == AST_STMT_IF) { } else if(s->nodeKind == AST_STMT_IF) {
char *cond = ast_dumpe(tlc, s->stmtIf.expression); char *cond = ast_dumpe(tlc, s->stmtIf.expression);
char *inner = ast_dumpc(tlc, s->stmtIf.then); char *inner = ast_dumpc(tlc, s->stmtIf.then);
char *c = malp("if(%s) {\n%s}", cond, inner); char *elss = s->stmtIf.elss ? ast_dumpc(tlc, s->stmtIf.elss) : NULL;
char *c;
if(elss) {
c = malp("if(%s) {\n%s} else {\n%s}", cond, inner, elss);
free(elss);
} else {
c = malp("if(%s) {\n%s}", cond, inner);
}
free(cond); free(cond);
free(inner); free(inner);
return c; return c;
@ -1098,6 +1115,21 @@ void ast_segmented_dereference(AST *tlc) {
generic_visitor(&tlc, NULL, NULL, tlc, tlc, tlc, ast_segmented_dereference_visitor, NULL); generic_visitor(&tlc, NULL, NULL, tlc, tlc, tlc, ast_segmented_dereference_visitor, NULL);
} }
static void ast_patch_in_chunk(AST *chunkOuter, AST *stmtBefore, AST *chunkInner, AST *stmtAfter) {
if(chunkInner->chunk.statementFirst) {
stmtBefore->statement.next = chunkInner->chunk.statementFirst;
for(AST *z = chunkInner->chunk.statementFirst; z; z = z->statement.next) {
if(!z->statement.next) {
z->statement.next = stmtAfter;
break;
}
}
} else {
stmtBefore->statement.next = stmtAfter;
}
}
#define LOOPSTACKSIZE 64 #define LOOPSTACKSIZE 64
struct LinearizeState { struct LinearizeState {
size_t currentDepth; size_t currentDepth;
@ -1113,38 +1145,69 @@ static void ast_linearize_visitor_pre(AST **aptr, AST *stmt, AST *stmtPrev, AST
AST *a = *aptr; AST *a = *aptr;
if(a->nodeKind == AST_STMT_IF) { if(a->nodeKind == AST_STMT_IF) {
ASTExprUnaryOp *notcond = calloc(1, sizeof(*notcond)); if(a->stmtIf.elss == NULL) {
notcond->nodeKind = AST_EXPR_UNARY_OP; ASTExprUnaryOp *notcond = calloc(1, sizeof(*notcond));
notcond->operator = UNOP_NOT; notcond->nodeKind = AST_EXPR_UNARY_OP;
notcond->operand = a->stmtIf.expression; notcond->operator = UNOP_NOT;
notcond->type = a->stmtIf.expression->expression.type; notcond->operand = a->stmtIf.expression;
notcond->type = a->stmtIf.expression->expression.type;
ASTStmtJump *jump = calloc(1, sizeof(ASTStmtJump));
jump->nodeKind = AST_STMT_JUMP; ASTStmtJump *jump = calloc(1, sizeof(ASTStmtJump));
jump->condition = (AST*) notcond; jump->nodeKind = AST_STMT_JUMP;
jump->label = malp("$Lin%lu", nextLabelIdx++); jump->condition = (AST*) notcond;
jump->label = malp("$Lin%lu", nextLabelIdx++);
ASTStmtLabel *label = calloc(1, sizeof(ASTStmtLabel));
label->nodeKind = AST_STMT_LABEL; ASTStmtLabel *label = calloc(1, sizeof(ASTStmtLabel));
label->name = strdup(jump->label); label->nodeKind = AST_STMT_LABEL;
label->name = strdup(jump->label);
if(stmtPrev) {
stmtPrev->statement.next = (AST*) jump; if(stmtPrev) {
} else { stmtPrev->statement.next = (AST*) jump;
chunk->chunk.statementFirst = (AST*) jump; } else {
} chunk->chunk.statementFirst = (AST*) jump;
if(a->stmtIf.then->chunk.statementFirst) {
jump->next = a->stmtIf.then->chunk.statementFirst;
for(AST *z = a->stmtIf.then->chunk.statementFirst; z; z = z->statement.next) {
if(!z->statement.next) {
z->statement.next = (AST*) label;
break;
}
} }
ast_patch_in_chunk(chunk, (AST*) jump, a->stmtIf.then, (AST*) label);
label->next = a->statement.next;
} else { } else {
jump->next = (AST*) label; ASTExprUnaryOp *notcond = calloc(1, sizeof(*notcond));
notcond->nodeKind = AST_EXPR_UNARY_OP;
notcond->operator = UNOP_NOT;
notcond->operand = a->stmtIf.expression;
notcond->type = a->stmtIf.expression->expression.type;
ASTStmtJump *jump2Else = calloc(1, sizeof(ASTStmtJump));
jump2Else->nodeKind = AST_STMT_JUMP;
jump2Else->condition = (AST*) notcond;
jump2Else->label = malp("$Lin%lu", nextLabelIdx++);
ASTStmtJump *jump2End = calloc(1, sizeof(ASTStmtJump));
jump2End->nodeKind = AST_STMT_JUMP;
jump2End->label = malp("$Lin%lu", nextLabelIdx++);
ASTStmtLabel *labelElse = calloc(1, sizeof(ASTStmtLabel));
labelElse->nodeKind = AST_STMT_LABEL;
labelElse->name = strdup(jump2Else->label);
ASTStmtLabel *labelEnd = calloc(1, sizeof(ASTStmtLabel));
labelEnd->nodeKind = AST_STMT_LABEL;
labelEnd->name = strdup(jump2End->label);
if(stmtPrev) {
stmtPrev->statement.next = (AST*) jump2Else;
} else {
chunk->chunk.statementFirst = (AST*) jump2Else;
}
ast_patch_in_chunk(chunk, (AST*) jump2Else, a->stmtIf.then, (AST*) jump2End);
jump2End->next = (AST*) labelElse;
ast_patch_in_chunk(chunk, (AST*) labelElse, a->stmtIf.elss, (AST*) labelEnd);
labelEnd->next = a->statement.next;
} }
label->next = a->statement.next;
} else if(a->nodeKind == AST_STMT_LOOP) { } else if(a->nodeKind == AST_STMT_LOOP) {
size_t startIdx = nextLabelIdx++; size_t startIdx = nextLabelIdx++;
size_t endIdx = nextLabelIdx++; size_t endIdx = nextLabelIdx++;
@ -1167,17 +1230,9 @@ static void ast_linearize_visitor_pre(AST **aptr, AST *stmt, AST *stmtPrev, AST
} else { } else {
chunk->chunk.statementFirst = (AST*) startLabel; chunk->chunk.statementFirst = (AST*) startLabel;
} }
if(a->stmtLoop.body->chunk.statementFirst) {
startLabel->next = a->stmtLoop.body->chunk.statementFirst; ast_patch_in_chunk(chunk, (AST*) startLabel, a->stmtLoop.body, (AST*) jump);
for(AST *z = a->stmtLoop.body->chunk.statementFirst; z; z = z->statement.next) {
if(!z->statement.next) {
z->statement.next = (AST*) jump;
break;
}
}
} else {
startLabel->next = (AST*) jump;
}
jump->next = (AST*) endLabel; jump->next = (AST*) endLabel;
endLabel->next = a->statement.next; endLabel->next = a->statement.next;

View File

@ -225,6 +225,7 @@ typedef struct {
union AST *expression; union AST *expression;
union AST *then; union AST *then;
union AST *elss;
} ASTStmtIf; } ASTStmtIf;
typedef struct { typedef struct {

View File

@ -49,6 +49,7 @@ char *TOKEN_NAMES[] = {
"'.'", "'.'",
"'as'", "'as'",
"'use'", "'use'",
"'else'",
}; };
static int isAlpha(int c) { static int isAlpha(int c) {
@ -296,6 +297,10 @@ Token nct_tokenize(FILE *f) {
free(content); free(content);
tok.type = TOKEN_USE; tok.type = TOKEN_USE;
return tok; return tok;
} else if(!strcmp(content, "else")) {
free(content);
tok.type = TOKEN_ELSE;
return tok;
} }
tok.type = TOKEN_IDENTIFIER; tok.type = TOKEN_IDENTIFIER;

View File

@ -49,6 +49,7 @@ typedef enum {
TOKEN_DOT, TOKEN_DOT,
TOKEN_AS, TOKEN_AS,
TOKEN_USE, TOKEN_USE,
TOKEN_ELSE,
} TokenKind; } TokenKind;
typedef struct Token { typedef struct Token {

View File

@ -1095,6 +1095,13 @@ static void nct_parse_statement(Parser *P) {
expect(P, TOKEN_SQUIGGLY_L); expect(P, TOKEN_SQUIGGLY_L);
ret->then = (AST*) nct_parse_chunk(P, 0, 0, NULL, NULL); ret->then = (AST*) nct_parse_chunk(P, 0, 0, NULL, NULL);
expect(P, TOKEN_SQUIGGLY_R); expect(P, TOKEN_SQUIGGLY_R);
if(maybe(P, TOKEN_ELSE)) {
expect(P, TOKEN_SQUIGGLY_L);
ret->elss = (AST*) nct_parse_chunk(P, 0, 0, NULL, NULL);
expect(P, TOKEN_SQUIGGLY_R);
}
return; return;
} else if(maybe(P, TOKEN_LOOP)) { } else if(maybe(P, TOKEN_LOOP)) {
ASTStmtLoop *ret = alloc_node(P, sizeof(*ret)); ASTStmtLoop *ret = alloc_node(P, sizeof(*ret));