Introduce null keyword

This commit is contained in:
Mid 2025-10-14 16:30:58 +03:00
parent 2d56f124a9
commit 104ba53b33
6 changed files with 32 additions and 2 deletions

View File

@ -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); generic_visitor(&n->stmtJump.condition, stmt, stmtPrev, chu, tlc, ud, preHandler, postHandler);
} }
} else if(n->nodeKind == AST_STMT_LABEL) { } else if(n->nodeKind == AST_STMT_LABEL) {
} else if(n->nodeKind == AST_EXPR_NULL) {
} else { } else {
stahp_node(n, "generic_visitor: unhandled %s", AST_KIND_STR[n->nodeKind]); stahp_node(n, "generic_visitor: unhandled %s", AST_KIND_STR[n->nodeKind]);
} }

View File

@ -44,7 +44,8 @@
K(AST_EXPR_DOT) \ K(AST_EXPR_DOT) \
K(AST_EXPR_EXT_SIZEOF) \ K(AST_EXPR_EXT_SIZEOF) \
K(AST_STMT_JUMP) \ K(AST_STMT_JUMP) \
K(AST_STMT_LABEL) K(AST_STMT_LABEL) \
K(AST_EXPR_NULL)
typedef enum ENUMPAK { AST_KINDS(GEN_ENUM) } ASTKind; typedef enum ENUMPAK { AST_KINDS(GEN_ENUM) } ASTKind;
extern const char *AST_KIND_STR[]; extern const char *AST_KIND_STR[];
@ -331,6 +332,10 @@ typedef struct {
char *name; char *name;
} ASTStmtLabel; } ASTStmtLabel;
typedef struct {
ASTExpr;
} ASTExprNull;
typedef union AST { typedef union AST {
ASTBase; ASTBase;
@ -362,6 +367,7 @@ typedef union AST {
ASTExprExtSizeOf exprExtSizeOf; ASTExprExtSizeOf exprExtSizeOf;
ASTStmtJump stmtJump; ASTStmtJump stmtJump;
ASTStmtLabel stmtLabel; ASTStmtLabel stmtLabel;
ASTExprNull exprNull;
} AST; } AST;
#pragma pack(pop) #pragma pack(pop)

View File

@ -27,7 +27,9 @@ char *TOKEN_NAMES[] = {
"'break'", "'break'",
"','", "','",
"'&'", "'&'",
"'&&'",
"'|'", "'|'",
"'||'",
"'^'", "'^'",
"'~'", "'~'",
"'=='", "'=='",
@ -50,6 +52,7 @@ char *TOKEN_NAMES[] = {
"'as'", "'as'",
"'use'", "'use'",
"'else'", "'else'",
"'null'",
}; };
static int isAlpha(int c) { static int isAlpha(int c) {
@ -309,6 +312,10 @@ Token nct_tokenize(FILE *f) {
free(content); free(content);
tok.type = TOKEN_ELSE; tok.type = TOKEN_ELSE;
return tok; return tok;
} else if(!strcmp(content, "null")) {
free(content);
tok.type = TOKEN_NULL;
return tok;
} }
tok.type = TOKEN_IDENTIFIER; tok.type = TOKEN_IDENTIFIER;

View File

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

View File

@ -269,6 +269,12 @@ AST *nct_parse_expression(Parser *P, int lOP) {
e = (AST*) exprvar(P, vte); 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) { } else if(peek(P, 0).type == TOKEN_STRING) {
ASTExprStringLiteral *ret = alloc_node(P, sizeof(*ret)); ASTExprStringLiteral *ret = alloc_node(P, sizeof(*ret));
ret->nodeKind = AST_EXPR_STRING_LITERAL; ret->nodeKind = AST_EXPR_STRING_LITERAL;

View File

@ -596,7 +596,16 @@ static void denoop_visitor(AST **nptr, AST *stmt, AST *stmtPrev, AST *chunk, AST
bool *success = &state->success; 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` // Turn `&*a` into `a`
// Artificially change type of casted expression to keep types valid for subsequent passes // Artificially change type of casted expression to keep types valid for subsequent passes