meta_compile 0.0.8 → 0.0.10
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +11 -3
- data/Rakefile +44 -21
- data/bin/meta_compile +9 -8
- data/bootstrap/meta_ruby_compiler.rb +9 -8
- data/bootstrap/{meta_for_c.txt → meta_to_c.meta} +0 -0
- data/bootstrap/{meta_for_ruby.txt → meta_to_ruby_minimal.meta} +6 -7
- data/bootstrap/{meta_for_ruby_single_flag.txt → meta_to_ruby_minimal_single_flag.meta} +0 -0
- data/meta_compile.gemspec +1 -1
- metadata +4 -4
data/README.md
CHANGED
@@ -3,7 +3,7 @@ meta_compile
|
|
3
3
|
|
4
4
|
A meta compilation framework for Ruby à la [Meta-II by Val Schorre](http://ibm-1401.info/Meta-II-schorre.pdf).
|
5
5
|
|
6
|
-
|
6
|
+
This uses a [C version of Meta-II](https://github.com/impeachgod/meta) developed by Long Nguyen to bootstrap a Ruby version from a [fully self-contained, 26 (non-empty) line specification file](https://raw.github.com/robertfeldt/meta_compile/master/bootstrap/meta_to_ruby_minimal.meta). The [generated Ruby Meta-II compiler file](https://github.com/robertfeldt/meta_compile/blob/master/bin/meta_compile) is 231 lines of Ruby code.
|
7
7
|
|
8
8
|
Install
|
9
9
|
-------
|
@@ -25,16 +25,24 @@ Manually verifying that it is a meta compiler
|
|
25
25
|
|
26
26
|
In your local copy of the git repo, use the pre-generated binary to compile the specification file to a ruby file:
|
27
27
|
|
28
|
-
bin/meta_compile bootstrap/
|
28
|
+
bin/meta_compile bootstrap/meta_to_ruby_minimal.meta t.rb
|
29
29
|
|
30
30
|
This generates a t.rb which is itself a compiler for meta syntax specs. So lets use it to generate itself:
|
31
31
|
|
32
|
-
ruby t.rb bootstrap/
|
32
|
+
ruby t.rb bootstrap/meta_to_ruby_minimal.meta t2.rb
|
33
33
|
|
34
34
|
And ensure they are really the same:
|
35
35
|
|
36
36
|
diff t.rb t2.rb
|
37
37
|
|
38
|
+
To be really sure we can try the generated t2.rb as a meta-compiler:
|
39
|
+
|
40
|
+
ruby t2.rb bootstrap/meta_to_ruby_minimal.meta t3.rb
|
41
|
+
|
42
|
+
and this should convince us:
|
43
|
+
|
44
|
+
diff t2.rb t3.rb
|
45
|
+
|
38
46
|
Limitations
|
39
47
|
-----------
|
40
48
|
+ Very bad/little error handling
|
data/Rakefile
CHANGED
@@ -33,52 +33,75 @@ task :bootstrap do
|
|
33
33
|
Dir.chdir("bootstrap") do
|
34
34
|
puts "1. Build bootstrap compiler"
|
35
35
|
pexec "gcc -o bootstrapped_c bootstrap.c"
|
36
|
-
puts "2. Use the c meta compiler to compile the
|
37
|
-
pexec "./bootstrapped_c
|
36
|
+
puts "2. Use the c meta compiler to compile the meta_to_ruby_minimal.meta description"
|
37
|
+
pexec "./bootstrapped_c meta_to_ruby_minimal.meta compile_to_ruby.c"
|
38
38
|
puts "3. Build the stepping stone ruby compiler we created from the meta description"
|
39
|
-
pexec "gcc -o meta_r
|
39
|
+
pexec "gcc -o meta_r compile_to_ruby.c"
|
40
40
|
puts "4. Now use the generated stepping stone compiler to generate a ruby compiler for the ruby meta syntax"
|
41
|
-
pexec "./meta_r
|
41
|
+
pexec "./meta_r meta_to_ruby_minimal.meta meta_ruby_compiler_from_c.rb"
|
42
42
|
puts "5. Run the generated ruby meta compiler to a ruby version"
|
43
|
-
pexec "ruby -I. meta_ruby_compiler_from_c.rb
|
44
|
-
puts "6.
|
43
|
+
pexec "ruby -I. meta_ruby_compiler_from_c.rb meta_to_ruby_minimal.meta > meta_ruby_compiler.rb"
|
44
|
+
puts "6. Ruby version differ since it has single instead of double quotes around strings"
|
45
45
|
#pexec "diff meta_ruby_compiler_from_c.rb meta_ruby_compiler.rb"
|
46
46
|
puts "7. But we can generate again and ensure it is a meta compiler"
|
47
|
-
pexec "ruby -I. meta_ruby_compiler.rb
|
47
|
+
pexec "ruby -I. meta_ruby_compiler.rb meta_to_ruby_minimal.meta > meta_ruby_compiler2.rb"
|
48
48
|
pexec "diff meta_ruby_compiler.rb meta_ruby_compiler2.rb"
|
49
49
|
puts "8. One more round just to show off... :)"
|
50
|
-
pexec "ruby -I. meta_ruby_compiler2.rb
|
50
|
+
pexec "ruby -I. meta_ruby_compiler2.rb meta_to_ruby_minimal.meta > meta_ruby_compiler3.rb"
|
51
51
|
pexec "diff meta_ruby_compiler.rb meta_ruby_compiler3.rb"
|
52
|
-
puts "Summary:\nCreated a #{loc('meta_ruby_compiler.rb')} line meta-II meta compiler from a #{loc('
|
52
|
+
puts "Summary:\nCreated a #{loc('meta_ruby_compiler.rb')} line meta-II meta compiler from a #{loc('meta_to_ruby_minimal.meta')} line meta-II spec\n\n"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Bootstrap a syntax from the meta_compile compiler
|
57
|
+
def bootstrap_from_meta_compile(syntaxFile)
|
58
|
+
pexec "meta_compile #{syntaxFile} > tgen.rb"
|
59
|
+
ensure_is_meta("tgen.rb", syntaxFile)
|
60
|
+
end
|
61
|
+
|
62
|
+
def diff_files(f1, f2)
|
63
|
+
File.read(f1) != File.read(f2)
|
64
|
+
end
|
65
|
+
|
66
|
+
def ensure_is_meta(generatedFile, specFile)
|
67
|
+
pexec "ruby #{generatedFile} #{specFile} > t.rb"
|
68
|
+
pexec "ruby t.rb #{specFile} > t2.rb"
|
69
|
+
# Obviously we should now be able to go on and on... :)
|
70
|
+
pexec "ruby t2.rb #{specFile} > t3.rb"
|
71
|
+
begin
|
72
|
+
if diff_files("t.rb", "t2.rb") || diff_files("t2.rb", "t3.rb")
|
73
|
+
puts "ERROR: #{generatedFile} is NOT a meta compiler (generated from #{specFile})"
|
74
|
+
exit(-1)
|
75
|
+
else
|
76
|
+
puts "YES #{generatedFile} is meta!!! (generated from #{specFile})"
|
77
|
+
end
|
78
|
+
ensure
|
79
|
+
FileUtils.rm_f Dir.glob("t*.rb")
|
53
80
|
end
|
54
81
|
end
|
55
82
|
|
56
83
|
desc "Make binary from the bootstrapped ruby meta-II compiler"
|
57
84
|
task :make_bin => [:bootstrap] do
|
58
|
-
# First ensure it is a meta compiler
|
59
|
-
puts "Ensure it is a meta-compiler"
|
60
|
-
pexec "ruby bootstrap/meta_ruby_compiler.rb bootstrap/meta_for_ruby.txt t.rb"
|
61
|
-
if File.read("t.rb") != File.read("bootstrap/meta_ruby_compiler.rb")
|
62
|
-
puts "ERROR: bootstrap/meta_ruby_compiler.rb is NOT a meta compiler"
|
63
|
-
exit(-1)
|
64
|
-
else
|
65
|
-
puts "YES it is meta!!!"
|
66
|
-
end
|
67
85
|
FileUtils.cp "bootstrap/meta_ruby_compiler.rb", "bin/meta_compile"
|
68
86
|
FileUtils.chmod 0755, "bin/meta_compile"
|
69
87
|
puts "Created binary in bin/meta_compile"
|
70
88
|
end
|
71
89
|
|
90
|
+
desc "Ensure it is a meta compiler"
|
91
|
+
task :ensure_meta => [:make_bin] do
|
92
|
+
ensure_is_meta "bin/meta_compile", "bootstrap/meta_to_ruby_minimal.meta"
|
93
|
+
end
|
94
|
+
|
72
95
|
desc "Update line counts in README.template.md to make README.md"
|
73
96
|
task :update_readme => [:bootstrap] do
|
74
97
|
rmeta2_compiler_loc = loc('bootstrap/meta_ruby_compiler.rb')
|
75
|
-
rmeta2_spec_loc = loc('bootstrap/
|
98
|
+
rmeta2_spec_loc = loc('bootstrap/meta_to_ruby_minimal.meta')
|
76
99
|
readme = File.read("README.template.md").gsub("%%RMetaII_SPEC_LOC%%", rmeta2_spec_loc.to_s)
|
77
100
|
readme = readme.gsub("%%RMetaII_COMPILER_LOC%%", rmeta2_compiler_loc.to_s)
|
78
101
|
File.open("README.md", "w") {|f| f.puts readme}
|
79
102
|
end
|
80
103
|
|
81
|
-
task :default => :
|
104
|
+
task :default => :ensure_meta
|
82
105
|
|
83
106
|
desc "Build the gem"
|
84
107
|
task :build_gem => [:make_bin] do
|
@@ -99,7 +122,7 @@ end
|
|
99
122
|
|
100
123
|
task :clean do
|
101
124
|
Dir.chdir("bootstrap") do
|
102
|
-
FileUtils.rm_f %w{bootstrapped_c meta_compiler_from_boostrapped_c.c meta_compiler.c meta_ruby_compiler2.rb meta_ruby_compiler3.rb meta_ruby_compiler_from_c.rb
|
125
|
+
FileUtils.rm_f %w{bootstrapped_c meta_compiler_from_boostrapped_c.c meta_compiler.c meta_ruby_compiler2.rb meta_ruby_compiler3.rb meta_ruby_compiler_from_c.rb compile_to_ruby.c meta_c meta_r}
|
103
126
|
end
|
104
127
|
FileUtils.rm_f Dir.glob("t*.rb")
|
105
128
|
end
|
data/bin/meta_compile
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
require "strscan"
|
3
|
-
class
|
3
|
+
class C_program
|
4
|
+
$c = self
|
4
5
|
def compile(str, out)
|
5
6
|
@i, @o = StringScanner.new(str), out
|
6
7
|
compile_program
|
@@ -197,14 +198,17 @@ raise("error at: " + @i.rest.split("\n")[0]) if !@f
|
|
197
198
|
@o.print "\n"
|
198
199
|
@o.print 'require "strscan"'
|
199
200
|
@o.print "\n"
|
200
|
-
@o.print 'class '
|
201
|
+
@o.print 'class C_'
|
201
202
|
@o.print @t
|
202
203
|
@o.print "\n"
|
204
|
+
@o.print '$c = self'
|
205
|
+
@o.print "\n"
|
203
206
|
@o.print 'def compile(str, out)'
|
204
207
|
@o.print "\n"
|
205
208
|
@o.print '@i, @o = StringScanner.new(str), out'
|
206
209
|
@o.print "\n"
|
207
|
-
@o.print '
|
210
|
+
@o.print 'compile_'
|
211
|
+
@o.print @t
|
208
212
|
@o.print "\n"
|
209
213
|
@o.print 'end'
|
210
214
|
@o.print "\n"
|
@@ -218,13 +222,10 @@ raise("error at: " + @i.rest.split("\n")[0]) if !@f
|
|
218
222
|
raise("error at: " + @i.rest.split("\n")[0]) if !@f
|
219
223
|
@o.print 'end'
|
220
224
|
@o.print "\n"
|
221
|
-
@o.print '
|
222
|
-
@o.print "\n"
|
223
|
-
@o.print 'File.open(ARGV[1], "w") {|f| RMetaII.new.compile(File.read(ARGV[0]), f)}'
|
225
|
+
@o.print '$c.new.compile(File.read(ARGV[0]), STDOUT) if __FILE__ == $0'
|
224
226
|
@o.print "\n"
|
225
227
|
end
|
226
228
|
end while false
|
227
229
|
end
|
228
230
|
end
|
229
|
-
|
230
|
-
File.open(ARGV[1], "w") {|f| RMetaII.new.compile(File.read(ARGV[0]), f)}
|
231
|
+
$c.new.compile(File.read(ARGV[0]), STDOUT) if __FILE__ == $0
|
@@ -1,6 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
require "strscan"
|
3
|
-
class
|
3
|
+
class C_program
|
4
|
+
$c = self
|
4
5
|
def compile(str, out)
|
5
6
|
@i, @o = StringScanner.new(str), out
|
6
7
|
compile_program
|
@@ -197,14 +198,17 @@ raise("error at: " + @i.rest.split("\n")[0]) if !@f
|
|
197
198
|
@o.print "\n"
|
198
199
|
@o.print 'require "strscan"'
|
199
200
|
@o.print "\n"
|
200
|
-
@o.print 'class '
|
201
|
+
@o.print 'class C_'
|
201
202
|
@o.print @t
|
202
203
|
@o.print "\n"
|
204
|
+
@o.print '$c = self'
|
205
|
+
@o.print "\n"
|
203
206
|
@o.print 'def compile(str, out)'
|
204
207
|
@o.print "\n"
|
205
208
|
@o.print '@i, @o = StringScanner.new(str), out'
|
206
209
|
@o.print "\n"
|
207
|
-
@o.print '
|
210
|
+
@o.print 'compile_'
|
211
|
+
@o.print @t
|
208
212
|
@o.print "\n"
|
209
213
|
@o.print 'end'
|
210
214
|
@o.print "\n"
|
@@ -218,13 +222,10 @@ raise("error at: " + @i.rest.split("\n")[0]) if !@f
|
|
218
222
|
raise("error at: " + @i.rest.split("\n")[0]) if !@f
|
219
223
|
@o.print 'end'
|
220
224
|
@o.print "\n"
|
221
|
-
@o.print '
|
222
|
-
@o.print "\n"
|
223
|
-
@o.print 'File.open(ARGV[1], "w") {|f| RMetaII.new.compile(File.read(ARGV[0]), f)}'
|
225
|
+
@o.print '$c.new.compile(File.read(ARGV[0]), STDOUT) if __FILE__ == $0'
|
224
226
|
@o.print "\n"
|
225
227
|
end
|
226
228
|
end while false
|
227
229
|
end
|
228
230
|
end
|
229
|
-
|
230
|
-
File.open(ARGV[1], "w") {|f| RMetaII.new.compile(File.read(ARGV[0]), f)}
|
231
|
+
$c.new.compile(File.read(ARGV[0]), STDOUT) if __FILE__ == $0
|
File without changes
|
@@ -1,4 +1,4 @@
|
|
1
|
-
.syntax
|
1
|
+
.syntax program
|
2
2
|
|
3
3
|
outarg = '$' <'@o.print @t'> | .string <'@o.print ' $>;
|
4
4
|
|
@@ -6,7 +6,7 @@ out = '<' *outarg '>' <'@o.print "\n"'>;
|
|
6
6
|
|
7
7
|
exp3 = .id <'compile_' $>
|
8
8
|
| .string <'@i.scan /\s*/; s=' $ '; l=s.length;'>
|
9
|
-
|
9
|
+
<'@f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil'>
|
10
10
|
| '.id' <'@i.scan /\s*/; @f = @t = @i.scan /[A-Za-z]+[A-Za-z0-9_]+/'>
|
11
11
|
| '.string' <'@i.scan /\s*/; @f = @t = @i.scan /\047[^\047]*\047/'>
|
12
12
|
| '(' exp1 ')'
|
@@ -24,12 +24,11 @@ exp1 = <'begin'> exp2
|
|
24
24
|
rule = .id <'def compile_' $> '=' exp1 ';' <'end'>;
|
25
25
|
|
26
26
|
program = '.syntax' .id
|
27
|
-
<'#!/usr/bin/env ruby'> <'require "strscan"'>
|
28
|
-
<'class ' $> <'def compile(str, out)'>
|
27
|
+
<'#!/usr/bin/env ruby'> <'require "strscan"'>
|
28
|
+
<'class C_' $> <'$c = self'> <'def compile(str, out)'>
|
29
29
|
<'@i, @o = StringScanner.new(str), out'>
|
30
|
-
<'
|
30
|
+
<'compile_' $> <'end'>
|
31
31
|
*rule '.end' <'end'>
|
32
|
-
<'
|
33
|
-
<'File.open(ARGV[1], "w") {|f| RMetaII.new.compile(File.read(ARGV[0]), f)}'>;
|
32
|
+
<'$c.new.compile(File.read(ARGV[0]), STDOUT) if __FILE__ == $0'>;
|
34
33
|
|
35
34
|
.end
|
File without changes
|
data/meta_compile.gemspec
CHANGED
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.
|
4
|
+
version: 0.0.10
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -23,10 +23,10 @@ files:
|
|
23
23
|
- meta_compile.gemspec
|
24
24
|
- bin/meta_compile
|
25
25
|
- bootstrap/bootstrap.c
|
26
|
-
- bootstrap/meta_for_c.txt
|
27
|
-
- bootstrap/meta_for_ruby.txt
|
28
|
-
- bootstrap/meta_for_ruby_single_flag.txt
|
29
26
|
- bootstrap/meta_ruby_compiler.rb
|
27
|
+
- bootstrap/meta_to_c.meta
|
28
|
+
- bootstrap/meta_to_ruby_minimal.meta
|
29
|
+
- bootstrap/meta_to_ruby_minimal_single_flag.meta
|
30
30
|
- bootstrap/original_support.h
|
31
31
|
- bootstrap/support.h
|
32
32
|
homepage: http://rubygems.org/gems/meta_compile
|