File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -383,6 +383,16 @@ type Receive struct {
383383func (r * Receive ) statementNode () {}
384384func (r * Receive ) TokenLiteral () string { return r .Token .Literal }
385385
386+ // TimerAfterWait represents a standalone timer AFTER wait: tim ? AFTER expr
387+ type TimerAfterWait struct {
388+ Token lexer.Token // the ? token
389+ Timer string // timer variable name
390+ Deadline Expression // the deadline expression
391+ }
392+
393+ func (t * TimerAfterWait ) statementNode () {}
394+ func (t * TimerAfterWait ) TokenLiteral () string { return t .Token .Literal }
395+
386396// AltBlock represents an ALT block (alternation/select)
387397// If Replicator is non-nil, this is a replicated ALT (ALT i = 0 FOR n)
388398type AltBlock struct {
Original file line number Diff line number Diff line change @@ -745,7 +745,7 @@ func (g *Generator) containsPrint(stmt ast.Statement) bool {
745745
746746func (g * Generator ) containsTimer (stmt ast.Statement ) bool {
747747 switch s := stmt .(type ) {
748- case * ast.TimerDecl , * ast.TimerRead :
748+ case * ast.TimerDecl , * ast.TimerRead , * ast. TimerAfterWait :
749749 return true
750750 case * ast.AltBlock :
751751 for _ , c := range s .Cases {
@@ -1135,6 +1135,8 @@ func (g *Generator) generateStatement(stmt ast.Statement) {
11351135 g .generateSend (s )
11361136 case * ast.Receive :
11371137 g .generateReceive (s )
1138+ case * ast.TimerAfterWait :
1139+ g .generateTimerAfterWait (s )
11381140 case * ast.SeqBlock :
11391141 g .generateSeqBlock (s )
11401142 case * ast.ParBlock :
@@ -1431,6 +1433,14 @@ func (g *Generator) generateSend(send *ast.Send) {
14311433 g .write ("\n " )
14321434}
14331435
1436+ func (g * Generator ) generateTimerAfterWait (s * ast.TimerAfterWait ) {
1437+ // tim ? AFTER deadline → time.Sleep(time.Duration(deadline - time.Now().UnixMicro()) * time.Microsecond)
1438+ g .builder .WriteString (strings .Repeat ("\t " , g .indent ))
1439+ g .write ("time.Sleep(time.Duration(" )
1440+ g .generateExpression (s .Deadline )
1441+ g .write (" - int(time.Now().UnixMicro())) * time.Microsecond)\n " )
1442+ }
1443+
14341444func (g * Generator ) generateReceive (recv * ast.Receive ) {
14351445 chanRef := goIdent (recv .Channel )
14361446 if len (recv .ChannelIndices ) > 0 {
Original file line number Diff line number Diff line change @@ -181,6 +181,22 @@ func TestE2E_TimerAltTimeout(t *testing.T) {
181181 }
182182}
183183
184+ func TestE2E_TimerAfterWait (t * testing.T ) {
185+ // Test standalone tim ? AFTER expr (non-ALT timer wait)
186+ occam := `SEQ
187+ TIMER tim:
188+ INT t:
189+ tim ? t
190+ tim ? AFTER (t + 1000)
191+ print.int(42)
192+ `
193+ output := transpileCompileRun (t , occam )
194+ expected := "42\n "
195+ if output != expected {
196+ t .Errorf ("expected %q, got %q" , expected , output )
197+ }
198+ }
199+
184200func TestE2E_ChanParam (t * testing.T ) {
185201 occam := `PROC sender(CHAN OF INT output)
186202 output ! 42
Original file line number Diff line number Diff line change @@ -1207,13 +1207,28 @@ func (p *Parser) parseTimerDecl() *ast.TimerDecl {
12071207 return decl
12081208}
12091209
1210- func (p * Parser ) parseTimerRead () * ast.TimerRead {
1211- stmt := & ast.TimerRead {
1212- Timer : p .curToken .Literal ,
1213- }
1210+ func (p * Parser ) parseTimerRead () ast.Statement {
1211+ timerName := p .curToken .Literal
12141212
12151213 p .nextToken () // move to ?
1216- stmt .Token = p .curToken
1214+ recvToken := p .curToken
1215+
1216+ // Check for timer AFTER wait: tim ? AFTER expr
1217+ if p .peekTokenIs (lexer .AFTER ) {
1218+ p .nextToken () // move to AFTER
1219+ p .nextToken () // move past AFTER to deadline expression
1220+ deadline := p .parseExpression (LOWEST )
1221+ return & ast.TimerAfterWait {
1222+ Token : recvToken ,
1223+ Timer : timerName ,
1224+ Deadline : deadline ,
1225+ }
1226+ }
1227+
1228+ stmt := & ast.TimerRead {
1229+ Timer : timerName ,
1230+ }
1231+ stmt .Token = recvToken
12171232
12181233 if ! p .expectPeek (lexer .IDENT ) {
12191234 return nil
You can’t perform that action at this time.
0 commit comments