flaremc 0.2.2__tar.gz → 0.2.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {flaremc-0.2.2 → flaremc-0.2.3}/PKG-INFO +1 -1
- {flaremc-0.2.2 → flaremc-0.2.3}/flare/cli.py +7 -0
- {flaremc-0.2.2 → flaremc-0.2.3}/flare/command_parser.py +2 -2
- {flaremc-0.2.2 → flaremc-0.2.3}/flare/compiler.py +12 -12
- {flaremc-0.2.2 → flaremc-0.2.3}/flare/context.py +68 -32
- {flaremc-0.2.2 → flaremc-0.2.3}/flare/control_flow.py +41 -39
- {flaremc-0.2.2 → flaremc-0.2.3}/flare/execute_modifiers.py +7 -7
- {flaremc-0.2.2 → flaremc-0.2.3}/flare/preprocessor.py +52 -7
- {flaremc-0.2.2 → flaremc-0.2.3}/flare/validator/matchers.py +35 -2
- {flaremc-0.2.2 → flaremc-0.2.3}/flare/validator/schema.py +9 -1
- {flaremc-0.2.2 → flaremc-0.2.3}/flare/variables/bigscore.py +40 -40
- {flaremc-0.2.2 → flaremc-0.2.3}/flare/variables/core.py +2 -2
- {flaremc-0.2.2 → flaremc-0.2.3}/flare/variables/float32.py +119 -119
- {flaremc-0.2.2 → flaremc-0.2.3}/flare/variables/float64.py +41 -41
- {flaremc-0.2.2 → flaremc-0.2.3}/flare/variables/nbt.py +190 -169
- {flaremc-0.2.2 → flaremc-0.2.3}/flare/variables/score.py +148 -148
- {flaremc-0.2.2 → flaremc-0.2.3}/flare/variables/selector.py +7 -7
- {flaremc-0.2.2 → flaremc-0.2.3}/flaremc.egg-info/PKG-INFO +1 -1
- {flaremc-0.2.2 → flaremc-0.2.3}/pyproject.toml +1 -1
- {flaremc-0.2.2 → flaremc-0.2.3}/LICENSE +0 -0
- {flaremc-0.2.2 → flaremc-0.2.3}/README.md +0 -0
- {flaremc-0.2.2 → flaremc-0.2.3}/flare/__init__.py +0 -0
- {flaremc-0.2.2 → flaremc-0.2.3}/flare/__main__.py +0 -0
- {flaremc-0.2.2 → flaremc-0.2.3}/flare/math.py +0 -0
- {flaremc-0.2.2 → flaremc-0.2.3}/flare/nbt_schema.py +0 -0
- {flaremc-0.2.2 → flaremc-0.2.3}/flare/types.py +0 -0
- {flaremc-0.2.2 → flaremc-0.2.3}/flare/validator/__init__.py +0 -0
- {flaremc-0.2.2 → flaremc-0.2.3}/flare/validator/core.py +0 -0
- {flaremc-0.2.2 → flaremc-0.2.3}/flare/validator/parser.py +0 -0
- {flaremc-0.2.2 → flaremc-0.2.3}/flare/variables/__init__.py +0 -0
- {flaremc-0.2.2 → flaremc-0.2.3}/flare/variables/complex.py +0 -0
- {flaremc-0.2.2 → flaremc-0.2.3}/flare/variables/storage.py +0 -0
- {flaremc-0.2.2 → flaremc-0.2.3}/flaremc.egg-info/SOURCES.txt +0 -0
- {flaremc-0.2.2 → flaremc-0.2.3}/flaremc.egg-info/dependency_links.txt +0 -0
- {flaremc-0.2.2 → flaremc-0.2.3}/flaremc.egg-info/entry_points.txt +0 -0
- {flaremc-0.2.2 → flaremc-0.2.3}/flaremc.egg-info/requires.txt +0 -0
- {flaremc-0.2.2 → flaremc-0.2.3}/flaremc.egg-info/top_level.txt +0 -0
- {flaremc-0.2.2 → flaremc-0.2.3}/flarevsc/node_modules/flatted/python/flatted.py +0 -0
- {flaremc-0.2.2 → flaremc-0.2.3}/setup.cfg +0 -0
- {flaremc-0.2.2 → flaremc-0.2.3}/tests/test_flare.py +0 -0
|
@@ -96,6 +96,7 @@ def _build_datapack_inner(file_path: str, cli_overrides: dict = None):
|
|
|
96
96
|
global_env = {"__name__": "__main__", "__file__": abs_path}
|
|
97
97
|
exec(
|
|
98
98
|
"from flare import _flare_assign, _flare_aug_assign, _flare_if, _flare_while, _flare_for, _flare_with, runcommand, _flare_return, _flare_break, _flare_continue\n"
|
|
99
|
+
"from flare import context as ctx\n"
|
|
99
100
|
"from flare.command_parser import interpolate_command\n"
|
|
100
101
|
"from flare import _flare_print as print, selector, _as, at, positioned, aligned, facing, anchored, rotated, dimension, applyon, on, summon, store\n"
|
|
101
102
|
"from flare import nbt, score, fixed, tagged, ref, getscore, storage, array, byte, boolean, short, long, double\n"
|
|
@@ -153,8 +154,14 @@ def _build_datapack_inner(file_path: str, cli_overrides: dict = None):
|
|
|
153
154
|
if ":" in filename:
|
|
154
155
|
ns, name = filename.split(":", 1)
|
|
155
156
|
file_p = build_dir / "data" / ns / "functions" / f"{name}.mcfunction"
|
|
157
|
+
is_top_level = "generated_" not in name and "while_" not in name and name not in ("main", "load")
|
|
156
158
|
else:
|
|
157
159
|
file_p = build_dir / "data" / context._current_namespace / "functions" / f"{filename}.mcfunction"
|
|
160
|
+
is_top_level = "generated_" not in filename and "while_" not in filename and filename not in ("main",
|
|
161
|
+
"load")
|
|
162
|
+
|
|
163
|
+
if is_top_level and lines and lines[-1] in ("return 1", "return 0"):
|
|
164
|
+
lines.pop()
|
|
158
165
|
|
|
159
166
|
file_p.parent.mkdir(parents=True, exist_ok=True)
|
|
160
167
|
with open(file_p, "w") as f:
|
|
@@ -71,7 +71,7 @@ def interpolate_command(command: str, local_vars: dict, global_vars: dict) -> st
|
|
|
71
71
|
elif not is_key and ident in local_vars:
|
|
72
72
|
val = local_vars[ident]
|
|
73
73
|
if hasattr(val, "addr"):
|
|
74
|
-
output.append(val.
|
|
74
|
+
output.append(val._addr)
|
|
75
75
|
elif hasattr(val, "target"):
|
|
76
76
|
output.append(val.target)
|
|
77
77
|
elif isinstance(val, dict) and output and output[-1].endswith("**"):
|
|
@@ -88,7 +88,7 @@ def interpolate_command(command: str, local_vars: dict, global_vars: dict) -> st
|
|
|
88
88
|
elif not is_key and ident in global_vars:
|
|
89
89
|
val = global_vars[ident]
|
|
90
90
|
if hasattr(val, "addr"):
|
|
91
|
-
output.append(val.
|
|
91
|
+
output.append(val._addr)
|
|
92
92
|
elif hasattr(val, "target"):
|
|
93
93
|
output.append(val.target)
|
|
94
94
|
elif isinstance(val, dict) and output and output[-1].endswith("**"):
|
|
@@ -29,9 +29,9 @@ def _compile_relational(node, invert=False):
|
|
|
29
29
|
|
|
30
30
|
if not isinstance(right, score):
|
|
31
31
|
if isinstance(right, (int, float)):
|
|
32
|
-
right = getscore(right, left.
|
|
32
|
+
right = getscore(right, left._multiplier)
|
|
33
33
|
else:
|
|
34
|
-
t = score(addr=f"!c{ctx._temp_id} {temp_obj}", multiplier=left.
|
|
34
|
+
t = score(addr=f"!c{ctx._temp_id} {temp_obj}", multiplier=left._multiplier)
|
|
35
35
|
ctx._temp_id += 1
|
|
36
36
|
if isinstance(right, (BinaryOp, UnaryOp)):
|
|
37
37
|
right._eval_into(t)
|
|
@@ -39,42 +39,42 @@ def _compile_relational(node, invert=False):
|
|
|
39
39
|
t.__iset__(right)
|
|
40
40
|
right = t
|
|
41
41
|
|
|
42
|
-
if left.
|
|
43
|
-
t = score(addr=f"!c{ctx._temp_id} {temp_obj}", multiplier=left.
|
|
42
|
+
if left._multiplier != right._multiplier:
|
|
43
|
+
t = score(addr=f"!c{ctx._temp_id} {temp_obj}", multiplier=left._multiplier)
|
|
44
44
|
ctx._temp_id += 1
|
|
45
45
|
t.__iset__(right)
|
|
46
46
|
right = t
|
|
47
47
|
|
|
48
|
-
return f"{keyword} score {left.
|
|
48
|
+
return f"{keyword} score {left._addr} {mcop} {right._addr}"
|
|
49
49
|
|
|
50
50
|
|
|
51
51
|
def _eval_to_bool_score(node):
|
|
52
52
|
dest = score(addr=f"!b{ctx._temp_id} {temp_obj}")
|
|
53
53
|
ctx._temp_id += 1
|
|
54
|
-
runcommand(f"scoreboard players set {dest.
|
|
54
|
+
runcommand(f"scoreboard players set {dest._addr} 0")
|
|
55
55
|
|
|
56
56
|
if isinstance(node, BinaryOp) and node.op == "or":
|
|
57
57
|
left_conds = _flatten_and(node.left)
|
|
58
|
-
runcommand(f"execute {' '.join(left_conds)} run scoreboard players set {dest.
|
|
58
|
+
runcommand(f"execute {' '.join(left_conds)} run scoreboard players set {dest._addr} 1")
|
|
59
59
|
right_conds = _flatten_and(node.right)
|
|
60
60
|
runcommand(
|
|
61
|
-
f"execute if score {dest.
|
|
61
|
+
f"execute if score {dest._addr} matches 0 {' '.join(right_conds)} run scoreboard players set {dest._addr} 1")
|
|
62
62
|
return dest
|
|
63
63
|
|
|
64
64
|
if isinstance(node, UnaryOp) and node.op == "not":
|
|
65
65
|
sub_dest = _eval_to_bool_score(node.operand)
|
|
66
|
-
runcommand(f"execute if score {sub_dest.
|
|
66
|
+
runcommand(f"execute if score {sub_dest._addr} matches 0 run scoreboard players set {dest._addr} 1")
|
|
67
67
|
return dest
|
|
68
68
|
|
|
69
69
|
if isinstance(node, (BinaryOp, UnaryOp)):
|
|
70
70
|
t = score(addr=f"!b{ctx._temp_id} {temp_obj}")
|
|
71
71
|
ctx._temp_id += 1
|
|
72
72
|
node._eval_into(t)
|
|
73
|
-
runcommand(f"execute unless score {t.
|
|
73
|
+
runcommand(f"execute unless score {t._addr} matches 0 run scoreboard players set {dest._addr} 1")
|
|
74
74
|
return dest
|
|
75
75
|
|
|
76
76
|
if node:
|
|
77
|
-
runcommand(f"scoreboard players set {dest.
|
|
77
|
+
runcommand(f"scoreboard players set {dest._addr} 1")
|
|
78
78
|
return dest
|
|
79
79
|
|
|
80
80
|
|
|
@@ -84,4 +84,4 @@ def _flatten_and(node, invert=False):
|
|
|
84
84
|
|
|
85
85
|
dest = _eval_to_bool_score(node)
|
|
86
86
|
keyword = "unless" if invert else "if"
|
|
87
|
-
return [f"{keyword} score {dest.
|
|
87
|
+
return [f"{keyword} score {dest._addr} matches 1"]
|
|
@@ -8,9 +8,39 @@ current_file = "main"
|
|
|
8
8
|
_current_namespace = "flare"
|
|
9
9
|
functions = {}
|
|
10
10
|
constants = {}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class DynamicVar:
|
|
14
|
+
def __init__(self, fmt):
|
|
15
|
+
self.fmt = fmt
|
|
16
|
+
|
|
17
|
+
def __str__(self):
|
|
18
|
+
return self.fmt.format(ns=_current_namespace)
|
|
19
|
+
|
|
20
|
+
def __format__(self, format_spec):
|
|
21
|
+
return format(str(self), format_spec)
|
|
22
|
+
|
|
23
|
+
def __add__(self, other):
|
|
24
|
+
return str(self) + other
|
|
25
|
+
|
|
26
|
+
def __radd__(self, other):
|
|
27
|
+
return other + str(self)
|
|
28
|
+
|
|
29
|
+
def __hash__(self):
|
|
30
|
+
return hash(str(self))
|
|
31
|
+
|
|
32
|
+
def __eq__(self, other):
|
|
33
|
+
return str(self) == str(other)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
constant_obj = DynamicVar("__{ns}__constant__")
|
|
37
|
+
vars_obj = DynamicVar("__{ns}__vars__")
|
|
38
|
+
temp_obj = DynamicVar("__{ns}__temp__")
|
|
39
|
+
temp_storage = DynamicVar("{ns}:__flare_temp__")
|
|
40
|
+
vars_storage = DynamicVar("{ns}:__flare_vars__")
|
|
41
|
+
args_storage = DynamicVar("{ns}:__flare_args__")
|
|
42
|
+
returns_storage = DynamicVar("{ns}:__flare_returns__")
|
|
43
|
+
|
|
14
44
|
_temp_id = 0
|
|
15
45
|
_func_id = 0
|
|
16
46
|
_objective_offset = 0
|
|
@@ -138,28 +168,28 @@ def _flare_print(*args):
|
|
|
138
168
|
|
|
139
169
|
if isinstance(arg, score):
|
|
140
170
|
if getattr(arg, "multiplier", 1.0) != 1.0:
|
|
141
|
-
scale_str = f"{arg.
|
|
171
|
+
scale_str = f"{arg._multiplier:.15f}".rstrip("0")
|
|
142
172
|
if scale_str.endswith("."):
|
|
143
173
|
scale_str += "0"
|
|
144
174
|
runcommand(
|
|
145
|
-
f"execute store result storage
|
|
146
|
-
components.append({"nbt": f"__flare_debug_{i}", "storage":
|
|
175
|
+
f"execute store result storage {temp_storage} __flare_debug_{i} double {scale_str} run scoreboard players get {arg._addr}")
|
|
176
|
+
components.append({"nbt": f"__flare_debug_{i}", "storage": str(temp_storage)})
|
|
147
177
|
else:
|
|
148
|
-
name, obj = arg.
|
|
178
|
+
name, obj = arg._addr.split(" ", 1)
|
|
149
179
|
components.append({"score": {"name": name, "objective": obj}})
|
|
150
180
|
elif isinstance(arg, nbt):
|
|
151
|
-
nbt_comp = {"nbt": arg.
|
|
152
|
-
if arg.
|
|
181
|
+
nbt_comp = {"nbt": arg._path or "{}"}
|
|
182
|
+
if arg._path == "":
|
|
153
183
|
nbt_comp["nbt"] = "{}"
|
|
154
184
|
|
|
155
|
-
if arg.
|
|
156
|
-
nbt_comp["storage"] = arg.
|
|
157
|
-
elif arg.
|
|
158
|
-
nbt_comp["entity"] = arg.
|
|
159
|
-
elif arg.
|
|
160
|
-
nbt_comp["block"] = arg.
|
|
185
|
+
if arg._target_type == "storage":
|
|
186
|
+
nbt_comp["storage"] = arg._target
|
|
187
|
+
elif arg._target_type == "entity":
|
|
188
|
+
nbt_comp["entity"] = arg._target
|
|
189
|
+
elif arg._target_type == "block":
|
|
190
|
+
nbt_comp["block"] = arg._target
|
|
161
191
|
|
|
162
|
-
if arg.
|
|
192
|
+
if arg._path == "":
|
|
163
193
|
nbt_comp["nbt"] = "{}"
|
|
164
194
|
|
|
165
195
|
components.append(nbt_comp)
|
|
@@ -178,15 +208,21 @@ def _flare_print(*args):
|
|
|
178
208
|
runcommand(f"tellraw @a {cmd_text}")
|
|
179
209
|
|
|
180
210
|
|
|
181
|
-
def export(func=None, *, append=False):
|
|
211
|
+
def export(func=None, *, name=None, append=False):
|
|
182
212
|
from flare import score # avoid circular import
|
|
213
|
+
|
|
214
|
+
if isinstance(func, str):
|
|
215
|
+
name = func
|
|
216
|
+
func = None
|
|
217
|
+
|
|
183
218
|
if func is None:
|
|
184
219
|
def wrapper(f):
|
|
185
|
-
return export(f, append=append)
|
|
220
|
+
return export(f, name=name, append=append)
|
|
186
221
|
|
|
187
222
|
return wrapper
|
|
188
223
|
|
|
189
|
-
|
|
224
|
+
actual_name = name if name is not None else func.__name__
|
|
225
|
+
func_name = f"{_current_namespace}:{actual_name}"
|
|
190
226
|
if func_name in files and not append:
|
|
191
227
|
raise ValueError(f"Function {func_name} already exists. Use @export(append=True) to append.")
|
|
192
228
|
|
|
@@ -208,9 +244,9 @@ def export(func=None, *, append=False):
|
|
|
208
244
|
kwargs[name] = score(addr=f"{func.__name__}_{name} {vars_obj}")
|
|
209
245
|
elif hasattr(anno, "__name__") and anno.__name__ in ("nbt", "_TypedNBT"):
|
|
210
246
|
if is_recursive:
|
|
211
|
-
kwargs[name] = anno(addr=f"storage
|
|
247
|
+
kwargs[name] = anno(addr=f"storage {args_storage} {func.__name__}_{name}[-1]")
|
|
212
248
|
else:
|
|
213
|
-
kwargs[name] = anno(addr=f"storage
|
|
249
|
+
kwargs[name] = anno(addr=f"storage {args_storage} {func.__name__}_{name}")
|
|
214
250
|
elif anno is not inspect.Signature.empty:
|
|
215
251
|
raise TypeError(f"Argument '{name}' must be typed as score or nbt, not {anno}")
|
|
216
252
|
else:
|
|
@@ -239,20 +275,20 @@ def export(func=None, *, append=False):
|
|
|
239
275
|
target = kwargs[arg_name]
|
|
240
276
|
|
|
241
277
|
if is_recursive and isinstance(target, nbt):
|
|
242
|
-
base_addr = f"storage
|
|
278
|
+
base_addr = f"storage {args_storage} {func.__name__}_{arg_name}"
|
|
243
279
|
if isinstance(arg_val, (int, float, str)):
|
|
244
280
|
runcommand(f"data modify {base_addr} append value {json.dumps(arg_val)}")
|
|
245
281
|
elif isinstance(arg_val, nbt):
|
|
246
|
-
runcommand(f"data modify {base_addr} append from {arg_val.
|
|
282
|
+
runcommand(f"data modify {base_addr} append from {arg_val._addr}")
|
|
247
283
|
elif isinstance(arg_val, score):
|
|
248
284
|
runcommand(f"data modify {base_addr} append value 0")
|
|
249
285
|
runcommand(
|
|
250
|
-
f"execute store result {base_addr}[-1] int {1 / arg_val.
|
|
286
|
+
f"execute store result {base_addr}[-1] int {1 / arg_val._multiplier} run scoreboard players get {arg_val._addr}")
|
|
251
287
|
elif hasattr(type(arg_val), "_eval_into"):
|
|
252
|
-
temp = nbt(addr=f"storage
|
|
288
|
+
temp = nbt(addr=f"storage {temp_storage} !t{_temp_id}", datatype=target._type)
|
|
253
289
|
_temp_id += 1
|
|
254
290
|
arg_val._eval_into(temp)
|
|
255
|
-
runcommand(f"data modify {base_addr} append from {temp.
|
|
291
|
+
runcommand(f"data modify {base_addr} append from {temp._addr}")
|
|
256
292
|
else:
|
|
257
293
|
target.__iset__(arg_val)
|
|
258
294
|
|
|
@@ -261,7 +297,7 @@ def export(func=None, *, append=False):
|
|
|
261
297
|
if is_recursive:
|
|
262
298
|
for arg_name in bound.arguments.keys():
|
|
263
299
|
if isinstance(kwargs[arg_name], nbt):
|
|
264
|
-
base_addr = f"storage
|
|
300
|
+
base_addr = f"storage {args_storage} {func.__name__}_{arg_name}"
|
|
265
301
|
runcommand(f"data remove {base_addr}[-1]")
|
|
266
302
|
|
|
267
303
|
ret_anno = return_types.get(func_name, sig.return_annotation)
|
|
@@ -272,15 +308,15 @@ def export(func=None, *, append=False):
|
|
|
272
308
|
temp_ret = score(addr=f"!ret{_temp_id} {temp_obj}")
|
|
273
309
|
_temp_id += 1
|
|
274
310
|
runcommand(
|
|
275
|
-
f"scoreboard players operation {temp_ret.
|
|
311
|
+
f"scoreboard players operation {temp_ret._addr} = {func_name.replace(":", "_")}_ret {vars_obj}")
|
|
276
312
|
if ret_anno.__name__ in ("fixed", "_PrecisionScore"):
|
|
277
313
|
pass
|
|
278
314
|
return temp_ret
|
|
279
315
|
else:
|
|
280
|
-
temp_ret = nbt(addr=f"storage
|
|
316
|
+
temp_ret = nbt(addr=f"storage {temp_storage} !ret{_temp_id}")
|
|
281
317
|
_temp_id += 1
|
|
282
318
|
runcommand(
|
|
283
|
-
f"data modify {temp_ret.
|
|
319
|
+
f"data modify {temp_ret._addr} set from storage {returns_storage} {func_name.replace(':', '_')}")
|
|
284
320
|
return temp_ret
|
|
285
321
|
|
|
286
322
|
proxy = ProxyFunction()
|
|
@@ -402,12 +438,12 @@ def _flare_return(value):
|
|
|
402
438
|
target.__iset__(value)
|
|
403
439
|
else:
|
|
404
440
|
if inspect.isclass(ret_anno) and issubclass(ret_anno, nbt):
|
|
405
|
-
target = ret_anno(addr=f"storage
|
|
441
|
+
target = ret_anno(addr=f"storage {returns_storage} {func_name.replace(':', '_')}")
|
|
406
442
|
else:
|
|
407
443
|
datatype = None
|
|
408
444
|
if hasattr(ret_anno, "__origin__") or isinstance(ret_anno, type):
|
|
409
445
|
datatype = getattr(ret_anno, "__origin__", ret_anno)
|
|
410
|
-
target = nbt(addr=f"storage
|
|
446
|
+
target = nbt(addr=f"storage {returns_storage} {func_name.replace(':', '_')}", datatype=datatype)
|
|
411
447
|
target.__iset__(value)
|
|
412
448
|
|
|
413
449
|
runcommand("return 1")
|
|
@@ -1,9 +1,36 @@
|
|
|
1
1
|
from . import context as ctx
|
|
2
2
|
from .compiler import _flatten_and
|
|
3
3
|
from .context import push_context, runcommand, temp_obj
|
|
4
|
+
from .execute_modifiers import ExecuteChain
|
|
4
5
|
from .variables import score
|
|
5
6
|
|
|
6
7
|
|
|
8
|
+
def _has_early_return(func_name):
|
|
9
|
+
for cmd in ctx.files.get(func_name, []):
|
|
10
|
+
if cmd == "return 1" or cmd.endswith(" run return 1"):
|
|
11
|
+
return True
|
|
12
|
+
return False
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _invoke_block(func_name, cond_str):
|
|
16
|
+
if _has_early_return(func_name):
|
|
17
|
+
if not (ctx.files[func_name] and ctx.files[func_name][-1] in ("return 0", "return 1")):
|
|
18
|
+
ctx.files[func_name].append("return 0")
|
|
19
|
+
ret_temp = score(addr=f"!ret{ctx._temp_id} {ctx.temp_obj}")
|
|
20
|
+
ctx._temp_id += 1
|
|
21
|
+
|
|
22
|
+
if cond_str:
|
|
23
|
+
runcommand(f"execute store result score {ret_temp._addr} {cond_str} run function {func_name}")
|
|
24
|
+
else:
|
|
25
|
+
runcommand(f"execute store result score {ret_temp._addr} run function {func_name}")
|
|
26
|
+
runcommand(f"execute if score {ret_temp._addr} matches 1 run return 1")
|
|
27
|
+
else:
|
|
28
|
+
if cond_str:
|
|
29
|
+
runcommand(f"execute {cond_str} run function {func_name}")
|
|
30
|
+
else:
|
|
31
|
+
runcommand(f"function {func_name}")
|
|
32
|
+
|
|
33
|
+
|
|
7
34
|
def _flare_break():
|
|
8
35
|
runcommand(f"scoreboard players set !break {temp_obj} 1")
|
|
9
36
|
runcommand("return 0")
|
|
@@ -24,7 +51,7 @@ def _flare_if(*args):
|
|
|
24
51
|
if has_else_or_elif:
|
|
25
52
|
sometemp = score(addr=f"!elif{ctx._temp_id} {temp_obj}")
|
|
26
53
|
ctx._temp_id += 1
|
|
27
|
-
runcommand(f"scoreboard players set {sometemp.
|
|
54
|
+
runcommand(f"scoreboard players set {sometemp._addr} 0")
|
|
28
55
|
|
|
29
56
|
for cond_func, body_func in zip(conditions, bodies):
|
|
30
57
|
if cond_func is None:
|
|
@@ -38,16 +65,11 @@ def _flare_if(*args):
|
|
|
38
65
|
cmd = ctx.files[func_name][0]
|
|
39
66
|
del ctx.files[func_name]
|
|
40
67
|
if cmd.startswith("execute "):
|
|
41
|
-
runcommand(f"execute if score {sometemp.
|
|
68
|
+
runcommand(f"execute if score {sometemp._addr} matches 0 {cmd[8:]}")
|
|
42
69
|
else:
|
|
43
|
-
runcommand(f"execute if score {sometemp.
|
|
70
|
+
runcommand(f"execute if score {sometemp._addr} matches 0 run {cmd}")
|
|
44
71
|
else:
|
|
45
|
-
|
|
46
|
-
ret_temp = score(addr=f"!ret{ctx._temp_id} {temp_obj}")
|
|
47
|
-
ctx._temp_id += 1
|
|
48
|
-
runcommand(
|
|
49
|
-
f"execute store result score {ret_temp.addr} if score {sometemp.addr} matches 0 run function {func_name}")
|
|
50
|
-
runcommand(f"execute if score {ret_temp.addr} matches 1 run return 1")
|
|
72
|
+
_invoke_block(func_name, f"if score {sometemp._addr} matches 0")
|
|
51
73
|
else:
|
|
52
74
|
body_func()
|
|
53
75
|
break
|
|
@@ -67,16 +89,11 @@ def _flare_if(*args):
|
|
|
67
89
|
cmd = ctx.files[func_name][0]
|
|
68
90
|
del ctx.files[func_name]
|
|
69
91
|
if cmd.startswith("execute "):
|
|
70
|
-
runcommand(f"execute if score {sometemp.
|
|
92
|
+
runcommand(f"execute if score {sometemp._addr} matches 0 {cmd[8:]}")
|
|
71
93
|
else:
|
|
72
|
-
runcommand(f"execute if score {sometemp.
|
|
94
|
+
runcommand(f"execute if score {sometemp._addr} matches 0 run {cmd}")
|
|
73
95
|
else:
|
|
74
|
-
|
|
75
|
-
ret_temp = score(addr=f"!ret{ctx._temp_id} {temp_obj}")
|
|
76
|
-
ctx._temp_id += 1
|
|
77
|
-
runcommand(
|
|
78
|
-
f"execute store result score {ret_temp.addr} if score {sometemp.addr} matches 0 run function {func_name}")
|
|
79
|
-
runcommand(f"execute if score {ret_temp.addr} matches 1 run return 1")
|
|
96
|
+
_invoke_block(func_name, f"if score {sometemp._addr} matches 0")
|
|
80
97
|
else:
|
|
81
98
|
body_func()
|
|
82
99
|
break
|
|
@@ -85,13 +102,13 @@ def _flare_if(*args):
|
|
|
85
102
|
prefix = f"execute {' '.join(conds)}"
|
|
86
103
|
|
|
87
104
|
if sometemp is not None:
|
|
88
|
-
prefix = f"execute if score {sometemp.
|
|
105
|
+
prefix = f"execute if score {sometemp._addr} matches 0 {' '.join(conds)}"
|
|
89
106
|
|
|
90
107
|
func_name = f"{ctx._current_namespace}:generated_{ctx._func_id}"
|
|
91
108
|
ctx._func_id += 1
|
|
92
109
|
with push_context(func_name):
|
|
93
110
|
if sometemp is not None:
|
|
94
|
-
runcommand(f"scoreboard players set {sometemp.
|
|
111
|
+
runcommand(f"scoreboard players set {sometemp._addr} 1")
|
|
95
112
|
body_func()
|
|
96
113
|
|
|
97
114
|
if ctx.files.get(func_name):
|
|
@@ -103,14 +120,7 @@ def _flare_if(*args):
|
|
|
103
120
|
else:
|
|
104
121
|
runcommand(f"{prefix} run {cmd}")
|
|
105
122
|
else:
|
|
106
|
-
|
|
107
|
-
ret_temp = score(addr=f"!ret{ctx._temp_id} {temp_obj}")
|
|
108
|
-
ctx._temp_id += 1
|
|
109
|
-
if prefix.startswith("execute "):
|
|
110
|
-
runcommand(f"execute store result score {ret_temp.addr} {prefix[8:]} run function {func_name}")
|
|
111
|
-
else:
|
|
112
|
-
runcommand(f"execute store result score {ret_temp.addr} run function {func_name}")
|
|
113
|
-
runcommand(f"execute if score {ret_temp.addr} matches 1 run return 1")
|
|
123
|
+
_invoke_block(func_name, prefix[8:] if prefix.startswith("execute ") else "")
|
|
114
124
|
|
|
115
125
|
|
|
116
126
|
def _flare_while(cond_func, body_func, orelse_func=None, has_break=False, has_continue=False):
|
|
@@ -124,10 +134,7 @@ def _flare_while(cond_func, body_func, orelse_func=None, has_break=False, has_co
|
|
|
124
134
|
with push_context(func_body):
|
|
125
135
|
body_func()
|
|
126
136
|
|
|
127
|
-
|
|
128
|
-
ctx._temp_id += 1
|
|
129
|
-
runcommand(f"execute store result score {ret_body.addr} run function {func_body}")
|
|
130
|
-
runcommand(f"execute if score {ret_body.addr} matches 1 run return 1")
|
|
137
|
+
_invoke_block(func_body, "")
|
|
131
138
|
|
|
132
139
|
if has_break:
|
|
133
140
|
runcommand(f"execute if score !break {temp_obj} matches 1 run return 0")
|
|
@@ -137,11 +144,7 @@ def _flare_while(cond_func, body_func, orelse_func=None, has_break=False, has_co
|
|
|
137
144
|
cond = cond_func()
|
|
138
145
|
conds = _flatten_and(cond)
|
|
139
146
|
prefix = f"execute {' '.join(conds)}"
|
|
140
|
-
|
|
141
|
-
ret_temp = score(addr=f"!ret{ctx._temp_id} {temp_obj}")
|
|
142
|
-
ctx._temp_id += 1
|
|
143
|
-
runcommand(f"execute store result score {ret_temp.addr} {' '.join(conds)} run function {func_name}")
|
|
144
|
-
runcommand(f"execute if score {ret_temp.addr} matches 1 run return 1")
|
|
147
|
+
_invoke_block(func_name, " ".join(conds))
|
|
145
148
|
|
|
146
149
|
if has_break:
|
|
147
150
|
runcommand(f"scoreboard players set !break {temp_obj} 0")
|
|
@@ -151,8 +154,8 @@ def _flare_while(cond_func, body_func, orelse_func=None, has_break=False, has_co
|
|
|
151
154
|
prefix_init = f"execute {' '.join(conds_init)}"
|
|
152
155
|
ret_temp_init = score(addr=f"!ret{ctx._temp_id} {temp_obj}")
|
|
153
156
|
ctx._temp_id += 1
|
|
154
|
-
runcommand(f"execute store result score {ret_temp_init.
|
|
155
|
-
runcommand(f"execute if score {ret_temp_init.
|
|
157
|
+
runcommand(f"execute store result score {ret_temp_init._addr} {' '.join(conds_init)} run function {func_name}")
|
|
158
|
+
runcommand(f"execute if score {ret_temp_init._addr} matches 1 run return 1")
|
|
156
159
|
|
|
157
160
|
if orelse_func:
|
|
158
161
|
if has_break:
|
|
@@ -185,7 +188,6 @@ def _flare_with(*args):
|
|
|
185
188
|
if hasattr(obj, "__with__"):
|
|
186
189
|
obj.__with__(lambda: wrap(idx + 1))
|
|
187
190
|
elif isinstance(obj, str):
|
|
188
|
-
from .execute_modifiers import ExecuteChain
|
|
189
191
|
ExecuteChain(obj).__with__(lambda: wrap(idx + 1))
|
|
190
192
|
else:
|
|
191
193
|
raise TypeError(f"Object of type {type(obj).__name__} does not support __with__")
|
|
@@ -64,7 +64,7 @@ class ExecuteChain:
|
|
|
64
64
|
def store(self, target: Union[score, nbt, str]) -> ExecuteChain:
|
|
65
65
|
if isinstance(target, score):
|
|
66
66
|
target._check_addr()
|
|
67
|
-
return self._add(f"store result score {target.
|
|
67
|
+
return self._add(f"store result score {target._addr}")
|
|
68
68
|
elif isinstance(target, nbt):
|
|
69
69
|
target._check_addr()
|
|
70
70
|
return StoreExecuteChain(self.fragments.copy(), target)
|
|
@@ -101,23 +101,23 @@ class ExecuteChain:
|
|
|
101
101
|
ret_temp = score(addr=f"!ret{ctx._temp_id} {ctx.temp_obj}")
|
|
102
102
|
ctx._temp_id += 1
|
|
103
103
|
if prefix.startswith("execute "):
|
|
104
|
-
ctx.runcommand(f"execute store result score {ret_temp.
|
|
104
|
+
ctx.runcommand(f"execute store result score {ret_temp._addr} {prefix[8:]} run function {func_name}")
|
|
105
105
|
else:
|
|
106
|
-
ctx.runcommand(f"execute store result score {ret_temp.
|
|
107
|
-
ctx.runcommand(f"execute if score {ret_temp.
|
|
106
|
+
ctx.runcommand(f"execute store result score {ret_temp._addr} run function {func_name}")
|
|
107
|
+
ctx.runcommand(f"execute if score {ret_temp._addr} matches 1 run return 1")
|
|
108
108
|
|
|
109
109
|
|
|
110
110
|
class StoreExecuteChain(ExecuteChain):
|
|
111
111
|
def __init__(self, fragments: list[str], target: nbt):
|
|
112
112
|
super().__init__("")
|
|
113
113
|
self.fragments = fragments
|
|
114
|
-
self.
|
|
115
|
-
self._datatype = target.
|
|
114
|
+
self._target = target
|
|
115
|
+
self._datatype = target._type.name.lower() if target._type else "double"
|
|
116
116
|
self._multiplier = 1.0
|
|
117
117
|
self._update_frag()
|
|
118
118
|
|
|
119
119
|
def _update_frag(self):
|
|
120
|
-
frag = f"store result storage {self.
|
|
120
|
+
frag = f"store result storage {self._target.target} {self._target.path} {self._datatype} {self._multiplier}"
|
|
121
121
|
if self.fragments and self.fragments[-1].startswith("store result "):
|
|
122
122
|
self.fragments[-1] = frag
|
|
123
123
|
else:
|
|
@@ -59,7 +59,28 @@ class FlareTransformer(ast.NodeTransformer):
|
|
|
59
59
|
self.counter += 1
|
|
60
60
|
return f"__flare_{self.counter}"
|
|
61
61
|
|
|
62
|
+
def visit_FunctionDef(self, node):
|
|
63
|
+
is_exported = any(
|
|
64
|
+
isinstance(dec, ast.Name) and dec.id in ("export", "macro") or isinstance(dec, ast.Call) and getattr(
|
|
65
|
+
dec.func, "id", "") in ("export", "macro") for dec in node.decorator_list)
|
|
66
|
+
|
|
67
|
+
is_generated = node.name.startswith("__flare_")
|
|
68
|
+
prev_in_flare = getattr(self, "in_flare_func", False)
|
|
69
|
+
|
|
70
|
+
if is_exported or is_generated:
|
|
71
|
+
self.in_flare_func = True
|
|
72
|
+
else:
|
|
73
|
+
self.in_flare_func = False
|
|
74
|
+
|
|
75
|
+
self.generic_visit(node)
|
|
76
|
+
self.in_flare_func = prev_in_flare
|
|
77
|
+
return node
|
|
78
|
+
|
|
62
79
|
def visit_If(self, node):
|
|
80
|
+
if not getattr(self, "in_flare_func", False):
|
|
81
|
+
self.generic_visit(node)
|
|
82
|
+
return node
|
|
83
|
+
|
|
63
84
|
funcs = []
|
|
64
85
|
cond_args = []
|
|
65
86
|
body_args = []
|
|
@@ -106,11 +127,15 @@ class FlareTransformer(ast.NodeTransformer):
|
|
|
106
127
|
return funcs
|
|
107
128
|
|
|
108
129
|
def visit_Break(self, node):
|
|
130
|
+
if not getattr(self, "in_flare_func", False):
|
|
131
|
+
return node
|
|
109
132
|
call_expr = ast.Expr(value=ast.Call(func=ast.Name(id="_flare_break", ctx=ast.Load()), args=[], keywords=[]))
|
|
110
133
|
ast.copy_location(call_expr, node)
|
|
111
134
|
return call_expr
|
|
112
135
|
|
|
113
136
|
def visit_Continue(self, node):
|
|
137
|
+
if not getattr(self, "in_flare_func", False):
|
|
138
|
+
return node
|
|
114
139
|
call_expr = ast.Expr(value=ast.Call(func=ast.Name(id="_flare_continue", ctx=ast.Load()), args=[], keywords=[]))
|
|
115
140
|
ast.copy_location(call_expr, node)
|
|
116
141
|
return call_expr
|
|
@@ -120,6 +145,10 @@ class FlareTransformer(ast.NodeTransformer):
|
|
|
120
145
|
return node
|
|
121
146
|
|
|
122
147
|
def visit_While(self, node):
|
|
148
|
+
if not getattr(self, "in_flare_func", False):
|
|
149
|
+
self.generic_visit(node)
|
|
150
|
+
return node
|
|
151
|
+
|
|
123
152
|
class BreakContinueVisitor(ast.NodeVisitor):
|
|
124
153
|
def __init__(self):
|
|
125
154
|
self.has_break = False
|
|
@@ -184,6 +213,10 @@ class FlareTransformer(ast.NodeTransformer):
|
|
|
184
213
|
return funcs
|
|
185
214
|
|
|
186
215
|
def visit_For(self, node):
|
|
216
|
+
if not getattr(self, "in_flare_func", False):
|
|
217
|
+
self.generic_visit(node)
|
|
218
|
+
return node
|
|
219
|
+
|
|
187
220
|
class BreakContinueVisitor(ast.NodeVisitor):
|
|
188
221
|
def __init__(self):
|
|
189
222
|
self.has_break = False
|
|
@@ -286,20 +319,28 @@ class FlareTransformer(ast.NodeTransformer):
|
|
|
286
319
|
return node
|
|
287
320
|
|
|
288
321
|
def visit_Return(self, node):
|
|
322
|
+
if not getattr(self, "in_flare_func", False):
|
|
323
|
+
self.generic_visit(node)
|
|
324
|
+
return node
|
|
325
|
+
|
|
289
326
|
self.generic_visit(node)
|
|
290
327
|
|
|
291
328
|
value = node.value if node.value is not None else ast.Constant(value=None)
|
|
292
329
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
ast.copy_location(
|
|
330
|
+
if_node = ast.If(test=ast.Compare(
|
|
331
|
+
left=ast.Attribute(value=ast.Name(id="ctx", ctx=ast.Load()), attr="current_file", ctx=ast.Load()),
|
|
332
|
+
ops=[ast.IsNot()], comparators=[ast.Constant(value=None)]), body=[
|
|
333
|
+
ast.Expr(value=ast.Call(func=ast.Name(id="_flare_return", ctx=ast.Load()), args=[value], keywords=[])),
|
|
334
|
+
ast.Return(value=None)], orelse=[ast.Return(value=value)])
|
|
335
|
+
ast.copy_location(if_node, node)
|
|
299
336
|
|
|
300
|
-
return
|
|
337
|
+
return if_node
|
|
301
338
|
|
|
302
339
|
def visit_With(self, node):
|
|
340
|
+
if not getattr(self, "in_flare_func", False):
|
|
341
|
+
self.generic_visit(node)
|
|
342
|
+
return node
|
|
343
|
+
|
|
303
344
|
self.generic_visit(node)
|
|
304
345
|
|
|
305
346
|
name_body = self.gen_name()
|
|
@@ -414,6 +455,10 @@ def preprocess_minecraft_commands(source: str) -> str:
|
|
|
414
455
|
|
|
415
456
|
match = COMMAND_RE.match(line)
|
|
416
457
|
if match:
|
|
458
|
+
if re.match(r"^\s*(?:" + COMMAND_KEYWORDS + r")\s*(?:[+\-*/%&|^]?=|\()", line):
|
|
459
|
+
i += 1
|
|
460
|
+
continue
|
|
461
|
+
|
|
417
462
|
indent = match.group(1)
|
|
418
463
|
cmd = match.group(2) + match.group(3)
|
|
419
464
|
if cmd.startswith("/"):
|