Time and @
Ted treats time as an explicit effect in timed contexts. Each timed task carries a current logical time t.
Timed Contexts
@ and event waiting are only legal in timed contexts, such as:
onhandlersloopblocks inside modules- (planned)
timed fntasks
Core code cannot use @ and compiles directly with no scheduler overhead.
TODO: Define
timed fnsyntax and formalize module-level timed tasks in the grammar and parser.
Logical Time Model
Timed code runs as tasks with a current logical time t. Scheduling is expressed with assignment offsets.
x = vwrites at the task’s current timetx = v @ +deltaschedules the write att+deltaand yields the taskx @ -deltareads a temporal value as it was att-delta
Here, delta is a non-negative time offset (cycles or time units) and can come from a literal or an expression.
Example:
on change(sig) {
sig = 1 @ +10ns;
}
TODO: Add a standalone delay statement (
@ +delta;) for timed code that needs to advance time without assigning.
Temporal Storage
Not every value is time-travelable. Only temporal values keep history:
- Ports and module-level state are temporal today
- Future syntax will make temporal storage explicit (for example,
signalortemporaldeclarations)
Temporal values keep bounded history so the compiler can allocate compact ring buffers. The history window can be inferred from @ -delta uses or declared explicitly.
TODO: Specify explicit temporal storage declarations (for example,
signalortemporal) and history bounds.
Reading the Past
Access previous values of a temporal signal:
Note: The examples in this section assume they appear inside a timed context (for example, an on handler or a module-level loop).
// Relative to current time
let prev = sig @ -1; // one cycle ago
let older = sig @ -5; // five cycles ago
// With time units
let past = sig @ -10ns; // 10 nanoseconds ago
let history = sig @ -1us; // 1 microsecond ago
Use Cases
Edge Detection:
let rising_edge = sig && !(sig @ -1);
let falling_edge = !sig && (sig @ -1);
Change Detection:
let changed = sig != (sig @ -1);
Delay Line:
on change(input) {
delayed = input @ -100ns;
}
Scheduling the Future
Schedule values for future logical time:
// Relative scheduling
sig = 1 @ +1; // schedule for the next cycle
sig = value @ +10; // 10 cycles from now
// With time units
sig = 1 @ +10ns; // in 10 nanoseconds
sig = 0 @ +1ms; // in 1 millisecond
Use Cases
Pulse Generation:
// Generate a 10ns pulse
pulse = 1;
pulse = 0 @ +10ns;
Delayed Response:
on rising(trigger) {
output = 1 @ +100ns;
}
Periodic Toggle:
loop {
led = !led @ +500ms;
}
Time Units
Ted supports these time units:
| Unit | Meaning |
|---|---|
| (none) | cycles |
ns | nanoseconds |
us | microseconds |
ms | milliseconds |
s | seconds |
These units are part of logical time; they do not imply wall-clock delays.
Combining Past and Future
You can use past values to determine future assignments:
// Capture now, then apply later
let prev = sig @ -1;
sig = !prev @ +1;
// Delayed feedback
let sample = input @ -1;
output = sample @ +10ns;
Rules and Constraints
- Timed only -
@is only legal in timed contexts - Temporal only - History reads (
x @ -delta) require temporal values - Scheduling -
x = v @ +deltaschedules a write and yields the task - No future reads -
x @ +deltais invalid as a read; only assignments can target the future - Evaluation timing -
x = v @ +deltaevaluatesvafter the time advance; capture values explicitly if needed - Grouping - Use parentheses for compound expressions (for example,
(a + b) @ +1) - Deterministic - Ordering is defined; same input produces identical output
- Progress - Timed loops must include time advancement or event waits to avoid zero-time nontermination
- Cycle-accurate - Integer offsets refer to logical cycles
- Time-accurate - Unit-based offsets refer to logical time units