halunke 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1cf23103f236d1d5c248fe1bf071db2e49873fe1
4
- data.tar.gz: 03a326bb35a35d4a6711b5e72ab11cd6f55fec40
3
+ metadata.gz: d378d2686f483584090e764b7d90eeb13b18614c
4
+ data.tar.gz: 7f280aa4dfe247d55b37b863a8766bf9113fb80f
5
5
  SHA512:
6
- metadata.gz: dba700ccf46564d88034913a3ff10168cbb6acb0d50abbcf9d3a0f32cdcdb12ccf594b877f0e20fce4d70f1f50df69095ffedfb1ccccefcb07d811c885d66bd8
7
- data.tar.gz: 7d641c828755558b4581fccdd536a82bf8ac4434c667c3731d74ad0404f64d31f602f9c66a00d346cc88b07c4a15719fdacd1676345c0d825c734ccf3eafbd4d
6
+ metadata.gz: 5d1721feb87183a3be4cb3efd2420cb1b4ca5263fcc525413c64ee1884420441761200227f200572a38f24d9b12e1b12f29ccfcafae05d7498cc3179a9a0dd41
7
+ data.tar.gz: ae52853223039380e48c35eb867f693a88b257f8510b9d79c67e4e0641d89df3489a3104ebffadc0bcdc5a9edcf588dae68f218e82c36a930f0d5e421bdb1340
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- halunke (0.3.1)
4
+ halunke (0.4.0)
5
5
  rack (~> 2.0.4)
6
6
 
7
7
  GEM
data/docs/_config.yml CHANGED
@@ -7,5 +7,7 @@ title: Halunke!
7
7
  description: >-
8
8
  Halunke is a dynamic, object-oriented language that has a simple grammar inspired by Smalltalk and Lisp
9
9
 
10
+ baseurl: "/halunke"
11
+
10
12
  # Build settings
11
13
  markdown: kramdown
@@ -10,41 +10,41 @@
10
10
  <body>
11
11
  <div class="container">
12
12
  <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
13
- <a class="navbar-brand" href="#">Halunke!</a>
13
+ <a class="navbar-brand" href="/halunke">Halunke!</a>
14
14
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
15
15
  <span class="navbar-toggler-icon"></span>
16
16
  </button>
17
- <div class="collapse navbar-collapse">
17
+ <div class="collapse navbar-collapse" id="navbarNav">
18
18
  <ul class="navbar-nav">
19
19
  <li class="nav-item">
20
- <a class="nav-link" href="/">Intro</a>
20
+ <a class="nav-link" href="/halunke">Intro</a>
21
21
  </li>
22
22
  <li class="nav-item">
23
- <a class="nav-link" href="/number">Number</a>
23
+ <a class="nav-link" href="/halunke/number">Number</a>
24
24
  </li>
25
25
  <li class="nav-item">
26
- <a class="nav-link" href="/string">String</a>
26
+ <a class="nav-link" href="/halunke/string">String</a>
27
27
  </li>
28
28
  <li class="nav-item">
29
- <a class="nav-link" href="/array">Array</a>
29
+ <a class="nav-link" href="/halunke/array">Array</a>
30
30
  </li>
31
31
  <li class="nav-item">
32
- <a class="nav-link" href="/dictionary">Dictionary</a>
32
+ <a class="nav-link" href="/halunke/dictionary">Dictionary</a>
33
33
  </li>
34
34
  <li class="nav-item">
35
- <a class="nav-link" href="/true-false">True & False</a>
35
+ <a class="nav-link" href="/halunke/true-false">True & False</a>
36
36
  </li>
37
37
  <li class="nav-item">
38
- <a class="nav-link" href="/function">Function</a>
38
+ <a class="nav-link" href="/halunke/function">Function</a>
39
39
  </li>
40
40
  <li class="nav-item">
41
- <a class="nav-link" href="/class">Class</a>
41
+ <a class="nav-link" href="/halunke/class">Class</a>
42
42
  </li>
43
43
  <li class="nav-item">
44
- <a class="nav-link" href="/true-false">Stdio</a>
44
+ <a class="nav-link" href="/halunke/stdio">Stdio</a>
45
45
  </li>
46
46
  <li class="nav-item">
47
- <a class="nav-link" href="/true-false">Web</a>
47
+ <a class="nav-link" href="/halunke/web">Web</a>
48
48
  </li>
49
49
  </ul>
50
50
  </div>
@@ -57,5 +57,9 @@
57
57
  {{ content }}
58
58
  </main>
59
59
  </div>
60
+
61
+ <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
62
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
63
+ <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
60
64
  </body>
61
65
  </html>
