meta_compile 0.0.15 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -46,3 +46,44 @@ and this should convince us:
46
46
  Limitations
47
47
  -----------
48
48
  + Very bad/little error handling
49
+
50
+ Ok, now what?
51
+ -------------
52
+
53
+ Once the first meta compiler is up and running we can evolve the language. For example I made a change so [Ruby regexps can be used](https://github.com/robertfeldt/meta_compile/blob/master/syntaxes/meta_to_ruby_minimal_with_regexps.meta) instead of only string literals. Note that we need to use a [stepping stone syntax file](https://github.com/robertfeldt/meta_compile/blob/master/syntaxes/stepping_stone_meta_to_ruby_minimal_with_regexps.meta) before we can create a new meta compiler that accepts the new syntax.
54
+
55
+ Let's use this to compile programs which can only contain assignments of numbers to variables:
56
+
57
+ .syntax assignments
58
+ assignments = as *as;
59
+ as = /\w+/ <'address ' $> ':=' ex1 <'store'> ';';
60
+ ex1 = /\d+/ <'literal ' $>;
61
+ .end
62
+
63
+ The new thing here compared to the original Meta-II syntax is the two Regexp's (in as and ex1). First we need to bootstrap the meta compiler that accepts regexps:
64
+
65
+ rake bootstrap_re
66
+
67
+ Then we create a compiler for the assignments syntax:
68
+
69
+ ruby bin/metacomp_re syntaxes/assignments.meta > tas.rb
70
+
71
+ We now have a compiler for assignments and if we apply it [to the file](https://raw.github.com/robertfeldt/meta_compile/master/inputs/assignments.input1):
72
+
73
+ a := 137;
74
+ b := 4;
75
+
76
+ by running the command:
77
+
78
+ ruby tas.rb inputs/assignments.input1
79
+
80
+ it prints:
81
+
82
+ address a
83
+ literal 137
84
+ store
85
+ address d
86
+ literal 4
87
+ store
88
+
89
+ Not bad. :)
data/Rakefile CHANGED
@@ -92,6 +92,38 @@ task :ensure_meta => [:make_bin] do
92
92
  ensure_is_meta "bin/meta_compile", "syntaxes/meta_to_ruby_minimal.meta"
93
93
  end
94
94
 
95
+ def bootstrap_with_stepping_stone(syntaxFile, target)
96
+ syntaxf = File.join("syntaxes", syntaxFile)
97
+ stepstonef = File.join("syntaxes", "stepping_stone_" + syntaxFile)
98
+ pexec "meta_compile #{stepstonef} > tgen_stepstone.rb"
99
+ pexec "ruby tgen_stepstone.rb #{syntaxf} > #{target}"
100
+ ensure_is_meta(target, syntaxf)
101
+ end
102
+
103
+ desc "Bootstrap the meta compiler that accepts regexps"
104
+ task :bootstrap_re do
105
+ bootstrap_with_stepping_stone("meta_to_ruby_minimal_with_regexps.meta", "bin/metacomp_re")
106
+ end
107
+
108
+ def run_example(compiler, example)
109
+ puts "Compiling this input with #{compiler}:\n\n"
110
+ puts File.read(example)
111
+ puts "\ngives output:\n\n"
112
+ pexec "ruby #{compiler} #{example}"
113
+ end
114
+
115
+ def metacomp_re_run_examples(syntaxFile, *inputs)
116
+ pexec "ruby bin/metacomp_re #{syntaxFile} > tas.rb"
117
+ inputs.each do |i|
118
+ run_example("tas.rb", "inputs/#{i}")
119
+ end
120
+ end
121
+
122
+ desc "Compile all inputs for the assignments syntax"
123
+ task :ex_ass do
124
+ metacomp_re_run_examples "syntaxes/assignments.meta", "assignments.input1"
125
+ end
126
+
95
127
  desc "Update line counts in README.template.md to make README.md"
96
128
  task :update => [:bootstrap] do
97
129
  rmeta2_compiler_loc = loc('bootstrap/meta_ruby_compiler.rb')
data/bin/metacomp_re ADDED
@@ -0,0 +1,245 @@
1
+ #!/usr/bin/env ruby
2
+ require "strscan"
3
+ class C_program
4
+ $c = self
5
+ def compile(str, out)
6
+ @i, @o = StringScanner.new(str), out
7
+ compile_program
8
+ end
9
+ def compile_outarg
10
+ begin
11
+ @i.scan /\s*/; s='$'; l=s.length;
12
+ @f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
13
+ if @f
14
+ @o.print '@o.print @t'
15
+ @o.print "\n"
16
+ end
17
+ break if @f
18
+ @i.scan /\s*/; @f = @t = @i.scan /\047[^\047]*\047/
19
+ if @f
20
+ @o.print '@o.print '
21
+ @o.print @t
22
+ @o.print "\n"
23
+ end
24
+ end while false
25
+ end
26
+ def compile_out
27
+ begin
28
+ @i.scan /\s*/; s='<'; l=s.length;
29
+ @f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
30
+ if @f
31
+ begin
32
+ compile_outarg
33
+ end while @f
34
+ @f = true
35
+ raise("error at: " + @i.rest.split("\n")[0]) if !@f
36
+ @i.scan /\s*/; s='>'; l=s.length;
37
+ @f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
38
+ raise("error at: " + @i.rest.split("\n")[0]) if !@f
39
+ @o.print '@o.print "\n"'
40
+ @o.print "\n"
41
+ end
42
+ end while false
43
+ end
44
+ def compile_exp3
45
+ begin
46
+ @i.scan /\s*/; @f = @t = @i.scan /[A-Za-z]+[A-Za-z0-9_]+/
47
+ if @f
48
+ @o.print 'compile_'
49
+ @o.print @t
50
+ @o.print "\n"
51
+ end
52
+ break if @f
53
+ @i.scan /\s*/; @f = @t = @i.scan /\047[^\047]*\047/
54
+ if @f
55
+ @o.print '@i.scan /\s*/; s='
56
+ @o.print @t
57
+ @o.print '; l=s.length;'
58
+ @o.print "\n"
59
+ @o.print '@f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil'
60
+ @o.print "\n"
61
+ end
62
+ break if @f
63
+ @i.scan /\s*/; @f = @t = @i.scan /\/[^\/]*\//
64
+ if @f
65
+ @o.print '@i.scan /\s*/; @f = @t = @i.scan '
66
+ @o.print @t
67
+ @o.print "\n"
68
+ end
69
+ break if @f
70
+ @i.scan /\s*/; s='.id'; l=s.length;
71
+ @f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
72
+ if @f
73
+ @o.print '@i.scan /\s*/; @f = @t = @i.scan /[A-Za-z]+[A-Za-z0-9_]+/'
74
+ @o.print "\n"
75
+ end
76
+ break if @f
77
+ @i.scan /\s*/; s='.string'; l=s.length;
78
+ @f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
79
+ if @f
80
+ @o.print '@i.scan /\s*/; @f = @t = @i.scan /\047[^\047]*\047/'
81
+ @o.print "\n"
82
+ end
83
+ break if @f
84
+ @i.scan /\s*/; s='.re'; l=s.length;
85
+ @f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
86
+ if @f
87
+ @o.print '@i.scan /\s*/; @f = @t = @i.scan /\/[^\/]*\//'
88
+ @o.print "\n"
89
+ end
90
+ break if @f
91
+ @i.scan /\s*/; s='('; l=s.length;
92
+ @f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
93
+ if @f
94
+ compile_exp1
95
+ raise("error at: " + @i.rest.split("\n")[0]) if !@f
96
+ @i.scan /\s*/; s=')'; l=s.length;
97
+ @f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
98
+ raise("error at: " + @i.rest.split("\n")[0]) if !@f
99
+ end
100
+ break if @f
101
+ @i.scan /\s*/; s='.e'; l=s.length;
102
+ @f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
103
+ if @f
104
+ @o.print '@f = true'
105
+ @o.print "\n"
106
+ end
107
+ break if @f
108
+ @i.scan /\s*/; s='*'; l=s.length;
109
+ @f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
110
+ if @f
111
+ @o.print 'begin'
112
+ @o.print "\n"
113
+ compile_exp3
114
+ raise("error at: " + @i.rest.split("\n")[0]) if !@f
115
+ @o.print 'end while @f'
116
+ @o.print "\n"
117
+ @o.print '@f = true'
118
+ @o.print "\n"
119
+ end
120
+ end while false
121
+ end
122
+ def compile_exp2
123
+ begin
124
+ begin
125
+ compile_exp3
126
+ if @f
127
+ @o.print 'if @f'
128
+ @o.print "\n"
129
+ end
130
+ break if @f
131
+ compile_out
132
+ if @f
133
+ @o.print 'if true'
134
+ @o.print "\n"
135
+ end
136
+ end while false
137
+ if @f
138
+ begin
139
+ begin
140
+ compile_exp3
141
+ if @f
142
+ @o.print 'raise("error at: " + @i.rest.split("\n")[0]) if !@f'
143
+ @o.print "\n"
144
+ end
145
+ break if @f
146
+ compile_out
147
+ if @f
148
+ end
149
+ end while false
150
+ end while @f
151
+ @f = true
152
+ raise("error at: " + @i.rest.split("\n")[0]) if !@f
153
+ @o.print 'end'
154
+ @o.print "\n"
155
+ end
156
+ end while false
157
+ end
158
+ def compile_exp1
159
+ begin
160
+ @o.print 'begin'
161
+ @o.print "\n"
162
+ if true
163
+ compile_exp2
164
+ raise("error at: " + @i.rest.split("\n")[0]) if !@f
165
+ begin
166
+ begin
167
+ @i.scan /\s*/; s='|'; l=s.length;
168
+ @f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
169
+ if @f
170
+ @o.print 'break if @f'
171
+ @o.print "\n"
172
+ compile_exp2
173
+ raise("error at: " + @i.rest.split("\n")[0]) if !@f
174
+ end
175
+ end while false
176
+ end while @f
177
+ @f = true
178
+ raise("error at: " + @i.rest.split("\n")[0]) if !@f
179
+ @o.print 'end while false'
180
+ @o.print "\n"
181
+ end
182
+ end while false
183
+ end
184
+ def compile_rule
185
+ begin
186
+ @i.scan /\s*/; @f = @t = @i.scan /[A-Za-z]+[A-Za-z0-9_]+/
187
+ if @f
188
+ @o.print 'def compile_'
189
+ @o.print @t
190
+ @o.print "\n"
191
+ @i.scan /\s*/; s='='; l=s.length;
192
+ @f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
193
+ raise("error at: " + @i.rest.split("\n")[0]) if !@f
194
+ compile_exp1
195
+ raise("error at: " + @i.rest.split("\n")[0]) if !@f
196
+ @i.scan /\s*/; s=';'; l=s.length;
197
+ @f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
198
+ raise("error at: " + @i.rest.split("\n")[0]) if !@f
199
+ @o.print 'end'
200
+ @o.print "\n"
201
+ end
202
+ end while false
203
+ end
204
+ def compile_program
205
+ begin
206
+ @i.scan /\s*/; s='.syntax'; l=s.length;
207
+ @f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
208
+ if @f
209
+ @i.scan /\s*/; @f = @t = @i.scan /[A-Za-z]+[A-Za-z0-9_]+/
210
+ raise("error at: " + @i.rest.split("\n")[0]) if !@f
211
+ @o.print '#!/usr/bin/env ruby'
212
+ @o.print "\n"
213
+ @o.print 'require "strscan"'
214
+ @o.print "\n"
215
+ @o.print 'class C_'
216
+ @o.print @t
217
+ @o.print "\n"
218
+ @o.print '$c = self'
219
+ @o.print "\n"
220
+ @o.print 'def compile(str, out)'
221
+ @o.print "\n"
222
+ @o.print '@i, @o = StringScanner.new(str), out'
223
+ @o.print "\n"
224
+ @o.print 'compile_'
225
+ @o.print @t
226
+ @o.print "\n"
227
+ @o.print 'end'
228
+ @o.print "\n"
229
+ begin
230
+ compile_rule
231
+ end while @f
232
+ @f = true
233
+ raise("error at: " + @i.rest.split("\n")[0]) if !@f
234
+ @i.scan /\s*/; s='.end'; l=s.length;
235
+ @f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil
236
+ raise("error at: " + @i.rest.split("\n")[0]) if !@f
237
+ @o.print 'end'
238
+ @o.print "\n"
239
+ @o.print '$c.new.compile(File.read(ARGV[0]), STDOUT)'
240
+ @o.print "\n"
241
+ end
242
+ end while false
243
+ end
244
+ end
245
+ $c.new.compile(File.read(ARGV[0]), STDOUT)
@@ -0,0 +1,2 @@
1
+ a := 137;
2
+ d := 4;
data/meta_compile.gemspec CHANGED
@@ -1,12 +1,12 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'meta_compile'
3
- s.version = '0.0.15'
3
+ s.version = '0.1.0'
4
4
  s.date = '2012-11-25'
5
5
  s.summary = "meta compiler framework"
6
6
  s.description = "A meta compilation framework à la Meta-II by Val Schorre"
7
7
  s.authors = ["Robert Feldt"]
8
8
  s.email = 'robert.feldt@gmail.com'
9
- s.files = ["Rakefile", "README.md", "meta_compile.gemspec"] + Dir.glob("bin/*") + Dir.glob("bootstrap/*") + Dir.glob("syntaxes/*")
9
+ s.files = ["Rakefile", "README.md", "meta_compile.gemspec"] + Dir.glob("bin/*") + Dir.glob("bootstrap/*") + Dir.glob("syntaxes/*") + Dir.glob("inputs/*")
10
10
  s.executables << 'meta_compile'
11
11
  s.homepage =
12
12
  'http://rubygems.org/gems/meta_compile'
data/syntaxes/aexp.meta CHANGED
@@ -1,7 +1,7 @@
1
1
  .syntax aexp
2
2
 
3
3
  aexp = as *as;
4
- as = .id <'address' $> ':=' ex1 <'store'> ';';
4
+ as = /\w+/ <'address ' $> ':=' ex1 <'store'> ';';
5
5
  ex1 = ex2 *( '+' ex2 <'add'>
6
6
  | '-' ex2 <'sub'>);
7
7
  ex2 = ex3 *( '*' ex3 <'mpy'>
@@ -11,6 +11,7 @@ ex4 = '+' ex5
11
11
  | '-' ex5 <'minus'>
12
12
  | ex5;
13
13
  ex5 = .id <'load' $>
14
+ | /\d+/ <'literal ' $>
14
15
  | '(' ex1 ')';
15
16
 
16
17
  .end
@@ -0,0 +1,9 @@
1
+ .syntax assignments
2
+
3
+ assignments = as *as;
4
+
5
+ as = /\w+/ <'address ' $> ':=' ex1 <'store'> ';';
6
+
7
+ ex1 = /\d+/ <'literal ' $>;
8
+
9
+ .end
@@ -0,0 +1,36 @@
1
+ .syntax program
2
+
3
+ outarg = '$' <'@o.print @t'> | .string <'@o.print ' $>;
4
+
5
+ out = '<' *outarg '>' <'@o.print "\n"'>;
6
+
7
+ exp3 = .id <'compile_' $>
8
+ | .string <'@i.scan /\s*/; s=' $ '; l=s.length;'>
9
+ <'@f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil'>
10
+ | .re <'@i.scan /\s*/; @f = @t = @i.scan ' $>
11
+ | '.id' <'@i.scan /\s*/; @f = @t = @i.scan /[A-Za-z]+[A-Za-z0-9_]+/'>
12
+ | '.string' <'@i.scan /\s*/; @f = @t = @i.scan /\047[^\047]*\047/'>
13
+ | '.re' <'@i.scan /\s*/; @f = @t = @i.scan /\/[^\/]*\//'>
14
+ | '(' exp1 ')'
15
+ | '.e' <'@f = true'>
16
+ | '*' <'begin'> exp3 <'end while @f'> <'@f = true'>;
17
+
18
+ exp2 = ( exp3 <'if @f'> | out <'if true'> )
19
+ *( exp3 <'raise("error at: " + @i.rest.split("\n")[0]) if !@f'>
20
+ | out ) <'end'>;
21
+
22
+ exp1 = <'begin'> exp2
23
+ *( '|' <'break if @f'> exp2 )
24
+ <'end while false'>;
25
+
26
+ rule = .id <'def compile_' $> '=' exp1 ';' <'end'>;
27
+
28
+ program = '.syntax' .id
29
+ <'#!/usr/bin/env ruby'> <'require "strscan"'>
30
+ <'class C_' $> <'$c = self'> <'def compile(str, out)'>
31
+ <'@i, @o = StringScanner.new(str), out'>
32
+ <'compile_' $> <'end'>
33
+ *rule '.end' <'end'>
34
+ <'$c.new.compile(File.read(ARGV[0]), STDOUT)'>;
35
+
36
+ .end
@@ -0,0 +1,35 @@
1
+ .syntax program
2
+
3
+ outarg = '$' <'@o.print @t'> | .string <'@o.print ' $>;
4
+
5
+ out = '<' *outarg '>' <'@o.print "\n"'>;
6
+
7
+ exp3 = .id <'compile_' $>
8
+ | .string <'@i.scan /\s*/; s=' $ '; l=s.length;'>
9
+ <'@f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil'>
10
+ | '.id' <'@i.scan /\s*/; @f = @t = @i.scan /[A-Za-z]+[A-Za-z0-9_]+/'>
11
+ | '.string' <'@i.scan /\s*/; @f = @t = @i.scan /\047[^\047]*\047/'>
12
+ | '.re' <'@i.scan /\s*/; @f = @t = @i.scan /\/[^\/]*\//'>
13
+ | '(' exp1 ')'
14
+ | '.e' <'@f = true'>
15
+ | '*' <'begin'> exp3 <'end while @f'> <'@f = true'>;
16
+
17
+ exp2 = ( exp3 <'if @f'> | out <'if true'> )
18
+ *( exp3 <'raise("error at: " + @i.rest.split("\n")[0]) if !@f'>
19
+ | out ) <'end'>;
20
+
21
+ exp1 = <'begin'> exp2
22
+ *( '|' <'break if @f'> exp2 )
23
+ <'end while false'>;
24
+
25
+ rule = .id <'def compile_' $> '=' exp1 ';' <'end'>;
26
+
27
+ program = '.syntax' .id
28
+ <'#!/usr/bin/env ruby'> <'require "strscan"'>
29
+ <'class C_' $> <'$c = self'> <'def compile(str, out)'>
30
+ <'@i, @o = StringScanner.new(str), out'>
31
+ <'compile_' $> <'end'>
32
+ *rule '.end' <'end'>
33
+ <'$c.new.compile(File.read(ARGV[0]), STDOUT)'>;
34
+
35
+ .end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: meta_compile
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.15
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -22,16 +22,20 @@ files:
22
22
  - README.md
23
23
  - meta_compile.gemspec
24
24
  - bin/meta_compile
25
+ - bin/metacomp_re
25
26
  - bootstrap/bootstrap.c
26
27
  - bootstrap/meta_ruby_compiler.rb
27
28
  - bootstrap/meta_to_c.meta
28
29
  - bootstrap/original_support.h
29
30
  - bootstrap/support.h
30
- - syntaxes/aexp.input1
31
31
  - syntaxes/aexp.meta
32
+ - syntaxes/assignments.meta
32
33
  - syntaxes/meta_to_ruby.meta
33
34
  - syntaxes/meta_to_ruby_minimal.meta
34
35
  - syntaxes/meta_to_ruby_minimal_single_flag.meta
36
+ - syntaxes/meta_to_ruby_minimal_with_regexps.meta
37
+ - syntaxes/stepping_stone_meta_to_ruby_minimal_with_regexps.meta
38
+ - inputs/assignments.input1
35
39
  homepage: http://rubygems.org/gems/meta_compile
36
40
  licenses: []
37
41
  post_install_message:
data/syntaxes/aexp.input1 DELETED
@@ -1 +0,0 @@
1
- a := b