git.m455.casa

fa

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