data/docs/array.md ADDED
@@ -0,0 +1,65 @@
1
+ ---
2
+ title: Array
3
+ ---
4
+
5
+ In Halunke arrays are collections of objects. The objects do not
6
+ need to be of the same class. Arrays are sorted. They are
7
+ surrounded by square brackets. The items are separated by
8
+ whitespace.
9
+
10
+ ```
11
+ ["a" 1 "b"]
12
+ [
13
+ "a"
14
+ 5
15
+ ]
16
+ ```
17
+
18
+ It can answer to the following messages:
19
+
20
+ ## `=`
21
+
22
+ Compares to arrays. If they have the same length and each item from
23
+ the first array returns true on the `=` message for the according
24
+ item from the second list, it returns true. Otherwise, it returns
25
+ false. This can also be used to destructure an array.
26
+
27
+ **Example:**
28
+
29
+ ```
30
+ (["a" 1] = ["a" 1]) /* => true */
31
+
32
+ (['a 2] = [1 2]) /* => true */
33
+ /* a is now 2 */
34
+ ```
35
+
36
+ ## `map`
37
+
38
+ Calls the provided function for each element. Returns a new array of the same
39
+ length with the results of the function calls.
40
+
41
+ **Example:**
42
+
43
+ ```
44
+ ([0 1 2] map { |'x| (x + 1) }) /* => [1 2 3] */
45
+ ```
46
+
47
+ ## `to_s`
48
+
49
+ This returns a string to represent the array in output.
50
+
51
+ **Example:**
52
+
53
+ ```
54
+ ([0 1 2] to_s) /* => "0\n1\n2" */
55
+ ```
56
+
57
+ ## `inspect`
58
+
59
+ This returns a string to represent the array for debugging.
60
+
61
+ **Example:**
62
+
63
+ ```
64
+ ([0 1 2] inspect) /* => "[0 1 2]" */
65
+ ```
data/docs/class.md ADDED
@@ -0,0 +1,103 @@
1
+ ---
2
+ title: Class
3
+ ---
4
+
5
+ In Halunke, Classes are objects. They consist of a dictionary that
6
+ maps message names to functions. Objects are a wrapper around a
7
+ dictionary. The dictionary contains the attributes of the object.
8
+ The object knows its class, and when messages are send to the
9
+ object, it will look up the according function in its class and
10
+ call it.
11
+
12
+ Classes are created by sending a message to the Class object. One
13
+ of these messages is `new attributes methods`. Let's create a
14
+ class:
15
+
16
+ ```
17
+ (Class new 'Counter
18
+ attributes ["value"]
19
+ methods @[
20
+ "value" { |'self|
21
+ (self @ "value" else 0)
22
+ }
23
+ ]
24
+ )
25
+ ```
26
+
27
+ To create an instance of the class, we send the `new` message to
28
+ the class with a dictionary that represents the attributes:
29
+
30
+ ```
31
+ ('counter = (Counter new @["value" 0]))
32
+ ```
33
+
34
+ Now we can send the `value` message to our counter, and we will
35
+ receive 0:
36
+
37
+ ```
38
+ (counter value)
39
+ ```
40
+
41
+ In our class definition, we first gave an array of attributes. You
42
+ can imagine it as kind of whitelist for attributes: The attribute
43
+ dictionary you pass to new can only have keys that are on this
44
+ list. Now let's look at the function that is called when you send
45
+ the value message:
46
+
47
+ ```
48
+ { |'self| (self @ "value" else 0) }
49
+ ```
50
+
51
+ Every function that is used as a method receives the object itself
52
+ as its first argument. This can be used to send messages to the
53
+ object itself. Each object can receive the `@ else` message. This
54
+ is used to look up attributes in the dictionary. Our function
55
+ therefore returns the value attribute or 0, if it was not set.
56
+
57
+ Now let's add a method to increase the counter. Remember that objects
58
+ are immutable. So we need to return a new counter with the value
59
+ that is one higher than our current value:
60
+
61
+ ```
62
+ "increase" { |'self|
63
+ (Counter new @["value" ((self value) + 1)])
64
+ }
65
+ ```
66
+
67
+ We can use it like this:
68
+
69
+ ```
70
+ ('counter = (Counter new @["value" 0]))
71
+ ('increased_counter = (counter increase))
72
+ ```
73
+
74
+ The `'increased_counter` will return `1` as its value.
75
+
76
+ Now you might want to have a custom constructor that needs less typing and is
77
+ more expressive. You can do that by introducing a class method that calls the
78
+ `new` method. Class methods receive the class as the first parameter.
79
+
80
+ ```
81
+ (Class new 'Counter
82
+ attributes ["value"]
83
+ methods @[
84
+ "value" { |'self|
85
+ (self @ "value" else 0)
86
+ }
87
+ "increase" { |'self|
88
+ (Counter new @["value" ((self value) + 1)])
89
+ }
90
+ ]
91
+ class_methods @[
92
+ "from" { |'self 'value|
93
+ (self new @["value" value])
94
+ }
95
+ ]
96
+ )
97
+ ```
98
+
99
+ Now we can create a counter like this:
100
+
101
+ ```
102
+ ('counter = (Counter from 5))
103
+ ```
@@ -0,0 +1,48 @@
1
+ ---
2
+ title: Dictionary
3
+ ---
4
+
5
+ In Halunke, dictionaries are collections of objects that map values
6
+ to other values. The first entry is the key for the second entry,
7
+ the third for the fourth etc. (the number of elements is therefore
8
+ always even). Like in a real dictionary, you can then look them up
9
+ Like in a real dictionary, you can then look them up. They are
10
+ written in square brackets, prefixed with an `@`.
11
+
12
+ ```
13
+ @["a" 1 "b" 2]
14
+ ```
15
+
16
+ It can answer to the following message:
17
+
18
+ ## `@ else`
19
+
20
+ Looks up a value in the dictionary. If the key is not in the
21
+ dictionary, the fallback value is used.
22
+
23
+ **Example:**
24
+
25
+ ```
26
+ (@["a" 1 "b" 2] @ "a" else "Not Found") /* => 1 */
27
+ (@["a" 1 "b" 2] @ "c" else "Not Found") /* => "Not Found" */
28
+ ```
29
+
30
+ ## `to_s`
31
+
32
+ This returns a string to represent the dictionary in output.
33
+
34
+ **Example:**
35
+
36
+ ```
37
+ (@["a" 1 "b" 2] to_s) /* => "a 1\nb 2" */
38
+ ```
39
+
40
+ ## `inspect`
41
+
42
+ This returns a string to represent the dictionary for debugging.
43
+
44
+ **Example:**
45
+
46
+ ```
47
+ (@["a" 1 "b" 2] inspect) /* => "@[\"a\" 1 \"b\" 2]" */
48
+ ```
data/docs/function.md ADDED
@@ -0,0 +1,18 @@
1
+ ---
2
+ title: Function
3
+ ---
4
+
5
+ This is how you define a function:
6
+
7
+ ```
8
+ ('fn = { |'a 'b| (a + b) })
9
+ ```
10
+
11
+ This is a function that expects two arguments. Functions in Halunke are
12
+ Objects. If you want to invoke a function, you send them the `call` message
13
+ with an array with the arguments (in our case two):
14
+
15
+ ```
16
+ (fn call [1 2])
17
+ /* => 6 */
18
+ ```
data/docs/index.md CHANGED
@@ -57,12 +57,13 @@ works like this:
57
57
  This will return `"Spelunke!"`. The message we send here is `replace with` and
