2016-06-07 40 views
5

Mam następującą sytuację:funkcja Circular zwraca przy ocenie węzłów AST dla tłumacza

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" 

Jak widać, funkcja runStatement wywołuje runIf i runIf połączeń runStatement, ponieważ if-oświadczenie jest utworzona przez kilka ogólnych oświadczenia, a ogólne oświadczenie może być instrukcją if.

Jak mogę rozwiązać tę sytuację?

PS: Mam podobne sytuacje z innymi funkcjami, takimi jak runWhile, runIfElse i tak dalej.

+2

Proszę zawsze obejmować cały kod (rodzaje, funkcje, 'open' zeznań) wymagane, aby przykład kompilacji. To pozwala innym skupić się na dostarczaniu rozwiązań bez konieczności wcześniejszego naprawiania kodu. – TeaDrivenDev

+2

Przekazuj funkcje jako argumenty zamiast łączenia się z nimi. –

+0

Na marginesie: uważam, że jest to część twojego projektu kompilatora, ponieważ użyłeś znacznika 'kompilator-konstrukcja'. Powinieneś upuścić 'run' z nazw funkcji, ponieważ ludzie używają do pracy z parserami, oczekując, że nazwa funkcji będzie taka sama jak termin, który parsuje. Tak więc w tym przypadku terminy to "instrukcja", "instrukcje" i "jeśli". Wiem, że dostaniesz błąd, jeśli nazwiesz funkcję 'if', więc chciałbym ją nazwać' ifParser', ale nie używam run i to prowadzi mnie do przekonania, że ​​jest to funkcja, którą można wywołać z głównego program i podczas gdy jest to możliwe nie jest niestandardowe. –

Odpowiedz

8

naciśnij 'i' keyword

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

runx() |> ignore 

wydruki

runxrunyrunxrunyrunxrunyrunxrunyrunxrunyrunxrunyrunxrunyrunxrunyrunxrunyrunxrunyrunxruny 
+0

Phillip, masz rację, to rozwiązanie mojego pytania. - Na marginesie: Po przejrzeniu mojego kodu zauważyłem, że mój język opuścił rekursję i dlatego mam do czynienia z tego rodzaju problemem. Zmienię swój język, aby usunąć tę lewą rekursję. (Mówię to, bo może pomóc innym). – Gabriel