ada.2: typo
[jackhill/mal.git] / docs / Hints.md
CommitLineData
0198b7a2 1# Mal/Make-a-Lisp Implementation Hints
df5589d9
JM
2
3<a name="milliseconds"></a>
4
5### How do I get milliseconds since epoch for the "time-ms" function?
ae964c68 6### Does the "time-ms" function have to return millisecond since epoch?
df5589d9
JM
7
8Most languages usually have some way to do this natively even though
9it might be buried deeply in the language. If you are having trouble
10finding how to do this in your target language, consider asking the
11question on stackoverflow (if it has not been asked already) or asking
12on a discussion channel for your language because there is a good
13chance somebody there knows how and will answer quickly (if there is
14a native way at all).
15
16As a last resort you can always shell out and call the date command
17like this:
18
ae964c68
JM
19```
20date +%s%3N
21```
df5589d9 22
c19139e1
DM
23There are currently two implementations where this method was
24necessary (probably): bash and make. Unfortunately this method is
25limited to Linux/UNIX.
df5589d9
JM
26
27Also, "time-ms" technically just needs to return accurate milliseconds
28since some arbitrary point in time (even program start) in order to be
29used correctly for timing/benchmarking. For consistency it is best if
30it returns epoch milliseconds, but this is not strictly required if
31you language limitations make it difficult (e.g. size limit of
32integers).
33
34
35<a name="function_references"></a>
36
ae964c68
JM
37### How do I implement core/native functions if my language does not have any sort of function references (function pointers, closures, lambdas, etc)?
38### How do I implement mal functions in step4 if I do not have function references?
df5589d9
JM
39
40There are very few language that do not have any sort of function
41references so I suggest asking about the specific problem you are
42having on stackoverflow or a discussion channel for your language. In
43the rare case where you have a language without some sort of function
44reference abstraction, then you may have to implement a single
45function with a large switch statement (or equivalent) that calls out
46to the appropriate native core function ("+", "list", "throw", etc).
47In other words, you create a function that implements "function
48references" rather than using a feature of your language. You will
49still need to store the symbol names for those function in the base
50REPL environment but you will have some sort of tagging or marker that
51will indicate to the `EVAL` function that it should call your "big
52switch" function.
53
54In addition, if your language has no sort of closure/anonymous
55function capability (note that with sufficient object oriented
56features you can implement closure like functionality), then in step4
57you will need to borrow the way that functions are implemented from
58step5. In other words, functions become a normal data type that stores
59the function body (AST), the parameter list and the environment at the
60time the function is defined. When the function is invoked, `EVAL`
61will then evaluate these stored items rather than invoking a function
62closure. It is less convenient to have to do this at step4, but the
63bright side is that step5 will be simpler because you just have to
64implement the TCO loop because you have already refactored how
65functions are stored in step4.
66
67<a name="IO"></a>
68
ae964c68 69### How do I implement terminal input and output in a language which does not have standard I/O capabilities?
df5589d9
JM
70
71If your target language has some way to get data in and out while it
72is running (even if it is not standard terminal or file I/O) then you
73will need to create some sort of wrapper script (see
74`vimscript/run_vimscript.sh`) or call out to a shell script (see
75`make/readline.mk` and `make/util.mk`) or implement some other
76"appropriate" hack to to get the data in and out. As long
77as your implementation can be used with the test runner and the hack
78is just for working around I/O limitations in your target language,
79it is considered legitimate for upstream inclusion.
80
817316df
DM
81### How do I read the command-line arguments if my language runtime doesn't support access to them?
82
83Most languages give access to the command-line arguments that were passed to
0198b7a2 84the program, either as an argument to the `main` function (like `argc` and
817316df
DM
85`argv` in C) or as a global variable (like `sys.argv` in Python). If your
86target language doesn't have such mechanisms, consider adding a wrapper script
87that will read the command-line arguments that were passed to the script and
88pass them to the program in a way that the program can read. This might be
89through an environment variable (if the target language allows reading from
90environment variables) or through a temporary file.
91
92
df5589d9
JM
93<a name="no_reader_object">
94
95### How can I implement the reader without using a mutable object?
96
97You do not need a mutable object, but you do need someway of keeping
98track of the current position in the token list. One way to implement
99this is to pass both the token list and the current position to the
100reader functions (read_form, read_list, read_atom, etc) and return
101both the parsed AST and the new token list position. If your language
102does not allow multiple values to be returned from functions then you
103may need to define a data structure to return both the new position
104and the parsed AST together. In other words, the pseudo-code would
105look something like this:
106
107```
108ast, position = read_list(tokens, position)
109```
110
111---
112
113Answers for the following questions are TBD.
114
115### How do I implement slurp in a language without the ability to read raw file data?
116
117<a name="exceptions">
118
119### How do I support raising/throwing arbitrary objects in a language that does not support that?
120### What do I do if my implementation language only supports string exceptions?
121
122
123