-
Notifications
You must be signed in to change notification settings - Fork 179
Expand file tree
/
Copy pathDynamic.carp
More file actions
125 lines (100 loc) · 3.8 KB
/
Dynamic.carp
File metadata and controls
125 lines (100 loc) · 3.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
(doc Dynamic "This module contains dynamic functions which are used in the Carp repl and during compilation. They are not available in compiled code. Read more about dynamic functions in the [Language Guide](https://github.com/carp-lang/Carp/blob/master/docs/LanguageGuide.md#dynamic-functions).")
(defmodule Dynamic
;; Functions for doing things at the REPL and during compile time.
(doc proc? "checks whether `x` is callable.")
(defndynamic proc? [x]
(or
(List.in? (dynamic-type x) '(fn closure))
(let [s (s-expr x)]
(and (not (empty? s)) (= 'dynamic (dynamic-type (car s)))))))
(doc nil "is the value `nil`, i.e. the empty list.")
(defdynamic nil '())
(doc nil? "checks whether a value is nil, i.e. the empty list.")
(defndynamic nil? [value]
(= value nil))
(doc inc "increments a number.")
(defndynamic inc [x]
(+ x 1))
(doc dec "decrements a number.")
(defndynamic dec [x]
(- x 1))
(doc neg "negates a number.")
(defndynamic neg [x]
(* -1 x))
(doc mod "implements modulo, is slower than modulo specialized on
integers [`imod`](#imod).")
(defndynamic mod [x y]
(let-do [a (if (< x 0) (neg x) x)
b (if (< y 0) (neg y) y)
m a]
(while (or (> m b) (= m b))
(set! m (- m b)))
(if (< a 0) (neg m) m)))
(doc imod "implements modulo on integers, and is much faster than
[`mod](#mod).")
(defndynamic imod [x y]
(- x (* y (/ x y))))
(doc even? "checks whether the number `n` is even.")
(defndynamic even? [n] (= 0 (mod n 2)))
(doc odd? "checks whether the number `n` is odd.")
(defndynamic odd? [n] (= 1 (mod n 2)))
(defmodule Project
(doc no-echo "Turn off debug printing in the compiler.")
(defndynamic no-echo []
(do
(Project.config "print-ast" false)
(Project.config "echo-compiler-cmd" false))))
(defmodule String
(doc prefix "takes the prefix of the string `s` up to the index `to`.")
(defndynamic prefix [s to]
(String.slice s 0 to))
(doc suffix "takes the suffix of the string `s` from the index `from`.")
(defndynamic suffix [s from]
(String.slice s from (String.length s)))
(doc head "takes the head of the string `s` as a one-character string.")
(defndynamic head [s]
(String.prefix s 1))
(doc tail "takes the tail of the string `s`.")
(defndynamic tail [s]
(String.suffix s 1))
)
(defmodule Debug
(doc trace "prints the value of an expression to `stdout`, then returns its value.")
(defmacro trace [x]
(let [sym (gensym)]
`(let-do [%sym %x]
; we use eval here to ensure we resolve the symbol before putting it
; into file, line, and column
(macro-log
%(eval `(file %x)) ":"
%(eval `(line %x)) ":"
%(eval `(column %x)) ": "
%sym)
%sym))
)
)
)
;; The following functions are not put into a module for now:
(defndynamic add-cflag [flag]
(eval (list 'Project.config "cflag" flag)))
(defndynamic add-lib [lib]
(eval (list 'Project.config "libflag" lib)))
(defndynamic pkg-config [pkg flags]
(Dynamic.String.concat (Dynamic.append
(Dynamic.append
["`pkg-config " pkg " "]
(Project.get-config "pkgconfigflag")
)
[flags "`"])))
(defndynamic add-pkg [pkg]
(do
(add-cflag (pkg-config pkg "--cflags"))
(add-lib (pkg-config pkg "--libs"))))
(defndynamic current-file []
(car (Project.get-config "load-stack")))
(defndynamic relative-to [path relpath]
(Dynamic.String.concat [(Dynamic.Path.directory path)
"/"
relpath]))
(defndynamic add-c [relpath]
(Project.config "cmod" (relative-to (current-file) relpath)))