Skip to content

Commit

Permalink
fixes #227
Browse files Browse the repository at this point in the history
  • Loading branch information
thradams committed Jan 24, 2025
1 parent dcf8a11 commit 74c514e
Show file tree
Hide file tree
Showing 12 changed files with 1,077 additions and 1,009 deletions.
7 changes: 7 additions & 0 deletions ownership.md
Original file line number Diff line number Diff line change
Expand Up @@ -1206,6 +1206,13 @@ int main() {
<button onclick="Try(this)">try</button>
I later realized that C# has an out parameter, which is similar in
many ways. For example, both Cake and C# assume the argument is
initialized independently of the result.
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/out
#### Null and Not-Null state
The **null** state means that pointers/objects are empty, In other words, not referencing any object.
Expand Down
19 changes: 9 additions & 10 deletions src/file.c
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
void f(){
return 1;
}

#pragma cake diagnostic check "-E1120"

#pragma safety enable

int f2() {
return;
bool init(_Out int *a) {
*a = 3;
return true;
}

#pragma cake diagnostic check "-E1121"

int main() {
int a;
if (0 || init(&a)) return a;
return a;
}
2 changes: 0 additions & 2 deletions src/file.h

This file was deleted.

4 changes: 0 additions & 4 deletions src/file2.c

This file was deleted.

115 changes: 67 additions & 48 deletions src/lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -8517,10 +8517,16 @@ void add_standard_macros(struct preprocessor_ctx* ctx)
"#define __LINE__ 0\n"
"#define __COUNTER__ 0\n"
"#define _CONSOLE\n"
"#define __STDC_OWNERSHIP__ 1\n"
"#define _W_DIVIZION_BY_ZERO_ 29\n"


"#define __STDC_OWNERSHIP__ 1\n" /*cake extension*/
"#define __STDC_HOSTED__ " TOSTRING(__STDC_HOSTED__) "\n"
"#define __STDC_NO_ATOMICS__ " TOSTRING(__STDC_NO_ATOMICS__) "\n"
"#define __STDC_NO_COMPLEX__ " TOSTRING(__STDC_NO_COMPLEX__) "\n"
"#define __STDC_NO_THREADS__ " TOSTRING(__STDC_NO_THREADS__ ) "\n"
"#define __STDC_NO_VLA__ " TOSTRING(__STDC_NO_VLA__ ) "\n"
//"#define __STDC__ " TOSTRING(__STDC__) "\n"



#ifdef __EMSCRIPTEN__
//include dir on emscripten
"#pragma dir \"c:/\"\n"
Expand Down Expand Up @@ -13425,6 +13431,11 @@ enum flow_state

FLOW_OBJECT_STATE_UNINITIALIZED = 1 << 0,


/*
The only reason we have null and zero is because
of non pointer references -1 for instance can be the "null"
*/
FLOW_OBJECT_STATE_NULL = 1 << 1,
FLOW_OBJECT_STATE_NOT_NULL = 1 << 2,

Expand Down Expand Up @@ -28010,7 +28021,7 @@ void defer_start_visit_declaration(struct defer_visit_ctx* ctx, struct declarati

//#pragma once

#define CAKE_VERSION "0.9.50"
#define CAKE_VERSION "0.9.51"



Expand Down Expand Up @@ -45259,66 +45270,74 @@ static void flow_visit_expression(struct flow_visit_ctx* ctx, struct expression*
flow_check_pointer_used_as_bool(ctx, p_expression->left);
flow_check_pointer_used_as_bool(ctx, p_expression->right);

const int original_state_number = arena_add_copy_of_current_state(ctx, "original");

struct true_false_set left_set = { 0 };
flow_visit_expression(ctx, p_expression->left, &left_set);

if (object_has_constant_value(&p_expression->left->object) &&
object_to_bool(&p_expression->left->object) == true)
{
// left || right
//left is true, so the right side will not run
}
else
{
const int original_state_number = arena_add_copy_of_current_state(ctx, "original");

//Set all variables to false state, because otherwise, the right branch
// would not be evaluated
true_false_set_set_objects_to_false_branch(ctx, &left_set, nullable_enabled);

//Set all variables to false state, because otherwise, the right branch
// would not be evaluated
true_false_set_set_objects_to_false_branch(ctx, &left_set, nullable_enabled);
struct true_false_set right_set = { 0 };
flow_visit_expression(ctx, p_expression->right, &right_set);

struct true_false_set right_set = { 0 };
flow_visit_expression(ctx, p_expression->right, &right_set);
//Tudo que faz left ser true ou right ser true

// true_false_set_merge(expr_true_false_set, &left_set, &right_set,
// MERGE_OPTIONS_A_TRUE | MERGE_OPTIONS_A_FALSE | MERGE_OPTIONS_B_TRUE | MERGE_OPTIONS_B_FALSE,
// MERGE_OPTIONS_A_FALSE| MERGE_OPTIONS_B_FALSE);
for (int i = 0; i < left_set.size; i++)
{
struct true_false_set_item item5;

//Tudo que faz left ser true ou right ser true
item5.p_expression = left_set.data[i].p_expression;
item5.true_branch_state |= (left_set.data[i].true_branch_state | left_set.data[i].false_branch_state);
item5.false_branch_state |= left_set.data[i].false_branch_state;
true_false_set_push_back(expr_true_false_set, &item5);
}

for (int i = 0; i < left_set.size; i++)
{
struct true_false_set_item item5;
for (int k = 0; k < right_set.size; k++)
{
int index =
find_item_index_by_expression(expr_true_false_set, right_set.data[k].p_expression);
if (index == -1)
{
index = expr_true_false_set->size;

item5.p_expression = left_set.data[i].p_expression;
item5.true_branch_state |= (left_set.data[i].true_branch_state | left_set.data[i].false_branch_state);
item5.false_branch_state |= left_set.data[i].false_branch_state;
true_false_set_push_back(expr_true_false_set, &item5);
}
struct true_false_set_item item4 = {
.p_expression = right_set.data[k].p_expression
};

for (int k = 0; k < right_set.size; k++)
{
int index =
find_item_index_by_expression(expr_true_false_set, right_set.data[k].p_expression);
if (index == -1)
{
index = expr_true_false_set->size;
true_false_set_push_back(expr_true_false_set, &item4);
}

struct true_false_set_item item4 = {
.p_expression = right_set.data[k].p_expression
};
//Tudo que faz left true e right true faz expressao se true
expr_true_false_set->data[index].p_expression = right_set.data[k].p_expression;
//d->data[index].true_branch_state |= right_set.data[k].true_branch_state;
//Tudo que faz left true ou left false, e right false faz ser false
expr_true_false_set->data[index].false_branch_state |= right_set.data[k].false_branch_state;

true_false_set_push_back(expr_true_false_set, &item4);
}
//No path true seria possivel nao ser feito o right
expr_true_false_set->data[index].true_branch_state |= (BOOLEAN_FLAG_TRUE | BOOLEAN_FLAG_FALSE);

//Tudo que faz left true e right true faz expressao se true
expr_true_false_set->data[index].p_expression = right_set.data[k].p_expression;
//d->data[index].true_branch_state |= right_set.data[k].true_branch_state;
//Tudo que faz left true ou left false, e right false faz ser false
expr_true_false_set->data[index].false_branch_state |= right_set.data[k].false_branch_state;
}

//No path true seria possivel nao ser feito o right
expr_true_false_set->data[index].true_branch_state |= (BOOLEAN_FLAG_TRUE | BOOLEAN_FLAG_FALSE);
//TODO we whould not restore the previous states for states that
//are not true/false
// if (false || init(a)) ... we cannot undo the out a
arena_restore_current_state_from(ctx, original_state_number);
arena_remove_state(ctx, original_state_number);

true_false_set_destroy(&left_set);
true_false_set_destroy(&right_set);
}

arena_restore_current_state_from(ctx, original_state_number);
arena_remove_state(ctx, original_state_number);
true_false_set_destroy(&left_set);
true_false_set_destroy(&right_set);
}
break;

Expand All @@ -45330,11 +45349,11 @@ static void flow_visit_expression(struct flow_visit_ctx* ctx, struct expression*
flow_check_pointer_used_as_bool(ctx, p_expression->left);
flow_check_pointer_used_as_bool(ctx, p_expression->right);

const int original_state_number = arena_add_copy_of_current_state(ctx, "original");

struct true_false_set left_set = { 0 };
flow_visit_expression(ctx, p_expression->left, &left_set);

const int original_state_number = arena_add_copy_of_current_state(ctx, "original");

//Set all variables to true state, because otherwise, the right branch
// would not be evaluated
Expand Down
5 changes: 5 additions & 0 deletions src/object_flow.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ enum flow_state

FLOW_OBJECT_STATE_UNINITIALIZED = 1 << 0,


/*
The only reason we have null and zero is because
of non pointer references -1 for instance can be the "null"
*/
FLOW_OBJECT_STATE_NULL = 1 << 1,
FLOW_OBJECT_STATE_NOT_NULL = 1 << 2,

Expand Down
14 changes: 10 additions & 4 deletions src/tokenizer.c
Original file line number Diff line number Diff line change
Expand Up @@ -5303,10 +5303,16 @@ void add_standard_macros(struct preprocessor_ctx* ctx)
"#define __LINE__ 0\n"
"#define __COUNTER__ 0\n"
"#define _CONSOLE\n"
"#define __STDC_OWNERSHIP__ 1\n"
"#define _W_DIVIZION_BY_ZERO_ 29\n"


"#define __STDC_OWNERSHIP__ 1\n" /*cake extension*/
"#define __STDC_HOSTED__ " TOSTRING(__STDC_HOSTED__) "\n"
"#define __STDC_NO_ATOMICS__ " TOSTRING(__STDC_NO_ATOMICS__) "\n"
"#define __STDC_NO_COMPLEX__ " TOSTRING(__STDC_NO_COMPLEX__) "\n"
"#define __STDC_NO_THREADS__ " TOSTRING(__STDC_NO_THREADS__ ) "\n"
"#define __STDC_NO_VLA__ " TOSTRING(__STDC_NO_VLA__ ) "\n"
//"#define __STDC__ " TOSTRING(__STDC__) "\n"



#ifdef __EMSCRIPTEN__
//include dir on emscripten
"#pragma dir \"c:/\"\n"
Expand Down
2 changes: 1 addition & 1 deletion src/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@

#pragma once

#define CAKE_VERSION "0.9.50"
#define CAKE_VERSION "0.9.51"


94 changes: 51 additions & 43 deletions src/visit_flow.c
Original file line number Diff line number Diff line change
Expand Up @@ -2423,66 +2423,74 @@ static void flow_visit_expression(struct flow_visit_ctx* ctx, struct expression*
flow_check_pointer_used_as_bool(ctx, p_expression->left);
flow_check_pointer_used_as_bool(ctx, p_expression->right);

const int original_state_number = arena_add_copy_of_current_state(ctx, "original");

struct true_false_set left_set = { 0 };
flow_visit_expression(ctx, p_expression->left, &left_set);

if (object_has_constant_value(&p_expression->left->object) &&
object_to_bool(&p_expression->left->object) == true)
{
// left || right
//left is true, so the right side will not run
}
else
{
const int original_state_number = arena_add_copy_of_current_state(ctx, "original");

//Set all variables to false state, because otherwise, the right branch
// would not be evaluated
true_false_set_set_objects_to_false_branch(ctx, &left_set, nullable_enabled);

//Set all variables to false state, because otherwise, the right branch
// would not be evaluated
true_false_set_set_objects_to_false_branch(ctx, &left_set, nullable_enabled);
struct true_false_set right_set = { 0 };
flow_visit_expression(ctx, p_expression->right, &right_set);

struct true_false_set right_set = { 0 };
flow_visit_expression(ctx, p_expression->right, &right_set);
//Tudo que faz left ser true ou right ser true

// true_false_set_merge(expr_true_false_set, &left_set, &right_set,
// MERGE_OPTIONS_A_TRUE | MERGE_OPTIONS_A_FALSE | MERGE_OPTIONS_B_TRUE | MERGE_OPTIONS_B_FALSE,
// MERGE_OPTIONS_A_FALSE| MERGE_OPTIONS_B_FALSE);
for (int i = 0; i < left_set.size; i++)
{
struct true_false_set_item item5;

//Tudo que faz left ser true ou right ser true
item5.p_expression = left_set.data[i].p_expression;
item5.true_branch_state |= (left_set.data[i].true_branch_state | left_set.data[i].false_branch_state);
item5.false_branch_state |= left_set.data[i].false_branch_state;
true_false_set_push_back(expr_true_false_set, &item5);
}

for (int i = 0; i < left_set.size; i++)
{
struct true_false_set_item item5;
for (int k = 0; k < right_set.size; k++)
{
int index =
find_item_index_by_expression(expr_true_false_set, right_set.data[k].p_expression);
if (index == -1)
{
index = expr_true_false_set->size;

item5.p_expression = left_set.data[i].p_expression;
item5.true_branch_state |= (left_set.data[i].true_branch_state | left_set.data[i].false_branch_state);
item5.false_branch_state |= left_set.data[i].false_branch_state;
true_false_set_push_back(expr_true_false_set, &item5);
}
struct true_false_set_item item4 = {
.p_expression = right_set.data[k].p_expression
};

for (int k = 0; k < right_set.size; k++)
{
int index =
find_item_index_by_expression(expr_true_false_set, right_set.data[k].p_expression);
if (index == -1)
{
index = expr_true_false_set->size;
true_false_set_push_back(expr_true_false_set, &item4);
}

struct true_false_set_item item4 = {
.p_expression = right_set.data[k].p_expression
};
//Tudo que faz left true e right true faz expressao se true
expr_true_false_set->data[index].p_expression = right_set.data[k].p_expression;
//d->data[index].true_branch_state |= right_set.data[k].true_branch_state;
//Tudo que faz left true ou left false, e right false faz ser false
expr_true_false_set->data[index].false_branch_state |= right_set.data[k].false_branch_state;

true_false_set_push_back(expr_true_false_set, &item4);
}
//No path true seria possivel nao ser feito o right
expr_true_false_set->data[index].true_branch_state |= (BOOLEAN_FLAG_TRUE | BOOLEAN_FLAG_FALSE);

//Tudo que faz left true e right true faz expressao se true
expr_true_false_set->data[index].p_expression = right_set.data[k].p_expression;
//d->data[index].true_branch_state |= right_set.data[k].true_branch_state;
//Tudo que faz left true ou left false, e right false faz ser false
expr_true_false_set->data[index].false_branch_state |= right_set.data[k].false_branch_state;
}

//No path true seria possivel nao ser feito o right
expr_true_false_set->data[index].true_branch_state |= (BOOLEAN_FLAG_TRUE | BOOLEAN_FLAG_FALSE);
//TODO we whould not restore the previous states for states that
//are not true/false
// if (false || init(a)) ... we cannot undo the out a
arena_restore_current_state_from(ctx, original_state_number);
arena_remove_state(ctx, original_state_number);

true_false_set_destroy(&left_set);
true_false_set_destroy(&right_set);
}

arena_restore_current_state_from(ctx, original_state_number);
arena_remove_state(ctx, original_state_number);
true_false_set_destroy(&left_set);
true_false_set_destroy(&right_set);
}
break;

Expand All @@ -2494,11 +2502,11 @@ static void flow_visit_expression(struct flow_visit_ctx* ctx, struct expression*
flow_check_pointer_used_as_bool(ctx, p_expression->left);
flow_check_pointer_used_as_bool(ctx, p_expression->right);

const int original_state_number = arena_add_copy_of_current_state(ctx, "original");

struct true_false_set left_set = { 0 };
flow_visit_expression(ctx, p_expression->left, &left_set);

const int original_state_number = arena_add_copy_of_current_state(ctx, "original");

//Set all variables to true state, because otherwise, the right branch
// would not be evaluated
Expand Down
1,805 changes: 908 additions & 897 deletions src/web/cake.js

Large diffs are not rendered by default.

Loading

0 comments on commit 74c514e

Please sign in to comment.