mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 17:04:41 +00:00
why ? - We already have an emit that does the same thing - The name asm itself is a bit confusing, you might think it's an alias for asm.js or something else. - The asm keyword is used differently on different compiler targets (it makes it inexpressive). - Does anyone (other than some compiler libraries) use asm instead of emit ? If yes, it's a bit strange to use asm somewhere and emit somewhere. By making the asm keyword for js target deprecated, there would be even less use of the asm keyword for js target, reducing the amount of confusion. - New users might accidentally use a non-universal approach via the asm keyword instead of emit, and then when they learn about asm, try to figure out what the differences are. see https://forum.nim-lang.org/t/10821 --------- Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
88 lines
2.3 KiB
Nim
88 lines
2.3 KiB
Nim
#
|
|
#
|
|
# Nim's Runtime Library
|
|
# (c) Copyright 2020 Andreas Rumpf
|
|
#
|
|
# See the file "copying.txt", included in this
|
|
# distribution, for details about the copyright.
|
|
#
|
|
|
|
## This module allows adding hooks to program exit.
|
|
|
|
import std/locks
|
|
when defined(js) and not defined(nodejs):
|
|
import std/assertions
|
|
|
|
type
|
|
FunKind = enum kClosure, kNoconv # extend as needed
|
|
Fun = object
|
|
case kind: FunKind
|
|
of kClosure: fun1: proc () {.closure.}
|
|
of kNoconv: fun2: proc () {.noconv.}
|
|
|
|
var
|
|
gFunsLock: Lock
|
|
gFuns {.cursor.}: seq[Fun] #Intentionally use the cursor to break up the lifetime trace and make it compatible with JS.
|
|
|
|
initLock(gFunsLock)
|
|
|
|
when defined(js):
|
|
proc addAtExit(quitProc: proc() {.noconv.}) =
|
|
when defined(nodejs):
|
|
{.emit: """
|
|
process.on('exit', `quitProc`);
|
|
""".}
|
|
elif defined(js):
|
|
{.emit: """
|
|
window.onbeforeunload = `quitProc`;
|
|
""".}
|
|
else:
|
|
proc addAtExit(quitProc: proc() {.noconv.}) {.
|
|
importc: "atexit", header: "<stdlib.h>".}
|
|
|
|
proc callClosures() {.noconv.} =
|
|
withLock gFunsLock:
|
|
for i in countdown(gFuns.len-1, 0):
|
|
let fun = gFuns[i]
|
|
case fun.kind
|
|
of kClosure: fun.fun1()
|
|
of kNoconv: fun.fun2()
|
|
gFuns.setLen(0)
|
|
|
|
template fun() =
|
|
if gFuns.len == 0:
|
|
addAtExit(callClosures)
|
|
|
|
proc addExitProc*(cl: proc () {.closure.}) =
|
|
## Adds/registers a quit procedure. Each call to `addExitProc` registers
|
|
## another quit procedure. They are executed on a last-in, first-out basis.
|
|
# Support for `addExitProc` is done by Ansi C's facilities here.
|
|
# In case of an unhandled exception the exit handlers should
|
|
# not be called explicitly! The user may decide to do this manually though.
|
|
withLock gFunsLock:
|
|
fun()
|
|
gFuns.add Fun(kind: kClosure, fun1: cl)
|
|
|
|
proc addExitProc*(cl: proc() {.noconv.}) =
|
|
## overload for `noconv` procs.
|
|
withLock gFunsLock:
|
|
fun()
|
|
gFuns.add Fun(kind: kNoconv, fun2: cl)
|
|
|
|
when not defined(nimscript) and (not defined(js) or defined(nodejs)):
|
|
proc getProgramResult*(): int =
|
|
when defined(js) and defined(nodejs):
|
|
{.emit: """
|
|
`result` = process.exitCode;
|
|
""".}
|
|
else:
|
|
result = programResult
|
|
|
|
proc setProgramResult*(a: int) =
|
|
when defined(js) and defined(nodejs):
|
|
{.emit: """
|
|
process.exitCode = `a`;
|
|
""".}
|
|
else:
|
|
programResult = a
|