all repos — min @ 8b99c7917596ca64636f7965424a3ae7569417d4

A small but practical concatenative programming language.

Ensured the hint message is displayed at all clean exits.
h3rald h3rald@h3rald.com
Mon, 18 May 2026 11:26:56 +0200
commit

8b99c7917596ca64636f7965424a3ae7569417d4

parent

73d3471b3612ca68771ff107b3ae2c1d8bce2567

M min.nimmin.nim

@@ -2,13 +2,14 @@ import

std/[streams, strutils, sequtils, + exitprocs, times, os, logging] import minpkg/core/[niftylogger, - baseutils, env, + baseutils, parser, value, interpreter,

@@ -39,6 +40,12 @@

if logging.getHandlers().len == 0: newNiftyLogger().addHandler() +proc showUnhandledExceptionMessage = + if not ERRORS_HANDLED: + logging.warn "Please re-run this program in development mode (specify -d) for debugging information on this error." + +addExitProc(showUnhandledExceptionMessage) + proc interpret*(i: In, s: Stream) = i.stdLib() i.open(s, i.filename)

@@ -47,7 +54,8 @@ try:

i.interpret() except CatchableError: discard - i.close() + finally: + i.close() proc minFile*(fn: string, op = "interpret", main = true): seq[ string] {.discardable.}

@@ -55,7 +63,7 @@

proc compile*(i: In, s: Stream, main = true): seq[string] = if "nim".findExe == "": logging.error "Nim compiler not found, unable to compile." - quit(7) + terminate(7) result = newSeq[string](0) i.open(s, i.filename) discard i.parser.getToken()

@@ -105,7 +113,7 @@ try:

fileLines = fn.readFile().splitLines() except CatchableError: logging.fatal("Cannot read from file: " & fn) - quit(3) + terminate(3) if fileLines[0].len >= 2 and fileLines[0][0..1] == "#!": contents = ";;\n" & fileLines[1..fileLines.len-1].join("\n") else:

@@ -135,11 +143,11 @@ proc executeMmmCmd(cmd: proc (): void) =

try: MMM.setup() cmd() - quit(0) + terminate(0) except CatchableError: error getCurrentExceptionMsg() debug getCurrentException().getStackTrace() - quit(10) + terminate(10) let usage* = """ $exe v$version - a small but practical concatenative programming language (c) 2014-$year Fabio Cevasco

@@ -214,11 +222,11 @@ NIMOPTIONS = val

of "help", "h": if file == "": echo usage - quit(0) + terminate(0) of "version", "v": if file == "": echo pkgVersion - quit(0) + terminate(0) of "interactive", "i": if file == "": REPL = true

@@ -237,38 +245,39 @@ if f.endsWith(".min"):

MINMODULES.add f elif REPL: minRepl() - quit(0) + terminate(0) if file != "": var fn = resolveFile(file) if fn == "": if file == "compile": if args.len < 2: logging.error "No file was specified." - quit(8) + terminate(8) fn = resolveFile(args[1]) if fn == "": logging.error "File '$#' does not exist." % [args[1]] - quit(9) + terminate(9) minFile fn, "compile" - quit(0) + terminate(0) elif file == "eval": if args.len < 2: logging.error "No string to evaluate was specified." - quit(9) + terminate(9) minStr args[1] - quit(0) + terminate(0) elif file == "help": if args.len < 2: logging.error "No symbol to lookup was specified." - quit(9) + terminate(9) minStr("\"$#\" help" % [args[1]]) - quit(0) + terminate(0) elif file == "init": executeMmmCmd(proc () = MMM.init()) + terminate(0) elif file == "run": if args.len < 1: logging.error "No script was specified." - quit(8) + terminate(8) MMM.setup() var script: string try:

@@ -276,9 +285,9 @@ script = MMM.generateRunScript(args[1])

except CatchableError: error getCurrentExceptionMsg() debug getCurrentException().getStackTrace() - quit(10) + terminate(10) minStr(script) - quit(0) + terminate(0) elif file == "install": if args.len < 2: executeMmmCmd(proc () = MMM.install())

@@ -315,15 +324,14 @@ else:

executeMmmCmd(proc () = MMM.list(MMM.localDir)) else: logging.error "File not found: $#" % [file] - quit(1) + terminate(1) else: minFile fn, "interpret" elif SIMPLEREPL: minSimpleRepl() - quit(0) else: if isatty(stdin): minRepl() - quit(0) else: minStream newFileStream(stdin), "stdin", "interpret" + terminate(0)
M minpkg/core/baseutils.nimminpkg/core/baseutils.nim

@@ -2,6 +2,8 @@ import

std/[strutils, os, json] +import + env proc reverse*[T](xs: openarray[T]): seq[T] = result = newSeq[T](xs.len)

@@ -29,3 +31,7 @@ proc escapeEx*(s: string, unquoted = false): string =

if unquoted: return s.escapeJsonUnquoted return s.escapeJson + +proc terminate*(i: int) = + ERRORS_HANDLED = true + quit(i)
M minpkg/core/env.nimminpkg/core/env.nim

@@ -24,4 +24,5 @@ var DEV* {.threadvar.}: bool

DEV = false var COLOR* {.threadvar.}: bool COLOR = true - +var ERRORS_HANDLED* {.threadvar.}: bool +ERRORS_HANDLED = false
M minpkg/core/shell.nimminpkg/core/shell.nim

@@ -26,25 +26,15 @@ minline

var SIMPLEREPL* = false -var SUCCESS* = false - -proc showUnhandledExceptionMessage = - if not SUCCESS: - stderr.writeLine "=> Please re-run this program in development mode (specify -d) for debugging information on this error." - -addExitProc(showUnhandledExceptionMessage) - proc interpret*(i: In, s: string): MinValue = - SUCCESS = false i.open(newStringStream(s), i.filename) discard i.parser.getToken() try: result = i.interpret() except CatchableError: discard - i.close() finally: - SUCCESS = true + i.close() proc getCompletions*(ed: LineEditor, i: MinInterpreter): seq[string] = let symbols = toSeq(i.scope.symbols.keys)
M minpkg/lib/min_global.nimminpkg/lib/min_global.nim

@@ -429,7 +429,7 @@ raiseInvalid("Expected empty stack, found $# elements instead" % $l)

def.symbol("exit") do (i: In): let vals = i.expect("int") - quit(vals[0].intVal.int) + terminate(vals[0].intVal.int) def.symbol("print") do (i: In): let a = i.peek
M minpkg/lib/min_io.nimminpkg/lib/min_io.nim

@@ -7,9 +7,10 @@ terminal]

import minline import + ../core/env, + ../core/baseutils, ../core/parser, ../core/value, - ../core/env, ../core/interpreter, ../core/utils

@@ -73,7 +74,7 @@

def.symbol("fatal") do (i: In): let a = i.peek fatal $$a - quit(100) + terminate(100) def.symbol("column-print") do (i: In): let vals = i.expect("int", "quot")