├── spec
├── std
│ ├── data
│ │ ├── dir
│ │ │ ├── subdir2
│ │ │ │ └── .gitkeep
│ │ │ ├── f1.txt
│ │ │ ├── f2.txt
│ │ │ ├── f3.txx
│ │ │ ├── g2.txt
│ │ │ └── subdir
│ │ │ │ ├── f1.txt
│ │ │ │ └── subdir2
│ │ │ │ └── f2.txt
│ │ ├── symlink.txt
│ │ ├── argf_test_file_1.txt
│ │ ├── argf_test_file_2.txt
│ │ ├── test_template.ecr
│ │ ├── websocket_longpacket.bin
│ │ ├── test_file.ini
│ │ └── test_file.txt
│ ├── openssl
│ │ ├── cipher_spec.ciphertext
│ │ ├── pkcs5_spec.cr
│ │ ├── hmac_spec.cr
│ │ ├── digest_spec.cr
│ │ └── cipher_spec.cr
│ ├── box_spec.cr
│ ├── crypto
│ │ ├── md5_spec.cr
│ │ ├── bcrypt
│ │ │ └── password_spec.cr
│ │ └── subtle_spec.cr
│ ├── uint_spec.cr
│ ├── concurrent_spec.cr
│ ├── double_spec.cr
│ ├── oauth
│ │ ├── params_spec.cr
│ │ ├── authorization_header_spec.cr
│ │ ├── request_token_spec.cr
│ │ └── access_token_spec.cr
│ ├── html_spec.cr
│ ├── file_utils_spec.cr
│ ├── oauth2
│ │ └── session_spec.cr
│ ├── zlib
│ │ ├── deflate_spec.cr
│ │ ├── inflate_spec.cr
│ │ ├── stress_spec.cr
│ │ └── zlib_spec.cr
│ ├── string_builder_spec.cr
│ ├── struct_spec.cr
│ ├── signal_spec.cr
│ ├── class_spec.cr
│ ├── http
│ │ ├── http_spec.cr
│ │ ├── server
│ │ │ └── handlers
│ │ │ │ └── websocket_handler_spec.cr
│ │ └── server_spec.cr
│ ├── readline_spec.cr
│ ├── ecr
│ │ └── ecr_spec.cr
│ ├── symbol_spec.cr
│ ├── llvm
│ │ └── x86_abi_spec.cr
│ ├── io
│ │ └── argf_spec.cr
│ ├── inifile_spec.cr
│ ├── yaml
│ │ └── yaml_spec.cr
│ ├── semantic_version_spec.cr
│ ├── bool_spec.cr
│ ├── tempfile_spec.cr
│ ├── thread_spec.cr
│ ├── levenshtein_spec.cr
│ ├── thread
│ │ └── condition_variable_spec.cr
│ ├── random_spec.cr
│ ├── reference_spec.cr
│ ├── html
│ │ └── builder_spec.cr
│ └── string_pool_spec.cr
├── compiler
│ ├── crystal_path
│ │ └── test_files
│ │ │ ├── file_one.cr
│ │ │ ├── file_two.cr
│ │ │ └── test_folder
│ │ │ ├── file_three.cr
│ │ │ ├── test_folder.cr
│ │ │ └── not_a_crystal_file.txt
│ ├── data
│ │ ├── compiler_sample
│ │ └── build
│ ├── normalize
│ │ ├── until_spec.cr
│ │ ├── unless_spec.cr
│ │ ├── range_literal_spec.cr
│ │ ├── string_interpolation_spec.cr
│ │ ├── ifdef_spec.cr
│ │ ├── array_literal_spec.cr
│ │ ├── hash_literal_spec.cr
│ │ ├── or_spec.cr
│ │ ├── return_next_break_spec.cr
│ │ ├── and_spec.cr
│ │ └── chained_comparisons_spec.cr
│ ├── codegen
│ │ ├── until_spec.cr
│ │ ├── untyped_expression_spec.cr
│ │ ├── asm_spec.cr
│ │ ├── global_spec.cr
│ │ ├── previous_def_spec.cr
│ │ ├── no_return_spec.cr
│ │ └── private_def_spec.cr
│ ├── type_inference
│ │ ├── c_type_spec.cr
│ │ ├── reflection_spec.cr
│ │ ├── responds_to_spec.cr
│ │ ├── array_spec.cr
│ │ ├── method_missing_spec.cr
│ │ ├── dependencies_spec.cr
│ │ ├── c_enum_spec.cr
│ │ ├── named_args_spec.cr
│ │ └── global_spec.cr
│ ├── compiler_spec.cr
│ └── parser
│ │ └── parser_doc_spec.cr
└── all_spec.cr
├── .dockerignore
├── src
├── http
│ ├── http.cr
│ └── server
│ │ └── handlers
│ │ ├── error_handler.cr
│ │ ├── log_handler.cr
│ │ ├── deflate_handler.cr
│ │ └── static_file_handler.cr
├── compiler
│ ├── crystal
│ │ ├── tools
│ │ │ ├── init
│ │ │ │ └── template
│ │ │ │ │ ├── travis.yml.ecr
│ │ │ │ │ ├── version.cr.ecr
│ │ │ │ │ ├── spec_helper.cr.ecr
│ │ │ │ │ ├── example.cr.ecr
│ │ │ │ │ ├── shard.yml.ecr
│ │ │ │ │ ├── example_spec.cr.ecr
│ │ │ │ │ ├── gitignore.ecr
│ │ │ │ │ ├── readme.md.ecr
│ │ │ │ │ └── license.ecr
│ │ │ ├── doc.cr
│ │ │ ├── doc
│ │ │ │ ├── item.cr
│ │ │ │ ├── html
│ │ │ │ │ ├── other_types.html
│ │ │ │ │ ├── method_summary.html
│ │ │ │ │ ├── list_items.html
│ │ │ │ │ ├── methods_inherited.html
│ │ │ │ │ ├── main.html
│ │ │ │ │ └── method_detail.html
│ │ │ │ ├── constant.cr
│ │ │ │ ├── templates.cr
│ │ │ │ └── macro.cr
│ │ │ └── print_types_visitor.cr
│ │ ├── core_ext
│ │ │ └── enumerable.cr
│ │ ├── config.cr
│ │ ├── version.cr
│ │ ├── codegen
│ │ │ ├── target_machine.cr
│ │ │ ├── types.cr
│ │ │ ├── crystal_llvm_builder.cr
│ │ │ └── asm.cr
│ │ ├── macros
│ │ │ └── virtual_file.cr
│ │ ├── syntax
│ │ │ ├── visitor.cr
│ │ │ └── location.cr
│ │ └── semantic
│ │ │ ├── flags.cr
│ │ │ └── match.cr
│ └── crystal.cr
├── ecr
│ ├── process.cr
│ └── macros.cr
├── concurrent
│ ├── error.cr
│ └── concurrent.cr
├── oauth2
│ ├── oauth2.cr
│ ├── access_token
│ │ └── bearer.cr
│ ├── error.cr
│ └── session.cr
├── oauth
│ ├── error.cr
│ ├── oauth.cr
│ ├── request_token.cr
│ ├── authorization_header.cr
│ ├── params.cr
│ └── access_token.cr
├── llvm
│ ├── value.cr
│ ├── context.cr
│ ├── basic_block.cr
│ ├── basic_block_collection.cr
│ ├── phi_table.cr
│ ├── instruction_collection.cr
│ ├── module_pass_manager.cr
│ ├── global_collection.cr
│ ├── target_data.cr
│ ├── pass_registry.cr
│ ├── generic_value.cr
│ ├── function_collection.cr
│ ├── function_pass_manager.cr
│ ├── parameter_collection.cr
│ ├── function.cr
│ ├── jit_compiler.cr
│ ├── pass_manager_builder.cr
│ ├── abi.cr
│ ├── target.cr
│ └── target_machine.cr
├── time
│ ├── day_of_week.cr
│ └── format.cr
├── io
│ ├── error.cr
│ ├── pointer_io.cr
│ └── fd_set.cr
├── empty.cr
├── box.cr
├── xml
│ ├── attribute_type.cr
│ ├── save_options.cr
│ ├── type.cr
│ ├── html_parser_options.cr
│ ├── namespace.cr
│ ├── error.cr
│ ├── node_set.cr
│ ├── attributes.cr
│ └── xml.cr
├── openssl
│ ├── md5.cr
│ ├── sha1.cr
│ ├── pkcs5.cr
│ ├── ssl
│ │ ├── context.cr
│ │ └── socket.cr
│ ├── openssl.cr
│ ├── digest
│ │ └── digest_base.cr
│ ├── hmac.cr
│ └── lib_ssl.cr
├── gc.cr
├── crypto
│ ├── subtle.cr
│ └── bcrypt
│ │ └── blowfish.cr
├── json
│ ├── lexer
│ │ └── io_based.cr
│ └── token.cr
├── reflect.cr
├── fiber
│ └── lib_pcl.cr
├── html.cr
├── csv
│ ├── error.cr
│ ├── token.cr
│ └── lexer
│ │ ├── io_based.cr
│ │ └── string_based.cr
├── inifile.cr
├── main.cr
├── spec
│ ├── source.cr
│ ├── formatter.cr
│ └── dsl.cr
├── thread
│ ├── mutex.cr
│ ├── condition_variable.cr
│ ├── thread.cr
│ └── lib_pthread.cr
├── intrinsics.cr
├── gc
│ └── null.cr
├── file_utils.cr
├── markdown
│ └── markdown.cr
├── value.cr
├── dl.cr
├── iterable.cr
├── proc.cr
├── class.cr
├── regex
│ └── lib_pcre.cr
├── prelude.cr
├── process
│ └── status.cr
├── zlib
│ └── inflate.cr
├── unwind.cr
└── file
│ └── flock.cr
├── samples
├── quine.cr
├── egrep.cr
├── http_server.cr
├── tcp_client.cr
├── mandelbrot2.cr
├── sieve.cr
├── tcp_server.cr
├── tree.cr
├── channel_primes.cr
├── channel_select.cr
├── sdl
│ ├── tv.txt
│ ├── fire.txt
│ └── sdl
│ │ ├── surface.cr
│ │ └── sdl.cr
├── mandelbrot.cr
├── spectral-norm.cr
├── matmul.cr
├── impl.cr
├── wordcount.cr
└── binary-trees.cr
├── .editorconfig
├── .gitignore
├── Dockerfile.release
├── docs
├── char.cr
└── main.cr
├── LICENSE
├── Dockerfile
├── .travis.yml
├── Vagrantfile
├── BACKERS.md
└── Makefile
/spec/std/data/dir/subdir2/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/spec/std/data/symlink.txt:
--------------------------------------------------------------------------------
1 | test_file.txt
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | .git
2 | .crystal
3 | .vagrant
4 |
--------------------------------------------------------------------------------
/spec/std/data/argf_test_file_1.txt:
--------------------------------------------------------------------------------
1 | 12345
2 |
--------------------------------------------------------------------------------
/spec/std/data/argf_test_file_2.txt:
--------------------------------------------------------------------------------
1 | 67890
2 |
--------------------------------------------------------------------------------
/spec/compiler/crystal_path/test_files/file_one.cr:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/spec/compiler/crystal_path/test_files/file_two.cr:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/spec/compiler/data/compiler_sample:
--------------------------------------------------------------------------------
1 | print "Hello!"
2 |
--------------------------------------------------------------------------------
/src/http/http.cr:
--------------------------------------------------------------------------------
1 | require "uri"
2 | require "./**"
3 |
--------------------------------------------------------------------------------
/spec/std/data/dir/f1.txt:
--------------------------------------------------------------------------------
1 | This file is for Dir.glob specs
--------------------------------------------------------------------------------
/spec/std/data/dir/f2.txt:
--------------------------------------------------------------------------------
1 | This file is for Dir.glob specs
--------------------------------------------------------------------------------
/spec/std/data/dir/f3.txx:
--------------------------------------------------------------------------------
1 | This file is for Dir.glob specs
--------------------------------------------------------------------------------
/spec/std/data/dir/g2.txt:
--------------------------------------------------------------------------------
1 | This file is for Dir.glob specs
--------------------------------------------------------------------------------
/spec/compiler/crystal_path/test_files/test_folder/file_three.cr:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/spec/std/data/dir/subdir/f1.txt:
--------------------------------------------------------------------------------
1 | This file is for Dir.glob specs
--------------------------------------------------------------------------------
/spec/compiler/crystal_path/test_files/test_folder/test_folder.cr:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/spec/compiler/crystal_path/test_files/test_folder/not_a_crystal_file.txt:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/spec/compiler/data/build:
--------------------------------------------------------------------------------
1 | puts "this file is never compiled (#1412)"
2 |
--------------------------------------------------------------------------------
/spec/std/data/dir/subdir/subdir2/f2.txt:
--------------------------------------------------------------------------------
1 | This file is for Dir.glob specs
--------------------------------------------------------------------------------
/src/compiler/crystal/tools/init/template/travis.yml.ecr:
--------------------------------------------------------------------------------
1 | language: crystal
2 |
--------------------------------------------------------------------------------
/src/compiler/crystal.cr:
--------------------------------------------------------------------------------
1 | require "./crystal/**"
2 |
3 | Crystal::Command.run
4 |
--------------------------------------------------------------------------------
/src/ecr/process.cr:
--------------------------------------------------------------------------------
1 | require "ecr"
2 | puts ECR.process_file(ARGV[0], ARGV[1])
3 |
--------------------------------------------------------------------------------
/samples/quine.cr:
--------------------------------------------------------------------------------
1 | s = "s = @; puts s.sub(\"@\", s.dump)"; puts s.sub("@", s.dump)
2 |
--------------------------------------------------------------------------------
/spec/all_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 | require "./compiler/**"
3 | require "./std/**"
4 |
--------------------------------------------------------------------------------
/spec/std/data/test_template.ecr:
--------------------------------------------------------------------------------
1 | Hello <%= @msg %> <% 3.times { |i| %><%= i %><% } %>
2 |
--------------------------------------------------------------------------------
/src/concurrent/error.cr:
--------------------------------------------------------------------------------
1 | module Concurrent
2 | class CanceledError < Exception; end
3 | end
4 |
--------------------------------------------------------------------------------
/src/oauth2/oauth2.cr:
--------------------------------------------------------------------------------
1 | require "http/client"
2 | require "http/params"
3 | require "json"
4 | require "./**"
5 |
--------------------------------------------------------------------------------
/src/compiler/crystal/tools/init/template/version.cr.ecr:
--------------------------------------------------------------------------------
1 | module <%= module_name %>
2 | VERSION = "0.1.0"
3 | end
4 |
--------------------------------------------------------------------------------
/src/compiler/crystal/tools/init/template/spec_helper.cr.ecr:
--------------------------------------------------------------------------------
1 | require "spec"
2 | require "../src/<%= @config.name %>"
3 |
--------------------------------------------------------------------------------
/spec/std/data/websocket_longpacket.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shinh/crystal/master/spec/std/data/websocket_longpacket.bin
--------------------------------------------------------------------------------
/spec/std/openssl/cipher_spec.ciphertext:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shinh/crystal/master/spec/std/openssl/cipher_spec.ciphertext
--------------------------------------------------------------------------------
/src/oauth/error.cr:
--------------------------------------------------------------------------------
1 | class OAuth::Error < ::Exception
2 | def initialize(@response)
3 | super("OAuth:Error: #{@response.body}")
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/spec/std/data/test_file.ini:
--------------------------------------------------------------------------------
1 | [general]
2 | log_level = DEBUG
3 |
4 | [section1]
5 | foo = 1
6 | bar = 2
7 |
8 | [section2]
9 | x.y.z = coco lala
10 |
11 |
--------------------------------------------------------------------------------
/src/compiler/crystal/tools/init/template/example.cr.ecr:
--------------------------------------------------------------------------------
1 | require "./<%= config.name %>/*"
2 |
3 | module <%= module_name %>
4 | # TODO Put your code here
5 | end
6 |
--------------------------------------------------------------------------------
/src/llvm/value.cr:
--------------------------------------------------------------------------------
1 | require "./value_methods"
2 |
3 | struct LLVM::Value
4 | include ValueMethods
5 |
6 | def to_value
7 | self
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/src/time/day_of_week.cr:
--------------------------------------------------------------------------------
1 | enum Time::DayOfWeek
2 | Sunday
3 | Monday
4 | Tuesday
5 | Wednesday
6 | Thursday
7 | Friday
8 | Saturday
9 | end
10 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.cr]
2 | charset = utf-8
3 | end_of_line = lf
4 | insert_final_newline = true
5 | indent_style = space
6 | indent_size = 2
7 | trim_trailing_whitespace = true
8 |
--------------------------------------------------------------------------------
/src/oauth/oauth.cr:
--------------------------------------------------------------------------------
1 | require "http/client"
2 | require "http/params"
3 | require "uri"
4 | require "secure_random"
5 | require "openssl/hmac"
6 | require "base64"
7 | require "./**"
8 |
--------------------------------------------------------------------------------
/src/compiler/crystal/tools/init/template/shard.yml.ecr:
--------------------------------------------------------------------------------
1 | name: <%= config.name %>
2 | version: 0.1.0
3 |
4 | authors:
5 | - <%= config.author %> <<%= config.email %>>
6 |
7 | license: MIT
8 |
--------------------------------------------------------------------------------
/spec/std/box_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 |
3 | describe "Box" do
4 | it "boxes and unboxes" do
5 | a = 1
6 | box = Box.box(a)
7 | Box(Int32).unbox(box).should eq(1)
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/src/compiler/crystal/core_ext/enumerable.cr:
--------------------------------------------------------------------------------
1 | module Enumerable
2 | def to_s_with_line_numbers
3 | map_with_index { |line, i| "#{"%3d" % (i + 1)}. #{line.to_s.chomp}" }.join "\n"
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/samples/egrep.cr:
--------------------------------------------------------------------------------
1 | if ARGV.empty?
2 | puts "usage: cat somefile | egrep 'some'"
3 | exit
4 | end
5 |
6 | regx = Regex.new(ARGV[0])
7 | while str = STDIN.gets
8 | STDOUT.print(str) if str =~ regx
9 | end
10 |
--------------------------------------------------------------------------------
/spec/compiler/normalize/until_spec.cr:
--------------------------------------------------------------------------------
1 | require "../../spec_helper"
2 |
3 | describe "Normalize: until" do
4 | it "normalizes until" do
5 | assert_normalize "until 1; 2; end", "while !1\n 2\nend"
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/src/compiler/crystal/tools/doc.cr:
--------------------------------------------------------------------------------
1 | require "markdown"
2 |
3 | module Crystal
4 | def self.generate_docs(program, base_dirs)
5 | generator = Doc::Generator.new(program, base_dirs)
6 | generator.run
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/src/compiler/crystal/tools/doc/item.cr:
--------------------------------------------------------------------------------
1 | module Crystal::Doc::Item
2 | def formatted_doc
3 | @generator.doc(self)
4 | end
5 |
6 | def formatted_summary
7 | @generator.summary(self)
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/src/io/error.cr:
--------------------------------------------------------------------------------
1 | module IO
2 | class Error < Exception
3 | end
4 |
5 | class EOFError < Error
6 | def initialize(message = "end of file reached")
7 | super(message)
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/spec/compiler/normalize/unless_spec.cr:
--------------------------------------------------------------------------------
1 | require "../../spec_helper"
2 |
3 | describe "Normalize: unless" do
4 | it "normalizes unless" do
5 | assert_normalize "unless 1; 2; end", "if 1\nelse\n 2\nend"
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/src/llvm/context.cr:
--------------------------------------------------------------------------------
1 | class LLVM::Context
2 | def initialize(@unwrap)
3 | end
4 |
5 | def self.global
6 | new LibLLVM.get_global_context
7 | end
8 |
9 | def to_unsafe
10 | @unwrap
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | /.tags
3 | /.tags_sorted_by_file
4 | /.vagrant
5 | .crystal/
6 | coverage/
7 | /deps/
8 | /.build/
9 | .*.swp
10 | /Makefile.local
11 | all_spec
12 | /tmp
13 | /doc/
14 | /src/llvm/ext/llvm_ext.o
15 |
--------------------------------------------------------------------------------
/src/compiler/crystal/tools/init/template/example_spec.cr.ecr:
--------------------------------------------------------------------------------
1 | require "./spec_helper"
2 |
3 | describe <%= module_name %> do
4 | # TODO: Write tests
5 |
6 | it "works" do
7 | false.should eq(true)
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/samples/http_server.cr:
--------------------------------------------------------------------------------
1 | require "http/server"
2 |
3 | server = HTTP::Server.new "0.0.0.0", 8080 do |request|
4 | HTTP::Response.ok "text/plain", "Hello world!"
5 | end
6 |
7 | puts "Listening on http://0.0.0.0:8080"
8 | server.listen
9 |
--------------------------------------------------------------------------------
/spec/std/crypto/md5_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 | require "crypto/md5"
3 |
4 | describe "MD5" do
5 | it "calculates hash from string" do
6 | Crypto::MD5.hex_digest("foo").should eq("acbd18db4cc2f85cedef654fccc4a4d8")
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/spec/std/uint_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 |
3 | describe "UInt" do
4 | it "compares with <=>" do
5 | (1_u32 <=> 0_u32).should eq(1)
6 | (0_u32 <=> 0_u32).should eq(0)
7 | (0_u32 <=> 1_u32).should eq(-1)
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/src/empty.cr:
--------------------------------------------------------------------------------
1 | lib LibCrystalMain
2 | @[Raises]
3 | fun __crystal_main(argc : Int32, argv : UInt8**)
4 | end
5 |
6 | fun main(argc : Int32, argv : UInt8**) : Int32
7 | LibCrystalMain.__crystal_main(argc, argv)
8 | 0
9 | end
10 |
--------------------------------------------------------------------------------
/samples/tcp_client.cr:
--------------------------------------------------------------------------------
1 | require "socket"
2 |
3 | # goes with tcp_server.cr
4 |
5 | socket = TCPSocket.new "127.0.0.1", 9000
6 | 10.times do |i|
7 | socket.puts "#{i}"
8 | puts "server response #{socket.gets}"
9 | sleep 0.5
10 | end
11 |
--------------------------------------------------------------------------------
/src/ecr/macros.cr:
--------------------------------------------------------------------------------
1 | macro embed_ecr(filename, io_name)
2 | \{{ run("ecr/process", {{filename}}, {{io_name}}) }}
3 | end
4 |
5 | macro ecr_file(filename)
6 | def to_s(__io__)
7 | embed_ecr {{filename}}, "__io__"
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/src/box.cr:
--------------------------------------------------------------------------------
1 | class Box(T)
2 | getter object
3 |
4 | def initialize(@object : T)
5 | end
6 |
7 | def self.box(object)
8 | new(object) as Void*
9 | end
10 |
11 | def self.unbox(pointer : Void*)
12 | (pointer as self).object
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/spec/std/concurrent_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 |
3 | describe "concurrent" do
4 | it "does three things concurrently" do
5 | a, b, c = parallel(1 + 2, "hello".size, [1, 2, 3, 4].size)
6 | a.should eq(3)
7 | b.should eq(5)
8 | c.should eq(4)
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/spec/std/double_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 |
3 | describe "Double" do
4 | describe "**" do
5 | assert { (2.5 ** 2).should eq(6.25) }
6 | assert { (2.5 ** 2.5_f32).should eq(9.882117688026186) }
7 | assert { (2.5 ** 2.5).should eq(9.882117688026186) }
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/src/compiler/crystal/tools/init/template/gitignore.ecr:
--------------------------------------------------------------------------------
1 | /doc/
2 | /libs/
3 | /.crystal/
4 | /.shards/
5 |
6 | <% if config.skeleton_type == "lib" %>
7 | # Libraries don't need dependency lock
8 | # Dependencies will be locked in application that uses them
9 | /shard.lock
10 | <% end %>
11 |
--------------------------------------------------------------------------------
/src/http/server/handlers/error_handler.cr:
--------------------------------------------------------------------------------
1 | class HTTP::ErrorHandler < HTTP::Handler
2 | def call(request)
3 | begin
4 | call_next(request)
5 | rescue ex : Exception
6 | Response.error("text/plain", "ERROR: #{ex.inspect_with_backtrace}\n")
7 | end
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/src/xml/attribute_type.cr:
--------------------------------------------------------------------------------
1 | enum XML::AttributeType
2 | CDATA = 1
3 | ID = 2
4 | IDREF = 3
5 | IDREFS = 4
6 | ENTITY = 5
7 | ENTITIES = 6
8 | NMTOKEN = 7
9 | NMTOKENS = 8
10 | ENUMERATION = 9
11 | NOTATION = 10
12 | end
13 |
--------------------------------------------------------------------------------
/samples/mandelbrot2.cr:
--------------------------------------------------------------------------------
1 | require "complex"
2 |
3 | def mandelbrot(a)
4 | Iterator.of(a).take(100).inject(a) { |z, c| z*z + c }
5 | end
6 |
7 | (1.0).step(-1, -0.05) do |y|
8 | (-2.0).step(0.5, 0.0315) do |x|
9 | print mandelbrot(x + y.i).abs < 2 ? '*' : ' '
10 | end
11 | puts
12 | end
13 |
--------------------------------------------------------------------------------
/src/llvm/basic_block.cr:
--------------------------------------------------------------------------------
1 | struct LLVM::BasicBlock
2 | def initialize(@unwrap)
3 | end
4 |
5 | def instructions
6 | InstructionCollection.new self
7 | end
8 |
9 | def delete
10 | LibLLVM.delete_basic_block self
11 | end
12 |
13 | def to_unsafe
14 | @unwrap
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/src/compiler/crystal/tools/doc/html/other_types.html:
--------------------------------------------------------------------------------
1 | <% unless other_types.empty? %>
2 |
<%= title %>
3 |
4 | <% other_types.each_with_index do |other_type, i| %>
5 | - <%= other_type.link_from(type) %>
6 | <% end %>
7 |
8 | <% end %>
9 |
--------------------------------------------------------------------------------
/spec/compiler/codegen/until_spec.cr:
--------------------------------------------------------------------------------
1 | require "../../spec_helper"
2 |
3 | describe "Codegen: until" do
4 | it "codegens until" do
5 | run(%(
6 | require "bool"
7 |
8 | a = 1
9 | until a == 10
10 | a = a + 1
11 | end
12 | a
13 | )).to_i.should eq(10)
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/src/openssl/md5.cr:
--------------------------------------------------------------------------------
1 | require "./lib_crypto"
2 |
3 | class OpenSSL::MD5
4 | def self.hash(data : String)
5 | hash(data.cstr, data.bytesize)
6 | end
7 |
8 | def self.hash(data : UInt8*, bytesize : Int)
9 | buffer :: UInt8[16]
10 | LibCrypto.md5(data, bytesize, buffer)
11 | buffer
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/src/gc.cr:
--------------------------------------------------------------------------------
1 | module GC
2 | def self.malloc(size : Int)
3 | __crystal_malloc(size.to_u32)
4 | end
5 |
6 | def self.malloc_atomic(size : Int)
7 | __crystal_malloc_atomic(size.to_u32)
8 | end
9 |
10 | def self.realloc(pointer : Void*, size : Int)
11 | __crystal_realloc(pointer, size.to_u32)
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/spec/compiler/normalize/range_literal_spec.cr:
--------------------------------------------------------------------------------
1 | require "../../spec_helper"
2 |
3 | describe "Normalize: range literal" do
4 | it "normalizes not exclusive" do
5 | assert_expand "1..2", "::Range.new(1, 2, false)"
6 | end
7 |
8 | it "normalizes exclusive" do
9 | assert_expand "1...2", "::Range.new(1, 2, true)"
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/src/openssl/sha1.cr:
--------------------------------------------------------------------------------
1 | require "./lib_crypto"
2 |
3 | class OpenSSL::SHA1
4 | def self.hash(data : String)
5 | hash(data.cstr, LibC::SizeT.new(data.bytesize))
6 | end
7 |
8 | def self.hash(data : UInt8*, bytesize : LibC::SizeT)
9 | buffer :: UInt8[20]
10 | LibCrypto.sha1(data, bytesize, buffer)
11 | buffer
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/spec/std/data/test_file.txt:
--------------------------------------------------------------------------------
1 | Hello World
2 | Hello World
3 | Hello World
4 | Hello World
5 | Hello World
6 | Hello World
7 | Hello World
8 | Hello World
9 | Hello World
10 | Hello World
11 | Hello World
12 | Hello World
13 | Hello World
14 | Hello World
15 | Hello World
16 | Hello World
17 | Hello World
18 | Hello World
19 | Hello World
20 | Hello World
21 |
--------------------------------------------------------------------------------
/spec/std/oauth/params_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 | require "oauth"
3 |
4 | describe OAuth::Params do
5 | it "builds" do
6 | params = OAuth::Params.new
7 | params.add "foo", "value1"
8 | params.add "bar", "a+b"
9 | params.add "a=", "=/="
10 | params.to_s.should eq("a%253D%3D%253D%252F%253D%26bar%3Da%252Bb%26foo%3Dvalue1")
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/spec/std/oauth/authorization_header_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 | require "oauth"
3 |
4 | describe OAuth::AuthorizationHeader do
5 | it "builds" do
6 | params = OAuth::AuthorizationHeader.new
7 | params.add "foo", "value1"
8 | params.add "bar", "a+b"
9 | params.add "baz", "=/="
10 | params.to_s.should eq(%(OAuth foo="value1", bar="a%2Bb", baz="%3D%2F%3D"))
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/src/llvm/basic_block_collection.cr:
--------------------------------------------------------------------------------
1 | struct LLVM::BasicBlockCollection
2 | def initialize(@function)
3 | end
4 |
5 | def append(name = "")
6 | BasicBlock.new LibLLVM.append_basic_block(@function, name)
7 | end
8 |
9 | def append(name = "")
10 | block = append name
11 | builder = Builder.new
12 | builder.position_at_end block
13 | yield builder
14 | block
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/src/compiler/crystal/config.cr:
--------------------------------------------------------------------------------
1 | module Crystal
2 | module Config
3 | PATH = {{ env("CRYSTAL_CONFIG_PATH") || "" }}
4 | VERSION = {{ env("CRYSTAL_CONFIG_VERSION") || `(git describe --tags --long 2>/dev/null)`.stringify.chomp }}
5 | CACHE_DIR = ENV["CRYSTAL_CACHE_DIR"]? || ".crystal"
6 |
7 | def self.cache_dir
8 | @@cache_dir ||= File.expand_path(CACHE_DIR)
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/src/openssl/pkcs5.cr:
--------------------------------------------------------------------------------
1 | require "./openssl"
2 |
3 | module OpenSSL::PKCS5
4 | def self.pbkdf2_hmac_sha1(secret, salt, iterations = 2**16, key_size = 64)
5 | buffer = Slice(UInt8).new(key_size)
6 | if LibCrypto.pkcs5_pbkdf2_hmac_sha1(secret, secret.bytesize, salt, salt.bytesize, iterations, key_size, buffer) != 1
7 | raise OpenSSL::Error.new "pkcs5_pbkdf2_hmac"
8 | end
9 | buffer
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/src/compiler/crystal/version.cr:
--------------------------------------------------------------------------------
1 | require "./config"
2 |
3 | def Crystal.version_string
4 | build_date = {{ `date -u`.stringify.chomp }}
5 | version = Crystal::Config::VERSION
6 | pieces = version.split("-")
7 | tag = pieces[0]? || "?"
8 | if sha = pieces[2]?
9 | sha = sha[1..-1] if sha.starts_with? 'g'
10 | "#{tag} [#{sha}] (#{build_date})"
11 | else
12 | "#{tag} (#{build_date})"
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/src/llvm/phi_table.cr:
--------------------------------------------------------------------------------
1 | struct LLVM::PhiTable
2 | getter blocks
3 | getter values
4 |
5 | def initialize
6 | @blocks = [] of LLVM::BasicBlock
7 | @values = [] of LLVM::Value
8 | end
9 |
10 | def add(block, value)
11 | @blocks << block
12 | @values << value.to_value
13 | end
14 |
15 | def empty?
16 | @blocks.empty?
17 | end
18 |
19 | def size
20 | @blocks.size
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/src/crypto/subtle.cr:
--------------------------------------------------------------------------------
1 | module Crypto::Subtle
2 | def self.constant_time_compare(x, y)
3 | return 0 if x.size != y.size
4 |
5 | v = 0_u8
6 |
7 | x.size.times do |i|
8 | v |= x[i] ^ y[i]
9 | end
10 |
11 | constant_time_byte_eq(v, 0)
12 | end
13 |
14 | def self.constant_time_byte_eq(x, y)
15 | z = ~(x ^ y)
16 | z &= z >> 4
17 | z &= z >> 2
18 | z &= z >> 1
19 | z
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/src/llvm/instruction_collection.cr:
--------------------------------------------------------------------------------
1 | struct LLVM::InstructionCollection
2 | def initialize(@basic_block)
3 | end
4 |
5 | def empty?
6 | llvm_first.nil?
7 | end
8 |
9 | def first?
10 | value = llvm_first
11 | value ? Value.new(value) : nil
12 | end
13 |
14 | def first
15 | first?.not_nil!
16 | end
17 |
18 | private def llvm_first
19 | LibLLVM.get_first_instruction @basic_block
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/samples/sieve.cr:
--------------------------------------------------------------------------------
1 | # Compute prime numbers up to 100 with the Sieve of Eratosthenes
2 | max = 100
3 |
4 | sieve = Array.new(max + 1, true)
5 | sieve[0] = false
6 | sieve[1] = false
7 |
8 | 2.step(Math.sqrt(max)) do |i|
9 | if sieve[i]
10 | (i * i).step(max, i) do |j|
11 | sieve[j] = false
12 | end
13 | end
14 | end
15 |
16 | sieve.each_with_index do |prime, number|
17 | if prime
18 | puts number
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/spec/std/html_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 | require "html"
3 |
4 | describe "HTML" do
5 | describe ".escape" do
6 | it "does not change a safe string" do
7 | str = HTML.escape("safe_string")
8 |
9 | str.should eq("safe_string")
10 | end
11 |
12 | it "escapes dangerous characters from a string" do
13 | str = HTML.escape("< & >")
14 |
15 | str.should eq("< & >")
16 | end
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/src/json/lexer/io_based.cr:
--------------------------------------------------------------------------------
1 | # :nodoc:
2 | class JSON::Lexer::IOBased < JSON::Lexer
3 | def initialize(io)
4 | super()
5 | @io = io
6 | @current_char = @io.read_char || '\0'
7 | end
8 |
9 | private getter current_char
10 |
11 | private def next_char_no_column_increment
12 | @current_char = @io.read_char || '\0'
13 | end
14 |
15 | private def consume_string
16 | consume_string_with_buffer
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/src/reflect.cr:
--------------------------------------------------------------------------------
1 | # # :nodoc:
2 | struct Reflect(X)
3 | # Note: This type might be removed.
4 | #
5 | # For now it's just a way to implement `Enumerable#sum` in a way that the
6 | # initial value given to it has the type of the first type in the union,
7 | # if the type is a union.
8 | def self.first
9 | {% if X.union? %}
10 | {{X.union_types.first}}
11 | {% else %}
12 | X
13 | {% end %}
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/src/fiber/lib_pcl.cr:
--------------------------------------------------------------------------------
1 | @[Link("pcl")]
2 | lib LibPcl
3 | alias Int = LibC::Int
4 |
5 | type Coroutine = Void*
6 |
7 | fun co_thread_init : Int
8 | fun co_create(func : (Void* ->), data : Void*, stack : Void*, size : Int) : Coroutine
9 | fun co_call(cr : Coroutine)
10 | fun co_resume
11 | fun co_current : Coroutine
12 | fun co_get_data(cr : Coroutine) : Void*
13 | fun co_set_data(cr : Coroutine, data : Void*) : Void*
14 | end
15 |
--------------------------------------------------------------------------------
/src/html.cr:
--------------------------------------------------------------------------------
1 | module HTML
2 | SUBSTITUTIONS = {
3 | '&' => "&",
4 | '\"' => """,
5 | '\'' => "'",
6 | '<' => "<",
7 | '>' => ">",
8 | }
9 |
10 | def self.escape(string : String)
11 | string.gsub(SUBSTITUTIONS)
12 | end
13 |
14 | def self.escape(string : String, io : IO)
15 | string.each_char do |char|
16 | io << SUBSTITUTIONS.fetch(char, char)
17 | end
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/Dockerfile.release:
--------------------------------------------------------------------------------
1 | FROM ubuntu:14.04
2 |
3 | RUN \
4 | apt-key adv --keyserver keys.gnupg.net --recv-keys 09617FD37CC06B54 && \
5 | echo "deb http://dist.crystal-lang.org/apt crystal main" > /etc/apt/sources.list.d/crystal.list && \
6 | apt-get update && \
7 | apt-get install -y crystal gcc pkg-config libssl-dev && \
8 | apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
9 |
10 | WORKDIR /opt/crystal
11 |
12 | CMD ["bash"]
13 |
--------------------------------------------------------------------------------
/src/csv/error.cr:
--------------------------------------------------------------------------------
1 | class CSV
2 | # Raises when an error related to a CSV is found
3 | class Error < Exception
4 | end
5 |
6 | # Raised when an error is encountered during CSV parsing.
7 | class MalformedCSVError < Error
8 | getter line_number
9 | getter column_number
10 |
11 | def initialize(message, @line_number, @column_number)
12 | super("#{message} at #{@line_number}:#{@column_number}")
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/spec/std/file_utils_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 | require "file_utils"
3 |
4 | describe "FileUtils" do
5 | describe "cmp" do
6 | it "compares two equal files" do
7 | FileUtils.cmp("#{__DIR__}/data/test_file.txt", "#{__DIR__}/data/test_file.txt").should be_true
8 | end
9 |
10 | it "compares two different files" do
11 | FileUtils.cmp("#{__DIR__}/data/test_file.txt", "#{__DIR__}/data/test_file.ini").should be_false
12 | end
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/src/io/pointer_io.cr:
--------------------------------------------------------------------------------
1 | struct PointerIO
2 | include IO
3 |
4 | def initialize(@pointer : UInt8**)
5 | end
6 |
7 | def read(slice : Slice(UInt8))
8 | count = slice.size
9 | slice.copy_from(@pointer.value, count)
10 | @pointer.value += count
11 | count
12 | end
13 |
14 | def write(slice : Slice(UInt8))
15 | count = slice.size
16 | slice.copy_to(@pointer.value, count)
17 | @pointer.value += count
18 | nil
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/src/llvm/module_pass_manager.cr:
--------------------------------------------------------------------------------
1 | class LLVM::ModulePassManager
2 | def initialize
3 | @unwrap = LibLLVM.pass_manager_create
4 | end
5 |
6 | def add_target_data(target_data)
7 | LibLLVM.add_target_data target_data, self
8 | end
9 |
10 | def run(mod)
11 | LibLLVM.run_pass_manager(self, mod) != 0
12 | end
13 |
14 | def to_unsafe
15 | @unwrap
16 | end
17 |
18 | def finalize
19 | LibLLVM.dispose_pass_manager(@unwrap)
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/src/compiler/crystal/tools/doc/constant.cr:
--------------------------------------------------------------------------------
1 | require "./item"
2 |
3 | class Crystal::Doc::Constant
4 | include Item
5 |
6 | getter type
7 | getter const
8 |
9 | def initialize(@generator, @type : Type, @const)
10 | end
11 |
12 | def doc
13 | @const.doc
14 | end
15 |
16 | def name
17 | @const.name
18 | end
19 |
20 | def value
21 | @const.value
22 | end
23 |
24 | def formatted_value
25 | Highlighter.highlight value.to_s
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/spec/std/oauth2/session_spec.cr:
--------------------------------------------------------------------------------
1 | require "oauth2"
2 | require "http/client"
3 |
4 | module OAuth2
5 | typeof(begin
6 | client = Client.new "localhost", "client_id", "client_secret", redirect_uri: "uri", authorize_uri: "/baz"
7 | token = OAuth2::AccessToken::Bearer.new("token", 3600)
8 | session = Session.new(client, token) { |s| }
9 | session = Session.new(client, token, Time.new) { |s| }
10 | session.authenticate(HTTP::Client.new("localhost"))
11 | end)
12 | end
13 |
--------------------------------------------------------------------------------
/src/csv/token.cr:
--------------------------------------------------------------------------------
1 | # A token in a CSV. It consists of a `Kind` and a value.
2 | # The value only makes sense when the *kind* is `Cell`.
3 | struct CSV::Token
4 | # Token kinds.
5 | enum Kind
6 | Cell
7 | Newline
8 | Eof
9 | end
10 |
11 | # The `Kind`.
12 | property kind
13 |
14 | # The string value. Only makes sense for a `Cell`.
15 | property value
16 |
17 | # :nodoc:
18 | def initialize
19 | @kind = Kind::Cell
20 | @value = ""
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/src/inifile.cr:
--------------------------------------------------------------------------------
1 | class IniFile
2 | def self.load(str)
3 | ini = {} of String => Hash(String, String)
4 |
5 | section = ""
6 | str.lines.each do |line|
7 | if line =~ /\s*(.*[^\s])\s*=\s*(.*[^\s])/
8 | ini[section] ||= {} of String => String if section == ""
9 | ini[section][$1] = $2
10 | elsif line =~ /\[(.*)\]/
11 | section = $1
12 | ini[section] = {} of String => String
13 | end
14 | end
15 | ini
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/src/compiler/crystal/codegen/target_machine.cr:
--------------------------------------------------------------------------------
1 | require "llvm"
2 | require "../program"
3 |
4 | module Crystal
5 | module TargetMachine
6 | def self.create(target_triple, cpu, release)
7 | LLVM.init_x86
8 |
9 | opt_level = release ? LLVM::CodeGenOptLevel::Aggressive : LLVM::CodeGenOptLevel::None
10 |
11 | target = LLVM::Target.from_triple(target_triple)
12 | target.create_target_machine(target_triple, cpu: cpu, opt_level: opt_level).not_nil!
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/src/llvm/global_collection.cr:
--------------------------------------------------------------------------------
1 | struct LLVM::GlobalCollection
2 | def initialize(@mod)
3 | end
4 |
5 | def add(type, name)
6 | Value.new LibLLVM.add_global(@mod, type, name)
7 | end
8 |
9 | def []?(name)
10 | global = LibLLVM.get_named_global(@mod, name)
11 | global ? Value.new(global) : nil
12 | end
13 |
14 | def [](name)
15 | global = self[name]?
16 | if global
17 | global
18 | else
19 | raise "Global not found: #{name}"
20 | end
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/spec/std/zlib/deflate_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 | require "zlib"
3 |
4 | module Zlib
5 | describe Deflate do
6 | it "should be able to deflate" do
7 | deflate = Deflate.new(MemoryIO.new("this is a test string !!!!\n"))
8 | slice = Slice(UInt8).new(32)
9 | read = deflate.read_fully(slice)
10 |
11 | slice[0, read.to_i32].hexstring.should eq("789c2bc9c82c5600a2448592d4e21285e292a2ccbc74054520e00200854f087b")
12 | deflate.read(slice).should eq(0)
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/src/main.cr:
--------------------------------------------------------------------------------
1 | lib LibCrystalMain
2 | @[Raises]
3 | fun __crystal_main(argc : Int32, argv : UInt8**)
4 | end
5 |
6 | macro redefine_main(name = main)
7 | fun main = {{name}}(argc : Int32, argv : UInt8**) : Int32
8 | GC.init
9 | {{yield LibCrystalMain.__crystal_main(argc, argv)}}
10 | 0
11 | rescue ex
12 | ex.inspect_with_backtrace STDERR
13 | 1
14 | ensure
15 | AtExitHandlers.run
16 | STDOUT.flush
17 | end
18 | end
19 |
20 | redefine_main do |main|
21 | {{main}}
22 | end
23 |
--------------------------------------------------------------------------------
/src/oauth/request_token.cr:
--------------------------------------------------------------------------------
1 | class OAuth::RequestToken
2 | getter token
3 | getter secret
4 |
5 | def initialize(@token, @secret)
6 | end
7 |
8 | def self.from_response(response)
9 | token = nil
10 | secret = nil
11 |
12 | HTTP::Params.parse(response) do |key, value|
13 | case key
14 | when "oauth_token" then token = value
15 | when "oauth_token_secret" then secret = value
16 | end
17 | end
18 |
19 | new token.not_nil!, secret.not_nil!
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/spec/std/oauth/request_token_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 | require "oauth"
3 |
4 | describe OAuth::RequestToken do
5 | it "creates from response" do
6 | token = OAuth::RequestToken.from_response("oauth_token_secret=p58A6bzyGaT8PR54gM0S4ZesOVC2ManiTmwHcho8&oauth_callback_confirmed=true&oauth_token=qyprd6Pe2PbnSxUcyHcWz0VnTF8bg1rxsBbUwOpkQ6bSQEyK")
7 | token.secret.should eq("p58A6bzyGaT8PR54gM0S4ZesOVC2ManiTmwHcho8")
8 | token.token.should eq("qyprd6Pe2PbnSxUcyHcWz0VnTF8bg1rxsBbUwOpkQ6bSQEyK")
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/spec/compiler/normalize/string_interpolation_spec.cr:
--------------------------------------------------------------------------------
1 | require "../../spec_helper"
2 |
3 | describe "Normalize: string interpolation" do
4 | it "normalizes string interpolation" do
5 | assert_expand "\"foo\#{bar}baz\"", "(((::String::Builder.new << \"foo\") << bar) << \"baz\").to_s"
6 | end
7 |
8 | it "normalizes string interpolation with long string" do
9 | s = "*" * 200
10 | assert_expand "\"foo\#{bar}#{s}\"",
11 | "((((::String::Builder.new(218)) << \"foo\") << bar) << \"#{s}\").to_s"
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/spec/std/string_builder_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 |
3 | describe String::Builder do
4 | it "builds" do
5 | str = String::Builder.build do |builder|
6 | builder << 123
7 | builder << 456
8 | end
9 | str.should eq("123456")
10 | str.size.should eq(6)
11 | str.bytesize.should eq(6)
12 | end
13 |
14 | it "raises if invokes to_s twice" do
15 | builder = String::Builder.new
16 | builder << 123
17 | builder.to_s.should eq("123")
18 |
19 | expect_raises { builder.to_s }
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/src/oauth/authorization_header.cr:
--------------------------------------------------------------------------------
1 | # :nodoc:
2 | struct OAuth::AuthorizationHeader
3 | def initialize
4 | @str = MemoryIO.new
5 | @str << "OAuth "
6 | @first = true
7 | end
8 |
9 | def add(key, value)
10 | return unless value
11 |
12 | @str << ", " unless @first
13 | @str << key
14 | @str << %(=")
15 | URI.escape value, @str
16 | @str << '"'
17 | @first = false
18 | end
19 |
20 | def to_s(io : IO)
21 | @str.to_s(io)
22 | end
23 |
24 | def to_s
25 | @str.to_s
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/spec/std/struct_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 |
3 | struct StructSpecTestClass
4 | def initialize(@x, @y)
5 | end
6 | end
7 |
8 | describe "Struct" do
9 | it "does to_s" do
10 | s = StructSpecTestClass.new(1, "hello")
11 | s.to_s.should eq(%(StructSpecTestClass(@x=1, @y="hello")))
12 | end
13 |
14 | it "does ==" do
15 | s = StructSpecTestClass.new(1, "hello")
16 | s.should eq(s)
17 | end
18 |
19 | it "does hash" do
20 | s = StructSpecTestClass.new(1, "hello")
21 | s.hash.should eq(31 + "hello".hash)
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/src/compiler/crystal/tools/doc/html/method_summary.html:
--------------------------------------------------------------------------------
1 | <% unless methods.empty? %>
2 | <%= title %>
3 |
13 | <% end %>
14 |
--------------------------------------------------------------------------------
/src/spec/source.cr:
--------------------------------------------------------------------------------
1 | module Spec
2 | # :nodoc:
3 | def self.lines_cache
4 | @@lines_cache ||= {} of String => Array(String)
5 | end
6 |
7 | # :nodoc:
8 | def self.read_line(file, line)
9 | return nil unless File.file?(file)
10 |
11 | lines = lines_cache[file] ||= File.read_lines(file)
12 | lines[line - 1]?
13 | end
14 |
15 | # :nodoc:
16 | def self.relative_file(file)
17 | cwd = Dir.working_directory
18 | if file.starts_with?(cwd)
19 | file = ".#{file[cwd.size..-1]}"
20 | end
21 | file
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/samples/tcp_server.cr:
--------------------------------------------------------------------------------
1 | require "socket"
2 |
3 | # goes with tcp_client.cr
4 |
5 | def process(client)
6 | client_addr = "#{client.peeraddr.ip_address}:#{client.peeraddr.ip_port}"
7 | puts "#{client_addr} connected"
8 |
9 | while msg = client.read_line
10 | puts "#{client_addr} msg '#{msg.chop}'"
11 | client << msg
12 | end
13 | rescue IO::EOFError
14 | puts "#{client_addr} dissconnected"
15 | ensure
16 | client.close
17 | end
18 |
19 | server = TCPServer.new "127.0.0.1", 9000
20 | puts "listen on 127.0.0.1:9000"
21 | loop { spawn process(server.accept) }
22 |
--------------------------------------------------------------------------------
/src/compiler/crystal/macros/virtual_file.cr:
--------------------------------------------------------------------------------
1 | # A VirtualFile is used as a Location's filename when
2 | # expanding a macro. It contains the macro expanded source
3 | # code so the user can debug it as if there was a file in the
4 | # filesystem with those contents.
5 | class Crystal::VirtualFile
6 | getter :macro
7 | getter :source
8 | getter :expanded_location
9 |
10 | def initialize(@macro, @source, @expanded_location)
11 | end
12 |
13 | def to_s
14 | "expanded macro: #{@macro.name}"
15 | end
16 |
17 | def to_s(io)
18 | io << to_s
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/src/thread/mutex.cr:
--------------------------------------------------------------------------------
1 | class Mutex
2 | def initialize
3 | LibPThread.mutex_init(out @mutex, nil)
4 | end
5 |
6 | def lock
7 | LibPThread.mutex_lock(self)
8 | end
9 |
10 | def try_lock
11 | LibPThread.mutex_trylock(self)
12 | end
13 |
14 | def unlock
15 | LibPThread.mutex_unlock(self)
16 | end
17 |
18 | def synchronize
19 | lock
20 | yield self
21 | ensure
22 | unlock
23 | end
24 |
25 | def finalize
26 | LibPThread.mutex_destroy(self)
27 | end
28 |
29 | def to_unsafe
30 | pointerof(@mutex)
31 | end
32 | end
33 |
--------------------------------------------------------------------------------
/spec/compiler/type_inference/c_type_spec.cr:
--------------------------------------------------------------------------------
1 | require "../../spec_helper"
2 |
3 | describe "Type inference: type" do
4 | it "can call methods of original type" do
5 | assert_type("
6 | lib Lib
7 | type X = Void*
8 | fun foo : X
9 | end
10 |
11 | Lib.foo.address
12 | ") { uint64 }
13 | end
14 |
15 | it "can call methods of parent type" do
16 | assert_error("
17 | lib Lib
18 | type X = Void*
19 | fun foo : X
20 | end
21 |
22 | Lib.foo.baz
23 | ", "undefined method 'baz'")
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/spec/compiler/normalize/ifdef_spec.cr:
--------------------------------------------------------------------------------
1 | require "../../spec_helper"
2 |
3 | describe "Normalize: ifdef" do
4 | it "keeps then if condition is true" do
5 | assert_normalize "ifdef foo; 1; else; 2; end", "1", flags: "foo"
6 | end
7 |
8 | it "keeps else if condition is false" do
9 | assert_normalize "ifdef bar; 1; else; 2; end", "2", flags: "foo"
10 | end
11 |
12 | it "keeps then if condition is true inside lib" do
13 | assert_normalize "lib LibFoo; ifdef foo; type A = B; else; type A = D; end; end", "lib LibFoo\n type A = B\nend", flags: "foo"
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/src/io/fd_set.cr:
--------------------------------------------------------------------------------
1 | # :nodoc:
2 | struct IO::FdSet
3 | NFDBITS = sizeof(Int32) * 8
4 |
5 | def self.from_ios(ios)
6 | fdset = new
7 | ios.try &.each do |io|
8 | fdset.set io
9 | end
10 | fdset
11 | end
12 |
13 | def initialize
14 | @fdset = StaticArray(Int32, 32).new(0)
15 | end
16 |
17 | def set(io)
18 | @fdset[io.fd / NFDBITS] |= 1 << (io.fd % NFDBITS)
19 | end
20 |
21 | def is_set(io)
22 | @fdset[io.fd / NFDBITS] & 1 << (io.fd % NFDBITS) != 0
23 | end
24 |
25 | def to_unsafe
26 | pointerof(@fdset) as Void*
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/spec/std/oauth/access_token_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 | require "oauth"
3 |
4 | describe OAuth::AccessToken do
5 | it "creates from response body" do
6 | access_token = OAuth::AccessToken.from_response("oauth_token=1234-nyi1G37179bVdYNZGZqKQEdO&oauth_token_secret=f7T6ibH25q4qkVTAUN&user_id=1234&screen_name=someuser")
7 | access_token.token.should eq("1234-nyi1G37179bVdYNZGZqKQEdO")
8 | access_token.secret.should eq("f7T6ibH25q4qkVTAUN")
9 | access_token.extra["user_id"].should eq("1234")
10 | access_token.extra["screen_name"].should eq("someuser")
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/spec/compiler/normalize/array_literal_spec.cr:
--------------------------------------------------------------------------------
1 | require "../../spec_helper"
2 |
3 | describe "Normalize: array literal" do
4 | it "normalizes empty with of" do
5 | assert_expand "[] of Int", "::Array(Int).new"
6 | end
7 |
8 | it "normalizes non-empty with of" do
9 | assert_expand "[1, 2] of Int", "::Array(Int).build(2) do |__temp_1|\n __temp_1[0] = 1\n __temp_1[1] = 2\n 2\nend"
10 | end
11 |
12 | it "normalizes non-empty without of" do
13 | assert_expand "[1, 2]", "::Array(typeof(1, 2)).build(2) do |__temp_1|\n __temp_1[0] = 1\n __temp_1[1] = 2\n 2\nend"
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/src/compiler/crystal/tools/doc/html/list_items.html:
--------------------------------------------------------------------------------
1 |
2 | <% types.each do |type| %>
3 | - <%= type.current?(current_type) ? "current" : "" %>" data-id="<%= type.html_id %>" data-name="<%= type.full_name.downcase %>">
4 | <%= type.name %>
5 | <% unless type.program? || type.types.empty? %>
6 | <%= ListItemsTemplate.new(type.types, current_type) %>
7 | <% end %>
8 |
9 | <% end %>
10 |
11 |
--------------------------------------------------------------------------------
/src/openssl/ssl/context.cr:
--------------------------------------------------------------------------------
1 | class OpenSSL::SSL::Context
2 | def self.default
3 | @@default ||= new
4 | end
5 |
6 | def initialize
7 | @handle = LibSSL.ssl_ctx_new(LibSSL.sslv23_method)
8 | end
9 |
10 | def finalize
11 | LibSSL.ssl_ctx_free(@handle)
12 | end
13 |
14 | def certificate_chain=(file_path)
15 | LibSSL.ssl_ctx_use_certificate_chain_file(@handle, file_path)
16 | end
17 |
18 | def private_key=(file_path)
19 | LibSSL.ssl_ctx_use_privatekey_file(@handle, file_path, LibSSL::SSLFileType::PEM)
20 | end
21 |
22 | def to_unsafe
23 | @handle
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/spec/std/openssl/pkcs5_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 | require "openssl/pkcs5"
3 |
4 | describe OpenSSL::PKCS5 do
5 | it "computes pbkdf2_hmac_sha1" do
6 | [
7 | {1, 16, "0c60c80f961f0e71f3a9b524af601206"},
8 | {1, 32, "0c60c80f961f0e71f3a9b524af6012062fe037a6e0f0eb94fe8fc46bdc637164"},
9 | {2**16, 16, "1b345dd55f62a35aecdb9229bc7ae95b"},
10 | {2**16, 32, "1b345dd55f62a35aecdb9229bc7ae95b305a8d538940134627e46f82d3a41e5e"}
11 | ].each do |tuple|
12 | OpenSSL::PKCS5.pbkdf2_hmac_sha1("password", "salt", tuple[0], tuple[1]).hexstring.should eq tuple[2]
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/src/xml/save_options.cr:
--------------------------------------------------------------------------------
1 | @[Flags]
2 | enum XML::SaveOptions
3 | # Format save output
4 | FORMAT = 1
5 |
6 | # Drop the xml declaration
7 | NO_DECL = 2
8 |
9 | # No empty tags
10 | NO_EMPTY = 4
11 |
12 | # Disable XHTML1 specific rules
13 | NO_XHTML = 8
14 |
15 | # Force XHTML1 specific rules
16 | XHTML = 16
17 |
18 | # Force XML serialization on HTML doc
19 | AS_XML = 32
20 |
21 | # Force HTML serialization on XML doc
22 | AS_HTML = 64
23 |
24 | # Format with non-significant whitespace
25 | WSNONSIG = 128
26 |
27 | def self.xml_default
28 | FORMAT | AS_XML
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/spec/compiler/codegen/untyped_expression_spec.cr:
--------------------------------------------------------------------------------
1 | require "../../spec_helper"
2 |
3 | describe "Code gen: untyped expression spec" do
4 | it "raises if class was never instantiated" do
5 | run(%(
6 | require "prelude"
7 |
8 | class Foo
9 | def foo
10 | 1
11 | end
12 | end
13 |
14 | pointer = Pointer(Foo).malloc(1_64)
15 | foo = pointer.value
16 |
17 | begin
18 | foo.foo
19 | false
20 | rescue ex
21 | ex.message.includes?("Foo in `foo` was never instantiated")
22 | end
23 | )).to_b.should be_true
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/src/intrinsics.cr:
--------------------------------------------------------------------------------
1 | lib Intrinsics
2 | fun debugtrap = "llvm.debugtrap"
3 | fun memcpy = "llvm.memcpy.p0i8.p0i8.i32"(dest : Void*, src : Void*, len : UInt32, align : UInt32, is_volatile : Bool)
4 | fun memmove = "llvm.memmove.p0i8.p0i8.i32"(dest : Void*, src : Void*, len : UInt32, align : UInt32, is_volatile : Bool)
5 | fun memset = "llvm.memset.p0i8.i32"(dest : Void*, val : UInt8, len : UInt32, align : UInt32, is_volatile : Bool)
6 | fun read_cycle_counter = "llvm.readcyclecounter" : UInt64
7 | fun bswap32 = "llvm.bswap.i32"(id : UInt32) : UInt32
8 | end
9 |
10 | macro debugger
11 | Intrinsics.debugtrap
12 | end
13 |
--------------------------------------------------------------------------------
/docs/char.cr:
--------------------------------------------------------------------------------
1 | struct Char
2 | # Returns the codepoint of this char.
3 | #
4 | # The codepoint is the integer
5 | # representation. The Universal Coded Character Set (UCS) standard,
6 | # commonly known as Unicode, assigns names and meanings to numbers, these
7 | # numbers are called codepoints.
8 | #
9 | # For values below and including 127 this matches the ASCII codes
10 | # and thus its byte representation.
11 | #
12 | # ```
13 | # 'a'.ord # => 97
14 | # '\0'.ord # => 0
15 | # '\u007f'.ord # => 127
16 | # '☃'.ord # => 9731
17 | # ```
18 | def ord : Int32
19 | 1
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/src/llvm/target_data.cr:
--------------------------------------------------------------------------------
1 | struct LLVM::TargetData
2 | def initialize(@unwrap)
3 | end
4 |
5 | def size_in_bits(type)
6 | LibLLVM.size_of_type_in_bits(self, type)
7 | end
8 |
9 | def size_in_bytes(type)
10 | size_in_bits(type) / 8
11 | end
12 |
13 | def abi_size(type)
14 | LibLLVM.abi_size_of_type(self, type)
15 | end
16 |
17 | def abi_alignment(type)
18 | LibLLVM.abi_alignment_of_type(self, type)
19 | end
20 |
21 | def to_unsafe
22 | @unwrap
23 | end
24 |
25 | def offset_of_element(struct_type, element)
26 | LibLLVM.offset_of_element(self, struct_type, element)
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/spec/compiler/normalize/hash_literal_spec.cr:
--------------------------------------------------------------------------------
1 | require "../../spec_helper"
2 |
3 | describe "Normalize: hash literal" do
4 | it "normalizes empty with of" do
5 | assert_expand "{} of Int => Float", "::Hash(Int, Float).new"
6 | end
7 |
8 | it "normalizes non-empty with of" do
9 | assert_expand "{1 => 2, 3 => 4} of Int => Float", "__temp_1 = ::Hash(Int, Float).new\n__temp_1[1] = 2\n__temp_1[3] = 4\n__temp_1"
10 | end
11 |
12 | it "normalizes non-empty without of" do
13 | assert_expand "{1 => 2, 3 => 4}", "__temp_1 = ::Hash(typeof(1, 3), typeof(2, 4)).new\n__temp_1[1] = 2\n__temp_1[3] = 4\n__temp_1"
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2012-2013 Manas Technology Solutions.
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 |
--------------------------------------------------------------------------------
/src/gc/null.cr:
--------------------------------------------------------------------------------
1 | # :nodoc:
2 | fun __crystal_malloc(size : UInt32) : Void*
3 | LibC.malloc(size)
4 | end
5 |
6 | # :nodoc:
7 | fun __crystal_malloc_atomic(size : UInt32) : Void*
8 | LibC.malloc(size)
9 | end
10 |
11 | # :nodoc:
12 | fun __crystal_realloc(ptr : Void*, size : UInt32) : Void*
13 | LibC.realloc(ptr, size)
14 | end
15 |
16 | module GC
17 | def self.init
18 | end
19 |
20 | def self.collect
21 | end
22 |
23 | def self.enable
24 | end
25 |
26 | def self.disable
27 | end
28 |
29 | def self.free(pointer : Void*)
30 | LibC.free(pointer)
31 | end
32 |
33 | def self.add_finalizer(object)
34 | end
35 | end
36 |
--------------------------------------------------------------------------------
/src/oauth/params.cr:
--------------------------------------------------------------------------------
1 | # :nodoc:
2 | struct OAuth::Params
3 | def initialize
4 | @params = [] of {String, String}
5 | end
6 |
7 | def add(key, value)
8 | if value
9 | @params << {URI.escape(key), URI.escape(value)}
10 | end
11 | end
12 |
13 | def add_query(query)
14 | HTTP::Params.parse(query) do |key, value|
15 | add key, value
16 | end
17 | end
18 |
19 | def to_s(io : IO)
20 | @params.sort_by! &.[0]
21 | @params.each_with_index do |tuple, i|
22 | io << "%26" if i > 0
23 | URI.escape tuple[0], io
24 | io << "%3D"
25 | URI.escape tuple[1], io
26 | end
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/src/time/format.cr:
--------------------------------------------------------------------------------
1 | struct Time::Format
2 | ISO_8601_DATE = new "%F"
3 |
4 | class Error < ::Exception
5 | end
6 |
7 | getter pattern
8 |
9 | def initialize(@pattern : String, @kind = Time::Kind::Unspecified)
10 | end
11 |
12 | def parse(string, kind = @kind)
13 | parser = Parser.new(string)
14 | parser.visit(pattern)
15 | parser.time(kind)
16 | end
17 |
18 | def format(time : Time)
19 | String.build do |str|
20 | format time, str
21 | end
22 | end
23 |
24 | def format(time : Time, io : IO)
25 | formatter = Formatter.new(time, io)
26 | formatter.visit(pattern)
27 | io
28 | end
29 | end
30 |
--------------------------------------------------------------------------------
/samples/tree.cr:
--------------------------------------------------------------------------------
1 | class Node
2 | def initialize(v)
3 | @value = v
4 | end
5 |
6 | def add(x)
7 | if x < @value
8 | if left = @left
9 | left.add(x)
10 | else
11 | @left = Node.new(x)
12 | end
13 | else
14 | if right = @right
15 | right.add(x)
16 | else
17 | @right = Node.new(x)
18 | end
19 | end
20 | end
21 |
22 | def print
23 | @left.try &.print
24 | print @value
25 | @right.try &.print
26 | end
27 | end
28 |
29 | root = Node.new('$')
30 | "crystalrocks!".each_char do |c|
31 | root.add c
32 | end
33 |
34 | root.print # => !$accklorrssty
35 | puts
36 |
--------------------------------------------------------------------------------
/samples/channel_primes.cr:
--------------------------------------------------------------------------------
1 | # Ported from Go sample from this page: http://dancallahan.info/journal/go-concurrency/#How+do+channels+and+goroutines+work+together?
2 |
3 | def generate(chan)
4 | i = 2
5 | loop do
6 | chan.send(i)
7 | i += 1
8 | end
9 | end
10 |
11 | def filter(in_chan, out_chan, prime)
12 | loop do
13 | i = in_chan.receive
14 | if i % prime != 0
15 | out_chan.send(i)
16 | end
17 | end
18 | end
19 |
20 | ch = Channel(Int32).new
21 | spawn generate(ch)
22 |
23 | 100.times do
24 | prime = ch.receive
25 | puts prime
26 | ch1 = Channel(Int32).new
27 | spawn filter(ch, ch1, prime)
28 | ch = ch1
29 | end
30 |
--------------------------------------------------------------------------------
/spec/std/signal_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 | require "signal"
3 |
4 | describe "Signal" do
5 | typeof(Signal::PIPE.reset)
6 | typeof(Signal::PIPE.ignore)
7 | typeof(Signal::PIPE.trap { 1 })
8 |
9 | it "runs a signal handler" do
10 | ran = false
11 | Signal::USR1.trap do
12 | ran = true
13 | end
14 | Process.kill Signal::USR1, Process.pid
15 | 10.times do |i|
16 | break if ran
17 | sleep 0.1
18 | end
19 | ran.should be_true
20 | end
21 |
22 | it "ignores a signal" do
23 | Signal::USR2.ignore
24 | Process.kill Signal::USR2, Process.pid
25 | end
26 |
27 | # TODO: test Signal::X.reset
28 | end
29 |
--------------------------------------------------------------------------------
/src/llvm/pass_registry.cr:
--------------------------------------------------------------------------------
1 | struct LLVM::PassRegistry
2 | def self.instance
3 | new LibLLVM.get_global_pass_registry
4 | end
5 |
6 | def initialize(@unwrap)
7 | end
8 |
9 | Inits = %w(core transform_utils scalar_opts obj_c_arc_opts vectorization inst_combine ipo instrumentation analysis ipa code_gen target)
10 |
11 | {% for name in Inits %}
12 | def initialize_{{name.id}}
13 | LibLLVM.initialize_{{name.id}} self
14 | end
15 | {% end %}
16 |
17 | def initialize_all
18 | {% for name in Inits %}
19 | initialize_{{name.id}}
20 | {% end %}
21 | end
22 |
23 | def to_unsafe
24 | @unwrap
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/src/json/token.cr:
--------------------------------------------------------------------------------
1 | class JSON::Token
2 | property :type
3 | property :string_value
4 | property :int_value
5 | property :float_value
6 | property :line_number
7 | property :column_number
8 |
9 | def initialize
10 | @type = :EOF
11 | @line_number = 0
12 | @column_number = 0
13 | @string_value = ""
14 | @int_value = 0_i64
15 | @float_value = 0.0
16 | end
17 |
18 | def to_s(io)
19 | case @type
20 | when :INT
21 | @int_value.to_s(io)
22 | when :FLOAT
23 | @float_value.to_s(io)
24 | when :STRING
25 | @string_value.to_s(io)
26 | else
27 | @type.to_s(io)
28 | end
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/spec/std/zlib/inflate_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 | require "zlib"
3 |
4 | module Zlib
5 | describe Inflate do
6 | it "should be able to inflate" do
7 | io = MemoryIO.new
8 | "789c2bc9c82c5600a2448592d4e21285e292a2ccbc74054520e00200854f087b".scan(/../).each do |match|
9 | io.write_byte match[0].to_u8(16)
10 | end
11 | io.rewind
12 |
13 | inflate = Inflate.new(io)
14 |
15 | str = String::Builder.build do |builder|
16 | IO.copy(inflate, builder)
17 | end
18 |
19 | str.should eq("this is a test string !!!!\n")
20 | inflate.read(Slice(UInt8).new(10)).should eq(0)
21 | end
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/spec/std/zlib/stress_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 | require "zlib"
3 |
4 | module Zlib
5 | describe Zlib do
6 | it "inflate deflate should be inverse with random string" do
7 | expected = String.build do |io|
8 | 1_000_000.times { rand(2000).to_i.to_s(32, io) }
9 | end
10 | actual = Inflate.new(Deflate.new(MemoryIO.new(expected))).gets_to_end
11 | expected.should eq(actual)
12 | end
13 |
14 | it "inflate deflate should be inverse (utf-8)" do
15 | expected = "日本さん語日本さん語"
16 | actual = Inflate.new(Deflate.new(MemoryIO.new(expected))).gets_to_end
17 | expected.should eq(actual)
18 | end
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/src/compiler/crystal/tools/doc/html/methods_inherited.html:
--------------------------------------------------------------------------------
1 | <% method_groups = methods.group_by { |method| method.name } %>
2 | <% unless method_groups.empty? %>
3 | <%= label %> methods inherited from <%= ancestor.kind %> <%= ancestor.full_name %>
4 | <% method_groups.each_with_index do |method_name, methods, i| %>
5 |
6 | <%= methods.map { |method| method.name + method.args_to_s } .join("
") %>
7 | <%= method_name %><%= ", " if i != method_groups.size - 1 %>
8 | <% end %>
9 | <% end %>
10 |
--------------------------------------------------------------------------------
/src/xml/type.cr:
--------------------------------------------------------------------------------
1 | enum XML::Type
2 | ELEMENT_NODE = 1
3 | ATTRIBUTE_NODE = 2
4 | TEXT_NODE = 3
5 | CDATA_SECTION_NODE = 4
6 | ENTITY_REF_NODE = 5
7 | ENTITY_NODE = 6
8 | PI_NODE = 7
9 | COMMENT_NODE = 8
10 | DOCUMENT_NODE = 9
11 | DOCUMENT_TYPE_NODE = 10
12 | DOCUMENT_FRAG_NODE = 11
13 | NOTATION_NODE = 12
14 | HTML_DOCUMENT_NODE = 13
15 | DTD_NODE = 14
16 | ELEMENT_DECL = 15
17 | ATTRIBUTE_DECL = 16
18 | ENTITY_DECL = 17
19 | NAMESPACE_DECL = 18
20 | XINCLUDE_START = 19
21 | XINCLUDE_END = 20
22 | DOCB_DOCUMENT_NODE = 21
23 | end
24 |
--------------------------------------------------------------------------------
/src/openssl/openssl.cr:
--------------------------------------------------------------------------------
1 | require "./lib_ssl"
2 |
3 | module OpenSSL
4 | class Error < Exception
5 | getter err
6 | getter err_msg
7 |
8 | def initialize(msg = nil)
9 | unless (err = @err = LibCrypto.err_get_error) == 0
10 | @err_msg = String.new(LibCrypto.err_error_string(err, nil))
11 | msg = msg ? "#{msg}: #{@err_msg}" : @err_msg
12 | end
13 | super(msg)
14 | end
15 | end
16 |
17 | LibSSL.ssl_library_init
18 | LibSSL.ssl_load_error_strings
19 | LibCrypto.openssl_add_all_algorithms
20 | LibCrypto.err_load_crypto_strings
21 | end
22 |
23 | require "./bio"
24 | require "./ssl/*"
25 | require "./digest/*"
26 | require "./md5"
27 |
--------------------------------------------------------------------------------
/spec/compiler/normalize/or_spec.cr:
--------------------------------------------------------------------------------
1 | require "../../spec_helper"
2 |
3 | describe "Normalize: or" do
4 | it "normalizes or without variable" do
5 | assert_expand "a || b", "if __temp_1 = a\n __temp_1\nelse\n b\nend"
6 | end
7 |
8 | it "normalizes or with variable on the left" do
9 | assert_expand_second "a = 1; a || b", "if a\n a\nelse\n b\nend"
10 | end
11 |
12 | it "normalizes or with assignment on the left" do
13 | assert_expand "(a = 1) || b", "if a = 1\n a\nelse\n b\nend"
14 | end
15 |
16 | it "normalizes or with is_a? on var" do
17 | assert_expand_second "a = 1; a.is_a?(Foo) || b", "if a.is_a?(Foo)\n a.is_a?(Foo)\nelse\n b\nend"
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/samples/channel_select.cr:
--------------------------------------------------------------------------------
1 | def generator(n : T)
2 | channel = Channel(T).new
3 | spawn do
4 | loop do
5 | sleep n
6 | channel.send n
7 | end
8 | end
9 | channel
10 | end
11 |
12 | ch1 = generator(1)
13 | ch2 = generator(1.5)
14 | ch3 = generator(5)
15 |
16 | loop do
17 | index, value = Channel.select(ch1.receive_op, ch2.receive_op, ch3.receive_op)
18 | case index
19 | when 0
20 | int = value as typeof(ch1.receive)
21 | puts "Int: #{int}"
22 | when 1
23 | float = value as typeof(ch2.receive)
24 | puts "Float: #{float}"
25 | when 2
26 | break
27 | else
28 | raise "BUG: Channel.select returned invalid index #{index}"
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/spec/std/class_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 |
3 | describe Class, "#===" do
4 | it "does ===" do
5 | (Int32 === 1).should be_true
6 | (Int32 === 1.5).should be_false
7 | (Array === [1]).should be_true
8 | (Array(Int32) === [1]).should be_true
9 | (Array(Int32) === ['a']).should be_false
10 | end
11 | end
12 |
13 | describe Class, ".cast" do
14 | it "casts, allowing the class to be passed in at runtime" do
15 | ar = [99, "something"]
16 | cl = {Int32, String}
17 | casted = {cl[0].cast(ar[0]), cl[1].cast(ar[1])}
18 | casted.should eq({99, "something"})
19 | typeof(casted[0]).should eq(Int32)
20 | typeof(casted[1]).should eq(String)
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/src/llvm/generic_value.cr:
--------------------------------------------------------------------------------
1 | class LLVM::GenericValue
2 | def initialize(@unwrap : LibLLVM::GenericValueRef)
3 | end
4 |
5 | def to_i
6 | LibLLVM.generic_value_to_int(self, 1)
7 | end
8 |
9 | def to_b
10 | to_i != 0
11 | end
12 |
13 | def to_f32
14 | LibLLVM.generic_value_to_float(LLVM::Float, self)
15 | end
16 |
17 | def to_f64
18 | LibLLVM.generic_value_to_float(LLVM::Double, self)
19 | end
20 |
21 | def to_string
22 | to_pointer as String
23 | end
24 |
25 | def to_pointer
26 | LibLLVM.generic_value_to_pointer(self)
27 | end
28 |
29 | def to_unsafe
30 | @unwrap
31 | end
32 |
33 | def finalize
34 | LibLLVM.dispose_generic_value(@unwrap)
35 | end
36 | end
37 |
--------------------------------------------------------------------------------
/samples/sdl/tv.txt:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | xxxxx xxxx x x xxxxx xxxxx xxxxx x
21 | x..... x...x x. x. x..... .x... x...x. x.
22 | x. x. x. x. x. x. x. x. x. x.
23 | x. x. x. x. x. x. x. x. x. x.
24 | x. xxxx x x . xxxxx x. xxxxx. x.
25 | x. x...x x . ...x. x. x...x. x.
26 | x. x. x. x. x. x. x. x. x.
27 | x. x. x. x. x. x. x. x. x.
28 | xxxxx x. x. x. xxxxx. x. x. x. xxxxx
29 | ..... . . . ..... . . . .....
30 |
--------------------------------------------------------------------------------
/src/oauth2/access_token/bearer.cr:
--------------------------------------------------------------------------------
1 | require "./access_token"
2 |
3 | class OAuth2::AccessToken::Bearer < OAuth2::AccessToken
4 | def token_type
5 | "Bearer"
6 | end
7 |
8 | def authenticate(request : HTTP::Request, ssl)
9 | request.headers["Authorization"] = "Bearer #{access_token}"
10 | end
11 |
12 | def to_json(io)
13 | io.json_object do |object|
14 | object.field "token_type", "bearer"
15 | object.field "access_token", access_token
16 | object.field "expires_in", expires_in
17 | object.field "refresh_token", refresh_token if refresh_token
18 | object.field "scope", scope if scope
19 | end
20 | end
21 |
22 | def_equals_and_hash access_token, expires_in, refresh_token, scope
23 | end
24 |
--------------------------------------------------------------------------------
/src/compiler/crystal/syntax/visitor.cr:
--------------------------------------------------------------------------------
1 | require "./ast"
2 |
3 | module Crystal
4 | class Visitor
5 | def visit_any(node)
6 | true
7 | end
8 |
9 | # def visit(node)
10 | # true
11 | # end
12 |
13 | def end_visit(node)
14 | end
15 |
16 | def end_visit_any(node)
17 | end
18 |
19 | def accept(node)
20 | node.accept self
21 | end
22 | end
23 |
24 | class ASTNode
25 | def accept(visitor)
26 | if visitor.visit_any self
27 | if visitor.visit self
28 | accept_children visitor
29 | end
30 | visitor.end_visit self
31 | visitor.end_visit_any self
32 | end
33 | end
34 |
35 | def accept_children(visitor)
36 | end
37 | end
38 | end
39 |
--------------------------------------------------------------------------------
/src/file_utils.cr:
--------------------------------------------------------------------------------
1 | module FileUtils
2 | extend self
3 |
4 | def cmp(filename1 : String, filename2 : String)
5 | return false unless File.size(filename1) == File.size(filename2)
6 |
7 | File.open(filename1, "rb") do |file1|
8 | File.open(filename2, "rb") do |file2|
9 | cmp(file1, file2)
10 | end
11 | end
12 | end
13 |
14 | def cmp(stream1 : IO, stream2 : IO)
15 | buf1 :: UInt8[1024]
16 | buf2 :: UInt8[1024]
17 |
18 | while true
19 | read1 = stream1.read buf1.to_slice
20 | read2 = stream2.read buf2.to_slice
21 |
22 | return false if read1 != read2
23 | return false if buf1.buffer.memcmp(buf2.buffer, read1) != 0
24 | return true if read1 == 0
25 | end
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/samples/sdl/fire.txt:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | xxxxxx xxxxx xx xx xxxxxx xxxxxx xxxxxx xx
21 | xxxxxx xxxxxx xx xx xxxxxx xxxxxx xxxxxx xx
22 | xx xx xx xx xx xx xx xx xx xx
23 | xx xx xx xxxxxx xx xx xx xx xx
24 | xx xxxxxx xxxxxx xxxxxx xx xxxxxx xx
25 | xx xxxxx xx xxxxxx xx xxxxxx xx
26 | xx xx xx xx xx xx xx xx xx
27 | xx xx xx xx xx xx xx xx xx
28 | xxxxxx xx xx xx xxxxxx xx xx xx xxxxxx
29 | xxxxxx xx xx xx xxxxxx xx xx xx xxxxxx
30 |
--------------------------------------------------------------------------------
/src/compiler/crystal/tools/doc/html/main.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | README - <%= repository_name %>
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
20 |
21 | <%= ListItemsTemplate.new(types, nil) %>
22 |
23 |
24 |
25 | <%= body %>
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/http/server/handlers/log_handler.cr:
--------------------------------------------------------------------------------
1 | class HTTP::LogHandler < HTTP::Handler
2 | def call(request)
3 | time = Time.now
4 | response = call_next(request)
5 | elapsed = Time.now - time
6 | elapsed_text = elapsed_text(elapsed)
7 |
8 | puts "#{request.method} #{request.resource} - #{response.status_code} (#{elapsed_text})"
9 | response
10 | end
11 |
12 | private def elapsed_text(elapsed)
13 | minutes = elapsed.total_minutes
14 | return "#{minutes.round(2)}m" if minutes >= 1
15 |
16 | seconds = elapsed.total_seconds
17 | return "#{seconds.round(2)}s" if seconds >= 1
18 |
19 | millis = elapsed.total_milliseconds
20 | return "#{millis.round(2)}ms" if millis >= 1
21 |
22 | "#{(millis * 1000).round(2)}µs"
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/src/openssl/digest/digest_base.cr:
--------------------------------------------------------------------------------
1 | require "base64"
2 |
3 | module OpenSSL
4 | module DigestBase
5 | def file(file_name)
6 | File.open(file_name) do |io|
7 | self << io
8 | end
9 | end
10 |
11 | def update(io : IO)
12 | buffer :: UInt8[2048]
13 | while (read_bytes = io.read(buffer.to_slice)) > 0
14 | self << buffer.to_slice
15 | end
16 | self
17 | end
18 |
19 | def digest
20 | self.clone.finish
21 | end
22 |
23 | def <<(data)
24 | update(data)
25 | end
26 |
27 | def base64digest
28 | Base64.encode(digest)
29 | end
30 |
31 | def hexdigest
32 | digest.hexstring
33 | end
34 |
35 | def to_s(io)
36 | io << hexdigest
37 | end
38 | end
39 | end
40 |
--------------------------------------------------------------------------------
/src/xml/html_parser_options.cr:
--------------------------------------------------------------------------------
1 | @[Flags]
2 | enum XML::HTMLParserOptions
3 | # Relaxed parsing
4 | RECOVER = 1
5 |
6 | # Do not default a doctype if not found
7 | NODEFDTD = 4
8 |
9 | # Suppress error reports
10 | NOERROR = 32
11 |
12 | # Suppress warning reports
13 | NOWARNING = 64
14 |
15 | # Pedantic error reporting
16 | PEDANTIC = 128
17 |
18 | # Remove blank nodes
19 | NOBLANKS = 256
20 |
21 | # Forbid network access
22 | NONET = 2048
23 |
24 | # Do not add implied html/body... elements
25 | NOIMPLIED = 8192
26 |
27 | # Compact small text nodes
28 | COMPACT = 65536
29 |
30 | # Ignore internal document encoding hint
31 | IGNORE_ENC = 2097152
32 |
33 | def self.default
34 | RECOVER | NOERROR | NOWARNING
35 | end
36 | end
37 |
--------------------------------------------------------------------------------
/spec/compiler/codegen/asm_spec.cr:
--------------------------------------------------------------------------------
1 | require "../../spec_helper"
2 |
3 | describe "Code gen: asm" do
4 | it "codegens without inputs" do
5 | run(%(
6 | dst :: Int32
7 | asm("mov $$1234, $0" : "=r"(dst))
8 | dst
9 | )).to_i.should eq(1234)
10 | end
11 |
12 | it "codegens with one input" do
13 | run(%(
14 | src = 1234
15 | dst :: Int32
16 | asm("mov $1, $0" : "=r"(dst) : "r"(src))
17 | dst
18 | )).to_i.should eq(1234)
19 | end
20 |
21 | it "codegens with two inputs" do
22 | run(%(
23 | c :: Int32
24 | a = 20
25 | b = 22
26 | asm(
27 | "add $2, $0"
28 | : "=r"(c)
29 | : "0"(a), "r"(b)
30 | )
31 | c
32 | )).to_i.should eq(42)
33 | end
34 | end
35 |
--------------------------------------------------------------------------------
/src/markdown/markdown.cr:
--------------------------------------------------------------------------------
1 | # Markdown library parses Markdown text. It supports rendering to HTML text.
2 | # Note: This library is in its early stage. Many features are still in development.
3 | #
4 | # Usage:
5 | #
6 | # require "markdown"
7 | #
8 | # text = "## This is title \n This is a [link](http://crystal-lang.org)"
9 | #
10 | # Markdown.to_html(text)
11 | # #=>This is title
12 | # #=>This is a link
13 | class Markdown
14 | def self.parse(text, renderer)
15 | parser = Parser.new(text, renderer)
16 | parser.parse
17 | end
18 |
19 | def self.to_html(text)
20 | String.build do |io|
21 | parse text, Markdown::HTMLRenderer.new(io)
22 | end
23 | end
24 | end
25 |
26 | require "./*"
27 |
--------------------------------------------------------------------------------
/samples/sdl/sdl/surface.cr:
--------------------------------------------------------------------------------
1 | class SDL::Surface
2 | getter :surface
3 | getter :width
4 | getter :height
5 | getter :bpp
6 |
7 | def initialize(@surface, @width, @height, @bpp)
8 | end
9 |
10 | def lock
11 | LibSDL.lock_surface @surface
12 | end
13 |
14 | def unlock
15 | LibSDL.unlock_surface @surface
16 | end
17 |
18 | def update_rect(x, y, w, h)
19 | LibSDL.update_rect @surface, x, y, w, h
20 | end
21 |
22 | def flip
23 | LibSDL.flip @surface
24 | end
25 |
26 | def []=(offset, color)
27 | (@surface.value.pixels as UInt32*)[offset] = color.to_u32
28 | end
29 |
30 | def []=(x, y, color)
31 | self[y.to_i32 * @width + x.to_i32] = color
32 | end
33 |
34 | def offset(x, y)
35 | x.to_i32 + (y.to_i32 * @width)
36 | end
37 | end
38 |
--------------------------------------------------------------------------------
/src/oauth2/error.cr:
--------------------------------------------------------------------------------
1 | class OAuth2::Error < Exception
2 | getter error
3 | getter error_description
4 |
5 | def initialize(@error, @error_description)
6 | if error_description = @error_description
7 | super("#{@error}: #{error_description}")
8 | else
9 | super(@error)
10 | end
11 | end
12 |
13 | def self.new(pull : JSON::PullParser)
14 | error = nil
15 | error_description = nil
16 |
17 | pull.read_object do |key|
18 | case key
19 | when "error" then error = pull.read_string
20 | when "error_description" then error_description = pull.read_string
21 | else
22 | raise "Uknown key in oauth2 error json: #{key}"
23 | end
24 | end
25 |
26 | new error.not_nil!, error_description
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/src/value.cr:
--------------------------------------------------------------------------------
1 | # Value is the base type of the primitive types (`Nil`, `Bool`, `Char`, `Number`),
2 | # `Symbol`, `Pointer`, `Tuple`, `StaticArray` and all structs.
3 | #
4 | # A Value is passed by value: when you pass it to methods,
5 | # return it from methods or assign it to variables, a copy
6 | # of the value is actually passed.
7 | # This is not important for nil, bools, integers, floats, symbols,
8 | # pointers and tuples, because they are immutable, but with a mutable
9 | # `Struct` or with a `StaticArray` you have to be careful. Read their
10 | # documentation to learn more about this.
11 | struct Value
12 | # Returns false.
13 | def ==(other)
14 | false
15 | end
16 |
17 | # Returns false.
18 | def !
19 | false
20 | end
21 |
22 | # Returns false.
23 | def nil?
24 | false
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/spec/compiler/codegen/global_spec.cr:
--------------------------------------------------------------------------------
1 | require "../../spec_helper"
2 |
3 | describe "Code gen: global" do
4 | it "codegens global" do
5 | run("$foo = 1; def foo; $foo = 2; end; foo; $foo").to_i.should eq(2)
6 | end
7 |
8 | it "codegens global with union" do
9 | run("$foo = 1; def foo; $foo = 2.5_f32; end; foo; $foo.to_f").to_f64.should eq(2.5)
10 | end
11 |
12 | it "codegens global when not initialized" do
13 | run(%(
14 | struct Nil; def to_i; 0; end; end
15 | $foo.to_i
16 | )).to_i.should eq(0)
17 | end
18 |
19 | it "codegens global when not initialized" do
20 | run(%(
21 | struct Nil; def to_i; 0; end; end
22 |
23 | def foo
24 | $foo = 2 if 1 == 2
25 | end
26 |
27 | foo
28 |
29 | $foo.to_i
30 | )).to_i.should eq(0)
31 | end
32 | end
33 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM manastech/crystal
2 |
3 | RUN apt-get update && \
4 | apt-get install -y build-essential curl libevent-dev && \
5 | apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
6 |
7 | RUN curl http://crystal-lang.s3.amazonaws.com/llvm/llvm-3.5.0-1-linux-x86_64.tar.gz | tar xz -C /opt
8 | RUN curl http://crystal-lang.s3.amazonaws.com/pcl/libpcl-1.12-1-linux-x86_64.tar.gz | tar xz -C /opt/crystal/embedded --strip-components=1
9 |
10 | ADD . /opt/crystal-head
11 |
12 | WORKDIR /opt/crystal-head
13 | ENV CRYSTAL_CONFIG_VERSION HEAD
14 | ENV CRYSTAL_CONFIG_PATH libs:/opt/crystal-head/src:/opt/crystal-head/libs
15 | ENV LIBRARY_PATH /opt/crystal/embedded/lib
16 | ENV PATH /opt/crystal-head/bin:/opt/llvm-3.5.0-1/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
17 |
18 | RUN make clean crystal release=1
19 |
--------------------------------------------------------------------------------
/src/compiler/crystal/tools/doc/html/method_detail.html:
--------------------------------------------------------------------------------
1 | <% unless methods.empty? %>
2 | <%= title %>
3 | <% methods.each do |method| %>
4 |
5 |
6 | <%= method.abstract? ? "abstract " : "" %>
7 | <%= method.kind %>
<%= method.name %><%= method.args_to_html %>
8 |
9 |
#
10 |
11 | <% if doc = method.formatted_doc %>
12 |
<%= doc %>
13 | <% end %>
14 |
15 |
16 | <% if source_link = method.source_link %>
17 | [
View source]
18 | <% end %>
19 |
20 |
21 | <% end %>
22 | <% end %>
23 |
--------------------------------------------------------------------------------
/src/xml/namespace.cr:
--------------------------------------------------------------------------------
1 | struct XML::Namespace
2 | getter document
3 |
4 | def initialize(@document : Node, @ns : LibXML::NS*)
5 | end
6 |
7 | def hash
8 | object_id
9 | end
10 |
11 | def href
12 | @ns.value.href ? String.new(@ns.value.href) : nil
13 | end
14 |
15 | def object_id
16 | @ns.address
17 | end
18 |
19 | def prefix
20 | @ns.value.prefix ? String.new(@ns.value.prefix) : nil
21 | end
22 |
23 | def to_s(io)
24 | io << "#"
38 | io
39 | end
40 |
41 | def inspect(io)
42 | to_s io
43 | end
44 | end
45 |
--------------------------------------------------------------------------------
/spec/compiler/normalize/return_next_break_spec.cr:
--------------------------------------------------------------------------------
1 | require "../../spec_helper"
2 |
3 | describe "Normalize: return next break" do
4 | ["return", "next", "break"].each do |keyword|
5 | it "removes nodes after #{keyword}" do
6 | assert_normalize "#{keyword} 1; 2", "#{keyword} 1"
7 | end
8 | end
9 |
10 | it "doesn't remove after return when there's an unless" do
11 | assert_normalize "return 1 unless 2; 3", "if 2\nelse\n return 1\nend\n3"
12 | end
13 |
14 | it "removes nodes after if that returns in both branches" do
15 | assert_normalize "if true; break; else; return; end; 1", "if true\n break\nelse\n return\nend"
16 | end
17 |
18 | it "doesn't remove nodes after if that returns in one branch" do
19 | assert_normalize "if true; 1; else; return; end; 1", "if true\n 1\nelse\n return\nend\n1"
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/spec/compiler/normalize/and_spec.cr:
--------------------------------------------------------------------------------
1 | require "../../spec_helper"
2 |
3 | describe "Normalize: and" do
4 | it "normalizes and without variable" do
5 | assert_expand "a && b", "if __temp_1 = a\n b\nelse\n __temp_1\nend"
6 | end
7 |
8 | it "normalizes and with variable on the left" do
9 | assert_expand_second "a = 1; a && b", "if a\n b\nelse\n a\nend"
10 | end
11 |
12 | it "normalizes and with is_a? on var" do
13 | assert_expand_second "a = 1; a.is_a?(Foo) && b", "if a.is_a?(Foo)\n b\nelse\n a.is_a?(Foo)\nend"
14 | end
15 |
16 | it "normalizes and with is_a? on exp" do
17 | assert_expand_second "a = 1; 1.is_a?(Foo) && b", "if __temp_1 = 1.is_a?(Foo)\n b\nelse\n __temp_1\nend"
18 | end
19 |
20 | it "normalizes and with assignment" do
21 | assert_expand "(a = 1) && b", "if a = 1\n b\nelse\n a\nend"
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/spec/compiler/normalize/chained_comparisons_spec.cr:
--------------------------------------------------------------------------------
1 | require "../../spec_helper"
2 |
3 | describe "Normalize: chained comparisons" do
4 | it "normalizes one comparison with literal" do
5 | assert_normalize "1 <= 2 <= 3", "1 <= 2 && 2 <= 3"
6 | end
7 |
8 | it "normalizes one comparison with var" do
9 | assert_normalize "b = 1; 1 <= b <= 3", "b = 1\n1 <= b && b <= 3"
10 | end
11 |
12 | it "normalizes one comparison with call" do
13 | assert_normalize "1 <= b <= 3", "1 <= __temp_1 = b && __temp_1 <= 3"
14 | end
15 |
16 | it "normalizes two comparisons with literal" do
17 | assert_normalize "1 <= 2 <= 3 <= 4", "1 <= 2 && 2 <= 3 && 3 <= 4"
18 | end
19 |
20 | it "normalizes two comparisons with calls" do
21 | assert_normalize "1 <= a <= b <= 4", "1 <= __temp_2 = a && __temp_2 <= __temp_1 = b && __temp_1 <= 4"
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/src/dl.cr:
--------------------------------------------------------------------------------
1 | @[Link("dl")]
2 | lib LibDL
3 | LAZY = 1
4 | GLOBAL = 8
5 |
6 | struct Info
7 | fname : LibC::Char*
8 | fbase : Void*
9 | sname : LibC::Char*
10 | saddr : Void*
11 | end
12 |
13 | fun dladdr(addr : Void*, info : Info*) : LibC::Int
14 | fun dlsym(handle : Void*, symbol : LibC::Char*) : Void*
15 | fun dlopen(path : LibC::Char*, mode : LibC::Int) : Void*
16 |
17 | ifdef darwin
18 | RTLD_NEXT = Pointer(Void).new(-1)
19 | RTLD_DEFAULT = Pointer(Void).new(-2)
20 | RTLD_SELF = Pointer(Void).new(-3)
21 | RTLD_MAIN_ONLY = Pointer(Void).new(-5)
22 | else
23 | RTLD_NEXT = Pointer(Void).new(-1)
24 | RTLD_DEFAULT = Pointer(Void).new(0)
25 | end
26 | end
27 |
28 | module DL
29 | def self.dlopen(path, mode = LibDL::LAZY | LibDL::GLOBAL)
30 | LibDL.dlopen(path, mode)
31 | end
32 | end
33 |
--------------------------------------------------------------------------------
/src/thread/condition_variable.cr:
--------------------------------------------------------------------------------
1 | class ConditionVariable
2 | def initialize
3 | if LibPThread.cond_init(out @cond, nil) != 0
4 | raise Errno.new("pthread_cond_init")
5 | end
6 | end
7 |
8 | def signal
9 | if LibPThread.cond_signal(self) != 0
10 | raise Errno.new("pthread_cond_signal")
11 | end
12 | end
13 |
14 | def broadcast
15 | if LibPThread.cond_broadcast(self) != 0
16 | raise Errno.new("pthread_cond_broadcast")
17 | end
18 | end
19 |
20 | def wait(mutex : Mutex)
21 | if LibPThread.cond_wait(self, mutex) != 0
22 | raise Errno.new("pthread_cond_wait")
23 | end
24 | end
25 |
26 | def finalize
27 | if LibPThread.cond_destroy(self) != 0
28 | raise Errno.new("pthread_cond_broadcast")
29 | end
30 | end
31 |
32 | def to_unsafe
33 | pointerof(@cond)
34 | end
35 | end
36 |
--------------------------------------------------------------------------------
/spec/compiler/compiler_spec.cr:
--------------------------------------------------------------------------------
1 | require "../spec_helper"
2 | require "tempfile"
3 |
4 | describe "Compiler" do
5 | it "compiles a file" do
6 | tempfile = Tempfile.new "compiler_spec_output"
7 | tempfile.close
8 |
9 | Crystal::Command.run ["build", "#{__DIR__}/data/compiler_sample", "-o", tempfile.path]
10 |
11 | File.exists?(tempfile.path).should be_true
12 |
13 | `#{tempfile.path}`.should eq("Hello!")
14 | end
15 |
16 | it "runs subcommand in preference to a filename " do
17 | Dir.cd "#{__DIR__}/data/" do
18 | tempfile = Tempfile.new "compiler_spec_output"
19 | tempfile.close
20 |
21 | Crystal::Command.run ["build", "#{__DIR__}/data/compiler_sample", "-o", tempfile.path]
22 |
23 | File.exists?(tempfile.path).should be_true
24 |
25 | `#{tempfile.path}`.should eq("Hello!")
26 | end
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/spec/std/http/http_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 | require "http"
3 |
4 | describe HTTP do
5 | it "parses RFC1123" do
6 | time = Time.new(1994, 11, 6, 8, 49, 37)
7 | HTTP.parse_time("Sun, 06 Nov 1994 08:49:37 GMT").should eq(time)
8 | end
9 |
10 | it "parses RFC1036" do
11 | time = Time.new(1994, 11, 6, 8, 49, 37)
12 | HTTP.parse_time("Sunday, 06-Nov-94 08:49:37 GMT").should eq(time)
13 | end
14 |
15 | it "parses ANSI C" do
16 | time = Time.new(1994, 11, 6, 8, 49, 37)
17 | HTTP.parse_time("Sun Nov 6 08:49:37 1994").should eq(time)
18 | time2 = Time.new(1994, 11, 16, 8, 49, 37)
19 | HTTP.parse_time("Sun Nov 16 08:49:37 1994").should eq(time2)
20 | end
21 |
22 | it "generates RFC1123" do
23 | time = Time.new(1994, 11, 6, 8, 49, 37)
24 | HTTP.rfc1123_date(time).should eq("Sun, 06 Nov 1994 08:49:37 GMT")
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/spec/std/readline_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 | require "readline"
3 |
4 | describe Readline do
5 | typeof(Readline.readline)
6 | typeof(Readline.readline("Hello", true))
7 | typeof(Readline.readline(prompt: "Hello"))
8 | typeof(Readline.readline(add_history: false))
9 | typeof(Readline.line_buffer)
10 | typeof(Readline.point)
11 | typeof(Readline.autocomplete { |s| %w(foo bar) })
12 |
13 | it "gets prefix in bytesize between two strings" do
14 | Readline.common_prefix_bytesize("", "foo").should eq(0)
15 | Readline.common_prefix_bytesize("foo", "").should eq(0)
16 | Readline.common_prefix_bytesize("a", "a").should eq(1)
17 | Readline.common_prefix_bytesize("open", "operate").should eq(3)
18 | Readline.common_prefix_bytesize("operate", "open").should eq(3)
19 | Readline.common_prefix_bytesize(["operate", "open", "optional"]).should eq(2)
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/spec/std/ecr/ecr_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 | require "ecr"
3 | require "ecr/macros"
4 |
5 | class ECRSpecHelloView
6 | def initialize(@msg)
7 | end
8 |
9 | ecr_file "#{__DIR__}/../data/test_template.ecr"
10 | end
11 |
12 | describe "ECR" do
13 | it "builds a crystal program from a source" do
14 | program = ECR.process_string "hello <%= 1 %> wor\nld <% while true %> 2 <% end %>", "foo.cr"
15 |
16 | pieces = [
17 | %(__str__ << "hello "),
18 | %((# 1 ).to_s __str__),
19 | %(__str__ << " wor\\nld "),
20 | %(# while true ),
21 | %(__str__ << " 2 "),
22 | %(# end ),
23 | ]
24 | program.should eq(pieces.join("\n") + "\n")
25 | end
26 |
27 | it "does ecr_file" do
28 | view = ECRSpecHelloView.new("world!")
29 | view.to_s.strip.should eq("Hello world! 012")
30 | end
31 | end
32 |
--------------------------------------------------------------------------------
/src/compiler/crystal/codegen/types.cr:
--------------------------------------------------------------------------------
1 | module Crystal
2 | class Type
3 | def llvm_name
4 | String.build do |io|
5 | llvm_name io
6 | end
7 | end
8 |
9 | def llvm_name(io)
10 | to_s io
11 | end
12 | end
13 |
14 | class PrimitiveType
15 | def llvm_name(io)
16 | io << name
17 | end
18 | end
19 |
20 | class AliasType
21 | def llvm_name(io)
22 | io << "alias."
23 | to_s io
24 | end
25 | end
26 |
27 | class CStructType
28 | def llvm_name(io)
29 | io << "struct."
30 | to_s io
31 | end
32 | end
33 |
34 | class CUnionType
35 | def llvm_name(io)
36 | io << "union."
37 | to_s io
38 | end
39 | end
40 |
41 | class TypeDefType
42 | def llvm_name(io)
43 | typedef.llvm_name(io)
44 | end
45 | end
46 |
47 | class Const
48 | property initializer
49 | end
50 | end
51 |
--------------------------------------------------------------------------------
/spec/std/zlib/zlib_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 | require "zlib"
3 |
4 | describe Zlib do
5 | it "should be able to calculate adler32" do
6 | adler = Zlib.adler32("foo").to_s(16)
7 | adler.should eq("2820145")
8 | end
9 |
10 | it "should be able to calculate adler32 combined" do
11 | adler1 = Zlib.adler32("hello")
12 | adler2 = Zlib.adler32(" world!")
13 | combined = Zlib.adler32_combine(adler1, adler2, " world!".size)
14 | Zlib.adler32("hello world!").should eq(combined)
15 | end
16 |
17 | it "should be able to calculate crc32" do
18 | crc = Zlib.crc32("foo").to_s(16)
19 | crc.should eq("8c736521")
20 | end
21 |
22 | it "should be able to calculate crc32 combined" do
23 | crc1 = Zlib.crc32("hello")
24 | crc2 = Zlib.crc32(" world!")
25 | combined = Zlib.crc32_combine(crc1, crc2, " world!".size)
26 | Zlib.crc32("hello world!").should eq(combined)
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/src/iterable.cr:
--------------------------------------------------------------------------------
1 | # The Iterable mixin provides convenince methods to collection classes
2 | # that provide an `each` method that returns an `Iterator` over the collection.
3 | module Iterable
4 | # Must return an `Iterator` over the elements in this collection.
5 | abstract def each
6 |
7 | # Same as `each.cycle`.
8 | def cycle
9 | each.cycle
10 | end
11 |
12 | # Same as `each.cycle(n)`.
13 | def cycle(n)
14 | each.cycle(n)
15 | end
16 |
17 | # Same as `each.slice(count)`.
18 | def each_slice(count : Int)
19 | each.slice(count)
20 | end
21 |
22 | # Same as `each.cons(count)`.
23 | def each_cons(count : Int)
24 | each.cons(count)
25 | end
26 |
27 | # Same as `each.with_index(offset)`.
28 | def each_with_index(offset = 0)
29 | each.with_index(offset)
30 | end
31 |
32 | # Same as `each.with_object(obj)`.
33 | def each_with_object(obj)
34 | each.with_object(obj)
35 | end
36 | end
37 |
--------------------------------------------------------------------------------
/src/csv/lexer/io_based.cr:
--------------------------------------------------------------------------------
1 | # :nodoc:
2 | class CSV::Lexer::IOBased < CSV::Lexer
3 | def initialize(io)
4 | super()
5 | @io = io
6 | @current_char = @io.read_char || '\0'
7 | end
8 |
9 | def rewind
10 | @io.rewind
11 | @current_char = @io.read_char || '\0'
12 | end
13 |
14 | private def consume_unquoted_cell
15 | @buffer.clear
16 | while true
17 | case current_char
18 | when ','
19 | check_last_empty_column
20 | break
21 | when '\r', '\n', '\0'
22 | break
23 | when '"'
24 | raise "unexpected quote"
25 | else
26 | @buffer << current_char
27 | next_char
28 | end
29 | end
30 | @buffer.to_s
31 | end
32 |
33 | private getter current_char
34 |
35 | private def next_char_no_column_increment
36 | @current_char = @io.read_char || '\0'
37 | end
38 |
39 | private def consume_string
40 | consume_string_with_buffer
41 | end
42 | end
43 |
--------------------------------------------------------------------------------
/src/xml/error.cr:
--------------------------------------------------------------------------------
1 | require "./libxml2"
2 |
3 | class XML::Error < Exception
4 | getter line_number
5 |
6 | def self.new(error : LibXML::Error*)
7 | new String.new(error.value.message).chomp, error.value.line
8 | end
9 |
10 | def initialize(message, @line_number)
11 | super(message)
12 | end
13 |
14 | # TODO: this logic isn't thread/fiber safe, but error checking is less needed than
15 | # the ability to parse HTML5 and malformed documents. In any case, fix this.
16 | @@errors = [] of self
17 |
18 | LibXML.xmlSetStructuredErrorFunc nil, ->(ctx, error) {
19 | @@errors << XML::Error.new(error)
20 | }
21 |
22 | LibXML.xmlSetGenericErrorFunc nil, ->(ctx, fmt) {
23 | # TODO: use va_start and va_end
24 | raise XML::Error.new(String.new(fmt).chomp, 0)
25 | }
26 |
27 | # :nodoc:
28 | def self.set_errors(node)
29 | unless @@errors.empty?
30 | node.errors = @@errors.dup
31 | @@errors.clear
32 | end
33 | end
34 | end
35 |
--------------------------------------------------------------------------------
/spec/compiler/type_inference/reflection_spec.cr:
--------------------------------------------------------------------------------
1 | require "../../spec_helper"
2 |
3 | describe "Type inference: reflection" do
4 | it "types Object class" do
5 | assert_type("Object") { types["Class"] }
6 | end
7 |
8 | it "types Class class" do
9 | assert_type("Class") { types["Class"] }
10 | end
11 |
12 | it "types Object and Class metaclases" do
13 | assert_type("Object.class") { types["Class"] }
14 | assert_type("Class.class") { types["Class"] }
15 | end
16 |
17 | it "types Reference metaclass" do
18 | assert_type("Reference") { types["Reference"].metaclass }
19 | assert_type("Reference.class") { types["Class"] }
20 | end
21 |
22 | it "types metaclass parent" do
23 | input = parse("
24 | class Foo; end
25 | class Bar < Foo; end
26 | ")
27 | result = infer_type input
28 | mod = result.program
29 |
30 | (mod.types["Bar"].metaclass as ClassType).superclass.should eq(mod.types["Foo"].metaclass)
31 | end
32 | end
33 |
--------------------------------------------------------------------------------
/src/llvm/function_collection.cr:
--------------------------------------------------------------------------------
1 | struct LLVM::FunctionCollection
2 | def initialize(@mod)
3 | end
4 |
5 | def add(name, arg_types : Array(LLVM::Type), ret_type, varargs = false)
6 | fun_type = LLVM::Type.function(arg_types, ret_type, varargs)
7 | func = LibLLVM.add_function(@mod, name, fun_type)
8 | Function.new(func)
9 | end
10 |
11 | def add(name, arg_types : Array(LLVM::Type), ret_type, varargs = false)
12 | func = add(name, arg_types, ret_type, varargs)
13 | yield func
14 | func
15 | end
16 |
17 | def [](name)
18 | func = self[name]?
19 | func || raise "undefined llvm function: #{name}"
20 | end
21 |
22 | def []?(name)
23 | func = LibLLVM.get_named_function(@mod, name)
24 | func ? Function.new(func) : nil
25 | end
26 |
27 | def each
28 | f = LibLLVM.get_first_function(@mod)
29 | while f
30 | yield LLVM::Function.new f
31 | f = LibLLVM.get_next_function(f)
32 | end
33 | self
34 | end
35 | end
36 |
--------------------------------------------------------------------------------
/src/llvm/function_pass_manager.cr:
--------------------------------------------------------------------------------
1 | class LLVM::FunctionPassManager
2 | def initialize(@unwrap)
3 | end
4 |
5 | def add_target_data(target_data)
6 | LibLLVM.add_target_data target_data, self
7 | end
8 |
9 | def run(mod : Module)
10 | changed = false
11 | run do |runner|
12 | mod.functions.each do |func|
13 | changed ||= runner.run(func)
14 | end
15 | end
16 | changed
17 | end
18 |
19 | def run
20 | LibLLVM.initialize_function_pass_manager(self)
21 |
22 | runner = Runner.new(self)
23 | yield runner
24 |
25 | LibLLVM.finalize_function_pass_manager(self)
26 |
27 | self
28 | end
29 |
30 | def to_unsafe
31 | @unwrap
32 | end
33 |
34 | def finalize
35 | LibLLVM.dispose_pass_manager(@unwrap)
36 | end
37 |
38 | struct Runner
39 | def initialize(@fpm)
40 | end
41 |
42 | def run(f : LLVM::Function)
43 | LibLLVM.run_function_pass_manager(@fpm, f) != 0
44 | end
45 | end
46 | end
47 |
--------------------------------------------------------------------------------
/samples/mandelbrot.cr:
--------------------------------------------------------------------------------
1 | def print_density(d)
2 | if d > 8
3 | print ' '
4 | elsif d > 4
5 | print '.'
6 | elsif d > 2
7 | print '*'
8 | else
9 | print '+'
10 | end
11 | end
12 |
13 | def mandelconverger(real, imag, iters, creal, cimag)
14 | if iters > 255 || real*real + imag*imag >= 4
15 | iters
16 | else
17 | mandelconverger real*real - imag*imag + creal, 2*real*imag + cimag, iters + 1, creal, cimag
18 | end
19 | end
20 |
21 | def mandelconverge(real, imag)
22 | mandelconverger real, imag, 0, real, imag
23 | end
24 |
25 | def mandelhelp(xmin, xmax, xstep, ymin, ymax, ystep)
26 | ymin.step(ymax, ystep) do |y|
27 | xmin.step(xmax, xstep) do |x|
28 | print_density mandelconverge(x, y)
29 | end
30 | puts
31 | end
32 | end
33 |
34 | def mandel(realstart, imagstart, realmag, imagmag)
35 | mandelhelp realstart, realstart + realmag*78, realmag, imagstart, imagstart + imagmag*40, imagmag
36 | end
37 |
38 | mandel -2.3, -1.3, 0.05, 0.07
39 |
--------------------------------------------------------------------------------
/samples/sdl/sdl/sdl.cr:
--------------------------------------------------------------------------------
1 | require "./*"
2 |
3 | module SDL
4 | def self.init(flags = LibSDL::INIT_EVERYTHING)
5 | if LibSDL.init(flags) != 0
6 | raise "Can't initialize SDL: #{error}"
7 | end
8 | end
9 |
10 | def self.set_video_mode(width, height, bpp, flags)
11 | surface = LibSDL.set_video_mode(width, height, bpp, flags)
12 | if surface.nil?
13 | raise "Can't set SDL video mode: #{error}"
14 | end
15 | Surface.new(surface, width, height, bpp)
16 | end
17 |
18 | def self.show_cursor
19 | LibSDL.show_cursor LibSDL::ENABLE
20 | end
21 |
22 | def self.hide_cursor
23 | LibSDL.show_cursor LibSDL::DISABLE
24 | end
25 |
26 | def self.error
27 | String.new LibSDL.get_error
28 | end
29 |
30 | def self.ticks
31 | LibSDL.get_ticks
32 | end
33 |
34 | def self.quit
35 | LibSDL.quit
36 | end
37 |
38 | def self.poll_events
39 | while LibSDL.poll_event(out event) == 1
40 | yield event
41 | end
42 | end
43 | end
44 |
--------------------------------------------------------------------------------
/spec/std/symbol_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 |
3 | describe Symbol do
4 | it "inspects" do
5 | :foo.inspect.should eq(%(:foo))
6 | :"{".inspect.should eq(%(:"{"))
7 | :"hi there".inspect.should eq(%(:"hi there"))
8 | # :かたな.inspect.should eq(%(:かたな))
9 | end
10 | it "can be compared with another symbol" do
11 | :s.between?(:a, :z).should be_true
12 | :a.between?(:s, :z).should be_false
13 | (:foo > :bar).should be_true
14 | (:foo < :bar).should be_false
15 |
16 | a = %i(q w e r t y u i o p a s d f g h j k l z x c v b n m)
17 | b = %i(a b c d e f g h i j k l m n o p q r s t u v w x y z)
18 | a.sort.should eq(b)
19 | end
20 |
21 | it "displays symbols that don't need quotes without quotes" do
22 | a = %i(+ - * / == < <= > >= ! != =~ !~ & | ^ ~ ** >> << % [] <=> === []? []=)
23 | b = "[:+, :-, :*, :/, :==, :<, :<=, :>, :>=, :!, :!=, :=~, :!~, :&, :|, :^, :~, :**, :>>, :<<, :%, :[], :<=>, :===, :[]?, :[]=]"
24 | a.inspect.should eq(b)
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: generic
2 | sudo: required
3 | services:
4 | - docker
5 | matrix:
6 | include:
7 | - env: ARCH=i386 ARCH_CMD=linux32
8 | os: linux
9 | - env: ARCH=x86_64 ARCH_CMD=linux64
10 | os: linux
11 | - os: osx
12 | before_install: bin/ci prepare_system
13 | install: bin/ci prepare_build
14 | script:
15 | - bin/ci with_build_env 'make crystal spec doc'
16 | - bin/ci with_build_env 'find samples -name "*.cr" | xargs -L 1 ./bin/crystal build --no-codegen'
17 | branches:
18 | only:
19 | - master
20 | - gh-pages
21 | notifications:
22 | irc:
23 | channels:
24 | - "irc.freenode.net#crystal-lang"
25 | use_notice: true
26 | skip_join: true
27 | template:
28 | - "%{repository_slug}#%{commit} (%{branch} - %{commit_subject}): %{message} %{build_url}"
29 | slack:
30 | secure: Ng3nTqGWY+9p1pS6yjGqDhmRvdgbIZgTNpMWbO/ngwpCyicmD3jafZkShqqXbULZTJJr3OxIGzi6GHGusT0Ic/Pi9JCM3X3v/xuBruKIR+EnNyPo7IL4ZYAlwnXyJHlCHHDBq0gSHGvGJwsXn6IgZBPRfeIq+CCyQHVPyvc9EHE=
31 |
--------------------------------------------------------------------------------
/spec/compiler/type_inference/responds_to_spec.cr:
--------------------------------------------------------------------------------
1 | require "../../spec_helper"
2 |
3 | describe "Type inference: responds_to?" do
4 | it "is bool" do
5 | assert_type("1.responds_to?(:foo)") { bool }
6 | end
7 |
8 | it "restricts type inside if scope 1" do
9 | nodes = parse "
10 | a = 1 || 'a'
11 | if a.responds_to?(:\"+\")
12 | a
13 | end
14 | "
15 | result = infer_type nodes
16 | mod, nodes = result.program, result.node as Expressions
17 | (nodes.last as If).then.type.should eq(mod.int32)
18 | end
19 |
20 | it "restricts other types inside if else" do
21 | assert_type("
22 | a = 1 || 'a'
23 | if a.responds_to?(:\"+\")
24 | a.to_i32
25 | else
26 | a.ord
27 | end
28 | ") { int32 }
29 | end
30 |
31 | it "restricts in assignment" do
32 | assert_type("
33 | a = 1 || 'a'
34 | if (b = a).responds_to?(:abs)
35 | b
36 | else
37 | 2
38 | end
39 | ") { int32 }
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/src/csv/lexer/string_based.cr:
--------------------------------------------------------------------------------
1 | # :nodoc:
2 | class CSV::Lexer::StringBased < CSV::Lexer
3 | def initialize(string)
4 | super()
5 | @reader = Char::Reader.new(string)
6 | if @reader.current_char == '\n'
7 | @line_number += 1
8 | @column_number = 0
9 | end
10 | end
11 |
12 | def rewind
13 | @reader.pos = 0
14 | end
15 |
16 | private def consume_unquoted_cell
17 | start_pos = @reader.pos
18 | end_pos = start_pos
19 | while true
20 | case next_char
21 | when ','
22 | end_pos = @reader.pos
23 | check_last_empty_column
24 | break
25 | when '\r', '\n', '\0'
26 | end_pos = @reader.pos
27 | break
28 | when '"'
29 | raise "unexpected quote"
30 | end
31 | end
32 | @reader.string.byte_slice(start_pos, end_pos - start_pos)
33 | end
34 |
35 | private def next_char_no_column_increment
36 | @reader.next_char
37 | end
38 |
39 | private def current_char
40 | @reader.current_char
41 | end
42 | end
43 |
--------------------------------------------------------------------------------
/src/proc.cr:
--------------------------------------------------------------------------------
1 | struct Proc
2 | def self.new(pointer : Void*, closure_data : Void*)
3 | func = {pointer, closure_data}
4 | ptr = pointerof(func) as self*
5 | ptr.value
6 | end
7 |
8 | def pointer
9 | internal_representation[0]
10 | end
11 |
12 | def closure_data
13 | internal_representation[1]
14 | end
15 |
16 | def closure?
17 | !closure_data.nil?
18 | end
19 |
20 | private def internal_representation
21 | func = self
22 | ptr = pointerof(func) as {Void*, Void*}*
23 | ptr.value
24 | end
25 |
26 | def ==(other : self)
27 | pointer == other.pointer && closure_data == other.closure_data
28 | end
29 |
30 | def ===(other : self)
31 | self == other
32 | end
33 |
34 | def ===(other)
35 | call(other)
36 | end
37 |
38 | def to_s(io)
39 | io << "#<"
40 | io << {{@type.name.stringify}}
41 | io << ":0x"
42 | pointer.address.to_s(16, io)
43 | if closure?
44 | io << ":closure"
45 | end
46 | io << ">"
47 | nil
48 | end
49 | end
50 |
--------------------------------------------------------------------------------
/src/crypto/bcrypt/blowfish.cr:
--------------------------------------------------------------------------------
1 | require "../blowfish"
2 |
3 | # :nodoc:
4 | class Crypto::Bcrypt::Blowfish < Crypto::Blowfish
5 | def enhance_key_schedule(data, key, cost)
6 | enhance_key_schedule(data, key)
7 |
8 | (1_u32 << cost).times do
9 | expand_key(key)
10 | expand_key(data)
11 | end
12 | end
13 |
14 | def enhance_key_schedule(data, key)
15 | pos = 0
16 |
17 | 0.upto(17) do |i|
18 | @p[i] ^= next_word(key, pointerof(pos))
19 | end
20 |
21 | l, r, pos = 0, 0, 0
22 |
23 | 0.step(17, 2) do |i|
24 | l ^= next_word(data, pointerof(pos))
25 | r ^= next_word(data, pointerof(pos))
26 | l, r = encrypt_pair(l, r)
27 | @p[i] = l
28 | @p[i + 1] = r
29 | end
30 |
31 | 0.upto(3) do |i|
32 | 0.step(255, 2) do |j|
33 | l ^= next_word(data, pointerof(pos))
34 | r ^= next_word(data, pointerof(pos))
35 | l, r = encrypt_pair(l, r)
36 | @s[i][j] = l
37 | @s[i][j + 1] = r
38 | end
39 | end
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/samples/spectral-norm.cr:
--------------------------------------------------------------------------------
1 | # Copied with little modifications from: https://github.com/wmoxam/Ruby-Benchmarks-Game/blob/master/benchmarks/spectral-norm.rb
2 |
3 | def eval_A(i, j)
4 | return 1.0_f64 / ((i + j) * (i + j + 1.0) / 2.0 + i + 1.0)
5 | end
6 |
7 | def eval_A_times_u(u)
8 | (0...u.size).map do |i|
9 | v = 0.0_f64
10 | (0...u.size).each do |j|
11 | v += eval_A(i, j) * u[j]
12 | end
13 | v
14 | end
15 | end
16 |
17 | def eval_At_times_u(u)
18 | (0...u.size).map do |i|
19 | v = 0.0_f64
20 | (0...u.size).each do |j|
21 | v += eval_A(j, i) * u[j]
22 | end
23 | v
24 | end
25 | end
26 |
27 | def eval_AtA_times_u(u)
28 | eval_At_times_u(eval_A_times_u(u))
29 | end
30 |
31 | n = (ARGV[0]? || 1000).to_i
32 | u = Array.new(n, 1.0_f64)
33 | v = Array.new(n, 1.0_f64)
34 | 10.times do
35 | v = eval_AtA_times_u(u)
36 | u = eval_AtA_times_u(v)
37 | end
38 | vBv = vv = 0.0_f64
39 | (0...n).each do |i|
40 | vBv += u[i] * v[i]
41 | vv += v[i] * v[i]
42 | end
43 | puts "#{(Math.sqrt(vBv / vv))}"
44 |
--------------------------------------------------------------------------------
/spec/std/llvm/x86_abi_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 | require "llvm"
3 |
4 | LLVM.init_x86
5 |
6 | private def abi
7 | triple = LLVM.default_target_triple
8 | target = LLVM::Target.from_triple(triple)
9 | machine = target.create_target_machine(triple)
10 | LLVM::ABI::X86.new(machine)
11 | end
12 |
13 | class LLVM::ABI
14 | describe X86 do
15 | it "does size" do
16 | abi.size(LLVM::Int32).should eq(4)
17 | end
18 |
19 | it "does align" do
20 | abi.align(LLVM::Int32).should eq(4)
21 | end
22 |
23 | describe "abi_info" do
24 | it "does with primitives" do
25 | arg_types = [LLVM::Int32, LLVM::Int64]
26 | return_type = LLVM::Int8
27 | info = abi.abi_info(arg_types, return_type, true)
28 | info.arg_types.size.should eq(2)
29 |
30 | info.arg_types[0].should eq(ArgType.direct(LLVM::Int32))
31 | info.arg_types[1].should eq(ArgType.direct(LLVM::Int64))
32 | info.return_type.should eq(ArgType.direct(LLVM::Int8))
33 | end
34 | end
35 | end
36 | end
37 |
--------------------------------------------------------------------------------
/Vagrantfile:
--------------------------------------------------------------------------------
1 | # -*- mode: ruby -*-
2 | # vi: set ft=ruby :
3 |
4 | Vagrant.configure("2") do |config|
5 | %w(precise trusty vivid).product([32, 64]).each do |dist, bits|
6 | box_name = "#{dist}#{bits}"
7 | config.vm.define(box_name) { |c| c.vm.box = "ubuntu/#{box_name}" }
8 | end
9 |
10 | config.vm.provider "virtualbox" do |vb|
11 | vb.memory = 4096
12 | vb.cpus = 2
13 | end
14 |
15 | config.vm.provision :shell, inline: %(
16 | curl -s http://dist.crystal-lang.org/apt/setup.sh | bash
17 | apt-get install -y crystal git libgmp3-dev zlib1g-dev libedit-dev libxml2-dev libssl-dev libyaml-dev libreadline-dev
18 | curl -s http://crystal-lang.s3.amazonaws.com/llvm/llvm-3.5.0-1-linux-`uname -m`.tar.gz | tar xz -C /opt
19 | echo 'export LIBRARY_PATH="/opt/crystal/embedded/lib"' > /etc/profile.d/crystal.sh
20 | echo 'export PATH="$PATH:/opt/llvm-3.5.0-1/bin"' >> /etc/profile.d/crystal.sh
21 | )
22 |
23 | config.vm.provision :shell, privileged: false, inline: %(
24 | git clone /vagrant crystal
25 | )
26 | end
27 |
--------------------------------------------------------------------------------
/src/llvm/parameter_collection.cr:
--------------------------------------------------------------------------------
1 | struct LLVM::ParameterCollection
2 | def initialize(@function)
3 | end
4 |
5 | def size
6 | LibLLVM.count_param_types(@function.function_type).to_i
7 | end
8 |
9 | def to_a
10 | param_size = size()
11 | Array(LLVM::Value).build(param_size) do |buffer|
12 | LibLLVM.get_params(@function, buffer as LibLLVM::ValueRef*)
13 | param_size
14 | end
15 | end
16 |
17 | def [](index)
18 | param_size = size()
19 | index += param_size if index < 0
20 |
21 | unless 0 <= index < param_size
22 | raise IndexError.new
23 | end
24 |
25 | Value.new LibLLVM.get_param(@function, index)
26 | end
27 |
28 | def first
29 | raise IndexError.new if size == 0
30 |
31 | Value.new LibLLVM.get_param(@function, 0)
32 | end
33 |
34 | def types
35 | param_size = size()
36 | Array(LLVM::Type).build(param_size) do |buffer|
37 | LibLLVM.get_param_types(@function.function_type, buffer as LibLLVM::TypeRef*)
38 | param_size
39 | end
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/samples/matmul.cr:
--------------------------------------------------------------------------------
1 | # Copied with little modifications from: https://github.com/attractivechaos/plb/blob/master/matmul/matmul_v1.rb
2 |
3 | def matmul(a, b)
4 | m = a.size
5 | n = a[0].size
6 | p = b[0].size
7 | # transpose
8 | b2 = Array.new(n) { Array.new(p, 0.0) }
9 | (0...n).each do |i|
10 | (0...p).each do |j|
11 | b2[j][i] = b[i][j]
12 | end
13 | end
14 | # multiplication
15 | c = Array.new(m) { Array.new(p, 0.0) }
16 | (0...m).each do |i|
17 | (0...p).each do |j|
18 | s = 0.0
19 | ai, b2j = a[i], b2[j]
20 | (0...n).each do |k|
21 | s += ai[k] * b2j[k]
22 | end
23 | c[i][j] = s
24 | end
25 | end
26 | c
27 | end
28 |
29 | def matgen(n)
30 | tmp = 1.0 / n / n
31 | a = Array.new(n) { Array.new(n, 0.0) }
32 | (0...n).each do |i|
33 | (0...n).each do |j|
34 | a[i][j] = tmp * (i - j) * (i + j)
35 | end
36 | end
37 | a
38 | end
39 |
40 | n = (ARGV[0]? || 500).to_i
41 | n = n / 2 * 2
42 | a = matgen(n)
43 | b = matgen(n)
44 | c = matmul(a, b)
45 | puts c[n / 2][n / 2]
46 |
--------------------------------------------------------------------------------
/spec/std/io/argf_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 |
3 | describe IO::ARGF do
4 | it "reads from STDIN if ARGV isn't specified" do
5 | argv = [] of String
6 | stdin = MemoryIO.new("hello")
7 |
8 | argf = IO::ARGF.new argv, stdin
9 | argf.path.should eq("-")
10 | argf.gets_to_end.should eq("hello")
11 | argf.read_byte.should be_nil
12 | end
13 |
14 | it "reads from ARGV if specified" do
15 | path1 = "#{__DIR__}/../data/argf_test_file_1.txt"
16 | path2 = "#{__DIR__}/../data/argf_test_file_2.txt"
17 | stdin = MemoryIO.new("")
18 | argv = [path1, path2]
19 |
20 | argf = IO::ARGF.new argv, stdin
21 | argf.path.should eq(path1)
22 | argv.should eq([path1, path2])
23 |
24 | str = argf.gets(5)
25 | str.should eq("12345")
26 |
27 | argv.should eq([path2])
28 |
29 | str = argf.gets_to_end
30 | str.should eq("\n67890\n")
31 |
32 | argv.empty?.should be_true
33 |
34 | argf.read_byte.should be_nil
35 |
36 | argv << path1
37 | str = argf.gets(5)
38 | str.should eq("12345")
39 | end
40 | end
41 |
--------------------------------------------------------------------------------
/spec/std/inifile_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 | require "inifile"
3 |
4 | describe "IniFile" do
5 | describe "parse from string" do
6 | it "parses key = value" do
7 | IniFile.load("key = value").should eq({"" => {"key" => "value"}})
8 | end
9 |
10 | it "ignores whitespaces" do
11 | IniFile.load(" key = value ").should eq({"" => {"key" => "value"}})
12 | end
13 |
14 | it "parses sections" do
15 | IniFile.load("[section]\na = 1").should eq({"section" => {"a" => "1"}})
16 | end
17 |
18 | it "empty section" do
19 | IniFile.load("[section]").should eq({"section" => {} of String => String})
20 | end
21 |
22 | it "parse file" do
23 | IniFile.load(File.read "#{__DIR__}/data/test_file.ini").should eq({
24 | "general" => {
25 | "log_level" => "DEBUG",
26 | },
27 | "section1" => {
28 | "foo" => "1",
29 | "bar" => "2",
30 | },
31 | "section2" => {
32 | "x.y.z" => "coco lala",
33 | },
34 | })
35 | end
36 | end
37 | end
38 |
--------------------------------------------------------------------------------
/src/class.cr:
--------------------------------------------------------------------------------
1 | class Class
2 | def inspect(io)
3 | to_s(io)
4 | end
5 |
6 | def hash
7 | crystal_type_id
8 | end
9 |
10 | def ==(other : Class)
11 | crystal_type_id == other.crystal_type_id
12 | end
13 |
14 | def ===(other)
15 | other.is_a?(self)
16 | end
17 |
18 | # Returns the name of this class.
19 | #
20 | # ```
21 | # String.name # => "String"
22 | # ```
23 | macro def name : String
24 | {{ @type.name.stringify }}
25 | end
26 |
27 | # Casts `other` to this class.
28 | #
29 | # This is the same as using `as`, but allows the class to be passed around as
30 | # an argument. See the [documentation on
31 | # as](//crystal-lang.org/docs/syntax_and_semantics/as.html) for more
32 | # information.
33 | #
34 | # klass = Int32
35 | # number = [99, "str"][0]
36 | # typeof(number) # => (String | Int32)
37 | # typeof(klass.cast(number)) # => Int32
38 | #
39 | macro def cast(other) : self
40 | other as self
41 | end
42 |
43 | def to_s(io)
44 | io << name
45 | end
46 | end
47 |
--------------------------------------------------------------------------------
/spec/compiler/type_inference/array_spec.cr:
--------------------------------------------------------------------------------
1 | require "../../spec_helper"
2 |
3 | describe "Type inference: array" do
4 | it "types array literal of int" do
5 | assert_type("require \"prelude\"; [1, 2, 3]") { array_of(int32) }
6 | end
7 |
8 | it "types array literal of union" do
9 | assert_type("require \"prelude\"; [1, 2.5]") { array_of(union_of int32, float64) }
10 | end
11 |
12 | it "types empty typed array literal of int" do
13 | assert_type("require \"prelude\"; [] of Int32") { array_of(int32) }
14 | end
15 |
16 | it "types non-empty typed array literal of int" do
17 | assert_type("require \"prelude\"; [1, 2, 3] of Int32") { array_of(int32) }
18 | end
19 |
20 | it "types array literal size correctly" do
21 | assert_type("require \"prelude\"; [1].size") { int32 }
22 | end
23 |
24 | it "recalculates array literal type after element type changes" do
25 | assert_type(%(
26 | require "prelude"
27 | $a = 1
28 | x = [$a]
29 | $a = 1.1
30 | x
31 | )) { array_of(union_of int32, float64) }
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/spec/std/yaml/yaml_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 | require "yaml"
3 |
4 | describe "YAML" do
5 | describe "parser" do
6 | assert { YAML.load("foo").should eq("foo") }
7 | assert { YAML.load("- foo\n- bar").should eq(["foo", "bar"]) }
8 | assert { YAML.load_all("---\nfoo\n---\nbar\n").should eq(["foo", "bar"]) }
9 | assert { YAML.load("foo: bar").should eq({"foo" => "bar"}) }
10 | assert { YAML.load("--- []\n").should eq([] of YAML::Type) }
11 | assert { YAML.load("---\n...").should eq("") }
12 |
13 | it "parses recursive sequence" do
14 | doc = YAML.load("--- &foo\n- *foo\n") as Array
15 | doc[0].should be(doc)
16 | end
17 |
18 | it "parses recursive mapping" do
19 | doc = YAML.load(%(--- &1
20 | friends:
21 | - *1
22 | )) as Hash
23 | (doc["friends"] as Array)[0].should be(doc)
24 | end
25 |
26 | it "parses alias to scalar" do
27 | doc = YAML.load("---\n- &x foo\n- *x\n") as Array
28 | doc.should eq(["foo", "foo"])
29 | doc[0].should be(doc[1])
30 | end
31 | end
32 | end
33 |
--------------------------------------------------------------------------------
/src/regex/lib_pcre.cr:
--------------------------------------------------------------------------------
1 | @[Link("pcre")]
2 | lib LibPCRE
3 | alias Int = LibC::Int
4 |
5 | type Pcre = Void*
6 | type PcreExtra = Void*
7 | fun compile = pcre_compile(pattern : UInt8*, options : Int, errptr : UInt8**, erroffset : Int*, tableptr : Void*) : Pcre
8 | fun study = pcre_study(code : Pcre, options : Int, errptr : UInt8**) : PcreExtra
9 | fun exec = pcre_exec(code : Pcre, extra : PcreExtra, subject : UInt8*, length : Int, offset : Int, options : Int,
10 | ovector : Int*, ovecsize : Int) : Int32
11 | fun full_info = pcre_fullinfo(code : Pcre, extra : PcreExtra, what : Int, where : Int32*) : Int
12 | fun get_stringnumber = pcre_get_stringnumber(code : Pcre, string_name : UInt8*) : Int
13 |
14 | INFO_CAPTURECOUNT = 2
15 | INFO_NAMEENTRYSIZE = 7
16 | INFO_NAMECOUNT = 8
17 | INFO_NAMETABLE = 9
18 |
19 | alias Malloc = LibC::SizeT -> Void*
20 | alias Free = Void* ->
21 |
22 | $pcre_malloc : Malloc
23 | $pcre_free : Free
24 | end
25 |
26 | LibPCRE.pcre_malloc = ->GC.malloc(LibC::SizeT)
27 | LibPCRE.pcre_free = ->GC.free(Void*)
28 |
--------------------------------------------------------------------------------
/src/xml/node_set.cr:
--------------------------------------------------------------------------------
1 | struct XML::NodeSet
2 | include Enumerable(Node)
3 |
4 | def initialize(@doc : Node, @set : LibXML::NodeSet*)
5 | end
6 |
7 | def self.new(doc : Node)
8 | new doc, LibXML.xmlXPathNodeSetCreate(nil)
9 | end
10 |
11 | def [](index : Int)
12 | index += size if index < 0
13 |
14 | unless 0 <= index < size
15 | raise IndexError.new
16 | end
17 |
18 | internal_at(index)
19 | end
20 |
21 | def each
22 | size.times do |i|
23 | yield internal_at(i)
24 | end
25 | end
26 |
27 | def empty?
28 | size == 0
29 | end
30 |
31 | def hash
32 | object_id
33 | end
34 |
35 | def inspect(io)
36 | io << "["
37 | join ", ", io, &.inspect(io)
38 | io << "]"
39 | end
40 |
41 | def size
42 | @set.value.node_nr
43 | end
44 |
45 | def object_id
46 | @set.address
47 | end
48 |
49 | def to_s(io)
50 | join "\n", io
51 | end
52 |
53 | def to_unsafe
54 | @set
55 | end
56 |
57 | private def internal_at(index)
58 | Node.new(@set.value.node_tab[index])
59 | end
60 | end
61 |
--------------------------------------------------------------------------------
/spec/std/semantic_version_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 | require "semantic_version"
3 |
4 | describe SemanticVersion do
5 | it "compares <" do
6 | sversions = %w(
7 | 1.2.3-2
8 | 1.2.3-10
9 | 1.2.3-alpha
10 | 1.2.3-alpha.2
11 | 1.2.3-alpha.10
12 | 1.2.3-beta
13 | 1.2.3
14 | 1.2.4-alpha
15 | 1.2.4-beta
16 | 1.2.4
17 | )
18 | versions = sversions.map { |s| SemanticVersion.parse(s) }.to_a
19 |
20 | versions.each_with_index do |v, i|
21 | v.to_s.should eq(sversions[i])
22 | end
23 |
24 | versions.each_cons(2) do |pair|
25 | pair[0].should be < pair[1]
26 | end
27 | end
28 |
29 | it "compares build equivalence" do
30 | sversions = [
31 | "1.2.3+1",
32 | "1.2.3+999",
33 | "1.2.3+a",
34 | ]
35 | versions = sversions.map { |s| SemanticVersion.parse(s) }.to_a
36 |
37 | versions.each_with_index do |v, i|
38 | v.to_s.should eq(sversions[i])
39 | end
40 |
41 | versions.each_cons(2) do |pair|
42 | pair[0].should eq(pair[1])
43 | end
44 | end
45 | end
46 |
--------------------------------------------------------------------------------
/src/llvm/function.cr:
--------------------------------------------------------------------------------
1 | require "./value_methods"
2 |
3 | struct LLVM::Function
4 | include LLVM::ValueMethods
5 |
6 | def basic_blocks
7 | BasicBlockCollection.new self
8 | end
9 |
10 | def call_convention
11 | LLVM::CallConvention.new LibLLVM.get_function_call_convention(self)
12 | end
13 |
14 | def call_convention=(cc)
15 | LibLLVM.set_function_call_convention(self, cc)
16 | end
17 |
18 | def add_attribute(attribute)
19 | LibLLVM.add_function_attr self, attribute
20 | end
21 |
22 | def add_target_dependent_attribute(name, value)
23 | LibLLVM.add_target_dependent_function_attr self, name, value
24 | end
25 |
26 | def attributes
27 | LibLLVM.get_function_attr(self)
28 | end
29 |
30 | def function_type
31 | Type.new LibLLVM.get_element_type(LibLLVM.type_of(self))
32 | end
33 |
34 | def return_type
35 | Type.new LibLLVM.get_return_type(function_type)
36 | end
37 |
38 | def varargs?
39 | LibLLVM.is_function_var_arg(function_type) != 0
40 | end
41 |
42 | def params
43 | ParameterCollection.new self
44 | end
45 | end
46 |
--------------------------------------------------------------------------------
/spec/compiler/codegen/previous_def_spec.cr:
--------------------------------------------------------------------------------
1 | require "../../spec_helper"
2 |
3 | describe "codegen: previous_def" do
4 | it "codegens previous def" do
5 | run(%(
6 | def foo
7 | 1
8 | end
9 |
10 | def foo
11 | previous_def + 1
12 | end
13 |
14 | foo
15 | )).to_i.should eq(2)
16 | end
17 |
18 | it "codeges previous def when inside fun and forwards args" do
19 | run(%(
20 | def foo(z)
21 | z + 1
22 | end
23 |
24 | def foo(z)
25 | ->(x : Int32) { x + previous_def }
26 | end
27 |
28 | x = foo(2)
29 | x.call(3)
30 | )).to_i.should eq(6)
31 | end
32 |
33 | it "codegens previous def when inside fun with self" do
34 | run(%(
35 | class Foo
36 | def initialize
37 | @x = 1
38 | end
39 |
40 | def bar
41 | @x
42 | end
43 | end
44 |
45 | class Foo
46 | def bar
47 | x = ->{ previous_def }
48 | end
49 | end
50 |
51 | Foo.new.bar.call
52 | )).to_i.should eq(1)
53 | end
54 | end
55 |
--------------------------------------------------------------------------------
/spec/std/openssl/hmac_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 | require "openssl/hmac"
3 |
4 | describe OpenSSL::HMAC do
5 | [
6 | {:dss, "46b4ec586117154dacd49d664e5d63fdc88efb51"},
7 | {:dss1, "46b4ec586117154dacd49d664e5d63fdc88efb51"},
8 | {:md4, "f3593b56f00b25c8af31d02ddef6d2d0"},
9 | {:md5, "0c7a250281315ab863549f66cd8a3a53"},
10 | {:sha, "df3c18b162b0c3b1884ba1b8eaf60559c41abc50"},
11 | {:sha1, "46b4ec586117154dacd49d664e5d63fdc88efb51"},
12 | {:sha224, "4c1f774863acb63b7f6e9daa9b5c543fa0d5eccf61e3ffc3698eacdd"},
13 | {:sha256, "f9320baf0249169e73850cd6156ded0106e2bb6ad8cab01b7bbbebe6d1065317"},
14 | {:sha384, "3d10d391bee2364df2c55cf605759373e1b5a4ca9355d8f3fe42970471eca2e422a79271a0e857a69923839015877fc6"},
15 | {:sha512, "114682914c5d017dfe59fdc804118b56a3a652a0b8870759cf9e792ed7426b08197076bf7d01640b1b0684df79e4b67e37485669e8ce98dbab60445f0db94fce"},
16 | {:ripemd160, "20d23140503df606c91bda9293f1ad4a23afe509"},
17 | ].each do |tuple|
18 | it "computes #{tuple[0]}" do
19 | OpenSSL::HMAC.hexdigest(tuple[0], "foo", "bar").should eq(tuple[1])
20 | end
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/spec/compiler/type_inference/method_missing_spec.cr:
--------------------------------------------------------------------------------
1 | require "../../spec_helper"
2 |
3 | describe "Type inference: method_missing" do
4 | it "does error in method_missing macro with virtual type" do
5 | assert_error %(
6 | abstract class Foo
7 | end
8 |
9 | class Bar < Foo
10 | macro method_missing(name, args, block)
11 | 2
12 | end
13 | end
14 |
15 | class Baz < Foo
16 | end
17 |
18 | foo = Baz.new || Bar.new
19 | foo.lala
20 | ), "undefined method 'lala' for Baz"
21 | end
22 |
23 | it "does error in method_missing if wrong number of args" do
24 | assert_error %(
25 | class Foo
26 | macro method_missing(name, args)
27 | end
28 | end
29 | ), "macro 'method_missing' expects 1 or 3 arguments: (call) or (name, args, block)"
30 | end
31 |
32 | it "does method missing for generic type" do
33 | assert_type(%(
34 | class Foo(T)
35 | macro method_missing(name, args, block)
36 | 1
37 | end
38 | end
39 |
40 | Foo(Int32).new.foo
41 | )) { int32 }
42 | end
43 | end
44 |
--------------------------------------------------------------------------------
/src/openssl/ssl/socket.cr:
--------------------------------------------------------------------------------
1 | class OpenSSL::SSL::Socket
2 | include IO
3 |
4 | def initialize(io, mode = :client, context = Context.default)
5 | @ssl = LibSSL.ssl_new(context)
6 | @bio = BIO.new(io)
7 | LibSSL.ssl_set_bio(@ssl, @bio, @bio)
8 |
9 | if mode == :client
10 | LibSSL.ssl_connect(@ssl)
11 | else
12 | LibSSL.ssl_accept(@ssl)
13 | end
14 | end
15 |
16 | def finalize
17 | LibSSL.ssl_free(@ssl)
18 | end
19 |
20 | def read(slice : Slice(UInt8))
21 | count = slice.size
22 | return 0 if count == 0
23 | LibSSL.ssl_read(@ssl, slice.pointer(count), count)
24 | end
25 |
26 | def write(slice : Slice(UInt8))
27 | count = slice.size
28 | LibSSL.ssl_write(@ssl, slice.pointer(count), count)
29 | nil
30 | end
31 |
32 | def close
33 | begin
34 | while LibSSL.ssl_shutdown(@ssl) == 0; end
35 | rescue IO::Error
36 | end
37 | end
38 |
39 | def self.open_client(io, context = Context.default)
40 | ssl_sock = new(io, :client, context)
41 | begin
42 | yield ssl_sock
43 | ensure
44 | ssl_sock.close
45 | end
46 | end
47 | end
48 |
--------------------------------------------------------------------------------
/src/prelude.cr:
--------------------------------------------------------------------------------
1 | require "intrinsics"
2 | require "reflect"
3 | require "libc"
4 | require "macros"
5 | require "object"
6 | require "reference"
7 | require "exception"
8 | require "value"
9 | require "struct"
10 | require "proc"
11 | require "thread"
12 | require "gc"
13 | # require "gc/null"
14 | require "gc/boehm"
15 | require "class"
16 | require "comparable"
17 | require "enumerable"
18 | require "iterable"
19 | require "iterator"
20 | require "nil"
21 | require "bool"
22 | require "char"
23 | require "number"
24 | require "int"
25 | require "float"
26 | require "pointer"
27 | require "slice"
28 | require "range"
29 | require "char/reader"
30 | require "string"
31 | require "symbol"
32 | require "enum"
33 | require "static_array"
34 | require "array"
35 | require "hash"
36 | require "set"
37 | require "tuple"
38 | require "box"
39 | require "math/math"
40 | require "process"
41 | require "io"
42 | require "env"
43 | require "file"
44 | require "dir"
45 | require "time"
46 | require "random"
47 | require "regex"
48 | require "raise"
49 | require "errno"
50 | require "concurrent"
51 | require "signal"
52 | require "kernel"
53 | require "main"
54 |
--------------------------------------------------------------------------------
/src/compiler/crystal/tools/doc/templates.cr:
--------------------------------------------------------------------------------
1 | require "ecr/macros"
2 |
3 | module Crystal::Doc
4 | record TypeTemplate, type, types do
5 | ecr_file "#{__DIR__}/html/type.html"
6 | end
7 |
8 | record ListItemsTemplate, types, current_type do
9 | ecr_file "#{__DIR__}/html/list_items.html"
10 | end
11 |
12 | record MethodSummaryTemplate, title, methods do
13 | ecr_file "#{__DIR__}/html/method_summary.html"
14 | end
15 |
16 | record MethodDetailTemplate, title, methods do
17 | ecr_file "#{__DIR__}/html/method_detail.html"
18 | end
19 |
20 | record MethodsInheritedTemplate, type, ancestor, methods, label do
21 | ecr_file "#{__DIR__}/html/methods_inherited.html"
22 | end
23 |
24 | record OtherTypesTemplate, title, type, other_types do
25 | ecr_file "#{__DIR__}/html/other_types.html"
26 | end
27 |
28 | record MainTemplate, body, types, repository_name do
29 | ecr_file "#{__DIR__}/html/main.html"
30 | end
31 |
32 | struct JsTypeTemplate
33 | ecr_file "#{__DIR__}/html/js/doc.js"
34 | end
35 |
36 | struct StyleTemplate
37 | ecr_file "#{__DIR__}/html/css/style.css"
38 | end
39 | end
40 |
--------------------------------------------------------------------------------
/spec/std/http/server/handlers/websocket_handler_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 | require "http/server"
3 |
4 | describe HTTP::WebSocketHandler do
5 | it "returns not found if the request is not an websocket upgrade" do
6 | handler = HTTP::WebSocketHandler.new { }
7 | response = handler.call HTTP::Request.new("GET", "/")
8 | response.status_code.should eq(404)
9 | response.upgrade_handler.should be_nil
10 | end
11 |
12 | it "gives upgrade response for websocket upgrade request" do
13 | handler = HTTP::WebSocketHandler.new { }
14 | headers = HTTP::Headers{
15 | "Upgrade": "websocket",
16 | "Connection": "Upgrade",
17 | "Sec-WebSocket-Key": "dGhlIHNhbXBsZSBub25jZQ==",
18 | }
19 | request = HTTP::Request.new("GET", "/", headers)
20 | response = handler.call request
21 | response.status_code.should eq(101)
22 | response.headers["Upgrade"].should eq("websocket")
23 | response.headers["Connection"].should eq("Upgrade")
24 | response.headers["Sec-WebSocket-Accept"].should eq("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=")
25 | response.upgrade_handler.should_not be_nil
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/spec/compiler/type_inference/dependencies_spec.cr:
--------------------------------------------------------------------------------
1 | require "../../spec_helper"
2 |
3 | describe "Crystal::Dependencies" do
4 | it "is empty" do
5 | deps = Dependencies.new
6 | deps.size.should eq(0)
7 | deps.to_a.should eq([] of ASTNode)
8 | end
9 |
10 | it "pushes one" do
11 | deps = Dependencies.new
12 | node = NilLiteral.new
13 | deps.push node
14 | deps.size.should eq(1)
15 | deps.to_a.map(&.object_id).should eq([node.object_id])
16 | end
17 |
18 | it "pushes two" do
19 | deps = Dependencies.new
20 | node1 = NilLiteral.new
21 | node2 = NilLiteral.new
22 | deps.push node1
23 | deps.push node2
24 | deps.size.should eq(2)
25 | deps.to_a.map(&.object_id).should eq([node1.object_id, node2.object_id])
26 | end
27 |
28 | it "pushes three" do
29 | deps = Dependencies.new
30 | node1 = NilLiteral.new
31 | node2 = NilLiteral.new
32 | node3 = NilLiteral.new
33 | deps.push node1
34 | deps.push node2
35 | deps.push node3
36 | deps.size.should eq(3)
37 | deps.to_a.map(&.object_id).should eq([node1.object_id, node2.object_id, node3.object_id])
38 | end
39 | end
40 |
--------------------------------------------------------------------------------
/spec/std/bool_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 |
3 | describe "Bool" do
4 | describe "!" do
5 | assert { (!true).should be_false }
6 | assert { (!false).should be_true }
7 | end
8 |
9 | describe "|" do
10 | assert { (false | false).should be_false }
11 | assert { (false | true).should be_true }
12 | assert { (true | false).should be_true }
13 | assert { (true | true).should be_true }
14 | end
15 |
16 | describe "&" do
17 | assert { (false & false).should be_false }
18 | assert { (false & true).should be_false }
19 | assert { (true & false).should be_false }
20 | assert { (true & true).should be_true }
21 | end
22 |
23 | describe "^" do
24 | assert { (false ^ false).should be_false }
25 | assert { (false ^ true).should be_true }
26 | assert { (true ^ false).should be_true }
27 | assert { (true ^ true).should be_false }
28 | end
29 |
30 | describe "hash" do
31 | assert { true.hash.should eq(1) }
32 | assert { false.hash.should eq(0) }
33 | end
34 |
35 | describe "to_s" do
36 | assert { true.to_s.should eq("true") }
37 | assert { false.to_s.should eq("false") }
38 | end
39 | end
40 |
--------------------------------------------------------------------------------
/spec/std/openssl/digest_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 | require "../src/openssl"
3 |
4 | describe OpenSSL::Digest do
5 | [
6 | {"SHA1", "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"},
7 | {"SHA256", "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae"},
8 | {"SHA512", "f7fbba6e0636f890e56fbbf3283e524c6fa3204ae298382d624741d0dc6638326e282c41be5e4254d8820772c5518a2c5a8c0c7f7eda19594a7eb539453e1ed7"},
9 | ].each do |tuple|
10 | it "should be able to calculate #{tuple[0]}" do
11 | digest = OpenSSL::Digest.new(tuple[0])
12 | digest << "foo"
13 | digest.hexdigest.should eq(tuple[1])
14 | end
15 | end
16 |
17 | it "raises a UnsupportedError if digest is unsupported" do
18 | expect_raises OpenSSL::Digest::UnsupportedError do
19 | OpenSSL::Digest.new("unsupported")
20 | end
21 | end
22 |
23 | it "returns the digest size" do
24 | OpenSSL::Digest.new("SHA1").digest_size.should eq 20
25 | OpenSSL::Digest.new("SHA256").digest_size.should eq 32
26 | end
27 |
28 | it "returns the block size" do
29 | OpenSSL::Digest.new("SHA1").block_size.should eq 64
30 | OpenSSL::Digest.new("SHA256").block_size.should eq 64
31 | end
32 | end
33 |
--------------------------------------------------------------------------------
/src/llvm/jit_compiler.cr:
--------------------------------------------------------------------------------
1 | class LLVM::JITCompiler
2 | def initialize(mod)
3 | # JIT compilers own an LLVM::Module, and when they are disposed the module is disposed,
4 | # so we must prevent the module from being dispose when the GC will want to free it.
5 | mod.take_ownership { raise "can't create two JIT compilers for the same module" }
6 |
7 | # if LibLLVM.create_jit_compiler_for_module(out @unwrap, mod, 3, out error) != 0
8 | if LibLLVM.create_mc_jit_compiler_for_module(out @unwrap, mod, nil, 0, out error) != 0
9 | raise LLVM.string_and_dispose(error)
10 | end
11 | end
12 |
13 | def run_function(func)
14 | ret = LibLLVM.run_function(self, func, 0, nil)
15 | GenericValue.new(ret)
16 | end
17 |
18 | def run_function(func, args : Array(LLVM::GenericValue))
19 | ret = LibLLVM.run_function(self, func, args.size, (args.buffer as LibLLVM::GenericValueRef*))
20 | GenericValue.new(ret)
21 | end
22 |
23 | def get_pointer_to_global(value)
24 | LibLLVM.get_pointer_to_global(self, value)
25 | end
26 |
27 | def to_unsafe
28 | @unwrap
29 | end
30 |
31 | def finalize
32 | LibLLVM.dispose_execution_engine(@unwrap)
33 | end
34 | end
35 |
--------------------------------------------------------------------------------
/spec/std/tempfile_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 | require "tempfile"
3 |
4 | describe Tempfile do
5 | it "creates and writes" do
6 | tempfile = Tempfile.new "foo"
7 | tempfile.print "Hello!"
8 | tempfile.close
9 |
10 | File.exists?(tempfile.path).should be_true
11 | File.read(tempfile.path).should eq("Hello!")
12 | end
13 |
14 | it "creates and deletes" do
15 | tempfile = Tempfile.new "foo"
16 | tempfile.close
17 | tempfile.delete
18 |
19 | File.exists?(tempfile.path).should be_false
20 | end
21 |
22 | it "doesn't delete on open with block" do
23 | tempfile = Tempfile.open("foo") do |f|
24 | f.print "Hello!"
25 | end
26 | File.exists?(tempfile.path).should be_true
27 | end
28 |
29 | it "creates and writes with TMPDIR environment variable" do
30 | old_tmpdir = ENV["TMPDIR"]?
31 | ENV["TMPDIR"] = "/tmp"
32 |
33 | begin
34 | tempfile = Tempfile.new "foo"
35 | tempfile.print "Hello!"
36 | tempfile.close
37 |
38 | File.exists?(tempfile.path).should be_true
39 | File.read(tempfile.path).should eq("Hello!")
40 | ensure
41 | ENV["TMPDIR"] = old_tmpdir if old_tmpdir
42 | end
43 | end
44 | end
45 |
--------------------------------------------------------------------------------
/src/compiler/crystal/tools/init/template/readme.md.ecr:
--------------------------------------------------------------------------------
1 | # <%= config.name %>
2 |
3 | TODO: Write a description here
4 |
5 | ## Installation
6 |
7 | <% if config.skeleton_type == "lib" %>
8 | Add this to your application's `shard.yml`:
9 |
10 | ```yaml
11 | dependencies:
12 | <%= config.name %>:
13 | github: <%= config.github_name %>/<%= config.name %>
14 | ```
15 | <% else %>
16 | TODO: Write installation instructions here
17 | <% end %>
18 |
19 | ## Usage
20 |
21 | <% if config.skeleton_type == "lib" %>
22 | ```crystal
23 | require "<%= config.name %>"
24 | ```
25 | <% end %>
26 |
27 | TODO: Write usage instructions here
28 |
29 | ## Development
30 |
31 | TODO: Write development instructions here
32 |
33 | ## Contributing
34 |
35 | 1. Fork it ( https://github.com/<%= config.github_name %>/<%= config.name %>/fork )
36 | 2. Create your feature branch (git checkout -b my-new-feature)
37 | 3. Commit your changes (git commit -am 'Add some feature')
38 | 4. Push to the branch (git push origin my-new-feature)
39 | 5. Create a new Pull Request
40 |
41 | ## Contributors
42 |
43 | - [<%= config.github_name %>](https://github.com/<%= config.github_name %>) <%= config.author %> - creator, maintainer
44 |
--------------------------------------------------------------------------------
/src/llvm/pass_manager_builder.cr:
--------------------------------------------------------------------------------
1 | class LLVM::PassManagerBuilder
2 | def initialize
3 | @unwrap = LibLLVM.pass_manager_builder_create
4 | end
5 |
6 | def opt_level=(level)
7 | LibLLVM.pass_manager_builder_set_opt_level self, level
8 | end
9 |
10 | def size_level=(level)
11 | LibLLVM.pass_manager_builder_set_size_level self, level
12 | end
13 |
14 | def disable_unroll_loops=(value)
15 | LibLLVM.pass_manager_builder_set_disable_unroll_loops self, value ? 1 : 0
16 | end
17 |
18 | def disable_simplify_lib_calls=(value)
19 | LibLLVM.pass_manager_builder_set_disable_simplify_lib_calls self, value ? 1 : 0
20 | end
21 |
22 | def use_inliner_with_threshold=(threshold)
23 | LibLLVM.pass_manager_builder_use_inliner_with_threshold self, threshold
24 | end
25 |
26 | def populate(pm : FunctionPassManager)
27 | LibLLVM.pass_manager_builder_populate_function_pass_manager self, pm
28 | end
29 |
30 | def populate(pm : ModulePassManager)
31 | LibLLVM.pass_manager_builder_populate_module_pass_manager self, pm
32 | end
33 |
34 | def to_unsafe
35 | @unwrap
36 | end
37 |
38 | def finalize
39 | LibLLVM.dispose_pass_manager_builder(@unwrap)
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/src/compiler/crystal/tools/init/template/license.ecr:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) <%= Time.now.year %> <%= config.author %>
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/BACKERS.md:
--------------------------------------------------------------------------------
1 | # Bountysource Backers
2 |
3 | Thank you to everyone who backed our [Bountysource fundraiser](https://www.bountysource.com/teams/crystal-lang/fundraiser)!
4 |
5 | ### Your name and URL in BACKERS.md.
6 |
7 | - Adam Daniels, https://github.com/adam12
8 | - Bo Jeanes, http://bjeanes.com/
9 | - Bruno Antunes, https://github.com/sardaukar
10 | - gottlike, https://github.com/gottlike
11 | - Hirofumi Wakasugi, https://github.com/5t111111
12 | - Jean-Baptiste Barth, http://jbbarth.com/
13 | - jhp
14 | - Kris Leech, http://teamcoding.com/
15 | - Luis Lavena, http://blog.mmediasys.com/
16 | - Sb
17 | - Scott Fleckenstein, https://about.me/nullstyle
18 | - Serdar Dogruyol, http://www.serdardogruyol.com/
19 | - Sergey Kucher, https://github.com/sergey-kucher
20 | - Simon George, http://www.sfcgeorge.co.uk/about
21 | - Yukihiro "Matz" Matsumoto, https://github.com/matz
22 |
23 | ### Your name in BACKERS.md.
24 |
25 | - Ashley Towns
26 | - Ben Miller
27 | - benoist
28 | - Dor Kalev
29 | - Hayashida Ryuichi
30 | - Jesse Doyle
31 | - Joakim Ekström
32 | - Jonne Haß
33 | - Joseph Method
34 | - Keiji Matsuzaki
35 | - marcpmichel
36 | - rhoeft
37 | - Ryan Worl
38 | - schaarw
39 | - Sergio Gil
40 | - Shannon Skipper
41 | - Sho Kusano
42 |
--------------------------------------------------------------------------------
/src/xml/attributes.cr:
--------------------------------------------------------------------------------
1 | struct XML::Attributes
2 | include Enumerable(Node)
3 |
4 | def initialize(@node)
5 | end
6 |
7 | def empty?
8 | return true unless @node.element?
9 |
10 | props = self.props
11 | props.nil?
12 | end
13 |
14 | def [](index : Int)
15 | size = self.size
16 |
17 | index += size if index < 0
18 |
19 | unless 0 <= index < size
20 | raise IndexError.new
21 | end
22 |
23 | each_with_index do |node, i|
24 | return node if i == index
25 | end
26 |
27 | raise IndexError.new
28 | end
29 |
30 | def [](name : String)
31 | self[name]? || raise KeyError.new("Missing attribute: #{name}")
32 | end
33 |
34 | def []?(name : String)
35 | find { |node| node.name == name }
36 | end
37 |
38 | def each
39 | return unless @node.element?
40 |
41 | props = self.props
42 | until props.nil?
43 | yield Node.new(props)
44 | props = props.value.next
45 | end
46 | end
47 |
48 | def to_s(io)
49 | io << "["
50 | join ", ", io, &.inspect(io)
51 | io << "]"
52 | end
53 |
54 | def inspect(io)
55 | to_s(io)
56 | end
57 |
58 | protected def props
59 | @node.to_unsafe.value.properties
60 | end
61 | end
62 |
--------------------------------------------------------------------------------
/src/openssl/hmac.cr:
--------------------------------------------------------------------------------
1 | require "./lib_crypto"
2 |
3 | class OpenSSL::HMAC
4 | def self.digest(algorithm : Symbol, key, data)
5 | evp = case algorithm
6 | when :dss then LibCrypto.evp_dss
7 | when :dss1 then LibCrypto.evp_dss1
8 | when :md4 then LibCrypto.evp_md4
9 | when :md5 then LibCrypto.evp_md5
10 | when :ripemd160 then LibCrypto.evp_ripemd160
11 | when :sha then LibCrypto.evp_sha
12 | when :sha1 then LibCrypto.evp_sha1
13 | when :sha224 then LibCrypto.evp_sha224
14 | when :sha256 then LibCrypto.evp_sha256
15 | when :sha384 then LibCrypto.evp_sha384
16 | when :sha512 then LibCrypto.evp_sha512
17 | else raise "Unsupported digest algorithm: #{algorithm}"
18 | end
19 | key_slice = key.to_slice
20 | data_slice = data.to_slice
21 | buffer = Slice(UInt8).new(128)
22 | LibCrypto.hmac(evp, key_slice, key_slice.size, data_slice, data_slice.size, buffer, out buffer_len)
23 | buffer[0, buffer_len.to_i]
24 | end
25 |
26 | def self.hexdigest(algorithm : Symbol, key, data)
27 | digest(algorithm, key, data).hexstring
28 | end
29 | end
30 |
--------------------------------------------------------------------------------
/samples/impl.cr:
--------------------------------------------------------------------------------
1 | class A
2 | property lorem
3 |
4 | def foo
5 | 1
6 | end
7 | end
8 |
9 | class B
10 | def foo
11 | 2
12 | end
13 | end
14 |
15 | def bar(o)
16 | while false
17 | o.foo
18 | end
19 | end
20 |
21 | def baz(o)
22 | o.foo
23 | end
24 |
25 | puts bar(A.new)
26 | puts bar(B.new)
27 | puts baz(A.new)
28 |
29 | A.new.lorem
30 |
31 | # ./crystal tool implementations samples/impl.cr --cursor samples/impl.cr:16:8
32 | #
33 | # 2 implementations found
34 | # .../samples/impl.cr:3:3
35 | # .../samples/impl.cr:9:3
36 |
37 | # ./crystal tool implementations samples/impl.cr --cursor samples/impl.cr:21:5
38 | #
39 | # 1 implementation found
40 | # .../samples/impl.cr:3:3
41 |
42 | # ./crystal tool implementations samples/impl.cr --cursor samples/impl.cr:24:7
43 | #
44 | # 1 implementation found
45 | # .../samples/impl.cr:14:1
46 |
47 | # ./crystal tool implementations samples/impl.cr --cursor samples/impl.cr:26:3
48 | #
49 | # 1 implementation found
50 | # .../src/kernel.cr:67:1
51 |
52 | # ./crystal tool implementations samples/impl.cr --cursor samples/impl.cr:28:9
53 | #
54 | # 1 implementation found
55 | # .../samples/impl.cr:2:3
56 | # ~> macro property: .../src/object.cr:364:5
57 | # ~> macro getter: .../src/object.cr:207:7
58 |
--------------------------------------------------------------------------------
/spec/std/openssl/cipher_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 | require "openssl/cipher"
3 |
4 | describe OpenSSL::Cipher do
5 | it "encrypts/decrypts" do
6 | cipher = "aes-128-cbc"
7 | c1 = OpenSSL::Cipher.new(cipher)
8 | c2 = OpenSSL::Cipher.new(cipher)
9 | key = "\0" * 16
10 | iv = "\0" * 16
11 | data = "DATA" * 5
12 | ciphertext = File.read(File.join(__DIR__ + "/cipher_spec.ciphertext"))
13 |
14 | c1.name.should eq(c2.name)
15 |
16 | c1.encrypt
17 | c2.encrypt
18 | c1.key = c2.key = key
19 | c1.iv = c2.iv = iv
20 |
21 | s1 = MemoryIO.new
22 | s2 = MemoryIO.new
23 | s1.write(c1.update("DATA"))
24 | s1.write(c1.update("DATA" * 4))
25 | s1.write(c1.final)
26 | s2.write(c2.update(data))
27 | s2.write(c2.final)
28 |
29 | s1.to_slice.should eq(ciphertext.to_slice)
30 | s1.to_slice.should eq(s2.to_slice)
31 |
32 | c1.decrypt
33 | c2.decrypt
34 | c1.key = c2.key = key
35 | c1.iv = c2.iv = iv
36 |
37 | s3 = MemoryIO.new
38 | s4 = MemoryIO.new
39 | s3.write(c1.update(s1.to_slice))
40 | s3.write(c1.final)
41 |
42 | s4.write(c2.update(s2.to_slice))
43 | s4.write(c2.final)
44 | s3.to_s.should eq(data)
45 | s3.to_slice.should eq(s4.to_slice)
46 | end
47 | end
48 |
--------------------------------------------------------------------------------
/src/compiler/crystal/tools/print_types_visitor.cr:
--------------------------------------------------------------------------------
1 | require "set"
2 | require "../syntax/ast"
3 |
4 | module Crystal
5 | def self.print_types(node)
6 | node.accept PrintTypesVisitor.new
7 | end
8 |
9 | class PrintTypesVisitor < Visitor
10 | def initialize
11 | @vars = Set(String).new
12 | end
13 |
14 | def visit(node)
15 | true
16 | end
17 |
18 | def visit(node : ClassDef)
19 | false
20 | end
21 |
22 | def visit(node : Def)
23 | false
24 | end
25 |
26 | def visit(node : FunDef)
27 | false
28 | end
29 |
30 | def visit(node : Macro)
31 | false
32 | end
33 |
34 | def visit(node : Assign)
35 | !node.target.is_a?(Path)
36 | end
37 |
38 | def visit(node : Var)
39 | output_name node
40 | end
41 |
42 | def visit(node : Global)
43 | output_name node
44 | end
45 |
46 | def visit(node : DeclareVar)
47 | var = node.var
48 | if var.is_a?(Var)
49 | output_name var
50 | end
51 | end
52 |
53 | def output_name(node)
54 | if !node.name.starts_with?('#') && !@vars.includes?(node.name)
55 | puts "#{node.name} : #{node.type?}"
56 | @vars.add node.name
57 | end
58 | end
59 | end
60 | end
61 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | .PHONY: all spec crystal doc clean
2 |
3 | -include Makefile.local # for optional local options e.g. threads
4 |
5 | O := .build
6 | SOURCES := $(shell find src -name '*.cr')
7 | SPEC_SOURCES := $(shell find spec -name '*.cr')
8 | FLAGS := $(if $(release),--release )$(if $(stats),--stats )$(if $(threads),--threads $(threads) )
9 | EXPORTS := $(if $(release),,CRYSTAL_CONFIG_PATH=`pwd`/src)
10 | SHELL = /bin/bash
11 | LLVM_CONFIG := $(shell command -v llvm-config-3.6 llvm-config-3.5 llvm-config | head -n 1)
12 | LLVM_EXT_DIR = src/llvm/ext
13 | LLVM_EXT_OBJ = $(LLVM_EXT_DIR)/llvm_ext.o
14 |
15 | all: crystal
16 | spec: all_spec
17 | $(O)/all_spec
18 | doc:
19 | $(BUILD_PATH) ./bin/crystal doc docs/main.cr
20 |
21 | crystal: $(O)/crystal
22 | all_spec: $(O)/all_spec
23 |
24 | llvm_ext: $(LLVM_EXT_OBJ)
25 |
26 | $(O)/all_spec: $(LLVM_EXT_OBJ) $(SOURCES) $(SPEC_SOURCES)
27 | @mkdir -p $(O)
28 | $(BUILD_PATH) ./bin/crystal build $(FLAGS) -o $@ spec/all_spec.cr
29 |
30 | $(O)/crystal: $(LLVM_EXT_OBJ) $(SOURCES)
31 | @mkdir -p $(O)
32 | $(BUILD_PATH) $(EXPORTS) ./bin/crystal build $(FLAGS) -o $@ src/compiler/crystal.cr
33 |
34 | $(LLVM_EXT_OBJ): $(LLVM_EXT_DIR)/llvm_ext.cc
35 | $(CXX) -c -o $@ $< `$(LLVM_CONFIG) --cxxflags`
36 |
37 | clean:
38 | rm -rf $(O)
39 | rm -rf ./doc
40 | rm -rf $(LLVM_EXT_OBJ)
41 |
--------------------------------------------------------------------------------
/spec/std/http/server_spec.cr:
--------------------------------------------------------------------------------
1 | require "http/server"
2 |
3 | module HTTP
4 | typeof(begin
5 | # Initialize with custom host
6 | server = Server.new("0.0.0.0", 0) { |req| HTTP::Response.ok("text/plain", "OK") }
7 | server.listen
8 | server.listen_fork(workers: 2)
9 | server.close
10 |
11 | server = Server.new("0.0.0.0", 0, [
12 | ErrorHandler.new,
13 | LogHandler.new,
14 | DeflateHandler.new,
15 | StaticFileHandler.new("."),
16 | ]
17 | )
18 | server.listen
19 | server.close
20 |
21 | server = Server.new("0.0.0.0", 0, [StaticFileHandler.new(".")]) { |req| HTTP::Response.ok("text/plain", "OK") }
22 | server.listen
23 | server.close
24 |
25 | # Initialize with default host
26 | server = Server.new(0) { |req| HTTP::Response.ok("text/plain", "OK") }
27 | server.listen
28 | server.listen_fork(workers: 2)
29 | server.close
30 |
31 | server = Server.new(0, [
32 | ErrorHandler.new,
33 | LogHandler.new,
34 | DeflateHandler.new,
35 | StaticFileHandler.new("."),
36 | ]
37 | )
38 | server.listen
39 | server.close
40 |
41 | server = Server.new(0, [StaticFileHandler.new(".")]) { |req| HTTP::Response.ok("text/plain", "OK") }
42 | server.listen
43 | server.close
44 | end)
45 | end
46 |
--------------------------------------------------------------------------------
/src/process/status.cr:
--------------------------------------------------------------------------------
1 | # The status of a terminated process.
2 | class Process::Status
3 | getter exit_status
4 |
5 | def initialize(@exit_status)
6 | end
7 |
8 | # Returns `true` if the process was terminated by a signal.
9 | def signal_exit?
10 | # define __WIFSIGNALED(status) (((signed char) (((status) & 0x7f) + 1) >> 1) > 0)
11 | ((LibC::SChar.new(@exit_status & 0x7f) + 1) >> 1) > 0
12 | end
13 |
14 | # Returns `true` if the process terminated normally.
15 | def normal_exit?
16 | # define __WIFEXITED(status) (__WTERMSIG(status) == 0)
17 | signal_code == 0
18 | end
19 |
20 | # If `signal_exit?` is `true`, returns the *Signal* the process
21 | # received and didn't handle. Will raise if `signal_exit?` is `false`.
22 | def exit_signal
23 | Signal.from_value(signal_code)
24 | end
25 |
26 | # If `normal_exit?` is `true`, returns the exit code of the process.
27 | def exit_code
28 | # define __WEXITSTATUS(status) (((status) & 0xff00) >> 8)
29 | (@exit_status & 0xff00) >> 8
30 | end
31 |
32 | # Returns `true` if the process exited normally with an exit code of 0.
33 | def success?
34 | normal_exit? && exit_code == 0
35 | end
36 |
37 | private def signal_code
38 | # define __WTERMSIG(status) ((status) & 0x7f)
39 | @exit_status & 0x7f
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/spec/std/thread_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 |
3 | describe "Thread" do
4 | it "allows passing an argumentless fun to execute" do
5 | a = 0
6 | thread = Thread.new { a = 1; 10 }
7 | thread.join.should eq(10)
8 | a.should eq(1)
9 | end
10 |
11 | it "allows passing a fun with an argument to execute" do
12 | a = 0
13 | thread = Thread.new(3) { |i| a += i; 20 }
14 | thread.join.should eq(20)
15 | a.should eq(3)
16 | end
17 |
18 | it "raises inside thread and gets it on join" do
19 | thread = Thread.new { raise "OH NO" }
20 | expect_raises Exception, "OH NO" do
21 | thread.join
22 | end
23 | end
24 |
25 | it "gets a non-nilable value from join" do
26 | thread = Thread.new { 1 }
27 | value = thread.join
28 | (value + 2).should eq(3)
29 | end
30 | end
31 |
32 | describe "ConditionVariable" do
33 | pending "waits and send signal" do
34 | a = 0
35 | cv1 = ConditionVariable.new
36 | cv2 = ConditionVariable.new
37 | m = Mutex.new
38 |
39 | thread = Thread.new do
40 | 3.times do
41 | m.synchronize { cv1.wait(m); a += 1; cv2.signal }
42 | end
43 | end
44 |
45 | a.should eq(0)
46 | 3.times do |i|
47 | m.synchronize { cv1.signal; cv2.wait(m) }
48 | a.should eq(i + 1)
49 | end
50 |
51 | thread.join
52 | end
53 | end
54 |
--------------------------------------------------------------------------------
/spec/compiler/type_inference/c_enum_spec.cr:
--------------------------------------------------------------------------------
1 | require "../../spec_helper"
2 |
3 | describe "Type inference: c enum" do
4 | it "types enum value" do
5 | assert_type("lib LibFoo; enum Bar; X, Y, Z = 10, W; end; end; LibFoo::Bar::X") { types["LibFoo"].types["Bar"] }
6 | end
7 |
8 | it "allows using an enum as a type in a fun" do
9 | assert_type("
10 | lib LibC
11 | enum Foo
12 | A
13 | end
14 | fun my_mega_function(y : Foo) : Foo
15 | end
16 |
17 | LibC.my_mega_function(LibC::Foo::A)
18 | ") { types["LibC"].types["Foo"] }
19 | end
20 |
21 | it "allows using an enum as a type in a struct" do
22 | assert_type("
23 | lib LibC
24 | enum Foo
25 | A
26 | end
27 | struct Bar
28 | x : Foo
29 | end
30 | end
31 |
32 | f = LibC::Bar.new
33 | f.x = LibC::Foo::A
34 | f.x
35 | ") { types["LibC"].types["Foo"] }
36 | end
37 |
38 | it "types enum value with base type" do
39 | assert_type("lib LibFoo; enum Bar : Int16; X; end; end; LibFoo::Bar::X") { types["LibFoo"].types["Bar"] }
40 | end
41 |
42 | it "errors if enum base type is not an integer" do
43 | assert_error "lib LibFoo; enum Bar : Float32; X; end; end; LibFoo::Bar::X",
44 | "enum base type must be an integer type"
45 | end
46 | end
47 |
--------------------------------------------------------------------------------
/src/compiler/crystal/syntax/location.cr:
--------------------------------------------------------------------------------
1 | require "../../../partial_comparable"
2 |
3 | module Crystal
4 | class Location
5 | include PartialComparable(self)
6 |
7 | getter line_number
8 | getter column_number
9 | getter filename
10 |
11 | def initialize(@line_number, @column_number, @filename)
12 | end
13 |
14 | def dirname
15 | filename = @filename
16 | if filename.is_a?(String)
17 | File.dirname(filename)
18 | else
19 | nil
20 | end
21 | end
22 |
23 | def inspect(io)
24 | to_s(io)
25 | end
26 |
27 | def original_filename
28 | case filename = @filename
29 | when String
30 | filename
31 | when VirtualFile
32 | filename.expanded_location.try &.original_filename
33 | else
34 | nil
35 | end
36 | end
37 |
38 | def inspect
39 | to_s
40 | end
41 |
42 | def to_s(io)
43 | io << filename << ":" << line_number << ":" << column_number
44 | end
45 |
46 | def <=>(other)
47 | self_file = @filename
48 | other_file = other.filename
49 | if self_file.is_a?(String) && other_file.is_a?(String) && self_file == other_file
50 | {@line_number, @column_number} <=> {other.line_number, other.column_number}
51 | else
52 | nil
53 | end
54 | end
55 | end
56 | end
57 |
--------------------------------------------------------------------------------
/src/xml/xml.cr:
--------------------------------------------------------------------------------
1 | module XML
2 | def self.parse(string : String, options = ParserOptions.default : ParserOptions)
3 | from_ptr LibXML.xmlReadMemory(string, string.bytesize, nil, nil, options)
4 | end
5 |
6 | def self.parse(io : IO, options = ParserOptions.default : ParserOptions)
7 | from_ptr LibXML.xmlReadIO(
8 | ->(ctx, buffer, len) {
9 | LibC::Int.new(Box(IO).unbox(ctx).read Slice.new(buffer, len))
10 | },
11 | ->(ctx) { 0 },
12 | Box(IO).box(io),
13 | nil,
14 | nil,
15 | options,
16 | )
17 | end
18 |
19 | def self.parse_html(string : String, options = HTMLParserOptions.default : HTMLParserOptions)
20 | from_ptr LibXML.htmlReadMemory(string, string.bytesize, nil, nil, options)
21 | end
22 |
23 | def self.parse_html(io : IO, options = HTMLParserOptions.default : HTMLParserOptions)
24 | from_ptr LibXML.htmlReadIO(
25 | ->(ctx, buffer, len) {
26 | LibC::Int.new(Box(IO).unbox(ctx).read Slice.new(buffer, len))
27 | },
28 | ->(ctx) { 0 },
29 | Box(IO).box(io),
30 | nil,
31 | nil,
32 | options,
33 | )
34 | end
35 |
36 | protected def self.from_ptr(doc : LibXML::DocPtr)
37 | raise Error.new(LibXML.xmlGetLastError) unless doc
38 |
39 | node = Node.new(doc)
40 | XML::Error.set_errors(node)
41 | node
42 | end
43 | end
44 |
45 | require "./*"
46 |
--------------------------------------------------------------------------------
/spec/std/crypto/bcrypt/password_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 | require "crypto/bcrypt/password"
3 |
4 | describe "Crypto::Bcrypt::Password" do
5 | describe "new" do
6 | password = Crypto::Bcrypt::Password.new("$2a$08$K8y0i4Wyqyei3SiGHLEd.OweXJt7sno2HdPVrMvVf06kGgAZvPkga")
7 |
8 | it "parses version" do
9 | password.version.should eq("2a")
10 | end
11 |
12 | it "parses cost" do
13 | password.cost.should eq(8)
14 | end
15 |
16 | it "parses salt" do
17 | password.salt.should eq("K8y0i4Wyqyei3SiGHLEd.O")
18 | end
19 |
20 | it "parses digest" do
21 | password.digest.should eq("weXJt7sno2HdPVrMvVf06kGgAZvPkga")
22 | end
23 | end
24 |
25 | describe "create" do
26 | password = Crypto::Bcrypt::Password.create("super secret", 5)
27 |
28 | it "uses cost" do
29 | password.cost.should eq(5)
30 | end
31 |
32 | it "generates salt" do
33 | password.salt.should_not be_nil
34 | end
35 |
36 | it "generates digest" do
37 | password.digest.should_not be_nil
38 | end
39 | end
40 |
41 | describe "==" do
42 | password = Crypto::Bcrypt::Password.create("secret", 4)
43 |
44 | it "verifies password is incorrect" do
45 | (password == "wrong").should be_false
46 | end
47 |
48 | it "verifies password is correct" do
49 | (password == "secret").should be_true
50 | end
51 | end
52 | end
53 |
--------------------------------------------------------------------------------
/src/llvm/abi.cr:
--------------------------------------------------------------------------------
1 | # Based on https://github.com/rust-lang/rust/blob/master/src/librustc_trans/trans/cabi.rs
2 | abstract class LLVM::ABI
3 | getter target_data
4 | getter is_osx
5 | getter is_windows
6 |
7 | def initialize(target_machine : TargetMachine)
8 | @target_data = target_machine.data_layout
9 | triple = target_machine.triple
10 | @is_osx = !!(triple =~ /apple/)
11 | @is_windows = !!(triple =~ /windows/)
12 | end
13 |
14 | abstract def abi_info(atys : Array(Type), rty : Type, ret_def : Bool)
15 | abstract def size(type : Type)
16 | abstract def align(type : Type)
17 |
18 | enum ArgKind
19 | Direct
20 | Indirect
21 | Ignore
22 | end
23 |
24 | struct ArgType
25 | getter kind
26 | getter type
27 | getter cast
28 | getter pad
29 | getter attr
30 |
31 | def self.direct(type, cast = nil, pad = nil, attr = nil)
32 | new ArgKind::Direct, type, cast, pad, attr
33 | end
34 |
35 | def self.indirect(type, attr)
36 | new ArgKind::Indirect, type, attr: attr
37 | end
38 |
39 | def self.ignore(type)
40 | new ArgKind::Ignore, type
41 | end
42 |
43 | def initialize(@kind, @type, @cast = nil, @pad = nil, @attr = nil)
44 | end
45 | end
46 |
47 | class FunctionType
48 | getter arg_types
49 | getter return_type
50 |
51 | def initialize(@arg_types, @return_type)
52 | end
53 | end
54 | end
55 |
--------------------------------------------------------------------------------
/src/llvm/target.cr:
--------------------------------------------------------------------------------
1 | struct LLVM::Target
2 | def self.each
3 | target = LibLLVM.get_first_target
4 | while target
5 | yield Target.new target
6 | target = LibLLVM.get_next_target target
7 | end
8 | end
9 |
10 | def self.first
11 | Target.new LibLLVM.get_first_target
12 | end
13 |
14 | def self.from_triple(triple)
15 | return_code = LibLLVM.get_target_from_triple triple, out target, out error
16 | raise LLVM.string_and_dispose(error) unless return_code == 0
17 | new target
18 | end
19 |
20 | def initialize(@unwrap)
21 | end
22 |
23 | def name
24 | String.new LibLLVM.get_target_name(self)
25 | end
26 |
27 | def description
28 | String.new LibLLVM.get_target_description(self)
29 | end
30 |
31 | def create_target_machine(triple, cpu = "", features = "",
32 | opt_level = LLVM::CodeGenOptLevel::Default,
33 | reloc = LLVM::RelocMode::PIC,
34 | code_model = LLVM::CodeModel::Default)
35 | target_machine = LibLLVM.create_target_machine(self, triple, cpu, features, opt_level, reloc, code_model)
36 | target_machine ? TargetMachine.new(target_machine) : raise "Couldn't create target machine"
37 | end
38 |
39 | def to_s(io)
40 | io << name
41 | io << " - "
42 | io << description
43 | end
44 |
45 | def to_unsafe
46 | @unwrap
47 | end
48 | end
49 |
--------------------------------------------------------------------------------
/spec/std/levenshtein_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 | require "levenshtein"
3 |
4 | describe "levenshtein" do
5 | assert { Levenshtein.distance("algorithm", "altruistic").should eq(6) }
6 | assert { Levenshtein.distance("1638452297", "444488444").should eq(9) }
7 | assert { Levenshtein.distance("", "").should eq(0) }
8 | assert { Levenshtein.distance("", "a").should eq(1) }
9 | assert { Levenshtein.distance("aaapppp", "").should eq(7) }
10 | assert { Levenshtein.distance("frog", "fog").should eq(1) }
11 | assert { Levenshtein.distance("fly", "ant").should eq(3) }
12 | assert { Levenshtein.distance("elephant", "hippo").should eq(7) }
13 | assert { Levenshtein.distance("hippo", "elephant").should eq(7) }
14 | assert { Levenshtein.distance("hippo", "zzzzzzzz").should eq(8) }
15 | assert { Levenshtein.distance("hello", "hallo").should eq(1) }
16 | assert { Levenshtein.distance("こんにちは", "こんちは").should eq(1) }
17 |
18 | it "finds with finder" do
19 | finder = Levenshtein::Finder.new "hallo"
20 | finder.test "hay"
21 | finder.test "hall"
22 | finder.test "hallo world"
23 | finder.best_match.should eq("hall")
24 | end
25 |
26 | it "finds with finder and other values" do
27 | finder = Levenshtein::Finder.new "hallo"
28 | finder.test "hay", "HAY"
29 | finder.test "hall", "HALL"
30 | finder.test "hallo world", "HALLO WORLD"
31 | finder.best_match.should eq("HALL")
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/src/compiler/crystal/semantic/flags.cr:
--------------------------------------------------------------------------------
1 | class Crystal::Program
2 | def flags
3 | @flags ||= parse_flags(`uname -m -s`)
4 | end
5 |
6 | def flags=(flags)
7 | @flags = parse_flags(flags)
8 | end
9 |
10 | def has_flag?(name)
11 | flags.includes?(name)
12 | end
13 |
14 | def eval_flags(node)
15 | evaluator = FlagsEvaluator.new(self)
16 | node.accept evaluator
17 | evaluator.value
18 | end
19 |
20 | private def parse_flags(flags_name)
21 | flags_name.split.map(&.downcase).to_set
22 | end
23 |
24 | class FlagsEvaluator < Visitor
25 | getter value
26 |
27 | def initialize(@program)
28 | @value = false
29 | end
30 |
31 | def visit(node : Var)
32 | @value = @program.has_flag?(node.name)
33 | end
34 |
35 | def visit(node : Not)
36 | node.exp.accept self
37 | @value = !@value
38 | false
39 | end
40 |
41 | def visit(node : And)
42 | node.left.accept self
43 | left_value = @value
44 | node.right.accept self
45 | @value = left_value && @value
46 | false
47 | end
48 |
49 | def visit(node : Or)
50 | node.left.accept self
51 | left_value = @value
52 | node.right.accept self
53 | @value = left_value || @value
54 | false
55 | end
56 |
57 | def visit(node : ASTNode)
58 | raise "Bug: shouldn't visit #{node} in FlagsEvaluator"
59 | end
60 | end
61 | end
62 |
--------------------------------------------------------------------------------
/spec/std/thread/condition_variable_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 |
3 | describe ConditionVariable do
4 | it "signals" do
5 | mutex = Mutex.new
6 | cond = ConditionVariable.new
7 | pcond = ConditionVariable.new
8 | waiting = 0
9 | signaled = 0
10 |
11 | threads = 3.times.map do
12 | Thread.new do
13 | mutex.synchronize do
14 | waiting += 1
15 | pcond.signal
16 | cond.wait mutex
17 | end
18 | end
19 | end.to_a
20 |
21 | while signaled < 3
22 | mutex.synchronize do
23 | if waiting > 0
24 | waiting -= 1
25 | signaled += 1
26 | cond.signal
27 | end
28 | end
29 | end
30 | threads.map &.join
31 | end
32 |
33 | it "broadcasts" do
34 | mutex = Mutex.new
35 | cond = ConditionVariable.new
36 | pcond = ConditionVariable.new
37 | waiting = 0
38 | signaled = false
39 |
40 | threads = 3.times.map do
41 | Thread.new do
42 | mutex.synchronize do
43 | waiting += 1
44 | pcond.signal
45 | cond.wait mutex
46 | end
47 | end
48 | end.to_a
49 |
50 | until signaled
51 | mutex.synchronize do
52 | if waiting >= 3
53 | cond.broadcast
54 | signaled = true
55 | else
56 | pcond.wait mutex
57 | end
58 | end
59 | end
60 |
61 | threads.map &.join
62 | end
63 | end
64 |
--------------------------------------------------------------------------------
/samples/wordcount.cr:
--------------------------------------------------------------------------------
1 | # Ported from http://arthurtw.github.io/2015/01/12/quick-comparison-nim-vs-rust.html
2 |
3 | require "option_parser"
4 |
5 | def do_work(in_filenames, output_filename, ignore_case)
6 | if in_filenames.empty?
7 | in_files = [STDIN]
8 | else
9 | in_files = in_filenames.map { |name| File.open(name, "r") }
10 | end
11 |
12 | if output_filename
13 | out_file = File.open(output_filename, "w")
14 | else
15 | out_file = STDOUT
16 | end
17 |
18 | counts = Hash(String, Int32).new(0)
19 |
20 | in_files.each do |in_file|
21 | in_file.each_line do |line|
22 | line = line.downcase if ignore_case
23 | line.scan(/\w+/) do |match|
24 | counts[match[0]] += 1
25 | end
26 | end
27 | end
28 |
29 | entries = counts.to_a.sort_by! &.[0]
30 | entries.each do |entry|
31 | word, count = entry
32 | out_file.puts "#{count}\t#{word}"
33 | end
34 | end
35 |
36 | output_filename = nil
37 | ignore_case = false
38 |
39 | OptionParser.parse! do |opts|
40 | opts.banner = "Usage: wordcount [OPTIONS] [FILES]"
41 | opts.on("-o NAME", "set output filename") do |filename|
42 | output_filename = filename
43 | end
44 | opts.on("-i", "--ignore-case", "ignore case") do
45 | ignore_case = true
46 | end
47 | opts.on("-h", "--help", "print this help menu") do
48 | puts opts
49 | end
50 | end
51 |
52 | in_filenames = ARGV
53 |
54 | do_work ARGV, output_filename, ignore_case
55 |
--------------------------------------------------------------------------------
/src/spec/formatter.cr:
--------------------------------------------------------------------------------
1 | module Spec
2 | # :nodoc:
3 | abstract class Formatter
4 | def push(context)
5 | end
6 |
7 | def pop
8 | end
9 |
10 | def before_example(description)
11 | end
12 |
13 | def report(result)
14 | end
15 |
16 | def finish
17 | end
18 | end
19 |
20 | # :nodoc:
21 | class DotFormatter < Formatter
22 | def report(result)
23 | print Spec.color(LETTERS[result.kind], result.kind)
24 | end
25 |
26 | def finish
27 | puts
28 | end
29 | end
30 |
31 | # :nodoc:
32 | class VerboseFormatter < Formatter
33 | def initialize
34 | @ident = 0
35 | @last_description = ""
36 | end
37 |
38 | def push(context)
39 | print_ident
40 | puts context.description
41 | @ident += 1
42 | end
43 |
44 | def pop
45 | @ident -= 1
46 | end
47 |
48 | def print_ident
49 | @ident.times { print " " }
50 | end
51 |
52 | def before_example(description)
53 | print_ident
54 | print description
55 | @last_description = description
56 | end
57 |
58 | def report(result)
59 | print '\r'
60 | print_ident
61 | puts Spec.color(@last_description, result.kind)
62 | end
63 | end
64 |
65 | @@formatter = DotFormatter.new
66 |
67 | # :nodoc:
68 | def self.formatter=(@@formatter)
69 | end
70 |
71 | # :nodoc:
72 | def self.formatter
73 | @@formatter
74 | end
75 | end
76 |
--------------------------------------------------------------------------------
/spec/std/random_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 |
3 | describe "Random" do
4 | it "limited number" do
5 | rand(1).should eq(0)
6 |
7 | x = rand(2)
8 | x.should be >= 0
9 | x.should be < 2
10 | end
11 |
12 | it "float number" do
13 | x = rand
14 | x.should be > 0
15 | x.should be < 1
16 | end
17 |
18 | it "raises on invalid number" do
19 | expect_raises ArgumentError, "incorrect rand value: 0" do
20 | rand(0)
21 | end
22 | end
23 |
24 | it "does with inclusive range" do
25 | rand(1..1).should eq(1)
26 | x = rand(1..3)
27 | x.should be >= 1
28 | x.should be <= 3
29 | end
30 |
31 | it "does with exclusive range" do
32 | rand(1...2).should eq(1)
33 | x = rand(1...4)
34 | x.should be >= 1
35 | x.should be < 4
36 | end
37 |
38 | it "raises on invalid range" do
39 | expect_raises ArgumentError, "incorrect rand value: 1...1" do
40 | rand(1...1)
41 | end
42 | end
43 |
44 | it "allows creating a new default random" do
45 | rand = Random.new
46 | value = rand.rand
47 | (0 <= value < 1).should be_true
48 | end
49 |
50 | it "allows creating a new default random with a seed" do
51 | rand = Random.new(1234)
52 | value1 = rand.rand
53 |
54 | rand = Random.new(1234)
55 | value2 = rand.rand
56 |
57 | value1.should eq(value2)
58 | end
59 |
60 | it "gets a random bool" do
61 | Random::DEFAULT.next_bool.should be_a(Bool)
62 | end
63 | end
64 |
--------------------------------------------------------------------------------
/src/compiler/crystal/tools/doc/macro.cr:
--------------------------------------------------------------------------------
1 | require "html"
2 | require "uri"
3 | require "./item"
4 |
5 | class Crystal::Doc::Macro
6 | include Item
7 |
8 | getter type
9 | getter :macro
10 |
11 | def initialize(@generator, @type, @macro)
12 | end
13 |
14 | def name
15 | @macro.name
16 | end
17 |
18 | def args
19 | @macro.args
20 | end
21 |
22 | def doc
23 | @macro.doc
24 | end
25 |
26 | def source_link
27 | @generator.source_link(@macro)
28 | end
29 |
30 | def id
31 | String.build do |io|
32 | io << to_s.gsub(' ', "")
33 | io << "-macro"
34 | end
35 | end
36 |
37 | def html_id
38 | HTML.escape(id)
39 | end
40 |
41 | def anchor
42 | "#" + URI.escape(id)
43 | end
44 |
45 | def prefix
46 | ""
47 | end
48 |
49 | def abstract?
50 | false
51 | end
52 |
53 | def kind
54 | "macro "
55 | end
56 |
57 | def to_s(io)
58 | io << name
59 | args_to_s io
60 | end
61 |
62 | def args_to_s
63 | String.build { |io| args_to_s io }
64 | end
65 |
66 | def args_to_s(io)
67 | return if @macro.args.empty?
68 |
69 | io << '('
70 | @macro.args.each_with_index do |arg, i|
71 | io << ", " if i > 0
72 | io << '*' if @macro.splat_index == i
73 | io << arg
74 | end
75 | io << ')'
76 | end
77 |
78 | def args_to_html
79 | args_to_s
80 | end
81 |
82 | def must_be_included?
83 | @generator.must_include? @macro
84 | end
85 | end
86 |
--------------------------------------------------------------------------------
/src/openssl/lib_ssl.cr:
--------------------------------------------------------------------------------
1 | require "./lib_crypto"
2 |
3 | @[Link("ssl")]
4 | lib LibSSL
5 | alias Int = LibC::Int
6 |
7 | type SSLMethod = Void*
8 | type SSLContext = Void*
9 | type SSL = Void*
10 |
11 | enum SSLFileType
12 | PEM = 1
13 | ASN1 = 2
14 | end
15 |
16 | fun ssl_load_error_strings = SSL_load_error_strings
17 | fun ssl_library_init = SSL_library_init
18 | fun sslv23_method = SSLv23_method : SSLMethod
19 | fun ssl_ctx_new = SSL_CTX_new(method : SSLMethod) : SSLContext
20 | fun ssl_ctx_free = SSL_CTX_free(context : SSLContext)
21 |
22 | @[Raises]
23 | fun ssl_new = SSL_new(context : SSLContext) : SSL
24 |
25 | @[Raises]
26 | fun ssl_connect = SSL_connect(handle : SSL) : Int
27 |
28 | @[Raises]
29 | fun ssl_accept = SSL_accept(handle : SSL) : Int
30 |
31 | @[Raises]
32 | fun ssl_write = SSL_write(handle : SSL, text : UInt8*, length : Int) : Int
33 |
34 | @[Raises]
35 | fun ssl_read = SSL_read(handle : SSL, buffer : UInt8*, read_size : Int) : Int
36 |
37 | @[Raises]
38 | fun ssl_shutdown = SSL_shutdown(handle : SSL) : Int
39 |
40 | fun ssl_free = SSL_free(handle : SSL)
41 | fun ssl_ctx_use_certificate_chain_file = SSL_CTX_use_certificate_chain_file(ctx : SSLContext, file : UInt8*) : Int
42 | fun ssl_ctx_use_privatekey_file = SSL_CTX_use_PrivateKey_file(ctx : SSLContext, file : UInt8*, filetype : SSLFileType) : Int
43 | fun ssl_set_bio = SSL_set_bio(handle : SSL, rbio : LibCrypto::Bio*, wbio : LibCrypto::Bio*)
44 | end
45 |
--------------------------------------------------------------------------------
/src/http/server/handlers/deflate_handler.cr:
--------------------------------------------------------------------------------
1 | require "zlib"
2 |
3 | class HTTP::DeflateHandler < HTTP::Handler
4 | DEFAULT_DEFLATE_TYPES = %w(text/html text/plain text/xml text/css text/javascript application/javascript application/json)
5 |
6 | property deflate_types
7 |
8 | def initialize(@deflate_types = DEFAULT_DEFLATE_TYPES)
9 | end
10 |
11 | def call(request)
12 | response = call_next(request)
13 |
14 | if should_deflate?(request, response)
15 | body_io = if response.body?
16 | MemoryIO.new(response.body)
17 | else
18 | response.body_io
19 | end
20 |
21 | deflate_io = Zlib::Deflate.new(body_io)
22 |
23 | headers = response.headers.dup
24 | headers.delete "Content-length"
25 | headers["Content-Encoding"] = "deflate"
26 |
27 | response = Response.new(response.status_code, nil, headers, response.status_message, response.version, deflate_io)
28 | end
29 |
30 | response
31 | end
32 |
33 | private def should_deflate?(request, response)
34 | return false unless HTTP::Response.mandatory_body?(response.status_code)
35 | return false if response.headers["Cache-Control"]? =~ /\bno-transform\b/
36 |
37 | accept_encoding = request.headers["Accept-encoding"]?
38 | content_type = response.content_type
39 | accept_encoding && accept_encoding =~ /deflate/ && response.version == "HTTP/1.1" && content_type && deflate_types.includes?(content_type)
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/spec/std/crypto/subtle_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 | require "crypto/subtle"
3 |
4 | describe "Subtle" do
5 | it "compares constant times" do
6 | data = [
7 | {"a" => Slice.new(1, 0x11), "b" => Slice.new(1, 0x11), "result" => 1},
8 | {"a" => Slice.new(1, 0x12), "b" => Slice.new(1, 0x11), "result" => 0},
9 | {"a" => Slice.new(1, 0x11), "b" => Slice.new(2) { |i| 0x11 + i }, "result" => 0},
10 | {"a" => Slice.new(2) { |i| 0x11 + i }, "b" => Slice.new(1, 0x11), "result" => 0},
11 | ]
12 |
13 | data.each do |test|
14 | Crypto::Subtle.constant_time_compare(test["a"] as Slice(Int32), test["b"] as Slice(Int32)).should eq(test["result"])
15 | end
16 | end
17 |
18 | it "compares constant time bytes on equality" do
19 | data = [
20 | {"a" => 0x00_u8, "b" => 0x00_u8, "result" => 1},
21 | {"a" => 0x00_u8, "b" => 0x01_u8, "result" => 0},
22 | {"a" => 0x01_u8, "b" => 0x00_u8, "result" => 0},
23 | {"a" => 0xff_u8, "b" => 0xff_u8, "result" => 1},
24 | {"a" => 0xff_u8, "b" => 0xfe_u8, "result" => 0},
25 | ]
26 |
27 | data.each do |test|
28 | Crypto::Subtle.constant_time_byte_eq(test["a"], test["b"]).should eq(test["result"])
29 | end
30 | end
31 |
32 | it "compares constant time bytes bug" do
33 | h1 = "$2a$05$LEC1XBXgXECzKUO2LBDhKOa9lH9zigNKnksVaDwViFNgPU4WkrD53J"
34 | h2 = "$2a$05$LEC1XBXgXECzKUO2LBDhKOaHlSGFuDDwMuVg6gOzdxQ0xN4rFOwMUn"
35 | Crypto::Subtle.constant_time_compare(h1.to_slice, h2.to_slice).should eq(0)
36 | end
37 | end
38 |
--------------------------------------------------------------------------------
/src/llvm/target_machine.cr:
--------------------------------------------------------------------------------
1 | class LLVM::TargetMachine
2 | def initialize(@unwrap)
3 | end
4 |
5 | def target
6 | target = LibLLVM.get_target_machine_target(self)
7 | target ? Target.new(target) : raise "Couldn't get target"
8 | end
9 |
10 | def data_layout
11 | layout = LibLLVM.get_target_machine_data(self)
12 | layout ? TargetData.new(layout) : raise "Missing layout for #{self}"
13 | end
14 |
15 | def triple
16 | triple_c = LibLLVM.get_target_machine_triple(self)
17 | LLVM.string_and_dispose(triple_c)
18 | end
19 |
20 | def emit_obj_to_file(llvm_mod, filename)
21 | emit_to_file llvm_mod, filename, LLVM::CodeGenFileType::ObjectFile
22 | end
23 |
24 | def emit_asm_to_file(llvm_mod, filename)
25 | emit_to_file llvm_mod, filename, LLVM::CodeGenFileType::AssemblyFile
26 | end
27 |
28 | private def emit_to_file(llvm_mod, filename, type)
29 | status = LibLLVM.target_machine_emit_to_file(self, llvm_mod, filename, type, out error_msg)
30 | unless status == 0
31 | raise LLVM.string_and_dispose(error_msg)
32 | end
33 | true
34 | end
35 |
36 | def abi
37 | triple = self.triple
38 | case triple
39 | when /x86_64/
40 | ABI::X86_64.new(self)
41 | when /i386|i686/
42 | ABI::X86.new(self)
43 | else
44 | raise "Unsupported ABI for target triple: #{triple}"
45 | end
46 | end
47 |
48 | def to_unsafe
49 | @unwrap
50 | end
51 |
52 | def finalize
53 | LibLLVM.dispose_target_machine(@unwrap)
54 | end
55 | end
56 |
--------------------------------------------------------------------------------
/src/compiler/crystal/codegen/crystal_llvm_builder.cr:
--------------------------------------------------------------------------------
1 | module Crystal
2 | class CrystalLLVMBuilder
3 | property :end
4 |
5 | def initialize(@builder, @printf)
6 | @end = false
7 | end
8 |
9 | def llvm_nil
10 | LLVMTyper::NIL_VALUE
11 | end
12 |
13 | def ret
14 | return llvm_nil if @end
15 | value = @builder.ret
16 | @end = true
17 | value
18 | end
19 |
20 | def ret(value)
21 | return llvm_nil if @end
22 | value = @builder.ret(value)
23 | @end = true
24 | value
25 | end
26 |
27 | def br(block)
28 | return llvm_nil if @end
29 | value = @builder.br(block)
30 | @end = true
31 | value
32 | end
33 |
34 | def unreachable
35 | if ENV["UNREACHABLE"]? == "1"
36 | printf "Reached the unreachable!"
37 | end
38 | return if @end
39 | value = @builder.unreachable
40 | @end = true
41 | value
42 | end
43 |
44 | def printf(format, args = [] of LLVM::Value)
45 | call @printf, [global_string_pointer(format)] + args
46 | end
47 |
48 | def position_at_end(block)
49 | @builder.position_at_end block
50 | @end = false
51 | end
52 |
53 | def insert_block
54 | @builder.insert_block
55 | end
56 |
57 | def to_unsafe
58 | @builder.to_unsafe
59 | end
60 |
61 | macro method_missing(name, args, block)
62 | return llvm_nil if @end
63 |
64 | @builder.{{name.id}}({{*args}}) {{block}}
65 | end
66 | end
67 | end
68 |
--------------------------------------------------------------------------------
/src/thread/thread.cr:
--------------------------------------------------------------------------------
1 | require "./*"
2 |
3 | # :nodoc:
4 | class Thread(T, R)
5 | # Don't use this class, it is used internally by the event scheduler.
6 | # Use spawn and channels instead.
7 |
8 | def self.new(&func : -> R)
9 | Thread(Nil, R).new(nil) { func.call }
10 | end
11 |
12 | def initialize(arg : T, &func : T -> R)
13 | @func = func
14 | @arg = arg
15 | @detached = false
16 | ret = LibPThread.create(out @th, nil, ->(data) {
17 | (data as Thread(T, R)).start
18 | }, self as Void*)
19 |
20 | if ret != 0
21 | raise Errno.new("pthread_create")
22 | end
23 | end
24 |
25 | def finalize
26 | LibPThread.detach(@th) unless @detached
27 | end
28 |
29 | def join
30 | if LibPThread.join(@th, out _ret) != 0
31 | raise Errno.new("pthread_join")
32 | end
33 | @detached = true
34 |
35 | if exception = @exception
36 | raise exception
37 | end
38 |
39 | # TODO: We need to cast ret to R, otherwise it'll be nilable
40 | # and we don't want that. But `@ret as R` gives
41 | # `can't cast Nil to NoReturn` in the case when the Thread's body is
42 | # NoReturn. The following trick works, but we should find another
43 | # way to do it.
44 | ret = @ret
45 | if ret.is_a?(R) # Always true
46 | ret
47 | else
48 | exit # unreachable, really
49 | end
50 | end
51 |
52 | protected def start
53 | begin
54 | @ret = @func.call(@arg)
55 | rescue ex
56 | @exception = ex
57 | end
58 | end
59 | end
60 |
--------------------------------------------------------------------------------
/docs/main.cr:
--------------------------------------------------------------------------------
1 | require "../src/big_int/**"
2 | require "../src/crypto/**"
3 | require "../src/csv"
4 | require "../src/ecr"
5 | require "../src/event/**"
6 | require "../src/fiber/**"
7 | # require "../src/fs/fs"
8 | require "../src/gc/**"
9 | require "../src/html/**"
10 | require "../src/http/**"
11 | require "../src/io/**"
12 | require "../src/json/**"
13 | require "../src/llvm/**"
14 | require "../src/logger"
15 | require "../src/macros"
16 | require "../src/math/**"
17 | require "../src/markdown"
18 | require "../src/oauth/**"
19 | require "../src/oauth2/**"
20 | require "../src/openssl/**"
21 | require "../src/process/**"
22 | require "../src/regex/**"
23 | require "../src/socket/**"
24 | require "../src/spec/**"
25 | require "../src/string/**"
26 | require "../src/thread/**"
27 | require "../src/time/**"
28 | require "../src/xml/**"
29 | require "../src/yaml/**"
30 | require "../src/benchmark"
31 | require "../src/array"
32 | require "../src/bit_array"
33 | require "../src/box"
34 | require "../src/colorize"
35 | require "../src/complex"
36 | require "../src/deque"
37 | require "../src/dl"
38 | require "../src/inifile"
39 | require "../src/levenshtein"
40 | require "../src/matrix"
41 | require "../src/option_parser"
42 | require "../src/partial_comparable"
43 | require "../src/readline"
44 | require "../src/secure_random"
45 | require "../src/signal"
46 | require "../src/simple_hash"
47 | require "../src/string_pool"
48 | require "../src/string_scanner"
49 | require "../src/tempfile"
50 | require "../src/uri"
51 | require "./macros"
52 | require "./char"
53 |
--------------------------------------------------------------------------------
/src/zlib/inflate.cr:
--------------------------------------------------------------------------------
1 | module Zlib
2 | class Inflate
3 | include IO
4 |
5 | def initialize(@input : IO, wbits = LibZ::MAX_BITS)
6 | @buf :: UInt8[8192] # input buffer used by zlib
7 | @stream = LibZ::ZStream.new
8 | ret = LibZ.inflateInit2(pointerof(@stream), wbits, LibZ.zlibVersion, sizeof(LibZ::ZStream))
9 | check_error(ret)
10 | end
11 |
12 | private def check_error(err)
13 | msg = @stream.msg ? String.new(@stream.msg) : nil
14 | ZlibError.check_error(err, msg)
15 | end
16 |
17 | def write(slice : Slice(UInt8))
18 | raise IO::Error.new "Can't write to InflateIO"
19 | end
20 |
21 | def read(slice : Slice(UInt8))
22 | prepare_input_data
23 |
24 | @stream.avail_out = slice.size.to_u32
25 | @stream.next_out = slice.to_unsafe
26 |
27 | # if no data was read, and the stream is not finished keep inflating
28 | while perform_inflate != LibZ::STREAM_END && @stream.avail_out == slice.size.to_u32
29 | prepare_input_data
30 | end
31 |
32 | slice.size - @stream.avail_out
33 | end
34 |
35 | private def prepare_input_data
36 | return if @stream.avail_in > 0
37 | @stream.next_in = @buf.buffer
38 | @stream.avail_in = @input.read(@buf.to_slice).to_u32
39 | end
40 |
41 | private def perform_inflate
42 | flush = @stream.avail_in == 0 ? LibZ::Flush::FINISH : LibZ::Flush::NO_FLUSH
43 | ret = LibZ.inflate(pointerof(@stream), flush)
44 | check_error(ret)
45 | ret
46 | end
47 | end
48 | end
49 |
--------------------------------------------------------------------------------
/src/oauth/access_token.cr:
--------------------------------------------------------------------------------
1 | class OAuth::AccessToken
2 | getter token
3 | getter secret
4 |
5 | def initialize(@token, @secret, @extra = nil)
6 | end
7 |
8 | def extra
9 | @extra ||= {} of String => String
10 | end
11 |
12 | def self.from_response(response)
13 | token = nil
14 | secret = nil
15 | extra = {} of String => String
16 |
17 | HTTP::Params.parse(response) do |key, value|
18 | case key
19 | when "oauth_token" then token = value
20 | when "oauth_token_secret" then secret = value
21 | else extra[key] = value
22 | end
23 | end
24 |
25 | new token.not_nil!, secret.not_nil!, extra
26 | end
27 |
28 | def self.new(pull : JSON::PullParser)
29 | token = nil
30 | secret = nil
31 | extra = {} of String => String
32 |
33 | pull.read_object do |key|
34 | case key
35 | when "oauth_token"
36 | token = pull.read_string
37 | when "oauth_token_secret"
38 | secret = pull.read_string
39 | else
40 | if pull.kind == :STRING
41 | extra[key] = pull.read_string
42 | else
43 | pull.skip
44 | end
45 | end
46 | end
47 |
48 | new token.not_nil!, secret.not_nil!, extra
49 | end
50 |
51 | def to_json(io : IO)
52 | io.json_object do |object|
53 | object.field "oauth_token", @token
54 | object.field "oauth_token_secret", @secret
55 | @extra.try &.each do |key, value|
56 | object.field key, value
57 | end
58 | end
59 | end
60 | end
61 |
--------------------------------------------------------------------------------
/src/unwind.cr:
--------------------------------------------------------------------------------
1 | lib LibUnwind
2 | struct Exception
3 | exception_class : LibC::SizeT
4 | exception_cleanup : LibC::SizeT
5 | private1 : UInt64
6 | private2 : UInt64
7 | exception_object : UInt64
8 | exception_type_id : Int32
9 | end
10 |
11 | @[Flags]
12 | enum Action
13 | SEARCH_PHASE = 1
14 | CLEANUP_PHASE = 2
15 | HANDLER_FRAME = 4
16 | FORCE_UNWIND = 8
17 | END_OF_STACK = 16
18 | end
19 |
20 | enum ReasonCode
21 | NO_REASON = 0
22 | FOREIGN_EXCEPTION_CAUGHT = 1
23 | FATAL_PHASE2_ERROR = 2
24 | FATAL_PHASE1_ERROR = 3
25 | NORMAL_STOP = 4
26 | END_OF_STACK = 5
27 | HANDLER_FOUND = 6
28 | INSTALL_CONTEXT = 7
29 | CONTINUE_UNWIND = 8
30 | end
31 |
32 | ifdef x86_64
33 | EH_REGISTER_0 = 0
34 | EH_REGISTER_1 = 1
35 | else
36 | EH_REGISTER_0 = 0
37 | EH_REGISTER_1 = 2
38 | end
39 |
40 | alias Context = Void*
41 |
42 | fun raise_exception = _Unwind_RaiseException(ex : Exception*) : Int32
43 | fun get_region_start = _Unwind_GetRegionStart(Context) : LibC::SizeT
44 | fun get_ip = _Unwind_GetIP(Context) : LibC::SizeT
45 | fun set_ip = _Unwind_SetIP(context : Context, ip : LibC::SizeT) : LibC::SizeT
46 | fun set_gr = _Unwind_SetGR(context : Context, index : Int32, value : LibC::SizeT)
47 | fun get_language_specific_data = _Unwind_GetLanguageSpecificData(Context) : UInt8*
48 | fun backtrace = _Unwind_Backtrace((Context, Void*) -> ReasonCode, Void*) : Int32
49 | end
50 |
--------------------------------------------------------------------------------
/spec/compiler/codegen/no_return_spec.cr:
--------------------------------------------------------------------------------
1 | require "../../spec_helper"
2 |
3 | describe "Code gen: no return" do
4 | it "codegens if with NoReturn on then and union on else" do
5 | run("lib LibC; fun exit(c : Int32) : NoReturn; end; (if 1 == 2; LibC.exit(1); else; 1 || 2.5; end).to_i").to_i.should eq(1)
6 | end
7 |
8 | it "codegens Pointer(NoReturn).malloc" do
9 | run("Pointer(NoReturn).malloc(1_u64); 1").to_i.should eq(1)
10 | end
11 |
12 | it "codegens if with no reutrn and variable used afterwards" do
13 | codegen(%(
14 | require "prelude"
15 |
16 | lib LibC
17 | fun exit2 : NoReturn
18 | end
19 |
20 | if (a = LibC.exit2) && a.size == 3
21 | end
22 | ))
23 | end
24 |
25 | it "codegen types exception handler as NoReturn if ensure is NoReturn" do
26 | codegen(%(
27 | require "prelude"
28 |
29 | lib LibC
30 | fun foo : NoReturn
31 | end
32 |
33 | begin
34 | 1
35 | ensure
36 | LibC.foo
37 | end
38 | ))
39 | end
40 |
41 | it "codegens no return variable declaration (#1508)" do
42 | run(%(
43 | foo :: NoReturn
44 | 1
45 | )).to_i.should eq(1)
46 | end
47 |
48 | it "codegens no return instance variable declaration (#1508)" do
49 | run(%(
50 | class Foo
51 | def initialize
52 | @foo :: NoReturn
53 | @x = 1
54 | end
55 |
56 | def x
57 | @x
58 | end
59 | end
60 |
61 | Foo.new.x
62 | )).to_i.should eq(1)
63 | end
64 | end
65 |
--------------------------------------------------------------------------------
/spec/std/reference_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 |
3 | class ReferenceSpecTestClass
4 | def initialize(@x, @y)
5 | end
6 | end
7 |
8 | class ReferenceSpecTestClassBase
9 | end
10 |
11 | class ReferenceSpecTestClassSubclass < ReferenceSpecTestClassBase
12 | end
13 |
14 | describe "Reference" do
15 | it "compares reference to other reference" do
16 | o1 = Reference.new
17 | o2 = Reference.new
18 | (o1 == o1).should be_true
19 | (o1 == o2).should be_false
20 | (o1 == 1).should be_false
21 | end
22 |
23 | it "should not be nil" do
24 | Reference.new.nil?.should be_false
25 | end
26 |
27 | it "should be false when negated" do
28 | (!Reference.new).should be_false
29 | end
30 |
31 | it "does inspect" do
32 | r = ReferenceSpecTestClass.new(1, "hello")
33 | r.inspect.should eq(%(#))
34 | end
35 |
36 | it "does to_s" do
37 | r = ReferenceSpecTestClass.new(1, "hello")
38 | r.to_s.should eq(%(#))
39 | end
40 |
41 | it "does inspect for class" do
42 | String.inspect.should eq("String")
43 | end
44 |
45 | it "does to_s for class" do
46 | String.to_s.should eq("String")
47 | end
48 |
49 | it "does to_s for class if virtual" do
50 | [ReferenceSpecTestClassBase, ReferenceSpecTestClassSubclass].to_s.should eq("[ReferenceSpecTestClassBase, ReferenceSpecTestClassSubclass]")
51 | end
52 |
53 | it "returns itself" do
54 | x = "hello"
55 | x.itself.should be(x)
56 | end
57 | end
58 |
--------------------------------------------------------------------------------
/spec/compiler/type_inference/named_args_spec.cr:
--------------------------------------------------------------------------------
1 | require "../../spec_helper"
2 |
3 | describe "Type inference: named args" do
4 | it "errors if named arg not found" do
5 | assert_error %(
6 | def foo(x, y = 1, z = 2)
7 | end
8 |
9 | foo 1, w: 3
10 | ),
11 | "no argument named 'w'"
12 | end
13 |
14 | it "errors if named arg already specified" do
15 | assert_error %(
16 | def foo(x, y = 1, z = 2)
17 | end
18 |
19 | foo 1, x: 1
20 | ),
21 | "argument 'x' already specified"
22 | end
23 |
24 | it "errors if named arg not found in new" do
25 | assert_error %(
26 | class Foo
27 | def initialize(x, y = 1, z = 2)
28 | end
29 | end
30 |
31 | Foo.new 1, w: 3
32 | ),
33 | "no argument named 'w'"
34 | end
35 |
36 | it "errors if named arg already specified" do
37 | assert_error %(
38 | class Foo
39 | def initialize(x, y = 1, z = 2)
40 | end
41 | end
42 |
43 | Foo.new 1, x: 1
44 | ),
45 | "argument 'x' already specified"
46 | end
47 |
48 | it "errors if doesn't pass named arg restriction" do
49 | assert_error %(
50 | def foo(x = 1 : Int32)
51 | end
52 |
53 | foo x: 1.5
54 | ),
55 | "no overload matches"
56 | end
57 |
58 | it "errors if named arg already specified but in same position" do
59 | assert_error %(
60 | def foo(headers = nil)
61 | end
62 |
63 | foo 1, headers: 2
64 | ),
65 | "argument 'headers' already specified"
66 | end
67 | end
68 |
--------------------------------------------------------------------------------
/src/file/flock.cr:
--------------------------------------------------------------------------------
1 | lib LibC
2 | @[Flags]
3 | enum FlockOp
4 | SH = 0x1
5 | EX = 0x2
6 | NB = 0x4
7 | UN = 0x8
8 | end
9 |
10 | fun flock(fd : Int, op : FlockOp) : Int
11 | end
12 |
13 | class File
14 | def flock_shared(blocking = true)
15 | flock_shared blocking
16 | begin
17 | yield
18 | ensure
19 | flock_unlock
20 | end
21 | end
22 |
23 | # Place a shared advisory lock. More than one process may hold a shared lock for a given file at a given time.
24 | # Errno::EWOULDBLOCK is raised if *blocking* is set to `false` and an existing exclusive lock is set.
25 | def flock_shared(blocking = true)
26 | flock LibC::FlockOp::SH, blocking
27 | end
28 |
29 | def flock_exclusive(blocking = true)
30 | flock_exclusive blocking
31 | begin
32 | yield
33 | ensure
34 | flock_unlock
35 | end
36 | end
37 |
38 | # Place an exclusive advisory lock. Only one process may hold an exclusive lock for a given file at a given time.
39 | # Errno::EWOULDBLOCK is raised if *blocking* is set to `false` and any existing lock is set.
40 | def flock_exclusive(blocking = true)
41 | flock LibC::FlockOp::EX, blocking
42 | end
43 |
44 | # Remove an existing advisory lock held by this process.
45 | def flock_unlock
46 | flock LibC::FlockOp::UN
47 | end
48 |
49 | private def flock(op : LibC::FlockOp, blocking = true : Bool)
50 | op |= LibC::FlockOp::NB unless blocking
51 |
52 | if LibC.flock(@fd, op) != 0
53 | raise Errno.new("flock")
54 | end
55 |
56 | nil
57 | end
58 | end
59 |
--------------------------------------------------------------------------------
/src/thread/lib_pthread.cr:
--------------------------------------------------------------------------------
1 | lib LibPThread
2 | alias Int = LibC::Int
3 |
4 | type Thread = Void*
5 |
6 | ifdef darwin
7 | type Mutex = Int64[8]
8 | else
9 | ifdef x86_64
10 | type Mutex = Int64[5]
11 | else
12 | type Mutex = Int64[3]
13 | end
14 | end
15 |
16 | ifdef darwin
17 | type MutexAttr = UInt8[16]
18 | else
19 | type MutexAttr = UInt8[4]
20 | end
21 |
22 | type Cond = Int64[6]
23 | type CondAttr = Void*
24 |
25 | fun create = pthread_create(thread : Thread*, attr : Void*, start : Void* ->, arg : Void*) : Int
26 | fun exit = pthread_exit(value : Void*)
27 | fun join = pthread_join(thread : Thread, value : Void**) : Int
28 | fun detach = pthread_detach(thread : Thread) : Int
29 |
30 | fun mutex_init = pthread_mutex_init(mutex : Mutex*, mutex_attr : MutexAttr*) : Int
31 | fun mutex_lock = pthread_mutex_lock(mutex : Mutex*) : Int
32 | fun mutex_trylock = pthread_mutex_trylock(mutex : Mutex*) : Int
33 | fun mutex_unlock = pthread_mutex_unlock(mutex : Mutex*) : Int
34 | fun mutex_destroy = pthread_mutex_destroy(mutex : Mutex*) : Int
35 |
36 | fun cond_init = pthread_cond_init(cond : Cond*, cond_attr : CondAttr) : Int
37 | fun cond_signal = pthread_cond_signal(cond : Cond*) : Int
38 | fun cond_broadcast = pthread_cond_broadcast(cond : Cond*) : Int
39 | fun cond_wait = pthread_cond_wait(cond : Cond*, mutext : Mutex*) : Int
40 | fun cond_timed_wait = pthread_cond_wait(cond : Cond*, mutext : Mutex*, abstime : LibC::TimeSpec) : Int
41 | fun cond_destroy = pthread_cond_destroy(cond : Cond*) : Int
42 | end
43 |
--------------------------------------------------------------------------------
/spec/std/html/builder_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 | require "html/builder"
3 |
4 | describe "HTML" do
5 | describe "Builder" do
6 | it "builds html" do
7 | str = HTML::Builder.new.build do
8 | doctype
9 | html do
10 | head do
11 | title { text "Crystal Programming Language" }
12 | end
13 | body do
14 | a({href: "http://crystal-lang.org"}) { text "Crystal rocks!" }
15 | form({method: "POST"}) do
16 | input({name: "name"})
17 | end
18 | end
19 | end
20 | end
21 | str.should eq %(Crystal Programming LanguageCrystal rocks!)
22 | end
23 |
24 | it "builds html with some tag attributes" do
25 | str = HTML::Builder.new.build do
26 | a({href: "http://crystal-lang.org", class: "crystal", id: "main"}) do
27 | text "Crystal rocks!"
28 | end
29 | end
30 | str.should eq %(Crystal rocks!)
31 | end
32 |
33 | it "escapes attribute values" do
34 | str = HTML::Builder.new.build do
35 | a({href: "<>"}) { }
36 | end
37 | str.should eq %()
38 | end
39 |
40 | it "escapes text" do
41 | str = HTML::Builder.new.build do
42 | a { text "<>" }
43 | end
44 | str.should eq %(<>)
45 | end
46 | end
47 | end
48 |
--------------------------------------------------------------------------------
/samples/binary-trees.cr:
--------------------------------------------------------------------------------
1 | # Copied with little modifications from: http://benchmarksgame.alioth.debian.org/u64q/benchmark.php?test=binarytrees&lang=yarv&id=1&data=u64q
2 |
3 | class Node
4 | def initialize(@a, @b, @c)
5 | end
6 |
7 | property :a
8 | property :b
9 | property :c
10 | end
11 |
12 | def item_check(tree)
13 | tree = tree.not_nil!
14 | return tree.b if tree.a.nil?
15 | tree.b + item_check(tree.a) - item_check(tree.c)
16 | end
17 |
18 | def bottom_up_tree(item, depth)
19 | return Node.new(nil, item, nil) unless depth > 0
20 | item_item = 2 * item
21 | depth -= 1
22 | Node.new(bottom_up_tree(item_item - 1, depth), item, bottom_up_tree(item_item, depth))
23 | end
24 |
25 | max_depth = (ARGV[0]? || 15).to_i
26 | min_depth = 4
27 |
28 | max_depth = min_depth + 2 if min_depth + 2 > max_depth
29 |
30 | stretch_depth = max_depth + 1
31 | stretch_tree = bottom_up_tree(0, stretch_depth)
32 |
33 | puts "stretch tree of depth #{stretch_depth}\t check: #{item_check(stretch_tree)}"
34 | stretch_tree = nil
35 |
36 | long_lived_tree = bottom_up_tree(0, max_depth)
37 |
38 | min_depth.step(max_depth + 1, 2) do |depth|
39 | iterations = 2**(max_depth - depth + min_depth)
40 |
41 | check = 0
42 |
43 | (1..iterations).each do |i|
44 | temp_tree = bottom_up_tree(i, depth)
45 | check += item_check(temp_tree)
46 |
47 | temp_tree = bottom_up_tree(-i, depth)
48 | check += item_check(temp_tree)
49 | end
50 |
51 | puts "#{iterations * 2}\t trees of depth #{depth}\t check: #{check}"
52 | end
53 |
54 | puts "long lived tree of depth #{max_depth}\t check: #{item_check(long_lived_tree)}"
55 |
--------------------------------------------------------------------------------
/spec/compiler/type_inference/global_spec.cr:
--------------------------------------------------------------------------------
1 | require "../../spec_helper"
2 |
3 | describe "Global inference" do
4 | it "infers type of global assign" do
5 | node = parse "$foo = 1"
6 | result = infer_type node
7 | mod, node = result.program, result.node as Assign
8 |
9 | node.type.should eq(mod.int32)
10 | node.target.type.should eq(mod.int32)
11 | node.value.type.should eq(mod.int32)
12 | end
13 |
14 | it "infers type of global assign with union" do
15 | nodes = parse "$foo = 1; $foo = 'a'"
16 | result = infer_type nodes
17 | mod, node = result.program, result.node as Expressions
18 |
19 | (node[0] as Assign).target.type.should eq(mod.union_of(mod.int32, mod.char))
20 | (node[1] as Assign).target.type.should eq(mod.union_of(mod.int32, mod.char))
21 | end
22 |
23 | it "infers type of global reference" do
24 | assert_type("$foo = 1; def foo; $foo = 'a'; end; foo; $foo") { union_of(int32, char) }
25 | end
26 |
27 | it "infers type of read global variable when not previously assigned" do
28 | assert_type("def foo; $foo; end; foo; $foo") { |mod| mod.nil }
29 | end
30 |
31 | it "infers type of write global variable when not previously assigned" do
32 | assert_type("def foo; $foo = 1; end; foo; $foo") { |mod| union_of(mod.nil, int32) }
33 | end
34 |
35 | it "types constant depending on global (related to #708)" do
36 | assert_type(%(
37 | A = foo
38 |
39 | def foo
40 | if a = $foo
41 | a
42 | else
43 | $foo = 1
44 | end
45 | end
46 |
47 | A
48 | )) { int32 }
49 | end
50 | end
51 |
--------------------------------------------------------------------------------
/src/compiler/crystal/codegen/asm.cr:
--------------------------------------------------------------------------------
1 | require "./codegen"
2 |
3 | class Crystal::CodeGenVisitor
4 | def visit(node : Asm)
5 | constraints = MemoryIO.new
6 |
7 | if ptrof = node.ptrof
8 | output = node.output.not_nil!
9 | output_type = llvm_type((ptrof.type as PointerInstanceType).element_type)
10 | constraints << output.constraint
11 | else
12 | output_type = LLVM::Void
13 | end
14 |
15 | input_types = [] of LLVM::Type
16 | input_values = [] of LLVM::Value
17 |
18 | if inputs = node.inputs
19 | constraints << "," unless constraints.empty?
20 |
21 | inputs.each_with_index do |input, i|
22 | input.exp.accept self
23 | input_types << llvm_type(input.exp.type)
24 | input_values << @last
25 | constraints << "," if i > 0
26 | constraints << input.constraint
27 | end
28 | end
29 |
30 | if clobbers = node.clobbers
31 | constraints << "," unless constraints.empty?
32 |
33 | clobbers.each_with_index do |clobber, i|
34 | constraints << "," if i > 0
35 | constraints << "~{"
36 | constraints << clobber
37 | constraints << '}'
38 | end
39 | end
40 |
41 | fun_type = LLVM::Type.function(input_types, output_type)
42 | constraints = constraints.to_s
43 |
44 | value = LLVM.const_inline_asm(fun_type, node.text, constraints, node.volatile, node.alignstack)
45 | asm_value = call value, input_values
46 |
47 | if ptrof
48 | ptrof.accept self
49 | store asm_value, @last
50 | end
51 |
52 | @last = llvm_nil
53 |
54 | false
55 | end
56 | end
57 |
--------------------------------------------------------------------------------
/spec/std/string_pool_spec.cr:
--------------------------------------------------------------------------------
1 | require "spec"
2 | require "string_pool"
3 |
4 | describe StringPool do
5 | it "is empty" do
6 | pool = StringPool.new
7 | pool.empty?.should be_true
8 | pool.size.should eq(0)
9 | end
10 |
11 | it "gets string" do
12 | pool = StringPool.new
13 | s1 = pool.get "foo"
14 | s2 = pool.get "foo"
15 |
16 | s1.should eq("foo")
17 | s2.should eq("foo")
18 | s1.should be(s2)
19 | pool.size.should eq(1)
20 | end
21 |
22 | it "gets string IO" do
23 | pool = StringPool.new
24 | io = MemoryIO.new "foo"
25 |
26 | s1 = pool.get io
27 | s2 = pool.get "foo"
28 |
29 | s1.should eq("foo")
30 | s2.should eq("foo")
31 | s1.should be(s2)
32 | pool.size.should eq(1)
33 | end
34 |
35 | it "gets slice" do
36 | pool = StringPool.new
37 | slice = Slice(UInt8).new(3, 'a'.ord.to_u8)
38 |
39 | s1 = pool.get(slice)
40 | s2 = pool.get(slice)
41 |
42 | s1.should eq("aaa")
43 | s2.should eq("aaa")
44 | s1.should be(s2)
45 | pool.size.should eq(1)
46 | end
47 |
48 | it "gets pointer with size" do
49 | pool = StringPool.new
50 | slice = Slice(UInt8).new(3, 'a'.ord.to_u8)
51 |
52 | s1 = pool.get(slice.pointer(slice.size), slice.size)
53 | s2 = pool.get(slice.pointer(slice.size), slice.size)
54 |
55 | s1.should eq("aaa")
56 | s2.should eq("aaa")
57 | s1.should be(s2)
58 | pool.size.should eq(1)
59 | end
60 |
61 | it "puts many" do
62 | pool = StringPool.new
63 | 10_000.times do |i|
64 | pool.get(i.to_s)
65 | end
66 | pool.size.should eq(10_000)
67 | end
68 | end
69 |
--------------------------------------------------------------------------------
/src/compiler/crystal/semantic/match.cr:
--------------------------------------------------------------------------------
1 | module Crystal
2 | class MatchContext
3 | property owner
4 | property type_lookup
5 | getter free_vars
6 | getter? strict
7 |
8 | def initialize(@owner, @type_lookup, @free_vars = nil, @strict = false)
9 | end
10 |
11 | def get_free_var(name)
12 | @free_vars.try &.[name]?
13 | end
14 |
15 | def set_free_var(name, type)
16 | free_vars = @free_vars ||= {} of String => Type
17 | free_vars[name] = type
18 | end
19 |
20 | def clone
21 | MatchContext.new(@owner, @type_lookup, @free_vars.clone)
22 | end
23 | end
24 |
25 | class Match
26 | getter :def
27 | getter :arg_types
28 | getter :context
29 |
30 | def initialize(@def, @arg_types, @context)
31 | end
32 | end
33 |
34 | struct Matches
35 | include Enumerable(Match)
36 |
37 | property :matches
38 | property :cover
39 | property :owner
40 |
41 | def initialize(@matches, @cover, @owner = nil, @success = true)
42 | end
43 |
44 | def cover_all?
45 | cover = @cover
46 | matches = @matches
47 | @success && matches && matches.size > 0 && (cover == true || (cover.is_a?(Cover) && cover.all?))
48 | end
49 |
50 | def empty?
51 | return true unless @success
52 |
53 | if matches = @matches
54 | matches.empty?
55 | else
56 | true
57 | end
58 | end
59 |
60 | def each
61 | @success && @matches.try &.each do |match|
62 | yield match
63 | end
64 | end
65 |
66 | def size
67 | @matches.try(&.size) || 0
68 | end
69 | end
70 | end
71 |
--------------------------------------------------------------------------------
/src/concurrent/concurrent.cr:
--------------------------------------------------------------------------------
1 | require "fiber"
2 | require "./*"
3 |
4 | def sleep(seconds : Number)
5 | if seconds < 0
6 | raise ArgumentError.new "sleep seconds must be positive"
7 | end
8 |
9 | Fiber.sleep(seconds)
10 | end
11 |
12 | def sleep(time : Time::Span)
13 | sleep(time.total_seconds)
14 | end
15 |
16 | def sleep
17 | Scheduler.reschedule
18 | end
19 |
20 | macro spawn
21 | %fiber = Fiber.new do
22 | begin
23 | {{ yield }}
24 | rescue %ex
25 | STDERR.puts "Unhandled exception:"
26 | %ex.inspect_with_backtrace STDERR
27 | STDERR.flush
28 | end
29 | end
30 |
31 | Scheduler.enqueue %fiber
32 |
33 | %fiber
34 | end
35 |
36 | # TODO: this doesn't work if a Call has a block or named arguments... yet
37 | macro spawn(exp)
38 | {% if exp.is_a?(Call) %}
39 | ->(
40 | {% for arg, i in exp.args %}
41 | __arg{{i}} : typeof({{arg}}),
42 | {% end %}
43 | ) {
44 | spawn do
45 | {{exp.name}}(
46 | {% for arg, i in exp.args %}
47 | __arg{{i}},
48 | {% end %}
49 | )
50 | end
51 | }.call({{*exp.args}})
52 | {% else %}
53 | spawn do
54 | {{exp}}
55 | end
56 | {% end %}
57 | end
58 |
59 | macro parallel(*jobs)
60 | %channel = Channel(Bool).new
61 |
62 | {% for job, i in jobs %}
63 | %ret{i} = nil
64 | spawn do
65 | %ret{i} = {{job}}
66 | %channel.send true
67 | end
68 | {% end %}
69 |
70 | {{ jobs.size }}.times { %channel.receive }
71 |
72 | {
73 | {% for job, i in jobs %}
74 | %ret{i}.not_nil!,
75 | {% end %}
76 | }
77 | end
78 |
--------------------------------------------------------------------------------
/spec/compiler/parser/parser_doc_spec.cr:
--------------------------------------------------------------------------------
1 | require "../../spec_helper"
2 |
3 | describe "Parser doc" do
4 | [
5 | {"class", "class Foo\nend"},
6 | {"abstract class", "abstract class Foo\nend"},
7 | {"struct", "struct Foo\nend"},
8 | {"module", "module Foo\nend"},
9 | {"def", "def foo\nend"},
10 | {"abstract def", "abstract def foo"},
11 | {"macro", "macro foo\nend"},
12 | {"macro def", "macro def foo : Int32\nend"},
13 | {"call without obj", "foo"},
14 | {"fun def", "fun foo : Int32\nend"},
15 | {"enum def", "enum Foo\nend"},
16 | {"constant assign", "A = 1"},
17 | {"alias", "alias Foo = Bar"},
18 | {"attribute", "@[Some]"},
19 | {"private def", "private def foo\nend"},
20 | ].each do |tuple|
21 | desc, code = tuple
22 |
23 | it "includes doc for #{desc}" do
24 | parser = Parser.new(%(
25 | # This is Foo.
26 | # Use it well.
27 | #{code}
28 | ))
29 | parser.wants_doc = true
30 | node = parser.parse
31 | node.doc.should eq("This is Foo.\nUse it well.")
32 | end
33 | end
34 |
35 | it "disables doc parsing inside defs" do
36 | parser = Parser.new(%(
37 | # doc 1
38 | def foo
39 | # doc 2
40 | bar
41 | end
42 |
43 | # doc 3
44 | def baz
45 | end
46 | ))
47 | parser.wants_doc = true
48 | nodes = parser.parse as Expressions
49 |
50 | foo = nodes[0] as Def
51 | foo.doc.should eq("doc 1")
52 |
53 | bar = foo.body as Call
54 | bar.doc.should be_nil
55 |
56 | baz = nodes[1] as Def
57 | baz.doc.should eq("doc 3")
58 | end
59 | end
60 |
--------------------------------------------------------------------------------
/src/spec/dsl.cr:
--------------------------------------------------------------------------------
1 | module Spec::DSL
2 | def describe(description, file = __FILE__, line = __LINE__, &block)
3 | Spec::RootContext.describe(description.to_s, file, line, &block)
4 | end
5 |
6 | def context(description, file = __FILE__, line = __LINE__, &block)
7 | describe(description.to_s, file, line, &block)
8 | end
9 |
10 | def it(description, file = __FILE__, line = __LINE__, &block)
11 | return if Spec.aborted?
12 | return unless Spec.matches?(description, file, line)
13 |
14 | Spec.formatter.before_example description
15 |
16 | begin
17 | Spec.run_before_each_hooks
18 | block.call
19 | Spec::RootContext.report(:success, description, file, line)
20 | rescue ex : Spec::AssertionFailed
21 | Spec::RootContext.report(:fail, description, file, line, ex)
22 | Spec.abort! if Spec.fail_fast?
23 | rescue ex
24 | Spec::RootContext.report(:error, description, file, line, ex)
25 | Spec.abort! if Spec.fail_fast?
26 | ensure
27 | Spec.run_after_each_hooks
28 | end
29 | end
30 |
31 | def pending(description, file = __FILE__, line = __LINE__, &block)
32 | return if Spec.aborted?
33 | return unless Spec.matches?(description, file, line)
34 |
35 | Spec.formatter.before_example description
36 |
37 | Spec::RootContext.report(:pending, description, file, line)
38 | end
39 |
40 | def assert(file = __FILE__, line = __LINE__, &block)
41 | it("assert", file, line, &block)
42 | end
43 |
44 | def fail(msg, file = __FILE__, line = __LINE__)
45 | raise Spec::AssertionFailed.new(msg, file, line)
46 | end
47 | end
48 |
49 | include Spec::DSL
50 |
--------------------------------------------------------------------------------
/src/http/server/handlers/static_file_handler.cr:
--------------------------------------------------------------------------------
1 | require "html/builder"
2 |
3 | class HTTP::StaticFileHandler < HTTP::Handler
4 | def initialize(@publicdir)
5 | end
6 |
7 | def call(request)
8 | request_path = request.path.not_nil!
9 | file_path = @publicdir + request_path
10 | if Dir.exists?(file_path)
11 | HTTP::Response.new(200, directory_listing(request_path, file_path), HTTP::Headers{"Content-Type": "text/html"})
12 | elsif File.exists?(file_path)
13 | HTTP::Response.new(200, File.read(file_path), HTTP::Headers{"Content-Type": mime_type(file_path)})
14 | else
15 | call_next(request)
16 | end
17 | end
18 |
19 | private def mime_type(path)
20 | case File.extname(path)
21 | when ".txt" then "text/plain"
22 | when ".htm", ".html" then "text/html"
23 | when ".css" then "text/css"
24 | when ".js" then "application/javascript"
25 | else "application/octet-stream"
26 | end
27 | end
28 |
29 | private def directory_listing(request_path, path)
30 | HTML::Builder.new.build do
31 | html do
32 | title { text "Directory listing for #{request_path}" }
33 | body do
34 | h2 { text "Directory listing for #{request_path}" }
35 | hr
36 | ul do
37 | Dir.foreach(path) do |entry|
38 | next if entry == "." || entry == ".."
39 | li do
40 | a({href: "#{request_path == "/" ? "" : request_path}/#{entry}"}) { text entry }
41 | end
42 | end
43 | end
44 | end
45 | end
46 | end
47 | end
48 | end
49 |
--------------------------------------------------------------------------------
/spec/compiler/codegen/private_def_spec.cr:
--------------------------------------------------------------------------------
1 | require "../../spec_helper"
2 | require "tempfile"
3 |
4 | describe "Codegen: private def" do
5 | it "codegens private def in same file" do
6 | compiler = Compiler.new
7 | sources = [
8 | Compiler::Source.new("foo.cr", %(
9 | private def foo
10 | 1
11 | end
12 |
13 | foo
14 | )),
15 | ]
16 | compiler.prelude = "empty"
17 |
18 | tempfile = Tempfile.new("crystal-spec-output")
19 | output_filename = tempfile.path
20 | tempfile.close
21 |
22 | compiler.compile sources, output_filename
23 | end
24 |
25 | it "codegens overloaded private def in same file" do
26 | compiler = Compiler.new
27 | sources = [
28 | Compiler::Source.new("foo.cr", %(
29 | private def foo(x : Int32)
30 | 1
31 | end
32 |
33 | private def foo(x : Char)
34 | 2
35 | end
36 |
37 | a = 3 || 'a'
38 | foo a
39 | )),
40 | ]
41 | compiler.prelude = "empty"
42 |
43 | tempfile = Tempfile.new("crystal-spec-output")
44 | output_filename = tempfile.path
45 | tempfile.close
46 |
47 | compiler.compile sources, output_filename
48 | end
49 | end
50 |
--------------------------------------------------------------------------------
/src/oauth2/session.cr:
--------------------------------------------------------------------------------
1 | # An OAuth2 session makes it easy to implement APIs that need to refresh
2 | # an access token once its expired before executing an HTTP request.
3 | class OAuth2::Session
4 | getter oauth2_client
5 | getter access_token
6 | getter expires_at
7 |
8 | # Creates an OAuth2::Session.
9 | #
10 | # Params:
11 | # * oauth2_client: the OAuth2::Client used to refresh an access token.
12 | # * access_token: the OAuth2::AccessToken to make requests.
13 | # * expires_at: the Time when the access token expires.
14 | # * callback: invoked when an access token is refreshed, giving you a chance to persist it.
15 | def initialize(@oauth2_client, @access_token, @expires_at = Time.utc_now, &@callback : OAuth2::Session ->)
16 | end
17 |
18 | # Authenticates an HTTP::Client, refreshing the access token if it is expired.
19 | #
20 | # Invoke this method on an HTTP::Client before executing an HTTP request.
21 | def authenticate(http_client)
22 | check_refresh_token
23 | @access_token.authenticate http_client
24 | end
25 |
26 | private def check_refresh_token
27 | if access_token_expired?
28 | refresh_access_token
29 |
30 | @callback.call(self)
31 | end
32 | end
33 |
34 | private def access_token_expired?
35 | Time.utc_now >= @expires_at
36 | end
37 |
38 | private def refresh_access_token
39 | old_access_token = @access_token
40 | @access_token = @oauth2_client.get_access_token_using_refresh_token(@access_token.refresh_token)
41 | @expires_at = Time.utc_now + @access_token.expires_in.seconds
42 | @access_token.refresh_token ||= old_access_token.refresh_token
43 | end
44 | end
45 |
--------------------------------------------------------------------------------