Skip to content

Commit 4a8a474

Browse files
committed
* introduced 'let' directive
1 parent 947a8ae commit 4a8a474

File tree

14 files changed

+203
-132
lines changed

14 files changed

+203
-132
lines changed

README.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
- [meta](#meta-)
66
- [option](#option-)
77
- [check](#check-)
8-
- [set](#set-)
8+
- [set|let](#set--let-)
99
- [env](#env-)
1010
- [${}](#-variable-evaluation)
1111
- [@{}](#-program-output-evaluation)
@@ -523,12 +523,17 @@ set {
523523
}
524524
```
525525

526-
# set {...}
526+
# set | let {...}
527527

528528
The `set` rule assigns a value to a variable in the build script.
529+
The expression value is registered during the `init` build phase and then lazily evaluated
530+
upon the first access to that variable.
531+
532+
If a variable is used multiple times in a declarative context (for example, inside [macros](#macros))
533+
the let directive is more appropriate, as it is evaluated every time it is accessed in every build phase.
529534

530535
```cfg
531-
set {
536+
set | let {
532537
| NAME
533538
| _
534539
| parent { NAME }
@@ -538,8 +543,6 @@ set {
538543
}
539544
```
540545

541-
`set` is a lazily evaluated rule - the value of set is only computed if the variable or expression is actually used.
542-
543546
The most common form is `set { NAME [VALUES]... }`
544547

545548
Note that in Autark, all variables are either strings or lists. A list is just a string internally,
@@ -1243,7 +1246,7 @@ Example:
12431246
```cfg
12441247
macro {
12451248
M_ECHO
1246-
set {
1249+
let {
12471250
JOIN
12481251
^{&{1} ' ' &{2}}
12491252
}

autark_core.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,17 +52,23 @@ void unit_env_set_val(struct unit *u, const char *key, const char *val) {
5252
map_put_str(u->env, key, item);
5353
}
5454

55-
void unit_env_set_node(struct unit *u, const char *key, struct node *n) {
55+
void unit_env_set_node(struct unit *u, const char *key, struct node *n, unsigned tag) {
5656
struct unit_env_item *item = xmalloc(sizeof(*item));
5757
item->val = 0;
5858
item->n = n;
59+
item->tag = tag;
5960
map_put_str(u->env, key, item);
6061
}
6162

62-
struct node* unit_env_get_node(struct unit *u, const char *key) {
63+
struct node* unit_env_get_node(struct unit *u, const char *key, unsigned *out_tag) {
6364
struct unit_env_item *item = map_get(u->env, key);
6465
if (item) {
66+
if (out_tag) {
67+
*out_tag = item->tag;
68+
}
6569
return item->n;
70+
} else if (out_tag) {
71+
*out_tag = 0;
6672
}
6773
return 0;
6874
}

dist/autark.c

Lines changed: 61 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#define CONFIG_H
33

44
#define META_VERSION "0.9.0"
5-
#define META_REVISION "e6bb7fe"
5+
#define META_REVISION "947a8ae"
66

77
#define MACRO_MAX_RECURSIVE_CALLS 128
88

@@ -755,6 +755,10 @@ char* path_basename(char *path);
755755
#include <stdbool.h>
756756
#endif
757757

758+
#define TAG_INIT 1
759+
#define TAG_SETUP 2
760+
#define TAG_BUILD 3
761+
758762
#define AUTARK_CACHE "autark-cache"
759763
#define AUTARK_SCRIPT "Autark"
760764

@@ -771,6 +775,7 @@ char* path_basename(char *path);
771775
struct unit_env_item {
772776
const char *val;
773777
struct node *n;
778+
unsigned tag;
774779
};
775780

776781
/// Current execution unit.
@@ -811,7 +816,7 @@ struct env {
811816
const char *prefix_dir; // Absolute path to install prefix dir.
812817
const char *bin_dir; // Path to the bin dir relative to prefix.
813818
const char *lib_dir; // Path to lib dir relative to prefix.
814-
const char *data_dir; // Path to lib data dir relative to prefix.
819+
const char *data_dir; // Path to lib data dir relative to prefix.
815820
const char *include_dir; // Path to include headers dir relative to prefix.
816821
const char *pkgconf_dir; // Path to pkgconfig dir.
817822
const char *man_dir; // Path to man pages dir.
@@ -856,9 +861,9 @@ void unit_ch_src_dir(struct unit*, char *prevcwd);
856861

857862
void unit_env_set_val(struct unit*, const char *key, const char *val);
858863

859-
void unit_env_set_node(struct unit*, const char *key, struct node *n);
864+
void unit_env_set_node(struct unit*, const char *key, struct node *n, unsigned tag);
860865

861-
struct node* unit_env_get_node(struct unit *u, const char *key);
866+
struct node* unit_env_get_node(struct unit *u, const char *key, unsigned *out_tag);
862867

863868
const char* unit_env_get(struct node *n, const char *key);
864869

@@ -1100,7 +1105,7 @@ const char* node_env_get(struct node*, const char *key);
11001105

11011106
void node_env_set(struct node*, const char *key, const char *val);
11021107

1103-
void node_env_set_node(struct node*, const char *key);
1108+
void node_env_set_node(struct node*, const char *key, unsigned tag);
11041109

11051110
struct node* node_by_product(struct node*, const char *prod, char pathbuf[PATH_MAX]);
11061111

@@ -3834,6 +3839,17 @@ int node_check_setup(struct node *n) {
38343839

38353840
static const char* _set_value_get(struct node *n);
38363841

3842+
static void _set_dispose(struct node *n) {
3843+
if ((uintptr_t) n->impl != (uintptr_t) -1) {
3844+
free(n->impl);
3845+
}
3846+
n->impl = 0;
3847+
}
3848+
3849+
static bool _set_is_let(struct node *n) {
3850+
return strcmp(n->value, "let") == 0;
3851+
}
3852+
38373853
static struct unit* _unit_for_set(struct node *n, struct node *nn, const char **keyp) {
38383854
if (nn->type == NODE_TYPE_BAG) {
38393855
if (strcmp(nn->value, "root") == 0) {
@@ -3849,10 +3865,29 @@ static struct unit* _unit_for_set(struct node *n, struct node *nn, const char **
38493865
return unit_peek();
38503866
}
38513867

3852-
static void _set_init(struct node *n);
3868+
static void _set_init_impl(struct node *n) {
3869+
const char *key = 0;
3870+
struct unit *unit = n->child ? _unit_for_set(n, n->child, &key) : 0;
3871+
if (!key) {
3872+
node_warn(n, "No name specified for 'set' directive");
3873+
return;
3874+
}
3875+
unsigned tag = 0;
3876+
struct node *nn = unit_env_get_node(unit, key, &tag);
3877+
if (nn && nn != n) {
3878+
n->recur_next.n = nn;
3879+
}
3880+
unit_env_set_node(unit, key, n, 0);
3881+
}
3882+
3883+
static void _set_init(struct node *n) {
3884+
_set_init_impl(n);
3885+
}
38533886

38543887
static void _set_setup(struct node *n) {
3855-
_set_init(n);
3888+
if (_set_is_let(n)) {
3889+
_set_init_impl(n);
3890+
}
38563891
if (n->child && strcmp(n->value, "env") == 0) {
38573892
const char *v = _set_value_get(n);
38583893
if (v) {
@@ -3868,18 +3903,10 @@ static void _set_setup(struct node *n) {
38683903
}
38693904
}
38703905

3871-
static void _set_init(struct node *n) {
3872-
const char *key = 0;
3873-
struct unit *unit = n->child ? _unit_for_set(n, n->child, &key) : 0;
3874-
if (!key) {
3875-
node_warn(n, "No name specified for 'set' directive");
3876-
return;
3877-
}
3878-
struct node *nn = unit_env_get_node(unit, key);
3879-
if (nn && nn != n) {
3880-
n->recur_next.n = nn;
3906+
static void _set_build(struct node *n) {
3907+
if (_set_is_let(n)) {
3908+
_set_init_impl(n);
38813909
}
3882-
unit_env_set_node(unit, key, n);
38833910
}
38843911

38853912
static const char* _set_value_get(struct node *n) {
@@ -3889,7 +3916,7 @@ static const char* _set_value_get(struct node *n) {
38893916
n->recur_next.active = true;
38903917

38913918
struct node_foreach *fe = node_find_parent_foreach(n);
3892-
if (fe) {
3919+
if (fe || _set_is_let(n)) {
38933920
if ((uintptr_t) n->impl != (uintptr_t) -1) {
38943921
free(n->impl);
38953922
}
@@ -3941,24 +3968,13 @@ static const char* _set_value_get(struct node *n) {
39413968
return n->impl;
39423969
}
39433970

3944-
static void _set_dispose(struct node *n) {
3945-
if ((uintptr_t) n->impl != (uintptr_t) -1) {
3946-
free(n->impl);
3947-
}
3948-
n->impl = 0;
3949-
}
3950-
3951-
static void _set_build(struct node *n) {
3952-
_set_init(n);
3953-
}
3954-
39553971
int node_set_setup(struct node *n) {
39563972
n->flags |= NODE_FLG_NO_CWD;
39573973
n->init = _set_init;
39583974
n->setup = _set_setup;
3975+
n->build = _set_build;
39593976
n->value_get = _set_value_get;
39603977
n->dispose = _set_dispose;
3961-
n->build = _set_build;
39623978
return 0;
39633979
}
39643980
#ifndef _AMALGAMATE_
@@ -6484,7 +6500,7 @@ static void _find_init(struct node *n) {
64846500
node_fatal(AK_ERROR_SCRIPT_SYNTAX, n, "No name specified for '%s' directive", n->value);
64856501
return;
64866502
}
6487-
unit_env_set_node(unit, key, n);
6503+
unit_env_set_node(unit, key, n, TAG_INIT);
64886504
}
64896505

64906506
static void _find_dispose(struct node *n) {
@@ -6551,7 +6567,7 @@ static void _macro_init(struct node *n) {
65516567
return;
65526568
}
65536569
_macro_remove(n);
6554-
unit_env_set_node(unit, key, n);
6570+
unit_env_set_node(unit, key, n, TAG_INIT);
65556571
}
65566572

65576573
static void _macro_dispose(struct node *n) {
@@ -6682,7 +6698,7 @@ static void _call_init(struct node *n) {
66826698
node_warn(n, "No name specified for 'call' directive");
66836699
return;
66846700
}
6685-
struct node *mn = unit_env_get_node(unit, key);
6701+
struct node *mn = unit_env_get_node(unit, key, 0);
66866702
if (!mn) {
66876703
node_fatal(0, n, "Unknown script macro: %s", key);
66886704
return;
@@ -6786,17 +6802,23 @@ void unit_env_set_val(struct unit *u, const char *key, const char *val) {
67866802
map_put_str(u->env, key, item);
67876803
}
67886804

6789-
void unit_env_set_node(struct unit *u, const char *key, struct node *n) {
6805+
void unit_env_set_node(struct unit *u, const char *key, struct node *n, unsigned tag) {
67906806
struct unit_env_item *item = xmalloc(sizeof(*item));
67916807
item->val = 0;
67926808
item->n = n;
6809+
item->tag = tag;
67936810
map_put_str(u->env, key, item);
67946811
}
67956812

6796-
struct node* unit_env_get_node(struct unit *u, const char *key) {
6813+
struct node* unit_env_get_node(struct unit *u, const char *key, unsigned *out_tag) {
67976814
struct unit_env_item *item = map_get(u->env, key);
67986815
if (item) {
6816+
if (out_tag) {
6817+
*out_tag = item->tag;
6818+
}
67996819
return item->n;
6820+
} else if (out_tag) {
6821+
*out_tag = 0;
68006822
}
68016823
return 0;
68026824
}
@@ -8385,7 +8407,7 @@ static unsigned _rule_type(const char *key, unsigned *flags) {
83858407
return NODE_TYPE_SUBST;
83868408
} else if (strcmp(key, "^") == 0) {
83878409
return NODE_TYPE_JOIN;
8388-
} else if (strcmp(key, "set") == 0 || strcmp(key, "env") == 0) {
8410+
} else if (strcmp(key, "set") == 0 || strcmp(key, "env") == 0 || strcmp(key, "let") == 0) {
83898411
return NODE_TYPE_SET;
83908412
} else if (strcmp(key, "check") == 0) {
83918413
return NODE_TYPE_CHECK;
@@ -9199,14 +9221,14 @@ void node_env_set(struct node *n, const char *key, const char *val) {
91999221
}
92009222
}
92019223

9202-
void node_env_set_node(struct node *n_, const char *key) {
9224+
void node_env_set_node(struct node *n_, const char *key, unsigned tag) {
92039225
if (key[0] == '_' && key[1] == '\0') {
92049226
// Skip on special '_' key
92059227
return;
92069228
}
92079229
for (struct node *n = n_; n; n = n->parent) {
92089230
if (n->unit) {
9209-
unit_env_set_node(n->unit, key, n_);
9231+
unit_env_set_node(n->unit, key, n_, tag);
92109232
return;
92119233
}
92129234
}

0 commit comments

Comments
 (0)