Permalink
Switch branches/tags
Nothing to show
Find file Copy path
98123b4 Nov 15, 2018
1 contributor

Users who have contributed to this file

1283 lines (969 sloc) 27.4 KB

2018/09/15

Enum and number

enum Status
  # Pattern 1
  case Initialized do
    def to_i; 1; end
  end
  case Processing(progress: Float) do
    def to_i; 2; end
  end
  case Done(result: Int)
  case Error(msg: String)

  # Pattern 2
  case class Initialized
    def to_i; 1; end
  end
  case class Processing(progress: Float)
    def to_i; 2; end
  end
  case Done(result: Int)
  case Error(msg: String)

  # Pattern 3 (swift style)
  def to_i
    case self
    when Initialized then 1
    when Processing then 2
    when Done then 3
    when Error then 4
    end
  end
end

Scala: https://dev.classmethod.jp/server-side/scala-algebra-data-type/

sealed abstract class IndexedEnum(val index: Int)
 
case object IA extends IndexedEnum(1)   // You can specify the arguments for the superclass initializer
case object IB extends IndexedEnum(2)
case object IC extends IndexedEnum(3)
case object ID extends IndexedEnum(4)

Enum and def

enum Status
  def foo
  end

  case class Initialized
    def foo
    end
  end
  case class Processing(progress: Float); end
  case class Done(result: Int); end
  case class Error(msg: String); end
end

:thinking_face:

2018/09/12

Enum

enum Status
  case Initialized
  case Processing(progress: Float)
  case Done(result: Int)
  case Error(msg: String)
end

status = Status::Initialized  # ???
status = Status::Processing.new(0.1)
status = Status::Done.new(result)
status = Status::Error.new("failed")

Maybe

enum Maybe<T>
  case Some(value: T)
  case None
end

We need special care to

  • write None as nil
  • T is transparently compatible to Maybe<T> (like Swift, Crystal)

2018/09/11

nitches

enum A
  case B(x: Int, y: Int)
end
case foo
when B(x, y)
when B(x)
when B(y)    # ??
when B(y, x) # ??
end

Enum (tagged union)

class Result<T, E>
  class Ok<T> < Result<T, E>
    def initialize(@value: T); end
  end
  class Err<T> < Result<T, E>
    def initialize(@value: T); end
  end
end

def foo -> Result<Int, String>
  if bar
    Ok.new(1)
  else
    Err.new('failed')
  end
end

case foo
when Ok(value)
  p value
when Err(msg)
  p msg
else
  # How to make sure never reach here? 
end
enum Result<T, E>
  case Ok(value: T)
  case Err(value: E)
end

def foo -> Result<Int, String>
  if bar
    Result::Ok.new(1)
  else
    Result::Err.new('failed')
  end
end

case foo
when Ok(value)
  ...
when Error(msg)
  ...
else
  # Never reaches here (we cannot add new case to an enum)
end

2018/09/09

Maybe

https://qiita.com/koher/items/e4835bd429b88809ab33#comment-bca0e884f74ca1acdd9a

class Maybe<T>
  class Some<T> extends Maybe<T>
    def initialize(@value: T); end
  end
  class None extends Maybe<Nothing>  # Nothing: the bottom type
  end
end
nil = Maybe::None.new(??)

var a : Maybe<Int> = Some.new(1)
var a : Maybe<Int> = nil

Changing signature on override

I found this is not an error in Scala because it has method overloads :thinking_face:

class A(id: String) {
  def foo(x: Int): Int = {
    x
  }
}
class B(id: String) extends A(id) {
  def foo(x: String): Int = {
    x.length() + 99
  }
}
class C(id: String) extends A(id) {
}

Array(new B("hi"), new C("c")).foreach(item => println(item.foo(1)))
  • Method with the same name and different parameter types are considered different
  • It is not allowed to define method with the same name, parameter types and different return type

2018/09/08

KeyError: key not found: "B<Int>"

    class A; end
    class B<T> extends A; end
    var x = A.new
    x = B<Int>.new
  1. B<Int> is instantiated while evaluating the rhs of =
  2. It should be added to the env to type check =

2018/09/07

Type and SkClass

Maybe we need only one of these?

2018/09/06

Superclass and metaclass

- Array<T> < Object
- Meta:Array<T> < Meta:Object 

- B<T> < A<T>
- Meta:B<T> < Meta:A<T>

Make sure every ivars are initialized on instance creation

  • Rule 1(Parent class): initialize should initialize every ivar
  • Rule 2(Child class): When overriding initialize, it should call super on all paths
class A
  def initialize(@a: Int)
    @b = 2
    var @c = 3
  end
end

class B extends A
  # NG
  def initialize
  end

  # OK 1
  def initialize(@a: Int)
  end

  # OK 2
  def initialize
    super(99)
  end
end

Inheritance and initialize

class A
  def initialize(@a: Int)
  end
end

class B extends A
#  def initialize  # This is wrong because `b = B.new` does not initialize @a
#  end

  def initialize(@a: Int)
  end

  def initialize
    super(1)
  end
end

Java: Members are initialized by null

class A<T> {
  public String id;
}
class B<T> extends A<T> {}

public class Main {
  public static void main(String[] args){
    System.out.println(new B().id);  //=> null
  }
}

Scala: Pass arguments on extend

class A[T](id: String) {
}
// class B[T] extends A[T] {  // error: not enough arguments for constructor A: (id: String)this.A[T].
// }
class B[T](id: String) extends A[T](id) {
}
println(new B("hi"))

Swift: Memvers should have an initial value or initialized by init (or decalred as optional)

class A<T> {
    public let id: Int;
    init(id: Int) {
        self.id = id;
    }
}
class B<T>: A<T> {}
print(B<Int>())  // error: missing argument for parameter 'id' in call

Swift: When overriding init, super.init must be called in every path

class A<T> {
    public let id: Int;
    public let foo: Int;
    init(id: Int) {
        self.id = id;
        self.foo = id;
    }
}
class B<T>: A<T> {
    override init(id: Int) {
        super.init(id: id)
        // Without this:
        // error: super.init isn't called on all paths before returning from initializer
    }
}
print(B<Int>(id: 1))

Crystal: like Swift

class A
    def initialize(a : String)
        @a = a
    end
end
class B < A
    def initialize
        #return    # This causes Invalid memory acceess (^_^;
        super(1)
        # Without this:
        # Error in a.cr:7: this 'initialize' doesn't initialize instance variable '@a' of A, with B < A, rendering it nilable
    end
end

p B.new()

Subtyping

  • class B<S, T> extends A<S, T, S, S>
    • The direct superclass of B<Int, Bool> is A<Int, Bool, Int, Int>
  • class C<S, T> extends A<S, A<T, S>>
    • The direct superclass of C<Int, Bool> is A<Int, A<Bool, Int>>
    • That is, c = C<Int, Bool>.new conforms to A<Int, A<Bool, Int>>

2018/07/07

Type conformation

Sometimes we want to know a type conforms to another type.

class A<T> < B
  def foo(x: Array<T>)
    bar(x)
  end

  def bar(y: Foo<T>)
  end
end
  • Method call bar(x) is legal when Array<T> conforms to Foo<T>.
    • For example, when Foo is defined as class Foo<T> : Array<T>

Type and class

class A<T> < B
  def foo(x: Array<T>)
  end
end

Array<T> here is obviously "a type", but not "a class". A type may represent more than one classes.

Subtyping

  • class A < B; end
    • A < B (A is a subclass of B)
    • A <: B (A is a proper subclass of B, because A != B)
    • A <1 B (A is a direct subclass of B)
  • class C[T] < B; end`
    • C[T] < B
    • C[Int] < B
  • class D[T] < C[T]; end`
    • D[Int] < C[Int]
    • class E[S]; def f(x: D[S])

Module

module M
  def foo
  end
end

class A
  include M
  #=> A.new.foo
  # A --> M --> Object
end

class B
  extend M
  #=> B.foo
  #=> Meta:B --> M --> Meta:Object
end

2018/06/27

Lambda

Syntax

  • f = fn(x: Int){ x + 1 }
  • f = fn{|x: Int| x + 1 }
  • f = fn<T>(x: T){ x }
  • How to invoke it?
    • Like method call?
      • f(1)
      • g = fn(){ foo }; g()
      • Unlike method invocation, parentheses are mandatory
      • Otherwise (i.e. if g is an invocation) we cannot pass g as an argument
    • g.call(1)
    • g.(1)
    • g[1]

Types

  • f = fn(x: Int){ x + 1 } :: Func1[Int, Int]

Passing to method call

def foo(x: Int, f: (y: Int) -> Int)
  f(x)
end

foo(123){|y| y+1}

f = fn(y: Int){ y+1 }
foo(123, f)

2018/06/08

vararg

        class A
          def self.first(*b: Array<Int>) -> Int
            b.first
          end
        end
        A.first(1,2,3)

What is needed to implement this?

2018/06/04

Class method and typaram

         class A<T>
           def self.foo(x: T) -> Void
           end

           def self.bar(x: Int) -> Void
           end
         end

Idea

  • A<Int>.foo(1) is ok
  • A.foo(1) is ng (SkNoMethodError)
  • A.bar(1) is ok
  • A<String>.bar(1) is... ok? ng? whichever?

2018/06/02

Variance

Even if you don't add variance annotation to your language, you may need to care about variance in some places:

  • Functions
  • Built-in classes like Array[T]

Actually Swift's arrays are "magically" covariant, though it does not have variance annotations for user-defined classes.

2018/06/01

Symbol for generics (again)

class Something<T <: String>
  def 
end

This is terrible.

class Something[T <: String]
  def 
end

Now I'm thinking to use [] again, even if APIs like Set[] become impossible.

2018/05/31

Where typaram occurs

         class A<T>
           def initialize(@a: T, x: T)
             # Type of @a should be TyParam[T]
             # Type of x should be TyParam[T]
           end

           def foo(x: T) -> T
             # Type of x should be TyParam[T]
           end
           # It is better if the signature of foo is (x: TyParam[T]) -> TyParam[T]
           # I guess it is (x: TyRaw[T]) -> TyRaw[T] now (unconfirmed)
         end
  • Change them to TyParam<T> on:
    • a) Ast::DefMethod?
      • It does not know its context (i.e. the surrounding DefClass) now
    • b) Typing SkMethod
      • Looks fine!

Ast::TypeParameter

                # This `T` is Ast::TypeParameter
         class A<T>

Type of x

         class A<T>
           def foo(x: T) -> Int
             x.abs  #=> I need to know its lower bound here.
                    # So type of `x` should be `TyParam["T"]`
           end
         end
         A<Int>.new.foo(1)
  • Currently it's TyRaw[T]
  • parser.ry.erb generates this TyRaw
    • Because it does not know T is a typaram here

Another bug

Noticed that this program is also results in an exception.

         class A<T>
           def foo(x: T) -> Int
             x.abs
           end
         end
         A<Int>.new.foo(1)

# expected Shiika::Program::SkTypeError, got #<KeyError: key not found: "T"> with backtrace:
#  ./lib/shiika/program/env.rb:88:in `fetch'
#  ./lib/shiika/program/env.rb:88:in `find_method'

The correct exception is an SkTypeError. (because x does not always have .abs method)

Current status

  • Type of @a is TyRaw[T]
  • Should be TyParam[T] or something? :thinking_face:
  • For method parameters, we inject type arguments "lazily"
    • @sk_methods of SkSpecializedClass is empty at first. Methods are created when they are called (i.e. its invocation is found during type checking)
  • options:
    • a) Do it lazily for ivars too
    • b) Do it eagerly
  • No, this question is wrong. We want to know the lower bound of @a while typing the SkGenericClass A.

oh

This program should be invalid.

     class A<T>
       def initialize(@a: T)
         @a = 2
       end
     end
     A<Int>.new(1)

Because the lower bound of T is Object and is not compatible with 2(Int). (XXX: I'm not confident about the relation between lower bound and assignment)

find_ivar

  • Currently Program::Env#find_ivar lookups ivar from :sk_self
  • It looks sk_self.sk_ivars

ivars of generic class

class A<T>
  def initialize(@a: T)
  end
end
  • A itself does not have ivars?
    • This seems to be a subtle problem because we can never touch them
    • But the SkGenericClass must have @a because it will be used when creating a SkSpecializedClass
  • A<Int> has an ivar @a whose type is Int
    • When creating a SkSpecializedClass, its ivars must have appropreate type

Concrete class, abstract class

  • String is a concrete class
  • Array is an abstract class
  • Array<Int> is a concrete class

2018/05/05

When to create SkSpecializedClass?

  • Specialized class may appear in the program as:
    • part of an expression. eg: Pair<Int, Int>.new
    • type specification. eg: def f(x: Pair<Int, Int>)

2018/05/04

Typecheck of generic methods

class A<T>
  def foo(x: T)
    x.abs
  end
end
A<Int>.new.foo(1)
  • On typechecking the call of foo, we need to know that T is Int
  • However, on typechecking the body of foo, we need to "forget" T is Int in this program
    • Because T could be another type in other part of the program

Therefore:

  • The body of foo is typechecked only once
    • x is considered to be an instance of Object (the upper bound of T)
  • On the other hand, different SkMethod will be created for each A<??>
    • eg. A<Int>#foo(x: Int)

2018/05/03

.new of a specialized class

  • SkGenericMetaClass never have .new
  • However, SkSpecializedMetaClass should have a .new, magically
  • Here we need a special rule
  • Note that SkGenericClass may have #initialize

Env#find_method

  • When typechecking a call of a generic method, we need to create a specialized version of the SkMethod
  • Conceptually, each SkSpecialized(Meta)Class has all the method defined in SkGeneric(Meta)Class
  • But I want to create them lazily
  • Anyway, type arguments are needed to instantiate a generic method
    • SkSpecialized(Meta)Class knows the type args

Infinite loop on #inspect

           <-  #sk_class
 SkClass              SkMetaClass
   #meta_class  ->

TODO: remove SkClass#meta_class (find from env instead)

When to check type of specialized class?

  • a) When it is first used
  • b) On typecheck the ClassSpecialization

b.

Pair<Int,Int>.new

  1. Check type of the MethodCall (method_name: "new")
  2. Find method "new" of SkSpeMeta Pair<Int,Int>
  3. But SkSpecializedMetaClass Pair<Int,Int> is not yet created here

2018/05/02

SkMethod#sk_class ?

class A<X>
  def foo<Y>(x: X, y: Y)
  end
end
a = A<Int>.new
a.foo<Int>(1, 2)
  • The signature of A#foo is (x: X, y: Y) -> Void
  • To typecheck the call of A#foo, actual type of X and Y is needed
  • How to get X ?
    • a) SkMethod has typarams == ['X', 'Y']
    • b) SkMethod has reference to SkClass

2018/04/16

Oh

  • If Set[Int] is Set.[](Int), we could never write Set[1,2,3]!

2018/04/13

Hmm

  • SkMethod(...)
  • SkGenericMethod(..., type_parameters)
  • SkSpecializedMethod(..., type_parameters, type_arguments)

2018/04/11

TODO

  • Syntax of types is extended
    • def foo(a: Int)
    • def foo(a: Pair[Int, Int])
    • def foo(a: Pair[Int, Pair[Int, Int]])

2018/04/07

Pair.[] should not be a method

Reason:

  • a = Pair[Int, String].new(1, "foo") is a valid code
  • But it is nice if type parameters are automatically inferred:
    • a = Pair.new(1, "foo")
  • It is very odd to say "Invocation of Pair.[] is ommited here"
  • vs.
    • a = Pair<Int, String>.new(1, "foo")
    • a = Pair.new(1, "foo")
    • "<> is a notation for typarmas and sometimes you can omit it"

Can we define Pair.[] ?

  • Pair.[] takes two class objects and returns a class object
  • i.e. Pair[Int, String] returns a class object Pair[Int, String]
  • Pair[1, 2] is nonsense. i.e. the arguments must be classes
  • So the signature should be Pair[S, T] -> Pair[S, T], where S <: Meta:Object and T <: Meta:Object ?

Method that takes a class

  • Given def bar(x: Object)
    • bar(Object.new) is ok
    • bar(Int.new) is ok because Int <: Object
  • Given def foo(x: Meta:Int)
    • foo(Int) is the only way to call this method
    • How to allow foo(Object) ?
    • What object Int.superclass evaluates to?
      • Object seems natural
    • If Meta:Int <: Meta:Object ?
Int <: Object
Meta:Int <: Meta:Object <: Class
Pair <: GenericClass
Meta:Pair <: GenericClass

2018/04/06

Remember the problem

Exception:

Shiika::Program::SkTypeError: class Meta:Pair' does not have a method []'

Shiika source:

  Pair[Int, Bool].new(1, true).fst

Problem:

  • Can we define Pair.[] ?
    • What type will it have?
      • Pair.[][S, T] :: (S, T) -> Pair[S, T] ?
      • NO.
      • Pair.[] takes two classes, not usual objects
  • Maybe [] should not be a method
    • In that case I would choose Pair<S, T> notation

Singleton method and metaclass

  • 1.class returns a object Int
  • I've learned that we need a type for that
    • so it is not possible to introduce singleton methods "instead of" metaclasses.

2018/04/04

Hmm

  • Introducing 'singleton method' means that some objects has special methods
  • To check 'what methods that object has', special type is needed
    • A type for a single object
  • How should I call it?
    • Meta:A
      • A : Meta:A
      • a.class : Meta:A
      • A.class : Meta
    • Class:A
      • A : Class:A
      • a.class : Class:A
      • A.class : Class
  • We need a type of a class
    • or a class of a class
    • which cannot be just a Class (because of singleton methods)
  • I'm glad if all types are classes
    • so type of a class should be a class
    • and not just a Class
    • Meta:A should be a class (with special naming rule)

self

   # SkClass
      def calc_type!(env)
        @sk_ivars.each_value{|x| x.add_type!(env)}
        senv = env.merge(:sk_self, self)  #???
        @class_methods.each_value{|x| x.add_type!(senv)}
        menv = env.merge(:sk_self, self)
        @sk_methods.each_value{|x| x.add_type!(menv)}
        return env, TyRaw[name]
      end

2018/04/03

Next task

  • Remove metaclass and introduce singleton method
  • Only Classes/Modules can have singleton methods
  • On method invoation, if the receiver is a Class/Module, singleton methods should be searched

I'm back

Mostly forgot what to do next.

2018/03/11

Singleton class in Ruby

  • Each ruby object has its singleton classes
    • Which holds its singleton methods
  • In this way, method lookup could be implemented straight-forward

2018/03/09

Superclass

  • String is an instance of Class
  • String's superclass is Object
  • Array is an intance of Class
  • Array's superclass template is Object
  • Array[Int] is an instance of Class
  • Array[Int]'s superclass is Object
  • If one defined SortedArray[T] < Array[T]:
    • SortedArray is an intance of Class
    • SortedArray[T]'s superclass template is Array[T]
    • SortedArray[Int] is an instance of Class
    • SortedArray[Int]'s superclass is Array[Int]
  • Class is an instance of Class
  • Class's superclass is Module
  • Module is an instance of Class
  • Module's superclass is Object
  • Object is an instance of Class
  • Object's superclass is nil

Metaclass vs. singleton methods

Maybe Metaclass model is too complex... 🤔 How about singleton methods?

  • Allow classes to have singleton methods
    • (Unlike Ruby, singleton methods are allowed only to Classes and Modules)
  • String.new() -> String is a singleton method of String
  • String itself is an instance of Class class
    • There are many instances of Class class but their .new method have all different signature
    • This is legal because they are singleton method

So next question is how to mix this with generics.

  • Array.new is not allowed
  • Array[Int].new(100) should be legal
    • So specialized class Array[Int] has a singleton method new(Int) -> Array[Int]
  • Array does not have .new but has some other methods
    • Like Array.constants?
    • This method is defined in Class (or inherited from the superclass Module)
      • Remember Array is an instance of Class
      • (Memo: Class is also an instance of Class)

Metaclass

  • "foo".reverse

    • String#reverse() -> String
  • "foo".object_id

    • Object#object_id() -> Int
  • String.new

    • Meta:String#new() -> String
  • [1,2,3].reverse

    • Array[Int]#reverse() -> Array[Int]
  • Array[Int].new(1,2,3)

    • Meta:Array[Int]#new(*items) -> Array[Int]

Metaclasses in Smalltalk

(I'm not sure this is correct)

  • Everything is object
  • So class itself is an object
  • For each class X, there is a metaclass X class
    • Metaclass is also an object (instance of Metaclass)
      • Metaclass is also an object (instance of Metaclass itself, so there is no things like meta-meta-class)

2018/03/08

Meta:Pair

🤔

 Object     Meta:Object  "Object"      Object    GenericClass   Meta:Object
 .object_id  .new                                    .[]
   v           v            v             v           v             v
  Int        Meta:Int   Pair[S,T]   Pair[Int,Int] Meta:Pair  Meta:Pair[Int,Int]

Current status

Exception:

Shiika::Program::SkTypeError: class Meta:Pair' does not have a method []'

Shiika source:

  Pair[Int, Bool].new(1, true).fst

Pair[Int, Bool] is parsed as Pair.[](Int, Bool) here. So generic class Pair should have a class method [].

2018/03/04

Container classes in Ruby

  • Array[T]
  • Hash[K, V]
  • Set[T] (stdlib)

and Enumerable?

2018/03/02

What to do next

  class Pair[S, T]
    # Here we refer to `S`, but env.find_type raises "unknown type: S"
    def initialize(@a: S, @b: T)
    end

    def fst -> S; @a; end
    def snd -> T; @b; end
  end
  Pair[Int, Bool].new(1, true).fst
  • env.find_type('S') should return something
    • Like Type::Typaram?
      • Currently it is almost the same as Object
      • This object will have the information about upper/lower bound, if introduced
        • to tell if a class confirms to the type

2018/03/01

Keyword argument

(Current idea) All methods can be invoked with keyword arguments.

def foo(a: Int = 1, b: Int = 2); end

foo(3, 4)
foo(3, b: 4)     # Allow this?
foo(b: 4, a: 3)

2018/02/28

Types in Shiika

🤔

  • Value types
    • Concrete value types
      • Class type
    • Abstract value types
      • Type parameter
  • Non-value types
    • Generic class
    • Method signature
    • Function signature?

2018/02/27

Types in Scala

https://www.scala-lang.org/files/archive/spec/2.11/03-types.html#paths

  • Value types
    • Concrete value types
      • Class type
      • Compound type
    • Abstract value types
      • Type parameter
      • Abstract type binding
  • Non-value types
    • Type constructor
    • Method type

2018/02/25

Scala functions

  • Int => Int is just a shorthand of Function1[Int, Int]
  • This type does not include all information about the function (eg. default value for a parameter)
  • IOW this type includes all the information for type checking
    • Arity
    • Types of each paraemter
    • Type of the return value

2018/02/24

Signature of closures?

f = fn(x){ x + 1 }

What is "type" and/or "signature" of f?

2018/02/23

Type vs. Signature

  • What is "signature"?
    • Is it a type or not?
  • eg. In Haskell:
    • Every value belongs to a type
    • Functions are values
    • So each function belongs to a type such as f :: Int -> Int
    • Application f "foo" is a type error
  • In Shiika, methods are not first-class value
    • But off course, we want to check type errors for method calls
    • There should be information of what a method takes and returns (= Signature)

2018/02/20

Funcion call or variable reference

  def do_task(after: () -> Void)
    # do something

    # This may look like a function call, but...
    after

    # There's a case that passing `after` to another function,
    # so `after` should be a variable reference.
    do_task_2(after)

    # Allow this?
    after()

    # How about these?
    another()  # Call of another method
    another    # Allow this or prohibit this?
  end

  def another
  end

2018/02/19

Nullary-function problem

  • Ruby's Proc is like function but has different syntax to invoke
def foo(*args); end
bar = Proc.new

foo  # Method call
bar  # Variable reference
foo(1)  # Method call
bar(1)  # *Error*
bar.call(1)  # OK

bar[1]       # Alternative syntax of call (`#[]` is an alias of `#call`)
bar.(1)      # Alternative syntax of call (rarely used, though)

Note that you need to write bar.call to invoke the function with 0 arguments.

2018/02/18

Function type?

2018/02/17

Data structure for types

  • What object should env.find_type return?
    • It should be able to tell an object conforms (= its class conforms) to the type

Type syntax

  • Types can be appeared in some place of a program
    • Function signature (params, return value)
    • Instance variable type
    • Cast
  • Type syntax
    • Class name (non-generic)
      • => An instance of the class or its subclasses
    • Class name (generic)
      • => Illegal (type argument required)
    • Generic class name + type arguments
      • eg. Stack[Int]
      • => Instance of the class
      • (This will change once covariance/contravariance are introduced)
    • Type parameter name
      • => An instance of the class Object or its subclasses
      • (Once upper/lower bounds are introduced, instance of a class between the bound)

2018/02/16

What is type

  • Given x: Foo, x is an instance of Foo or its subclasses
    • Type = set of classes
  • x: Array is not allowed (missing type argument)
    • Shiika needs a definition of type syntax

Is Stack[Int] a class?

No?

Generics

Thinking about generics since the new year. Shiika won't have even the class Array without it.

Notes:

  • Use [] for generics syntax
  • Reason1: <> is not suitable when <: and >: are introduced to denote upper/lower bound
    • Swift uses : to denote upper bound (No syntax for lower bound)
  • Reason2: Stack[T] looks like a method call :-)
    • Can we define this as method call?
    • Stack#[] to return specialized class

2018/02/15

MetaClass

  • In Ruby, Array evaluates to an object (an instance of the Class class)
  • In Shiika too?
  • But Array.new and String.new have different signature
    • In Ruby, new is their "singleton method" so they can behave differently even the name is the same
  • No plan to introduce "singleton method" to Shiika
  • MetaClass
    • Array evaluates to an object
    • Its class is Meta:Array (metaclass of Array)
    • new is defined on Meta:Array

Shiika

  • Static typing
  • Ruby-like syntax
    • But not 100% compatible
  • Interpreter is written in Ruby (for now)
    • Future plan: compile to LLVM IR (using Go or something?)
  • Challenge
    • Rubyish + Static type system

shiika-memo

Notes for https://github.com/yhara/shiika .