aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2026-09-03 03:36:06 +0200
committerhachem <im@hachem.wtf>2026-09-03 03:36:06 +0200
commit56ba8b2a373dd1386950592bda9c68ff9f25c203 (patch)
treee33d46037b8a0cb25f5c9052d1f2ee3b143dff22 /src
parent9956f626110a5b55fc58049bbe5841a98e941614 (diff)
fix: i JUST started using a static analyzer for ts
Diffstat (limited to 'src')
-rw-r--r--src/codegen/nasm.c44
-rw-r--r--src/lexer/lexer.c5
-rw-r--r--src/lexer/lexer.h2
-rw-r--r--src/parser/ast.c18
-rw-r--r--src/parser/parser.c25
-rw-r--r--src/sema/sema.c26
6 files changed, 73 insertions, 47 deletions
diff --git a/src/codegen/nasm.c b/src/codegen/nasm.c
index 31bcee0..6df22a4 100644
--- a/src/codegen/nasm.c
+++ b/src/codegen/nasm.c
@@ -93,7 +93,7 @@ static bool is_float_register(struct Token token)
return true;
}
-static size_t float_index(struct FloatTable* floats, struct Token literal)
+static size_t float_index(const struct FloatTable* floats, struct Token literal)
{
for (size_t i = 0; i < floats->count; i += 1)
if (floats->items[i].length == literal.length
@@ -310,7 +310,7 @@ static bool fold_member(struct Program* program, struct Expr* object, struct Tok
return false;
struct Token name = object->primary.token;
- struct EnumDecl* enumeration = find_enum(program, name);
+ const struct EnumDecl* enumeration = find_enum(program, name);
if (enumeration != NULL)
{
for (size_t i = 0; i < enumeration->member_count; i += 1)
@@ -322,7 +322,7 @@ static bool fold_member(struct Program* program, struct Expr* object, struct Tok
return false;
}
- struct StructDecl* layout = find_struct(program, name);
+ const struct StructDecl* layout = find_struct(program, name);
if (layout != NULL)
{
uint64_t offset = 0;
@@ -400,7 +400,7 @@ static bool fold_const(struct Program* program, struct Expr* expr, uint64_t* out
// offset (or the total size for `.size`)
static bool emit_named_member(struct Emitter* emitter, struct Token object, struct Token member)
{
- struct EnumDecl* enumeration = find_enum(emitter->program, object);
+ const struct EnumDecl* enumeration = find_enum(emitter->program, object);
if (enumeration != NULL)
{
for (size_t i = 0; i < enumeration->member_count; i += 1)
@@ -411,7 +411,7 @@ static bool emit_named_member(struct Emitter* emitter, struct Token object, stru
}
}
- struct StructDecl* layout = find_struct(emitter->program, object);
+ const struct StructDecl* layout = find_struct(emitter->program, object);
if (layout != NULL)
{
uint64_t offset = 0;
@@ -494,6 +494,19 @@ static void emit_division(struct Emitter* emitter, const char* dst, struct Expr*
fprintf(emitter->out, "\tmov %s, rax\n", dst);
}
+// idiv leaves the remainder in rdx, so a modulo takes its result from there
+static void emit_modulo(struct Emitter* emitter, const char* dst, struct Expr* divisor)
+{
+ if (strcmp(dst, "rax") != 0)
+ fprintf(emitter->out, "\tmov rax, %s\n", dst);
+ fprintf(emitter->out, "\tcqo\n");
+ fprintf(emitter->out, "\tidiv ");
+ emit_operand(emitter, divisor);
+ fprintf(emitter->out, "\n");
+ if (strcmp(dst, "rdx") != 0)
+ fprintf(emitter->out, "\tmov %s, rdx\n", dst);
+}
+
static void emit_divide(struct Emitter* emitter, struct AssignStatement* assign)
{
if (assign->target_deref)
@@ -505,7 +518,11 @@ static void emit_divide(struct Emitter* emitter, struct AssignStatement* assign)
struct Token target = resolve_register(emitter, assign->target);
char dst[32];
snprintf(dst, sizeof(dst), "%.*s", (int)target.length, target.start);
- emit_division(emitter, dst, assign->value);
+
+ if (assign->op.type == TOKEN_PERCENT_EQUAL)
+ emit_modulo(emitter, dst, assign->value);
+ else
+ emit_division(emitter, dst, assign->value);
}
// an expression can be evaluated into a register when it is a single term
@@ -576,6 +593,11 @@ static void emit_expr_into(struct Emitter* emitter, const char* dst, struct Expr
emit_division(emitter, dst, expr->binary.right);
return;
}
+ if (expr->binary.op.type == TOKEN_PERCENT)
+ {
+ emit_modulo(emitter, dst, expr->binary.right);
+ return;
+ }
const char* mnemonic =
expr->binary.op.type == TOKEN_PLUS ? "add" :
@@ -677,7 +699,7 @@ static const char* float_mnemonic(enum TokenType op)
}
}
-static bool value_is_float(struct Emitter* emitter, struct Expr* expr)
+static bool value_is_float(struct Emitter* emitter, const struct Expr* expr)
{
if (expr->kind != EXPR_PRIMARY)
return false;
@@ -766,7 +788,7 @@ static void emit_assign(struct Emitter* emitter, struct AssignStatement* assign)
return;
}
- if (assign->op.type == TOKEN_SLASH_EQUAL)
+ if (assign->op.type == TOKEN_SLASH_EQUAL || assign->op.type == TOKEN_PERCENT_EQUAL)
{
emit_divide(emitter, assign);
return;
@@ -860,7 +882,7 @@ static struct ProcDecl* find_proc(struct Program* program, struct Token name)
static void emit_call(struct Emitter* emitter, struct CallStatement* call)
{
- struct ProcDecl* callee = find_proc(emitter->program, call->name);
+ const struct ProcDecl* callee = find_proc(emitter->program, call->name);
if (callee == NULL || callee->param_count != call->arg_count)
{
fprintf(emitter->out, "\t; TODO: unsupported call\n");
@@ -902,7 +924,7 @@ static const char* float_jump_if_false(enum TokenType comparison)
}
}
-static void emit_float_operand(struct Emitter* emitter, struct Expr* expr)
+static void emit_float_operand(struct Emitter* emitter, const struct Expr* expr)
{
if (expr->kind == EXPR_PRIMARY && expr->primary.token.type == TOKEN_FLOAT)
{
@@ -1082,7 +1104,7 @@ static struct FloatTable collect_floats(struct Program* program)
return floats;
}
-static void emit_float_data(struct FloatTable* floats, FILE* out)
+static void emit_float_data(const struct FloatTable* floats, FILE* out)
{
for (size_t i = 0; i < floats->count; i += 1)
fprintf(out, "__float%zu: dq %.*s\n", i,
diff --git a/src/lexer/lexer.c b/src/lexer/lexer.c
index b4fb7d7..01bbd41 100644
--- a/src/lexer/lexer.c
+++ b/src/lexer/lexer.c
@@ -114,7 +114,7 @@ static void skip_whitespace(struct Lexer* lexer)
}
}
-static struct Token make_token(struct Lexer* lexer, enum TokenType type, const char* start)
+static struct Token make_token(const struct Lexer* lexer, enum TokenType type, const char* start)
{
struct Token token;
token.type = type;
@@ -231,6 +231,7 @@ struct Token scan_token(struct Lexer* lexer)
case '-': return make_token(lexer, match(lexer, '=') ? TOKEN_MINUS_EQUAL : TOKEN_MINUS, start);
case '*': return make_token(lexer, match(lexer, '=') ? TOKEN_STAR_EQUAL : TOKEN_STAR, start);
case '/': return make_token(lexer, match(lexer, '=') ? TOKEN_SLASH_EQUAL : TOKEN_SLASH, start);
+ case '%': return make_token(lexer, match(lexer, '=') ? TOKEN_PERCENT_EQUAL : TOKEN_PERCENT, start);
case '^': return make_token(lexer, TOKEN_CARET, start);
case '.': return make_token(lexer, TOKEN_DOT, start);
@@ -275,6 +276,7 @@ const char* token_type_name(enum TokenType type)
case TOKEN_MINUS: return "minus";
case TOKEN_STAR: return "star";
case TOKEN_SLASH: return "slash";
+ case TOKEN_PERCENT: return "percent";
case TOKEN_CARET: return "caret";
case TOKEN_BANG: return "bang";
case TOKEN_LESS: return "less";
@@ -294,6 +296,7 @@ const char* token_type_name(enum TokenType type)
case TOKEN_MINUS_EQUAL: return "minus_equal";
case TOKEN_STAR_EQUAL: return "star_equal";
case TOKEN_SLASH_EQUAL: return "slash_equal";
+ case TOKEN_PERCENT_EQUAL: return "percent_equal";
case TOKEN_LESS_EQUAL: return "less_equal";
case TOKEN_GREATER_EQUAL: return "greater_equal";
case TOKEN_UNKNOWN: return "unknown";
diff --git a/src/lexer/lexer.h b/src/lexer/lexer.h
index 5c1e868..45e9b3d 100644
--- a/src/lexer/lexer.h
+++ b/src/lexer/lexer.h
@@ -31,6 +31,7 @@ enum TokenType
TOKEN_MINUS,
TOKEN_STAR,
TOKEN_SLASH,
+ TOKEN_PERCENT,
TOKEN_CARET,
TOKEN_BANG,
TOKEN_LESS,
@@ -51,6 +52,7 @@ enum TokenType
TOKEN_MINUS_EQUAL,
TOKEN_STAR_EQUAL,
TOKEN_SLASH_EQUAL,
+ TOKEN_PERCENT_EQUAL,
TOKEN_LESS_EQUAL,
TOKEN_GREATER_EQUAL,
diff --git a/src/parser/ast.c b/src/parser/ast.c
index 788341b..a387533 100644
--- a/src/parser/ast.c
+++ b/src/parser/ast.c
@@ -150,10 +150,7 @@ void add_data(struct Program* program, struct DataDecl decl)
struct EnumDecl create_enum(void)
{
- struct EnumDecl decl;
- decl.members = NULL;
- decl.member_count = 0;
- decl.member_capacity = 0;
+ struct EnumDecl decl = { 0 };
return decl;
}
@@ -185,10 +182,7 @@ void add_enum(struct Program* program, struct EnumDecl decl)
struct StructDecl create_struct(void)
{
- struct StructDecl decl;
- decl.fields = NULL;
- decl.field_count = 0;
- decl.field_capacity = 0;
+ struct StructDecl decl = { 0 };
return decl;
}
@@ -220,13 +214,7 @@ void add_struct(struct Program* program, struct StructDecl decl)
struct ProcDecl create_proc(void)
{
- struct ProcDecl proc;
- proc.params = NULL;
- proc.param_count = 0;
- proc.param_capacity = 0;
- proc.body = NULL;
- proc.body_count = 0;
- proc.body_capacity = 0;
+ struct ProcDecl proc = { 0 };
return proc;
}
diff --git a/src/parser/parser.c b/src/parser/parser.c
index 3ed9fff..a83c3c4 100644
--- a/src/parser/parser.c
+++ b/src/parser/parser.c
@@ -209,13 +209,15 @@ static bool is_assign_op(enum TokenType type)
|| type == TOKEN_PLUS_EQUAL
|| type == TOKEN_MINUS_EQUAL
|| type == TOKEN_STAR_EQUAL
- || type == TOKEN_SLASH_EQUAL;
+ || type == TOKEN_SLASH_EQUAL
+ || type == TOKEN_PERCENT_EQUAL;
}
static struct Expr* alloc_expr(enum ExprKind kind)
{
struct Expr* expr = malloc(sizeof(struct Expr));
- expr->kind = kind;
+ if (expr != NULL)
+ expr->kind = kind;
return expr;
}
@@ -289,13 +291,14 @@ static struct Expr* parse_postfix(struct Parser* parser)
return expr;
}
-static struct Expr* parse_binary(struct Parser* parser, struct Expr* (*operand)(struct Parser*), enum TokenType a, enum TokenType b)
+static struct Expr* parse_binary(struct Parser* parser, struct Expr* (*operand)(struct Parser*),
+ enum TokenType a, enum TokenType b, enum TokenType c)
{
struct Expr* left = operand(parser);
if (left == NULL)
return NULL;
- while (check(parser, a) || check(parser, b))
+ while (check(parser, a) || check(parser, b) || check(parser, c))
{
advance_parser(parser);
struct Token op = parser->previous;
@@ -319,12 +322,12 @@ static struct Expr* parse_binary(struct Parser* parser, struct Expr* (*operand)(
static struct Expr* parse_multiplicative(struct Parser* parser)
{
- return parse_binary(parser, parse_postfix, TOKEN_STAR, TOKEN_SLASH);
+ return parse_binary(parser, parse_postfix, TOKEN_STAR, TOKEN_SLASH, TOKEN_PERCENT);
}
static struct Expr* parse_expression(struct Parser* parser)
{
- return parse_binary(parser, parse_multiplicative, TOKEN_PLUS, TOKEN_MINUS);
+ return parse_binary(parser, parse_multiplicative, TOKEN_PLUS, TOKEN_MINUS, TOKEN_MINUS);
}
static bool is_compare_op(enum TokenType type)
@@ -354,7 +357,13 @@ static bool parse_call(struct Parser* parser, struct Token name, struct Statemen
if (count == capacity)
{
capacity = capacity < 4 ? 4 : capacity * 2;
- args = realloc(args, capacity * sizeof(struct Expr*));
+ struct Expr** grown = realloc(args, capacity * sizeof(struct Expr*));
+ if (grown == NULL)
+ {
+ free_expr(arg);
+ goto error;
+ }
+ args = grown;
}
args[count] = arg;
count += 1;
@@ -614,7 +623,7 @@ static bool parse_directive(struct Parser* parser, struct Program* program)
bool parse_program(struct Lexer* lexer, struct Program* out)
{
- struct Parser parser;
+ struct Parser parser = { 0 };
parser.lexer = lexer;
parser.source.name = lexer->name;
parser.source.text = lexer->source;
diff --git a/src/sema/sema.c b/src/sema/sema.c
index 12fd53f..4b4bc26 100644
--- a/src/sema/sema.c
+++ b/src/sema/sema.c
@@ -33,6 +33,8 @@ static bool check_duplicate_names(struct Source source, struct Program* program)
return true;
struct Token* names = malloc(count * sizeof(struct Token));
+ if (names == NULL)
+ return true;
size_t n = 0;
for (size_t i = 0; i < program->const_count; i += 1)
{
@@ -92,7 +94,7 @@ static bool check_entry_point(struct Source source, struct Program* program)
return false;
}
-static bool is_program_const(struct Program* program, struct Token name)
+static bool is_program_const(const struct Program* program, struct Token name)
{
for (size_t i = 0; i < program->const_count; i += 1)
if (names_equal(program->consts[i].name, name))
@@ -227,7 +229,7 @@ static bool is_register(struct RefCheck* check, struct Token token)
return check->program->config.logical_registers && is_logical_register(token);
}
-static bool is_param(struct RefCheck* check, struct Token token)
+static bool is_param(const struct RefCheck* check, struct Token token)
{
for (size_t i = 0; i < check->proc->param_count; i += 1)
if (names_equal(check->proc->params[i].name, token))
@@ -236,7 +238,7 @@ static bool is_param(struct RefCheck* check, struct Token token)
return false;
}
-static bool is_const(struct RefCheck* check, struct Token token)
+static bool is_const(const struct RefCheck* check, struct Token token)
{
for (size_t i = 0; i < check->program->const_count; i += 1)
if (names_equal(check->program->consts[i].name, token))
@@ -245,7 +247,7 @@ static bool is_const(struct RefCheck* check, struct Token token)
return false;
}
-static bool is_data(struct RefCheck* check, struct Token token)
+static bool is_data(const struct RefCheck* check, struct Token token)
{
for (size_t i = 0; i < check->program->data_count; i += 1)
if (names_equal(check->program->data_decls[i].name, token))
@@ -276,7 +278,7 @@ static bool is_stack_buffer(struct RefCheck* check, struct Token token)
{
for (size_t i = 0; i < check->proc->body_count; i += 1)
{
- struct Statement* statement = &check->proc->body[i];
+ const struct Statement* statement = &check->proc->body[i];
if (statement->kind == STATEMENT_STACK && names_equal(statement->stack.name, token))
return true;
}
@@ -288,7 +290,7 @@ static bool is_label(struct RefCheck* check, struct Token token)
{
for (size_t i = 0; i < check->proc->body_count; i += 1)
{
- struct Statement* statement = &check->proc->body[i];
+ const struct Statement* statement = &check->proc->body[i];
if (statement->kind == STATEMENT_LABEL && names_equal(statement->label.name, token))
return true;
}
@@ -305,7 +307,7 @@ static void check_value_name(struct RefCheck* check, struct Token name)
ref_error(check, name, "undefined name '%.*s'", (int)name.length, name.start);
}
-static void check_expr(struct RefCheck* check, struct Expr* expr)
+static void check_expr(struct RefCheck* check, const struct Expr* expr)
{
switch (expr->kind)
{
@@ -319,7 +321,7 @@ static void check_expr(struct RefCheck* check, struct Expr* expr)
break;
case EXPR_DEREF:
{
- struct Expr* address = expr->deref.address;
+ const struct Expr* address = expr->deref.address;
if (address->kind == EXPR_PRIMARY
&& (is_register(check, address->primary.token) || is_param(check, address->primary.token)))
break;
@@ -332,7 +334,7 @@ static void check_expr(struct RefCheck* check, struct Expr* expr)
}
case EXPR_MEMBER:
{
- struct Expr* object = expr->member.object;
+ const struct Expr* object = expr->member.object;
struct Token member = expr->member.member;
if (member.type == TOKEN_INTEGER)
@@ -344,7 +346,7 @@ static void check_expr(struct RefCheck* check, struct Expr* expr)
if (object->kind == EXPR_PRIMARY)
{
- struct EnumDecl* enumeration = find_enum(check, object->primary.token);
+ const struct EnumDecl* enumeration = find_enum(check, object->primary.token);
if (enumeration != NULL)
{
bool found = false;
@@ -358,7 +360,7 @@ static void check_expr(struct RefCheck* check, struct Expr* expr)
break;
}
- struct StructDecl* layout = find_struct(check, object->primary.token);
+ const struct StructDecl* layout = find_struct(check, object->primary.token);
if (layout != NULL)
{
bool found = token_is(member, "size");
@@ -406,7 +408,7 @@ static void check_stack_size(struct RefCheck* check, struct Expr* expr)
break;
case EXPR_MEMBER:
{
- struct Expr* object = expr->member.object;
+ const struct Expr* object = expr->member.object;
if (object->kind == EXPR_PRIMARY
&& (find_enum(check, object->primary.token) != NULL
|| find_struct(check, object->primary.token) != NULL))