From 104ba53b334843c60ba56a8932360d1e7a5b472a Mon Sep 17 00:00:00 2001 From: Mid <> Date: Tue, 14 Oct 2025 16:30:58 +0300 Subject: [PATCH] Introduce null keyword --- src/ast/ast.c | 1 + src/ast/ast.h | 8 +++++++- src/lexer.c | 7 +++++++ src/lexer.h | 1 + src/parse.c | 6 ++++++ src/x86/normalize.c | 11 ++++++++++- 6 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/ast/ast.c b/src/ast/ast.c index 52a4f02..f513690 100644 --- a/src/ast/ast.c +++ b/src/ast/ast.c @@ -92,6 +92,7 @@ void generic_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chu, AST *tlc, v generic_visitor(&n->stmtJump.condition, stmt, stmtPrev, chu, tlc, ud, preHandler, postHandler); } } else if(n->nodeKind == AST_STMT_LABEL) { + } else if(n->nodeKind == AST_EXPR_NULL) { } else { stahp_node(n, "generic_visitor: unhandled %s", AST_KIND_STR[n->nodeKind]); } diff --git a/src/ast/ast.h b/src/ast/ast.h index 559a811..422e052 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -44,7 +44,8 @@ K(AST_EXPR_DOT) \ K(AST_EXPR_EXT_SIZEOF) \ K(AST_STMT_JUMP) \ - K(AST_STMT_LABEL) + K(AST_STMT_LABEL) \ + K(AST_EXPR_NULL) typedef enum ENUMPAK { AST_KINDS(GEN_ENUM) } ASTKind; extern const char *AST_KIND_STR[]; @@ -331,6 +332,10 @@ typedef struct { char *name; } ASTStmtLabel; +typedef struct { + ASTExpr; +} ASTExprNull; + typedef union AST { ASTBase; @@ -362,6 +367,7 @@ typedef union AST { ASTExprExtSizeOf exprExtSizeOf; ASTStmtJump stmtJump; ASTStmtLabel stmtLabel; + ASTExprNull exprNull; } AST; #pragma pack(pop) diff --git a/src/lexer.c b/src/lexer.c index a41771f..ea1364f 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -27,7 +27,9 @@ char *TOKEN_NAMES[] = { "'break'", "','", "'&'", + "'&&'", "'|'", + "'||'", "'^'", "'~'", "'=='", @@ -50,6 +52,7 @@ char *TOKEN_NAMES[] = { "'as'", "'use'", "'else'", + "'null'", }; static int isAlpha(int c) { @@ -309,6 +312,10 @@ Token nct_tokenize(FILE *f) { free(content); tok.type = TOKEN_ELSE; return tok; + } else if(!strcmp(content, "null")) { + free(content); + tok.type = TOKEN_NULL; + return tok; } tok.type = TOKEN_IDENTIFIER; diff --git a/src/lexer.h b/src/lexer.h index 4ce0266..9a8b759 100644 --- a/src/lexer.h +++ b/src/lexer.h @@ -52,6 +52,7 @@ typedef enum { TOKEN_AS, TOKEN_USE, TOKEN_ELSE, + TOKEN_NULL, } TokenKind; typedef struct Token { diff --git a/src/parse.c b/src/parse.c index c33b0a5..28ea10b 100644 --- a/src/parse.c +++ b/src/parse.c @@ -269,6 +269,12 @@ AST *nct_parse_expression(Parser *P, int lOP) { e = (AST*) exprvar(P, vte); } + } else if(maybe(P, TOKEN_NULL)) { + ASTExprNull *ret = alloc_node(P, sizeof(*ret)); + ret->nodeKind = AST_EXPR_NULL; + ret->type = type_pointer_wrap(type_u(8)); + + e = (AST*) ret; } else if(peek(P, 0).type == TOKEN_STRING) { ASTExprStringLiteral *ret = alloc_node(P, sizeof(*ret)); ret->nodeKind = AST_EXPR_STRING_LITERAL; diff --git a/src/x86/normalize.c b/src/x86/normalize.c index b878e02..7b591ff 100644 --- a/src/x86/normalize.c +++ b/src/x86/normalize.c @@ -596,7 +596,16 @@ static void denoop_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chunk, AST bool *success = &state->success; - if(n->nodeKind == AST_EXPR_UNARY_OP && n->exprUnOp.operator == UNOP_REF && n->exprUnOp.operand->nodeKind == AST_EXPR_UNARY_OP && n->exprUnOp.operand->exprUnOp.operator == UNOP_DEREF) { + if(n->nodeKind == AST_EXPR_NULL) { + // Turn `null` into integer + + ASTExprPrimitive *prim = calloc(1, sizeof(*prim)); + prim->nodeKind = AST_EXPR_PRIMITIVE; + prim->type = n->expression.type; + prim->val = ntc_get_int_default("null", 0); + + *nptr = (AST*) prim; + } else if(n->nodeKind == AST_EXPR_UNARY_OP && n->exprUnOp.operator == UNOP_REF && n->exprUnOp.operand->nodeKind == AST_EXPR_UNARY_OP && n->exprUnOp.operand->exprUnOp.operator == UNOP_DEREF) { // Turn `&*a` into `a` // Artificially change type of casted expression to keep types valid for subsequent passes