Reorganized basically everything, making way for the compiler
This commit is contained in:
9
bin/dune
9
bin/dune
@@ -1,6 +1,5 @@
|
|||||||
(executable
|
(executable
|
||||||
(name main)
|
(name inter)
|
||||||
(public_name main)
|
(public_name inter)
|
||||||
(libraries str lisp unix))
|
(libraries str interpreter unix)
|
||||||
(include_subdirs unqualified)
|
(package main))
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
open Lisp.Ast;;
|
open Interpreter.Ast;;
|
||||||
open Printf;;
|
open Printf;;
|
||||||
open Lisp;;
|
open Interpreter;;
|
||||||
open Env;;
|
open Env;;
|
||||||
open Eval;;
|
open Eval;;
|
||||||
open Read;;
|
|
||||||
|
|
||||||
let () = InterpreterStdlib.init_default_env ()
|
let () = Stdlib.init_default_env ()
|
||||||
|
|
||||||
let rec repl env c =
|
let rec repl env c =
|
||||||
let () = printf ">>> "; Out_channel.flush Out_channel.stdout; in
|
let () = printf ">>> "; Out_channel.flush Out_channel.stdout; in
|
||||||
@@ -14,7 +13,7 @@ let rec repl env c =
|
|||||||
| Some "exit" -> ()
|
| Some "exit" -> ()
|
||||||
| Some l ->
|
| Some l ->
|
||||||
try
|
try
|
||||||
let vals = (parse_str l) in
|
let vals = (read_from_str l) in
|
||||||
(* dbg_print_all vals; *)
|
(* dbg_print_all vals; *)
|
||||||
pretty_print_all (eval_all env vals);
|
pretty_print_all (eval_all env vals);
|
||||||
Out_channel.flush Out_channel.stdout;
|
Out_channel.flush Out_channel.stdout;
|
||||||
@@ -23,7 +22,7 @@ let rec repl env c =
|
|||||||
| Invalid_argument s ->
|
| Invalid_argument s ->
|
||||||
printf "%s\nResuming repl\n" s;
|
printf "%s\nResuming repl\n" s;
|
||||||
repl env c
|
repl env c
|
||||||
| Parser.Error ->
|
| Parser.Parse.Error ->
|
||||||
printf "Expression '%s' couldn't be parsed, try again\n" l;
|
printf "Expression '%s' couldn't be parsed, try again\n" l;
|
||||||
repl env c
|
repl env c
|
||||||
;;
|
;;
|
||||||
@@ -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 =
|
type lisp_val =
|
||||||
| LInt of int
|
| LInt of int
|
||||||
| LDouble of float
|
| LDouble of float
|
||||||
@@ -16,8 +30,8 @@ type lisp_val =
|
|||||||
| LFunction of string * environment * lisp_val * lisp_val
|
| LFunction of string * environment * lisp_val * lisp_val
|
||||||
| LLambda of environment * lisp_val * lisp_val
|
| LLambda of environment * lisp_val * lisp_val
|
||||||
(* a macro is exactly the same as a function, with the distinction
|
(* a macro is exactly the same as a function, with the distinction
|
||||||
that it receives all of its arguments completely unevaluated
|
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
|
| LMacro of string * environment * lisp_val * lisp_val
|
||||||
| LUnnamedMacro of environment * lisp_val * lisp_val
|
| LUnnamedMacro of environment * lisp_val * lisp_val
|
||||||
| LQuoted of lisp_val
|
| LQuoted of lisp_val
|
||||||
@@ -113,3 +127,16 @@ let pretty_print_all vs =
|
|||||||
let dbg_print_all vs =
|
let dbg_print_all vs =
|
||||||
let pr v = Printf.printf "%s\n" (dbg_print_one v) in
|
let pr v = Printf.printf "%s\n" (dbg_print_one v) in
|
||||||
List.iter pr vs
|
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
3
interpreter/dune
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
(library
|
||||||
|
(name interpreter)
|
||||||
|
(libraries parser))
|
||||||
@@ -200,5 +200,5 @@ let init_default_env () =
|
|||||||
Idea: maybe put this in a file instead of putting
|
Idea: maybe put this in a file instead of putting
|
||||||
literally the entire standard library in a constant string
|
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));
|
||||||
()
|
()
|
||||||
7
lib/dune
7
lib/dune
@@ -1,7 +0,0 @@
|
|||||||
(library
|
|
||||||
(name lisp))
|
|
||||||
|
|
||||||
(include_subdirs unqualified)
|
|
||||||
|
|
||||||
(menhir (modules parser))
|
|
||||||
(ocamllex lexer)
|
|
||||||
0
parser.opam
Normal file
0
parser.opam
Normal file
9
parser/ast.ml
Normal file
9
parser/ast.ml
Normal 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
18
parser/ast.mli
Normal 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
8
parser/dune
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
(library
|
||||||
|
(name parser)
|
||||||
|
(public_name parser)
|
||||||
|
(modules parser lex parse ast)
|
||||||
|
)
|
||||||
|
|
||||||
|
(menhir (modules parse))
|
||||||
|
(ocamllex lex)
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
open Lexing
|
open Lexing
|
||||||
open Parser
|
open Parse
|
||||||
exception SyntaxError of string
|
exception SyntaxError of string
|
||||||
|
|
||||||
let strip_quotes s = String.sub s 1 (String.length s - 2);;
|
let strip_quotes s = String.sub s 1 (String.length s - 2);;
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
%token DOT
|
%token DOT
|
||||||
%token EOF
|
%token EOF
|
||||||
|
|
||||||
%start <Ast.lisp_val option> prog
|
%start <lisp_ast option> prog
|
||||||
%%
|
%%
|
||||||
|
|
||||||
prog:
|
prog:
|
||||||
@@ -22,7 +22,7 @@ prog:
|
|||||||
|
|
||||||
expr:
|
expr:
|
||||||
| i = INT { LInt i }
|
| i = INT { LInt i }
|
||||||
| d = DOUBLE {LDouble d}
|
| d = DOUBLE { LDouble d}
|
||||||
| s = SYM { LSymbol s }
|
| s = SYM { LSymbol s }
|
||||||
| s = STR { LString (String.uppercase_ascii s) }
|
| s = STR { LString (String.uppercase_ascii s) }
|
||||||
| LPAREN; l = lisp_list_rest { l }
|
| LPAREN; l = lisp_list_rest { l }
|
||||||
@@ -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 parse lb =
|
||||||
let rec helper () =
|
let rec helper () =
|
||||||
@@ -11,3 +11,6 @@ let parse lb =
|
|||||||
let parse_str s =
|
let parse_str s =
|
||||||
parse (Lexing.from_string s)
|
parse (Lexing.from_string s)
|
||||||
|
|
||||||
|
|
||||||
|
module Ast = Ast
|
||||||
|
module Parse = Parse
|
||||||
Reference in New Issue
Block a user