├── .gitignore ├── README.md ├── bootstrap ├── download └── files ├── gems.sha256 ├── libevent-2.1.10-stable.tar.gz.sha256 ├── llvm-3.3.src.tar.gz.sha256 ├── llvm-3.5.2.src.tar.xz.sha256 ├── llvm-3.9.1.src.tar.xz.sha256 ├── llvm-config-3.3 ├── openssl-1.0.2q.tar.gz.sha256 ├── pcl-1.12.tar.gz.sha256 ├── ruby-1.9.3-p551.tar.gz.sha256 ├── stage1.patch ├── stage11.patch ├── stage16.patch ├── stage17.patch ├── stage18.patch ├── stage19.patch ├── stage25.patch ├── stage26.patch ├── stage27.patch ├── stage3.patch ├── stage35.patch ├── stage46.patch ├── stage47.patch ├── stage5.patch ├── stage61.patch ├── stage65.patch └── stage9.patch /.gitignore: -------------------------------------------------------------------------------- 1 | /downloads/ 2 | /buildroot/ 3 | /stages/ 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Crystal Bootstrap Automation 2 | 3 | This script automates bootstrapping crystal from source code, compiling every 4 | intermediate compiler version to reach the latest version. 5 | 6 | Dependencies: 7 | 8 | - Essential build tools i.e. `build-essential`/`base-devel` 9 | - curl 10 | - git 11 | - patch 12 | - which 13 | - tar 14 | - xz 15 | - autoconf 16 | - libtool 17 | - cmake 18 | - python2 19 | - pcre dev package 20 | - zlib dev package 21 | - libyaml dev package 22 | - libunwind dev package 23 | - libgc (bdwgc) dev package 24 | - libevent dev package 25 | -------------------------------------------------------------------------------- /bootstrap: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | # CD to the directly this file is actually in 5 | cd "$(dirname "$(realpath --logical "$0")")" 6 | 7 | downloads="$(pwd)"/downloads 8 | files="$(pwd)"/files 9 | buildroot="$(pwd)"/buildroot 10 | src="$buildroot"/src 11 | stages="$(pwd)"/stages 12 | 13 | crystal_stages="160" 14 | 15 | export PATH="$buildroot/bin:$PATH" 16 | export PKG_CONFIG_PATH="$buildroot/lib/pkgconfig" 17 | export LIBRARY_PATH="$buildroot/lib:$buildroot/llvm33/lib:$buildroot/llvm35/lib" 18 | export LD_LIBRARY_PATH="$LIBRARY_PATH" 19 | export LLVM_CONFIG="$buildroot"/bin/llvm-config 20 | export GEM_HOME="$buildroot"/lib/ruby/gems/1.9.1 21 | export CRYSTAL_CACHE_DIR=".crystal" 22 | 23 | test -d "$downloads" || (echo "downloads directory doesn't exist" && exit 1) 24 | 25 | echo "==> Checking files" 26 | 27 | ( 28 | cd "$downloads" 29 | 30 | sha256sum -c "$files"/openssl-1.0.2q.tar.gz.sha256 31 | sha256sum -c "$files"/ruby-1.9.3-p551.tar.gz.sha256 32 | sha256sum -c "$files"/libevent-2.1.10-stable.tar.gz.sha256 33 | sha256sum -c "$files"/llvm-3.3.src.tar.gz.sha256 34 | sha256sum -c "$files"/llvm-3.5.2.src.tar.xz.sha256 35 | sha256sum -c "$files"/llvm-3.9.1.src.tar.xz.sha256 36 | sha256sum -c "$files"/pcl-1.12.tar.gz.sha256 37 | 38 | cd "$downloads"/gems 39 | 40 | sha256sum -c "$files"/gems.sha256 41 | ) 42 | 43 | mkdir -p "$src" "$stages" 44 | 45 | echo "==> Installing OpenSSL" 46 | test -d "$src"/openssl-1.0.2q || ( 47 | cd "$src" 48 | 49 | tar xzf "$downloads"/openssl-1.0.2q.tar.gz 50 | 51 | cd openssl-1.0.2q 52 | 53 | ./config --prefix="$buildroot" shared 54 | make "-j$(nproc --all)" 55 | make install 56 | ) 57 | 58 | echo "==> Installing Ruby" 59 | test -d "$src"/ruby-1.9.3-p551 || ( 60 | cd "$src" 61 | 62 | tar xzf "$downloads"/ruby-1.9.3-p551.tar.gz 63 | 64 | cd ruby-1.9.3-p551 65 | 66 | autoconf 67 | ./configure --prefix="$buildroot" --enable-shared --disable-rpath 68 | make "-j$(nproc --all)" 69 | make install 70 | ) 71 | 72 | echo "==> Installing libevent 2.1.10" 73 | test -d "$src"/libevent-2.1.10-stable || ( 74 | cd "$src" 75 | 76 | tar xzf "$downloads"/libevent-2.1.10-stable.tar.gz 77 | 78 | cd libevent-2.1.10-stable 79 | 80 | ./configure --prefix="$buildroot" --enable-shared 81 | make "-j$(nproc --all)" 82 | make install 83 | ) 84 | 85 | mv -n "$buildroot"/lib/libevent.so.disabled "$buildroot"/lib/libevent.so || true 86 | 87 | echo "==> Installing LLVM 3.3" 88 | test -d "$src"/llvm-3.3.src || ( 89 | cd "$src" 90 | 91 | rm -Rf llvm-3.3.src 92 | tar xzf "$downloads"/llvm-3.3.src.tar.gz 93 | 94 | cd llvm-3.3.src 95 | 96 | CC=gcc CXX=g++ ./configure --prefix="$buildroot/llvm33" --enable-shared --enable-optimized --enable-targets="x86_64" --with-python="$(command -v python2)" 97 | make "-j$(nproc --all)" 98 | make install 99 | 100 | cp "$files"/llvm-config-3.3 "$buildroot"/bin/llvm-config-3.3 101 | chmod +x "$buildroot"/bin/llvm-config-3.3 102 | sed -i "s|@LLVM_CONFIG@|${buildroot}/llvm33/bin/llvm-config|" "$buildroot"/bin/llvm-config-3.3 103 | ) 104 | 105 | ln -sf "$buildroot"/bin/llvm-config-3.3 "$buildroot"/bin/llvm-config 106 | 107 | echo "==> Installing Gems" 108 | 109 | test -d "$src"/ruby-llvm || ( 110 | rm -Rf "$src"/ruby-llvm 111 | git clone -q "$downloads"/gems/ruby-llvm.git "$src"/ruby-llvm 112 | 113 | cd "$src"/ruby-llvm 114 | 115 | git checkout aaadfe83a3f99b550f5f1b0756b1784db73e0c37 116 | gem build ruby-llvm.gemspec 117 | ) 118 | 119 | test -d "$src"/ruby-prof || ( 120 | rm -Rf "$src"/ruby-prof 121 | git clone -q "$downloads"/gems/ruby-prof.git "$src"/ruby-prof 122 | 123 | cd "$src"/ruby-prof 124 | 125 | git checkout e1d1ba17e13f8ef5e24097034095ecc182d785e0 126 | gem build ruby-prof.gemspec 127 | ) 128 | 129 | cd "$src" 130 | 131 | test -f "$src"/gems-installed || ( 132 | gem install --no-rdoc --no-ri --local "$downloads"/gems/bundler-1.17.1.gem 133 | gem install --no-rdoc --no-ri --local "$downloads"/gems/mime-types-1.25.gem 134 | gem install --no-rdoc --no-ri --local "$downloads"/gems/rest-client-1.6.7.gem 135 | gem install --no-rdoc --no-ri --local "$downloads"/gems/tins-0.9.0.gem 136 | gem install --no-rdoc --no-ri --local "$downloads"/gems/term-ansicolor-1.2.2.gem 137 | gem install --no-rdoc --no-ri --local "$downloads"/gems/multi_json-1.8.0.gem 138 | gem install --no-rdoc --no-ri --local "$downloads"/gems/thor-0.18.1.gem 139 | gem install --no-rdoc --no-ri --local "$downloads"/gems/simplecov-html-0.7.1.gem 140 | gem install --no-rdoc --no-ri --local "$downloads"/gems/simplecov-0.7.1.gem 141 | gem install --no-rdoc --no-ri --local "$downloads"/gems/coveralls-0.7.0.gem 142 | gem install --no-rdoc --no-ri --local "$downloads"/gems/diff-lcs-1.2.4.gem 143 | gem install --no-rdoc --no-ri --local "$downloads"/gems/ffi-1.9.0.gem 144 | gem install --no-rdoc --no-ri --local "$downloads"/gems/json-1.7.7.gem 145 | gem install --no-rdoc --no-ri --local "$downloads"/gems/levenshtein-ffi-1.0.2.gem 146 | gem install --no-rdoc --no-ri --local "$downloads"/gems/rake-0.9.6.gem 147 | gem install --no-rdoc --no-ri --local "$downloads"/gems/rspec-core-2.14.5.gem 148 | gem install --no-rdoc --no-ri --local "$downloads"/gems/rspec-expectations-2.14.2.gem 149 | gem install --no-rdoc --no-ri --local "$downloads"/gems/rspec-mocks-2.14.3.gem 150 | gem install --no-rdoc --no-ri --local "$downloads"/gems/rspec-2.14.1.gem 151 | gem install --no-rdoc --no-ri --local "$downloads"/gems/ruby-graphviz-1.0.9.gem 152 | gem install --no-rdoc --no-ri --local "$src"/ruby-llvm/ruby-llvm-3.3.0.alpha.gem 153 | gem install --no-rdoc --no-ri --local "$src"/ruby-prof/ruby-prof-0.13.0.gem 154 | 155 | touch "$src"/gems-installed 156 | ) 157 | 158 | clone-crystal-at() { 159 | local ref="$1" 160 | 161 | rm -Rf "$src"/crystal 162 | git clone -q "$downloads"/crystal.git "$src"/crystal 163 | (cd "$src"/crystal; git checkout -q "$ref") 164 | } 165 | 166 | stage() { 167 | local stage_num="$1" 168 | local ref="$2" 169 | local commands="${3:-}" 170 | 171 | local input="$(find "$stages" -type f -regex ".*/$(( "$stage_num" - 1))-.*crystal")" 172 | if [[ "$ref" =~ [0-9]+\.[0-9]+\.[0-9]+ ]]; then 173 | local output="$stages/$stage_num-$ref-crystal" 174 | local name="Crystal $ref" 175 | else 176 | local output="$stages/$stage_num-crystal" 177 | local name="Crystal" 178 | fi 179 | 180 | echo "==> Bootstrapping $name ($(printf '%03d' "$stage_num")/$crystal_stages)" 181 | test -f "$output" || ( 182 | cd "$src" 183 | 184 | clone-crystal-at "$ref" 185 | 186 | cd crystal 187 | 188 | eval "$commands" 189 | 190 | "$input" "${crystal_args[@]}" -o "$output" src/compiler/crystal.cr || 191 | "$input" "${crystal_args[@]}" -o "$output" src/compiler/crystal.cr || exit 192 | ) 193 | } 194 | 195 | export CRYSTAL_PATH="$src"/crystal/src 196 | 197 | echo "==> Bootstrapping Crystal (001/$crystal_stages)" 198 | test -f "$stages"/1-crystal || ( 199 | cd "$src" 200 | 201 | clone-crystal-at 04964442a2de0268f63c492b22b17cb502724fc7 202 | 203 | cd crystal 204 | 205 | patch -p1 < "$files"/stage1.patch 206 | 207 | LD_LIBRARY_PATH="$buildroot/lib:$buildroot/llvm33/lib" bin/crystal -stats bootstrap/crystal.cr 208 | mv crystal "$stages"/1-crystal 209 | ) 210 | 211 | crystal_args=(-stats) 212 | 213 | stage 2 bffda57eafff50a41e86618f7c2726803d31e42c "sed -i 's/\`llvm-config --libs --ldflags\`/LLVM-3.3/' src/compiler/crystal/llvm.cr && 214 | sed -i 's/\\\\e/$(printf '\e')/' src/compiler/crystal/lexer.cr" 215 | 216 | crystal_args=(-stats --llc '-relocation-model=pic') 217 | 218 | stage 3 6657d3c84c93ec0c886aa9262b2a33791e22285f 'patch -p1 < "$files"/stage3.patch' 219 | stage 4 407e719ddb90d27e45a2e25e82f8a4653ae45beb 220 | stage 5 4d343928fda4d728294965af95febb38afd0d0ac 'patch -p1 < "$files"/stage5.patch' 221 | stage 6 72f260e00bf343d179dd2a72b5f6e699f9030739 222 | stage 7 90d7aad39c500fcbced6d5fba7f63098a0d24918 223 | stage 8 570be14b8bd422ebf68f2b4c65de8431d23014e1 224 | 225 | # addressof was renamed to pointerof in a sinle commit. This patch is just the compiler changes. 226 | stage 9 6f084f00e416045a6a5de16e8a0637831e041f22 'patch -p1 < "$files"/stage9.patch' 227 | 228 | stage 10 b2cdfe57ef177f3362a977ebd80fb3eed692b465 229 | stage 11 4ceda49393a5cd6063fcacc97acb6a5d19e5b0a2 'patch -p1 < "$files"/stage11.patch' 230 | stage 12 9af98fc4d4f75938b4e4989afa50a388c8219a60 231 | stage 13 55dae4faa3e2591d384da3acb368c8dbe10fa1aa 232 | stage 14 b3954fd743dfecec4e28cdf04c8575319fadd9fa 233 | stage 15 d6a5ad0d26811d977ac46ca468123f7f8f5bdddf 234 | stage 16 12d3afc73ab370dff7b01a4181cd0e351914e4fa 'patch -p1 < "$files"/stage16.patch' 235 | 236 | # This patch is a combination of the compiler half of commit 55f369935a9201bbb47cfae431358137f0e08340 237 | # and a cherry-pick of 9885f81cc5507f6589486142664abbb2959e2252. That latter commit avoids any JIT issues 238 | # when changing the in-memory format of crystal objects by not JITing anything. 239 | stage 17 7b3172b28ec78dfef4f459399e8cfe30e84dfb22 'patch -p1 < "$files"/stage17.patch' 240 | 241 | stage 18 c1b24dde5ac2b8e893018eafb681f47f9a04c414 'patch -p1 < "$files"/stage18.patch' 242 | stage 19 4d64dc843bff941c3ab3805011164d79afa83d61 'patch -p1 < "$files"/stage19.patch' 243 | stage 20 2a462911c231480d919a37ef3bc03a5941e3e51b 244 | stage 21 bd69c9bc9abd9295b17fe3a0e46dc826e08bdca9 245 | stage 22 107f1a8948e1c0b0fe39fd151f105e4e39cf0439 246 | stage 23 d1e4943a46ffc6efaf3bc2f9e4c92f27de54b12d 247 | 248 | export CRYSTAL_PATH="$src"/crystal/src:libs 249 | 250 | stage 24 51bb8313ea45c1eed59151f34ac618ef2a930fe9 251 | stage 25 c2d5bea9fa3d7779a35b8266d1e6be78bf627e76 'patch -p1 < "$files"/stage25.patch' 252 | stage 26 1f58dc82b733dc06e237ee2ed6b17cb07f196308 'patch -p1 < "$files"/stage26.patch' 253 | stage 27 25eb532631e3dbeaa778cd10f18e085e077cde72 'patch -p1 < "$files"/stage27.patch' 254 | stage 28 dec595a2f21c91b5510aec1bed62011dbc76b4e8 255 | stage 29 fbea5680d69dd4924bc769444614d17dd6953e97 256 | 257 | crystal_args=(--stats --llc '-relocation-model=pic') 258 | 259 | stage 30 ba1613f26e261bf8a3c43c143bc7f4d8868146d0 'git revert -n e5909ae322ecc292512c8d58decb4cd37c344fbd' 260 | stage 31 b50b0226d9b5f8c8688236e54104918bc06ea526 261 | stage 32 3abb79bb83468751bb4aec1541d49c9f9526a9a5 262 | stage 33 b169aec39aff9b8dce35faf2af2fb4bd95866cf3 263 | stage 34 e697ecd3e80957b89bfa98d8df41d0596ba5a3a0 264 | stage 35 698485e0351f3ee7f10f8d749d360a573241e034 'patch -p1 < "$files"/stage35.patch' 265 | stage 36 dcecbe7a258a4e929541a17765ad984eb500ae73 266 | stage 37 89b1e67b74530bdd7f8c45914d131300c4b9998c 267 | stage 38 fd022eb1391ed29f7c7fc9b21a3ebbc1a08eee96 268 | stage 39 834e29389eb0618a9fbc62cba0b1c9b4d00478b8 269 | stage 40 4aaae0d89e1d2c89b738956829ad5430a11dd8c0 270 | stage 41 e60ee730726c488df85bf2cc6304f2ef82c5e9ac 271 | stage 42 b8577f770904c97d651a86e892648fe9d3ec4bb7 272 | stage 43 0506317f71561c54d67db5119a5290cc39920d16 273 | stage 44 523ebc0f40b673f2f17a57a5783d74e868d9c785 274 | stage 45 a89665b6c65e14c43a9ef19a38d1b12849bb56f6 275 | stage 46 68d154c82f0b5ef3e3fa29e0e9be25e033328530 'patch -p1 < "$files"/stage46.patch' 276 | 277 | # TODO: build clang for LLVM and remove --release 278 | crystal_args=(--stats --release --llc '-relocation-model=pic') 279 | 280 | stage 47 f1d3a458b8f23cb1334e700ef224ee6b381b0e42 'patch -p1 < "$files"/stage47.patch' 281 | stage 48 7689dfa91c41e9aa54110c1d701816eea2dca721 282 | stage 49 4fb32b775bf5f71abf46b6efe936c019aab100b4 283 | stage 50 4948b8f2517e5d19c583181f4c9b561a99b568dd 284 | stage 51 8a7bf7dddfe55b195e1f2923ffb10f340f239d61 285 | stage 52 157fadbc0899bb490574f6ad1542dbe3d080c0e1 286 | stage 53 bca6ca585db5d82c02d195c178c29812357255e7 287 | stage 54 859ff652db9112a258117bdd43de2bc264001186 288 | stage 55 56de290dd4f8d0db6ab7b0b4da994be48a8dd4dd 289 | stage 56 6418bf84f68c6f2a1af18af0b70a82dd7f67ef35 290 | 291 | crystal_args=(--stats --llc '-relocation-model=pic') 292 | 293 | stage 57 0.1.0 294 | 295 | # Fix check for clang/gcc was accidentally removed in some previous commit 296 | stage 58 bafc4722d67f3db25434d8ad1f8cf0fb9068ca93 'git cherry-pick -n b04d62623ff9791db57c3bcd59d1e4cb284b8271' 297 | 298 | # Fix check for clang/gcc was accidentally removed in some previous commit 299 | stage 59 0.2.0 'git cherry-pick -n b04d62623ff9791db57c3bcd59d1e4cb284b8271' 300 | 301 | # We are so close to building 0.3.0 with the previous compiler (and the diff to do so is trivial), 302 | # we just fudge it so we can. 303 | stage 60 0.3.0 'git revert -n 623d4d6801a1980590219174ce78d26028713879' 304 | 305 | stage 61 632d53d703c7766b3d58670aaaf94696cd55271b 'patch -p1 < "$files"/stage61.patch' 306 | stage 62 0.3.1 307 | stage 63 0.3.2 308 | stage 64 0ff6dac07625a8921742525e67b3ffaf18a15d69 309 | stage 65 e7845ec76573a8192a997baeeb443b01d6a51c62 'patch -p1 < "$files"/stage65.patch' 310 | stage 66 0.3.3 311 | stage 67 0.3.4 312 | stage 68 f4b8600835f76727467f9b649c192f1609a61fcd 313 | stage 69 0.3.5 314 | stage 70 0.4.0 315 | stage 71 0.4.1 316 | stage 72 0.4.2 'git revert -n 0e2e664a304027bb7d50835cb49ec09cb1307b4c' 317 | stage 73 0.4.3 318 | stage 74 0.4.4 "sed -i 's/LLVM::RelocMode::Default/LLVM::RelocMode::PIC/' libs/llvm/target.cr" 319 | 320 | echo "==> Installing LLVM 3.5.2" 321 | test -d "$src"/llvm-3.5.2.src || ( 322 | cd "$src" 323 | 324 | rm -Rf llvm-3.5.2.src 325 | tar xJf "$downloads"/llvm-3.5.2.src.tar.xz 326 | 327 | cd llvm-3.5.2.src 328 | 329 | CC=gcc CXX=g++ ./configure --prefix="$buildroot/llvm35" --enable-shared --enable-optimized --enable-targets="x86_64" --with-python="$(command -v python2)" 330 | make "-j$(nproc --all)" 331 | make install 332 | 333 | ln -s "$buildroot"/llvm35/bin/llvm-config "$buildroot"/bin/llvm-config-3.5 334 | ) 335 | 336 | ln -sf "$buildroot"/bin/llvm-config-3.5 "$buildroot"/bin/llvm-config 337 | 338 | crystal_args=(--stats) 339 | 340 | stage 75 0.4.5 "sed -i 's/LLVM::RelocMode::Default/LLVM::RelocMode::PIC/' libs/llvm/target.cr" 341 | stage 76 0.5.0 "sed -i 's/LLVM::RelocMode::Default/LLVM::RelocMode::PIC/' libs/llvm/target.cr" 342 | stage 77 0.5.1 "sed -i 's/LLVM::RelocMode::Default/LLVM::RelocMode::PIC/' libs/llvm/target.cr" 343 | stage 78 0.5.2 "sed -i 's/LLVM::RelocMode::Default/LLVM::RelocMode::PIC/' libs/llvm/target.cr" 344 | 345 | crystal_args=(build --stats) 346 | 347 | stage 79 0.5.3 "sed -i 's/LLVM::RelocMode::Default/LLVM::RelocMode::PIC/' libs/llvm/target.cr" 348 | stage 80 0.5.4 "sed -i 's/LLVM::RelocMode::Default/LLVM::RelocMode::PIC/' libs/llvm/target.cr" 349 | 350 | export CRYSTAL_PATH="$src"/crystal/src 351 | 352 | stage 81 0.5.5 "sed -i 's/LLVM::RelocMode::Default/LLVM::RelocMode::PIC/' src/llvm/target.cr" 353 | stage 82 0.5.6 "sed -i 's/LLVM::RelocMode::Default/LLVM::RelocMode::PIC/' src/llvm/target.cr" 354 | stage 83 0.5.7 "sed -i 's/LLVM::RelocMode::Default/LLVM::RelocMode::PIC/' src/llvm/target.cr" 355 | stage 84 0.5.8 "sed -i 's/LLVM::RelocMode::Default/LLVM::RelocMode::PIC/' src/llvm/target.cr" 356 | stage 85 0.5.9 "sed -i 's/LLVM::RelocMode::Default/LLVM::RelocMode::PIC/' src/llvm/target.cr" 357 | stage 86 0.5.10 "sed -i 's/LLVM::RelocMode::Default/LLVM::RelocMode::PIC/' src/llvm/target.cr" 358 | stage 87 0.6.0 "sed -i 's/LLVM::RelocMode::Default/LLVM::RelocMode::PIC/' src/llvm/target.cr" 359 | stage 88 0.6.1 "sed -i 's/LLVM::RelocMode::Default/LLVM::RelocMode::PIC/' src/llvm/target.cr" 360 | 361 | echo "==> Installing libpcl" 362 | test -d "$src"/pcl-1.12 || ( 363 | cd "$src" 364 | 365 | tar xzf "$downloads"/pcl-1.12.tar.gz 366 | 367 | cd pcl-1.12 368 | 369 | ./configure --prefix="$buildroot" 370 | make "-j$(nproc --all)" 371 | make install 372 | ) 373 | 374 | stage 89 0.7.0 375 | stage 90 0.7.1 376 | stage 91 0.7.2 377 | stage 92 0.7.3 378 | stage 93 0.7.4 379 | stage 94 0.7.5 380 | stage 95 0.7.6 381 | stage 96 0.7.7 382 | stage 97 0.8.0 'make llvm_ext' 383 | stage 98 0.9.0 'make llvm_ext' 384 | stage 99 0.9.1 'make llvm_ext' 385 | stage 100 0.10.0 'make llvm_ext' 386 | stage 101 0.10.1 'make llvm_ext' 387 | stage 102 0.10.2 'make llvm_ext' 388 | stage 103 0.11.0 'make llvm_ext' 389 | stage 104 0.11.1 'make llvm_ext' 390 | stage 105 0.12.0 'make deps' 391 | stage 106 0.13.0 'make deps' 392 | 393 | crystal_args=(build --stats -Dwithout_openssl -Dwithout_zlib) 394 | 395 | stage 107 0.14.0 'make deps' 396 | stage 108 0.14.1 'make deps' 397 | stage 109 0.14.2 'make deps' 398 | stage 110 0.15.0 'make deps' 399 | stage 111 a08e178530839ff3a998cc6f8aea7bcc516f267c 'make deps' 400 | stage 112 0.16.0 'make deps' 401 | stage 113 0.17.0 'make deps' 402 | stage 114 0.17.1 'make deps' 403 | stage 115 0.17.2 'make deps' 404 | stage 116 0.17.3 'make deps' 405 | stage 117 0.17.4 'make deps' 406 | 407 | fix_libdirs_command='sed -i "s|\\[\"/usr/lib\", \"/usr/local/lib\"\\]|[] of String|" src/compiler/crystal/codegen/link.cr' 408 | 409 | stage 118 0.18.0 "$fix_libdirs_command && make deps" 410 | stage 119 0.18.1 "$fix_libdirs_command && make deps" 411 | stage 120 0.18.2 "$fix_libdirs_command && make deps" 412 | stage 121 0.18.3 'make deps' 413 | stage 122 0.18.4 'make deps' 414 | stage 123 0.18.5 'make deps' 415 | stage 124 0.18.6 'make deps' 416 | stage 125 0.18.7 'make deps' 417 | stage 126 0.19.0 'make deps' 418 | stage 127 0.19.1 'make deps' 419 | stage 128 0.19.2 'make deps' 420 | stage 129 0.19.3 'make deps' 421 | stage 130 0.19.4 'make deps' 422 | 423 | echo "==> Installing LLVM 3.9.1" 424 | test -d "$src"/llvm-3.9.1.src || ( 425 | cd "$src" 426 | 427 | rm -Rf llvm-3.9.1.src 428 | tar xJf "$downloads"/llvm-3.9.1.src.tar.xz 429 | 430 | cd llvm-3.9.1.src 431 | 432 | mkdir build 433 | cd build 434 | cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$buildroot/llvm39" -DLLVM_TARGETS_TO_BUILD="X86" .. 435 | 436 | make "-j$(nproc --all)" 437 | make install 438 | 439 | ln -s "$buildroot"/llvm39/bin/llvm-config "$buildroot"/bin/llvm-config-3.9 440 | ) 441 | 442 | ln -sf "$buildroot"/bin/llvm-config-3.9 "$buildroot"/bin/llvm-config 443 | 444 | stage 131 0.20.0 'make deps' 445 | stage 132 0.20.1 'make deps' 446 | 447 | crystal_args=(build --stats -Dwithout_openssl -Dwithout_zlib -Di_know_what_im_doing) 448 | 449 | stage 133 0.20.2 'make deps' 450 | stage 134 0.20.3 'make deps' 451 | stage 135 0.20.4 'make deps' 452 | stage 136 0.20.5 'make deps' 453 | stage 137 0.21.0 'make deps' 454 | stage 138 0.21.1 'make deps' 455 | stage 139 0.22.0 'make deps' 456 | stage 140 0.23.0 'make deps' 457 | stage 141 0.23.1 'make deps' 458 | stage 142 0.24.0 'make deps' 459 | stage 143 0.24.1 'make deps' 460 | stage 144 0.24.2 'make deps' 461 | stage 145 0.25.0 'make deps' 462 | stage 146 0.25.1 'make deps' 463 | stage 147 0.26.0 'make deps' 464 | stage 148 0.26.1 'make deps' 465 | stage 149 0.27.0 'make deps' 466 | stage 150 0.27.1 'make deps' 467 | stage 151 0.27.2 'make deps' 468 | stage 152 0.28.0 'make deps' 469 | stage 153 0.29.0 'make deps' 470 | stage 154 0.30.0 'make deps' 471 | stage 155 0.30.1 'make deps' 472 | stage 156 0.31.0 'make deps' 473 | stage 157 0.31.1 'make deps' 474 | 475 | # Libevent incompatibility is fixed now, swap out libevent.so 476 | mv -f "$buildroot"/lib/libevent.so "$buildroot"/lib/libevent.so.disabled 477 | 478 | stage 158 0.32.0 'make deps' 479 | stage 159 0.32.1 'make deps' 480 | stage 160 0.33.0 'make deps' 481 | stage 161 0.34.0 'make deps' 482 | stage 162 0.35.1 'make deps' 483 | stage 162 0.36.1 'make deps' 484 | -------------------------------------------------------------------------------- /download: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | # CD to the directly this file is actually in 5 | cd "$(dirname "$(realpath --logical "$0")")" 6 | 7 | downloads="$(pwd)"/downloads 8 | 9 | rm -Rf "$downloads" 10 | mkdir -p "$downloads" 11 | 12 | curl -L -o "$downloads"/openssl-1.0.2q.tar.gz https://www.openssl.org/source/old/1.0.2/openssl-1.0.2q.tar.gz 13 | curl -L -o "$downloads"/ruby-1.9.3-p551.tar.gz https://cache.ruby-lang.org/pub/ruby/1.9/ruby-1.9.3-p551.tar.gz 14 | curl -L -o "$downloads"/libevent-2.1.10-stable.tar.gz https://github.com/libevent/libevent/releases/download/release-2.1.10-stable/libevent-2.1.10-stable.tar.gz 15 | curl -L -o "$downloads"/llvm-3.3.src.tar.gz https://releases.llvm.org/3.3/llvm-3.3.src.tar.gz 16 | curl -L -o "$downloads"/llvm-3.5.2.src.tar.xz https://releases.llvm.org/3.5.2/llvm-3.5.2.src.tar.xz 17 | curl -L -o "$downloads"/llvm-3.9.1.src.tar.xz https://releases.llvm.org/3.9.1/llvm-3.9.1.src.tar.xz 18 | curl -L -o "$downloads"/pcl-1.12.tar.gz http://xmailserver.org/pcl-1.12.tar.gz 19 | git clone --mirror https://github.com/crystal-lang/crystal.git "$downloads"/crystal.git 20 | 21 | # Gems 22 | mkdir "$downloads"/gems 23 | curl -L -o "$downloads"/gems/bundler-1.17.1.gem https://rubygems.org/downloads/bundler-1.17.1.gem 24 | git clone --mirror https://github.com/manastech/ruby-llvm.git "$downloads"/gems/ruby-llvm.git 25 | git clone --mirror https://github.com/ruby-prof/ruby-prof.git "$downloads"/gems/ruby-prof.git 26 | curl -L -o "$downloads"/gems/coveralls-0.7.0.gem https://rubygems.org/downloads/coveralls-0.7.0.gem 27 | curl -L -o "$downloads"/gems/diff-lcs-1.2.4.gem https://rubygems.org/downloads/diff-lcs-1.2.4.gem 28 | curl -L -o "$downloads"/gems/ffi-1.9.0.gem https://rubygems.org/downloads/ffi-1.9.0.gem 29 | curl -L -o "$downloads"/gems/json-1.7.7.gem https://rubygems.org/downloads/json-1.7.7.gem 30 | curl -L -o "$downloads"/gems/levenshtein-ffi-1.0.2.gem https://rubygems.org/downloads/levenshtein-ffi-1.0.2.gem 31 | curl -L -o "$downloads"/gems/mime-types-1.25.gem https://rubygems.org/downloads/mime-types-1.25.gem 32 | curl -L -o "$downloads"/gems/multi_json-1.8.0.gem https://rubygems.org/downloads/multi_json-1.8.0.gem 33 | curl -L -o "$downloads"/gems/rake-0.9.6.gem https://rubygems.org/downloads/rake-0.9.6.gem 34 | curl -L -o "$downloads"/gems/rest-client-1.6.7.gem https://rubygems.org/downloads/rest-client-1.6.7.gem 35 | curl -L -o "$downloads"/gems/rspec-2.14.1.gem https://rubygems.org/downloads/rspec-2.14.1.gem 36 | curl -L -o "$downloads"/gems/rspec-core-2.14.5.gem https://rubygems.org/downloads/rspec-core-2.14.5.gem 37 | curl -L -o "$downloads"/gems/rspec-expectations-2.14.2.gem https://rubygems.org/downloads/rspec-expectations-2.14.2.gem 38 | curl -L -o "$downloads"/gems/rspec-mocks-2.14.3.gem https://rubygems.org/downloads/rspec-mocks-2.14.3.gem 39 | curl -L -o "$downloads"/gems/ruby-graphviz-1.0.9.gem https://rubygems.org/downloads/ruby-graphviz-1.0.9.gem 40 | curl -L -o "$downloads"/gems/simplecov-0.7.1.gem https://rubygems.org/downloads/simplecov-0.7.1.gem 41 | curl -L -o "$downloads"/gems/simplecov-html-0.7.1.gem https://rubygems.org/downloads/simplecov-html-0.7.1.gem 42 | curl -L -o "$downloads"/gems/term-ansicolor-1.2.2.gem https://rubygems.org/downloads/term-ansicolor-1.2.2.gem 43 | curl -L -o "$downloads"/gems/thor-0.18.1.gem https://rubygems.org/downloads/thor-0.18.1.gem 44 | curl -L -o "$downloads"/gems/tins-0.9.0.gem https://rubygems.org/downloads/tins-0.9.0.gem 45 | -------------------------------------------------------------------------------- /files/gems.sha256: -------------------------------------------------------------------------------- 1 | cc9042aff791fb05dc037da8dc617bee3fb4d77d74c3d921c2f51c23f231b24a bundler-1.17.1.gem 2 | 449284ddd071e2297d06d0a9d18fe4c2b4027848263b1087d4180fb44e03e36b coveralls-0.7.0.gem 3 | ad87b8b5892d3c275674d57e8398d83b2152419c08dd3f88453e0df3a473ab27 diff-lcs-1.2.4.gem 4 | 7e73075fd054440d03e9ebedfe9c0240e24783683ebe5351acedb2efbc4fd066 ffi-1.9.0.gem 5 | fd702ed46565b354d7508e88bb3c4855f7fdd771ab89435d7ecbbe98deb0b7ec json-1.7.7.gem 6 | fda5c1bb871eb51a78757e7fa997c7c790e9be7ff9606a4feb3c3dc9858b18dd levenshtein-ffi-1.0.2.gem 7 | ee2dc47f195959f3b0729e889c3dabfce7ba0cf9e04cfba31eddcb02e885a641 mime-types-1.25.gem 8 | 3d273b486882b140c7774cc8ccf99b25313df07be1debd9d9b5094b27ac2a4eb multi_json-1.8.0.gem 9 | 0cde8637bc097b984b602d7db77b1982b3a0be5ab014f1e533b6b517ca807e26 rake-0.9.6.gem 10 | a3203433b8b0c914648caea54395a8791a61e0df7d401c81f4e2b7f8a8fac75a rest-client-1.6.7.gem 11 | 4f9fc6c58696faa22571ca80d710fd0e4f30eaeb700155968d36df303f279e8c rspec-2.14.1.gem 12 | 99d51ee6038e43ff500574119119ad0b485f31a332406882be44fea78a17f3a3 rspec-core-2.14.5.gem 13 | cb397f5b2f966adcd3fa6c6bb1e3ff0cb0237c08bb8ab01ea56bab106b9b61a9 rspec-expectations-2.14.2.gem 14 | f92faf5e39abc858c8700cde9a40d934e71165c8648e05a50862d5bb7594d0f5 rspec-mocks-2.14.3.gem 15 | a37dddf517eb5adad5ae94532edc5a8432e1edf09b3af60652a1be2cdccacdbb ruby-graphviz-1.0.9.gem 16 | f0b974cb466bfd9174e16a7f74bde1edc651548d6c221fd112fa07d9c56f1b25 simplecov-0.7.1.gem 17 | 5eb2889435813c390e1ddc946e4dd853e92d9dd0e8aeac63b3858cf4a27d6948 simplecov-html-0.7.1.gem 18 | b9534713ba4c2a48f2291fadf9ce2edae9f2dc96157ee812fe8fe16a70c081ac term-ansicolor-1.2.2.gem 19 | 8321c57da1b142327ce802227fde78fefd04f9a81467e45a9cee306de4192f34 thor-0.18.1.gem 20 | 6cdd0469d8d8cf1ab5acea24a4dca2adb3c49e365171cd7cf28b2dd8bf3f249c tins-0.9.0.gem 21 | -------------------------------------------------------------------------------- /files/libevent-2.1.10-stable.tar.gz.sha256: -------------------------------------------------------------------------------- 1 | e864af41a336bb11dab1a23f32993afe963c1f69618bd9292b89ecf6904845b0 libevent-2.1.10-stable.tar.gz 2 | -------------------------------------------------------------------------------- /files/llvm-3.3.src.tar.gz.sha256: -------------------------------------------------------------------------------- 1 | 68766b1e70d05a25e2f502e997a3cb3937187a3296595cf6e0977d5cd6727578 llvm-3.3.src.tar.gz 2 | -------------------------------------------------------------------------------- /files/llvm-3.5.2.src.tar.xz.sha256: -------------------------------------------------------------------------------- 1 | 44196156d5749eb4b4224fe471a29cc3984df92570a4a89fa859f7394fc0c575 llvm-3.5.2.src.tar.xz 2 | -------------------------------------------------------------------------------- /files/llvm-3.9.1.src.tar.xz.sha256: -------------------------------------------------------------------------------- 1 | 1fd90354b9cf19232e8f168faf2220e79be555df3aa743242700879e8fd329ee llvm-3.9.1.src.tar.xz 2 | -------------------------------------------------------------------------------- /files/llvm-config-3.3: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | LLVM_CONFIG = "@LLVM_CONFIG@" 4 | 5 | ARGV.each do |arg| 6 | if arg == "--libs" 7 | puts "-lLLVM-3.3" 8 | else 9 | print `#{LLVM_CONFIG} #{arg}` 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /files/openssl-1.0.2q.tar.gz.sha256: -------------------------------------------------------------------------------- 1 | 5744cfcbcec2b1b48629f7354203bc1e5e9b5466998bbccc5b5fcde3b18eb684 openssl-1.0.2q.tar.gz 2 | -------------------------------------------------------------------------------- /files/pcl-1.12.tar.gz.sha256: -------------------------------------------------------------------------------- 1 | e7b30546765011575d54ae6b44f9d52f138f5809221270c815d2478273319e1a pcl-1.12.tar.gz 2 | -------------------------------------------------------------------------------- /files/ruby-1.9.3-p551.tar.gz.sha256: -------------------------------------------------------------------------------- 1 | bb5be55cd1f49c95bb05b6f587701376b53d310eb1bb7c76fbd445a1c75b51e8 ruby-1.9.3-p551.tar.gz 2 | -------------------------------------------------------------------------------- /files/stage1.patch: -------------------------------------------------------------------------------- 1 | diff --git a/bin/crystal b/bin/crystal 2 | index ecbe088f6..bd3c00430 100755 3 | --- a/bin/crystal 4 | +++ b/bin/crystal 5 | @@ -1,11 +1,9 @@ 6 | #!/usr/bin/env ruby 7 | GC.disable unless ENV["CI"] 8 | 9 | -ENV['BUNDLE_GEMFILE'] = File.expand_path('../../Gemfile', File.realpath(__FILE__)) 10 | -require 'bundler/setup' 11 | +require 'forwardable' 12 | require_relative '../lib/crystal' 13 | -require 'pry' 14 | -require 'pry-debugger' 15 | +require 'pathname' 16 | 17 | compiler = Crystal::Compiler.new 18 | compiler.compile 19 | diff --git a/bootstrap/crystal/compiler.cr b/bootstrap/crystal/compiler.cr 20 | index dbdef7c37..72805c235 100644 21 | --- a/bootstrap/crystal/compiler.cr 22 | +++ b/bootstrap/crystal/compiler.cr 23 | @@ -205,7 +205,7 @@ module Crystal 24 | end 25 | end 26 | flags << " -Wl,-allow_stack_execute" if mod.has_require_flag?("darwin") 27 | - flags << " -L#{@config.lib_dir}" 28 | + flags << " " << Program.exec("llvm-config-3.3 --ldflags") 29 | end 30 | end 31 | 32 | @@ -250,9 +250,9 @@ module Crystal 33 | system "mv #{bc_name_new} #{bc_name}" 34 | if compiler.release 35 | system "#{compiler.opt} #{bc_name} -O3 -o #{bc_name_opt}" 36 | - system "#{compiler.llc} #{bc_name_opt} -o #{s_name}" 37 | + system "#{compiler.llc} -relocation-model=pic #{bc_name_opt} -o #{s_name}" 38 | else 39 | - system "#{compiler.llc} #{bc_name} -o #{s_name}" 40 | + system "#{compiler.llc} -relocation-model=pic #{bc_name} -o #{s_name}" 41 | end 42 | system "#{compiler.clang} -c #{s_name} -o #{o_name}" 43 | end 44 | diff --git a/bootstrap/crystal/program.cr b/bootstrap/crystal/program.cr 45 | index fca150a8b..a3762944f 100644 46 | --- a/bootstrap/crystal/program.cr 47 | +++ b/bootstrap/crystal/program.cr 48 | @@ -326,7 +326,7 @@ module Crystal 49 | end 50 | 51 | def require_from_load_path(file) 52 | - file = File.expand_path("std/#{file}") 53 | + file = File.expand_path("src/#{file}") 54 | # file = File.expand_path("../../../std/#{file}", __FILE__) 55 | require_absolute file 56 | end 57 | diff --git a/lib/crystal/compiler.rb b/lib/crystal/compiler.rb 58 | index 84bbdd3f3..df731a8a5 100644 59 | --- a/lib/crystal/compiler.rb 60 | +++ b/lib/crystal/compiler.rb 61 | @@ -147,7 +147,7 @@ module Crystal 62 | 63 | llvm_modules = nil 64 | with_stats_or_profile('codegen-llvm') do 65 | - llvm_modules = program.build node, filename: filename, debug: @options[:debug], single_module: @options[:release] 66 | + llvm_modules = program.build node, filename: filename, debug: @options[:debug], single_module: true 67 | end 68 | rescue Crystal::Exception => ex 69 | puts ex.to_s(source) 70 | @@ -195,9 +195,9 @@ module Crystal 71 | FileUtils.mv "#{bc_name}.new", bc_name 72 | if @options[:release] 73 | `#{@opt} #{bc_name} -O3 -o #{bc_name_opt}` 74 | - `#{@llc} #{bc_name_opt} -o #{s_name}` 75 | + `#{@llc} -relocation-model=pic #{bc_name_opt} -o #{s_name}` 76 | else 77 | - `#{@llc} #{bc_name} -o #{s_name}` 78 | + `#{@llc} -relocation-model=pic #{bc_name} -o #{s_name}` 79 | end 80 | `#{@clang} -c #{s_name} -o #{o_name}` 81 | end 82 | @@ -275,7 +275,7 @@ module Crystal 83 | end 84 | end 85 | flags << " -Wl,-allow_stack_execute" if RUBY_PLATFORM =~ /darwin/ 86 | - flags << " -L#{`llvm-config-3.3 --libdir`.strip}" 87 | + flags << " #{`llvm-config-3.3 --ldflags`.strip}" 88 | flags 89 | end 90 | end 91 | -------------------------------------------------------------------------------- /files/stage11.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/compiler/crystal/ast.cr b/src/compiler/crystal/ast.cr 2 | index 2205b37f9..2869725c5 100644 3 | --- a/src/compiler/crystal/ast.cr 4 | +++ b/src/compiler/crystal/ast.cr 5 | @@ -2708,6 +2708,68 @@ module Crystal 6 | end 7 | end 8 | 9 | + class IndirectRead < ASTNode 10 | + @obj :: ASTNode+ 11 | + @names :: Array(String) 12 | + 13 | + def initialize(@obj, @names) 14 | + end 15 | + 16 | + def obj=(@obj) 17 | + end 18 | + 19 | + def obj 20 | + @obj 21 | + end 22 | + 23 | + def names=(@names) 24 | + end 25 | + 26 | + def names 27 | + @names 28 | + end 29 | + 30 | + def accept_children(visitor) 31 | + @obj.accept visitor 32 | + end 33 | + 34 | + def ==(other : self) 35 | + @obj == other.obj && @names == other.names 36 | + end 37 | + 38 | + def clone_without_location 39 | + IndirectRead.new(@obj.clone, @names) 40 | + end 41 | + end 42 | + 43 | + class IndirectWrite < IndirectRead 44 | + @value :: ASTNode+ 45 | + 46 | + def initialize(obj, names, @value) 47 | + super(obj, names) 48 | + end 49 | + 50 | + def value=(@value) 51 | + end 52 | + 53 | + def value 54 | + @value 55 | + end 56 | + 57 | + def accept_children(visitor) 58 | + @obj.accept visitor 59 | + @value.accept visitor 60 | + end 61 | + 62 | + def ==(other : self) 63 | + @obj == other.obj && @names == other.names && @value == other.value 64 | + end 65 | + 66 | + def clone_without_location 67 | + IndirectWrite.new(@obj.clone, @names, @value.clone) 68 | + end 69 | + end 70 | + 71 | # Ficticious node to represent primitives 72 | class Primitive < ASTNode 73 | @name :: Symbol 74 | diff --git a/src/compiler/crystal/codegen.cr b/src/compiler/crystal/codegen.cr 75 | index 5d5c02f8c..846427232 100644 76 | --- a/src/compiler/crystal/codegen.cr 77 | +++ b/src/compiler/crystal/codegen.cr 78 | @@ -120,7 +120,11 @@ module Crystal 79 | def finish 80 | br_block_chain [@alloca_block, @const_block_entry] 81 | br_block_chain [@const_block, @entry_block] 82 | - return_from_fun nil, @main_ret_type unless @main_ret_type && @main_ret_type.no_return? 83 | + val = return_from_fun nil, @main_ret_type unless @main_ret_type && @main_ret_type.no_return? 84 | + if DUMP_LLVM 85 | + @llvm_mod.dump 86 | + end 87 | + val 88 | end 89 | 90 | def visit(node : FunDef) 91 | @@ -494,9 +498,15 @@ module Crystal 92 | end 93 | 94 | def codegen_primitive_struct_new(node, target_def, call_args) 95 | - struct_type = llvm_struct_type(node.type) 96 | - @last = malloc struct_type 97 | - memset @last, int8(0), LLVM.size_of(struct_type) 98 | + type = node.type 99 | + assert_type type, PointerInstanceType 100 | + 101 | + struct_type = type.var.type 102 | + assert_type struct_type, CStructType 103 | + 104 | + llvm_struct_type = llvm_struct_type(struct_type) 105 | + @last = malloc llvm_struct_type 106 | + memset @last, int8(0), LLVM.size_of(llvm_struct_type) 107 | @last 108 | end 109 | 110 | @@ -506,10 +516,13 @@ module Crystal 111 | 112 | name = target_def.name[0 .. -2] 113 | 114 | - ptr = gep call_args[0], 0, type.index_of_var(name) 115 | + index = type.index_of_var(name) 116 | + ptr = gep call_args[0], 0, index 117 | @last = call_args[1] 118 | + 119 | value = @last 120 | - value = @builder.load @last if node.type.c_struct? || node.type.c_union? 121 | + value = @builder.load value if node.type.c_struct? || node.type.c_union? 122 | + 123 | @builder.store value, ptr 124 | call_args[1] 125 | end 126 | @@ -522,11 +535,12 @@ module Crystal 127 | 128 | var = type.vars[name] 129 | index = type.index_of_var(name) 130 | + ptr = gep call_args[0], 0, index 131 | + 132 | if var.type.c_struct? || var.type.c_union? 133 | - gep call_args[0], 0, index 134 | + @last = ptr 135 | else 136 | - struct = @builder.load call_args[0] 137 | - @builder.extract_value struct, index, name 138 | + @last = @builder.load ptr 139 | end 140 | end 141 | 142 | @@ -547,6 +561,8 @@ module Crystal 143 | ptr = gep call_args[0], 0, 0 144 | casted_value = cast_to_pointer ptr, var.type 145 | @last = call_args[1] 146 | + @last = @builder.load @last if node.type.c_struct? || node.type.c_union? 147 | + 148 | @builder.store @last, casted_value 149 | @last 150 | end 151 | @@ -558,11 +574,13 @@ module Crystal 152 | name = target_def.name 153 | 154 | var = type.vars[name] 155 | + 156 | ptr = gep call_args[0], 0, 0 157 | + casted_value = cast_to_pointer ptr, var.type 158 | + 159 | if var.type.c_struct? || var.type.c_union? 160 | - @last = @builder.bit_cast(ptr, LLVM.pointer_type(llvm_struct_type(var.type))) 161 | + @last = casted_value 162 | else 163 | - casted_value = cast_to_pointer ptr, var.type 164 | @last = @builder.load casted_value 165 | end 166 | end 167 | @@ -980,11 +998,6 @@ module Crystal 168 | end 169 | 170 | def codegen_cond_branch(node_cond, then_block, else_block) 171 | - unless node_cond.type? 172 | - puts node_cond 173 | - puts node_cond.location 174 | - end 175 | - 176 | @builder.cond(codegen_cond(node_cond.type), then_block, else_block) 177 | 178 | nil 179 | @@ -1217,7 +1230,7 @@ module Crystal 180 | index = type.index_of_instance_var(target.name) 181 | 182 | ptr = gep llvm_self_ptr, 0, index 183 | - codegen_assign(ptr, target.type, value.type, llvm_value, true) 184 | + codegen_assign(ptr, target.type, value.type, llvm_value) 185 | end 186 | 187 | def codegen_assign_target(target : Global, value, llvm_value) 188 | @@ -1272,9 +1285,9 @@ module Crystal 189 | false 190 | end 191 | 192 | - def codegen_assign(pointer, target_type, value_type, value, instance_var = false) 193 | + def codegen_assign(pointer, target_type, value_type, value, load_struct_and_union = true) 194 | if target_type == value_type 195 | - value = @builder.load value if target_type.union? || (instance_var && (target_type.c_struct? || target_type.c_union?)) 196 | + value = @builder.load value if target_type.union? || (load_struct_and_union && (target_type.c_struct? || target_type.c_union?)) 197 | @builder.store value, pointer 198 | # Hack until we fix it in the type inference 199 | elsif value_type.is_a?(HierarchyType) && value_type.base_type == target_type 200 | @@ -1365,7 +1378,7 @@ module Crystal 201 | if var_type == @mod.void 202 | # Nothing to do 203 | elsif var_type == node.type 204 | - @last = @builder.load(@last) unless var.treated_as_pointer || var_type.union? 205 | + @last = @builder.load(@last) unless var.treated_as_pointer || var_type.union? || var_type.c_struct? || var_type.c_union? 206 | elsif var_type.is_a?(NilableType) 207 | if node.type.nil_type? 208 | @last = null_pointer?(@last) 209 | @@ -1647,6 +1660,10 @@ module Crystal 210 | end 211 | 212 | copy = alloca llvm_type(arg.type), "block_#{arg.name}" 213 | + # if arg.type.c_struct? || arg.type.c_union? 214 | + # @last = @builder.load(@last) 215 | + # end 216 | + 217 | codegen_assign copy, arg.type, exp_type, @last 218 | new_vars[arg.name] = LLVMVar.new(copy, arg.type) 219 | end 220 | @@ -1781,6 +1798,65 @@ module Crystal 221 | false 222 | end 223 | 224 | + def visit(node : IndirectRead) 225 | + ptr = visit_indirect(node) 226 | + ptr = cast_to_pointer ptr, node.type 227 | + 228 | + if node.type.c_struct? || node.type.c_union? 229 | + @last = ptr 230 | + else 231 | + @last = @builder.load ptr 232 | + end 233 | + 234 | + false 235 | + end 236 | + 237 | + def visit(node : IndirectWrite) 238 | + ptr = visit_indirect(node) 239 | + ptr = cast_to_pointer ptr, node.value.type 240 | + 241 | + node.value.accept self 242 | + 243 | + if node.value.type.c_struct? || node.value.type.c_union? 244 | + @last = @builder.load @last 245 | + end 246 | + 247 | + @builder.store @last, ptr 248 | + 249 | + false 250 | + end 251 | + 252 | + def visit_indirect(node) 253 | + indices = [int32(0)] 254 | + 255 | + type = node.obj.type 256 | + assert_type type, PointerInstanceType 257 | + 258 | + element_type = type.var.type 259 | + 260 | + node.names.each do |name| 261 | + case element_type 262 | + when CStructType 263 | + index = element_type.vars.keys.index(name).not_nil! 264 | + var = element_type.vars[name] 265 | + 266 | + indices << int32(index) 267 | + element_type = var.type 268 | + when CUnionType 269 | + var = element_type.vars[name] 270 | + 271 | + indices << int32(0) 272 | + element_type = var.type 273 | + else 274 | + raise "Bug: #{node} had a wrong type (#{element_type})" 275 | + end 276 | + end 277 | + 278 | + node.obj.accept self 279 | + 280 | + @builder.gep @last, indices 281 | + end 282 | + 283 | def visit(node : Call) 284 | if target_macro = node.target_macro 285 | accept(target_macro) 286 | @@ -1842,6 +1918,13 @@ module Crystal 287 | end 288 | else 289 | accept(arg) 290 | + 291 | + if arg.type? 292 | + if !node.target_def.body.is_a?(Primitive) && (arg.type.c_struct? || arg.type.c_union?) 293 | + @last = @builder.load @last 294 | + end 295 | + end 296 | + 297 | call_args << @last 298 | end 299 | end 300 | @@ -2084,40 +2167,15 @@ module Crystal 301 | return 302 | end 303 | 304 | - 305 | func = target_def_fun(target_def, self_type) 306 | 307 | - # Check for struct out arguments: alloca before the call, then copy to the pointer value after the call. 308 | - has_struct_or_union_out_args = target_def.is_a?(External) && node.args.any? { |arg| arg.out? && arg.is_a?(Var) && (arg.type.c_struct? || arg.type.c_union?) } 309 | - if has_struct_or_union_out_args 310 | - old_call_args = call_args.dup 311 | - call_args = call_args.map_with_index do |call_arg, i| 312 | - arg = node.args[i] 313 | - if arg.out? && (arg.type.c_struct? || arg.type.c_union?) 314 | - alloca llvm_struct_type(arg.type) 315 | - else 316 | - call_arg 317 | - end 318 | - end 319 | - end 320 | - 321 | codegen_call_or_invoke(func, call_args, target_def.raises) 322 | 323 | - if has_struct_or_union_out_args 324 | - old_call_args = old_call_args.not_nil! 325 | - call_args.each_with_index do |call_arg, i| 326 | - arg = node.args[i] 327 | - if arg.out? && (arg.type.c_struct? || arg.type.c_union?) 328 | - @builder.store call_arg, old_call_args[i] 329 | - end 330 | - end 331 | - end 332 | - 333 | if target_def.type.no_return? 334 | @builder.unreachable 335 | end 336 | 337 | - if target_def.type.union? 338 | + if target_def.type.union? || target_def.type.c_struct? || target_def.type.c_union? 339 | union = alloca llvm_type(target_def.type) 340 | @builder.store @last, union 341 | @last = union 342 | @@ -2240,7 +2298,7 @@ module Crystal 343 | var_type = target_def_vars ? target_def_vars[arg.name].type : arg.type 344 | pointer = alloca(llvm_type(var_type), arg.name) 345 | @vars[arg.name] = LLVMVar.new(pointer, var_type) 346 | - codegen_assign(pointer, var_type, arg.type, @fun.get_param(i)) 347 | + codegen_assign(pointer, var_type, arg.type, @fun.get_param(i), false) 348 | end 349 | end 350 | 351 | @@ -2305,6 +2363,8 @@ module Crystal 352 | 353 | if return_type == @mod.void 354 | ret 355 | + elsif return_type.c_struct? || return_type.c_union? 356 | + ret(@builder.load(@last)) 357 | else 358 | ret(@last) 359 | end 360 | diff --git a/src/compiler/crystal/codegen/llvm_typer.cr b/src/compiler/crystal/codegen/llvm_typer.cr 361 | index 3a9dae410..f0e18aef8 100644 362 | --- a/src/compiler/crystal/codegen/llvm_typer.cr 363 | +++ b/src/compiler/crystal/codegen/llvm_typer.cr 364 | @@ -75,11 +75,11 @@ module Crystal 365 | end 366 | 367 | def create_llvm_type(type : CStructType) 368 | - LLVM.pointer_type(llvm_struct_type(type)) 369 | + llvm_struct_type(type) 370 | end 371 | 372 | def create_llvm_type(type : CUnionType) 373 | - LLVM.pointer_type(llvm_struct_type(type)) 374 | + llvm_struct_type(type) 375 | end 376 | 377 | def create_llvm_type(type : TypeDefType) 378 | diff --git a/src/compiler/crystal/parser.cr b/src/compiler/crystal/parser.cr 379 | index b4b356395..bee38778c 100644 380 | --- a/src/compiler/crystal/parser.cr 381 | +++ b/src/compiler/crystal/parser.cr 382 | @@ -646,14 +646,19 @@ module Crystal 383 | when :INSTANCE_VAR 384 | name = @token.value.to_s 385 | ivar = InstanceVar.new(name) 386 | - next_token_skip_space 387 | - if @token.type == :"::" 388 | - next_token_skip_space 389 | - ivar_type = parse_single_type 390 | - DeclareVar.new(ivar, ivar_type) 391 | + next_token 392 | + if @token.type == :"->" 393 | + parse_indirect(ivar) 394 | else 395 | - @instance_vars.add name if @instance_vars 396 | - ivar 397 | + skip_space 398 | + if @token.type == :"::" 399 | + next_token_skip_space 400 | + ivar_type = parse_single_type 401 | + DeclareVar.new(ivar, ivar_type) 402 | + else 403 | + @instance_vars.add name if @instance_vars 404 | + ivar 405 | + end 406 | end 407 | when :CLASS_VAR 408 | node_and_next_token ClassVar.new(@token.value.to_s) 409 | @@ -1658,6 +1663,8 @@ module Crystal 410 | end 411 | 412 | def parse_var_or_call(global = false, force_call = false) 413 | + location = @token.location 414 | + 415 | name = @token.value.to_s 416 | name_column_number = @token.column_number 417 | 418 | @@ -1667,6 +1674,12 @@ module Crystal 419 | 420 | next_token 421 | 422 | + if @token.type == :"->" && is_var?(name) 423 | + var = Var.new(name) 424 | + var.location = location 425 | + return parse_indirect(var) 426 | + end 427 | + 428 | @calls_super = true if name == "super" 429 | 430 | call_args = parse_call_args 431 | @@ -1712,6 +1725,34 @@ module Crystal 432 | end 433 | end 434 | 435 | + def parse_indirect(obj) 436 | + next_token 437 | + 438 | + names = [] of String 439 | + 440 | + while true 441 | + check :IDENT 442 | + names << @token.value.to_s 443 | + next_token 444 | + 445 | + if @token.type == :"->" 446 | + next_token 447 | + else 448 | + break 449 | + end 450 | + end 451 | + 452 | + skip_space 453 | + 454 | + if @token.type == :"=" 455 | + next_token_skip_space_or_newline 456 | + value = parse_op_assign 457 | + IndirectWrite.new(obj, names, value) 458 | + else 459 | + IndirectRead.new(obj, names) 460 | + end 461 | + end 462 | + 463 | def parse_block(block) 464 | if @token.keyword?(:do) 465 | raise "block already specified with &" if block 466 | diff --git a/src/compiler/crystal/to_s.cr b/src/compiler/crystal/to_s.cr 467 | index 0cfa5c9af..6668dcc51 100644 468 | --- a/src/compiler/crystal/to_s.cr 469 | +++ b/src/compiler/crystal/to_s.cr 470 | @@ -835,6 +835,26 @@ module Crystal 471 | false 472 | end 473 | 474 | + def visit(node : IndirectRead) 475 | + node.obj.accept self 476 | + node.names.each do |name| 477 | + @str << "->" 478 | + @str << name 479 | + end 480 | + false 481 | + end 482 | + 483 | + def visit(node : IndirectWrite) 484 | + node.obj.accept self 485 | + node.names.each do |name| 486 | + @str << "->" 487 | + @str << name 488 | + end 489 | + @str << " = " 490 | + node.value.accept self 491 | + false 492 | + end 493 | + 494 | def visit(node : PrimitiveBody) 495 | @str << "" 496 | end 497 | diff --git a/src/compiler/crystal/transformer.cr b/src/compiler/crystal/transformer.cr 498 | index bef4b1345..96b08d041 100644 499 | --- a/src/compiler/crystal/transformer.cr 500 | +++ b/src/compiler/crystal/transformer.cr 501 | @@ -428,6 +428,17 @@ module Crystal 502 | node 503 | end 504 | 505 | + def transform(node : IndirectRead) 506 | + node.obj = node.obj.transform(self) 507 | + node 508 | + end 509 | + 510 | + def transform(node : IndirectWrite) 511 | + node.obj = node.obj.transform(self) 512 | + node.value = node.value.transform(self) 513 | + node 514 | + end 515 | + 516 | def transform(node : TypeMerge) 517 | node 518 | end 519 | diff --git a/src/compiler/crystal/type_inference.cr b/src/compiler/crystal/type_inference.cr 520 | index d7af37608..e060d4156 100644 521 | --- a/src/compiler/crystal/type_inference.cr 522 | +++ b/src/compiler/crystal/type_inference.cr 523 | @@ -866,13 +866,13 @@ module Crystal 524 | when :float64_infinity 525 | node.type = @mod.float64 526 | when :struct_new 527 | - node.type = scope.instance_type 528 | + node.type = @mod.pointer_of(scope.instance_type) 529 | when :struct_set 530 | node.bind_to @vars["value"] 531 | when :struct_get 532 | visit_struct_get node 533 | when :union_new 534 | - node.type = scope.instance_type 535 | + node.type = @mod.pointer_of(scope.instance_type) 536 | when :union_set 537 | node.bind_to @vars["value"] 538 | when :union_get 539 | @@ -1085,6 +1085,58 @@ module Crystal 540 | end 541 | end 542 | 543 | + def end_visit(node : IndirectRead) 544 | + var = visit_indirect(node) 545 | + node.bind_to var 546 | + end 547 | + 548 | + def end_visit(node : IndirectWrite) 549 | + var = visit_indirect(node) 550 | + if var.type != node.value.type 551 | + type = node.obj.type 552 | + assert_type type, PointerInstanceType 553 | + 554 | + node.raise "field '#{node.names.join "->"}' of struct #{type.var.type} has type #{var.type}, not #{node.value.type}" 555 | + end 556 | + 557 | + node.bind_to node.value 558 | + end 559 | + 560 | + def visit_indirect(node) 561 | + type = node.obj.type 562 | + if type.is_a?(PointerInstanceType) 563 | + element_type = type.var.type 564 | + var = nil 565 | + node.names.each do |name| 566 | + # TOOD remove duplicate code 567 | + case element_type 568 | + when CStructType 569 | + var = element_type.vars[name]? 570 | + if var 571 | + var_type = var.type 572 | + element_type = var_type 573 | + else 574 | + node.raise "#{element_type.type_desc} #{element_type} has no field '#{name}'" 575 | + end 576 | + when CUnionType 577 | + var = element_type.vars[name]? 578 | + if var 579 | + var_type = var.type 580 | + element_type = var_type 581 | + else 582 | + node.raise "#{element_type.type_desc} #{element_type} has no field '#{name}'" 583 | + end 584 | + else 585 | + node.raise "#{element_type.type_desc} is not a struct or union, it's a #{element_type}" 586 | + end 587 | + end 588 | + 589 | + return var.not_nil! 590 | + end 591 | + 592 | + node.raise "#{type} is not a pointer to a struct or union, it's a #{type.type_desc} #{type}" 593 | + end 594 | + 595 | def lookup_var(name) 596 | @vars[name] ||= Var.new(name) 597 | end 598 | -------------------------------------------------------------------------------- /files/stage16.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/compiler/crystal/macro_expander.cr b/src/compiler/crystal/macro_expander.cr 2 | index a4148aedf..3d0dc31b1 100644 3 | --- a/src/compiler/crystal/macro_expander.cr 4 | +++ b/src/compiler/crystal/macro_expander.cr 5 | @@ -8,44 +8,50 @@ module Crystal 6 | mapped_args = node.args.map do |arg| 7 | if arg.is_a?(Call) && !arg.obj && !arg.block && !arg.block_arg && arg.args.length == 0 8 | Var.new(arg.name) 9 | + elsif arg.is_a?(Ident) && arg.names.length == 1 10 | + Var.new(arg.names.first) 11 | + elsif arg.is_a?(SymbolLiteral) 12 | + Var.new(arg.value) 13 | + elsif arg.is_a?(StringLiteral) 14 | + Var.new(arg.value) 15 | + elsif arg.is_a?(Assign) 16 | + arg.value 17 | else 18 | arg 19 | end 20 | end 21 | 22 | + macro_args = mapped_args.map &.to_crystal_macro_node 23 | + 24 | macro_arg_types = mapped_args.map &.crystal_type_id 25 | info = @untyped_def.lookup_instance(macro_arg_types) 26 | unless info 27 | - typed_def = Def.new(@macro_name, @untyped_def.args.map(&.clone), @untyped_def.body.clone) 28 | - typed_def = @mod.normalize(typed_def) as Def 29 | + args = Array(ASTNode).new(mapped_args.length) 30 | + mapped_args.each do |arg| 31 | + args.push arg.to_crystal_node.not_nil! 32 | + end 33 | 34 | - vars = {} of String => Var 35 | - typed_def.args.zip(mapped_args) do |def_arg, macro_arg| 36 | - arg_type = lookup_node_type(macro_arg) 37 | - def_arg.set_type(arg_type) 38 | + typed_def = Def.new(@macro_name, @untyped_def.args.map(&.clone), @untyped_def.body.clone) 39 | 40 | - var = Var.new(def_arg.name, arg_type) 41 | - var.bind_to(var) 42 | - vars[def_arg.name] = var 43 | - end 44 | + macro_call = Call.new(nil, @macro_name, args) 45 | + macro_nodes = Expressions.new([typed_def, macro_call] of ASTNode) 46 | + macro_nodes = @mod.normalize(macro_nodes) 47 | 48 | - visitor = TypeVisitor.new(@mod, vars) 49 | - typed_def.bind_to typed_def.body 50 | - typed_def.body.accept visitor 51 | + @mod.infer_type macro_nodes 52 | 53 | - if typed_def.type != @mod.string 54 | + if macro_nodes.type != @mod.string 55 | node.raise "macro return value must be a String, not #{typed_def.type}" 56 | end 57 | 58 | llvm_mod = LLVM::Module.new @macro_name 59 | engine = LLVM::JITCompiler.new llvm_mod 60 | 61 | - visitor = CodeGenVisitor.new(@mod, typed_def, llvm_mod, true, true) 62 | - visitor.codegen_fun(@macro_name, typed_def, nil) 63 | + @mod.build macro_nodes, true, llvm_mod 64 | 65 | # llvm_mod.dump 66 | 67 | - func = llvm_mod.functions[@macro_name]? 68 | + func = llvm_mod.functions[macro_call.target_def.mangled_name(nil)]? 69 | + 70 | info = Macro::Info.new(llvm_mod, engine, func) 71 | @untyped_def.add_instance info, macro_arg_types 72 | end 73 | @@ -55,7 +61,7 @@ module Crystal 74 | func = info.func 75 | 76 | if func 77 | - macro_args = mapped_args.map do |arg| 78 | + macro_args = macro_args.map do |arg| 79 | pointer = Pointer(Void).new(arg.object_id) 80 | LibLLVM.create_generic_value_of_pointer(pointer) 81 | end 82 | diff --git a/src/compiler/crystal/to_crystal.cr b/src/compiler/crystal/to_crystal.cr 83 | new file mode 100644 84 | index 000000000..413cc0443 85 | --- /dev/null 86 | +++ b/src/compiler/crystal/to_crystal.cr 87 | @@ -0,0 +1,95 @@ 88 | +require "ast" 89 | + 90 | +module Crystal 91 | + class ASTNode 92 | + def to_crystal_node 93 | + visitor = ToCrystalNodeVisitor.new 94 | + accept visitor 95 | + visitor.value.not_nil! 96 | + end 97 | + 98 | + def to_crystal_macro_node 99 | + visitor = ToCrystalMacroNodeVisitor.new 100 | + accept visitor 101 | + visitor.value.not_nil! 102 | + end 103 | + end 104 | + 105 | + class ToCrystalNodeVisitor < Visitor 106 | + def visit(node : ASTNode) 107 | + true 108 | + end 109 | + 110 | + def visit(node : NumberLiteral) 111 | + new_node "NumberLiteral", [StringLiteral.new(node.value), SymbolLiteral.new(node.kind.to_s)] of ASTNode 112 | + end 113 | + 114 | + def visit(node : SymbolLiteral) 115 | + new_node "SymbolLiteral", StringLiteral.new(node.value) 116 | + end 117 | + 118 | + def visit(node : StringLiteral) 119 | + new_node "StringLiteral", node 120 | + end 121 | + 122 | + def visit(node : Var) 123 | + new_node "Var", StringLiteral.new(node.name) 124 | + end 125 | + 126 | + def visit(node : InstanceVar) 127 | + new_node "InstanceVar", StringLiteral.new(node.name) 128 | + end 129 | + 130 | + # def visit_array_literal(node) 131 | + # args = [] 132 | + # node.elements.each do |elem| 133 | + # elem.accept self 134 | + # args.push @last 135 | + # end 136 | + # new_node 'ArrayLiteral', ArrayLiteral.new(args) 137 | + # false 138 | + # end 139 | + 140 | + def new_node(name, arg) 141 | + new_node name, [arg] of ASTNode 142 | + end 143 | + 144 | + def new_node(name, args : Array) 145 | + @last = Call.new(Ident.new(["Macro", name]), "new", args) 146 | + end 147 | + 148 | + def value 149 | + @last 150 | + end 151 | + end 152 | + 153 | + class ToCrystalMacroNodeVisitor < Visitor 154 | + def visit(node : ASTNode) 155 | + true 156 | + end 157 | + 158 | + # def visit(node : NumberLiteral) 159 | + # new_node "NumberLiteral", [StringLiteral.new(node.value), SymbolLiteral.new(node.kind.to_s)] of ASTNode 160 | + # end 161 | + 162 | + def visit(node : SymbolLiteral) 163 | + @last = Macro::SymbolLiteral.new(node.value) 164 | + end 165 | + 166 | + def visit(node : StringLiteral) 167 | + @last = Macro::StringLiteral.new(node.value) 168 | + end 169 | + 170 | + def visit(node : Var) 171 | + @last = Macro::Var.new(node.name) 172 | + end 173 | + 174 | + def visit(node : InstanceVar) 175 | + @last = Macro::InstanceVar.new(node.name) 176 | + end 177 | + 178 | + def value 179 | + @last 180 | + end 181 | + end 182 | +end 183 | -------------------------------------------------------------------------------- /files/stage17.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/compiler/crystal/codegen.cr b/src/compiler/crystal/codegen.cr 2 | index 5a6815a9c..5dacc574b 100644 3 | --- a/src/compiler/crystal/codegen.cr 4 | +++ b/src/compiler/crystal/codegen.cr 5 | @@ -404,20 +404,14 @@ module Crystal 6 | end 7 | 8 | def codegen_primitive_allocate(node, target_def, call_args) 9 | - node_type = node.type 10 | - if node_type.is_a?(HierarchyType) 11 | - type = node_type.base_type 12 | - else 13 | - type = node_type 14 | - end 15 | + type = node.type 16 | 17 | struct_type = llvm_struct_type(type) 18 | @last = malloc struct_type 19 | memset @last, int8(0), LLVM.size_of(struct_type) 20 | 21 | - if node_type.is_a?(HierarchyType) 22 | - @last = box_object_in_hierarchy(node_type.base_type, node.type, @last, false) 23 | - end 24 | + type_id_ptr = gep @last, 0, 0 25 | + @builder.store int32(type.type_id), type_id_ptr 26 | 27 | @last 28 | end 29 | @@ -685,7 +679,7 @@ module Crystal 30 | when InstanceVar 31 | type = @type as InstanceVarContainer 32 | 33 | - @last = gep llvm_self_ptr, 0, type.index_of_instance_var(node_exp.name) 34 | + @last = gep llvm_self_ptr, 0, (type.index_of_instance_var(node_exp.name) + 1) 35 | when IndirectRead 36 | @last = visit_indirect(node_exp) 37 | else 38 | @@ -895,10 +889,10 @@ module Crystal 39 | name = name.replace '@', '.' 40 | key = StringKey.new(@llvm_mod, str) 41 | @strings[key] ||= begin 42 | - global = @llvm_mod.globals.add(LLVM.struct_type([LLVM::Int32, LLVM.array_type(LLVM::Int8, str.length + 1)]), name) 43 | + global = @llvm_mod.globals.add(LLVM.struct_type([LLVM::Int32, LLVM::Int32, LLVM.array_type(LLVM::Int8, str.length + 1)]), name) 44 | LLVM.set_linkage global, LibLLVM::Linkage::Private 45 | LLVM.set_global_constant global, true 46 | - LLVM.set_initializer global, LLVM.struct([int32(str.length), LLVM.string(str)]) 47 | + LLVM.set_initializer global, LLVM.struct([int32(@mod.string.type_id), int32(str.length), LLVM.string(str)]) 48 | cast_to global, @mod.string 49 | end 50 | end 51 | @@ -1205,7 +1199,7 @@ module Crystal 52 | type = @type as InstanceVarContainer 53 | 54 | ivar = type.lookup_instance_var(target.name) 55 | - index = type.index_of_instance_var(target.name) 56 | + index = type.index_of_instance_var(target.name) + 1 57 | 58 | ptr = gep llvm_self_ptr, 0, index 59 | codegen_assign(ptr, target.type, value.type, llvm_value) 60 | @@ -1449,7 +1443,11 @@ module Crystal 61 | 62 | ivar = type.lookup_instance_var(node.name) 63 | if ivar.type.union? || ivar.type.c_struct? || ivar.type.c_union? 64 | - @last = gep llvm_self_ptr, 0, type.index_of_instance_var(node.name) 65 | + if ivar.type.union? 66 | + @last = gep llvm_self_ptr, 0, type.index_of_instance_var(node.name) + 1 67 | + else 68 | + @last = gep llvm_self_ptr, 0, type.index_of_instance_var(node.name) 69 | + end 70 | unless node.type == ivar.type 71 | if node.type.union? 72 | @last = cast_to_pointer @last, node.type 73 | @@ -1460,7 +1458,7 @@ module Crystal 74 | end 75 | end 76 | else 77 | - index = type.index_of_instance_var(node.name) 78 | + index = type.index_of_instance_var(node.name) + 1 79 | 80 | struct = @builder.load llvm_self_ptr 81 | @last = @builder.extract_value struct, index, node.name 82 | @@ -1938,7 +1936,7 @@ module Crystal 83 | call_args << @vars[arg.name].pointer 84 | when InstanceVar 85 | type = @type as InstanceVarContainer 86 | - call_args << (gep llvm_self_ptr, 0, type.index_of_instance_var(arg.name)) 87 | + call_args << (gep llvm_self_ptr, 0, (type.index_of_instance_var(arg.name) + 1)) 88 | else 89 | raise "Bug: out argument was #{arg}" 90 | end 91 | diff --git a/src/compiler/crystal/codegen/llvm_typer.cr b/src/compiler/crystal/codegen/llvm_typer.cr 92 | index 74ad50c7f..64a6d2b16 100644 93 | --- a/src/compiler/crystal/codegen/llvm_typer.cr 94 | +++ b/src/compiler/crystal/codegen/llvm_typer.cr 95 | @@ -116,7 +116,8 @@ module Crystal 96 | @struct_cache[type] = struct 97 | 98 | ivars = type.all_instance_vars 99 | - element_types = Array(LibLLVM::TypeRef).new(ivars.length) 100 | + element_types = Array(LibLLVM::TypeRef).new(ivars.length + 1) 101 | + element_types.push LLVM::Int32 # For the type id 102 | ivars.each { |name, ivar| element_types.push llvm_embedded_type(ivar.type) } 103 | element_types 104 | end 105 | diff --git a/src/compiler/crystal/macro_expander.cr b/src/compiler/crystal/macro_expander.cr 106 | index 78d27a6f1..48e205cb5 100644 107 | --- a/src/compiler/crystal/macro_expander.cr 108 | +++ b/src/compiler/crystal/macro_expander.cr 109 | @@ -7,6 +7,26 @@ module Crystal 110 | end 111 | 112 | def expand(node) 113 | + body = @untyped_def.body 114 | + 115 | + # A simple case: when the macro is just a string interpolation with variables, 116 | + # we do it without a JIT 117 | + if body.is_a?(StringInterpolation) 118 | + if body.expressions.all? { |exp| exp.is_a?(StringLiteral) || exp.is_a?(Var) } 119 | + return String.build do |str| 120 | + body.expressions.each do |exp| 121 | + case exp 122 | + when StringLiteral 123 | + str << exp.value 124 | + when Var 125 | + index = @untyped_def.args.index { |arg| arg.name == exp.name }.not_nil! 126 | + str << node.args[index].to_s 127 | + end 128 | + end 129 | + end 130 | + end 131 | + end 132 | + 133 | mapped_args = node.args.map do |arg| 134 | if arg.is_a?(Call) && !arg.obj && !arg.block && !arg.block_arg && arg.args.length == 0 135 | Var.new(arg.name) 136 | diff --git a/src/compiler/crystal/normalizer.cr b/src/compiler/crystal/normalizer.cr 137 | index 5d5d785e2..61214c0c1 100644 138 | --- a/src/compiler/crystal/normalizer.cr 139 | +++ b/src/compiler/crystal/normalizer.cr 140 | @@ -597,17 +597,6 @@ module Crystal 141 | end 142 | 143 | def transform(node : Macro) 144 | - # if node.has_default_arguments? 145 | - # exps = node.expand_default_arguments.map! { |a_def| a_def.transform(self) } 146 | - # return Expressions.new(exps) 147 | - # end 148 | - 149 | - if node.body 150 | - pushing_vars_from_args(node.args) do 151 | - node.body = node.body.transform(self) 152 | - end 153 | - end 154 | - 155 | node 156 | end 157 | 158 | -------------------------------------------------------------------------------- /files/stage18.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/compiler/crystal/ast.cr b/src/compiler/crystal/ast.cr 2 | index 779e56dce..ee1c1e7a7 100644 3 | --- a/src/compiler/crystal/ast.cr 4 | +++ b/src/compiler/crystal/ast.cr 5 | @@ -319,7 +319,7 @@ module Crystal 6 | end 7 | end 8 | 9 | - class RegexpLiteral < ASTNode 10 | + class RegexLiteral < ASTNode 11 | property :value 12 | property :modifiers 13 | 14 | @@ -331,7 +331,7 @@ module Crystal 15 | end 16 | 17 | def clone_without_location 18 | - RegexpLiteral.new(@value, @modifiers) 19 | + RegexLiteral.new(@value, @modifiers) 20 | end 21 | end 22 | 23 | diff --git a/src/compiler/crystal/lexer.cr b/src/compiler/crystal/lexer.cr 24 | index bed394f3c..d6cc6027b 100644 25 | --- a/src/compiler/crystal/lexer.cr 26 | +++ b/src/compiler/crystal/lexer.cr 27 | @@ -231,14 +231,14 @@ module Crystal 28 | next_char 29 | else 30 | if 'a' <= @buffer.value.downcase <= 'z' 31 | - raise "unknown regexp option: #{@buffer.value}" 32 | + raise "unknown regex option: #{@buffer.value}" 33 | end 34 | break 35 | end 36 | end 37 | 38 | - @token.type = :REGEXP 39 | - @token.regexp_modifiers = modifiers 40 | + @token.type = :REGEX 41 | + @token.regex_modifiers = modifiers 42 | @token.value = string_buffer.to_s 43 | end 44 | when '%' 45 | diff --git a/src/compiler/crystal/normalizer.cr b/src/compiler/crystal/normalizer.cr 46 | index c18efcc3f..55369c3c0 100644 47 | --- a/src/compiler/crystal/normalizer.cr 48 | +++ b/src/compiler/crystal/normalizer.cr 49 | @@ -131,10 +131,10 @@ module Crystal 50 | new_node.transform(self) 51 | end 52 | 53 | - def transform(node : RegexpLiteral) 54 | - const_name = "#Regexp_#{node.value}_#{node.modifiers}" 55 | + def transform(node : RegexLiteral) 56 | + const_name = "#Regex_#{node.value}_#{node.modifiers}" 57 | unless program.types[const_name]? 58 | - constructor = Call.new(Ident.new(["Regexp"], true), "new", [StringLiteral.new(node.value), NumberLiteral.new(node.modifiers, :i32)] of ASTNode) 59 | + constructor = Call.new(Ident.new(["Regex"], true), "new", [StringLiteral.new(node.value), NumberLiteral.new(node.modifiers, :i32)] of ASTNode) 60 | program.types[const_name] = Const.new program, program, const_name, constructor, [program] of Type, program 61 | end 62 | 63 | diff --git a/src/compiler/crystal/parser.cr b/src/compiler/crystal/parser.cr 64 | index 86ebee06c..9d38a1eea 100644 65 | --- a/src/compiler/crystal/parser.cr 66 | +++ b/src/compiler/crystal/parser.cr 67 | @@ -614,8 +614,8 @@ module Crystal 68 | parse_string_array 69 | when :SYMBOL 70 | node_and_next_token SymbolLiteral.new(@token.value.to_s) 71 | - when :REGEXP 72 | - node_and_next_token RegexpLiteral.new(@token.value.to_s, @token.regexp_modifiers) 73 | + when :REGEX 74 | + node_and_next_token RegexLiteral.new(@token.value.to_s, @token.regex_modifiers) 75 | when :GLOBAL 76 | node_and_next_token Global.new(@token.value.to_s) 77 | when :GLOBAL_MATCH 78 | @@ -1923,7 +1923,7 @@ module Crystal 79 | end 80 | when :"{" 81 | return nil unless allow_curly 82 | - when :CHAR, :STRING, :STRING_START, :STRING_ARRAY_START, :NUMBER, :IDENT, :SYMBOL, :INSTANCE_VAR, :CLASS_VAR, :CONST, :GLOBAL, :GLOBAL_MATCH, :REGEXP, :"(", :"!", :"[", :"[]", :"+", :"-", :"&", :"->" 83 | + when :CHAR, :STRING, :STRING_START, :STRING_ARRAY_START, :NUMBER, :IDENT, :SYMBOL, :INSTANCE_VAR, :CLASS_VAR, :CONST, :GLOBAL, :GLOBAL_MATCH, :REGEX, :"(", :"!", :"[", :"[]", :"+", :"-", :"&", :"->" 84 | # Nothing 85 | else 86 | return nil 87 | diff --git a/src/compiler/crystal/to_s.cr b/src/compiler/crystal/to_s.cr 88 | index b718d0f0b..f0bf22d3c 100644 89 | --- a/src/compiler/crystal/to_s.cr 90 | +++ b/src/compiler/crystal/to_s.cr 91 | @@ -559,7 +559,7 @@ module Crystal 92 | false 93 | end 94 | 95 | - def visit(node : RegexpLiteral) 96 | + def visit(node : RegexLiteral) 97 | @str << "/" 98 | @str << node.value 99 | @str << "/" 100 | diff --git a/src/compiler/crystal/token.cr b/src/compiler/crystal/token.cr 101 | index 1adfbe8a7..adbd5317f 100644 102 | --- a/src/compiler/crystal/token.cr 103 | +++ b/src/compiler/crystal/token.cr 104 | @@ -11,7 +11,7 @@ module Crystal 105 | property :line_number 106 | property :column_number 107 | property :filename 108 | - property :regexp_modifiers 109 | + property :regex_modifiers 110 | 111 | def initialize 112 | @type = :EOF 113 | @@ -21,7 +21,7 @@ module Crystal 114 | @string_open_count = 0 115 | @line_number = 0 116 | @column_number = 0 117 | - @regexp_modifiers = 0 118 | + @regex_modifiers = 0 119 | end 120 | 121 | def location 122 | diff --git a/src/compiler/crystal/transformer.cr b/src/compiler/crystal/transformer.cr 123 | index 6dff23d20..bd0d38a26 100644 124 | --- a/src/compiler/crystal/transformer.cr 125 | +++ b/src/compiler/crystal/transformer.cr 126 | @@ -368,7 +368,7 @@ module Crystal 127 | node 128 | end 129 | 130 | - def transform(node : RegexpLiteral) 131 | + def transform(node : RegexLiteral) 132 | node 133 | end 134 | 135 | diff --git a/src/compiler/crystal/type_inference.cr b/src/compiler/crystal/type_inference.cr 136 | index 9277ad1d9..b2bd543d4 100644 137 | --- a/src/compiler/crystal/type_inference.cr 138 | +++ b/src/compiler/crystal/type_inference.cr 139 | @@ -1174,8 +1174,8 @@ module Crystal 140 | raise "Bug: When node '#{node}' (#{node.location}) should have been eliminated in normalize" 141 | end 142 | 143 | - def visit(node : RegexpLiteral) 144 | - raise "Bug: RegexpLiteral node '#{node}' (#{node.location}) should have been eliminated in normalize" 145 | + def visit(node : RegexLiteral) 146 | + raise "Bug: RegexLiteral node '#{node}' (#{node.location}) should have been eliminated in normalize" 147 | end 148 | 149 | def visit(node : ArrayLiteral) 150 | -------------------------------------------------------------------------------- /files/stage19.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/compiler/crystal/codegen.cr b/src/compiler/crystal/codegen.cr 2 | index 06e66e133..a83c30a9d 100644 3 | --- a/src/compiler/crystal/codegen.cr 4 | +++ b/src/compiler/crystal/codegen.cr 5 | @@ -388,7 +388,7 @@ module Crystal 6 | end 7 | 8 | def codegen_cast(from_type : IntegerType, to_type : CharType, arg) 9 | - codegen_cast(from_type, @mod.int8, arg) 10 | + codegen_cast(from_type, @mod.int32, arg) 11 | end 12 | 13 | def codegen_cast(from_type : CharType, to_type : IntegerType, arg) 14 | @@ -684,7 +684,7 @@ module Crystal 15 | end 16 | 17 | def visit(node : CharLiteral) 18 | - @last = int8(node.value[0].ord) 19 | + @last = int32(node.value[0].ord) 20 | end 21 | 22 | def visit(node : StringLiteral) 23 | diff --git a/src/compiler/crystal/program.cr b/src/compiler/crystal/program.cr 24 | index 078fafdcb..ca2066837 100644 25 | --- a/src/compiler/crystal/program.cr 26 | +++ b/src/compiler/crystal/program.cr 27 | @@ -36,7 +36,7 @@ module Crystal 28 | @types["Void"] = @void = VoidType.new self, self, "Void", @value, LLVM::Void, 1 29 | @types["Nil"] = @nil = NilType.new self, self, "Nil", @value, LLVM::Int1, 1 30 | @types["Bool"] = @bool = BoolType.new self, self, "Bool", @value, LLVM::Int1, 1 31 | - @types["Char"] = @char = CharType.new self, self, "Char", @value, LLVM::Int8, 1 32 | + @types["Char"] = @char = CharType.new self, self, "Char", @value, LLVM::Int32, 4 33 | 34 | @types["Int"] = @int = ValueType.new self, self, "Int", @number 35 | @int.abstract = true 36 | @@ -68,7 +68,7 @@ module Crystal 37 | @string.type_id = 1 38 | 39 | @string.lookup_instance_var("@length").set_type(@int32) 40 | - @string.lookup_instance_var("@c").set_type(@char) 41 | + @string.lookup_instance_var("@c").set_type(@uint8) 42 | 43 | @types["Class"] = @class = Metaclass.new(self, @object, @reference, "Class") 44 | @object.force_metaclass @class 45 | @@ -340,8 +340,8 @@ module Crystal 46 | 47 | getter :nil_var 48 | 49 | - def char_pointer 50 | - pointer_of char 51 | + def uint8_pointer 52 | + pointer_of uint8 53 | end 54 | 55 | def pointer_of(type) 56 | diff --git a/src/compiler/crystal/type_inference.cr b/src/compiler/crystal/type_inference.cr 57 | index eaa76ca70..6362cd384 100644 58 | --- a/src/compiler/crystal/type_inference.cr 59 | +++ b/src/compiler/crystal/type_inference.cr 60 | @@ -805,7 +805,7 @@ module Crystal 61 | when :argc 62 | node.type = @mod.int32 63 | when :argv 64 | - node.type = @mod.pointer_of(@mod.pointer_of(@mod.char)) 65 | + node.type = @mod.pointer_of(@mod.pointer_of(@mod.uint8)) 66 | when :float32_infinity 67 | node.type = @mod.float32 68 | when :float64_infinity 69 | @@ -829,7 +829,7 @@ module Crystal 70 | when :object_id 71 | node.type = mod.uint64 72 | when :object_to_cstr 73 | - node.type = mod.char_pointer 74 | + node.type = mod.uint8_pointer 75 | when :object_crystal_type_id 76 | node.type = mod.int32 77 | when :math_sqrt_float32 78 | diff --git a/src/compiler/crystal/type_inference/call.cr b/src/compiler/crystal/type_inference/call.cr 79 | index f5de1b691..0044f556d 100644 80 | --- a/src/compiler/crystal/type_inference/call.cr 81 | +++ b/src/compiler/crystal/type_inference/call.cr 82 | @@ -393,7 +393,7 @@ module Crystal 83 | if actual_type.nil_type? && expected_type.pointer? 84 | nil_conversions ||= [] of Int32 85 | nil_conversions << i 86 | - elsif (actual_type == mod.string || actual_type == mod.string.hierarchy_type) && (expected_type.is_a?(PointerInstanceType) && expected_type.var.type == mod.char) 87 | + elsif (actual_type == mod.string || actual_type == mod.string.hierarchy_type) && (expected_type.is_a?(PointerInstanceType) && expected_type.var.type == mod.uint8) 88 | string_conversions ||= [] of Int32 89 | string_conversions << i 90 | elsif expected_type.is_a?(FunType) && actual_type.is_a?(FunType) && expected_type.return_type == mod.void && expected_type.arg_types == actual_type.arg_types 91 | -------------------------------------------------------------------------------- /files/stage25.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/compiler/crystal/lexer.cr b/src/compiler/crystal/lexer.cr 2 | index a4de2cfd7..f4f62247e 100644 3 | --- a/src/compiler/crystal/lexer.cr 4 | +++ b/src/compiler/crystal/lexer.cr 5 | @@ -88,12 +88,6 @@ module Crystal 6 | case next_char 7 | when '=' 8 | next_char :"!=" 9 | - when '@' 10 | - if peek_next_char.ident_start? 11 | - @token.type = :"!" 12 | - else 13 | - next_char :"!@" 14 | - end 15 | else 16 | @token.type = :"!" 17 | end 18 | @@ -175,12 +169,6 @@ module Crystal 19 | case next_char 20 | when '=' 21 | next_char :"+=" 22 | - when '@' 23 | - if peek_next_char.ident_start? 24 | - @token.type = :"+" 25 | - else 26 | - next_char :"+@" 27 | - end 28 | when '0' 29 | case peek_next_char 30 | when 'x' 31 | @@ -202,12 +190,6 @@ module Crystal 32 | case next_char 33 | when '=' 34 | next_char :"-=" 35 | - when '@' 36 | - if peek_next_char.ident_start? 37 | - @token.type = :"-" 38 | - else 39 | - next_char :"-@" 40 | - end 41 | when '>' 42 | next_char :"->" 43 | when '0' 44 | @@ -376,12 +358,7 @@ module Crystal 45 | @token.type = :":" 46 | end 47 | when '~' 48 | - case next_char 49 | - when '@' 50 | - next_char :"~@" 51 | - else 52 | - @token.type = :"~" 53 | - end 54 | + next_char :"~" 55 | when '.' 56 | case next_char 57 | when '.' 58 | diff --git a/src/compiler/crystal/parser.cr b/src/compiler/crystal/parser.cr 59 | index 0754d82bc..de3c91694 100644 60 | --- a/src/compiler/crystal/parser.cr 61 | +++ b/src/compiler/crystal/parser.cr 62 | @@ -385,16 +385,16 @@ module Crystal 63 | case @token.type 64 | when :"!" 65 | next_token_skip_space_or_newline 66 | - Call.new parse_prefix, "!@", [] of ASTNode, nil, nil, false, column_number 67 | + Call.new parse_prefix, "!", [] of ASTNode, nil, nil, false, column_number 68 | when :"+" 69 | next_token_skip_space_or_newline 70 | - Call.new parse_prefix, "+@", [] of ASTNode, nil, nil, false, column_number 71 | + Call.new parse_prefix, "+", [] of ASTNode, nil, nil, false, column_number 72 | when :"-" 73 | next_token_skip_space_or_newline 74 | - Call.new parse_prefix, "-@", [] of ASTNode, nil, nil, false, column_number 75 | + Call.new parse_prefix, "-", [] of ASTNode, nil, nil, false, column_number 76 | when :"~" 77 | next_token_skip_space_or_newline 78 | - Call.new parse_prefix, "~@", [] of ASTNode, nil, nil, false, column_number 79 | + Call.new parse_prefix, "~", [] of ASTNode, nil, nil, false, column_number 80 | else 81 | parse_pow 82 | end 83 | @@ -703,19 +703,6 @@ module Crystal 84 | end 85 | when :CLASS_VAR 86 | node_and_next_token ClassVar.new(@token.value.to_s) 87 | - when :"-@" 88 | - next_token 89 | - case @token.type 90 | - when :IDENT 91 | - ivar_name = "@#{@token.value}" 92 | - @instance_vars.add ivar_name if @instance_vars 93 | - node_and_next_token Call.new(InstanceVar.new(ivar_name), "-@") 94 | - when :INSTANCE_VAR 95 | - class_var_name = "@#{@token.value}" 96 | - node_and_next_token Call.new(ClassVar.new(class_var_name), "-@") 97 | - else 98 | - unexpected_token "-@" 99 | - end 100 | else 101 | unexpected_token 102 | end 103 | @@ -1361,8 +1348,8 @@ module Crystal 104 | parse_def_or_macro Crystal::Macro 105 | end 106 | 107 | - DefOrMacroCheck1 = [:IDENT, :CONST, :"=", :"<<", :"<", :"<=", :"==", :"===", :"!=", :"=~", :">>", :">", :">=", :"+", :"-", :"*", :"/", :"%", :"+@", :"-@", :"~@", :"!@", :"&", :"|", :"^", :"**", :"[]", :"[]=", :"<=>", :"[]?"] 108 | - DefOrMacroCheck2 = [:IDENT, :"=", :"<<", :"<", :"<=", :"==", :"===", :"!=", :"=~", :">>", :">", :">=", :"+", :"-", :"*", :"/", :"%", :"+@", :"-@", :"~@", :"!@", :"&", :"|", :"^", :"**", :"[]", :"[]=", :"<=>"] 109 | + DefOrMacroCheck1 = [:IDENT, :CONST, :"=", :"<<", :"<", :"<=", :"==", :"===", :"!=", :"=~", :">>", :">", :">=", :"+", :"-", :"*", :"/", :"!", :"~", :"%", :"&", :"|", :"^", :"**", :"[]", :"[]=", :"<=>", :"[]?"] 110 | + DefOrMacroCheck2 = [:IDENT, :"=", :"<<", :"<", :"<=", :"==", :"===", :"!=", :"=~", :">>", :">", :">=", :"+", :"-", :"*", :"/", :"!", :"~", :"%", :"&", :"|", :"^", :"**", :"[]", :"[]=", :"<=>"] 111 | 112 | def parse_def_or_macro(klass) 113 | push_def 114 | -------------------------------------------------------------------------------- /files/stage26.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/compiler/crystal/codegen.cr b/src/compiler/crystal/codegen.cr 2 | index 4d0c896e0..0b7630efd 100644 3 | --- a/src/compiler/crystal/codegen.cr 4 | +++ b/src/compiler/crystal/codegen.cr 5 | @@ -2216,7 +2216,7 @@ module Crystal 6 | elsif return_type.no_return? 7 | unreachable 8 | elsif return_type.represented_as_union? 9 | - if target_def && target_def.body.type? != return_type && !target_def.body.returns? 10 | + if target_def && target_def.body.type? != return_type && !target_def.body.returns? && !target_def.body.type.no_return? 11 | @last = assign_to_return_union(return_type, target_def.body.type, @last) 12 | else 13 | @last = load @last 14 | -------------------------------------------------------------------------------- /files/stage27.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/compiler/crystal/codegen.cr b/src/compiler/crystal/codegen.cr 2 | index ef903f871..91f2ce277 100644 3 | --- a/src/compiler/crystal/codegen.cr 4 | +++ b/src/compiler/crystal/codegen.cr 5 | @@ -2132,6 +2132,11 @@ module Crystal 6 | end 7 | 8 | def codegen_return(exp_type, fun_type) 9 | + if exp_type && exp_type.no_return? 10 | + unreachable 11 | + return 12 | + end 13 | + 14 | case fun_type 15 | when VoidType 16 | yield nil 17 | -------------------------------------------------------------------------------- /files/stage3.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/compiler/crystal/program.cr b/src/compiler/crystal/program.cr 2 | index e6f9dedbb..278dfafcf 100644 3 | --- a/src/compiler/crystal/program.cr 4 | +++ b/src/compiler/crystal/program.cr 5 | @@ -81,10 +81,10 @@ module Crystal 6 | 7 | @types["Macro"] = macro_mod = NonGenericModuleType.new self, self, "Macro" 8 | macro_var = macro_mod.types["Var"] = NonGenericClassType.new self, macro_mod, "Var", @reference 9 | - macro_var.lookup_instance_var("@padding").type = PaddingType.new(self, 24) 10 | + macro_var.lookup_instance_var("@padding").type = PaddingType.new(self, 17) 11 | 12 | macro_ivar = macro_mod.types["InstanceVar"] = NonGenericClassType.new self, macro_mod, "InstanceVar", @reference 13 | - macro_ivar.lookup_instance_var("@padding").type = PaddingType.new(self, 24) 14 | + macro_ivar.lookup_instance_var("@padding").type = PaddingType.new(self, 17) 15 | 16 | @symbols = Set(String).new 17 | @global_vars = {} of String => Var 18 | -------------------------------------------------------------------------------- /files/stage35.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/compiler/crystal/codegen.cr b/src/compiler/crystal/codegen.cr 2 | index ff27406a1..79640d989 100644 3 | --- a/src/compiler/crystal/codegen.cr 4 | +++ b/src/compiler/crystal/codegen.cr 5 | @@ -527,7 +527,7 @@ module Crystal 6 | end 7 | 8 | def codegen_primitive_struct_new(node, target_def, call_args) 9 | - allocate_aggregate (node.type as PointerInstanceType).element_type 10 | + allocate_aggregate node.type 11 | end 12 | 13 | def codegen_primitive_struct_set(node, target_def, call_args) 14 | @@ -549,7 +549,7 @@ module Crystal 15 | end 16 | 17 | def codegen_primitive_union_new(node, target_def, call_args) 18 | - allocate_aggregate (node.type as PointerInstanceType).element_type 19 | + allocate_aggregate node.type 20 | end 21 | 22 | def codegen_primitive_union_set(node, target_def, call_args) 23 | @@ -2658,7 +2658,7 @@ module Crystal 24 | 25 | def allocate_aggregate(type) 26 | struct_type = llvm_struct_type(type) 27 | - if type.struct? 28 | + if type.passed_by_value? 29 | @last = alloca struct_type 30 | else 31 | @last = malloc struct_type 32 | diff --git a/src/compiler/crystal/codegen/llvm_typer.cr b/src/compiler/crystal/codegen/llvm_typer.cr 33 | index 3df35b405..b87c61274 100644 34 | --- a/src/compiler/crystal/codegen/llvm_typer.cr 35 | +++ b/src/compiler/crystal/codegen/llvm_typer.cr 36 | @@ -215,7 +215,7 @@ module Crystal 37 | 38 | def create_llvm_struct_type(type : CUnionType) 39 | max_size = 0 40 | - max_type :: LibLLVM::TypeRef 41 | + max_type = nil 42 | type.vars.each do |name, var| 43 | var_type = var.type 44 | unless var_type.void? 45 | @@ -228,7 +228,7 @@ module Crystal 46 | end 47 | end 48 | 49 | - LLVM.struct_type([max_type] of LibLLVM::TypeRef, type.llvm_name) 50 | + LLVM.struct_type([max_type.not_nil!] of LibLLVM::TypeRef, type.llvm_name) 51 | end 52 | 53 | def create_llvm_struct_type(type : Type) 54 | diff --git a/src/compiler/crystal/type_inference.cr b/src/compiler/crystal/type_inference.cr 55 | index f41a4a469..614ddf60c 100644 56 | --- a/src/compiler/crystal/type_inference.cr 57 | +++ b/src/compiler/crystal/type_inference.cr 58 | @@ -1159,13 +1159,13 @@ module Crystal 59 | when :float64_infinity 60 | node.type = @mod.float64 61 | when :struct_new 62 | - node.type = @mod.pointer_of(scope.instance_type) 63 | + node.type = scope.instance_type 64 | when :struct_set 65 | node.bind_to @vars["value"] 66 | when :struct_get 67 | visit_struct_get node 68 | when :union_new 69 | - node.type = @mod.pointer_of(scope.instance_type) 70 | + node.type = scope.instance_type 71 | when :union_set 72 | node.bind_to @vars["value"] 73 | when :union_get 74 | -------------------------------------------------------------------------------- /files/stage46.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/compiler/crystal/lexer.cr b/src/compiler/crystal/lexer.cr 2 | index bc14fd77c..e9881411f 100644 3 | --- a/src/compiler/crystal/lexer.cr 4 | +++ b/src/compiler/crystal/lexer.cr 5 | @@ -292,6 +292,8 @@ module Crystal 6 | else 7 | @token.type = :"%" 8 | end 9 | + when '}' 10 | + next_char :"%}" 11 | else 12 | @token.type = :"%" 13 | end 14 | diff --git a/src/compiler/crystal/parser.cr b/src/compiler/crystal/parser.cr 15 | index d51c18333..76db5adf6 100644 16 | --- a/src/compiler/crystal/parser.cr 17 | +++ b/src/compiler/crystal/parser.cr 18 | @@ -695,7 +695,7 @@ module Crystal 19 | when :"{%" 20 | macro_control = parse_macro_control(@line_number, @column_number) 21 | if macro_control 22 | - check :"}" 23 | + check :"%}" 24 | next_token_skip_space_or_newline 25 | macro_control 26 | else 27 | @@ -1750,13 +1750,13 @@ module Crystal 28 | 29 | exp = parse_expression_inside_macro 30 | 31 | - check :"}" 32 | + check :"%}" 33 | 34 | body = parse_macro_body(start_line, start_column, macro_state) 35 | 36 | check_ident :end 37 | next_token_skip_space 38 | - check :"}" 39 | + check :"%}" 40 | 41 | return MacroFor.new(vars, exp, body) 42 | when :if 43 | @@ -1774,7 +1774,7 @@ module Crystal 44 | 45 | cond = parse_expression_inside_macro 46 | 47 | - check :"}" 48 | + check :"%}" 49 | 50 | a_then = parse_macro_body(start_line, start_column, macro_state) 51 | 52 | @@ -1782,25 +1782,25 @@ module Crystal 53 | case @token.value 54 | when :else 55 | next_token_skip_space 56 | - check :"}" 57 | + check :"%}" 58 | 59 | a_else = parse_macro_body(start_line, start_column, macro_state) 60 | 61 | check_ident :end 62 | next_token_skip_space 63 | - check :"}" 64 | + check :"%}" 65 | when :elsif 66 | a_else = parse_macro_if(start_line, start_column, macro_state, false) 67 | 68 | if check_end 69 | check_ident :end 70 | next_token_skip_space 71 | - check :"}" 72 | + check :"%}" 73 | end 74 | when :end 75 | if check_end 76 | next_token_skip_space 77 | - check :"}" 78 | + check :"%}" 79 | end 80 | else 81 | unexpected_token 82 | -------------------------------------------------------------------------------- /files/stage47.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/compiler/crystal/codegen.cr b/src/compiler/crystal/codegen.cr 2 | index e24e78e24..d6cb8f7f5 100644 3 | --- a/src/compiler/crystal/codegen.cr 4 | +++ b/src/compiler/crystal/codegen.cr 5 | @@ -232,12 +232,8 @@ module Crystal 6 | LLVM.float(Float32::INFINITY) 7 | when :float64_infinity 8 | LLVM.double(Float64::INFINITY) 9 | - when :struct_hash 10 | - codegen_primitive_struct_hash 11 | when :struct_equals 12 | codegen_primitive_struct_equals 13 | - when :struct_to_s 14 | - codegen_primitive_struct_to_s 15 | else 16 | raise "Bug: unhandled primitive in codegen visit: #{node.name}" 17 | end 18 | @@ -708,49 +704,6 @@ module Crystal 19 | end 20 | end 21 | 22 | - def codegen_primitive_struct_hash 23 | - type = context.type as InstanceVarContainer 24 | - ivars = type.all_instance_vars 25 | - 26 | - # Generate: 27 | - # hash = 0 28 | - # - for each instance var 29 | - # hash = 31 * hash + @ivar.hash 30 | - # - end 31 | - # hash 32 | - 33 | - hash_var = Var.new("hash") 34 | - n0 = NumberLiteral.new(0, :i32) 35 | - n31 = NumberLiteral.new(31, :i32) 36 | - 37 | - vars = MetaVars.new 38 | - vars["hash"] = MetaVar.new(hash_var.name) 39 | - 40 | - exps = [] of ASTNode 41 | - exps << Assign.new(hash_var, n0) 42 | - i = 0 43 | - ivars.each_value do |ivar| 44 | - ivar_name = "#ivar#{i}" 45 | - ivar_var = Var.new(ivar_name, ivar.type) 46 | - 47 | - context.vars[ivar_name] = LLVMVar.new(aggregate_index(llvm_self, i), ivar.type) 48 | - vars[ivar_name] = MetaVar.new(ivar_var.name) 49 | - 50 | - mul = Call.new(n31, "*", [hash_var] of ASTNode) 51 | - ivar_hash = Call.new(ivar_var, "hash") 52 | - add = Call.new(mul, "+", [ivar_hash] of ASTNode) 53 | - exps << Assign.new(hash_var, add) 54 | - i += 1 55 | - end 56 | - exps << hash_var 57 | - exps = Expressions.new(exps) 58 | - visitor = TypeVisitor.new(@mod, vars, Def.new("dummy", [] of Arg)) 59 | - exps.accept visitor 60 | - alloca_vars visitor.meta_vars 61 | - exps.accept self 62 | - @last 63 | - end 64 | - 65 | def codegen_primitive_struct_equals 66 | type = context.type as InstanceVarContainer 67 | ivars = type.all_instance_vars 68 | @@ -795,37 +748,6 @@ module Crystal 69 | @last 70 | end 71 | 72 | - def codegen_primitive_struct_to_s 73 | - type = context.type as InstanceVarContainer 74 | - ivars = type.all_instance_vars 75 | - 76 | - # Generate 77 | - # "ClassName(#{ivar_name}=#{ivar_value}, ...)" 78 | - 79 | - vars = MetaVars.new 80 | - 81 | - exps = [] of ASTNode 82 | - exps << StringLiteral.new("#{type}(") 83 | - i = 0 84 | - ivars.each_value do |ivar| 85 | - ivar_name = "#ivar#{i}" 86 | - ivar_var = Var.new(ivar_name, ivar.type) 87 | - 88 | - context.vars[ivar_name] = LLVMVar.new(aggregate_index(llvm_self, i), ivar.type) 89 | - vars[ivar_name] = MetaVar.new(ivar_var.name) 90 | - 91 | - exps << StringLiteral.new(i == 0 ? "#{ivar.name}=" : ", #{ivar.name}=") 92 | - exps << ivar_var 93 | - i += 1 94 | - end 95 | - exps << StringLiteral.new(")") 96 | - exps = StringInterpolation.new(exps) 97 | - exps = @mod.normalize(exps) 98 | - exps.accept TypeVisitor.new(@mod, vars, Def.new("dummy", [] of Arg)) 99 | - exps.accept self 100 | - @last 101 | - end 102 | - 103 | def visit(node : ASTNode) 104 | true 105 | end 106 | @@ -1874,7 +1796,7 @@ module Crystal 107 | body = target_def.body 108 | if body.is_a?(Primitive) 109 | case body.name 110 | - when :struct_hash, :struct_equals, :struct_to_s 111 | + when :struct_equals 112 | # Skip: we want a method body for these 113 | else 114 | # Change context type: faster then creating a new context 115 | diff --git a/src/compiler/crystal/macro_expander.cr b/src/compiler/crystal/macros.cr 116 | similarity index 80% 117 | rename from src/compiler/crystal/macro_expander.cr 118 | rename to src/compiler/crystal/macros.cr 119 | index 0e6d22e7d..b17274196 100644 120 | --- a/src/compiler/crystal/macro_expander.cr 121 | +++ b/src/compiler/crystal/macros.cr 122 | @@ -1,16 +1,66 @@ 123 | module Crystal 124 | + class Program 125 | + def expand_def_macros 126 | + until @def_macros.empty? 127 | + def_macro = @def_macros.pop 128 | + expand_def_macro def_macro 129 | + end 130 | + end 131 | + 132 | + def expand_def_macro(target_def) 133 | + the_macro = Macro.new("macro_#{target_def.object_id}", [] of Arg, target_def.body) 134 | + the_macro.location = target_def.location 135 | + 136 | + owner = target_def.owner.not_nil! 137 | + 138 | + begin 139 | + generated_source = @program.expand_macro owner, target_def.body 140 | + rescue ex : Crystal::Exception 141 | + target_def.raise "expanding macro", ex 142 | + end 143 | + 144 | + vars = MetaVars.new 145 | + target_def.args.each do |arg| 146 | + vars[arg.name] = MetaVar.new(arg.name, arg.type) 147 | + end 148 | + target_def.vars = vars 149 | + 150 | + begin 151 | + arg_names = target_def.args.map(&.name) 152 | + 153 | + parser = Parser.new(generated_source, [Set.new(arg_names)]) 154 | + parser.filename = VirtualFile.new(the_macro, generated_source) 155 | + generated_nodes = parser.parse 156 | + rescue ex : Crystal::SyntaxException 157 | + target_def.raise "def macro didn't expand to a valid program, it expanded to:\n\n#{"=" * 80}\n#{"-" * 80}\n#{generated_source.lines.to_s_with_line_numbers}\n#{"-" * 80}\n#{ex.to_s(generated_source)}\n#{"=" * 80}" 158 | + end 159 | + 160 | + generated_nodes = @program.normalize(generated_nodes) 161 | + 162 | + type_visitor = TypeVisitor.new(@program, vars, target_def) 163 | + type_visitor.scope = owner 164 | + generated_nodes.accept type_visitor 165 | + 166 | + if generated_nodes.type != target_def.type 167 | + target_def.raise "expected '#{target_def.name}' to return #{target_def.type}, not #{generated_nodes.type}" 168 | + end 169 | + 170 | + target_def.body = generated_nodes 171 | + end 172 | + end 173 | + 174 | class MacroExpander 175 | def initialize(@mod) 176 | end 177 | 178 | - def expand(a_macro, call) 179 | - visitor = MacroVisitor.new @mod, a_macro, call 180 | + def expand(scope : Type, a_macro, call) 181 | + visitor = MacroVisitor.new @mod, scope, a_macro, call 182 | a_macro.body.accept visitor 183 | visitor.to_s 184 | end 185 | 186 | - def expand(node) 187 | - visitor = MacroVisitor.new @mod 188 | + def expand(scope : Type, node) 189 | + visitor = MacroVisitor.new @mod, scope 190 | node.accept visitor 191 | visitor.to_s 192 | end 193 | @@ -18,16 +68,16 @@ module Crystal 194 | class MacroVisitor < Visitor 195 | getter last 196 | 197 | - def self.new(mod, a_macro, call) 198 | + def self.new(mod, scope, a_macro, call) 199 | vars = {} of String => ASTNode 200 | a_macro.args.zip(call.args) do |macro_arg, call_arg| 201 | vars[macro_arg.name] = call_arg.to_macro_var 202 | end 203 | 204 | - new(mod, vars) 205 | + new(mod, scope, vars) 206 | end 207 | 208 | - def initialize(@mod, @vars = {} of String => ASTNode) 209 | + def initialize(@mod, @scope, @vars = {} of String => ASTNode) 210 | @str = StringBuilder.new 211 | @last = Nop.new 212 | end 213 | @@ -197,6 +247,33 @@ module Crystal 214 | end 215 | end 216 | 217 | + def visit(node : InstanceVar) 218 | + case node.name 219 | + when "@name" 220 | + @last = StringLiteral.new(@scope.to_s) 221 | + when "@instance_vars" 222 | + scope = @scope 223 | + unless scope.is_a?(InstanceVarContainer) 224 | + node.raise "#{scope} can't have instance vars" 225 | + end 226 | + 227 | + all_ivars = scope.all_instance_vars 228 | + 229 | + ivars = Array(ASTNode).new(all_ivars.length) 230 | + all_ivars.each do |name, ivar| 231 | + ivars.push MetaVar.new(name, ivar.type) 232 | + end 233 | + 234 | + @last = ArrayLiteral.new(ivars) 235 | + else 236 | + node.raise "unknown macro instance var: '#{node.name}'" 237 | + end 238 | + end 239 | + 240 | + def visit(node : MetaVar) 241 | + @last = node 242 | + end 243 | + 244 | def visit(node : BoolLiteral) 245 | @last = node 246 | end 247 | @@ -274,16 +351,7 @@ module Crystal 248 | raise "wrong number of arguments for stringify (#{args.length} for 0)" 249 | end 250 | 251 | - me = self 252 | - 253 | - case me 254 | - when StringLiteral 255 | - StringLiteral.new("\"#{me.value.dump}\"") 256 | - when SymbolLiteral 257 | - StringLiteral.new("\":#{me.value.dump}\"") 258 | - else 259 | - StringLiteral.new(to_s) 260 | - end 261 | + stringify 262 | when "==" 263 | BoolLiteral.new(self == args.first) 264 | when "!=" 265 | @@ -308,6 +376,10 @@ module Crystal 266 | raise "wrong number of arguments for #{method} (#{args.length} for #{length})" 267 | end 268 | end 269 | + 270 | + def stringify 271 | + StringLiteral.new(to_macro_id) 272 | + end 273 | end 274 | 275 | class NilLiteral 276 | @@ -364,6 +436,10 @@ module Crystal 277 | @value 278 | end 279 | 280 | + def stringify 281 | + StringLiteral.new("\"#{@value.dump}\"") 282 | + end 283 | + 284 | def interpret(method, args, block, interpreter) 285 | case method 286 | when "downcase" 287 | @@ -431,10 +507,14 @@ module Crystal 288 | end 289 | when "empty?" 290 | interpret_argless_method(method, args) { BoolLiteral.new(elements.empty?) } 291 | + when "first" 292 | + interpret_argless_method(method, args) { elements.first? || NilLiteral.new } 293 | when "join" 294 | interpret_one_arg_method(method, args) do |arg| 295 | StringLiteral.new(elements.map(&.to_macro_id).join arg.to_macro_id) 296 | end 297 | + when "last" 298 | + interpret_argless_method(method, args) { elements.last? || NilLiteral.new } 299 | when "length" 300 | interpret_argless_method(method, args) { NumberLiteral.new(elements.length, :i32) } 301 | when "map" 302 | @@ -543,10 +623,24 @@ module Crystal 303 | end 304 | end 305 | 306 | + class MetaVar 307 | + def to_macro_id 308 | + @name 309 | + end 310 | + 311 | + def stringify 312 | + StringLiteral.new("\"#{@name}\"") 313 | + end 314 | + end 315 | + 316 | class SymbolLiteral 317 | def to_macro_id 318 | @value 319 | end 320 | + 321 | + def stringify 322 | + StringLiteral.new("\":#{@value.dump}\"") 323 | + end 324 | end 325 | 326 | class Var 327 | diff --git a/src/compiler/crystal/primitives.cr b/src/compiler/crystal/primitives.cr 328 | index 808320a25..bc046dda3 100644 329 | --- a/src/compiler/crystal/primitives.cr 330 | +++ b/src/compiler/crystal/primitives.cr 331 | @@ -71,9 +71,7 @@ module Crystal 332 | end 333 | 334 | def define_struct_primitives 335 | - self.struct.add_def Def.new("hash", ([] of Arg), Primitive.new(:struct_hash)) 336 | self.struct.add_def Def.new("==", [Arg.new_with_restriction("other", Self.new)], Primitive.new(:struct_equals)) 337 | - self.struct.add_def Def.new("to_s", ([] of Arg), Primitive.new(:struct_to_s)) 338 | end 339 | 340 | def define_pointer_primitives 341 | diff --git a/src/compiler/crystal/program.cr b/src/compiler/crystal/program.cr 342 | index c134b5ef1..d864bb124 100644 343 | --- a/src/compiler/crystal/program.cr 344 | +++ b/src/compiler/crystal/program.cr 345 | @@ -108,6 +108,7 @@ module Crystal 346 | @vars = MetaVars.new 347 | @literal_expander = LiteralExpander.new self 348 | @macro_expander = MacroExpander.new self 349 | + @def_macros = [] of Def 350 | 351 | define_primitives 352 | end 353 | @@ -136,12 +137,16 @@ module Crystal 354 | flags 355 | end 356 | 357 | - def expand_macro(a_macro, call) 358 | - @macro_expander.expand a_macro, call 359 | + def push_def_macro(def) 360 | + @def_macros << def 361 | end 362 | 363 | - def expand_macro(node) 364 | - @macro_expander.expand node 365 | + def expand_macro(scope : Type, a_macro, call) 366 | + @macro_expander.expand scope, a_macro, call 367 | + end 368 | + 369 | + def expand_macro(scope : Type, node) 370 | + @macro_expander.expand scope, node 371 | end 372 | 373 | class PopenCommand < File 374 | diff --git a/src/compiler/crystal/type_inference.cr b/src/compiler/crystal/type_inference.cr 375 | index ec6b87084..ba3bdef29 100644 376 | --- a/src/compiler/crystal/type_inference.cr 377 | +++ b/src/compiler/crystal/type_inference.cr 378 | @@ -7,6 +7,7 @@ module Crystal 379 | class Program 380 | def infer_type(node) 381 | node.accept TypeVisitor.new(self) 382 | + expand_def_macros 383 | fix_empty_types node 384 | after_type_inference node 385 | end 386 | @@ -691,7 +692,7 @@ module Crystal 387 | return false unless the_macro 388 | 389 | generated_nodes = expand_macro(the_macro, node) do 390 | - @mod.expand_macro the_macro, node 391 | + @mod.expand_macro (@scope || @mod), the_macro, node 392 | end 393 | 394 | node.target_macro = generated_nodes 395 | @@ -717,7 +718,7 @@ module Crystal 396 | the_macro.location = node.location 397 | 398 | generated_nodes = expand_macro(the_macro, node) do 399 | - @mod.expand_macro node 400 | + @mod.expand_macro (@scope || @mod), node 401 | end 402 | 403 | node.expanded = generated_nodes 404 | @@ -738,7 +739,7 @@ module Crystal 405 | parser.filename = VirtualFile.new(the_macro, generated_source) 406 | generated_nodes = parser.parse 407 | rescue ex : Crystal::SyntaxException 408 | - node.raise "macro didn't expand to a valid program, it expanded to:\n\n#{"=" * 80}\n#{"-" * 80}\n#{number_lines generated_source}\n#{"-" * 80}\n#{ex.to_s(generated_source)}\n#{"=" * 80}" 409 | + node.raise "macro didn't expand to a valid program, it expanded to:\n\n#{"=" * 80}\n#{"-" * 80}\n#{generated_source.lines.to_s_with_line_numbers}\n#{"-" * 80}\n#{ex.to_s(generated_source)}\n#{"=" * 80}" 410 | end 411 | 412 | generated_nodes = mod.normalize(generated_nodes) 413 | @@ -746,16 +747,12 @@ module Crystal 414 | begin 415 | generated_nodes.accept self 416 | rescue ex : Crystal::Exception 417 | - node.raise "macro didn't expand to a valid program, it expanded to:\n\n#{"=" * 80}\n#{"-" * 80}\n#{number_lines generated_source}\n#{"-" * 80}\n#{ex.to_s(generated_source)}\n#{"=" * 80}" 418 | + node.raise "macro didn't expand to a valid program, it expanded to:\n\n#{"=" * 80}\n#{"-" * 80}\n#{generated_source.lines.to_s_with_line_numbers}\n#{"-" * 80}\n#{ex.to_s(generated_source)}\n#{"=" * 80}" 419 | end 420 | 421 | generated_nodes 422 | end 423 | 424 | - def number_lines(source) 425 | - source.lines.to_s_with_line_numbers 426 | - end 427 | - 428 | def visit(node : Return) 429 | node.raise "can't return from top level" unless @typed_def 430 | 431 | @@ -1489,12 +1486,8 @@ module Crystal 432 | node.type = mod.int32 433 | when :symbol_to_s 434 | node.type = mod.string 435 | - when :struct_hash 436 | - node.type = mod.int32 437 | when :struct_equals 438 | node.type = mod.bool 439 | - when :struct_to_s 440 | - node.type = mod.string 441 | when :class 442 | node.type = scope.metaclass 443 | when :fun_call 444 | diff --git a/src/compiler/crystal/type_inference/after_type_inference_transformer.cr b/src/compiler/crystal/type_inference/after_type_inference_transformer.cr 445 | index e7a37260d..2a7e8c484 100644 446 | --- a/src/compiler/crystal/type_inference/after_type_inference_transformer.cr 447 | +++ b/src/compiler/crystal/type_inference/after_type_inference_transformer.cr 448 | @@ -179,11 +179,7 @@ module Crystal 449 | @transformed.add(target_def.object_id) 450 | 451 | node.bubbling_exception do 452 | - if return_type = target_def.return_type 453 | - expand_def_macro target_def, target_def.type 454 | - else 455 | - target_def.body = target_def.body.transform(self) 456 | - end 457 | + target_def.body = target_def.body.transform(self) 458 | end 459 | end 460 | else 461 | @@ -214,48 +210,6 @@ module Crystal 462 | node 463 | end 464 | 465 | - def expand_def_macro(target_def, return_type) 466 | - the_macro = Macro.new("macro_#{target_def.object_id}", [] of Arg, target_def.body) 467 | - the_macro.location = target_def.location 468 | - 469 | - begin 470 | - generated_source = @program.expand_macro target_def.body 471 | - rescue ex : Crystal::Exception 472 | - target_def.raise "expanding macro", ex 473 | - end 474 | - 475 | - vars = MetaVars.new 476 | - target_def.args.each do |arg| 477 | - vars[arg.name] = MetaVar.new(arg.name, arg.type) 478 | - end 479 | - target_def.vars = vars 480 | - 481 | - begin 482 | - arg_names = target_def.args.map(&.name) 483 | - 484 | - parser = Parser.new(generated_source, [Set.new(arg_names)]) 485 | - parser.filename = VirtualFile.new(the_macro, generated_source) 486 | - generated_nodes = parser.parse 487 | - rescue ex : Crystal::SyntaxException 488 | - target_def.raise "def macro didn't expand to a valid program, it expanded to:\n\n#{"=" * 80}\n#{"-" * 80}\n#{number_lines generated_source}\n#{"-" * 80}\n#{ex.to_s(generated_source)}\n#{"=" * 80}" 489 | - end 490 | - 491 | - generated_nodes = @program.normalize(generated_nodes) 492 | - 493 | - type_visitor = TypeVisitor.new(@program, vars, target_def) 494 | - type_visitor.scope = target_def.owner 495 | - generated_nodes.accept type_visitor 496 | - 497 | - @program.fix_empty_types generated_nodes 498 | - generated_nodes = generated_nodes.transform(self) 499 | - 500 | - if generated_nodes.type != return_type 501 | - target_def.raise "expected '#{target_def.name}' to return #{return_type}, not #{generated_nodes.type}" 502 | - end 503 | - 504 | - target_def.body = generated_nodes 505 | - end 506 | - 507 | def number_lines(source) 508 | source.lines.to_s_with_line_numbers 509 | end 510 | diff --git a/src/compiler/crystal/type_inference/ast.cr b/src/compiler/crystal/type_inference/ast.cr 511 | index 02f80d9f4..e30aae8d0 100644 512 | --- a/src/compiler/crystal/type_inference/ast.cr 513 | +++ b/src/compiler/crystal/type_inference/ast.cr 514 | @@ -229,6 +229,13 @@ module Crystal 515 | property :self_closured 516 | @self_closured = false 517 | 518 | + def macro_owner=(@macro_owner) 519 | + end 520 | + 521 | + def macro_owner 522 | + @macro_owner || @owner 523 | + end 524 | + 525 | def has_default_arguments? 526 | args.length > 0 && args.last.default_value 527 | end 528 | diff --git a/src/compiler/crystal/type_inference/call.cr b/src/compiler/crystal/type_inference/call.cr 529 | index b74e2eaf2..264e7cd0b 100644 530 | --- a/src/compiler/crystal/type_inference/call.cr 531 | +++ b/src/compiler/crystal/type_inference/call.cr 532 | @@ -153,7 +153,8 @@ module Crystal 533 | typed_def, typed_def_args = prepare_typed_def_with_args(match.def, match_owner, lookup_self_type, match.arg_types) 534 | match_owner.add_def_instance(match.def.object_id, lookup_arg_types, block_type, typed_def) if use_cache 535 | if return_type = typed_def.return_type 536 | - typed_def.type = TypeLookup.lookup(match_owner, return_type) 537 | + typed_def.type = TypeLookup.lookup(match.def.macro_owner.not_nil!, return_type) 538 | + mod.push_def_macro typed_def 539 | else 540 | bubbling_exception do 541 | visitor = TypeVisitor.new(mod, typed_def_args, typed_def) 542 | diff --git a/src/compiler/crystal/types.cr b/src/compiler/crystal/types.cr 543 | index ef87cd15f..2800d7d43 100644 544 | --- a/src/compiler/crystal/types.cr 545 | +++ b/src/compiler/crystal/types.cr 546 | @@ -790,6 +790,7 @@ module Crystal 547 | super(program, container, name) 548 | if superclass 549 | @depth = superclass.depth + 1 550 | + copy_def_macros superclass 551 | else 552 | @depth = 0 553 | end 554 | @@ -806,6 +807,18 @@ module Crystal 555 | @superclass.try &.add_subclass(self) 556 | end 557 | 558 | + def copy_def_macros(superclass) 559 | + superclass.defs.try &.each do |name, hash| 560 | + hash.each do |def_key, def| 561 | + if def.return_type 562 | + cloned_def = def.clone 563 | + cloned_def.macro_owner = def.macro_owner 564 | + add_def cloned_def 565 | + end 566 | + end 567 | + end 568 | + end 569 | + 570 | def all_subclasses 571 | subclasses = [] of Type 572 | append_subclasses(self, subclasses) 573 | -------------------------------------------------------------------------------- /files/stage5.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/compiler/crystal/type_inference/type_lookup.cr b/src/compiler/crystal/type_inference/type_lookup.cr 2 | index 4de3dc121..863a79d17 100644 3 | --- a/src/compiler/crystal/type_inference/type_lookup.cr 4 | +++ b/src/compiler/crystal/type_inference/type_lookup.cr 5 | @@ -14,7 +14,7 @@ module Crystal 6 | if the_type && the_type.is_a?(Type) 7 | @type = the_type 8 | else 9 | - node.raise("uninitialized constant #{node.to_s_node}") 10 | + node.raise("uninitialized constant #{node}") 11 | end 12 | end 13 | 14 | -------------------------------------------------------------------------------- /files/stage61.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/compiler/crystal/macros.cr b/src/compiler/crystal/macros.cr 2 | index 2f9b3c790..230604236 100644 3 | --- a/src/compiler/crystal/macros.cr 4 | +++ b/src/compiler/crystal/macros.cr 5 | @@ -448,7 +448,7 @@ module Crystal 6 | 7 | def visit(node : InstanceVar) 8 | case node.name 9 | - when "@name", "@class_name" 10 | + when "@class_name" 11 | @last = StringLiteral.new(@scope.to_s) 12 | when "@instance_vars" 13 | @last = MacroType.instance_vars(@scope) 14 | @@ -869,7 +869,7 @@ module Crystal 15 | 16 | ivars = Array(ASTNode).new(all_ivars.length) 17 | all_ivars.each do |name, ivar| 18 | - ivars.push MetaVar.new(name, ivar.type) 19 | + ivars.push MetaVar.new(name[1 .. -1], ivar.type) 20 | end 21 | 22 | ArrayLiteral.new(ivars) 23 | -------------------------------------------------------------------------------- /files/stage65.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/compiler/crystal/parser.cr b/src/compiler/crystal/parser.cr 2 | index be70d2730..8e76fd1b0 100644 3 | --- a/src/compiler/crystal/parser.cr 4 | +++ b/src/compiler/crystal/parser.cr 5 | @@ -1604,9 +1604,9 @@ module Crystal 6 | result 7 | end 8 | 9 | - def parse_def(is_abstract = false) 10 | + def parse_def(is_abstract = false, allow_return_type = false) 11 | instance_vars = prepare_parse_def 12 | - a_def = parse_def_helper(is_abstract) 13 | + a_def = parse_def_helper(is_abstract, allow_return_type) 14 | 15 | # Small memory optimization: don't keep the Set in the Def if it's empty 16 | instance_vars = nil if instance_vars.empty? 17 | @@ -1629,12 +1629,15 @@ module Crystal 18 | end 19 | 20 | def parse_macro 21 | + next_token_skip_space_or_newline 22 | + 23 | + if @token.keyword?(:def) 24 | + return parse_def_helper(false, true) 25 | + end 26 | + 27 | push_def 28 | @def_nest += 1 29 | 30 | - next_token 31 | - 32 | - skip_space_or_newline 33 | check DefOrMacroCheck1 34 | 35 | name_line_number = @token.line_number 36 | @@ -1850,7 +1853,7 @@ module Crystal 37 | DefOrMacroCheck1 = [:IDENT, :CONST, :"=", :"<<", :"<", :"<=", :"==", :"===", :"!=", :"=~", :">>", :">", :">=", :"+", :"-", :"*", :"/", :"!", :"~", :"%", :"&", :"|", :"^", :"**", :"[]", :"[]=", :"<=>", :"[]?"] 38 | DefOrMacroCheck2 = [:"<<", :"<", :"<=", :"==", :"===", :"!=", :"=~", :">>", :">", :">=", :"+", :"-", :"*", :"/", :"!", :"~", :"%", :"&", :"|", :"^", :"**", :"[]", :"[]?", :"[]=", :"<=>"] 39 | 40 | - def parse_def_helper(is_abstract) 41 | + def parse_def_helper(is_abstract, allow_return_type) 42 | push_def 43 | @def_nest += 1 44 | 45 | @@ -1959,8 +1962,11 @@ module Crystal 46 | break 47 | end 48 | end 49 | - when :";", :"NEWLINE", :":" 50 | + when :";", :"NEWLINE" 51 | # Skip 52 | + when :":" 53 | + unexpected_token unless allow_return_type 54 | + # Skip 55 | else 56 | if is_abstract && @token.type == :EOF 57 | # OK 58 | @@ -1969,7 +1975,7 @@ module Crystal 59 | end 60 | end 61 | 62 | - if @token.type == :":" 63 | + if allow_return_type && @token.type == :":" 64 | next_token_skip_space 65 | return_type = parse_single_type 66 | 67 | -------------------------------------------------------------------------------- /files/stage9.patch: -------------------------------------------------------------------------------- 1 | diff --git a/spec/compiler/codegen/c_struct_spec.cr b/spec/compiler/codegen/c_struct_spec.cr 2 | index caed0f07e..50d0895ae 100644 3 | --- a/spec/compiler/codegen/c_struct_spec.cr 4 | +++ b/spec/compiler/codegen/c_struct_spec.cr 5 | @@ -13,7 +13,7 @@ describe "Code gen: struct" do 6 | end 7 | 8 | it "codegens struct property setter" do 9 | - run("#{CodeGenStructString}; bar = Foo::Bar.new; p = addressof(bar); p.value.y = 2.5_f32; bar.y").to_f32.should eq(2.5) 10 | + run("#{CodeGenStructString}; bar = Foo::Bar.new; p = pointerof(bar); p.value.y = 2.5_f32; bar.y").to_f32.should eq(2.5) 11 | end 12 | 13 | it "codegens set struct value with constant" do 14 | @@ -53,7 +53,7 @@ describe "Code gen: struct" do 15 | end 16 | 17 | foo = C::Foo.new 18 | - (addressof(foo).as(Int32) + 1_i64).value = 2 19 | + (pointerof(foo).as(Int32) + 1_i64).value = 2 20 | 21 | foo.bar.y 22 | ").to_i.should eq(2) 23 | diff --git a/spec/compiler/codegen/pointer_spec.cr b/spec/compiler/codegen/pointer_spec.cr 24 | index b9c9b584f..613999208 100755 25 | --- a/spec/compiler/codegen/pointer_spec.cr 26 | +++ b/spec/compiler/codegen/pointer_spec.cr 27 | @@ -3,7 +3,7 @@ require "../../spec_helper" 28 | 29 | describe "Code gen: pointer" do 30 | it "get pointer and value of it" do 31 | - run("a = 1; b = addressof(a); b.value").to_i.should eq(1) 32 | + run("a = 1; b = pointerof(a); b.value").to_i.should eq(1) 33 | end 34 | 35 | it "get pointer of instance var" do 36 | @@ -14,7 +14,7 @@ describe "Code gen: pointer" do 37 | end 38 | 39 | def value_ptr 40 | - addressof(@value) 41 | + pointerof(@value) 42 | end 43 | end 44 | 45 | @@ -25,11 +25,11 @@ describe "Code gen: pointer" do 46 | end 47 | 48 | it "set pointer value" do 49 | - run("a = 1; b = addressof(a); b.value = 2; a").to_i.should eq(2) 50 | + run("a = 1; b = pointerof(a); b.value = 2; a").to_i.should eq(2) 51 | end 52 | 53 | it "get value of pointer to union" do 54 | - run("a = 1.1; a = 1; b = addressof(a); b.value.to_i").to_i.should eq(1) 55 | + run("a = 1.1; a = 1; b = pointerof(a); b.value.to_i").to_i.should eq(1) 56 | end 57 | 58 | it "sets value of pointer to union" do 59 | @@ -44,7 +44,7 @@ describe "Code gen: pointer" do 60 | @b = 2 61 | end 62 | def value 63 | - p = addressof(@a) 64 | + p = pointerof(@a) 65 | p += 1_i64 66 | p.value 67 | end 68 | @@ -62,7 +62,7 @@ describe "Code gen: pointer" do 69 | end 70 | 71 | it "codegens pointer cast" do 72 | - run("a = 1_i64; addressof(a).as(Int32).value").to_i.should eq(1) 73 | + run("a = 1_i64; pointerof(a).as(Int32).value").to_i.should eq(1) 74 | end 75 | 76 | it "codegens pointer null" do 77 | @@ -70,7 +70,7 @@ describe "Code gen: pointer" do 78 | end 79 | 80 | it "codegens pointer as if condition" do 81 | - run("a = 0; addressof(a) ? 1 : 2").to_i.should eq(1) 82 | + run("a = 0; pointerof(a) ? 1 : 2").to_i.should eq(1) 83 | end 84 | 85 | it "codegens null pointer as if condition" do 86 | @@ -85,7 +85,7 @@ describe "Code gen: pointer" do 87 | end 88 | 89 | def foo 90 | - addressof(@a) 91 | + pointerof(@a) 92 | end 93 | end 94 | 95 | @@ -112,7 +112,7 @@ describe "Code gen: pointer" do 96 | color2 = C::Color.new 97 | color2.r = 20_u8 98 | 99 | - p = addressof(color) 100 | + p = pointerof(color) 101 | p.value = color2 102 | 103 | color.r 104 | @@ -122,7 +122,7 @@ describe "Code gen: pointer" do 105 | it "changes through var and reads from pointer" do 106 | run(" 107 | x = 1 108 | - px = addressof(x) 109 | + px = pointerof(x) 110 | x = 2 111 | px.value 112 | ").to_i.should eq(2) 113 | @@ -138,7 +138,7 @@ describe "Code gen: pointer" do 114 | it "calculates pointer diff" do 115 | run(" 116 | x = 1 117 | - (addressof(x) + 1_i64) - addressof(x) 118 | + (pointerof(x) + 1_i64) - pointerof(x) 119 | ").to_i.should eq(1) 120 | end 121 | end 122 | diff --git a/spec/compiler/lexer/lexer_spec.cr b/spec/compiler/lexer/lexer_spec.cr 123 | index 462045f81..0eb63939f 100755 124 | --- a/spec/compiler/lexer/lexer_spec.cr 125 | +++ b/spec/compiler/lexer/lexer_spec.cr 126 | @@ -125,7 +125,7 @@ describe "Lexer" do 127 | it_lexes "\t", :SPACE 128 | it_lexes "\n", :NEWLINE 129 | it_lexes "\n\n\n", :NEWLINE 130 | - it_lexes_keywords [:def, :if, :else, :elsif, :end, :true, :false, :class, :module, :include, :while, :nil, :do, :yield, :return, :unless, :next, :break, :begin, :lib, :fun, :type, :struct, :union, :enum, :macro, :ptr, :out, :require, :case, :when, :then, :of, :abstract, :rescue, :ensure, :is_a?, :alias, :addressof] 131 | + it_lexes_keywords [:def, :if, :else, :elsif, :end, :true, :false, :class, :module, :include, :while, :nil, :do, :yield, :return, :unless, :next, :break, :begin, :lib, :fun, :type, :struct, :union, :enum, :macro, :ptr, :out, :require, :case, :when, :then, :of, :abstract, :rescue, :ensure, :is_a?, :alias, :pointerof] 132 | it_lexes_idents ["ident", "something", "with_underscores", "with_1", "foo?", "bar!", "foo$123"] 133 | it_lexes_idents ["def?", "if?", "else?", "elsif?", "end?", "true?", "false?", "class?", "while?", "nil?", "do?", "yield?", "return?", "unless?", "next?", "break?", "begin?"] 134 | it_lexes_idents ["def!", "if!", "else!", "elsif!", "end!", "true!", "false!", "class!", "while!", "nil!", "do!", "yield!", "return!", "unless!", "next!", "break!", "begin!"] 135 | diff --git a/spec/compiler/normalize/ssa_spec.cr b/spec/compiler/normalize/ssa_spec.cr 136 | index bc4e8011c..1007c5df8 100755 137 | --- a/spec/compiler/normalize/ssa_spec.cr 138 | +++ b/spec/compiler/normalize/ssa_spec.cr 139 | @@ -185,11 +185,11 @@ describe "Normalize: ssa" do 140 | end 141 | 142 | it "stops ssa if address is taken" do 143 | - assert_normalize "a = 1; x = addressof(a); a = 2", "a = 1\nx = addressof(a)\na = 2" 144 | + assert_normalize "a = 1; x = pointerof(a); a = 2", "a = 1\nx = pointerof(a)\na = 2" 145 | end 146 | 147 | it "stops ssa if address is taken 2" do 148 | - assert_normalize "a = 1; a = 2; x = addressof(a); a = 3", "a = 1\na$1 = 2\nx = addressof(a$1)\na$1 = 3" 149 | + assert_normalize "a = 1; a = 2; x = pointerof(a); a = 3", "a = 1\na$1 = 2\nx = pointerof(a$1)\na$1 = 3" 150 | end 151 | 152 | it "performs ssa on var on nested if" do 153 | diff --git a/spec/compiler/parser/parser_spec.cr b/spec/compiler/parser/parser_spec.cr 154 | index 7bd975717..8cb893155 100755 155 | --- a/spec/compiler/parser/parser_spec.cr 156 | +++ b/spec/compiler/parser/parser_spec.cr 157 | @@ -477,8 +477,10 @@ describe "Parser" do 158 | 159 | it_parses "macro foo;end", Crystal::Macro.new("foo", [] of Arg) 160 | 161 | - it_parses "a = 1; addressof(a)", [Assign.new("a".var, 1.int32), AddressOf.new("a".var)] 162 | - it_parses "addressof(@a)", AddressOf.new("@a".instance_var) 163 | + it_parses "a = 1; pointerof(a)", [Assign.new("a".var, 1.int32), PointerOf.new("a".var)] 164 | + it_parses "pointerof(@a)", PointerOf.new("@a".instance_var) 165 | + it_parses "a = 1; pointerof(a)", [Assign.new("a".var, 1.int32), PointerOf.new("a".var)] 166 | + it_parses "pointerof(@a)", PointerOf.new("@a".instance_var) 167 | 168 | it_parses "foo.is_a?(Const)", IsA.new("foo".call, "Const".ident) 169 | it_parses "foo.is_a?(Foo | Bar)", IsA.new("foo".call, IdentUnion.new(["Foo".ident, "Bar".ident] of ASTNode)) 170 | diff --git a/spec/compiler/type_inference/pointer_spec.cr b/spec/compiler/type_inference/pointer_spec.cr 171 | index b0a5f2f58..df6b2177d 100755 172 | --- a/spec/compiler/type_inference/pointer_spec.cr 173 | +++ b/spec/compiler/type_inference/pointer_spec.cr 174 | @@ -3,19 +3,19 @@ require "../../spec_helper" 175 | 176 | describe "Type inference: pointer" do 177 | it "types int pointer" do 178 | - assert_type("a = 1; addressof(a)") { pointer_of(int32) } 179 | + assert_type("a = 1; pointerof(a)") { pointer_of(int32) } 180 | end 181 | 182 | it "types pointer value" do 183 | - assert_type("a = 1; b = addressof(a); b.value") { int32 } 184 | + assert_type("a = 1; b = pointerof(a); b.value") { int32 } 185 | end 186 | 187 | it "types pointer add" do 188 | - assert_type("a = 1; addressof(a) + 1_i64") { pointer_of(int32) } 189 | + assert_type("a = 1; pointerof(a) + 1_i64") { pointer_of(int32) } 190 | end 191 | 192 | it "types pointer diff" do 193 | - assert_type("a = 1; b = 2; addressof(a) - addressof(b)") { int64 } 194 | + assert_type("a = 1; b = 2; pointerof(a) - pointerof(b)") { int64 } 195 | end 196 | 197 | it "types Pointer.malloc" do 198 | @@ -31,11 +31,11 @@ describe "Type inference: pointer" do 199 | end 200 | 201 | it "type pointer casting" do 202 | - assert_type("a = 1; addressof(a).as(Char)") { pointer_of(char) } 203 | + assert_type("a = 1; pointerof(a).as(Char)") { pointer_of(char) } 204 | end 205 | 206 | it "type pointer casting of object type" do 207 | - assert_type("a = 1; addressof(a).as(String)") { string } 208 | + assert_type("a = 1; pointerof(a).as(String)") { string } 209 | end 210 | 211 | it "pointer malloc creates new type" do 212 | diff --git a/src/compiler/crystal/ast.cr b/src/compiler/crystal/ast.cr 213 | index cffff1955..99906f1cf 100644 214 | --- a/src/compiler/crystal/ast.cr 215 | +++ b/src/compiler/crystal/ast.cr 216 | @@ -1410,7 +1410,7 @@ module Crystal 217 | end 218 | end 219 | 220 | - class AddressOf < ASTNode 221 | + class PointerOf < ASTNode 222 | @exp :: ASTNode+ 223 | 224 | def initialize(@exp) 225 | @@ -1432,7 +1432,7 @@ module Crystal 226 | end 227 | 228 | def clone_without_location 229 | - AddressOf.new(@exp.clone) 230 | + PointerOf.new(@exp.clone) 231 | end 232 | end 233 | 234 | diff --git a/src/compiler/crystal/codegen.cr b/src/compiler/crystal/codegen.cr 235 | index 77c9f229a..b5ee5f5de 100644 236 | --- a/src/compiler/crystal/codegen.cr 237 | +++ b/src/compiler/crystal/codegen.cr 238 | @@ -665,7 +665,7 @@ module Crystal 239 | LLVM.null(llvm_type(node.type)) 240 | end 241 | 242 | - def visit(node : AddressOf) 243 | + def visit(node : PointerOf) 244 | node_exp = node.exp 245 | case node_exp 246 | when Var 247 | @@ -682,7 +682,7 @@ module Crystal 248 | 249 | @last = gep llvm_self_ptr, 0, type.index_of_instance_var(node_exp.name) 250 | else 251 | - raise "Bug: addressof(#{node.to_s_node})" 252 | + raise "Bug: pointerof(#{node.to_s_node})" 253 | end 254 | false 255 | end 256 | diff --git a/src/compiler/crystal/lexer.cr b/src/compiler/crystal/lexer.cr 257 | index 01d7e84c1..e95439d45 100644 258 | --- a/src/compiler/crystal/lexer.cr 259 | +++ b/src/compiler/crystal/lexer.cr 260 | @@ -429,10 +429,6 @@ module Crystal 261 | if next_char == 's' && next_char == 't' && next_char == 'r' && next_char == 'a' && next_char == 'c' && next_char == 't' 262 | return check_ident_or_keyword(:abstract, start, start_column) 263 | end 264 | - when 'd' 265 | - if next_char == 'd' && next_char == 'r' && next_char == 'e' && next_char == 's' && next_char == 's' && next_char == 'o' && next_char == 'f' 266 | - return check_ident_or_keyword(:addressof, start, start_column) 267 | - end 268 | when 'l' 269 | if next_char == 'i' && next_char == 'a' && next_char == 's' 270 | return check_ident_or_keyword(:alias, start, start_column) 271 | @@ -571,8 +567,15 @@ module Crystal 272 | end 273 | scan_ident(start, start_column) 274 | when 'p' 275 | - if next_char == 't' && next_char == 'r' 276 | - return check_ident_or_keyword(:ptr, start, start_column) 277 | + case next_char 278 | + when 't' 279 | + if next_char == 'r' 280 | + return check_ident_or_keyword(:ptr, start, start_column) 281 | + end 282 | + when 'o' 283 | + if next_char == 'i' && next_char == 'n' && next_char == 't' && next_char == 'e' && next_char == 'r' && next_char == 'o' && next_char == 'f' 284 | + return check_ident_or_keyword(:pointerof, start, start_column) 285 | + end 286 | end 287 | scan_ident(start, start_column) 288 | when 'r' 289 | diff --git a/src/compiler/crystal/normalizer.cr b/src/compiler/crystal/normalizer.cr 290 | index 698bfd350..58be50cdc 100644 291 | --- a/src/compiler/crystal/normalizer.cr 292 | +++ b/src/compiler/crystal/normalizer.cr 293 | @@ -396,7 +396,7 @@ module Crystal 294 | end 295 | end 296 | 297 | - def transform(node : AddressOf) 298 | + def transform(node : PointerOf) 299 | exp = node.exp 300 | 301 | if exp.is_a?(Var) 302 | diff --git a/src/compiler/crystal/parser.cr b/src/compiler/crystal/parser.cr 303 | index 8d8ab4e9d..16683a692 100644 304 | --- a/src/compiler/crystal/parser.cr 305 | +++ b/src/compiler/crystal/parser.cr 306 | @@ -515,7 +515,7 @@ module Crystal 307 | # if atomic.block 308 | # raise "'ptr' can't receive a block" 309 | # end 310 | - # atomic = AddressOf.new(atomic_obj) 311 | + # atomic = PointerOf.new(atomic_obj) 312 | # atomic.location = location 313 | when "responds_to?" 314 | if atomic.args.length != 1 315 | @@ -634,8 +634,8 @@ module Crystal 316 | parse_fun_def(true) 317 | when :alias 318 | parse_alias 319 | - when :addressof 320 | - parse_addressof 321 | + when :pointerof 322 | + parse_pointerof 323 | else 324 | parse_var_or_call 325 | end 326 | @@ -2369,7 +2369,7 @@ module Crystal 327 | node 328 | end 329 | 330 | - def parse_addressof 331 | + def parse_pointerof 332 | next_token_skip_space 333 | 334 | check :"(" 335 | @@ -2381,7 +2381,7 @@ module Crystal 336 | check :")" 337 | next_token_skip_space 338 | 339 | - AddressOf.new(exp) 340 | + PointerOf.new(exp) 341 | end 342 | 343 | def parse_type_def 344 | diff --git a/src/compiler/crystal/to_s.cr b/src/compiler/crystal/to_s.cr 345 | index 84faf04f6..e05183db4 100644 346 | --- a/src/compiler/crystal/to_s.cr 347 | +++ b/src/compiler/crystal/to_s.cr 348 | @@ -719,8 +719,8 @@ module Crystal 349 | false 350 | end 351 | 352 | - def visit(node : AddressOf) 353 | - @str << "addressof(" 354 | + def visit(node : PointerOf) 355 | + @str << "pointerof(" 356 | node.exp.accept(self) 357 | @str << ")" 358 | false 359 | diff --git a/src/compiler/crystal/transformer.cr b/src/compiler/crystal/transformer.cr 360 | index a1daa451b..db745e204 100644 361 | --- a/src/compiler/crystal/transformer.cr 362 | +++ b/src/compiler/crystal/transformer.cr 363 | @@ -151,7 +151,7 @@ module Crystal 364 | node 365 | end 366 | 367 | - def transform(node : AddressOf) 368 | + def transform(node : PointerOf) 369 | node.exp = node.exp.transform(self) 370 | node 371 | end 372 | diff --git a/src/compiler/crystal/type_inference.cr b/src/compiler/crystal/type_inference.cr 373 | index 3e382dc8d..d7af37608 100644 374 | --- a/src/compiler/crystal/type_inference.cr 375 | +++ b/src/compiler/crystal/type_inference.cr 376 | @@ -1021,7 +1021,7 @@ module Crystal 377 | node.type = instance_type 378 | end 379 | 380 | - def visit(node : AddressOf) 381 | + def visit(node : PointerOf) 382 | node.mod = @mod 383 | node_exp = node.exp 384 | var = case node_exp 385 | diff --git a/src/compiler/crystal/type_inference/ast.cr b/src/compiler/crystal/type_inference/ast.cr 386 | index 7258e12a6..bf456caa4 100644 387 | --- a/src/compiler/crystal/type_inference/ast.cr 388 | +++ b/src/compiler/crystal/type_inference/ast.cr 389 | @@ -136,7 +136,7 @@ module Crystal 390 | end 391 | end 392 | 393 | - class AddressOf 394 | + class PointerOf 395 | property! mod 396 | 397 | def map_type(type) 398 | --------------------------------------------------------------------------------