clone url: git://git.m455.casa/fa
esperbuild/espersrc/fennel-0.7.0/src/fennel.fnl
1 | ;; Copyright © 2016-2020 Calvin Rose and contributors |
2 | ;; Permission is hereby granted, free of charge, to any person obtaining a copy |
3 | ;; of this software and associated documentation files (the "Software"), to |
4 | ;; deal in the Software without restriction, including without limitation the |
5 | ;; rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
6 | ;; sell copies of the Software, and to permit persons to whom the Software is |
7 | ;; furnished to do so, subject to the following conditions: The above copyright |
8 | ;; notice and this permission notice shall be included in all copies or |
9 | ;; substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", |
10 | ;; WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED |
11 | ;; TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
12 | ;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
13 | ;; LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF |
14 | ;; CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
15 | ;; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
16 |
|
17 | ;; This module ties everything else together; it's the public interface of |
18 | ;; the compiler. All other modules should be considered implementation details |
19 | ;; subject to change. |
20 |
|
21 | (local utils (require :fennel.utils)) |
22 | (local parser (require :fennel.parser)) |
23 | (local compiler (require :fennel.compiler)) |
24 | (local specials (require :fennel.specials)) |
25 | (local repl (require :fennel.repl)) |
26 |
|
27 | (fn get-env [env] |
28 | (if (= env :_COMPILER) |
29 | (let [env (specials.make-compiler-env nil compiler.scopes.compiler {}) |
30 | mt (getmetatable env)] |
31 | ;; remove sandboxing; linting won't work with it |
32 | (set mt.__index _G) |
33 | (specials.wrap-env env)) |
34 | (and env (specials.wrap-env env)))) |
35 |
|
36 | (fn eval [str options ...] |
37 | ;; eval and dofile are considered "live" entry points, so we can assume |
38 | ;; that the globals available at compile time are a reasonable allowed list |
39 | ;; UNLESS there's a metatable on env, in which case we can't assume that |
40 | ;; pairs will return all the effective globals; for instance openresty |
41 | ;; sets up _G in such a way that all the globals are available thru |
42 | ;; the __index meta method, but as far as pairs is concerned it's empty. |
43 | (let [opts (utils.copy options) |
44 | _ (when (and (= opts.allowedGlobals nil) |
45 | (not (getmetatable opts.env))) |
46 | (set opts.allowedGlobals (specials.current-global-names opts.env))) |
47 | ;; This is ... not great. Should we expose make-compiler-env in the API? |
48 | env (get-env opts.env) |
49 | lua-source (compiler.compile-string str opts) |
50 | loader (specials.load-code lua-source env |
51 | (if opts.filename |
52 | (.. "@" opts.filename) str))] |
53 | (set opts.filename nil) |
54 | (loader ...))) |
55 |
|
56 | (fn dofile* [filename options ...] |
57 | (let [opts (utils.copy options) |
58 | f (assert (io.open filename :rb)) |
59 | source (assert (f:read :*all) (.. "Could not read " filename))] |
60 | (f:close) |
61 | (set opts.filename filename) |
62 | (eval source opts ...))) |
63 |
|
64 | ;; The public API module we export: |
65 | (local mod {:list utils.list |
66 | :list? utils.list? |
67 | :sym utils.sym |
68 | :sym? utils.sym? |
69 | :varg utils.varg |
70 | :path utils.path |
71 |
|
72 | :parser parser.parser |
73 | :granulate parser.granulate |
74 | :string-stream parser.string-stream |
75 | :stringStream parser.string-stream ; backwards-compatibility alias |
76 |
|
77 | :compile compiler.compile |
78 | :compile-string compiler.compile-string |
79 | :compileString compiler.compile-string ; backwards-compatibility alias |
80 | :compile-stream compiler.compile-stream |
81 | :compileStream compiler.compile-stream ; backwards-compatibility alias |
82 | :compile1 compiler.compile1 |
83 | :traceback compiler.traceback |
84 | :mangle compiler.global-mangling |
85 | :unmangle compiler.global-unmangling |
86 | :metadata compiler.metadata |
87 | :scope compiler.make-scope |
88 | :gensym compiler.gensym |
89 |
|
90 | :load-code specials.load-code |
91 | :loadCode specials.load-code ; backwards-compatibility alias |
92 | :macro-loaded specials.macro-loaded |
93 | :macroLoaded specials.macro-loaded ; backwards-compatibility alias |
94 | :search-module specials.search-module |
95 | :searchModule specials.search-module ; backwards-compatibility alias |
96 | :make-searcher specials.make-searcher |
97 | :makeSearcher specials.make-searcher ; backwards-compatibility alias |
98 | :make_searcher specials.make-searcher ; backwards-compatibility alias |
99 | :searcher (specials.make-searcher) |
100 | :doc specials.doc |
101 |
|
102 | :eval eval |
103 | :dofile dofile* |
104 | :version "0.7.0" |
105 |
|
106 | :repl repl}) |
107 |
|
108 | ;; This is bad; we have a circular dependency between the specials section and |
109 | ;; the evaluation section due to require-macros/import-macros, etc. For now |
110 | ;; stash it in the utils table, but we should untangle it |
111 | (set utils.fennel-module mod) |
112 |
|
113 | ;; Load the built-in macros from macros.fnl. |
114 | (let [builtin-macros (eval-compiler |
115 | (with-open [f (assert (io.open "src/fennel/macros.fnl"))] |
116 | (.. "[===[" (f:read "*all") "]===]"))) |
117 | module-name "fennel.macros" |
118 | _ (tset package.preload module-name #mod) |
119 | env (doto (specials.make-compiler-env nil compiler.scopes.compiler {}) |
120 | (tset :require require) ; for macrodebug to require fennelview |
121 | (tset :utils utils) ; for import-macros to propagate compile opts |
122 | (tset :fennel mod)) |
123 | built-ins (eval builtin-macros {:env env |
124 | :scope compiler.scopes.compiler |
125 | :allowedGlobals false |
126 | :useMetadata true |
127 | :filename "src/fennel/macros.fnl" |
128 | :moduleName module-name})] |
129 | (each [k v (pairs built-ins)] |
130 | (tset compiler.scopes.global.macros k v)) |
131 | (set compiler.scopes.global.macros.λ compiler.scopes.global.macros.lambda) |
132 | (tset package.preload module-name nil)) |
133 |
|
134 | mod |