meta_compile 0.0.8 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|