-
-
Notifications
You must be signed in to change notification settings - Fork 921
/
c_compiler.rb
134 lines (92 loc) · 2.61 KB
/
c_compiler.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
require 'duby'
require 'duby/compiler'
module Duby
module Compiler
class C
class MathCompiler
def call(compiler, call)
call.target.compile(compiler)
compiler.src << " #{call.name} "
call.parameters.each {|param| param.compile(compiler)}
end
end
attr_accessor :filename, :src
def initialize(filename)
@filename = filename
@src = ""
self.type_mapper[AST::TypeReference.new(:fixnum)] = "int"
self.call_compilers[AST::TypeReference.new(:fixnum)] = MathCompiler.new
end
def compile(ast)
ast.compile(self)
end
def define_main(body)
old_src, @src = @src, "int main(int argc, char **argv)\n{\n"
body.compile(self)
@src << "}\n\n"
@src = old_src + @src
end
def define_method(name, signature, args, body)
old_src, @src = @src, "#{type_mapper[signature[:return]]} #{name}("
args.compile(self)
@src << ")\n{\n"
body.compile(self)
@src << "\n}\n\n"
@src = old_src + @src
end
def declare_argument(name, type)
@src << "#{type_mapper[type]} #{name}"
end
def branch(iff)
@src << "if ("
iff.condition.compile(self)
@src << ") {"
iff.body.compile(self)
if iff.else
@src << "} else {"
iff.else.compile(self)
end
@src << "}"
end
def call(call)
call_compilers[call.target.inferred_type].call(self, call)
end
def call_compilers
@call_compilers ||= {}
end
def self_call(fcall)
@src << "#{fcall.name}("
fcall.parameters.each {|param| param.compile(self)}
@src << ")"
end
def local(name, type)
@src << name
end
def fixnum(value)
@src << value.to_s
end
def newline
@src << ";\n"
end
def ret
@src << "return "
yield
end
def generate
@src
end
def type_mapper
@type_mapper ||= {}
end
end
end
end
if __FILE__ == $0
ast = Duby::AST.parse(File.read(ARGV[0]))
typer = Duby::Typer::Simple.new(:script)
ast.infer(typer)
typer.resolve(true)
compiler = Duby::Compiler::C.new("#{ARGV[0]}.c")
ast.compile(compiler)
File.open(compiler.filename, "w") {|file| file.write(compiler.generate)}
end