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 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
- Uses a C version of Meta-II developed by Long Nguyen's ([meta](https://github.com/impeachgod/meta)) to bootstrap a Ruby version from a [fully self-contained 27 (non-empty) line specification file](https://raw.github.com/robertfeldt/meta_compile/master/bootstrap/meta_for_ruby.txt). The [generated Ruby Meta-II compiler file](https://github.com/robertfeldt/meta_compile/blob/master/bin/meta_compile) is 230 lines of non-empty Ruby code.
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/meta_for_ruby.txt t.rb
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/meta_for_ruby.txt t2.rb
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 meta_for_ruby.txt description"
37
- pexec "./bootstrapped_c meta_for_ruby.txt compile_syntax_c_to_ruby.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 compile_syntax_c_to_ruby.c"
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 meta_for_ruby.txt meta_ruby_compiler_from_c.rb"
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 meta_for_ruby.txt meta_ruby_compiler.rb"
44
- puts "6. The Ruby version differ in that it has single quotes instead of double quotes around emitted strings"
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 meta_for_ruby.txt meta_ruby_compiler2.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 meta_for_ruby.txt meta_ruby_compiler3.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('meta_for_ruby.txt')} line meta-II spec\n\n"
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/meta_for_ruby.txt')
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 => :make_bin
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 compile_syntax_c_to_ruby.c meta_c meta_r}
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 RMetaII
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 'compile_program'
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 'begin; puts("Use: " + $0 + " <in> <out>"); exit; end if ARGV.length != 2'
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
- begin; puts("Use: " + $0 + " <in> <out>"); exit; end if ARGV.length != 2
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 RMetaII
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 'compile_program'
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 'begin; puts("Use: " + $0 + " <in> <out>"); exit; end if ARGV.length != 2'
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
- begin; puts("Use: " + $0 + " <in> <out>"); exit; end if ARGV.length != 2
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 RMetaII
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
- <'@f = (@i.peek(l) == s) ? (@t=s; @i.pos += l) : nil'>
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
- <'compile_program'> <'end'>
30
+ <'compile_' $> <'end'>
31
31
  *rule '.end' <'end'>
32
- <'begin; puts("Use: " + $0 + " <in> <out>"); exit; end if ARGV.length != 2'>
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
data/meta_compile.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'meta_compile'
3
- s.version = '0.0.8'
3
+ s.version = '0.0.10'
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"
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.8
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