Skip to content

Commit 852c571

Browse files
gh-96: Pointer args preserve aliasing.
1 parent bc61219 commit 852c571

File tree

2 files changed

+76
-0
lines changed

2 files changed

+76
-0
lines changed

src/interpreter.c

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,6 +1250,7 @@ Value eval_expr(Interpreter* interp, Expr* expr, Env* env) {
12501250
Value arg_val = value_null();
12511251
int arg_from_pos = -1;
12521252
int arg_from_kw = -1;
1253+
Expr* source_node = NULL;
12531254

12541255
bool provided = false;
12551256
// positional provided?
@@ -1312,6 +1313,12 @@ Value eval_expr(Interpreter* interp, Expr* expr, Env* env) {
13121313
}
13131314
}
13141315

1316+
if (arg_from_pos >= 0) {
1317+
source_node = expr->as.call.args.items[arg_from_pos];
1318+
} else if (arg_from_kw >= 0) {
1319+
source_node = expr->as.call.kw_args.items[arg_from_kw];
1320+
}
1321+
13151322
if (!provided) {
13161323
char buf[128];
13171324
snprintf(buf, sizeof(buf), "Missing argument for parameter '%s'", param->name);
@@ -1326,6 +1333,65 @@ Value eval_expr(Interpreter* interp, Expr* expr, Env* env) {
13261333
return value_null();
13271334
}
13281335

1336+
if (source_node && source_node->type == EXPR_PTR) {
1337+
const char* target_name = source_node->as.ptr_name;
1338+
if (!target_name) {
1339+
interp->error = strdup("Invalid pointer target");
1340+
interp->error_line = expr->line;
1341+
interp->error_col = expr->column;
1342+
if (arg_from_pos >= 0) {
1343+
value_free(pos_vals[arg_from_pos]);
1344+
pos_vals[arg_from_pos] = value_null();
1345+
}
1346+
if (arg_from_kw >= 0) {
1347+
value_free(kw_vals[arg_from_kw]);
1348+
kw_vals[arg_from_kw] = value_null();
1349+
}
1350+
for (int t = 0; t < pos_argc; t++) value_free(pos_vals[t]);
1351+
free(pos_vals);
1352+
for (int t = 0; t < kwc; t++) value_free(kw_vals[t]);
1353+
free(kw_vals);
1354+
env_free(call_env);
1355+
return value_null();
1356+
}
1357+
1358+
if (env_set_alias(call_env, param->name, target_name, param->type, true)) {
1359+
if (arg_from_pos >= 0) {
1360+
value_free(pos_vals[arg_from_pos]);
1361+
pos_vals[arg_from_pos] = value_null();
1362+
}
1363+
if (arg_from_kw >= 0) {
1364+
value_free(kw_vals[arg_from_kw]);
1365+
kw_vals[arg_from_kw] = value_null();
1366+
}
1367+
continue;
1368+
}
1369+
1370+
if (interp->error) {
1371+
free(interp->error);
1372+
interp->error = NULL;
1373+
}
1374+
char buf[256];
1375+
snprintf(buf, sizeof(buf), "Cannot bind pointer argument to parameter '%s'", param->name);
1376+
interp->error = strdup(buf);
1377+
interp->error_line = expr->line;
1378+
interp->error_col = expr->column;
1379+
if (arg_from_pos >= 0) {
1380+
value_free(pos_vals[arg_from_pos]);
1381+
pos_vals[arg_from_pos] = value_null();
1382+
}
1383+
if (arg_from_kw >= 0) {
1384+
value_free(kw_vals[arg_from_kw]);
1385+
kw_vals[arg_from_kw] = value_null();
1386+
}
1387+
for (int t = 0; t < pos_argc; t++) value_free(pos_vals[t]);
1388+
free(pos_vals);
1389+
for (int t = 0; t < kwc; t++) value_free(kw_vals[t]);
1390+
free(kw_vals);
1391+
env_free(call_env);
1392+
return value_null();
1393+
}
1394+
13291395
Value bind_val = arg_val;
13301396
bool used_coercion = false;
13311397
if (value_type_to_decl(bind_val.type) != param->type && param->coerced) {

tests/test2.pre

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,16 @@ DEL(x)
258258
DEL(y)
259259
PRINT("Pointers: PASS\n")
260260

261+
PRINT("Testing pointer arguments...")
262+
INT: ptr_arg = 0d5
263+
FUNC INT: SET_ZERO(INT: target){
264+
target = 0d0
265+
}
266+
SET_ZERO(@ptr_arg)
267+
ASSERT(EQ(ptr_arg, 0d0))
268+
DEL(ptr_arg)
269+
PRINT("Pointer arguments: PASS\n")
270+
261271
PRINT("Testing ASSIGN inline operator...")
262272
! typed first assignment should declare, assign, and return the value
263273
ASSERT(EQ(ASSIGN(STR: as_s, "foo"), "foo"))

0 commit comments

Comments
 (0)