mirror of
				https://github.com/KevinMidboe/linguist.git
				synced 2025-10-29 17:50:22 +00:00 
			
		
		
		
	Merge pull request #1109 from github/adding_crystal_samples
Adding Crystal samples to address https://github.com/github/github/issue...
This commit is contained in:
		@@ -96,6 +96,9 @@
 | 
			
		||||
    "Creole": [
 | 
			
		||||
      ".creole"
 | 
			
		||||
    ],
 | 
			
		||||
    "Crystal": [
 | 
			
		||||
      ".cr"
 | 
			
		||||
    ],
 | 
			
		||||
    "CSS": [
 | 
			
		||||
      ".css"
 | 
			
		||||
    ],
 | 
			
		||||
@@ -661,8 +664,8 @@
 | 
			
		||||
      ".gemrc"
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  "tokens_total": 583212,
 | 
			
		||||
  "languages_total": 696,
 | 
			
		||||
  "tokens_total": 584718,
 | 
			
		||||
  "languages_total": 699,
 | 
			
		||||
  "tokens": {
 | 
			
		||||
    "ABAP": {
 | 
			
		||||
      "*/**": 1,
 | 
			
		||||
@@ -16233,6 +16236,253 @@
 | 
			
		||||
      "Ruby": 1,
 | 
			
		||||
      "distribution.": 1
 | 
			
		||||
    },
 | 
			
		||||
    "Crystal": {
 | 
			
		||||
      "SHEBANG#!bin/crystal": 2,
 | 
			
		||||
      "require": 2,
 | 
			
		||||
      "describe": 2,
 | 
			
		||||
      "do": 26,
 | 
			
		||||
      "it": 21,
 | 
			
		||||
      "run": 14,
 | 
			
		||||
      "(": 201,
 | 
			
		||||
      ")": 201,
 | 
			
		||||
      ".to_i.should": 11,
 | 
			
		||||
      "eq": 16,
 | 
			
		||||
      "end": 135,
 | 
			
		||||
      ".to_f32.should": 2,
 | 
			
		||||
      ".to_b.should": 1,
 | 
			
		||||
      "be_true": 1,
 | 
			
		||||
      "assert_type": 7,
 | 
			
		||||
      "{": 7,
 | 
			
		||||
      "int32": 8,
 | 
			
		||||
      "}": 7,
 | 
			
		||||
      "union_of": 1,
 | 
			
		||||
      "char": 1,
 | 
			
		||||
      "result": 3,
 | 
			
		||||
      "types": 3,
 | 
			
		||||
      "[": 9,
 | 
			
		||||
      "]": 9,
 | 
			
		||||
      "mod": 1,
 | 
			
		||||
      "result.program": 1,
 | 
			
		||||
      "foo": 3,
 | 
			
		||||
      "mod.types": 1,
 | 
			
		||||
      "as": 4,
 | 
			
		||||
      "NonGenericClassType": 1,
 | 
			
		||||
      "foo.instance_vars": 1,
 | 
			
		||||
      ".type.should": 3,
 | 
			
		||||
      "mod.int32": 1,
 | 
			
		||||
      "GenericClassType": 2,
 | 
			
		||||
      "foo_i32": 4,
 | 
			
		||||
      "foo.instantiate": 2,
 | 
			
		||||
      "of": 3,
 | 
			
		||||
      "Type": 2,
 | 
			
		||||
      "|": 8,
 | 
			
		||||
      "ASTNode": 4,
 | 
			
		||||
      "foo_i32.lookup_instance_var": 2,
 | 
			
		||||
      "module": 1,
 | 
			
		||||
      "Crystal": 1,
 | 
			
		||||
      "class": 2,
 | 
			
		||||
      "def": 84,
 | 
			
		||||
      "transform": 81,
 | 
			
		||||
      "transformer": 1,
 | 
			
		||||
      "transformer.before_transform": 1,
 | 
			
		||||
      "self": 77,
 | 
			
		||||
      "node": 164,
 | 
			
		||||
      "transformer.transform": 1,
 | 
			
		||||
      "transformer.after_transform": 1,
 | 
			
		||||
      "Transformer": 1,
 | 
			
		||||
      "before_transform": 1,
 | 
			
		||||
      "after_transform": 1,
 | 
			
		||||
      "Expressions": 2,
 | 
			
		||||
      "exps": 6,
 | 
			
		||||
      "node.expressions.each": 1,
 | 
			
		||||
      "exp": 3,
 | 
			
		||||
      "new_exp": 3,
 | 
			
		||||
      "exp.transform": 3,
 | 
			
		||||
      "if": 23,
 | 
			
		||||
      "new_exp.is_a": 1,
 | 
			
		||||
      "exps.concat": 1,
 | 
			
		||||
      "new_exp.expressions": 1,
 | 
			
		||||
      "else": 2,
 | 
			
		||||
      "<<": 1,
 | 
			
		||||
      "exps.length": 1,
 | 
			
		||||
      "node.expressions": 3,
 | 
			
		||||
      "Call": 1,
 | 
			
		||||
      "node_obj": 1,
 | 
			
		||||
      "node.obj": 9,
 | 
			
		||||
      "node_obj.transform": 1,
 | 
			
		||||
      "transform_many": 23,
 | 
			
		||||
      "node.args": 3,
 | 
			
		||||
      "node_block": 1,
 | 
			
		||||
      "node.block": 2,
 | 
			
		||||
      "node_block.transform": 1,
 | 
			
		||||
      "node_block_arg": 1,
 | 
			
		||||
      "node.block_arg": 6,
 | 
			
		||||
      "node_block_arg.transform": 1,
 | 
			
		||||
      "And": 1,
 | 
			
		||||
      "node.left": 3,
 | 
			
		||||
      "node.left.transform": 3,
 | 
			
		||||
      "node.right": 3,
 | 
			
		||||
      "node.right.transform": 3,
 | 
			
		||||
      "Or": 1,
 | 
			
		||||
      "StringInterpolation": 1,
 | 
			
		||||
      "ArrayLiteral": 1,
 | 
			
		||||
      "node.elements": 1,
 | 
			
		||||
      "node_of": 1,
 | 
			
		||||
      "node.of": 2,
 | 
			
		||||
      "node_of.transform": 1,
 | 
			
		||||
      "HashLiteral": 1,
 | 
			
		||||
      "node.keys": 1,
 | 
			
		||||
      "node.values": 2,
 | 
			
		||||
      "of_key": 1,
 | 
			
		||||
      "node.of_key": 2,
 | 
			
		||||
      "of_key.transform": 1,
 | 
			
		||||
      "of_value": 1,
 | 
			
		||||
      "node.of_value": 2,
 | 
			
		||||
      "of_value.transform": 1,
 | 
			
		||||
      "If": 1,
 | 
			
		||||
      "node.cond": 5,
 | 
			
		||||
      "node.cond.transform": 5,
 | 
			
		||||
      "node.then": 3,
 | 
			
		||||
      "node.then.transform": 3,
 | 
			
		||||
      "node.else": 5,
 | 
			
		||||
      "node.else.transform": 3,
 | 
			
		||||
      "Unless": 1,
 | 
			
		||||
      "IfDef": 1,
 | 
			
		||||
      "MultiAssign": 1,
 | 
			
		||||
      "node.targets": 1,
 | 
			
		||||
      "SimpleOr": 1,
 | 
			
		||||
      "Def": 1,
 | 
			
		||||
      "node.body": 12,
 | 
			
		||||
      "node.body.transform": 10,
 | 
			
		||||
      "receiver": 2,
 | 
			
		||||
      "node.receiver": 4,
 | 
			
		||||
      "receiver.transform": 2,
 | 
			
		||||
      "block_arg": 2,
 | 
			
		||||
      "block_arg.transform": 2,
 | 
			
		||||
      "Macro": 1,
 | 
			
		||||
      "PointerOf": 1,
 | 
			
		||||
      "node.exp": 3,
 | 
			
		||||
      "node.exp.transform": 3,
 | 
			
		||||
      "SizeOf": 1,
 | 
			
		||||
      "InstanceSizeOf": 1,
 | 
			
		||||
      "IsA": 1,
 | 
			
		||||
      "node.obj.transform": 5,
 | 
			
		||||
      "node.const": 1,
 | 
			
		||||
      "node.const.transform": 1,
 | 
			
		||||
      "RespondsTo": 1,
 | 
			
		||||
      "Case": 1,
 | 
			
		||||
      "node.whens": 1,
 | 
			
		||||
      "node_else": 1,
 | 
			
		||||
      "node_else.transform": 1,
 | 
			
		||||
      "When": 1,
 | 
			
		||||
      "node.conds": 1,
 | 
			
		||||
      "ImplicitObj": 1,
 | 
			
		||||
      "ClassDef": 1,
 | 
			
		||||
      "superclass": 1,
 | 
			
		||||
      "node.superclass": 2,
 | 
			
		||||
      "superclass.transform": 1,
 | 
			
		||||
      "ModuleDef": 1,
 | 
			
		||||
      "While": 1,
 | 
			
		||||
      "Generic": 1,
 | 
			
		||||
      "node.name": 5,
 | 
			
		||||
      "node.name.transform": 5,
 | 
			
		||||
      "node.type_vars": 1,
 | 
			
		||||
      "ExceptionHandler": 1,
 | 
			
		||||
      "node.rescues": 1,
 | 
			
		||||
      "node_ensure": 1,
 | 
			
		||||
      "node.ensure": 2,
 | 
			
		||||
      "node_ensure.transform": 1,
 | 
			
		||||
      "Rescue": 1,
 | 
			
		||||
      "node.types": 2,
 | 
			
		||||
      "Union": 1,
 | 
			
		||||
      "Hierarchy": 1,
 | 
			
		||||
      "Metaclass": 1,
 | 
			
		||||
      "Arg": 1,
 | 
			
		||||
      "default_value": 1,
 | 
			
		||||
      "node.default_value": 2,
 | 
			
		||||
      "default_value.transform": 1,
 | 
			
		||||
      "restriction": 1,
 | 
			
		||||
      "node.restriction": 2,
 | 
			
		||||
      "restriction.transform": 1,
 | 
			
		||||
      "BlockArg": 1,
 | 
			
		||||
      "node.fun": 1,
 | 
			
		||||
      "node.fun.transform": 1,
 | 
			
		||||
      "Fun": 1,
 | 
			
		||||
      "node.inputs": 1,
 | 
			
		||||
      "output": 1,
 | 
			
		||||
      "node.output": 2,
 | 
			
		||||
      "output.transform": 1,
 | 
			
		||||
      "Block": 1,
 | 
			
		||||
      "node.args.map": 1,
 | 
			
		||||
      "Var": 2,
 | 
			
		||||
      "FunLiteral": 1,
 | 
			
		||||
      "node.def.body": 1,
 | 
			
		||||
      "node.def.body.transform": 1,
 | 
			
		||||
      "FunPointer": 1,
 | 
			
		||||
      "obj": 1,
 | 
			
		||||
      "obj.transform": 1,
 | 
			
		||||
      "Return": 1,
 | 
			
		||||
      "node.exps": 5,
 | 
			
		||||
      "Break": 1,
 | 
			
		||||
      "Next": 1,
 | 
			
		||||
      "Yield": 1,
 | 
			
		||||
      "scope": 1,
 | 
			
		||||
      "node.scope": 2,
 | 
			
		||||
      "scope.transform": 1,
 | 
			
		||||
      "Include": 1,
 | 
			
		||||
      "Extend": 1,
 | 
			
		||||
      "RangeLiteral": 1,
 | 
			
		||||
      "node.from": 1,
 | 
			
		||||
      "node.from.transform": 1,
 | 
			
		||||
      "node.to": 2,
 | 
			
		||||
      "node.to.transform": 2,
 | 
			
		||||
      "Assign": 1,
 | 
			
		||||
      "node.target": 1,
 | 
			
		||||
      "node.target.transform": 1,
 | 
			
		||||
      "node.value": 3,
 | 
			
		||||
      "node.value.transform": 3,
 | 
			
		||||
      "Nop": 1,
 | 
			
		||||
      "NilLiteral": 1,
 | 
			
		||||
      "BoolLiteral": 1,
 | 
			
		||||
      "NumberLiteral": 1,
 | 
			
		||||
      "CharLiteral": 1,
 | 
			
		||||
      "StringLiteral": 1,
 | 
			
		||||
      "SymbolLiteral": 1,
 | 
			
		||||
      "RegexLiteral": 1,
 | 
			
		||||
      "MetaVar": 1,
 | 
			
		||||
      "InstanceVar": 1,
 | 
			
		||||
      "ClassVar": 1,
 | 
			
		||||
      "Global": 1,
 | 
			
		||||
      "Require": 1,
 | 
			
		||||
      "Path": 1,
 | 
			
		||||
      "Self": 1,
 | 
			
		||||
      "LibDef": 1,
 | 
			
		||||
      "FunDef": 1,
 | 
			
		||||
      "body": 1,
 | 
			
		||||
      "body.transform": 1,
 | 
			
		||||
      "TypeDef": 1,
 | 
			
		||||
      "StructDef": 1,
 | 
			
		||||
      "UnionDef": 1,
 | 
			
		||||
      "EnumDef": 1,
 | 
			
		||||
      "ExternalVar": 1,
 | 
			
		||||
      "IndirectRead": 1,
 | 
			
		||||
      "IndirectWrite": 1,
 | 
			
		||||
      "TypeOf": 1,
 | 
			
		||||
      "Primitive": 1,
 | 
			
		||||
      "Not": 1,
 | 
			
		||||
      "TypeFilteredNode": 1,
 | 
			
		||||
      "TupleLiteral": 1,
 | 
			
		||||
      "Cast": 1,
 | 
			
		||||
      "DeclareVar": 1,
 | 
			
		||||
      "node.var": 1,
 | 
			
		||||
      "node.var.transform": 1,
 | 
			
		||||
      "node.declared_type": 1,
 | 
			
		||||
      "node.declared_type.transform": 1,
 | 
			
		||||
      "Alias": 1,
 | 
			
		||||
      "TupleIndexer": 1,
 | 
			
		||||
      "Attribute": 1,
 | 
			
		||||
      "exps.map": 1
 | 
			
		||||
    },
 | 
			
		||||
    "CSS": {
 | 
			
		||||
      ".clearfix": 8,
 | 
			
		||||
      "{": 1661,
 | 
			
		||||
@@ -60965,6 +61215,7 @@
 | 
			
		||||
    "Common Lisp": 103,
 | 
			
		||||
    "Coq": 18259,
 | 
			
		||||
    "Creole": 134,
 | 
			
		||||
    "Crystal": 1506,
 | 
			
		||||
    "CSS": 43867,
 | 
			
		||||
    "Cuda": 290,
 | 
			
		||||
    "Dart": 74,
 | 
			
		||||
@@ -61138,6 +61389,7 @@
 | 
			
		||||
    "Common Lisp": 1,
 | 
			
		||||
    "Coq": 12,
 | 
			
		||||
    "Creole": 1,
 | 
			
		||||
    "Crystal": 3,
 | 
			
		||||
    "CSS": 2,
 | 
			
		||||
    "Cuda": 2,
 | 
			
		||||
    "Dart": 1,
 | 
			
		||||
@@ -61284,5 +61536,5 @@
 | 
			
		||||
    "YAML": 2,
 | 
			
		||||
    "Zephir": 2
 | 
			
		||||
  },
 | 
			
		||||
  "md5": "400a9cd944fe65c38a9fa18d58b773b9"
 | 
			
		||||
  "md5": "5cbb8fcefc5e9c773796d772fe48907d"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										169
									
								
								samples/Crystal/const_spec.cr
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								samples/Crystal/const_spec.cr
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,169 @@
 | 
			
		||||
#!/usr/bin/env bin/crystal --run
 | 
			
		||||
require "../../spec_helper"
 | 
			
		||||
 | 
			
		||||
describe "Codegen: const" do
 | 
			
		||||
  it "define a constant" do
 | 
			
		||||
    run("A = 1; A").to_i.should eq(1)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "support nested constant" do
 | 
			
		||||
    run("class B; A = 1; end; B::A").to_i.should eq(1)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "support constant inside a def" do
 | 
			
		||||
    run("
 | 
			
		||||
      class Foo
 | 
			
		||||
        A = 1
 | 
			
		||||
 | 
			
		||||
        def foo
 | 
			
		||||
          A
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      Foo.new.foo
 | 
			
		||||
    ").to_i.should eq(1)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "finds nearest constant first" do
 | 
			
		||||
    run("
 | 
			
		||||
      A = 1
 | 
			
		||||
 | 
			
		||||
      class Foo
 | 
			
		||||
        A = 2.5_f32
 | 
			
		||||
 | 
			
		||||
        def foo
 | 
			
		||||
          A
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      Foo.new.foo
 | 
			
		||||
    ").to_f32.should eq(2.5)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "allows constants with same name" do
 | 
			
		||||
    run("
 | 
			
		||||
      A = 1
 | 
			
		||||
 | 
			
		||||
      class Foo
 | 
			
		||||
        A = 2.5_f32
 | 
			
		||||
 | 
			
		||||
        def foo
 | 
			
		||||
          A
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      A
 | 
			
		||||
      Foo.new.foo
 | 
			
		||||
    ").to_f32.should eq(2.5)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "constants with expression" do
 | 
			
		||||
    run("
 | 
			
		||||
      A = 1 + 1
 | 
			
		||||
      A
 | 
			
		||||
    ").to_i.should eq(2)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "finds global constant" do
 | 
			
		||||
    run("
 | 
			
		||||
      A = 1
 | 
			
		||||
 | 
			
		||||
      class Foo
 | 
			
		||||
        def foo
 | 
			
		||||
          A
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      Foo.new.foo
 | 
			
		||||
    ").to_i.should eq(1)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "define a constant in lib" do
 | 
			
		||||
    run("lib Foo; A = 1; end; Foo::A").to_i.should eq(1)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "invokes block in const" do
 | 
			
		||||
    run("require \"prelude\"; A = [\"1\"].map { |x| x.to_i }; A[0]").to_i.should eq(1)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "declare constants in right order" do
 | 
			
		||||
    run("A = 1 + 1; B = true ? A : 0; B").to_i.should eq(2)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "uses correct types lookup" do
 | 
			
		||||
    run("
 | 
			
		||||
      module A
 | 
			
		||||
        class B
 | 
			
		||||
          def foo
 | 
			
		||||
            1
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        C = B.new;
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      def foo
 | 
			
		||||
        A::C.foo
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      foo
 | 
			
		||||
      ").to_i.should eq(1)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "codegens variable assignment in const" do
 | 
			
		||||
    run("
 | 
			
		||||
      class Foo
 | 
			
		||||
        def initialize(@x)
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def x
 | 
			
		||||
          @x
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      A = begin
 | 
			
		||||
            f = Foo.new(1)
 | 
			
		||||
            f
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
      def foo
 | 
			
		||||
        A.x
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      foo
 | 
			
		||||
      ").to_i.should eq(1)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "declaring var" do
 | 
			
		||||
    run("
 | 
			
		||||
      BAR = begin
 | 
			
		||||
        a = 1
 | 
			
		||||
        while 1 == 2
 | 
			
		||||
          b = 2
 | 
			
		||||
        end
 | 
			
		||||
        a
 | 
			
		||||
      end
 | 
			
		||||
      class Foo
 | 
			
		||||
        def compile
 | 
			
		||||
          BAR
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      Foo.new.compile
 | 
			
		||||
      ").to_i.should eq(1)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "initialize const that might raise an exception" do
 | 
			
		||||
    run("
 | 
			
		||||
      require \"prelude\"
 | 
			
		||||
      CONST = (raise \"OH NO\" if 1 == 2)
 | 
			
		||||
 | 
			
		||||
      def doit
 | 
			
		||||
        CONST
 | 
			
		||||
      rescue
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      doit.nil?
 | 
			
		||||
    ").to_b.should be_true
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										79
									
								
								samples/Crystal/declare_var_spec.cr
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								samples/Crystal/declare_var_spec.cr
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,79 @@
 | 
			
		||||
#!/usr/bin/env bin/crystal --run
 | 
			
		||||
require "../../spec_helper"
 | 
			
		||||
 | 
			
		||||
describe "Type inference: declare var" do
 | 
			
		||||
  it "types declare var" do
 | 
			
		||||
    assert_type("a :: Int32") { int32 }
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "types declare var and reads it" do
 | 
			
		||||
    assert_type("a :: Int32; a") { int32 }
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "types declare var and changes its type" do
 | 
			
		||||
    assert_type("a :: Int32; while 1 == 2; a = 'a'; end; a") { union_of(int32, char) }
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "declares instance var which appears in initialize" do
 | 
			
		||||
    result = assert_type("
 | 
			
		||||
      class Foo
 | 
			
		||||
        @x :: Int32
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      Foo.new") { types["Foo"] }
 | 
			
		||||
 | 
			
		||||
    mod = result.program
 | 
			
		||||
 | 
			
		||||
    foo = mod.types["Foo"] as NonGenericClassType
 | 
			
		||||
    foo.instance_vars["@x"].type.should eq(mod.int32)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "declares instance var of generic class" do
 | 
			
		||||
    result = assert_type("
 | 
			
		||||
      class Foo(T)
 | 
			
		||||
        @x :: T
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      Foo(Int32).new") do
 | 
			
		||||
        foo = types["Foo"] as GenericClassType
 | 
			
		||||
        foo_i32 = foo.instantiate([int32] of Type | ASTNode)
 | 
			
		||||
        foo_i32.lookup_instance_var("@x").type.should eq(int32)
 | 
			
		||||
        foo_i32
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "declares instance var of generic class after reopen" do
 | 
			
		||||
    result = assert_type("
 | 
			
		||||
      class Foo(T)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      f = Foo(Int32).new
 | 
			
		||||
 | 
			
		||||
      class Foo(T)
 | 
			
		||||
        @x :: T
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      f") do
 | 
			
		||||
        foo = types["Foo"] as GenericClassType
 | 
			
		||||
        foo_i32 = foo.instantiate([int32] of Type | ASTNode)
 | 
			
		||||
        foo_i32.lookup_instance_var("@x").type.should eq(int32)
 | 
			
		||||
        foo_i32
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it "declares an instance variable in initialize" do
 | 
			
		||||
    assert_type("
 | 
			
		||||
      class Foo
 | 
			
		||||
        def initialize
 | 
			
		||||
          @x :: Int32
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        def x
 | 
			
		||||
          @x
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      Foo.new.x
 | 
			
		||||
      ") { int32 }
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										515
									
								
								samples/Crystal/transformer.cr
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										515
									
								
								samples/Crystal/transformer.cr
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,515 @@
 | 
			
		||||
module Crystal
 | 
			
		||||
  class ASTNode
 | 
			
		||||
    def transform(transformer)
 | 
			
		||||
      transformer.before_transform self
 | 
			
		||||
      node = transformer.transform self
 | 
			
		||||
      transformer.after_transform self
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  class Transformer
 | 
			
		||||
    def before_transform(node)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def after_transform(node)
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : Expressions)
 | 
			
		||||
      exps = [] of ASTNode
 | 
			
		||||
      node.expressions.each do |exp|
 | 
			
		||||
        new_exp = exp.transform(self)
 | 
			
		||||
        if new_exp
 | 
			
		||||
          if new_exp.is_a?(Expressions)
 | 
			
		||||
            exps.concat new_exp.expressions
 | 
			
		||||
          else
 | 
			
		||||
            exps << new_exp
 | 
			
		||||
          end
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      if exps.length == 1
 | 
			
		||||
        exps[0]
 | 
			
		||||
      else
 | 
			
		||||
        node.expressions = exps
 | 
			
		||||
        node
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : Call)
 | 
			
		||||
      if node_obj = node.obj
 | 
			
		||||
        node.obj = node_obj.transform(self)
 | 
			
		||||
      end
 | 
			
		||||
      transform_many node.args
 | 
			
		||||
 | 
			
		||||
      if node_block = node.block
 | 
			
		||||
        node.block = node_block.transform(self)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      if node_block_arg = node.block_arg
 | 
			
		||||
        node.block_arg = node_block_arg.transform(self)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : And)
 | 
			
		||||
      node.left = node.left.transform(self)
 | 
			
		||||
      node.right = node.right.transform(self)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : Or)
 | 
			
		||||
      node.left = node.left.transform(self)
 | 
			
		||||
      node.right = node.right.transform(self)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : StringInterpolation)
 | 
			
		||||
      transform_many node.expressions
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : ArrayLiteral)
 | 
			
		||||
      transform_many node.elements
 | 
			
		||||
 | 
			
		||||
      if node_of = node.of
 | 
			
		||||
        node.of = node_of.transform(self)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : HashLiteral)
 | 
			
		||||
      transform_many node.keys
 | 
			
		||||
      transform_many node.values
 | 
			
		||||
 | 
			
		||||
      if of_key = node.of_key
 | 
			
		||||
        node.of_key = of_key.transform(self)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      if of_value = node.of_value
 | 
			
		||||
        node.of_value = of_value.transform(self)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : If)
 | 
			
		||||
      node.cond = node.cond.transform(self)
 | 
			
		||||
      node.then = node.then.transform(self)
 | 
			
		||||
      node.else = node.else.transform(self)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : Unless)
 | 
			
		||||
      node.cond = node.cond.transform(self)
 | 
			
		||||
      node.then = node.then.transform(self)
 | 
			
		||||
      node.else = node.else.transform(self)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : IfDef)
 | 
			
		||||
      node.cond = node.cond.transform(self)
 | 
			
		||||
      node.then = node.then.transform(self)
 | 
			
		||||
      node.else = node.else.transform(self)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : MultiAssign)
 | 
			
		||||
      transform_many node.targets
 | 
			
		||||
      transform_many node.values
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : SimpleOr)
 | 
			
		||||
      node.left = node.left.transform(self)
 | 
			
		||||
      node.right = node.right.transform(self)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : Def)
 | 
			
		||||
      transform_many node.args
 | 
			
		||||
      node.body = node.body.transform(self)
 | 
			
		||||
 | 
			
		||||
      if receiver = node.receiver
 | 
			
		||||
        node.receiver = receiver.transform(self)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      if block_arg = node.block_arg
 | 
			
		||||
        node.block_arg = block_arg.transform(self)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : Macro)
 | 
			
		||||
      transform_many node.args
 | 
			
		||||
      node.body = node.body.transform(self)
 | 
			
		||||
 | 
			
		||||
      if receiver = node.receiver
 | 
			
		||||
        node.receiver = receiver.transform(self)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      if block_arg = node.block_arg
 | 
			
		||||
        node.block_arg = block_arg.transform(self)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : PointerOf)
 | 
			
		||||
      node.exp = node.exp.transform(self)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : SizeOf)
 | 
			
		||||
      node.exp = node.exp.transform(self)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : InstanceSizeOf)
 | 
			
		||||
      node.exp = node.exp.transform(self)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : IsA)
 | 
			
		||||
      node.obj = node.obj.transform(self)
 | 
			
		||||
      node.const = node.const.transform(self)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : RespondsTo)
 | 
			
		||||
      node.obj = node.obj.transform(self)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : Case)
 | 
			
		||||
      node.cond = node.cond.transform(self)
 | 
			
		||||
      transform_many node.whens
 | 
			
		||||
 | 
			
		||||
      if node_else = node.else
 | 
			
		||||
        node.else = node_else.transform(self)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : When)
 | 
			
		||||
      transform_many node.conds
 | 
			
		||||
      node.body = node.body.transform(self)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : ImplicitObj)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : ClassDef)
 | 
			
		||||
      node.body = node.body.transform(self)
 | 
			
		||||
 | 
			
		||||
      if superclass = node.superclass
 | 
			
		||||
        node.superclass = superclass.transform(self)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : ModuleDef)
 | 
			
		||||
      node.body = node.body.transform(self)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : While)
 | 
			
		||||
      node.cond = node.cond.transform(self)
 | 
			
		||||
      node.body = node.body.transform(self)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : Generic)
 | 
			
		||||
      node.name = node.name.transform(self)
 | 
			
		||||
      transform_many node.type_vars
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : ExceptionHandler)
 | 
			
		||||
      node.body = node.body.transform(self)
 | 
			
		||||
      transform_many node.rescues
 | 
			
		||||
 | 
			
		||||
      if node_ensure = node.ensure
 | 
			
		||||
        node.ensure = node_ensure.transform(self)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : Rescue)
 | 
			
		||||
      node.body = node.body.transform(self)
 | 
			
		||||
      transform_many node.types
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : Union)
 | 
			
		||||
      transform_many node.types
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : Hierarchy)
 | 
			
		||||
      node.name = node.name.transform(self)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : Metaclass)
 | 
			
		||||
      node.name = node.name.transform(self)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : Arg)
 | 
			
		||||
      if default_value = node.default_value
 | 
			
		||||
        node.default_value = default_value.transform(self)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      if restriction = node.restriction
 | 
			
		||||
        node.restriction = restriction.transform(self)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : BlockArg)
 | 
			
		||||
      node.fun = node.fun.transform(self)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : Fun)
 | 
			
		||||
      transform_many node.inputs
 | 
			
		||||
 | 
			
		||||
      if output = node.output
 | 
			
		||||
        node.output = output.transform(self)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : Block)
 | 
			
		||||
      node.args.map! { |exp| exp.transform(self) as Var }
 | 
			
		||||
      node.body = node.body.transform(self)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : FunLiteral)
 | 
			
		||||
      node.def.body = node.def.body.transform(self)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : FunPointer)
 | 
			
		||||
      if obj = node.obj
 | 
			
		||||
        node.obj = obj.transform(self)
 | 
			
		||||
      end
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : Return)
 | 
			
		||||
      transform_many node.exps
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : Break)
 | 
			
		||||
      transform_many node.exps
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : Next)
 | 
			
		||||
      transform_many node.exps
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : Yield)
 | 
			
		||||
      if scope = node.scope
 | 
			
		||||
        node.scope = scope.transform(self)
 | 
			
		||||
      end
 | 
			
		||||
      transform_many node.exps
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : Include)
 | 
			
		||||
      node.name = node.name.transform(self)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : Extend)
 | 
			
		||||
      node.name = node.name.transform(self)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : RangeLiteral)
 | 
			
		||||
      node.from = node.from.transform(self)
 | 
			
		||||
      node.to = node.to.transform(self)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : Assign)
 | 
			
		||||
      node.target = node.target.transform(self)
 | 
			
		||||
      node.value = node.value.transform(self)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : Nop)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : NilLiteral)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : BoolLiteral)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : NumberLiteral)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : CharLiteral)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : StringLiteral)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : SymbolLiteral)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : RegexLiteral)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : Var)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : MetaVar)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : InstanceVar)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : ClassVar)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : Global)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : Require)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : Path)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : Self)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : LibDef)
 | 
			
		||||
      node.body = node.body.transform(self)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : FunDef)
 | 
			
		||||
      if body = node.body
 | 
			
		||||
        node.body = body.transform(self)
 | 
			
		||||
      end
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : TypeDef)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : StructDef)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : UnionDef)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : EnumDef)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : ExternalVar)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : IndirectRead)
 | 
			
		||||
      node.obj = node.obj.transform(self)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : IndirectWrite)
 | 
			
		||||
      node.obj = node.obj.transform(self)
 | 
			
		||||
      node.value = node.value.transform(self)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : TypeOf)
 | 
			
		||||
      transform_many node.expressions
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : Primitive)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : Not)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : TypeFilteredNode)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : TupleLiteral)
 | 
			
		||||
      transform_many node.exps
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : Cast)
 | 
			
		||||
      node.obj = node.obj.transform(self)
 | 
			
		||||
      node.to = node.to.transform(self)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : DeclareVar)
 | 
			
		||||
      node.var = node.var.transform(self)
 | 
			
		||||
      node.declared_type = node.declared_type.transform(self)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : Alias)
 | 
			
		||||
      node.value = node.value.transform(self)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : TupleIndexer)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform(node : Attribute)
 | 
			
		||||
      node
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def transform_many(exps)
 | 
			
		||||
      exps.map! { |exp| exp.transform(self) } if exps
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
		Reference in New Issue
	
	Block a user