summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-23 19:05:10 +0000
committerZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-23 19:05:10 +0000
commit1991cb62d26b954e54cf13c2d765fb3a0bbaa3ca (patch)
treed183776b150690beb2ee45c1ace4e67ab5a29adc
parenta3ee8766e0fc9cb5c96fd9d38d5b0af7b02e01ff (diff)
Fix for #87
-rw-r--r--README.md10
-rw-r--r--src/ast/ast.c38
-rw-r--r--src/parser/parser_type.c21
-rw-r--r--tests/basic/test_basics.zc14
4 files changed, 79 insertions, 4 deletions
diff --git a/README.md b/README.md
index 2c74866..581a01a 100644
--- a/README.md
+++ b/README.md
@@ -48,6 +48,7 @@ Join the discussion, share demos, ask questions, or report bugs in the official
- [Type Aliases](#type-aliases)
- [4. Functions & Lambdas](#4-functions--lambdas)
- [Functions](#functions)
+ - [Const Arguments](#const-arguments)
- [Default Arguments](#default-arguments)
- [Lambdas (Closures)](#lambdas-closures)
- [Variadic Functions](#variadic-functions)
@@ -256,8 +257,17 @@ fn add(a: int, b: int) -> int {
// Named arguments supported in calls
add(a: 10, b: 20);
+```
> **Note**: Named arguments must strictly follow the defined parameter order. `add(b: 20, a: 10)` is invalid.
+
+#### Const Arguments
+Function arguments can be marked as `const` to enforce read-only semantics.
+```zc
+fn print_val(v: const int) {
+ // v = 10; // Error: Cannot assign to const variable
+ println "{v}";
+}
```
#### Default Arguments
diff --git a/src/ast/ast.c b/src/ast/ast.c
index 712f6e3..78d7efb 100644
--- a/src/ast/ast.c
+++ b/src/ast/ast.c
@@ -169,12 +169,31 @@ int type_eq(Type *a, Type *b)
return 1;
}
+static char *type_to_string_impl(Type *t);
+
char *type_to_string(Type *t)
{
if (!t)
{
return xstrdup("void");
}
+ char *res = type_to_string_impl(t);
+ if (t->is_const)
+ {
+ char *final = xmalloc(strlen(res) + 7);
+ sprintf(final, "const %s", res);
+ free(res);
+ return final;
+ }
+ return res;
+}
+
+static char *type_to_string_impl(Type *t)
+{
+ if (!t)
+ {
+ return xstrdup("void");
+ }
switch (t->kind)
{
@@ -293,12 +312,31 @@ char *type_to_string(Type *t)
// C-compatible type stringifier.
// Strictly uses 'struct T' for explicit structs to support external types.
// Does NOT mangle pointers to 'Ptr'.
+static char *type_to_c_string_impl(Type *t);
+
char *type_to_c_string(Type *t)
{
if (!t)
{
return xstrdup("void");
}
+ char *res = type_to_c_string_impl(t);
+ if (t->is_const)
+ {
+ char *final = xmalloc(strlen(res) + 7);
+ sprintf(final, "const %s", res);
+ free(res);
+ return final;
+ }
+ return res;
+}
+
+static char *type_to_c_string_impl(Type *t)
+{
+ if (!t)
+ {
+ return xstrdup("void");
+ }
switch (t->kind)
{
diff --git a/src/parser/parser_type.c b/src/parser/parser_type.c
index b11bedb..24e9f69 100644
--- a/src/parser/parser_type.c
+++ b/src/parser/parser_type.c
@@ -713,11 +713,20 @@ Type *parse_type_base(ParserContext *ctx, Lexer *l)
Type *parse_type_formal(ParserContext *ctx, Lexer *l)
{
int is_restrict = 0;
- if (lexer_peek(l).type == TOK_IDENT && lexer_peek(l).len == 8 &&
- strncmp(lexer_peek(l).start, "restrict", 8) == 0)
+ int is_const = 0;
+
+ if (lexer_peek(l).type == TOK_IDENT)
{
- lexer_next(l); // eat restrict
- is_restrict = 1;
+ if (lexer_peek(l).len == 8 && strncmp(lexer_peek(l).start, "restrict", 8) == 0)
+ {
+ lexer_next(l); // eat restrict
+ is_restrict = 1;
+ }
+ else if (lexer_peek(l).len == 5 && strncmp(lexer_peek(l).start, "const", 5) == 0)
+ {
+ lexer_next(l); // eat const
+ is_const = 1;
+ }
}
// Example: fn(int, int) -> int
@@ -829,6 +838,10 @@ Type *parse_type_formal(ParserContext *ctx, Lexer *l)
{
t->is_restrict = 1;
}
+ if (is_const)
+ {
+ t->is_const = 1;
+ }
return t;
}
diff --git a/tests/basic/test_basics.zc b/tests/basic/test_basics.zc
index d54389b..57dbb4e 100644
--- a/tests/basic/test_basics.zc
+++ b/tests/basic/test_basics.zc
@@ -8,3 +8,17 @@ test "test_vars" {
var y: int = 20;
println "Sum: {x + y}";
}
+
+fn take_const_arg(x: const int) -> int {
+ return x;
+}
+
+test "test_const_args" {
+ var x = take_const_arg(10);
+ assert(x == 10, "Failed const arg");
+
+ var y: const int = 20;
+ assert(y == 20, "Failed const var");
+
+ println "Const args work!";
+}