interpreter: added a new implementation for an interpreter. typechecks, but it needs testing
All checks were successful
ci/woodpecker/push/nix Pipeline was successful
ci/woodpecker/push/fedora Pipeline was successful
ci/woodpecker/push/debian Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/cron/debian Pipeline was successful
ci/woodpecker/cron/nix Pipeline was successful
ci/woodpecker/cron/fedora Pipeline was successful
ci/woodpecker/cron/publish Pipeline was successful
All checks were successful
ci/woodpecker/push/nix Pipeline was successful
ci/woodpecker/push/fedora Pipeline was successful
ci/woodpecker/push/debian Pipeline was successful
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/cron/debian Pipeline was successful
ci/woodpecker/cron/nix Pipeline was successful
ci/woodpecker/cron/fedora Pipeline was successful
ci/woodpecker/cron/publish Pipeline was successful
This commit is contained in:
3
lib/interpreter/dune
Normal file
3
lib/interpreter/dune
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
(library
|
||||||
|
(name interpreter)
|
||||||
|
(libraries compiler))
|
||||||
76
lib/interpreter/main.ml
Normal file
76
lib/interpreter/main.ml
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
|
||||||
|
let ( let* ) = Result.bind
|
||||||
|
let traverse = Compiler.Util.traverse
|
||||||
|
|
||||||
|
type runtime_value =
|
||||||
|
| Int of int
|
||||||
|
| Double of float
|
||||||
|
| String of string
|
||||||
|
| Nil
|
||||||
|
| Cons of runtime_value * runtime_value
|
||||||
|
| Symbol of string
|
||||||
|
(* The rest can't appear as literal values, and are constructed in other ways *)
|
||||||
|
| Closure of Compiler.Scope_analysis.expression * (runtime_value ref list)
|
||||||
|
|
||||||
|
let rec interpret_literal = function
|
||||||
|
| Compiler.Core_ast.Int x -> Ok (Int x)
|
||||||
|
| Double x -> Ok (Double x)
|
||||||
|
| String s -> Ok (String s)
|
||||||
|
| Cons (a, b) ->
|
||||||
|
let* a = interpret_literal a in
|
||||||
|
let* b = interpret_literal b in
|
||||||
|
Ok (Cons (a, b))
|
||||||
|
| Nil -> Ok (Nil)
|
||||||
|
|
||||||
|
|
||||||
|
let rec interpret_one expr env globals =
|
||||||
|
match expr with
|
||||||
|
| Compiler.Scope_analysis.Literal l -> interpret_literal l
|
||||||
|
| Local i ->
|
||||||
|
(match (List.nth_opt env i) with
|
||||||
|
| None -> Error "Error while accessing local variable!"
|
||||||
|
| Some x -> Ok !x)
|
||||||
|
| Global i ->
|
||||||
|
Ok (Array.get globals i)
|
||||||
|
| Apply (f, e) ->
|
||||||
|
let* f = interpret_one f env globals in
|
||||||
|
let* e = interpret_one e env globals in
|
||||||
|
(match f with
|
||||||
|
| Closure (body, inner_env) ->
|
||||||
|
let f_env = (ref e) :: inner_env in
|
||||||
|
interpret_one body f_env globals
|
||||||
|
| _ -> Error "Cannot apply an argument to non-closure value!")
|
||||||
|
| Lambda body ->
|
||||||
|
Ok (Closure (body, env))
|
||||||
|
| If (test, then_e, else_e) ->
|
||||||
|
let* test = interpret_one test env globals in
|
||||||
|
(match test with
|
||||||
|
| Nil -> interpret_one else_e env globals
|
||||||
|
| _ -> interpret_one then_e env globals)
|
||||||
|
| SetLocal (i, e) ->
|
||||||
|
(match (List.nth_opt env i) with
|
||||||
|
| None -> Error "Error while setting local variable!"
|
||||||
|
| Some r ->
|
||||||
|
let* e = interpret_one e env globals in
|
||||||
|
r := e; Ok e)
|
||||||
|
| SetGlobal (i, e) ->
|
||||||
|
let* e = interpret_one e env globals in
|
||||||
|
Array.set globals i e; Ok e
|
||||||
|
| Begin [] -> Ok Nil
|
||||||
|
| Begin [e] -> interpret_one e env globals
|
||||||
|
| Begin (e :: rest) ->
|
||||||
|
let* e = interpret_one e env globals in
|
||||||
|
ignore e; interpret_one (Begin rest) env globals
|
||||||
|
|
||||||
|
let interpret program global_syms =
|
||||||
|
let count = Compiler.Scope_analysis.SymbolTable.cardinal global_syms in
|
||||||
|
let globals : runtime_value array = Array.make count Nil in
|
||||||
|
|
||||||
|
Ok (interpret_one (Begin program) [] globals)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let interpret_src src =
|
||||||
|
let* (program, globals) = Compiler.Scope_analysis.of_src src in
|
||||||
|
interpret program globals
|
||||||
|
|
||||||
Reference in New Issue
Block a user