58
58
  the value is `["Ha" "Spe"]`.
59
59
 
60
- If you want to find out more about the types of objects in Halunke and the
61
- messages you can send to them, explore the navigation bar at the top. If you
62
- want to learn more about conditionals, check out the section about [True &
63
- False](/true-false). If you want to write your own functions, check out
64
- [Function](/function) and if you want to define your own classes, check out
65
- [Class](/class).
60
+ If you want to find out more about the types of objects in Halunke
61
+ and the messages you can send to them, explore the navigation bar
62
+ at the top. If you want to learn more about conditionals, check out
63
+ the section about [True & False](/halunke/true-false). If you want
64
+ to write your own functions, check out
65
+ [Function](/halunke/function) and if you want to define your own
66
+ classes, check out [Class](/halunke/class).
66
67
 
67
68
  If you want to store an object in a variable, you can do it like this:
68
69
 
@@ -75,3 +76,8 @@ Now you can send messages to `a` like `(a + 2)`. Why is there a `'` though? The
75
76
  with a value, and it will assign it. Be aware that you can't reassign. So if
76
77
  you assign something to a once, it will stay like this forever (within that
77
78
  scope). Reassigning will result in an error.
79
+
80
+ The values are also immutable. If you send a message to an object,
81
+ it will not change the object, but it will return an answer to you.
82
+
83
+ Comments are written between `/*` and `*/`. They can be multiline.
data/docs/number.md ADDED
@@ -0,0 +1,106 @@
1
+ ---
2
+ title: Number
3
+ ---
4
+
5
+ In Halunke all numbers are rational. You write them as decimal numbers:
6
+
7
+ ```
8
+ 2
9
+ -3
10
+ 2.12
11
+ ```
12
+
13
+ It can answer to the following messages:
14
+
15
+ ## `+`
16
+
17
+ This adds two numbers.
18
+
19
+ **Example:**
20
+
21
+ ```
22
+ (0.6 + 0.3) /* => 0.9 */
23
+ ```
24
+
25
+ ## `-`
26
+
27
+ This subtracts two numbers.
28
+
29
+ **Example:**
30
+
31
+ ```
32
+ (0.6 - 0.3) /* => 0.3 */
33
+ ```
34
+
35
+ ## `/`
36
+
37
+ This divides two numbers.
38
+
39
+ **Example:**
40
+
41
+ ```
42
+ (0.6 / 0.3) /* => 2 */
43
+ ```
44
+
45
+ ## `*`
46
+
47
+ This multiplies two numbers.
48
+
49
+ **Example:**
50
+
51
+ ```
52
+ (0.6 * 0.3) /* => 0.18 */
53
+ ```
54
+
55
+ ## `<`
56
+
57
+ This compares two numbers. It is true, if the first number is smaller than the
58
+ second number. Otherwise, it is false.
59
+
60
+ **Example:**
61
+
62
+ ```
63
+ (0.6 < 0.3) /* => false */
64
+ ```
65
+
66
+ ## `>`
67
+
68
+ This compares two numbers. It is true, if the first number is greater than the
69
+ second number. Otherwise, it is false.
70
+
71
+ **Example:**
72
+
73
+ ```
74
+ (0.6 > 0.3) /* => true */
75
+ ```
76
+
77
+ ## `=`
78
+
79
+ This compares two numbers. It is true, if the two numbers are equal. Otherwise,
80
+ it is false.
81
+
82
+ **Example:**
83
+
84
+ ```
85
+ (0.6 = 0.3) /* => false */
86
+ ```
87
+
88
+ ## `to_s`
89
+
90
+ This returns a string to represent the number in output.
91
+
92
+ **Example:**
93
+
94
+ ```
95
+ (0.6 to_s) /* => "0.6" */
96
+ ```
97
+
98
+ ## `inspect`
99
+
100
+ This returns a string to represent the number for debugging.
101
+
102
+ **Example:**
103
+
104
+ ```
105
+ (0.6 inspect) /* => "0.6" */
106
+ ```
data/docs/stdio.md ADDED
@@ -0,0 +1,62 @@
1
+ ---
2
+ title: Stdio
3
+ ---
4
+
5
+ The object `stdio` is available from everywhere. *This will change in the
6
+ future. Interacting with STDIO is IO and will be isolated.*
7
+
8
+ ## `puts`
9
+
10
+ Prints the object to stdout. To determine how to represent the object, it will
11
+ send the `to_s` message to the object, expecting a string.
12
+
13
+ **Example:**
14
+
15
+ ```
16
+ (stdio puts "Hello World")
17
+ (stdio puts 5.2)
18
+ (stdio puts @["a" 2 "b" 3])
19
+ (stdio puts ["a" "b"])
20
+ (stdio puts true)
21
+ (stdio puts false)
22
+ ```
23
+
24
+ This will output:
25
+
26
+ ```
27
+ Hello World
28
+ 5.2
29
+ a 2
30
+ b 3
31
+ a
32
+ b
33
+ true
34
+ false
35
+ ```
36
+
37
+ ## `p`
38
+
39
+ Prints the object to stdout for debugging. To determine how to represent the
40
+ object, it will send the `inspect` message to the object, expecting a string.
41
+
42
+ **Example:**
43
+
44
+ ```
45
+ (stdio p "Hello World")
46
+ (stdio p 5.2)
47
+ (stdio p @["a" 2 "b" 3])
48
+ (stdio p ["a" "b"])
49
+ (stdio p true)
50
+ (stdio p false)
51
+ ```
52
+
53
+ This will output:
54
+
55
+ ```
56
+ "Hello World"
57
+ 5.2
58
+ @["a" 2 "b" 3]
59
+ ["a" "b"]
60
+ true
61
+ false
62
+ ```
data/docs/string.md ADDED
@@ -0,0 +1,74 @@
1
+ ---
2
+ title: String
3
+ ---
4
+
5
+ In Halunke strings are used to represent all kinds of text
6
+ including single characters. They are surrounded by double quotes
7
+ (single quotes are not allowed).
8
+
9
+ ```
10
+ "Foo Bar"
11
+ ```
12
+
13
+ It can answer to the following messages:
14
+
15
+ ## `reverse`
16
+
17
+ Return a reversed version of the String.
18
+
19
+ **Example:**
20
+
21
+ ```
22
+ ("hello" reverse) /* => "olleh" */
23
+ ```
24
+
25
+ ## `replace with`
26
+
27
+ Replace all occurrences of the first string with the second string.
28
+
29
+ **Example:**
30
+
31
+ ```
32
+ ("ababab" replace "a" with "c") /* => "cbcbcb" */
33
+ ```
34
+
35
+ ## `=`
36
+
37
+ This compares two strings. It is true, if the two strings are equal. Otherwise,
38
+ it is false.
39
+
40
+ **Example:**
41
+
42
+ ```
43
+ ("aaa" = "aaa") /* => true */
44
+ ```
45
+
46
+ ## `+`
47
+
48
+ Concatenate two strings.
49
+
50
+ **Example:**
51
+
52
+ ```
53
+ ("aaa" + "bbb") /* => "aaabbb" */
54
+ ```
55
+
56
+ ## `to_s`
57
+
58
+ This returns the string itself.
59
+
60
+ **Example:**
61
+
62
+ ```
63
+ ("aaa" to_s) /* => "aaa" */
64
+ ```
65
+
66
+ ## `inspect`
67
+
68
+ This returns a string to represent the string in output. This is done by surrounding it with `"`
69
+
70
+ **Example:**
71
+
72
+ ```
73
+ ("aaa" inspect) /* => "\"aaa\"" */
74
+ ```
@@ -0,0 +1,68 @@
1
+ ---
2
+ title: True & False
3
+ ---
4
+
5
+ In Halunke `true` is an instance of the `True` class, and `false`
6
+ is an instance of the `False` class. They are used to realize
7
+ boolean operations (for example `and`) as well as for branching.
8
+ They answer to the same messages. So you could use it like this:
9
+
10
+ ```
11
+ ((5 > 3) then { "yes!" } else { "no!" })
12
+ /* Returns "yes!" */
13
+ ```
14
+
15
+ ## `and`
16
+
17
+ Returns true if both the receiver as well as the provided value are
18
+ true.
19
+
20
+ **Example:**
21
+
22
+ ```
23
+ ((5 > 3) and (2 < 1)) /* => false */
24
+ ```
25
+
26
+ ## `or`
27
+
28
+ Returns true if either the receiver or the provided value are true.
29
+
30
+ **Example:**
31
+
32
+ ```
33
+ ((5 > 3) or (2 < 1)) /* => true */
34
+ ```
35
+
36
+ ## `then else`
37
+
38
+ If the receiver is true, it will execute the first branch. If it is
39
+ false, it will return the second branch.
40
+
41
+ **Example:**
42
+
43
+ ```
44
+ (true then { "yes" } else { "no" }) /* => "yes" */
45
+ (false then { "yes" } else { "no" }) /* => "no" */
46
+ ```
47
+
48
+ ## `to_s`
49
+
50
+ This returns a string to represent true and false in output.
51
+
52
+ **Example:**
53
+
54
+ ```
55
+ (true to_s) /* => "true" */
56
+ (false to_s) /* => "false" */
57
+ ```
58
+
59
+ ## `inspect`
60
+
61
+ This returns a string to represent true and false for debugging.
62
+
63
+ **Example:**
64
+
65
+ ```
66
+ (true inspect) /* => "true" */
67
+ (false inspect) /* => "false" */
68
+ ```
data/docs/web.md ADDED
@@ -0,0 +1,32 @@
1
+ ---
2
+ title: Web
3
+ ---
4
+
5
+ The object `web` is available from everywhere. *This will change in the future.
6
+ Interacting with STDIO is IO and will be isolated.*
7
+
8
+ You can send the `run on` message to `web`. It expects the first object to be
9
+ your application (more on that later) and the second one the bind address and
10
+ port in the format: `0.0.0.0:3000`.
11
+
12
+ Your app needs to be an object that can receive the `call` message. It will be
13
+ called with the environment dictionary that represents the request. It expects
14
+ that your return an array that represents the response.
15
+
16
+ ## Environment Dictionary
17
+
18
+ The environment dictionary has the following keys:
19
+
20
+ * `request_method`: The request method in upper case (for example: `"GET"`)
21
+ * `path`: The path that was requested (for example: `"/the/path"`)
22
+ * `query`: The query part of the request (for example: `"foo=bar&beep=boop"`)
23
+
24
+ ## Response Array
25
+
26
+ The response array has three elements:
27
+
28
+ 1. The first element is the status code as a String (for example: `"200"`)
29
+ 2. The second element are the headers as a dictionary (for example: `@[
30
+ "Content-Type" "text/html" ]`)
31
+ 3. The third element is an array of strings that represent the body (for
32
+ example: `[ "<h1>Halunke!</h1>" ]`)
@@ -0,0 +1,22 @@
1
+ (Class new 'Counter
2
+ attributes ["value"]
3
+ methods @[
4
+ "value" { |'self|
5
+ (self @ "value" else 0)
6
+ }
7
+ "increase" { |'self|
8
+ (Counter new @["value" ((self value) + 1)])
9
+ }
10
+ ]
11
+ class_methods @[
12
+ "from" { |'self 'value|
13
+ (self new @["value" value])
14
+ }
15
+ ]
16
+ )
17
+
18
+ ('counter = (Counter from 0))
19
+ (stdio puts (counter value))
20
+
21
+ ('increased_counter = (counter increase))
22
+ (stdio puts (increased_counter value))
data/examples/hello.hal CHANGED
@@ -16,4 +16,4 @@
16
16
  )
17
17
 
18
18
  ('greeter = (Greeter for "World"))
19
- (stdout puts (greeter greet))
19
+ (stdio puts (greeter greet))
@@ -0,0 +1,13 @@
1
+ (stdio puts "Hello World")
2
+ (stdio puts 5.2)
3
+ (stdio puts @["a" 2 "b" 3])
4
+ (stdio puts ["a" "b"])
5
+ (stdio puts true)
6
+ (stdio puts false)
7
+
8
+ (stdio p "Hello World")
9
+ (stdio p 5.2)
10
+ (stdio p @["a" 2 "b" 3])
11
+ (stdio p ["a" "b"])
12
+ (stdio p true)
13
+ (stdio p false)
@@ -15,27 +15,29 @@ token BAR
15
15
  token START_COMMENT
16
16
  token END_COMMENT
17
17
 
18
+ options no_result_var
19
+
18
20
  rule
19
21
  Program:
20
- Expressions { result = val[0] }
22
+ Expressions { val[0] }
21
23
  ;
22
24
 
23
25
  Expressions:
24
- /* empty */ { result = Nodes.new([]) }
25
- | Expression Expressions { result = Nodes.new([val[0]].concat(val[1].nodes)) }
26
+ /* empty */ { Nodes.new([]) }
27
+ | Expression Expressions { Nodes.new([val[0]].concat(val[1].nodes)) }
26
28
  ;
27
29
 
28
30
  Expression:
29
- NUMBER { result = NumberNode.new(val[0]) }
30
- | STRING { result = StringNode.new(val[0]) }
31
- | BAREWORD { result = BarewordNode.new(val[0]) }
32
- | UNASSIGNED_BAREWORD { result = UnassignedNode.new(BarewordNode.new(val[0])) }
33
- | START_COMMENT Expressions END_COMMENT { result = Nodes.new([]) }
34
- | OPEN_CURLY Expressions CLOSE_CURLY { result = FunctionNode.new(ArrayNode.new([]), val[1]) }
35
- | OPEN_CURLY BAR Expressions BAR Expressions CLOSE_CURLY { result = FunctionNode.new(val[2].to_array, val[4]) }
36
- | OPEN_PAREN Expression Expressions CLOSE_PAREN { result = MessageSendNode.new(val[1], val[2].to_message) }
37
- | OPEN_BRACKET Expressions CLOSE_BRACKET { result = val[1].to_array }
38
- | OPEN_DICT_BRACKET Expressions CLOSE_BRACKET { result = val[1].to_dictionary }
31
+ NUMBER { NumberNode.new(val[0]) }
32
+ | STRING { StringNode.new(val[0]) }
33
+ | BAREWORD { BarewordNode.new(val[0]) }
34
+ | UNASSIGNED_BAREWORD { UnassignedNode.new(BarewordNode.new(val[0])) }
35
+ | START_COMMENT Expressions END_COMMENT { Nodes.new([]) }
36
+ | OPEN_CURLY Expressions CLOSE_CURLY { FunctionNode.new(ArrayNode.new([]), val[1]) }
37
+ | OPEN_CURLY BAR Expressions BAR Expressions CLOSE_CURLY { FunctionNode.new(val[2].to_array, val[4]) }
38
+ | OPEN_PAREN Expression Expressions CLOSE_PAREN { MessageSendNode.new(val[1], val[2].to_message) }
39
+ | OPEN_BRACKET Expressions CLOSE_BRACKET { val[1].to_array }
40
+ | OPEN_DICT_BRACKET Expressions CLOSE_BRACKET { val[1].to_dictionary }
39
41
  ;
40
42
  end
41
43
 
@@ -17,7 +17,7 @@ module Halunke
17
17
  @root_context["Array"] = Halunke::Runtime::HArray
18
18
  @root_context["Dictionary"] = Halunke::Runtime::HDictionary
19
19
  @root_context["UnassignedBareword"] = Halunke::Runtime::HUnassignedBareword
20
- @root_context["stdout"] = Halunke::Runtime::HStdout.create_instance
20
+ @root_context["stdio"] = Halunke::Runtime::HStdio.create_instance
21
21
  @root_context["web"] = Halunke::Runtime::HWeb.create_instance
22
22
 
23
23
  preludes.each do |prelude|
data/lib/halunke/lexer.rb CHANGED
@@ -99,10 +99,10 @@ self._lexer_trans_actions = [
99
99
  13, 0, 0, 0, 0, 0, 19, 21,
100
100
  0, 15, 29, 17, 31, 5, 9, 0,
101
101
  0, 33, 7, 0, 47, 47, 47, 45,
102
- 27, 39, 5, 37, 0, 5, 35, 0,
103
- 35, 25, 39, 23, 37, 0, 0, 0,
104
- 37, 43, 41, 39, 45, 39, 37, 35,
105
- 35, 39, 37, 37, 0
102
+ 27, 37, 5, 37, 0, 5, 35, 0,
103
+ 35, 25, 37, 23, 37, 0, 0, 0,
104
+ 37, 43, 41, 39, 45, 37, 37, 35,
105
+ 35, 37, 37, 37, 0
106
106
  ]
107
107
 
108
108
  class << self
@@ -128,8 +128,8 @@ class << self
128
128
  private :_lexer_eof_trans, :_lexer_eof_trans=
129
129
  end
130
130
  self._lexer_eof_trans = [
131
- 50, 51, 0, 58, 53, 58, 60, 57,
132
- 57, 58, 60, 60
131
+ 50, 51, 0, 52, 53, 60, 60, 57,
132
+ 57, 60, 60, 60
133
133
  ]
134
134
 
135
135
  class << self
data/lib/halunke/lexer.rl CHANGED
@@ -5,7 +5,7 @@
5
5
  number = ('+'|'-')?[0-9]+('.'[0-9]+)?;
6
6
  string = '"' [^"]* '"';
7
7
  unassigned_bareword = "'" [a-zA-Z_]+;
8
- bareword = [a-zA-Z_]+ | '+' | '-' | '<' | '>' | '=' | '@';
8
+ bareword = [a-zA-Z_]+ | '+' | '-' | '*' | '/' | '<' | '>' | '=' | '@';
9
9
  open_paren = '(';
10
10
  close_paren = ')';
11
11
  open_curly = '{';
@@ -13,7 +13,7 @@ require "halunke/nodes"
13
13
  module Halunke
14
14
  class Parser < Racc::Parser
15
15
 
16
- module_eval(<<'...end grammar.y/module_eval...', 'grammar.y', 48)
16
+ module_eval(<<'...end grammar.y/module_eval...', 'grammar.y', 50)
17
17
 
18
18
  def parse(code)
19
19
  @tokens = Lexer.new.tokenize(code)
@@ -124,7 +124,7 @@ racc_token_table = {
124
124
 
125
125
  racc_nt_base = 16
126
126
 
127
- racc_use_result_var = true
127
+ racc_use_result_var = false
128
128
 
129
129
  Racc_arg = [
130
130
  racc_action_table,
@@ -170,98 +170,85 @@ Racc_debug_parser = false
170
170
 
171
171
  # reduce 0 omitted
172
172
 
173
- module_eval(<<'.,.,', 'grammar.y', 19)
174
- def _reduce_1(val, _values, result)
175
- result = val[0]
176
- result
173
+ module_eval(<<'.,.,', 'grammar.y', 21)
174
+ def _reduce_1(val, _values)
175
+ val[0]
177
176
  end
178
177
  .,.,
179
178
 
180
- module_eval(<<'.,.,', 'grammar.y', 23)
181
- def _reduce_2(val, _values, result)
182
- result = Nodes.new([])
183
- result
179
+ module_eval(<<'.,.,', 'grammar.y', 25)
180
+ def _reduce_2(val, _values)
181
+ Nodes.new([])
184
182
  end
185
183
  .,.,
186
184
 
187
- module_eval(<<'.,.,', 'grammar.y', 24)
188
- def _reduce_3(val, _values, result)
189
- result = Nodes.new([val[0]].concat(val[1].nodes))
190
- result
191
- end
192
- .,.,
193
-
194
- module_eval(<<'.,.,', 'grammar.y', 28)
195
- def _reduce_4(val, _values, result)
196
- result = NumberNode.new(val[0])
197
- result
198
- end
199
- .,.,
200
-
201
- module_eval(<<'.,.,', 'grammar.y', 29)
202
- def _reduce_5(val, _values, result)
203
- result = StringNode.new(val[0])
204
- result
185
+ module_eval(<<'.,.,', 'grammar.y', 26)
186
+ def _reduce_3(val, _values)
187
+ Nodes.new([val[0]].concat(val[1].nodes))
205
188
  end
206
189
  .,.,
207
190
 
208
191
  module_eval(<<'.,.,', 'grammar.y', 30)
209
- def _reduce_6(val, _values, result)
210
- result = BarewordNode.new(val[0])
211
- result
192
+ def _reduce_4(val, _values)
193
+ NumberNode.new(val[0])
212
194
  end
213
195
  .,.,
214
196
 
215
197
  module_eval(<<'.,.,', 'grammar.y', 31)
216
- def _reduce_7(val, _values, result)
217
- result = UnassignedNode.new(BarewordNode.new(val[0]))
218
- result
198
+ def _reduce_5(val, _values)
199
+ StringNode.new(val[0])
219
200
  end
220
201
  .,.,
221
202
 
222
203
  module_eval(<<'.,.,', 'grammar.y', 32)
223
- def _reduce_8(val, _values, result)
224
- result = Nodes.new([])
225
- result
204
+ def _reduce_6(val, _values)
205
+ BarewordNode.new(val[0])
226
206
  end
227
207
  .,.,
228
208
 
229
209
  module_eval(<<'.,.,', 'grammar.y', 33)
230
- def _reduce_9(val, _values, result)
231
- result = FunctionNode.new(ArrayNode.new([]), val[1])
232
- result
210
+ def _reduce_7(val, _values)
211
+ UnassignedNode.new(BarewordNode.new(val[0]))
233
212
  end
234
213
  .,.,
235
214
 
236
215
  module_eval(<<'.,.,', 'grammar.y', 34)
237
- def _reduce_10(val, _values, result)
238
- result = FunctionNode.new(val[2].to_array, val[4])
239
- result
216
+ def _reduce_8(val, _values)
217
+ Nodes.new([])
240
218
  end
241
219
  .,.,
242
220
 
243
221
  module_eval(<<'.,.,', 'grammar.y', 35)
244
- def _reduce_11(val, _values, result)
245
- result = MessageSendNode.new(val[1], val[2].to_message)
246
- result
222
+ def _reduce_9(val, _values)
223
+ FunctionNode.new(ArrayNode.new([]), val[1])
247
224
  end
248
225
  .,.,
249
226
 
250
227
  module_eval(<<'.,.,', 'grammar.y', 36)
251
- def _reduce_12(val, _values, result)
252
- result = val[1].to_array
253
- result
228
+ def _reduce_10(val, _values)
229
+ FunctionNode.new(val[2].to_array, val[4])
254
230
  end
255
231
  .,.,
256
232
 
257
233
  module_eval(<<'.,.,', 'grammar.y', 37)
258
- def _reduce_13(val, _values, result)
259
- result = val[1].to_dictionary
260
- result
234
+ def _reduce_11(val, _values)
235
+ MessageSendNode.new(val[1], val[2].to_message)
236
+ end
237
+ .,.,
238
+
239
+ module_eval(<<'.,.,', 'grammar.y', 38)
240
+ def _reduce_12(val, _values)
241
+ val[1].to_array
242
+ end
243
+ .,.,
244
+
245
+ module_eval(<<'.,.,', 'grammar.y', 39)
246
+ def _reduce_13(val, _values)
247
+ val[1].to_dictionary
261
248
  end
262
249
  .,.,
263
250
 
264
- def _reduce_none(val, _values, result)
251
+ def _reduce_none(val, _values)
265
252
  val[0]
266
253
  end
267
254
 
@@ -7,5 +7,5 @@ require "halunke/runtime/hstring"
7
7
  require "halunke/runtime/harray"
8
8
  require "halunke/runtime/hdictionary"
9
9
  require "halunke/runtime/hunassigned_bareword"
10
- require "halunke/runtime/hstdout"
10
+ require "halunke/runtime/hstdio"
11
11
  require "halunke/runtime/hweb"
@@ -9,6 +9,9 @@
9
9
  "then else" { |'self 'true_branch 'false_branch|
10
10
  (false_branch call [])
11
11
  }
12
+ "to_s" { |'self 'other|
13
+ "false"
14
+ }
12
15
  "inspect" { |'self 'other|
13
16
  "false"
14
17
  }
@@ -4,10 +4,6 @@ module Halunke
4
4
  "Array",
5
5
  [],
6
6
  {
7
- "inspect" => HFunction.new([:self], lambda { |context|
8
- inspected_members = context["self"].ruby_value.map { |member| member.inspect(context) }
9
- HString.create_instance("[#{inspected_members.join(' ')}]")
10
- }),
11
7
  "=" => HFunction.new([:self, :other], lambda { |context|
12
8
  return context["false"] if context["self"].ruby_value.length != context["other"].ruby_value.length
13
9
 
@@ -21,6 +17,16 @@ module Halunke
21
17
  return HArray.create_instance(context["self"].ruby_value.map do |x|
22
18
  context["fn"].receive_message(context, "call", [HArray.create_instance([x])])
23
19
  end)
20
+ }),
21
+ "to_s" => HFunction.new([:self], lambda { |context|
22
+ inspected_members = context["self"].ruby_value.map do |member|
23
+ member.receive_message(context, "to_s", []).ruby_value
24
+ end
25
+ HString.create_instance("#{inspected_members.join("\n")}")
26
+ }),
27
+ "inspect" => HFunction.new([:self], lambda { |context|
28
+ inspected_members = context["self"].ruby_value.map { |member| member.inspect(context) }
29
+ HString.create_instance("[#{inspected_members.join(' ')}]")
24
30
  })
25
31
  },
26
32
  {},
@@ -4,6 +4,21 @@ module Halunke
4
4
  "Dictionary",
5
5
  [],
6
6
  {
7
+ "@ else" => HFunction.new([:self, :search, :fallback], lambda { |context|
8
+ result = context["self"].ruby_value.find do |key, _value|
9
+ key.receive_message(context, "=", [context["search"]]).inspect(context) == "true"
10
+ end
11
+ result ? result[1] : context["fallback"]
12
+ }),
13
+ "to_s" => HFunction.new([:self], lambda { |context|
14
+ x = []
15
+ context["self"].ruby_value.each_pair do |key, value|
16
+ key_s = key.receive_message(context, "to_s", [])
17
+ value_s = value.receive_message(context, "to_s", [])
18
+ x.push("#{key_s.ruby_value} #{value_s.ruby_value}")
19
+ end
20
+ HString.create_instance(x.join("\n"))
21
+ }),
7
22
  "inspect" => HFunction.new([:self], lambda { |context|
8
23
  x = []
9
24
  context["self"].ruby_value.each_pair do |key, value|
@@ -11,12 +26,6 @@ module Halunke
11
26
  x.push(value.inspect(context))
12
27
  end
13
28
  HString.create_instance("@[#{x.join(' ')}]")
14
- }),
15
- "@ else" => HFunction.new([:self, :search, :fallback], lambda { |context|
16
- result = context["self"].ruby_value.find do |key, _value|
17
- key.receive_message(context, "=", [context["search"]]).inspect(context) == "true"
18
- end
19
- result ? result[1] : context["fallback"]
20
29
  })
21
30
  },
22
31
  {},
@@ -7,6 +7,15 @@ module Halunke
7
7
  "+" => HFunction.new([:self, :other], lambda { |context|
8
8
  HNumber.create_instance(context["self"].ruby_value + context["other"].ruby_value)
9
9
  }),
10
+ "-" => HFunction.new([:self, :other], lambda { |context|
11
+ HNumber.create_instance(context["self"].ruby_value - context["other"].ruby_value)
12
+ }),
13
+ "/" => HFunction.new([:self, :other], lambda { |context|
14
+ HNumber.create_instance(context["self"].ruby_value / context["other"].ruby_value)
15
+ }),
16
+ "*" => HFunction.new([:self, :other], lambda { |context|
17
+ HNumber.create_instance(context["self"].ruby_value * context["other"].ruby_value)
18
+ }),
10
19
  "<" => HFunction.new([:self, :other], lambda { |context|
11
20
  if context["self"].ruby_value < context["other"].ruby_value
12
21
  context["true"]
@@ -28,10 +37,13 @@ module Halunke
28
37
  context["false"]
29
38
  end
30
39
  }),
31
- "inspect" => HFunction.new([:self], lambda { |context|
40
+ "to_s" => HFunction.new([:self], lambda { |context|
32
41
  float_value = context["self"].ruby_value.to_f
33
42
  float_value = float_value.to_i if float_value.to_i == float_value
34
43
  HString.create_instance(float_value.to_s)
44
+ }),
45
+ "inspect" => HFunction.new([:self], lambda { |context|
46
+ context["self"].receive_message(context, "to_s", [])
35
47
  })
36
48
  },
37
49
  {},
@@ -0,0 +1,22 @@
1
+ module Halunke
2
+ module Runtime
3
+ HStdio = HClass.new(
4
+ "Stdio",
5
+ [],
6
+ {
7
+ "puts" => HFunction.new([:self, :obj], lambda { |context|
8
+ str = context["obj"].receive_message(context, "to_s", [])
9
+ puts str.ruby_value
10
+ str
11
+ }),
12
+ "p" => HFunction.new([:self, :obj], lambda { |context|
13
+ str = context["obj"].receive_message(context, "inspect", [])
14
+ puts str.ruby_value
15
+ context["obj"]
16
+ })
17
+ },
18
+ {},
19
+ true
20
+ )
21
+ end
22
+ end
@@ -24,6 +24,9 @@ module Halunke
24
24
  "+" => HFunction.new([:self, :other], lambda { |context|
25
25
  HString.create_instance(context["self"].ruby_value + context["other"].ruby_value)
26
26
  }),
27
+ "to_s" => HFunction.new([:self], lambda { |context|
28
+ context["self"]
29
+ }),
27
30
  "inspect" => HFunction.new([:self], lambda { |context|
28
31
  HString.create_instance(context["self"].ruby_value.inspect)
29
32
  })
@@ -9,6 +9,9 @@
9
9
  "then else" { |'self 'true_branch 'false_branch|
10
10
  (true_branch call [])
11
11
  }
12
+ "to_s" { |'self 'other|
13
+ "true"
14
+ }
12
15
  "inspect" { |'self 'other|
13
16
  "true"
14
17
  }
@@ -1,3 +1,3 @@
1
1
  module Halunke
2
- VERSION = "0.3.1"
2
+ VERSION = "0.4.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: halunke
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lucas Dohmen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-02-10 00:00:00.000000000 Z
11
+ date: 2018-02-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -104,8 +104,19 @@ files:
104
104
  - docs/Gemfile.lock
105
105
  - docs/_config.yml
106
106
  - docs/_layouts/default.html
107
+ - docs/array.md
108
+ - docs/class.md
109
+ - docs/dictionary.md
110
+ - docs/function.md
107
111
  - docs/index.md
112
+ - docs/number.md
113
+ - docs/stdio.md
114
+ - docs/string.md
115
+ - docs/true-false.md
116
+ - docs/web.md
117
+ - examples/counter.hal
108
118
  - examples/hello.hal
119
+ - examples/stdio.hal
109
120
  - examples/web.hal
110
121
  - exe/halunke
111
122
  - halunke.gemspec
@@ -125,7 +136,7 @@ files:
125
136
  - lib/halunke/runtime/hnative_object.rb
126
137
  - lib/halunke/runtime/hnumber.rb
127
138
  - lib/halunke/runtime/hobject.rb
128
- - lib/halunke/runtime/hstdout.rb
139
+ - lib/halunke/runtime/hstdio.rb
129
140
  - lib/halunke/runtime/hstring.rb
130
141
  - lib/halunke/runtime/hunassigned_bareword.rb
131
142
  - lib/halunke/runtime/hweb.rb
@@ -1,16 +0,0 @@
1
- module Halunke
2
- module Runtime
3
- HStdout = HClass.new(
4
- "Stdout",
5
- [],
6
- {
7
- "puts" => HFunction.new([:self, :str], lambda { |context|
8
- puts context["str"].ruby_value
9
- context["str"]
10
- })
11
- },
12
- {},
13
- true
14
- )
15
- end
16
- end