You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Paste-ready draft; this proposes numeric MOVED with MOVED alone as boolean shorthand.
Proposal: expose the result of the previous OUTPUT through MOVED
Summary
Add a MOVED boolean expression that reports how much resource was actually transferred by the most recently executed OUTPUT statement.
input 1 sfm:memory_token from token_source
output 1 sfm:memory_token to state slot 2
if moved = 1 then
-- The transfer succeeded.
else
-- The source was empty, destination was blocked, or nothing moved.
end
This would let programs react to actual transfer results instead of trying to predict success using HAS checks.
The primary motivation is enabling a compiler to lower higher-level features such as variables, assignments, loops, and functions into backpressure-safe SFM programs. It would also be independently useful in handwritten programs for retries, fallbacks, alarms, and conditional routing.
Proposed grammar
boolexpr
: TRUE #BooleanTrue
| FALSE #BooleanFalse
| MOVED (comparisonOp number)? #BooleanMoved
| LPAREN boolexpr RPAREN #BooleanParen
| NOT boolexpr #BooleanNegation
| boolexpr AND boolexpr #BooleanConjunction
| boolexpr OR boolexpr #BooleanDisjunction
| setOp? labelAccess HAS comparisonOp number
resourceIdDisjunction? with?
(EXCEPT resourceIdList)? #BooleanHas
| REDSTONE (comparisonOp number)? #BooleanRedstone
;
MOVED : MOVED ;
Suggested shorthand:
MOVED
means:
MOVED > 0
The existing comparison operators would therefore support:
if moved then
if moved = 0 then
if moved = 1 then
if moved >= 16 then
Proposed semantics
Each running program context stores a value such as:
longlastOutputMoved;
When an OUTPUT statement begins:
lastOutputMoved = 0
As the output transfers resources:
lastOutputMoved += amountActuallyTransferred
After the statement finishes, MOVED reads that value.
Important details:
A completely unsuccessful output produces MOVED = 0.
A partial transfer reports the actual partial amount.
A successful one-item output produces MOVED = 1.
Every executed OUTPUT replaces the result of the previous OUTPUT.
INPUT, IF, FORGET, and other statements do not modify it.
It resets to zero at the beginning of every trigger execution so results cannot leak between ticks or trigger invocations.
The value belongs to the current program execution context, not to the disk globally.
Reading MOVED on a path where no OUTPUT has executed returns zero. The linter should warn because this is likely unintended.
Resetting immediately before every output is important. Otherwise, a failed output could accidentally leave the successful result from an earlier output visible.
Basic examples
Detect any successful movement
input minecraft:cobblestone from source
output to destination
if moved then
-- At least one cobblestone moved.
end
Distinguish full, partial, and failed transfers
input 16 minecraft:cobblestone from source
output 16 minecraft:cobblestone to destination
if moved = 16 then
-- Full transfer.
else if moved > 0 then
-- Partial transfer.
else
-- Nothing transferred.
end
Retry under backpressure
every 20 ticks do
input 1 minecraft:cobblestone from source
output 1 minecraft:cobblestone to destination
if moved = 0 then
-- The source may be empty or the destination may be full.
-- Leave the physical control state unchanged and retry later.
end
end
Why HAS is not sufficient
A compiler could generate checks such as:
if source has >= 1 minecraft:cobblestone
and destination has < 64 minecraft:cobblestone then
...
end
However, this is only a prediction that the operation will succeed.
It can be incorrect because of:
sided capability restrictions;
filters or resource-specific insertion rules;
modded inventories with unusual slot capacities;
virtual storage systems;
another operation modifying the inventory between the check and transfer;
an output spanning multiple blocks, slots, or resources;
partial insertion;
extraction or insertion handlers rejecting the operation for reasons not represented by HAS.
MOVED observes the result of the real operation. It does not require SFM or a compiler to reproduce every possible capability rule in advance.
Compiler use case
A higher-level compiler can represent variables using items in statically allocated inventory regions:
Eco → state slots 2–3
program counter → control slots 0–10
token source → cobblestone generator
token sink → disposal system
An increment:
Eco = Eco + 1
can be lowered into a one-token transfer:
input 1 sfm:memory_token from token_source
output 1 sfm:memory_token to state slots 2-3
The compiler must advance its physical program counter only if that transfer succeeded:
input 1 sfm:memory_token from token_source
output 1 sfm:memory_token to state slots 2-3
if moved = 1 then
forget
input 1 sfm:control_token from control slot 0
output 1 sfm:control_token to control slot 1
end
If the generator has not produced a token yet or the variable storage is full, MOVED = 0. The control token stays in the original state, and the operation is retried during a later trigger execution.
This supplies ordinary backpressure semantics:
success → advance
failure → remain in the current state and retry
Functions can be inlined or compiled into groups of control states. Loops can be implemented by repeatedly executing one control-state transition per trigger. The compiler does not need native target-language variables, functions, or loops, but it does need to know whether each physical transition actually happened.
Why this is preferable to adding loops or dynamic quantities first
A target-level WHILE loop could spin forever inside one server tick when an inventory is blocked.
A dynamic quantity such as:
output Eco minecraft:cobblestone to chest
would require a much larger runtime variable system and still would not answer whether the complete transfer succeeded.
One-unit micro-operations have simple behavior:
requested one
moved zero or one
advance or retry
MOVED provides the missing acknowledgement needed to compose those operations into larger programs.
Non-goals
This proposal does not itself add:
source-level variables;
functions;
loops;
dynamic slot indices;
transactions or rollback;
atomicity across multiple OUTPUT statements;
a guarantee that the requested amount was transferred.
MOVED only reports what the immediately preceding OUTPUT actually accomplished. Programs can compare it with the requested literal when they need full-transfer confirmation.
Suggested linting
The linter could report:
MOVED is read on a control-flow path where no OUTPUT has executed.
Its value will be zero.
It could also flag cases where another output overwrites the relevant result:
output to destination_a
output to destination_b
if moved then
-- This refers only to destination_b.
end
Suggested tests
No available input results in MOVED = 0.
A full destination results in MOVED = 0.
A successful one-unit output results in MOVED = 1.
Partial insertion reports the partial amount.
Full insertion reports the full amount.
A second output replaces the first output’s result.
A failed output does not retain an earlier successful result.
A new trigger invocation starts with MOVED = 0.
Nested IF blocks preserve the result until another output executes.
Multiple source or destination blocks report the total amount actually transferred by that output statement.
Open question: boolean versus numeric result
The minimum feature needed by the compiler is a boolean:
if moved then
meaning that at least one unit moved.
A numeric value is more generally useful because it can distinguish complete and partial transfers:
if moved = 16 then
Internally tracking the numeric amount should be nearly the same implementation work, since the output operation already has to determine how much was accepted.
If a single OUTPUT can combine resources whose quantities use incompatible units, numeric aggregation needs a precise definition. Possible approaches are:
define it as the sum of the quantities reported by all transfers;
permit numeric comparisons only for outputs using one resource unit;
initially expose only boolean MOVED, while retaining a numeric internal result for a future extension.
My preference is numeric MOVED with boolean shorthand, provided the aggregation rule can be defined consistently.
enhancementA feature to be addedlanguage featureInvolving the design of the domain-specific language, likely changes to the .g4 ANTLR grammar file
1 participant
Heading
Bold
Italic
Quote
Code
Link
Numbered list
Unordered list
Task list
Attach files
Mention
Reference
Menu
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
https://chatgpt.com/share/6a78216b-72e0-83ea-8c01-aacd7e53361c
From ChatGPT:
Paste-ready draft; this proposes numeric
MOVEDwithMOVEDalone as boolean shorthand.Proposal: expose the result of the previous
OUTPUTthroughMOVEDSummary
Add a
MOVEDboolean expression that reports how much resource was actually transferred by the most recently executedOUTPUTstatement.This would let programs react to actual transfer results instead of trying to predict success using
HASchecks.The primary motivation is enabling a compiler to lower higher-level features such as variables, assignments, loops, and functions into backpressure-safe SFM programs. It would also be independently useful in handwritten programs for retries, fallbacks, alarms, and conditional routing.
Proposed grammar
Suggested shorthand:
means:
The existing comparison operators would therefore support:
Proposed semantics
Each running program context stores a value such as:
When an
OUTPUTstatement begins:As the output transfers resources:
After the statement finishes,
MOVEDreads that value.Important details:
MOVED = 0.MOVED = 1.OUTPUTreplaces the result of the previousOUTPUT.INPUT,IF,FORGET, and other statements do not modify it.MOVEDon a path where noOUTPUThas executed returns zero. The linter should warn because this is likely unintended.Resetting immediately before every output is important. Otherwise, a failed output could accidentally leave the successful result from an earlier output visible.
Basic examples
Detect any successful movement
Distinguish full, partial, and failed transfers
Retry under backpressure
Why
HASis not sufficientA compiler could generate checks such as:
However, this is only a prediction that the operation will succeed.
It can be incorrect because of:
HAS.MOVEDobserves the result of the real operation. It does not require SFM or a compiler to reproduce every possible capability rule in advance.Compiler use case
A higher-level compiler can represent variables using items in statically allocated inventory regions:
An increment:
can be lowered into a one-token transfer:
The compiler must advance its physical program counter only if that transfer succeeded:
If the generator has not produced a token yet or the variable storage is full,
MOVED = 0. The control token stays in the original state, and the operation is retried during a later trigger execution.This supplies ordinary backpressure semantics:
Functions can be inlined or compiled into groups of control states. Loops can be implemented by repeatedly executing one control-state transition per trigger. The compiler does not need native target-language variables, functions, or loops, but it does need to know whether each physical transition actually happened.
Why this is preferable to adding loops or dynamic quantities first
A target-level
WHILEloop could spin forever inside one server tick when an inventory is blocked.A dynamic quantity such as:
would require a much larger runtime variable system and still would not answer whether the complete transfer succeeded.
One-unit micro-operations have simple behavior:
MOVEDprovides the missing acknowledgement needed to compose those operations into larger programs.Non-goals
This proposal does not itself add:
OUTPUTstatements;MOVEDonly reports what the immediately precedingOUTPUTactually accomplished. Programs can compare it with the requested literal when they need full-transfer confirmation.Suggested linting
The linter could report:
It could also flag cases where another output overwrites the relevant result:
Suggested tests
MOVED = 0.MOVED = 0.MOVED = 1.MOVED = 0.IFblocks preserve the result until another output executes.Open question: boolean versus numeric result
The minimum feature needed by the compiler is a boolean:
meaning that at least one unit moved.
A numeric value is more generally useful because it can distinguish complete and partial transfers:
Internally tracking the numeric amount should be nearly the same implementation work, since the output operation already has to determine how much was accepted.
If a single
OUTPUTcan combine resources whose quantities use incompatible units, numeric aggregation needs a precise definition. Possible approaches are:MOVED, while retaining a numeric internal result for a future extension.My preference is numeric
MOVEDwith boolean shorthand, provided the aggregation rule can be defined consistently.All reactions