crystal-lang / crystal Goto Github PK
View Code? Open in Web Editor NEWThe Crystal Programming Language
Home Page: https://crystal-lang.org
License: Apache License 2.0
The Crystal Programming Language
Home Page: https://crystal-lang.org
License: Apache License 2.0
I'd love to write something like https://github.com/mbj/mutant and https://github.com/mbj/unparser for crystal. Actually I expect I could reuse lots of code.
Both tools highly depend on the ability to do AST transformations.
Do you have any plans for including a net/http
library?
Would love to see something much easier to use than Ruby's net/http
, maybe something inspired by HTTParty.
foo.cr
class Foo
attr :value
end
foo = Foo.new
foo.value = Foo.new
puts foo.value.value.value
$ ./bin/crystal foo.cr
$ ./foo
Segmentatiion fault: 11
Expected: Called value() for nil
This is because Foo's @value is inferred to be Foo, but it should also be Nil.
(I'm not sure this only applies to recursive structures)
I finally got Crystal working. Yeah! I get a warning though:
DL is deprecated, please use Fiddle
Maybe b/c I am using Ruby 2.0, instead of 1.9?
Hello,
What do you think about automatically marking a class as generic instead of throwing a compiler error?
Just reading through the examples in this section: https://github.com/manastech/crystal/wiki/Introduction#defining-classes
class Box
def initialize(contents)
@contents = contents
end
def contents
@contents
end
end
b1 = Box.new "hello"
b2 = Box.new 1
puts b1.contents.length
puts b2.contents + 2
I think calling .length
somewhere in the code is enough to tell the compiler that you expect a generic Box
class.
Crystal sounds really awesome, and I'm looking forward to seeing how development progresses!
How should we do performance statistics? I'm trying to improve the performance of the specs, and I'm getting (very) different numbers based on my hardware. The array specs run at about 5 seconds on my desktop at home, whereas it runs at about 16 seconds on my laptop for work. Is there any agreed upon platform for measuring performance? What's the best way to deal with differences in performance between machines?
./bin/crystal 1.cr
llc: <stdin>: Invalid MODULE_CODE_GLOBALVAR record
/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
./bin/crystal 1.cr -run
this is works.
Syntax error in zzz: expecting token '=>', not ':'
sc = { A: 0, C: 0, G: 0, T: 0 }
Can I add support for this syntax?
class A
end
x = {} of Int32 => A
x.fetch(10) { A.new }
got big llvm error
Nil assertion failed:
*raise<String>:NoReturn + [53765888]
*Nil#not_nil!<Nil>:NoReturn + [53765888]
*Crystal::LLVMTyper#create_llvm_struct_type<Crystal::LLVMTyper, Crystal::NonGenericClassType+ | Crystal::Metaclass+ | Crystal::GenericClassInstanceType+ | Crystal::HierarchyType+>:Pointer(Void) + [53765888]
*Crystal::LLVMTyper#llvm_type<Crystal::LLVMTyper, Crystal::Type+>:Pointer(Void) + [53765888]
*Crystal::LLVMTyper#llvm_type<Crystal::LLVMTyper, Crystal::Type+>:Pointer(Void) + [53765888]
...
a = [[1], [1.5]]
a[0].each {}
$ ./bin/crystal bar.cr -run
Unknown return type for function call!
UNREACHABLE executed at JIT.cpp:451!
Illegal instruction: 4
Seeing what Ruby code I can port to Crystal. I see that argument splats cause a compile error unexpected token: *
def initialize(*points)
Will support for these be coming?
class Foo
def initialize(value)
@value = value
end
end
def foo
Foo.new(foo)
end
a = foo
I'd like to be able to compile Crystal code directly from Ruby, like this:
compiler = Crystal::Compiler.new
compiler.compile_from_source(File.read("my_code.cr"), output: "my_executable")
However, I noticed that most of this code is heavily coupled to the command line program bin/crystal
. How would the team feel about me doing some refactoring to decouple the compiler from bin/crystal
, provided I give enough test cases, so that both pieces still work as expected?
def foo(key, default)
foo(key) { default }
end
def foo(key)
if !(true)
return yield key
end
yield key
end
foo(1, nil)
Doesn't compile.
I have install llvm with
brew install llvm33 --with-clang
Then when run 'bundle', I have this error:
Gem::Installer::ExtensionBuildError: ERROR: Failed to build gem native extension.
"/Users/username/.rvm/rubies/ruby-1.9.3-p448/bin/ruby" -rubygems /Users/username/.rvm/gems/ruby-1.9.3-p448@global/gems/rake-10.1.0/bin/rake RUBYARCHDIR=/Users/username/.rvm/gems/ruby-1.9.3-p448@crystal/bundler/gems/ruby-llvm-fc8638f73c69/lib RUBYLIBDIR=/Users/username/.rvm/gems/ruby-1.9.3-p448@crystal/bundler/gems/ruby-llvm-fc8638f73c69/lib
checking for llvm-config... llvm-config-3.3
checking for C++ compiler... rake aborted!
Cannot find C++ compiler: tried ["clang++", "g++"]
/Users/username/.rvm/gems/ruby-1.9.3-p448@crystal/bundler/gems/ruby-llvm-fc8638f73c69/ext/ruby-llvm-support/Rakefile:24:in `check_for'
/Users/username/.rvm/gems/ruby-1.9.3-p448@crystal/bundler/gems/ruby-llvm-fc8638f73c69/ext/ruby-llvm-support/Rakefile:44:in `find_cxx'
/Users/username/.rvm/gems/ruby-1.9.3-p448@crystal/bundler/gems/ruby-llvm-fc8638f73c69/ext/ruby-llvm-support/Rakefile:51:in `<top (required)>'
(See full trace by running task with --trace)
I just updated my copy of crystal source, and when I ran crystal -h
I got a stack trace due to a failed dlopen call to libLLVM-3.3.dylib
.
Compiler expects location:
/usr/local/lib/LLVM-3.3
Actual location:
/usr/local/lib//llvm-3.3/lib/libLLVM-3.3.dylib
This could be an OSX thing, since I used homebrew to install llvm-3.3. I thought I may have messed up an Env Var since I'm messing around with emscripten trying to compile Crystal to JavaScript. but printenv
came up without anything related to LLVM.
I could symlink the DLL, but why not fix?
def bar
if 1 == 1
yield
i = 1
end
end
def foo
bar { return }
raise "some"
end
foo
Something's wrong in the codegen for this.
A = (o = Object.new)
def foo
A
end
foo
This doesn't seem very useful but "A = [1, 2, 3]" is lowered to:
A = begin
temp = Array.new(3)
temp[0] = 1
temp[1] = 2
temp[2] = 3
temp.length = 3
temp
end
The problem is in codegen.rb
Is is possible to use the ruby compiler to build some version of the crystal compiler? Then you could bootstrap it over to other, non-glibc platforms.
[1] pry(main)> require './lib/crystal'
=> true
[2] pry(main)> include Crystal
=> Object
[3] pry(main)> p = Program.new
=> main
[4] pry(main)> p.run(%Q{def y; $y = 2; end; y; $y}).to_i
=> 59106768
[5] pry(main)> p.run(%Q{def y; $y = 2; end; y; $y}).to_i
=> 59811104
[6] pry(main)> p.run(%Q{def y; $y = 2; end; y; $y}).to_i
=> 60519712
I'm willing to bet it's an issue with pointers..
I'm not quite all that familiar with how LLVM works, so I can't directly diagnose this myself. I might start messing around with ruby-llvm to get a feel for how the compiler does things.
Seems multiple assign is broken
multiple_assign.cr:
a, b = [1, 2]
Output:
bin/crystal multiple_assign.cr
crystal/lib/crystal/type_inference.rb:482:in `type_assign': undefined method `accept' for nil:NilClass (NoMethodError)
def f(x, &block)
l = ->(y : Int) { block.call(y) }
l.call(x)
end
f(1) { |x| p x }
/home/kostya/crystal/lib/crystal/codegen/llvm_typer.rb:47:in `llvm_type': Unexepcted type in llvm_type (RuntimeError)
from /home/kostya/crystal/lib/crystal/codegen.rb:115:in `llvm_type'
from /home/kostya/crystal/lib/crystal/codegen.rb:1400:in `codegen_fun'
from /home/kostya/crystal/lib/crystal/codegen.rb:220:in `visit_fun_literal'
from /home/kostya/crystal/lib/crystal/ast.rb:31:in `accept'
from /home/kostya/crystal/lib/crystal/codegen.rb:160:in `accept'
from /home/kostya/crystal/lib/crystal/codegen.rb:390:in `codegen_assign_node'
from /home/kostya/crystal/lib/crystal/codegen.rb:371:in `visit_assign'
from /home/kostya/crystal/lib/crystal/ast.rb:31:in `accept'
from /home/kostya/crystal/lib/crystal/codegen.rb:160:in `accept'
from /home/kostya/crystal/lib/crystal/codegen.rb:291:in `block in visit_expressions'
from /home/kostya/crystal/lib/crystal/codegen.rb:290:in `each'
from /home/kostya/crystal/lib/crystal/codegen.rb:290:in `visit_expressions'
from /home/kostya/crystal/lib/crystal/ast.rb:31:in `accept'
from /home/kostya/crystal/lib/crystal/codegen.rb:160:in `accept'
from /home/kostya/crystal/lib/crystal/codegen.rb:1073:in `visit_call'
from /home/kostya/crystal/lib/crystal/ast.rb:31:in `accept'
from /home/kostya/crystal/lib/crystal/codegen.rb:160:in `accept'
from /home/kostya/crystal/lib/crystal/codegen.rb:291:in `block in visit_expressions'
from /home/kostya/crystal/lib/crystal/codegen.rb:290:in `each'
from /home/kostya/crystal/lib/crystal/codegen.rb:290:in `visit_expressions'
from /home/kostya/crystal/lib/crystal/ast.rb:31:in `accept'
from /home/kostya/crystal/lib/crystal/codegen.rb:32:in `build'
from /home/kostya/crystal/lib/crystal/compiler.rb:149:in `block in compile_with_stats_and_profile'
from /home/kostya/crystal/lib/crystal/compiler.rb:204:in `call'
from /home/kostya/crystal/lib/crystal/compiler.rb:204:in `with_stats_or_profile'
from /home/kostya/crystal/lib/crystal/compiler.rb:148:in `compile_with_stats_and_profile'
from /home/kostya/crystal/lib/crystal/compiler.rb:110:in `compile'
from ./bin/crystal:10:in `<main>'
def foo(x)
return if x == 1
1
end
foo(2)
Wow. I just discovered Crystal today. It's perked my interest. Why? B/c I too love Ruby, but for a few years now I have become a little less enamored with her and have been thinking more and more about certain aspects of the language that I would like to see be just a bit different and better. So if you don't mind I would like to offer up some of the better ideas that I have had, and see how they might be received for Crystal.
I'll start with a very simple one here. The equal?
method is really a misnomer. The method would be much better if called identical?
instead b/c thats more exact to what it does --it checks it two reference refer to the exact same object by the fact the object_id
is the same. The use of equal?
also forces the need for an overly terse eql?
method, which could be dropped in favor of equal?
.
In the introduction it says:
Why not make every new instantiation of a class have their instance variables types be inferred as the program is written?The answer is that if every new instantiation of a class was different from every other instantiation, the type inference phase becomes exponential. You would have to wait a very, very, veeeeeeery long time for the program to compile (and believe us: we tried hard to make it fast).
I am trying to understand this better.
One thing that confuses me is that it seems to me that I could write a wrapper class (a bit simplified for example sake):
class Any(T)
def initialize(value : T)
@value = value
end
def method_missing(s, *a, &b)
@value.send(s, *a, &b)
end
end
And then write Box as:
class Box
def initialize(contents : Any)
@contents = contents
end
As long as I convert objects to Any objects when passing them to Box, it's going to act as if it is generic even though its not.
So in thinking about this, why can't Crystal do the same thing? If it can't guarantee an inferred type (or a compatible union) the just treat it like an Any.
def foo
end
if false
foo
else
1
end
def foo
if true
return Object.new
end
end
foo
./bin/crystal -e 'a = [1,2]; a[0], a[1] = a[1], a[0]; p a'
Syntax error in -:1: Impossible
./bin/crystal -e 'a = [1,2]; t = a[1]; a[1] = a[0]; a[0] = t; p a'
[2, 1]
LoadError encountered with the current Homebrew package for LLVM, version 3.2:
/Users/shannonskipper/.gem/ruby/1.9.3/gems/ffi-1.1.5/lib/ffi/library.rb:121:in `block in ffi_lib': Could not open library 'LLVM-3.1': dlopen(LLVM-3.1, 5): image not found. (LoadError)
Could not open library 'libLLVM-3.1.dylib': dlopen(libLLVM-3.1.dylib, 5): image not found
from /Users/shannonskipper/.gem/ruby/1.9.3/gems/ffi-1.1.5/lib/ffi/library.rb:88:in `map'
from /Users/shannonskipper/.gem/ruby/1.9.3/gems/ffi-1.1.5/lib/ffi/library.rb:88:in `ffi_lib'
from /Users/shannonskipper/.gem/ruby/1.9.3/gems/ruby-llvm-3.1.0.beta.1/lib/llvm.rb:10:in `<module:C>'
from /Users/shannonskipper/.gem/ruby/1.9.3/gems/ruby-llvm-3.1.0.beta.1/lib/llvm.rb:8:in `<module:LLVM>'
from /Users/shannonskipper/.gem/ruby/1.9.3/gems/ruby-llvm-3.1.0.beta.1/lib/llvm.rb:6:in `<top (required)>'
from /Users/shannonskipper/.gem/ruby/1.9.3/gems/ruby-llvm-3.1.0.beta.1/lib/llvm/core.rb:1:in `require'
from /Users/shannonskipper/.gem/ruby/1.9.3/gems/ruby-llvm-3.1.0.beta.1/lib/llvm/core.rb:1:in `<top (required)>'
from /Users/shannonskipper/code/crystal/lib/crystal/codegen.rb:1:in `require'
from /Users/shannonskipper/code/crystal/lib/crystal/codegen.rb:1:in `<top (required)>'
from /Users/shannonskipper/code/crystal/lib/crystal.rb:12:in `require'
from /Users/shannonskipper/code/crystal/lib/crystal.rb:12:in `block in <top (required)>'
from /Users/shannonskipper/code/crystal/lib/crystal.rb:11:in `each'
from /Users/shannonskipper/code/crystal/lib/crystal.rb:11:in `<top (required)>'
from ./icr:3:in `require_relative'
from ./icr:3:in `<main>'
Works as expected if I downgrade to the brew for LLVM 3.1.
updated to master and
./bin/crystal -e 'p 1'
DL is deprecated, please use Fiddle
.crystal/main.o: In function `_2A_caller_3C__3E__3A_Array_28_String_29_':
.crystal/main.bc:(.text+0x3e7): undefined reference to `_Ux86_64_getcontext'
.crystal/main.bc:(.text+0x3f6): undefined reference to `_ULx86_64_init_local'
.crystal/main.bc:(.text+0x4b6): undefined reference to `_ULx86_64_step'
.crystal/main.bc:(.text+0x4d1): undefined reference to `_ULx86_64_get_reg'
.crystal/main.bc:(.text+0x523): undefined reference to `_ULx86_64_get_proc_name'
.crystal/Time.o: In function `_2A_Time_23_initialize_3C_Time_3E__3A_Float64':
.crystal/Time.bc:(.text+0x54): undefined reference to `clock_gettime'
collect2: выполнение ld завершилось с кодом возврата 1
/home/kostya/crystal/lib/crystal/compiler.rb:241:in ``': No such file or directory - /tmp/user/1011/crystal20131114-27420-1yskt5u (Errno::ENOENT)
from /home/kostya/crystal/lib/crystal/compiler.rb:241:in `compile_with_stats_and_profile'
from /home/kostya/crystal/lib/crystal/compiler.rb:111:in `compile'
from ./bin/crystal:11:in `<main>'
def foo
yield 1
end
foo { |x| x = 2 }
It even fails if a variable is yielded.
class Test
def say
puts "Hello World!"
end
end
test = Test.new
test.send(:say)
$ bin/crystal hello.cr
Error in crystal/hello.cr:10: undefined method 'send' for Test
test.send(:say)
^~~~
I can't tell you how happy I am to learn that the following reports an undefined method 'monkey' for Zoo
error! I know from experience that Ruby's top-level polluting of all objects is a bad idea.
def monkey
"monkey"
end
class Zoo; end
zoo = Zoo.new
zoo.monkey
One bug report though. I replaced the last three lines with just:
puts monkey
And I get no output. Again, maybe b/c I am using Ruby 2.0? I will try 1.9 and report back.
Tried to install and Bundler reported:
Using ruby-llvm (3.3.0.alpha) from https://github.com/manastech/ruby-llvm.git (at master)
Gem::Installer::ExtensionBuildError: ERROR: Failed to build gem native extension.
"/home/trans/.rubies/ruby-2.0.0-p247/bin/ruby" -rubygems /home/trans/.rubies/ruby-2.0.0-p247/lib/ruby/gems/2.0.0/gems/rake-0.9.6/bin/rake RUBYARCHDIR=/home/trans/.gem/ruby/2.0.0/bundler/gems/ruby-llvm-fc8638f73c69/lib RUBYLIBDIR=/home/trans/.gem/ruby/2.0.0/bundler/gems/ruby-llvm-fc8638f73c69/lib
checking for llvm-config... rake aborted!
Cannot find llvm-config: tried ["llvm-config-3.3", "llvm-config"]
/home/trans/.gem/ruby/2.0.0/bundler/gems/ruby-llvm-fc8638f73c69/ext/ruby-llvm-support/Rakefile:24:in `check_for'
/home/trans/.gem/ruby/2.0.0/bundler/gems/ruby-llvm-fc8638f73c69/ext/ruby-llvm-support/Rakefile:29:in `find_llvm_config'
/home/trans/.gem/ruby/2.0.0/bundler/gems/ruby-llvm-fc8638f73c69/ext/ruby-llvm-support/Rakefile:50:in `<top (required)>'
(See full trace by running task with --trace)
An error occurred while installing ruby-llvm (3.3.0.alpha), and Bundler cannot continue.
Make sure that `gem install ruby-llvm -v '3.3.0.alpha'` succeeds before bundling.
Since crystal has no runtime dependencies (I think so), is crystal suitable for operating system (kernel) development?
a = 1
a = []
a = []
a << 1
"a" is incorrectly typed as a union of Int
and Array<Int>
, but it should be a union of Int
, Array<Nil>
and Array<Int>
./bin/crystal -e 'p 1'
/home/kostya/crystal/lib/crystal/compiler.rb:177:in ``': Text file busy - /tmp/user/1011/crystal20130908-28613-oyi51d (Errno::ETXTBSY)
from /home/kostya/crystal/lib/crystal/compiler.rb:177:in `compile_with_stats_and_profile'
from /home/kostya/crystal/lib/crystal/compiler.rb:102:in `compile'
from ./bin/crystal:10:in `<main>'
./bin/crystal 2.cr -run
/home/kostya/crystal/lib/crystal/compiler.rb:177:in ``': Text file busy - /tmp/user/1011/crystal20130908-29392-1sh4hb1 (Errno::ETXTBSY)
from /home/kostya/crystal/lib/crystal/compiler.rb:177:in `compile_with_stats_and_profile'
from /home/kostya/crystal/lib/crystal/compiler.rb:102:in `compile'
from ./bin/crystal:10:in `<main>'
but this is ok:
./bin/crystal 2.cr -O3 && ./2
I'm trying to write an AUR package of this, but it requires a license specification. I can't find one, however. Please specify what open source license the compiler and library are under
So I have this simple file:
a = "hello"
b = "#{a} world!"
puts b
And if I run crystal hello_world.cr
I get a big stack trace:
{standard input}:5:Unknown pseudo-op: .cfi_startproc
{standard input}:9:Unknown pseudo-op: .cfi_def_cfa_offset
{standard input}:9:Rest of line ignored. 1st junk character valued 51 (3).
{standard input}:39:Unknown pseudo-op: .cfi_endproc
{standard input}:43:Unknown pseudo-op: .cfi_startproc
{standard input}:47:Unknown pseudo-op: .cfi_def_cfa_offset
...
If I run llvm-config --version
I get 3.3
. Do I have the wrong version of LLVM installed? Is there an issue in OSX? Could it be that there's missing an Env Var when invoking crystal
since I just added it to my $PATH
? Thanks.
is this intentional? I expected it to compile hello_word.cr to llvm IR and output hello_world.ll, not compile to binary and print the IR to stderr.
Example:
class Foo
def foo
@x
end
end
Foo.new.foo
Hi,
Crystal is an exciting project with lots of potential. I am interested in the possibility of a Crystal compiler for Windows. How feasible is that idea, and how much work would it be?
Specifically, I would like to be able to compile a Crystal program into a Windows .DLL file with exported C functions. I don't care if I run the actual Crystal compiler on a Linux or Windows machine, I just want to end up with a DLL library that will run on Windows.
I have knowledge of Ruby and some C, and I'm willing to dive into learning about LLVM if it means I can contribute here. I would be pleased if you could point me in the right direction.
Regards,
Justin
class A
def bla
@a = 0
while @a < 10
@a += 1
end
@a
end
end
p A.new.bla
./bin/crystal 15.cr
Error in /home/kostya/crystal/15.cr:11: instantiating 'A#bla()'
p A.new.bla
^~~
in /home/kostya/crystal/15.cr:4: undefined method '<' for Nil
while @a < 10
^
================================================================================
Nil trace:
/home/kostya/crystal/15.cr:4
while @a < 10
^~
./bin/crystal -e 'p "asdf"'
.crystal/-/Math.o: In function `_2A_Math_3A__3A_log2_3C_Math_3A_Class_2C__20_Int32_3E__3A_Float64':
.crystal/-/Math.bc:(.text+0x2a): undefined reference to `log2'
.crystal/-/Float64.o: In function `_2A_Float64_23__2A__2A__3C_Float64_2C__20_Int32_3E__3A_Float64':
.crystal/-/Float64.bc:(.text+0x19): undefined reference to `pow'
collect2: выполнение ld завершилось с кодом возврата 1
sh: 1: /tmp/fileRT8dok: not found
./bin/crystal -e 'puts "asdf"'
asdf
I dont wana download the crystal
binary. I wanna see the source to hack / improve it? Am I'm to stupid to find the lib
directory, and or the Gemfile
Your Installation Instructions tell me to run bundle, but as there is no Gemfile it does not reall make sense?
Am I'm looking into the wrong repo?
./bin/crystal -e 'x = 1/2'
Error in line 1: undefined local variable or method 'tmp'
./bin/crystal -e 'x = (1/2)'
Syntax error in -:1: unexpected token: 2)
./bin/crystal -e 'x = 1 / 2'
ok
Just curious if there is a plan to implement exceptions?
generic class Entry
def next=(n)
@next = n
end
def next
@next
end
end
entry1 = Entry.new
entry1.next = entry1
entry2 = Entry.new
entry2.next = entry1
entry2.next = entry2
union = entry1
union = entry2
union.next
The type inference gives two Entry classes, but only one should exist, that has @next pointing to itself
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.