2016-06-07 34 views
5

ho la seguente situazione:funzione circolare le chiamate quando si valutano i nodi AST per interprete

let private runStatement (vars : Map<identifier, value>) stmt = 
    match stmt with 
    | Assignment (id, expr) -> runAssignment vars id expr 
    | Print exprs -> runPrint vars exprs 
    | Read id -> runRead vars id 
    | If (cond, stmts) -> runIf vars cond stmts 

let rec private runStatements vars stmts = 
    match stmts with 
    | stmt::rest -> 
     let newVars = runStatement vars stmt 
     runStatements newVars rest 
    | [] -> vars 

let private runIf vars conditionalValue statements = 
    match conditionalValue with 
    | Boolean v when v -> runStatements vars statements 
    | Boolean v -> vars 
    | _ -> failwith "Not a boolean expression in if statement" 

Come si può vedere, la funzione runStatement chiama runIf, e runIf chiamate runStatement, perché un se-dichiarazione è formata da alcuni generali dichiarazioni e una dichiarazione generale può essere un'istruzione if.

Come posso risolvere questa situazione?

PS .: Ho situazioni simili con altre funzioni come runWhile, runIfElse e così via.

+2

Si prega di inserire sempre tutto il codice (tipi, funzioni, 'dichiarazioni open') necessari per consentire l'esempio di compilazione. Ciò consente ad altri di concentrarsi sulla fornitura di una soluzione senza dover prima risolvere il codice. – TeaDrivenDev

+2

Passa le funzioni come argomenti anziché accoppiarle. –

+0

Come nota a margine: suppongo che faccia parte del progetto del compilatore poiché hai usato il tag 'compiler-construction'. Dovresti rilasciare 'run' dai nomi delle funzioni perché le persone usano per lavorare con i parser si aspettano che il nome della funzione sia lo stesso del termine che stanno analizzando. Quindi per questo i termini sono 'statement',' statements' e 'if'. So che si verificherà un errore se si chiama una funzione 'if', quindi quello che farei è chiamarlo' ifParser', ma non usare run e questo mi porta a credere che sia una funzione che può essere chiamata dal principale programma e mentre ciò è possibile non è personalizzato. –

risposta

8

utilizzare il 'e' parola chiave

let rec runx() = 
    printf "runx" 
    runy() 
and runy() = 
    printf "runy" 
    runx() 

runx() |> ignore 

stampe

runxrunyrunxrunyrunxrunyrunxrunyrunxrunyrunxrunyrunxrunyrunxrunyrunxrunyrunxrunyrunxruny 
+0

Phillip, hai ragione, questa è la soluzione per la mia domanda. - Come nota a margine: dopo aver esaminato il mio codice ho notato che il mio linguaggio ha lasciato la ricorsione ed è per questo che sto affrontando questo tipo di problema. Riformulerò la mia lingua per rimuovere questa ricorsione sinistra. (Lo dico perché può aiutare gli altri). – Gabriel