Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: crystal-lang/crystal
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 5c51ed1816b5
Choose a base ref
...
head repository: crystal-lang/crystal
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: c81b81d0de4c
Choose a head ref
  • 3 commits
  • 6 files changed
  • 1 contributor

Commits on Sep 17, 2017

  1. Codegen: always expose __crystal_main

    This makes it possible to invoke `__crystal_main` from inside types and modules.
    asterite committed Sep 17, 2017
    Copy the full SHA
    968e640 View commit details

Commits on Sep 18, 2017

  1. Add Crystal.main

    This makes it simpler to redefine main with custom logic.
    asterite committed Sep 18, 2017
    Copy the full SHA
    5f0fe1c View commit details

Commits on Sep 19, 2017

  1. Merge pull request #4998 from asterite/refactor/better-main

    Add Crystal.main
    asterite authored Sep 19, 2017
    Copy the full SHA
    c81b81d View commit details
Showing with 117 additions and 41 deletions.
  1. +0 −6 samples/sdl/sdl/lib_sdl.cr
  2. +3 −4 src/compiler/crystal/codegen/codegen.cr
  3. +1 −1 src/compiler/crystal/compiler.cr
  4. +112 −0 src/crystal/main.cr
  5. +0 −29 src/main.cr
  6. +1 −1 src/prelude.cr
6 changes: 0 additions & 6 deletions samples/sdl/sdl/lib_sdl.cr
Original file line number Diff line number Diff line change
@@ -150,9 +150,3 @@ lib LibSDL
fun get_ticks = SDL_GetTicks : UInt32
fun flip = SDL_Flip(screen : Surface*) : Int32
end

{% if flag?(:darwin) %}
redefine_main(SDL_main) do |main|
\{{main}}
end
{% end %}
7 changes: 3 additions & 4 deletions src/compiler/crystal/codegen/codegen.cr
Original file line number Diff line number Diff line change
@@ -60,8 +60,8 @@ module Crystal
end
end

def codegen(node, single_module = false, debug = Debug::Default, expose_crystal_main = true)
visitor = CodeGenVisitor.new self, node, single_module: single_module, debug: debug, expose_crystal_main: expose_crystal_main
def codegen(node, single_module = false, debug = Debug::Default)
visitor = CodeGenVisitor.new self, node, single_module: single_module, debug: debug
node.accept visitor
visitor.process_finished_hooks
visitor.finish
@@ -141,7 +141,7 @@ module Crystal
@main_module_info : ModuleInfo
@main_builder : CrystalLLVMBuilder

def initialize(@program : Program, @node : ASTNode, single_module = false, @debug = Debug::Default, expose_crystal_main = true)
def initialize(@program : Program, @node : ASTNode, single_module = false, @debug = Debug::Default)
@single_module = !!single_module
@abi = @program.target_machine.abi
@llvm_context = LLVM::Context.new
@@ -155,7 +155,6 @@ module Crystal
@main_ret_type = node.type? || @program.nil_type
ret_type = @llvm_typer.llvm_return_type(@main_ret_type)
@main = @llvm_mod.functions.add(MAIN_NAME, [llvm_context.int32, llvm_context.void_pointer.pointer], ret_type)
@main.linkage = LLVM::Linkage::Internal unless expose_crystal_main

emit_main_def_debug_metadata(@main, "??") unless @debug.none?

2 changes: 1 addition & 1 deletion src/compiler/crystal/compiler.cr
Original file line number Diff line number Diff line change
@@ -232,7 +232,7 @@ module Crystal

private def codegen(program, node : ASTNode, sources, output_filename)
llvm_modules = @progress_tracker.stage("Codegen (crystal)") do
program.codegen node, debug: debug, single_module: @single_module || @release || @cross_compile || @emit, expose_crystal_main: false
program.codegen node, debug: debug, single_module: @single_module || @release || @cross_compile || @emit
end

if @cross_compile
112 changes: 112 additions & 0 deletions src/crystal/main.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
lib LibCrystalMain
@[Raises]
fun __crystal_main(argc : Int32, argv : UInt8**)
end

# :nodoc:
def _crystal_main(argc : Int32, argv : UInt8**)
# TODO: remove this method and embed this inside
# Crystal.main. A bug in Crystal 0.23.1 prevents invoking
# __crystal_main from anywhere except the top level.
LibCrystalMain.__crystal_main(argc, argv)
end

module Crystal
# Defines the main routine run by normal Crystal programs:
#
# - Initializes the GC
# - Invokes the given *block*
# - Handles unhandled exceptions
# - Invokes `at_exit` handlers
# - Flushes `STDOUT` and `STDERR`
#
# This method can be invoked if you need to define a custom
# main (as in C main) function, doing all the above steps.
#
# For example:
#
# ```
# fun main(argc : Int32, argv : UInt8**) : Int32
# Crystal.main do
# time = Time.now
# Crystal.main_user_code(argc, argv)
# puts "Time to execute program: #{Time.now - time}"
# end
# end
# ```
#
# Note that the above is really just an example, almost the
# same can be accomplished with `at_exit`. But in some cases
# redefinition of C's main is needed.
def self.main(&block)
GC.init

status =
begin
yield
0
rescue ex
1
end

AtExitHandlers.run status
ex.inspect_with_backtrace STDERR if ex
STDOUT.flush
STDERR.flush
status
end

# Main method run by all Crystal programs at startup.
#
# This setups up the GC, invokes your program, rescuing
# any handled exception, and then runs `at_exit` handlers.
#
# This method is automatically invoked for you, so you
# don't need to invoke it.
#
# However, if you need to define a special main C function,
# you can redefine main and invoke `Crystal.main` from it:
#
# ```
# fun main(argc : Int32, argv : UInt8**) : Int32
# # some setup before Crystal main
# Crystal.main(argc, argv)
# # some cleanup logic after Crystal main
# end
# ```
#
# The `Crystal.main` can also be passed as a callback:
#
# ```
# fun main(argc : Int32, argv : UInt8**) : Int32
# LibFoo.init_foo_and_invoke_main(argc, argv, ->Crystal.main)
# end
# ```
#
# Note that before `Crystal.main` is invoked the GC
# is not setup yet, so nothing that allocates memory
# in Crystal (like `new` for classes) can be used.
def self.main(argc : Int32, argv : UInt8**)
main do
main_user_code(argc, argv)
end
end

# Executes the main user code. This normally is executed
# after initializing the GC and before executing `at_exit` handlers.
#
# You should never invoke this method unless you need to
# redefine C's main function. See `Crystal.main` for
# more details.
def self.main_user_code(argc : Int32, argv : UInt8**)
_crystal_main(argc, argv)
end
end

# Main function that acts as C's main function.
# Invokes `Crystal.main`.
#
# Can be redefined. See `Crystal.main` for examples.
fun main(argc : Int32, argv : UInt8**) : Int32
Crystal.main(argc, argv)
end
29 changes: 0 additions & 29 deletions src/main.cr

This file was deleted.

2 changes: 1 addition & 1 deletion src/prelude.cr
Original file line number Diff line number Diff line change
@@ -27,6 +27,7 @@ require "char"
require "char/reader"
require "class"
require "concurrent"
require "crystal/main"
require "deque"
require "dir"
require "enum"
@@ -45,7 +46,6 @@ require "int"
require "intrinsics"
require "io"
require "kernel"
require "main"
require "math/math"
require "mutex"
require "named_tuple"