blob: dee99ad2d7e6cf1497162adc31b816ed1bc9a0fc (
plain)
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
|
(ns cljcc.util
(:require
[clojure.string :as str]
[cljcc.core.exception :as exc]))
(def ^:private counter "Global integer counter for generating unique identifier names." (atom 0))
(defn create-identifier!
"Returns a unique identifier. Used for generating unique identifier.
Removes : from keywords.
Replaces all - with _ for generating valid assembly names."
([]
(create-identifier! "tmp"))
([identifier]
(let [n @counter
_ (swap! counter inc)]
(-> identifier
(str "." n)
(str/replace #":" "")
(str/replace #"-" "_")))))
(defn reset-counter! []
(reset! counter 0))
(defn letter? [^Character ch]
(or (= \_ ch)
(Character/isLetter ch)))
(defn letter-digit? [^Character ch]
(or (= \_ ch)
(Character/isLetterOrDigit ch)))
(defn letter-digit-period? [^Character ch]
(or (= \_ ch)
(= \. ch)
(= \+ ch)
(= \- ch)
(Character/isLetterOrDigit ch)))
(defn digit? [^Character ch]
(Character/isDigit ch))
(defn newline? [ch]
(= \newline ch))
(defn whitespace? [^Character ch]
(Character/isWhitespace ch))
(defn matches-regex [re s]
(not (nil? (re-matches re s))))
(def unsigned-long-re-without-wordbreak #"[0-9]+([lL][uU]|[uU][lL])")
(def signed-long-re-without-wordbreak #"[0-9]+[lL]")
(def unsigned-int-re-without-wordbreak #"[0-9]+[uU]")
(def signed-int-re-without-wordbreak #"[0-9]+")
(def floating-point-constant-without-wordbreak #"([0-9]*\.[0-9]+|[0-9]+\.?)[Ee][+-]?[0-9]+|[0-9]*\.[0-9]+|[0-9]+\.")
(def unsigned-long-re #"([0-9]+([lL][uU]|[uU][lL]))[^\w.]")
(def signed-long-re #"([0-9]+[lL])[^\w.]")
(def unsigned-int-re #"([0-9]+[uU])[^\w.]")
(def signed-int-re #"([0-9]+)[^\w.]")
(def floating-point-constant #"(([0-9]*\.[0-9]+|[0-9]+\.?)[Ee][+-]?[0-9]+|[0-9]*\.[0-9]+|[0-9]+\.)[^\w.]")
(defn- re-find-indexed [re s]
(let [matcher (re-matcher re s)]
(when (.find matcher)
[(.group matcher 1)
(.start matcher 1)
(.end matcher 1)])))
(defn match-regex
"Returns matched string and remaining string tuple, otherwise returns nil.
The first match by re-finds must be the starting subsequence, otherwise false."
[re s]
(when-let [[matched start-index _] (re-find-indexed re s)]
(when (and (= 0 start-index) (str/starts-with? s matched))
[matched (str/replace-first s matched "")])))
(defn read-number
"Returns tuple of matched number and remaining string, otherwise nil."
[s line col]
(if-let [x (or
(match-regex floating-point-constant s)
(match-regex signed-int-re s)
(match-regex signed-long-re s)
(match-regex unsigned-int-re s)
(match-regex unsigned-long-re s))]
x
(exc/lex-error {:line line
:col col})))
(defn round-away-from-zero [num div]
(let [div (abs div)]
(cond
(= (mod num div) 0) num
(< num 0) (- num (- div (mod num div)))
:else (+ num (- div (mod num div))))))
(defn in-int-range?
"Verifies whether -2^31 <= x <= 2^31."
[v]
(and (>= v Integer/MIN_VALUE)
(<= v Integer/MAX_VALUE)))
(defn get-type-size [t]
(condp = t
{:type :int} 5
{:type :uint} 5
{:type :long} 10
{:type :ulong} 10
(exc/analyzer-error "Invalid type passed to get-type-size." {:type t})))
(defn type-double? [t]
(= {:type :double} t))
(defn type-signed? [t]
(condp = t
{:type :int} true
{:type :long} true
{:type :uint} false
{:type :ulong} false
(exc/analyzer-error "Invalid type passed to type-signed?." {:type t})))
|