bakkdoor-blocktalk 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +14 -14
- data/examples/conditionals.bt +37 -0
- data/examples/literals.bt +8 -0
- data/examples/webserver.bt +145 -0
- data/grammar/blocktalk.rb +25 -11
- data/grammar/blocktalk.tt +2 -2
- data/lib/blocktalk.bt +2 -0
- data/lib/blocktalk/hash.bt +13 -0
- data/lib/kernel/codeblock.rb +16 -2
- data/parser/nodes/string.rb +1 -1
- metadata +5 -2
- data/version.rb +0 -3
data/README.markdown
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# ***Blocktalk*** #
|
2
|
-
### **v0.1.
|
2
|
+
### **v0.1.5** ###
|
3
3
|
|
4
4
|
## **Blocktalk** is a dynamic, object-oriented programming language somewhat in the tradition of Smalltalk and Ruby. ##
|
5
5
|
|
@@ -15,8 +15,8 @@ For example, defining classes and modules in Blocktalk is also done via methodca
|
|
15
15
|
respectively:
|
16
16
|
|
17
17
|
Class >> :Foo do
|
18
|
-
|
19
|
-
|
18
|
+
def bar = do |baz|
|
19
|
+
Console puts: "In Foo#bar with baz = #{baz}"
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
@@ -41,9 +41,9 @@ can take two explicit codeblocks for a if and then part, or just a block for the
|
|
41
41
|
or implicitly as a ruby-like method call with a passed in block):
|
42
42
|
|
43
43
|
(a < b) if_true: {
|
44
|
-
|
44
|
+
Console print: "a smaller than b!"
|
45
45
|
} if_false: {
|
46
|
-
|
46
|
+
Console print: "a greater than b!"
|
47
47
|
}
|
48
48
|
|
49
49
|
Since Blocktalk supports a very easy literal syntax for codeblocks, many special keywords aren't needed (as in Smalltalk).
|
@@ -53,8 +53,8 @@ Another example would be a while loop:
|
|
53
53
|
|
54
54
|
i = Console gets: "Please enter a number!" to_i
|
55
55
|
{i < 10} while_true {
|
56
|
-
|
57
|
-
|
56
|
+
Console print: "a smaller than b!"
|
57
|
+
i = Console gets: "Enter again!" to_i
|
58
58
|
}
|
59
59
|
|
60
60
|
In this case, while_true takes a ruby-like implicit block, noticeable by the absence of the colon after the methodname,
|
@@ -68,15 +68,15 @@ Exception handling in Blocktalk is done similar to most programming languages, i
|
|
68
68
|
|
69
69
|
i = Console gets: "Please enter a number!"
|
70
70
|
try {
|
71
|
-
|
71
|
+
Console print: "10 / i = #{(10 / (i to_i))}"
|
72
72
|
|
73
|
-
|
74
|
-
|
75
|
-
|
73
|
+
catch: ZeroDivisionError do |ex|
|
74
|
+
Console print: "got a exception: #{ex message}"
|
75
|
+
end
|
76
76
|
|
77
|
-
|
78
|
-
|
79
|
-
|
77
|
+
ensure {
|
78
|
+
Console print: "this will get done, no matter what value i has!"
|
79
|
+
}
|
80
80
|
}
|
81
81
|
|
82
82
|
This example will obviously fail if the we enter a zero. As in Ruby, the ensure-block gets run independent of an error
|
@@ -0,0 +1,37 @@
|
|
1
|
+
x = 10
|
2
|
+
y = 0
|
3
|
+
|
4
|
+
{
|
5
|
+
y = Console gets: "please enter a positive number:" to_i
|
6
|
+
} until {y > 0}
|
7
|
+
|
8
|
+
|
9
|
+
x <= y if_true: {
|
10
|
+
Console puts: "x (#{x}) <= y (#{y})!"
|
11
|
+
} if_false: {
|
12
|
+
Console puts: "x (#{x}) > y (#{y})!"
|
13
|
+
}
|
14
|
+
|
15
|
+
Console puts
|
16
|
+
|
17
|
+
# blocktalk also supports the if / unless at the end, as in ruby
|
18
|
+
{ Console puts: "x (#{x}) <= y (#{y})!" } if: (x <= y)
|
19
|
+
{ Console puts: "x (#{x}) > y (#{y})!"} if: (x > y)
|
20
|
+
|
21
|
+
Console puts
|
22
|
+
|
23
|
+
# this would also work:
|
24
|
+
{ Console puts: "x (#{x}) > y (#{y})!" } unless: (x <= y)
|
25
|
+
|
26
|
+
Console puts
|
27
|
+
|
28
|
+
x = 0
|
29
|
+
{x < 10} while_true {
|
30
|
+
Console puts: x
|
31
|
+
x = x + 1
|
32
|
+
}
|
33
|
+
|
34
|
+
{x < 0} while_false {
|
35
|
+
Console puts: x
|
36
|
+
x = x - 1
|
37
|
+
}
|
@@ -0,0 +1,145 @@
|
|
1
|
+
# small working webserver example
|
2
|
+
# taken, translated & changed a bit from:
|
3
|
+
# http://blogs.msdn.com/abhinaba/archive/2005/10/14/ruby-webserver-in-70-lines-of-code.aspx
|
4
|
+
|
5
|
+
System require: "socket"
|
6
|
+
require: "lib/blocktalk"
|
7
|
+
|
8
|
+
Class >> :Logger do
|
9
|
+
def initialize = do |logfile|
|
10
|
+
@log_file = logfile
|
11
|
+
end
|
12
|
+
|
13
|
+
def log = do |message|
|
14
|
+
Console puts: "\n\n";
|
15
|
+
puts: ("=" * 50);
|
16
|
+
puts: "\n #{message}"
|
17
|
+
|
18
|
+
(@log_file == nil) if_false {
|
19
|
+
@log_file puts: "\n\n";
|
20
|
+
puts: ("=" * 50);
|
21
|
+
puts: "\n #{message}"
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
Class >> :Webserver do
|
27
|
+
def initialize = do |session request: req root_path: root_path|
|
28
|
+
@session = session
|
29
|
+
@request = req
|
30
|
+
@root_path = root_path
|
31
|
+
end
|
32
|
+
|
33
|
+
def full_path = do
|
34
|
+
filename = nil
|
35
|
+
(@request =~ /GET (.*) HTTP.*/) if {
|
36
|
+
filename = $1
|
37
|
+
}
|
38
|
+
|
39
|
+
(filename == nil) unless {
|
40
|
+
filename = @root_path + filename
|
41
|
+
filename = File expand_path: filename with: @default_path
|
42
|
+
}
|
43
|
+
|
44
|
+
(File directory?: filename) if {
|
45
|
+
filename << '/index.html'
|
46
|
+
}
|
47
|
+
|
48
|
+
return filename
|
49
|
+
end
|
50
|
+
|
51
|
+
def serve = do
|
52
|
+
Console puts: "trying to serve content"
|
53
|
+
@full_path = self full_path
|
54
|
+
src = nil
|
55
|
+
try{
|
56
|
+
((File exist?: @full_path) and: (File file?: @full_path)) if_true: {
|
57
|
+
Console puts: "File exists: #{@full_path}"
|
58
|
+
# path should start with base path
|
59
|
+
((@full_path index: @root_path) == 0) if_true: {
|
60
|
+
content_type = self content_type: @full_path
|
61
|
+
@session print: "HTTP/1.1 200/OK\r\nServer: Blocktalk-HTTP\r\nContent-type: #{content_type}\r\n\r\n"
|
62
|
+
src = File open: @full_path mode: "rb"
|
63
|
+
|
64
|
+
{src eof?} while_false {
|
65
|
+
buffer = src read: 256
|
66
|
+
@session write: buffer
|
67
|
+
}
|
68
|
+
src close
|
69
|
+
src = nil
|
70
|
+
} if_false: {
|
71
|
+
# should have sent a 403 Forbidden access but then the attacker knows that such a file exists
|
72
|
+
@session print: "HTTP/1.1 404/Object Not Found\r\nServer: Blocktalk-HTTP\r\n\r\n"
|
73
|
+
}
|
74
|
+
} if_false: {
|
75
|
+
Console puts: "Error: File doesnt exist: #{@full_path}"
|
76
|
+
@session print: "HTTP/1.1 404/Object Not Found\r\nServer: Blocktalk-HTTP\r\n\r\n"
|
77
|
+
}
|
78
|
+
|
79
|
+
catch: StandardError do |ex|
|
80
|
+
Console puts: "OOPS: #{ex inspect}"
|
81
|
+
end
|
82
|
+
|
83
|
+
ensure{
|
84
|
+
(src nil?) if_false {
|
85
|
+
src close
|
86
|
+
}
|
87
|
+
@session close
|
88
|
+
}
|
89
|
+
}
|
90
|
+
end
|
91
|
+
|
92
|
+
def content_types = do
|
93
|
+
{
|
94
|
+
".html" => "text/html",
|
95
|
+
".htm" => "text/html",
|
96
|
+
".txt" => "text/plain",
|
97
|
+
".css" => "text/css",
|
98
|
+
".jpeg" => "image/jpeg",
|
99
|
+
".jpg" => "image/jpeg",
|
100
|
+
".gif" => "image/gif",
|
101
|
+
".bmp" => "image/bmp",
|
102
|
+
".rb" => "text/plain",
|
103
|
+
".xml" => "text/xml",
|
104
|
+
".xsl" => "text/xml"
|
105
|
+
}
|
106
|
+
end
|
107
|
+
|
108
|
+
def content_type = do |path|
|
109
|
+
ext = File extname: path
|
110
|
+
type = self content_types at: ext
|
111
|
+
|
112
|
+
(type nil?) if_true {
|
113
|
+
type = "text/html"
|
114
|
+
}
|
115
|
+
|
116
|
+
return type
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
root_path = "/home/bakkdoor/projekte/blocktalk/webserver/httpd/"
|
121
|
+
logfile_name = root_path + "/log.txt"
|
122
|
+
|
123
|
+
File open: logfile_name mode: "w+" do |logfile|
|
124
|
+
port = 3000
|
125
|
+
{port = ARGV at: 0} if: (ARGV at: 0)
|
126
|
+
|
127
|
+
server = TCPServer new: 'localhost' port: port
|
128
|
+
logger = Logger new: logfile
|
129
|
+
|
130
|
+
Kernel loop do
|
131
|
+
session = server accept
|
132
|
+
request = session gets
|
133
|
+
logStr = "#{session peeraddr at: 2} (#{session peeraddr at: 3})\n"
|
134
|
+
logStr = logStr + (Time now localtime strftime: "%Y/%m/%d %H:%M:%S")
|
135
|
+
logStr = logStr + "\n#{request}"
|
136
|
+
logger log: logStr
|
137
|
+
|
138
|
+
Console puts: "OK"
|
139
|
+
|
140
|
+
Thread start: session with: request do |session request|
|
141
|
+
ws = Webserver new: session request: request root_path: root_path
|
142
|
+
ws serve
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
data/grammar/blocktalk.rb
CHANGED
@@ -3015,6 +3015,7 @@ module Blocktalk
|
|
3015
3015
|
def pair
|
3016
3016
|
elements[2]
|
3017
3017
|
end
|
3018
|
+
|
3018
3019
|
end
|
3019
3020
|
|
3020
3021
|
module HashLiteral1
|
@@ -3037,7 +3038,7 @@ module Blocktalk
|
|
3037
3038
|
first_pair = first_entry.value
|
3038
3039
|
hash_str += "#{first_pair[0]} => #{first_pair[1]},"
|
3039
3040
|
rest_pairs.elements.each do |ws_and_pair|
|
3040
|
-
pair = ws_and_pair.pair
|
3041
|
+
pair = ws_and_pair.pair.value
|
3041
3042
|
hash_str += "#{pair[0]} => #{pair[1]},"
|
3042
3043
|
end
|
3043
3044
|
hash_str += "}"
|
@@ -3123,6 +3124,19 @@ module Blocktalk
|
|
3123
3124
|
if r11
|
3124
3125
|
r13 = _nt_hash_entry
|
3125
3126
|
s9 << r13
|
3127
|
+
if r13
|
3128
|
+
s14, i14 = [], index
|
3129
|
+
loop do
|
3130
|
+
r15 = _nt_ws
|
3131
|
+
if r15
|
3132
|
+
s14 << r15
|
3133
|
+
else
|
3134
|
+
break
|
3135
|
+
end
|
3136
|
+
end
|
3137
|
+
r14 = instantiate_node(SyntaxNode,input, i14...index, s14)
|
3138
|
+
s9 << r14
|
3139
|
+
end
|
3126
3140
|
end
|
3127
3141
|
end
|
3128
3142
|
if s9.last
|
@@ -3141,26 +3155,26 @@ module Blocktalk
|
|
3141
3155
|
r8 = instantiate_node(SyntaxNode,input, i8...index, s8)
|
3142
3156
|
s0 << r8
|
3143
3157
|
if r8
|
3144
|
-
|
3158
|
+
s16, i16 = [], index
|
3145
3159
|
loop do
|
3146
|
-
|
3147
|
-
if
|
3148
|
-
|
3160
|
+
r17 = _nt_ws
|
3161
|
+
if r17
|
3162
|
+
s16 << r17
|
3149
3163
|
else
|
3150
3164
|
break
|
3151
3165
|
end
|
3152
3166
|
end
|
3153
|
-
|
3154
|
-
s0 <<
|
3155
|
-
if
|
3167
|
+
r16 = instantiate_node(SyntaxNode,input, i16...index, s16)
|
3168
|
+
s0 << r16
|
3169
|
+
if r16
|
3156
3170
|
if input.index('}', index) == index
|
3157
|
-
|
3171
|
+
r18 = instantiate_node(SyntaxNode,input, index...(index + 1))
|
3158
3172
|
@index += 1
|
3159
3173
|
else
|
3160
3174
|
terminal_parse_failure('}')
|
3161
|
-
|
3175
|
+
r18 = nil
|
3162
3176
|
end
|
3163
|
-
s0 <<
|
3177
|
+
s0 << r18
|
3164
3178
|
end
|
3165
3179
|
end
|
3166
3180
|
end
|
data/grammar/blocktalk.tt
CHANGED
@@ -270,7 +270,7 @@ grammar Blocktalk do
|
|
270
270
|
|
271
271
|
rule hash_literal do
|
272
272
|
# '{' ws* '}' /
|
273
|
-
'{' ws* first_entry:(hash_entry)? ws* rest_pairs:(',' ws* pair:(hash_entry))* ws* '}' {
|
273
|
+
'{' ws* first_entry:(hash_entry)? ws* rest_pairs:(',' ws* pair:(hash_entry) ws*)* ws* '}' {
|
274
274
|
def value
|
275
275
|
if self.text_value =~ /\{\s*\}/
|
276
276
|
return "{}"
|
@@ -279,7 +279,7 @@ grammar Blocktalk do
|
|
279
279
|
first_pair = first_entry.value
|
280
280
|
hash_str += "#{first_pair[0]} => #{first_pair[1]},"
|
281
281
|
rest_pairs.elements.each do |ws_and_pair|
|
282
|
-
pair = ws_and_pair.pair
|
282
|
+
pair = ws_and_pair.pair.value
|
283
283
|
hash_str += "#{pair[0]} => #{pair[1]},"
|
284
284
|
end
|
285
285
|
hash_str += "}"
|
data/lib/blocktalk.bt
CHANGED
data/lib/kernel/codeblock.rb
CHANGED
@@ -50,8 +50,22 @@ module Kernel
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
-
def until(&
|
54
|
-
|
53
|
+
def until(&condition_block)
|
54
|
+
while not condition_block.call
|
55
|
+
self.call
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def if(condition)
|
60
|
+
if condition
|
61
|
+
self.call
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def unless(condition)
|
66
|
+
unless condition
|
67
|
+
self.call
|
68
|
+
end
|
55
69
|
end
|
56
70
|
end
|
57
71
|
end
|
data/parser/nodes/string.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Blocktalk
|
2
2
|
class StringLiteralNode < Treetop::Runtime::SyntaxNode
|
3
3
|
def value
|
4
|
-
"\"" + self.string_val.elements.collect{|e| e.value}.join("") + "\""
|
4
|
+
"\"" + self.string_val.elements.collect{|e| e.value}.join("").gsub('"', '\"').gsub("'", "\'") + "\""
|
5
5
|
end
|
6
6
|
end
|
7
7
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bakkdoor-blocktalk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Christopher Bertels
|
@@ -36,7 +36,6 @@ files:
|
|
36
36
|
- TODO
|
37
37
|
- LICENSE
|
38
38
|
- evaluator.rb
|
39
|
-
- version.rb
|
40
39
|
- grammar/blocktalk.tt
|
41
40
|
- grammar/blocktalk.rb
|
42
41
|
- lib/core.rb
|
@@ -51,21 +50,25 @@ files:
|
|
51
50
|
- lib/kernel/system.rb
|
52
51
|
- lib/kernel/object.rb
|
53
52
|
- lib/blocktalk
|
53
|
+
- lib/blocktalk/hash.bt
|
54
54
|
- lib/blocktalk/string.bt
|
55
55
|
- lib/blocktalk/array.bt
|
56
56
|
- lib/blocktalk.bt
|
57
57
|
- bin/blocktalk
|
58
|
+
- examples/webserver.bt
|
58
59
|
- examples/test3.bt
|
59
60
|
- examples/fac.bt
|
60
61
|
- examples/chained_method_call.bt
|
61
62
|
- examples/exceptions.bt
|
62
63
|
- examples/string_interpol.bt
|
63
64
|
- examples/test2.bt
|
65
|
+
- examples/literals.bt
|
64
66
|
- examples/ruby_methods.bt
|
65
67
|
- examples/multiple_methodcall.bt
|
66
68
|
- examples/linecounter.bt
|
67
69
|
- examples/require.bt
|
68
70
|
- examples/portscan.bt
|
71
|
+
- examples/conditionals.bt
|
69
72
|
- examples/classes_modules.bt
|
70
73
|
- examples/test.bt
|
71
74
|
- examples/string_test.bt
|
data/version.rb
DELETED