Reorganized basically everything, making way for the compiler

This commit is contained in:
2025-11-15 13:06:16 +03:00
parent 27115ab4f2
commit 3f0a860a03
15 changed files with 84 additions and 25 deletions

View File

@@ -1,6 +1,5 @@
(executable
(name main)
(public_name main)
(libraries str lisp unix))
(include_subdirs unqualified)
(name inter)
(public_name inter)
(libraries str interpreter unix)
(package main))

View File

@@ -1,11 +1,10 @@
open Lisp.Ast;;
open Interpreter.Ast;;
open Printf;;
open Lisp;;
open Interpreter;;
open Env;;
open Eval;;
open Read;;
let () = InterpreterStdlib.init_default_env ()
let () = Stdlib.init_default_env ()
let rec repl env c =
let () = printf ">>> "; Out_channel.flush Out_channel.stdout; in
@@ -14,7 +13,7 @@ let rec repl env c =
| Some "exit" -> ()
| Some l ->
try
let vals = (parse_str l) in
let vals = (read_from_str l) in
(* dbg_print_all vals; *)
pretty_print_all (eval_all env vals);
Out_channel.flush Out_channel.stdout;
@@ -23,7 +22,7 @@ let rec repl env c =
| Invalid_argument s ->
printf "%s\nResuming repl\n" s;
repl env c
| Parser.Error ->
| Parser.Parse.Error ->
printf "Expression '%s' couldn't be parsed, try again\n" l;
repl env c
;;

View File

@@ -1,3 +1,17 @@
(* This is different from the lisp_ast data returned by the parser!
We will first need to translate that into this in order to use it.
This representation includes things that can only occur during runtime,
like the various kinds of functions and macros.
Additionally, since this is an interpreter, macros tend to be a little
awkward in that they behave exactly like the macro gets expanded just
before the result gets executed. This is different from the compiled
behaviour where the macro is evaluated at compile time.
Though of course, with the dynamic nature of lisp, and its capability
to compile more code at runtime, there will naturally be complications.
*)
type lisp_val =
| LInt of int
| LDouble of float
@@ -17,7 +31,7 @@ type lisp_val =
| LLambda of environment * lisp_val * lisp_val
(* a macro is exactly the same as a function, with the distinction
that it receives all of its arguments completely unevaluated
in a compiled lisp this would probably make more of a difference *)
*)
| LMacro of string * environment * lisp_val * lisp_val
| LUnnamedMacro of environment * lisp_val * lisp_val
| LQuoted of lisp_val
@@ -113,3 +127,16 @@ let pretty_print_all vs =
let dbg_print_all vs =
let pr v = Printf.printf "%s\n" (dbg_print_one v) in
List.iter pr vs
let rec convert_one = function
| Parser.Ast.LInt x -> LInt x
| Parser.Ast.LDouble x -> LDouble x
| Parser.Ast.LNil -> LNil
| Parser.Ast.LString s -> LString s
| Parser.Ast.LSymbol s -> LSymbol s
| Parser.Ast.LCons (a, b) -> LCons (convert_one a, convert_one b)
let read_from_str s =
List.map convert_one (Parser.parse_str s)

3
interpreter/dune Normal file
View File

@@ -0,0 +1,3 @@
(library
(name interpreter)
(libraries parser))

View File

@@ -200,5 +200,5 @@ let init_default_env () =
Idea: maybe put this in a file instead of putting
literally the entire standard library in a constant string
*)
ignore (Eval.eval_all default_env (Read.parse_str init_script));
ignore (Eval.eval_all default_env (read_from_str init_script));
()

View File

@@ -1,7 +0,0 @@
(library
(name lisp))
(include_subdirs unqualified)
(menhir (modules parser))
(ocamllex lexer)

0
parser.opam Normal file
View File

9
parser/ast.ml Normal file
View File

@@ -0,0 +1,9 @@
type lisp_ast =
| LInt of int
| LDouble of float
| LSymbol of string
| LString of string
| LNil
| LCons of lisp_ast * lisp_ast

18
parser/ast.mli Normal file
View File

@@ -0,0 +1,18 @@
(** This is a simplified representation for the source code.
Note that this is different from the data representation used
during execution - that must naturally include things like
functions, structs, classes, etc.
This is used just to represent source code in an easy to process
manner. We translate this before actually using it.
The interpreter directly translates to its value type, the
compiler uses this to optimise and compile.
**)
type lisp_ast =
| LInt of int
| LDouble of float
| LSymbol of string
| LString of string
| LNil
| LCons of lisp_ast * lisp_ast

8
parser/dune Normal file
View File

@@ -0,0 +1,8 @@
(library
(name parser)
(public_name parser)
(modules parser lex parse ast)
)
(menhir (modules parse))
(ocamllex lex)

View File

@@ -1,6 +1,6 @@
{
open Lexing
open Parser
open Parse
exception SyntaxError of string
let strip_quotes s = String.sub s 1 (String.length s - 2);;

View File

@@ -12,7 +12,7 @@
%token DOT
%token EOF
%start <Ast.lisp_val option> prog
%start <lisp_ast option> prog
%%
prog:
@@ -22,7 +22,7 @@ prog:
expr:
| i = INT { LInt i }
| d = DOUBLE {LDouble d}
| d = DOUBLE { LDouble d}
| s = SYM { LSymbol s }
| s = STR { LString (String.uppercase_ascii s) }
| LPAREN; l = lisp_list_rest { l }

View File

@@ -1,4 +1,4 @@
let parse_one lb = Parser.prog (Lexer.read) lb
let parse_one lb = Parse.prog (Lex.read) lb
let parse lb =
let rec helper () =
@@ -11,3 +11,6 @@ let parse lb =
let parse_str s =
parse (Lexing.from_string s)
module Ast = Ast
module Parse = Parse