diff --git a/lib/vaporware/compiler.rb b/lib/vaporware/compiler.rb index 96f6493..bb270a6 100644 --- a/lib/vaporware/compiler.rb +++ b/lib/vaporware/compiler.rb @@ -40,7 +40,7 @@ def compile(compiler: "gcc", compiler_options: ["-O0"]) end output.close compiler_options += @generator.compile_shared_option if @generator.shared - @generator.call_compiler(compiler:, compiler_options:) + @generator.to_elf(input: @generator.precompile, compiler:, compiler_options:, debug: @generator.debug) end end end diff --git a/lib/vaporware/compiler/generator.rb b/lib/vaporware/compiler/generator.rb index b0eb4eb..19f17d0 100644 --- a/lib/vaporware/compiler/generator.rb +++ b/lib/vaporware/compiler/generator.rb @@ -31,16 +31,22 @@ def register_var_and_method(node) def already_build_methods? = defined_methods.sort == @doned.to_a.sort - def call_compiler(output: precompile, compiler: "gcc", compiler_options: ["-O0"]) - base_name = File.basename(output, ".*") + def to_elf(input: precompile, compiler: "gcc", compiler_options: ["-O0"], debug: false) + base_name = File.basename(input, ".*") name = shared ? "lib#{base_name}.so" : base_name - compile_commands = [compiler, *compiler_options, "-o", name, output].compact - IO.popen(compile_commands).close + if compiler.nil? + Vaporware::Compiler::Assemble.compile!(name, input) + else + compile_commands = [compiler, *compiler_options, "-o", name, input].compact + call_compiler(compile_commands) + end - File.delete(output) unless debug + File.delete(input) unless debug nil end + def call_compiler(compile_commands) = IO.popen(compile_commands).close + def epilogue(output) output.puts " mov rsp, rbp" output.puts " pop rbp" diff --git a/sig/vaporware.rbs b/sig/vaporware.rbs index fb62e27..3e9535e 100644 --- a/sig/vaporware.rbs +++ b/sig/vaporware.rbs @@ -3,4 +3,57 @@ module Vaporware # See the writing guide of rbs: https://github.com/ruby/rbs#guides class Error end + class Compiler + # class methods + def self.compile: (String, ?compiler: String, ?dest: String, ?debug: bool, ?compiler_options: Array[String], ?shared: bool) -> nil + def initialize: (String, ?_precompile: String, ?debug: bool, ?shared: bool) -> untyped + @generator: Vaporware::Compiler::Generator + # instance methods + def compile: (?compiler: String, ?compiler_options: Array[String]) -> nil + class Generator + REGISTER: Array[String] + # instance variables + @precompile: String + @debug: bool + @doned: Set[Symbol] + @defined_methods: Set[Symbol] + @defined_variables: Set[Symbol] + @seq: Integer + @main: bool + @shared: bool + # temporarily using untyped types since parser.gem's rbs information is unchecked. + @ast: untyped + # class methods + def initialize: (String, precompile: String, debug: bool, shared: bool) -> untyped + + # attr reader for instance variables + def precompile: -> String + def ast: -> untyped # Parser::AST::Node + def defined_methods: -> Set[Symbol] + def defined_variables: -> Set[Symbol] + def debug: -> bool + def doned: -> Set[Symbol] + def seq: -> Integer + def shared: -> bool + # instance private methods + def already_build_methods?: -> bool + def args: (untyped, File) -> nil + def build: (untyped, File, ?bool) -> nil + def call_compiler: (Array[String]) -> nil + def call_method: (untyped, File, bool) -> nil + def comp: (String, File) -> nil + def compile_shared_option: () -> Array[String] + def define_method_prologue: (untyped, File) -> nil + def epilogue: (File) -> nil + def lvar: (untyped, File) -> nil + def method: (Symbol, untyped, File) -> nil + def prologue: (untyped, File) -> nil + def prologue_methods: (File) -> nil + def ret: (File) -> nil + def lvar_offset: (Symbol | nil) -> Integer + def register_var_and_method: (untyped) -> nil + def to_elf: (?input: String, ?compiler: String, ?compiler_options: Array[String], ?debug: bool) -> nil + def variable_or_method?: (Symbol) -> bool + end + end end