Mon 16 Mar 11:09:06 CET 2026

This commit is contained in:
sbosse 2026-03-16 11:12:10 +01:00
parent 4b4274f9bd
commit 80e8557dd9

190
src/run.c Normal file
View File

@ -0,0 +1,190 @@
/*
VM handlers (and network message handlers)
*/
#include "config.h"
#include "types.h"
#include "lexer.h"
#include "tokens.h"
#include "mem.h"
#include "reg.h"
#include "stack.h"
#include "ops.h"
#include "context.h"
#include "code.h"
#include "event.h"
#include "vm.h"
#include "var.h"
#include "printf.h"
#include "ccall.h"
#include "version.h"
#include "debug.h"
#include "cconst.h"
#include "net.h"
#include "run.h"
#include "debug.h"
#include "error.h"
#include "str.h"
#include "log.h"
#ifdef IOAWAIT
/*
Main VM Execution and IO Loop
Returns: -1: error 0: no ready context, 1: ready context
*/
int Loop(context_t *C0,char service) {
int error=0,status,idle=0,run=0,ready=0;
context_t *C=C0; // root context
#if DEBUG > 0
log(LOGDEBUG1,"Loop: Enter.\n",NULL);
#endif
do {
C=C0;
idle=0;run=ready=0;
while (C) {
reg_t *R=C->R;
#if DEBUG>0
log(LOGDEBUG2,"Loop: Context #%d ",CONTEXTID(C));
if (log_level<=LOGDEBUG2) PrintState(C->R);
#endif
status=Run(C);
if (R->error) {
error=R->error;
break;
}
if (R->state&PIDLE) idle++; else run++; // still processing a program, maybe suspended
if (R->state&(PRUNNING|PHANDLER)) ready++; // pending VM ops
C=C->next;
}
if (!error && !ready && (run||service)) status=IOAWAIT(Context[0],ready);
} while (!error && (run||service));
#if DEBUG > 0
log(LOGDEBUG2,"Loop: Exit (ready=%d run=%d error=%d service=%d status=%d).\n",ready,run,error,service,status);
#endif
return error?-1:ready;
}
#else
/*
Main VM Execution Loop, embedded in an external main IO loop
Returns: -1: error 0: no ready context, 1: ready context
*/
int Loop(context_t *C0) {
int error=0,status,idle=0,run=0,ready=0;
context_t *C=C0; // root context
#if DEBUG > 0
log(LOGDEBUG2,"Loop enter.\n",NULL);
#endif
do {
C=C0;
idle=0;run=ready=0;
while (C) {
reg_t *R=C->R;
#if DEBUG>0
log(LOGDEBUG2,"Loop: Context #%d ",CONTEXTID(C));
if (log_level<=LOGDEBUG2) PrintState(C->R);
#endif
status=Run(C);
if (R->error) {
error=R->error;
break;
}
if (R->state&PIDLE) idle++; else run++; // still processing a program, maybe suspended
if (R->state&(PRUNNING|PHANDLER)) ready++; // pending VM ops
C=C->next;
}
} while (!error && ready);
#if DEBUG > 0
log(LOGDEBUG2,"Loop: Exit (ready=%d run=%d error=%d service=%d status=%d).\n",ready,run,error,service,status);
#endif
return error?-1:ready;
}
#endif
#if HAS_NET > 0
/*
Program Code Message Handler
*/
int MessageHandlerCode(port_t *P,message_type_t t) {
index_t top = P->rxTop;
#if PROFILE>0
unsigned long t0,t1;
#endif
context_t *c=NULL;
lexer_t L;
mem_t *m;
if (!Context[0]) { P->rxBottom=top; return -1; }
#if DEBUG >0
log(LOGDEBUG1,"MessageHandlerCode (%d) %d:[%s]\n",t,P->rxBottom,&P->rxBuffer[P->rxBottom]);
#endif
switch (t) {
case MSGPROGRAMPART:
c=Context[0];
case MSGCOMMAND:
// compile and run command
// use 1 or 0 (if IDLE) for command lines
if (!c) c=Context[ContextTop>1?1:0];
case MSGPROGRAM:
if (!c) c=Context[0]; // program for primary context
m=c->M;
if (string_cmp(&P->rxBuffer[P->rxBottom],"new",0)) {
// reset entire context chain including stacks, registers, events
ContextResetAll(NULL);
P->rxBottom=top;
return 0;
}
// TODO check IDLE state
if (t==MSGPROGRAM) ContextResetAll(NULL); // a new main program must reset the entire VM context chain!
else if (t==MSGCOMMAND) ContextReset(c);
log(LOGINFO,"MessageHandlerCode ContextReset(%d) \n",CONTEXTID(c));
#if PROFILE>0
t0=MICROS();
#endif
// sync. compiling
Compile(&L,&P->rxBuffer[P->rxBottom],c,PRUNNING);
P->rxBottom=top;
if (P->rxBottom==P->rxTop) P->rxBottom=P->rxTop=0;
#if PROFILE>0
t1=MICROS();
#endif
if (c->R->error) {
log(LOGERROR,"Compiler error %d(%s) in line %d\n",c->R->error,Errors[c->R->error],L.line);
#if DEBUG >0
PrintLexerToken(&L);
#endif
return -1;
}
#if PROFILE>0
c->S->ntoken=L.ntoken;
c->S->micros=t1-t0;
#endif
log(LOGINFO,"MessageHandlerCode Done(%d) pc=%d state=%d\n",CONTEXTID(c),c->R->pc,c->R->state);
return 1;
break;
}
return -1;
}
/* handle received event message */
int MessageHandlerEvent(port_t *P,message_type_t t) {
P->rxBottom=P->rxTop;
}
static index_t evmsgportall=-1;
/* handle received user message */
int MessageHandlerUser(port_t *P,message_type_t t) {
// raise EVMESSAGE event
// speed up and cache event index
if (evmsgportall!=-1) {
#if DEBUG >0
log(LOGDEBUG1,"MessageHandlerUser (%d)\n",evmsgportall);
#endif
RaiseEventIndex(evmsgportall);
return evmsgportall;
}
index_t evid=RaiseEvent("message",-1); // PORTALL
if (evid!=-1) evmsgportall=evid;
#if DEBUG >0
log(LOGDEBUG1,"MessageHandlerUser (%d)\n",evid);
#endif
return evid;
}
#endif