From 209aee25acfae532451be67d44b6f9aeab651f84 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig <aborenszweig@manas.com.ar> Date: Sat, 18 Jan 2014 22:31:25 -0300 Subject: [PATCH] Make primitive types that extend from Value be structs, and some errors when extending a struct from a class, etc. --- spec/compiler/codegen/and_spec.cr | 18 ++++----- spec/compiler/codegen/block_spec.cr | 10 ++--- spec/compiler/codegen/case_spec.cr | 2 +- spec/compiler/codegen/def_spec.cr | 4 +- spec/compiler/codegen/hierarchy_spec.cr | 2 +- spec/compiler/codegen/is_a_spec.cr | 6 +-- spec/compiler/codegen/or_spec.cr | 18 ++++----- spec/compiler/codegen/primitives_spec.cr | 2 +- spec/compiler/codegen/responds_to_spec.cr | 2 +- spec/compiler/codegen/return_spec.cr | 6 +-- spec/compiler/codegen/struct_spec.cr | 4 +- spec/compiler/codegen/union_type_spec.cr | 2 +- spec/compiler/interpreter/interpreter_spec.cr | 2 +- spec/compiler/parser/parser_spec.cr | 4 +- spec/compiler/type_inference/block_spec.cr | 2 +- spec/compiler/type_inference/class_spec.cr | 2 +- spec/compiler/type_inference/const_spec.cr | 2 +- spec/compiler/type_inference/def_spec.cr | 4 +- spec/compiler/type_inference/if_spec.cr | 2 +- spec/compiler/type_inference/is_a_spec.cr | 4 +- spec/compiler/type_inference/module_spec.cr | 2 +- spec/compiler/type_inference/union_spec.cr | 6 +-- src/bool.cr | 2 +- src/char.cr | 2 +- src/compiler/crystal/codegen.cr | 40 +++++++++---------- src/compiler/crystal/lexer.cr | 2 +- .../type_inference/type_visitor_helper.cr | 16 +++++++- src/compiler/crystal/types.cr | 24 ++++++++++- src/float.cr | 6 +-- src/int.cr | 18 ++++----- src/nil.cr | 2 +- src/number.cr | 2 +- src/symbol.cr | 4 +- src/value.cr | 2 +- 34 files changed, 131 insertions(+), 95 deletions(-) diff --git a/spec/compiler/codegen/and_spec.cr b/spec/compiler/codegen/and_spec.cr index d1467ecd6a..9bf16460fe 100755 --- a/spec/compiler/codegen/and_spec.cr +++ b/spec/compiler/codegen/and_spec.cr @@ -19,11 +19,11 @@ describe "Code gen: and" do end it "codegens and with bool and int 1" do - run("class Bool; def to_i; 0; end; end; (false && 2).to_i").to_i.should eq(0) + run("struct Bool; def to_i; 0; end; end; (false && 2).to_i").to_i.should eq(0) end it "codegens and with bool and int 2" do - run("class Bool; def to_i; 0; end; end; (true && 2).to_i").to_i.should eq(2) + run("struct Bool; def to_i; 0; end; end; (true && 2).to_i").to_i.should eq(2) end it "codegens and with primitive type other than bool" do @@ -85,7 +85,7 @@ describe "Code gen: and" do it "codegens and with bool union as left node 1" do run(" - class Bool; def to_i; 0; end; end + struct Bool; def to_i; 0; end; end a = false a = 1 (a && 2).to_i @@ -94,7 +94,7 @@ describe "Code gen: and" do it "codegens and with bool union as left node 2" do run(" - class Bool; def to_i; 0; end; end + struct Bool; def to_i; 0; end; end a = 1 a = false (a && 2).to_i @@ -103,7 +103,7 @@ describe "Code gen: and" do it "codegens and with bool union as left node 3" do run(" - class Bool; def to_i; 0; end; end + struct Bool; def to_i; 0; end; end a = 1 a = true (a && 2).to_i @@ -113,7 +113,7 @@ describe "Code gen: and" do it "codegens and with bool union as left node 1" do run(" require \"nil\" - class Bool; def to_i; 1; end; end + struct Bool; def to_i; 1; end; end a = false a = nil a = 2 @@ -124,7 +124,7 @@ describe "Code gen: and" do it "codegens and with bool union as left node 2" do run(" require \"nil\" - class Bool; def to_i; 1; end; end + struct Bool; def to_i; 1; end; end a = nil a = 2 a = false @@ -135,7 +135,7 @@ describe "Code gen: and" do it "codegens and with bool union as left node 3" do run(" require \"nil\" - class Bool; def to_i; 1; end; end + struct Bool; def to_i; 1; end; end a = nil a = 2 a = true @@ -146,7 +146,7 @@ describe "Code gen: and" do it "codegens and with bool union as left node 4" do run(" require \"nil\" - class Bool; def to_i; 1; end; end + struct Bool; def to_i; 1; end; end a = 2 a = true a = nil diff --git a/spec/compiler/codegen/block_spec.cr b/spec/compiler/codegen/block_spec.cr index 8e830df922..744da7f178 100755 --- a/spec/compiler/codegen/block_spec.cr +++ b/spec/compiler/codegen/block_spec.cr @@ -40,7 +40,7 @@ describe "Code gen: block" do it "pass self to yielder function" do run(" - class Int + struct Int def foo yield self end @@ -54,7 +54,7 @@ describe "Code gen: block" do it "pass self and arguments to yielder function" do run(" - class Int + struct Int def foo(i) yield self, i end @@ -550,7 +550,7 @@ describe "Code gen: block" do end - class Int + struct Int def foo x = Foo.new x = Bar.new @@ -708,7 +708,7 @@ describe "Code gen: block" do it "allows yields with less arguments than in block" do run(" - class Nil + struct Nil def to_i 0 end @@ -812,7 +812,7 @@ describe "Code gen: block" do it "codegens block with union arg" do run(" - class Number + struct Number def abs self end diff --git a/spec/compiler/codegen/case_spec.cr b/spec/compiler/codegen/case_spec.cr index de1b9fd2a9..f37c6794c5 100644 --- a/spec/compiler/codegen/case_spec.cr +++ b/spec/compiler/codegen/case_spec.cr @@ -55,7 +55,7 @@ describe "Code gen: case" do it "codegens case with class" do run(" require \"nil\" - class Int32 + struct Int32 def foo self end diff --git a/spec/compiler/codegen/def_spec.cr b/spec/compiler/codegen/def_spec.cr index 55f66bcb48..01d9a336be 100755 --- a/spec/compiler/codegen/def_spec.cr +++ b/spec/compiler/codegen/def_spec.cr @@ -23,7 +23,7 @@ describe "Code gen: def" do end it "uses self" do - run("class Int; def foo; self + 1; end; end; 3.foo").to_i.should eq(4) + run("struct Int; def foo; self + 1; end; end; 3.foo").to_i.should eq(4) end it "uses var after external" do @@ -138,7 +138,7 @@ describe "Code gen: def" do run(" require \"prelude\" - class Int + struct Int def baz(x) end end diff --git a/spec/compiler/codegen/hierarchy_spec.cr b/spec/compiler/codegen/hierarchy_spec.cr index 0a852658dd..4142036ee5 100755 --- a/spec/compiler/codegen/hierarchy_spec.cr +++ b/spec/compiler/codegen/hierarchy_spec.cr @@ -243,7 +243,7 @@ describe "Code gen: hierarchy type" do class Bar < Foo end - class Nil + struct Nil def foo 2 end diff --git a/spec/compiler/codegen/is_a_spec.cr b/spec/compiler/codegen/is_a_spec.cr index baa72bd459..f0e1db89c3 100755 --- a/spec/compiler/codegen/is_a_spec.cr +++ b/spec/compiler/codegen/is_a_spec.cr @@ -70,7 +70,7 @@ describe "Codegen: is_a?" do it "evaluate method on filtered type nilable type nil" do run(" - class Nil + struct Nil def foo 1 end @@ -251,13 +251,13 @@ describe "Codegen: is_a?" do it "restricts union with union" do run(" - class Char + struct Char def +(other : Int32) other end end - class Bool + struct Bool def foo 2 end diff --git a/spec/compiler/codegen/or_spec.cr b/spec/compiler/codegen/or_spec.cr index 93ec441565..e3d8119c17 100755 --- a/spec/compiler/codegen/or_spec.cr +++ b/spec/compiler/codegen/or_spec.cr @@ -19,11 +19,11 @@ describe "Code gen: or" do end it "codegens or with bool and int 1" do - run("class Bool; def to_i; 0; end; end; (false || 2).to_i").to_i.should eq(2) + run("struct Bool; def to_i; 0; end; end; (false || 2).to_i").to_i.should eq(2) end it "codegens or with bool and int 2" do - run("class Bool; def to_i; 0; end; end; (true || 2).to_i").to_i.should eq(0) + run("struct Bool; def to_i; 0; end; end; (true || 2).to_i").to_i.should eq(0) end it "codegens or with primitive type other than bool" do @@ -85,7 +85,7 @@ describe "Code gen: or" do it "codegens or with bool union as left node 1" do run(" - class Bool; def to_i; 0; end; end + struct Bool; def to_i; 0; end; end a = false a = 1 (a || 2).to_i @@ -94,7 +94,7 @@ describe "Code gen: or" do it "codegens or with bool union as left node 2" do run(" - class Bool; def to_i; 0; end; end + struct Bool; def to_i; 0; end; end a = 1 a = false (a || 2).to_i @@ -103,7 +103,7 @@ describe "Code gen: or" do it "codegens or with bool union as left node 3" do run(" - class Bool; def to_i; 0; end; end + struct Bool; def to_i; 0; end; end a = 1 a = true (a || 2).to_i @@ -113,7 +113,7 @@ describe "Code gen: or" do it "codegens or with bool union as left node 1" do run(" require \"nil\" - class Bool; def to_i; 1; end; end + struct Bool; def to_i; 1; end; end a = false a = nil a = 2 @@ -124,7 +124,7 @@ describe "Code gen: or" do it "codegens or with bool union as left node 2" do run(" require \"nil\" - class Bool; def to_i; 1; end; end + struct Bool; def to_i; 1; end; end a = nil a = 2 a = false @@ -135,7 +135,7 @@ describe "Code gen: or" do it "codegens or with bool union as left node 3" do run(" require \"nil\" - class Bool; def to_i; 1; end; end + struct Bool; def to_i; 1; end; end a = nil a = 2 a = true @@ -146,7 +146,7 @@ describe "Code gen: or" do it "codegens or with bool union as left node 4" do run(" require \"nil\" - class Bool; def to_i; 1; end; end + struct Bool; def to_i; 1; end; end a = 2 a = true a = nil diff --git a/spec/compiler/codegen/primitives_spec.cr b/spec/compiler/codegen/primitives_spec.cr index 469fb64c28..617da12390 100755 --- a/spec/compiler/codegen/primitives_spec.cr +++ b/spec/compiler/codegen/primitives_spec.cr @@ -49,7 +49,7 @@ describe "Code gen: primitives" do it "defined method that calls primitive (bug)" do run(" - class Int64 + struct Int64 def foo to_u64 end diff --git a/spec/compiler/codegen/responds_to_spec.cr b/spec/compiler/codegen/responds_to_spec.cr index df49a7c3fa..6c49004d8d 100644 --- a/spec/compiler/codegen/responds_to_spec.cr +++ b/spec/compiler/codegen/responds_to_spec.cr @@ -19,7 +19,7 @@ describe "Codegen: responds_to?" do end it "codegens is_a? with nilable gives true" do - run("class Nil; def foo; end; end; (1 == 1 ? nil : Reference.new).responds_to?(:foo)").to_b.should be_true + run("struct Nil; def foo; end; end; (1 == 1 ? nil : Reference.new).responds_to?(:foo)").to_b.should be_true end it "codegens is_a? with nilable gives false becuase other type 1" do diff --git a/spec/compiler/codegen/return_spec.cr b/spec/compiler/codegen/return_spec.cr index 75430d8037..dbaa22aa8e 100644 --- a/spec/compiler/codegen/return_spec.cr +++ b/spec/compiler/codegen/return_spec.cr @@ -15,11 +15,11 @@ describe "Code gen: return" do end it "return from function with union type" do - run("class Char; def to_i; 2; end; end; def foo; return 1 if 1 == 1; 'a'; end; foo.to_i").to_i.should eq(1) + run("struct Char; def to_i; 2; end; end; def foo; return 1 if 1 == 1; 'a'; end; foo.to_i").to_i.should eq(1) end it "return union" do - run("class Char; def to_i; 2; end; end; def foo; 1 == 2 ? return 1 : return 'a'; end; foo.to_i").to_i.should eq(2) + run("struct Char; def to_i; 2; end; end; def foo; 1 == 2 ? return 1 : return 'a'; end; foo.to_i").to_i.should eq(2) end it "return from function with nilable type" do @@ -32,7 +32,7 @@ describe "Code gen: return" do it "returns empty from function" do run(" - class Nil; def to_i; 0; end; end + struct Nil; def to_i; 0; end; end def foo(x) return if x == 1 1 diff --git a/spec/compiler/codegen/struct_spec.cr b/spec/compiler/codegen/struct_spec.cr index bfd87dabac..04b7391efc 100644 --- a/spec/compiler/codegen/struct_spec.cr +++ b/spec/compiler/codegen/struct_spec.cr @@ -212,13 +212,13 @@ describe "Code gen: struct" do it "uses nilable struct" do run(" - class Nil + struct Nil def nil? true end end - class Value + struct Value def nil? false end diff --git a/spec/compiler/codegen/union_type_spec.cr b/spec/compiler/codegen/union_type_spec.cr index b36fa95cdd..01e518b75a 100644 --- a/spec/compiler/codegen/union_type_spec.cr +++ b/spec/compiler/codegen/union_type_spec.cr @@ -68,7 +68,7 @@ describe "Code gen: union type" do run(" require \"prelude\" - class Char + struct Char def to_i ord end diff --git a/spec/compiler/interpreter/interpreter_spec.cr b/spec/compiler/interpreter/interpreter_spec.cr index b5e8f44429..28ec0e8be7 100644 --- a/spec/compiler/interpreter/interpreter_spec.cr +++ b/spec/compiler/interpreter/interpreter_spec.cr @@ -65,7 +65,7 @@ describe "Interpreter" do end it "interprets a def and a call with self" do - assert_interpret_primitive "class Int32; def foo; self; end; end; 1.foo", 1, &.int32 + assert_interpret_primitive "struct Int32; def foo; self; end; end; 1.foo", 1, &.int32 end it "interprets primitive +" do diff --git a/spec/compiler/parser/parser_spec.cr b/spec/compiler/parser/parser_spec.cr index 4b5b75e87c..ef8dcb1e55 100755 --- a/spec/compiler/parser/parser_spec.cr +++ b/spec/compiler/parser/parser_spec.cr @@ -1,7 +1,7 @@ #!/usr/bin/env crystal --run require "../../spec_helper" -class Number +struct Number def int32 NumberLiteral.new to_s, :i32 end @@ -19,7 +19,7 @@ class Number end end -class Bool +struct Bool def bool BoolLiteral.new self end diff --git a/spec/compiler/type_inference/block_spec.cr b/spec/compiler/type_inference/block_spec.cr index bdf31757c1..c437d8d5ed 100755 --- a/spec/compiler/type_inference/block_spec.cr +++ b/spec/compiler/type_inference/block_spec.cr @@ -93,7 +93,7 @@ describe "Block inference" do it "infers type of block before call" do result = assert_type(" - class Int32 + struct Int32 def foo 10.5 end diff --git a/spec/compiler/type_inference/class_spec.cr b/spec/compiler/type_inference/class_spec.cr index 4de1978ed8..8cc69a90fd 100755 --- a/spec/compiler/type_inference/class_spec.cr +++ b/spec/compiler/type_inference/class_spec.cr @@ -245,7 +245,7 @@ describe "Type inference: class" do end it "reports undefined method when method inside a class" do - assert_error "class Int; def foo; 1; end; end; foo", + assert_error "struct Int; def foo; 1; end; end; foo", "undefined local variable or method 'foo'" end diff --git a/spec/compiler/type_inference/const_spec.cr b/spec/compiler/type_inference/const_spec.cr index 6dfc4740b5..1c06102542 100755 --- a/spec/compiler/type_inference/const_spec.cr +++ b/spec/compiler/type_inference/const_spec.cr @@ -104,7 +104,7 @@ describe "Type inference: const" do it "finds const from restriction" do assert_type(" - class Int32 + struct Int32 FOO = 'a' end diff --git a/spec/compiler/type_inference/def_spec.cr b/spec/compiler/type_inference/def_spec.cr index 2b80ec4188..6789b2d221 100755 --- a/spec/compiler/type_inference/def_spec.cr +++ b/spec/compiler/type_inference/def_spec.cr @@ -65,7 +65,7 @@ describe "Type inference: def" do end it "assigns def owner" do - input = parse "class Int; def foo; 2.5; end; end; 1.foo" + input = parse "struct Int; def foo; 2.5; end; end; 1.foo" result = infer_type input mod, input = result.program, result.node as Expressions (input.last as Call).target_def.owner.should eq(mod.int32) @@ -116,7 +116,7 @@ describe "Type inference: def" do end it "defines class method with self" do - assert_type("class Int; def self.foo; 2.5; end; end; Int.foo") { float64 } + assert_type("struct Int; def self.foo; 2.5; end; end; Int.foo") { float64 } end it "calls with default argument" do diff --git a/spec/compiler/type_inference/if_spec.cr b/spec/compiler/type_inference/if_spec.cr index cd3eaedf89..0e1ee77a49 100755 --- a/spec/compiler/type_inference/if_spec.cr +++ b/spec/compiler/type_inference/if_spec.cr @@ -16,7 +16,7 @@ describe "Type inference: if" do it "types and if with and and assignment" do assert_type(" - class Number + struct Number def abs self end diff --git a/spec/compiler/type_inference/is_a_spec.cr b/spec/compiler/type_inference/is_a_spec.cr index cb3eeffb20..a74c2e2d7d 100755 --- a/spec/compiler/type_inference/is_a_spec.cr +++ b/spec/compiler/type_inference/is_a_spec.cr @@ -135,13 +135,13 @@ describe "Type inference: is_a?" do it "checks union with union" do assert_type(" - class Char + struct Char def +(other : Int32) self end end - class Bool + struct Bool def foo 2 end diff --git a/spec/compiler/type_inference/module_spec.cr b/spec/compiler/type_inference/module_spec.cr index ff3973f0c4..1010a93045 100755 --- a/spec/compiler/type_inference/module_spec.cr +++ b/spec/compiler/type_inference/module_spec.cr @@ -205,7 +205,7 @@ describe "Type inference: module" do assert_type(" require \"prelude\" - class Int32 + struct Int32 include Enumerable(Int32) def each diff --git a/spec/compiler/type_inference/union_spec.cr b/spec/compiler/type_inference/union_spec.cr index 3098473891..89eb32e69f 100755 --- a/spec/compiler/type_inference/union_spec.cr +++ b/spec/compiler/type_inference/union_spec.cr @@ -3,15 +3,15 @@ require "../../spec_helper" describe "Type inference: union" do it "types union when obj is union" do - assert_type("class Char; def +(other); self; end; end; a = 1 || 'a'; a + 1") { union_of(int32, char) } + assert_type("struct Char; def +(other); self; end; end; a = 1 || 'a'; a + 1") { union_of(int32, char) } end it "types union when arg is union" do - assert_type("class Int; def +(x : Char); x; end; end; a = 1 || 'a'; 1 + a") { union_of(int32, char) } + assert_type("struct Int; def +(x : Char); x; end; end; a = 1 || 'a'; 1 + a") { union_of(int32, char) } end it "types union when both obj and arg are union" do - assert_type("class Char; def +(other); self; end; end; class Int; def +(x : Char); x; end; end; a = 1 || 'a'; a + a") { union_of(int32, char) } + assert_type("struct Char; def +(other); self; end; end; struct Int; def +(x : Char); x; end; end; a = 1 || 'a'; a + a") { union_of(int32, char) } end it "types union of classes" do diff --git a/src/bool.cr b/src/bool.cr index 2061f4d1f2..1e4d45f727 100644 --- a/src/bool.cr +++ b/src/bool.cr @@ -1,4 +1,4 @@ -class Bool +struct Bool def !@ self ? false : true end diff --git a/src/char.cr b/src/char.cr index 01f4028b03..fea93a38aa 100644 --- a/src/char.cr +++ b/src/char.cr @@ -1,4 +1,4 @@ -class Char +struct Char def ==(other : Int) ord == other end diff --git a/src/compiler/crystal/codegen.cr b/src/compiler/crystal/codegen.cr index d57b295e6b..6569c58eb1 100644 --- a/src/compiler/crystal/codegen.cr +++ b/src/compiler/crystal/codegen.cr @@ -445,7 +445,7 @@ module Crystal def codegen_primitive_pointer_get(node, target_def, call_args) type = @type as PointerInstanceType @last = call_args[0] - @last = @builder.load(@last) unless type.var.type.union? || type.var.type.value_like? + @last = @builder.load(@last) unless type.var.type.union? || type.var.type.struct_like? @last end @@ -494,7 +494,7 @@ module Crystal @last = call_args[1] value = @last - value = @builder.load value if node.type.value_like? + value = @builder.load value if node.type.struct_like? ptr = struct_field_ptr(type, name, call_args[0]) @builder.store value, ptr @@ -508,7 +508,7 @@ module Crystal name = target_def.name @last = struct_field_ptr(type, name, call_args[0]) - @last = @builder.load(@last) unless node.type.value_like? + @last = @builder.load(@last) unless node.type.struct_like? @last end @@ -534,7 +534,7 @@ module Crystal name = target_def.name[0 .. -2] @last = call_args[1] - @last = @builder.load @last if node.type.value_like? + @last = @builder.load @last if node.type.struct_like? ptr = union_field_ptr(node, call_args[0]) @builder.store @last, ptr @@ -547,7 +547,7 @@ module Crystal name = target_def.name @last = union_field_ptr(node, call_args[0]) - @last = @builder.load(@last) unless node.type.value_like? + @last = @builder.load(@last) unless node.type.struct_like? @last end @@ -807,7 +807,7 @@ module Crystal ret @last end else - @last = @builder.load @last if return_type.value_like? + @last = @builder.load @last if return_type.struct_like? ret @last end end @@ -1075,7 +1075,7 @@ module Crystal if @node.type.nilable? && LLVM.type_kind_of(LLVM.type_of value) == LibLLVM::TypeKind::Integer @phi_table.add block, @codegen.builder.int2ptr(value, @codegen.llvm_type(node.type)) else - value = @codegen.builder.load value if type.value_like? + value = @codegen.builder.load value if type.struct_like? @phi_table.add block, value end @count += 1 @@ -1212,7 +1212,7 @@ module Crystal def codegen_assign(pointer, target_type, value_type, value, load_struct_and_union = true) if target_type == value_type - value = @builder.load value if target_type.union? || (load_struct_and_union && target_type.value_like?) + value = @builder.load value if target_type.union? || (load_struct_and_union && target_type.struct_like?) @builder.store value, pointer elsif target_type.is_a?(HierarchyTypeMetaclass) && value_type.is_a?(Metaclass) @builder.store value, pointer @@ -1281,7 +1281,7 @@ module Crystal unless type == @mod.void casted_value_ptr = cast_to_pointer value_ptr, type - value = @builder.load value if type.value_like? + value = @builder.load value if type.struct_like? @builder.store value, casted_value_ptr end end @@ -1308,7 +1308,7 @@ module Crystal if var_type == @mod.void # Nothing to do elsif var_type == node.type - @last = @builder.load(@last) unless var.treated_as_pointer || var_type.union? || var_type.value_like? + @last = @builder.load(@last) unless var.treated_as_pointer || var_type.union? || var_type.struct_like? elsif var_type.is_a?(NilableType) if node.type.nil_type? @last = null_pointer?(@last) @@ -1355,7 +1355,7 @@ module Crystal else value_ptr = union_value(@last) @last = cast_to_pointer value_ptr, to_type - @last = @builder.load(@last) unless to_type.value_like? + @last = @builder.load(@last) unless to_type.struct_like? end end @@ -1389,7 +1389,7 @@ module Crystal def read_global(name, type) @last = get_global name, type - @last = @builder.load @last unless type.union? || type.value_like? + @last = @builder.load @last unless type.union? || type.struct_like? @last end @@ -1399,7 +1399,7 @@ module Crystal ivar = type.lookup_instance_var(node.name) @last = instance_var_ptr type, node.name, llvm_self_ptr - if ivar.type.union? || ivar.type.value_like? + if ivar.type.union? || ivar.type.struct_like? unless node.type == ivar.type if node.type.union? @last = cast_to_pointer @last, node.type @@ -1568,7 +1568,7 @@ module Crystal LLVM.set_initializer global, @last LLVM.set_global_constant global, true else - if const.value.type.value_like? + if const.value.type.struct_like? @last = @builder.load @last LLVM.set_initializer global, LLVM.undef(llvm_type(const.value.type)) else @@ -1594,7 +1594,7 @@ module Crystal end @last = global - @last = @builder.load @last unless const.value.type.value_like? + @last = @builder.load @last unless const.value.type.struct_like? elsif replacement = node.syntax_replacement replacement.accept self else @@ -1770,7 +1770,7 @@ module Crystal ptr = visit_indirect(node) ptr = cast_to_pointer ptr, node.type - if node.type.value_like? + if node.type.struct_like? @last = ptr else @last = @builder.load ptr @@ -1785,7 +1785,7 @@ module Crystal node.value.accept self - if node.value.type.value_like? + if node.value.type.struct_like? @last = @builder.load @last end @@ -1924,7 +1924,7 @@ module Crystal return_block = @return_block = new_block "return" return_block_table = @return_block_table = LLVM::PhiTable.new return_type = @return_type = node.type - if return_type.union? || return_type.value_like? + if return_type.union? || return_type.struct_like? @return_union = alloca(llvm_type(node.type), "return") else @return_union = nil @@ -2136,7 +2136,7 @@ module Crystal @builder.unreachable end - if type.union? || type.value_like? + if type.union? || type.struct_like? union = alloca llvm_type(type) @builder.store @last, union @last = union @@ -2322,7 +2322,7 @@ module Crystal if return_type == @mod.void ret - elsif return_type.value_like? + elsif return_type.struct_like? ret(@builder.load(@last)) else ret(@last) diff --git a/src/compiler/crystal/lexer.cr b/src/compiler/crystal/lexer.cr index 53ecac276d..a94bb29d62 100644 --- a/src/compiler/crystal/lexer.cr +++ b/src/compiler/crystal/lexer.cr @@ -2,7 +2,7 @@ require "token" require "exception" require "char_reader" -class Char +struct Char def ident_start? alpha? || self == '_' end diff --git a/src/compiler/crystal/type_inference/type_visitor_helper.cr b/src/compiler/crystal/type_inference/type_visitor_helper.cr index 9b3ff0bcb9..d2318e2782 100644 --- a/src/compiler/crystal/type_inference/type_visitor_helper.cr +++ b/src/compiler/crystal/type_inference/type_visitor_helper.cr @@ -20,8 +20,22 @@ module Crystal end type = scope.types[name]? + + if !type && superclass + if (!!node.struct) != (!!superclass.struct?) + node.raise "can't make #{node.struct ? "struct" : "class"} '#{node.name}' inherit #{superclass.type_desc} '#{superclass.to_s}'" + end + end + if type - node.raise "#{name} is not a class, it's a #{type.type_desc}" unless type.is_a?(ClassType) + unless type.is_a?(ClassType) + node.raise "#{name} is not a #{node.struct ? "struct" : "class"}, it's a #{type.type_desc}" + end + + if (!!node.struct) != (!!type.struct?) + node.raise "#{name} is not a #{node.struct ? "struct" : "class"}, it's a #{type.type_desc}" + end + if node.superclass && type.superclass != superclass node.raise "superclass mismatch for class #{type} (#{superclass} for #{type.superclass})" end diff --git a/src/compiler/crystal/types.cr b/src/compiler/crystal/types.cr index 994640d82b..22ca98ec75 100644 --- a/src/compiler/crystal/types.cr +++ b/src/compiler/crystal/types.cr @@ -97,7 +97,7 @@ module Crystal false end - def value_like? + def struct_like? c_struct? || c_union? || struct? end @@ -924,6 +924,7 @@ module Crystal def initialize(program, container, name, superclass, @llvm_type, @llvm_size) super(program, container, name, superclass) + self.struct = true end def llvm_name @@ -938,6 +939,14 @@ module Crystal true end + def struct_like? + false + end + + def passed_by_val? + false + end + def allocated true end @@ -1020,9 +1029,22 @@ module Crystal end class ValueType < NonGenericClassType + def initialize(program, container, name, superclass, add_subclass = true) + super + self.struct = true + end + def value? true end + + def struct_like? + false + end + + def passed_by_val? + false + end end module GenericType diff --git a/src/float.cr b/src/float.cr index 26fd473885..eb2a6a045b 100644 --- a/src/float.cr +++ b/src/float.cr @@ -1,4 +1,4 @@ -class Float +struct Float def +@ self end @@ -16,7 +16,7 @@ class Float end end -class Float32 +struct Float32 MIN = -INFINITY MAX = INFINITY @@ -33,7 +33,7 @@ class Float32 end end -class Float64 +struct Float64 MIN = -INFINITY MAX = INFINITY diff --git a/src/int.cr b/src/int.cr index bd638297db..a205dbe5ee 100644 --- a/src/int.cr +++ b/src/int.cr @@ -1,4 +1,4 @@ -class Int +struct Int def ==(other : Char) self == other.ord end @@ -91,7 +91,7 @@ class Int end end -class Int8 +struct Int8 MIN = -128_i8 MAX = 127_i8 @@ -106,7 +106,7 @@ class Int8 end end -class Int16 +struct Int16 MIN = -32768_i16 MAX = 32767_i16 @@ -121,7 +121,7 @@ class Int16 end end -class Int32 +struct Int32 MIN = -2147483648_i32 MAX = 2147483647_i32 @@ -136,7 +136,7 @@ class Int32 end end -class Int64 +struct Int64 MIN = -9223372036854775808_i64 MAX = 9223372036854775807_i64 @@ -151,7 +151,7 @@ class Int64 end end -class UInt8 +struct UInt8 MIN = 0_u8 MAX = 255_u8 @@ -162,7 +162,7 @@ class UInt8 end end -class UInt16 +struct UInt16 MIN = 0_u16 MAX = 65535_u16 @@ -173,7 +173,7 @@ class UInt16 end end -class UInt32 +struct UInt32 MIN = 0_u32 MAX = 4294967295_u32 @@ -184,7 +184,7 @@ class UInt32 end end -class UInt64 +struct UInt64 MIN = 0_u64 MAX = 18446744073709551615_u64 diff --git a/src/nil.cr b/src/nil.cr index 9b9755d504..35a37d13d6 100644 --- a/src/nil.cr +++ b/src/nil.cr @@ -1,4 +1,4 @@ -class Nil +struct Nil def object_id 0_u64 end diff --git a/src/number.cr b/src/number.cr index af55d01496..31e301dd55 100644 --- a/src/number.cr +++ b/src/number.cr @@ -1,4 +1,4 @@ -class Number +struct Number def ==(other) false end diff --git a/src/symbol.cr b/src/symbol.cr index 6100a7ba7a..8bb8eedb0f 100644 --- a/src/symbol.cr +++ b/src/symbol.cr @@ -1,4 +1,4 @@ -class Symbol +struct Symbol def ==(other) false end @@ -6,4 +6,4 @@ class Symbol def inspect ":#{to_s}" end -end \ No newline at end of file +end diff --git a/src/value.cr b/src/value.cr index 5d93ece072..3142681517 100644 --- a/src/value.cr +++ b/src/value.cr @@ -1,4 +1,4 @@ -class Value +struct Value def !@ false end -- GitLab