📄 mal_session.mx
字号:
if (c == NULL) { stream_printf(fout, "!Out of client slots\n"); stream_flush(fout); GDKfree(command); return; } c->nspace = newModule(NULL, putName("user", 4)); c->nspace->outer = mal_scope; c->sessionkey = key; if (!lang) { if ((s = defaultScenario(c))) { stream_printf(c->fdout, "!%s\n", s); stream_flush(c->fdout); c->mode = FINISHING; } } else if ((s = setScenario(c, lang)) != NULL) { stream_printf(c->fdout, "!%s\n", s); stream_flush(c->fdout); c->mode = FINISHING; } } MSinitClientPrg(c,"user", "main"); GDKfree(command); if (MT_create_thread(&p, MSserveClient, (void *) c) < 0) { showException(MAL,"initClient", "can not fork new client"); return; }}@+ Client servicesAfter the client initialization has been finished, wecan start the interaction protocol. This involves parsing theinput in the context of an already defined procedure and uponsuccess, its execution.In essence, this calls for an incremental parsing operation, because we should wait until a complete basic block has been detected.Test, first collect the instructions before we take them all.@-In interactive mode, we should remove the instructions beforeaccepting new ones. The function signature remains the sameand the symbol table should also not be affected.Aside from removing instruction, we should also condense thevariable stack, i.e. removing at least the temporary variables,but maybe everything beyond a previous defined pont.Beware that we have to cleanup the global stack as well. This to avoidsubsequent calls to find garbage information.However, this action is only required after a successful execution.Otherwise, garbage collection is not needed.@cvoidMSresetInstructions(MalBlkPtr mb, int start){ int i; InstrPtr p; for (i = start; i < mb->stop; i++) { p = getInstrPtr(mb, i); if (p) freeInstruction(p); mb->stmt[i] = NULL; } mb->stop = start;}static int unknownType(int tpe){ return tpe == TYPE_any || (isaBatType(tpe) && ( getHeadType(tpe) == TYPE_any || getTailType(tpe) == TYPE_any ));}voidMSresetVariables(MalBlkPtr mb, MalStkPtr glb, int start){ int i, j; for (i = j = start; i < mb->vtop;) { if (isTmpVar(mb, i) || unknownType(getVarType(mb,i)) ) { clearVariable(mb, i); if (glb) { garbageElement(&glb->stk[i]); /* clean stack entry */ glb->stk[i].vtype = TYPE_int; glb->stk[i].val.ival = 0; glb->stk[i].len = 0; } i++; } else { if (i != j) { VarPtr v= getVar(mb,j); mb->var[j]= mb->var[i]; getVar(mb,i)= v; if (glb) { /* save stack state */ glb->stk[j] = glb->stk[i]; /* clean stack entry */ glb->stk[i].vtype = TYPE_int; glb->stk[i].val.ival = 0; glb->stk[i].len = 0; } } i++; j++; } } mb->vtop = j;}@-Here we start the first client. We need to initializethe corresponding thread and allocate space for the global variables. Thereafter it is up to the scenariointerpreter to process input.@cvoidMSserveClient(void *dummy){ MalBlkPtr mb; Client c = (Client) dummy; str msg = 0; if (!isAdministrator(c)) MCinitClientThread(c);@-A stack frame is initialized to keep track of global variables.The scenarios are run until we finally close the last one.@c mb = c->curprg->def; c->glb = newGlobalStack(MAXGLOBALS + mb->vsize); c->glb->stktop = mb->vtop; c->glb->blk = mb; if (c->scenario == 0) msg = defaultScenario(c); if (msg) { showException(MAL, "serveClient", "could not initialize default scenario"); c->mode = FINISHING + 1; } else do { runScenario(c); if (c->mode == FINISHING) break; resetScenario(c); } while (c->scenario);@-At this stage we should clean out the MAL block@c freeMalBlk(c->curprg->def); c->curprg->def = 0; if (c->mode > FINISHING) { if (isAdministrator(c)) { /* old OIDflushdelta =0; */ if (c->scenario) { exitScenario(c); } } } if (!isAdministrator(c)) MCcloseClient(c);}@+ MAL scenario componentsThe stages of processing user requests are controlled by ascenario. The routines below are the default implementation.The main issues to deal after parsing it to clean out theAdmin.main function from any information added erroneously.Ideally this involves resetting the state of the client'main' function, i.e. the symbol table is reset and anyinstruction added should be cleaned. Beware that the instructiontable may have grown in size.@= restoreState if( c->listing) printFunction(c->fdout,c->curprg->def, c->listing); resetMalBlk(c->curprg->def,oldstate.stop);/* MSresetInstructions(c->curprg->def, oldstate.stop);*/ MSresetVariables(c->curprg->def, 0, oldstate.vtop);@cstrMALexitSession(Client c){ (void) c; return 0;}strMALexitClient(Client c){ if (c->glb) { garbageCollector(c->curprg->def, c->glb,TRUE); GDKfree(c->glb); } c->glb = 0; return 0;}strMALreader(Client c){ int r= 1; c->fdin->pos += c->yycur; c->yycur = 0; c->fdin->buf[c->fdin->pos] = 0; if( c == mal_clients){ r= readConsole(c); if (r <0 && c->fdin->eof == 0 ) r= MCreadClient(c); if( r > 0) return MAL_SUCCEED; } else if (MCreadClient(c) > 0) return MAL_SUCCEED; c->mode = FINISHING; if (c->fdin) c->fdin->buf[c->fdin->pos] = 0; else throw(MAL, "MAL.reader", "Attempt to read beyond end of file"); return MAL_SUCCEED;}strMALparser(Client c){ InstrPtr p; MalBlkRecord oldstate; c->curprg->def->errors = 0; oldstate = *c->curprg->def; prepareMalBlk(c->curprg->def, CURRENT(c)); if (parseMAL(c, c->curprg) || c->curprg->def->errors) { /* just complete it for visibility */ pushEndInstruction(c->curprg->def); /* catched errors */ showErrors(); @:restoreState@ throw(SYNTAX, "MAL.parser", "Syntax errors detected"); } /* check for unfinished blocks */ if (c->blkmode) return MAL_SUCCEED; /* empty files should be skipped as well */ if (c->curprg->def->stop == 1) return MAL_SUCCEED; p = getInstrPtr(c->curprg->def, 0); if (p->token != FUNCTIONsymbol) { @:restoreState@ throw(MAL, "MAL.parser", "Function signature missing"); } pushEndInstruction(c->curprg->def); trimMalBlk(c->curprg->def); chkProgram(c->nspace, c->curprg->def); if (c->curprg->def->errors) { showErrors(); @:restoreState@ throw(MAL, "MAL.parser", "Semantic errors detected"); } return MAL_SUCCEED;}intMALcommentsOnly(MalBlkPtr mb){ int i; for (i = 1; i < mb->stop; i++) if (mb->stmt[i]->token != REMsymbol) return 0; return 1;}strMALengine(Client c){ Symbol prg; str msg = 0; MalBlkRecord oldstate; oldstate.stop = 0; oldstate.vtop = 0; if( c->blkmode) return MAL_SUCCEED; prg = c->curprg; if (prg == NULL) throw(MAL, "MAL.engine", "Main MAL function missing"); if (prg->def->errors > 0) { showErrors(); @:restoreState@ throw(MAL, "MAL.engine", "Program contains errors"); } if (prg->def->stop == 1 || MALcommentsOnly(prg->def)) return 0; /* empty block */ if (c->glb) { if (prg->def && c->glb->stksize < prg->def->vsize) c->glb = reallocGlobalStack(c->glb, prg->def->vsize); c->glb->stktop = prg->def->vtop; c->glb->blk = prg->def; c->glb->cmd = (c->itrace && c->itrace != 'C') ? 'n' : 0; } if (c->listing) printFunction(c->fdout, c->curprg->def, c->listing);@-In interactive mode we should avoid early garbage collection of values.This can be controlled by the clean up control at the instruction leveland marking all non-temporary variables as being (potentially) used.@c if (c->glb){ c->glb->pcup = 0; c->glb->keepAlive= TRUE; /* no garbage collection */ } if (prg->def->errors == 0) msg = (str) runMAL(c, prg->def, 1, 0, c->glb, 0); else msg = MAL_SUCCEED; if (msg) { str place = getExceptionPlace(msg); showException(getExceptionType(msg), place, getExceptionMessage(msg)); GDKfree(place); if (!c->listing) printFunction(c->fdout, c->curprg->def, c->listing); showErrors(); } resetMalBlk(prg->def,1); MSresetVariables(prg->def, c->glb, 0); prg->def->errors = 0; return msg;}@}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -