Skip to content

Commit

Permalink
added new tests and refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
urumo committed Feb 5, 2024
1 parent c483a4c commit 70ee828
Show file tree
Hide file tree
Showing 8 changed files with 725 additions and 22 deletions.
50 changes: 39 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,40 +1,59 @@
# RubyTypeSystem

### A Work in progress type system for Ruby

## Current state

* Ruby is a mature language with a lot of libraries and a lot of code written in it.
* Ruby is a dynamically typed language, which means that the type of a variable is not known until runtime or is known only in the mind of the developer.
* Ruby is a dynamically typed language, which means that the type of a variable is not known until runtime or is known
only in the mind of the developer.
* What ruby lacks is a type system, which is a set of rules that define what types are allowed in a program.
* Solutions like `Sorbet` and `RBS` exist, but they are not part of the language itself and are not widely used. They have their pros and cons.
* The problem with `RBS` is that you have to write a lot of boilerplate code to define types that are only a hint for you favorite IDE.
* The problem with `Sorbet` is that it's not very intuitive and you have to take time to learn and get used to the way it works.
* Solutions like `Sorbet` and `RBS` exist, but they are not part of the language itself and are not widely used. They
have their pros and cons.
* The problem with `RBS` is that you have to write a lot of boilerplate code to define types that are only a hint for
you favorite IDE.
* The problem with `Sorbet` is that it's not very intuitive and you have to take time to learn and get used to the way
it works.

## General idea
The RubyTypeSystem project aims to create an intuitive and easy-to-use type system for Ruby. The main ideas behind this project are:

1. **Intuitive Types**: The types used in this system come from the Ruby standard library. This makes the system intuitive for developers who are already familiar with Ruby.
The RubyTypeSystem project aims to create an intuitive and easy-to-use type system for Ruby. The main ideas behind this
project are:

1. **Intuitive Types**: The types used in this system come from the Ruby standard library. This makes the system
intuitive for developers who are already familiar with Ruby.

2. **Type Inference**: The system will take care of most of the typing through type inference. This reduces the amount of type annotations that developers need to write, making the code cleaner and easier to read.
2. **Type Inference**: The system will take care of most of the typing through type inference. This reduces the amount
of type annotations that developers need to write, making the code cleaner and easier to read.

3. **Method Typing**: Despite the type inference, methods will still require typing. This ensures that the behavior of methods is clear and predictable.
3. **Method Typing**: Despite the type inference, methods will still require typing. This ensures that the behavior of
methods is clear and predictable.

4. **New Keywords**: The system introduces new keywords to describe interfaces, abstract classes, union types, and types in general. These keywords extend the Ruby language with powerful features for static typing.
4. **New Keywords**: The system introduces new keywords to describe interfaces, abstract classes, union types, and types
in general. These keywords extend the Ruby language with powerful features for static typing.

## Some examples

### Type inference

```ruby
some_int: Integer = 1
some_float = some_method_that_returns_float # The compiler assumes a Float type
some_int + some_float # CompileTimeError
```

### Method typing

```ruby
def some_method(a: Integer, b: Integer): Integer
a + b
end
```
A more experienced developer would argue "But how are we going to introduce default values for parameters" and that is a great question.
A more experienced developer would argue "But how are we going to introduce default values for parameters" and that is a
great question.
Let's take the following ruby code as an example:
```ruby
def a(some_val = 1)
some_val + 1
Expand All @@ -44,22 +63,30 @@ def b(key: 'key', value: 'value')
"#{key}: #{value}"
end
```
In this example we have two methods, both have parameters with default values, but the first method has a positional parameter and the second method has keyword parameters.
In this example we have two methods, both have parameters with default values, but the first method has a positional
parameter and the second method has keyword parameters.
In case of positional parameters the following code is equivalent:
```ruby
def a(some_val: Integer = 1): Integer
some_val + 1
end
```
In case of keyword parameters the following code is equivalent:
```ruby
def b([key: String]: 'key', [value: String]: 'value'): String # this approach is up for debate, you can propose a better way in the issues section
"#{key}: #{value}"
end
```
## How it works
The RubyTypeSystem is a work in progress. More details will be added as the project evolves.
=
- The system will be implemented as a compiler that compiles Ruby code down to a single expression.
- The compiler will be written in Ruby.
- The compiler will be written in a way that allows it to be used as a library and a CLI.
Expand All @@ -68,6 +95,7 @@ The RubyTypeSystem is a work in progress. More details will be added as the proj
- The compiler will be able to compile Ruby code without type annotations(will print a lot of warnings).
## Milestones
- [x] Create a compressor, that compresses the source codes down to a single file
- [x] Create a lexer
- [ ] Create a parser that produces an AST
Expand Down
9 changes: 9 additions & 0 deletions spec/examples/test8
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
%w(a b c
d e f)

%i<a b c d
e f
>
%x@a b c d e f@
%Q_a b c d e f_
%r!a b c d e f!
26 changes: 26 additions & 0 deletions spec/examples/test9
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
module A
CONSTANT = 1
CONSTANT_1 = %x(ls ~)
CONSTANT_2 = %w!a b c d e f!

def self.log(msg)
puts msg
end

class A
attr_reader :name
def initialize(name)
@name = name
end

def to_s
"#{self.class.name}: #{@name}"
end
end

class B < A
def initialize(name)
super
end
end
end
2 changes: 1 addition & 1 deletion spec/lexer/results/test2.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
"column": 34
},
{
"type": "puts",
"type": "identifier",
"literal": "puts",
"line": 3,
"column": 40
Expand Down
12 changes: 6 additions & 6 deletions spec/lexer/results/test5.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[
{
"type": "require",
"type": "identifier",
"literal": "require",
"line": 1,
"column": 0
Expand All @@ -12,7 +12,7 @@
"column": 8
},
{
"type": "require_relative",
"type": "identifier",
"literal": "require_relative",
"line": 2,
"column": 19
Expand All @@ -24,7 +24,7 @@
"column": 36
},
{
"type": "load",
"type": "identifier",
"literal": "load",
"line": 3,
"column": 54
Expand Down Expand Up @@ -72,7 +72,7 @@
"column": 108
},
{
"type": "puts",
"type": "identifier",
"literal": "puts",
"line": 7,
"column": 124
Expand All @@ -84,7 +84,7 @@
"column": 129
},
{
"type": "puts",
"type": "identifier",
"literal": "puts",
"line": 8,
"column": 200
Expand Down Expand Up @@ -120,7 +120,7 @@
"column": 289
},
{
"type": "extend",
"type": "identifier",
"literal": "extend",
"line": 13,
"column": 301
Expand Down
8 changes: 4 additions & 4 deletions spec/lexer/results/test7.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[
{
"type": "require",
"type": "identifier",
"literal": "require",
"line": 1,
"column": 0
Expand All @@ -24,7 +24,7 @@
"column": 26
},
{
"type": "include",
"type": "identifier",
"literal": "include",
"line": 4,
"column": 38
Expand Down Expand Up @@ -54,7 +54,7 @@
"column": 55
},
{
"type": "extend",
"type": "identifier",
"literal": "extend",
"line": 5,
"column": 68
Expand Down Expand Up @@ -306,7 +306,7 @@
"column": 277
},
{
"type": "puts",
"type": "identifier",
"literal": "puts",
"line": 16,
"column": 286
Expand Down
Loading

0 comments on commit 70ee828

Please sign in to comment.