all repos — min @ c4c1bbc0f94e1a043ae9411ffeca8eceb610dc3b

A small but practical concatenative programming language.

Renamed into min.
h3rald h3rald@h3rald.com
Sat, 25 Feb 2017 19:44:16 +0100
commit

c4c1bbc0f94e1a043ae9411ffeca8eceb610dc3b

parent

74760894f1dc4cc1a08aa7b344593da89a3dccf9

8 files changed, 322 insertions(+), 322 deletions(-)

jump to
M .gitignore.gitignore

@@ -1,7 +1,7 @@

nimcache/ build/ -minim.exe -minim +min.exe +min nakefile nimsuggest.log *.zip
M core/consts.nimcore/consts.nim

@@ -6,16 +6,16 @@ strutils,

logging const - cfgfile = "../minim.nimble".slurp + cfgfile = "../min.nimble".slurp var - appname* = "MiNiM" + appname* = "min" version*: string f = newStringStream(cfgfile) if f != nil: var p: CfgParser - open(p, f, "../minim.nimble") + open(p, f, "../min.nimble") while true: var e = next(p) case e.kind

@@ -44,7 +44,7 @@ HOME = getenv("USERPROFILE")

if not defined(windows): HOME = getenv("HOME") -let MINIMRC* = HOME / ".minimrc" -let MINIMSYMBOLS* = HOME / ".minim_symbols" -let MINIMHISTORY* = HOME / ".minim_history" -let MINIMLOG* = HOME / "minim.log"+let MINIMRC* = HOME / ".minrc" +let MINIMSYMBOLS* = HOME / ".min_symbols" +let MINIMHISTORY* = HOME / ".min_history" +let MINIMLOG* = HOME / "min.log"
A min.nim

@@ -0,0 +1,253 @@

+import + streams, + critbits, + parseopt2, + strutils, + os, + json, + sequtils, + algorithm, + logging +import + packages/nimline/nimline, + packages/niftylogger, + core/consts, + core/parser, + core/value, + core/scope, + core/interpreter, + core/utils +import + lib/min_lang, + lib/min_num, + lib/min_str, + lib/min_logic, + lib/min_time, + lib/min_io, + lib/min_sys, + lib/min_crypto, + lib/min_fs + +export + parser, + interpreter, + utils, + niftylogger, + value, + scope, + min_lang + +const PRELUDE* = "prelude.min".slurp.strip + +newNiftyLogger().addHandler() +newRollingFileLogger(MINIMLOG, fmtStr = verboseFmtStr).addHandler() + +proc getExecs(): seq[string] = + var res = newSeq[string](0) + let getFiles = proc(dir: string) = + for c, s in walkDir(dir, true): + if (c == pcFile or c == pcLinkToFile) and not res.contains(s): + res.add s + getFiles(getCurrentDir()) + for dir in "PATH".getEnv.split(PathSep): + getFiles(dir) + res.sort(system.cmp) + return res + +proc getCompletions(ed: LineEditor, symbols: seq[string]): seq[string] = + var words = ed.lineText.split(" ") + var word: string + if words.len == 0: + word = ed.lineText + else: + word = words[words.len-1] + if word.startsWith("'"): + return symbols.mapIt("'" & $it) + elif word.startsWith("~"): + return symbols.mapIt("~" & $it) + if word.startsWith("@"): + return symbols.mapIt("@" & $it) + if word.startsWith("#"): + return symbols.mapIt("#" & $it) + if word.startsWith(">"): + return symbols.mapIt(">" & $it) + if word.startsWith("*"): + return symbols.mapIt("*" & $it) + if word.startsWith("("): + return symbols.mapIt("(" & $it) + if word.startsWith("<"): + return toSeq(MINIMSYMBOLS.readFile.parseJson.pairs).mapIt("<" & $it[0]) + if word.startsWith("$"): + return toSeq(envPairs()).mapIt("$" & $it[0]) + if word.startsWith("!"): + return getExecs().mapIt("!" & $it) + if word.startsWith("&"): + return getExecs().mapIt("&" & $it) + if word.startsWith("\""): + var f = word[1..^1] + if f == "": + f = getCurrentDir().replace("\\", "/") + return toSeq(walkDir(f, true)).mapIt("\"$1" % it.path.replace("\\", "/")) + elif f.dirExists: + f = f.replace("\\", "/") + if f[f.len-1] != '/': + f = f & "/" + return toSeq(walkDir(f, true)).mapIt("\"$1$2" % [f, it.path.replace("\\", "/")]) + else: + var dir: string + if f.contains("/") or dir.contains("\\"): + dir = f.parentDir + let file = f.extractFileName + return toSeq(walkDir(dir, true)).filterIt(it.path.toLowerAscii.startsWith(file.toLowerAscii)).mapIt("\"$1/$2" % [dir, it.path.replace("\\", "/")]) + else: + dir = getCurrentDir() + return toSeq(walkDir(dir, true)).filterIt(it.path.toLowerAscii.startsWith(f.toLowerAscii)).mapIt("\"$1" % [it.path.replace("\\", "/")]) + return symbols + +proc stdLib*(i: In) = + if not MINIMSYMBOLS.fileExists: + MINIMSYMBOLS.writeFile("{}") + if not MINIMHISTORY.fileExists: + MINIMHISTORY.writeFile("") + if not MINIMRC.fileExists: + MINIMRC.writeFile("") + i.lang_module + i.io_module + i.logic_module + i.num_module + i.str_module + i.sys_module + i.time_module + i.fs_module + i.crypto_module + i.eval PRELUDE, "<prelude>" + i.eval MINIMRC.readFile() + +proc interpret*(i: In, s: Stream) = + i.stdLib() + i.open(s, i.filename) + discard i.parser.getToken() + try: + i.interpret() + except: + discard + i.close() + +proc minStream(s: Stream, filename: string) = + var i = newMinInterpreter() + i.pwd = filename.parentDir + i.interpret(s) + +proc minString*(buffer: string) = + minStream(newStringStream(buffer), "input") + +proc minFile*(filename: string) = + var stream = newFileStream(filename, fmRead) + if stream == nil: + fatal("Cannot read from file: "& filename) + quit(3) + minStream(stream, filename) + +proc minFile*(file: File, filename="stdin") = + var stream = newFileStream(stdin) + if stream == nil: + fatal("Cannot read from file: "& filename) + quit(3) + minStream(stream, filename) + +proc printResult(i: In, res: MinValue) = + if res.isNil: + return + if i.stack.len > 0: + let n = $i.stack.len + if res.isQuotation and res.qVal.len > 1: + echo "{$1} -> (" % n + for item in res.qVal: + echo " " & $item + echo " ".repeat(n.len) & " )" + else: + echo "{$1} -> $2" % [$i.stack.len, $i.stack[i.stack.len - 1]] + +proc minRepl*(i: var MinInterpreter) = + i.stdLib() + var s = newStringStream("") + i.open(s, "") + var line: string + #echo "$1 v$2" % [appname, version] + var ed = initEditor(historyFile = MINIMHISTORY) + while true: + let symbols = toSeq(i.scope.symbols.keys) + ed.completionCallback = proc(ed: LineEditor): seq[string] = + return ed.getCompletions(symbols) + # evaluate prompt + i.apply(i.scope.getSymbol("prompt")) + var v: MinValue + i.reqString(v) + let prompt = v.getString() + line = ed.readLine(prompt) + i.parser.buf = $i.parser.buf & $line + i.parser.bufLen = i.parser.buf.len + discard i.parser.getToken() + try: + i.printResult i.interpret() + except: + discard + +proc minRepl*() = + var i = newMinInterpreter() + i.minRepl + +when isMainModule: + + var REPL = false + + let usage* = """ $1 v$2 - a tiny concatenative shell and programming language + (c) 2014-2017 Fabio Cevasco + + Usage: + min [options] [filename] + + Arguments: + filename A $1 file to interpret (default: STDIN). + Options: + -e, --evaluate Evaluate a $1 program inline + -h, --help Print this help + -v, --version Print the program version + -i, --interactive Start $1 shell""" % [appname, version] + + var file, s: string = "" + setLogFilter(lvlNotice) + + for kind, key, val in getopt(): + case kind: + of cmdArgument: + file = key + of cmdLongOption, cmdShortOption: + case key: + of "log", "l": + var val = val + setLogLevel(val) + of "evaluate", "e": + s = val + of "help", "h": + echo usage + quit(0) + of "version", "v": + echo version + quit(0) + of "interactive", "i": + REPL = true + else: + discard + else: + discard + + if s != "": + minString(s) + elif file != "": + minFile file + elif REPL: + minRepl() + quit(0) + else: + minFile stdin, "stdin"
A min.vim

@@ -0,0 +1,58 @@

+" Vim syntax file +" Language: min +" Maintainer: Fabio Cevasco +" Last Change: 11 November 2016 +" Version: 0.3.0 + +if exists("b:current_syntax") + finish +endif + +setl iskeyword=@,36-39,+,-,/,*,.,:,~,!,48-57,60-65,94-95,192-255 +setl iskeyword+=^ + +syntax keyword minDefaultSymbol ! != $ & ' * + # - % ^ -> . .. / : < <= == => =~ > >= @ ROOT aes and append ask at atime b bind bool bool? bury1 bury2 bury3 c call call! capitalize case cd chmod choose clear-stack column-print concat confirm cons cp cpu crypto ctime datetime ddel debug decode decrypt define delete dget dictionary? dig1 dig2 dig3 dip dir? dirname div dprint dprint! dset dump-stack dup dupd encode encrypt env? error eval even? exit fappend fatal file? filename filter first float float? foreach fperms fread from-json format-error fs fsize fstats ftype fwrite gets get-stack getenv hardlink hidden? ifte import indent info inspect int int? interpolate interval io join k keys length linrec load load-symbol logic loglevel loglevel? lowercase ls ls-r map match md5 mkdir mod module mtime mv newline not notice now num number? odd? os password pop popd pred print print! prompt publish puts puts! putenv q quotation? quote quote-bind quote-define raise regex remove-symbol repeat replace rest rm rmdir run save-symbol scope scope? seal search set-stack sha1 sha224 sha256 sha384 sha512 sigils sip sleep sort source split startup stored-symbols str string string? strip succ swap swapd swons symbols symlink symlink? sys system take tformat time timeinfo times timestamp titleize to-json try unquote uppercase unzip values version warn which while with xor zip contains + + +syntax match minDefaultSigil ;\<[:@'~!$%&$=<>#^*#+/]; contained +syntax match minSpecialSymbols ;[:@'~!$%&$=<>#^*#+/]; contained +syntax match minQuote ;\<[']; +syntax match minQuotedBinding ;#; +syntax match minBinding ;@; + +syntax keyword minCommentTodo TODO FIXME XXX TBD contained +syntax match minComment /;.*$/ contains=minCommentTodo + +syntax match minNumber ;[-+]\=\d\+\(\.\d*\)\=; +syntax keyword minBoolean true false +syntax region minString start=+"+ skip=+\\\\\|\\$"+ end=+"+ + +syntax region minSigilSymbol start=;\<[:@'~!$%&$=<>^*#+/]; end=;\>; contains=minDefaultSigil +syntax region minQuotedSymbol start=;\<[']; end=;\>; contains=minQuote +syntax region minBoundSymbol start=;@; end=;\>; contains=minBinding +syntax region minQuotedBoundSymbol start=;#; end=;\>; contains=minQuotedBinding +syntax match minSymbol ;[a-zA-Z0-9+._-][a-zA-Z0-9/!?+*._-]*; + +syntax match minParen ;(\|); + + + +" Highlighting +hi default link minComment Comment +hi default link minCommentTodo Todo +hi default link minString String +hi default link minSigilSymbol String +hi default link minNumber Number +hi default link minBoolean Boolean +hi default link minDefaultSymbol Statement +hi default link minQuote Delimiter +hi default link minBinding Delimiter +hi default link minQuotedBinding Delimiter +hi default link minDefaultSigil Delimiter +hi default link minSymbol Identifier +hi default link minQuotedSymbol Special +hi default link minBoundSymbol Special +hi default link minQuotedBoundSymbol Special +hi default link minParen Special + +let b:current_syntax = "min"
D minim.nim

@@ -1,253 +0,0 @@

-import - streams, - critbits, - parseopt2, - strutils, - os, - json, - sequtils, - algorithm, - logging -import - packages/nimline/nimline, - packages/niftylogger, - core/consts, - core/parser, - core/value, - core/scope, - core/interpreter, - core/utils -import - lib/min_lang, - lib/min_num, - lib/min_str, - lib/min_logic, - lib/min_time, - lib/min_io, - lib/min_sys, - lib/min_crypto, - lib/min_fs - -export - parser, - interpreter, - utils, - niftylogger, - value, - scope, - min_lang - -const PRELUDE* = "prelude.min".slurp.strip - -newNiftyLogger().addHandler() -newRollingFileLogger(MINIMLOG, fmtStr = verboseFmtStr).addHandler() - -proc getExecs(): seq[string] = - var res = newSeq[string](0) - let getFiles = proc(dir: string) = - for c, s in walkDir(dir, true): - if (c == pcFile or c == pcLinkToFile) and not res.contains(s): - res.add s - getFiles(getCurrentDir()) - for dir in "PATH".getEnv.split(PathSep): - getFiles(dir) - res.sort(system.cmp) - return res - -proc getCompletions(ed: LineEditor, symbols: seq[string]): seq[string] = - var words = ed.lineText.split(" ") - var word: string - if words.len == 0: - word = ed.lineText - else: - word = words[words.len-1] - if word.startsWith("'"): - return symbols.mapIt("'" & $it) - elif word.startsWith("~"): - return symbols.mapIt("~" & $it) - if word.startsWith("@"): - return symbols.mapIt("@" & $it) - if word.startsWith("#"): - return symbols.mapIt("#" & $it) - if word.startsWith(">"): - return symbols.mapIt(">" & $it) - if word.startsWith("*"): - return symbols.mapIt("*" & $it) - if word.startsWith("("): - return symbols.mapIt("(" & $it) - if word.startsWith("<"): - return toSeq(MINIMSYMBOLS.readFile.parseJson.pairs).mapIt("<" & $it[0]) - if word.startsWith("$"): - return toSeq(envPairs()).mapIt("$" & $it[0]) - if word.startsWith("!"): - return getExecs().mapIt("!" & $it) - if word.startsWith("&"): - return getExecs().mapIt("&" & $it) - if word.startsWith("\""): - var f = word[1..^1] - if f == "": - f = getCurrentDir().replace("\\", "/") - return toSeq(walkDir(f, true)).mapIt("\"$1" % it.path.replace("\\", "/")) - elif f.dirExists: - f = f.replace("\\", "/") - if f[f.len-1] != '/': - f = f & "/" - return toSeq(walkDir(f, true)).mapIt("\"$1$2" % [f, it.path.replace("\\", "/")]) - else: - var dir: string - if f.contains("/") or dir.contains("\\"): - dir = f.parentDir - let file = f.extractFileName - return toSeq(walkDir(dir, true)).filterIt(it.path.toLowerAscii.startsWith(file.toLowerAscii)).mapIt("\"$1/$2" % [dir, it.path.replace("\\", "/")]) - else: - dir = getCurrentDir() - return toSeq(walkDir(dir, true)).filterIt(it.path.toLowerAscii.startsWith(f.toLowerAscii)).mapIt("\"$1" % [it.path.replace("\\", "/")]) - return symbols - -proc stdLib*(i: In) = - if not MINIMSYMBOLS.fileExists: - MINIMSYMBOLS.writeFile("{}") - if not MINIMHISTORY.fileExists: - MINIMHISTORY.writeFile("") - if not MINIMRC.fileExists: - MINIMRC.writeFile("") - i.lang_module - i.io_module - i.logic_module - i.num_module - i.str_module - i.sys_module - i.time_module - i.fs_module - i.crypto_module - i.eval PRELUDE, "<prelude>" - i.eval MINIMRC.readFile() - -proc interpret*(i: In, s: Stream) = - i.stdLib() - i.open(s, i.filename) - discard i.parser.getToken() - try: - i.interpret() - except: - discard - i.close() - -proc minimStream(s: Stream, filename: string) = - var i = newMinInterpreter() - i.pwd = filename.parentDir - i.interpret(s) - -proc minimString*(buffer: string) = - minimStream(newStringStream(buffer), "input") - -proc minimFile*(filename: string) = - var stream = newFileStream(filename, fmRead) - if stream == nil: - fatal("Cannot read from file: "& filename) - quit(3) - minimStream(stream, filename) - -proc minimFile*(file: File, filename="stdin") = - var stream = newFileStream(stdin) - if stream == nil: - fatal("Cannot read from file: "& filename) - quit(3) - minimStream(stream, filename) - -proc printResult(i: In, res: MinValue) = - if res.isNil: - return - if i.stack.len > 0: - let n = $i.stack.len - if res.isQuotation and res.qVal.len > 1: - echo "{$1} -> (" % n - for item in res.qVal: - echo " " & $item - echo " ".repeat(n.len) & " )" - else: - echo "{$1} -> $2" % [$i.stack.len, $i.stack[i.stack.len - 1]] - -proc minimRepl*(i: var MinInterpreter) = - i.stdLib() - var s = newStringStream("") - i.open(s, "") - var line: string - #echo "$1 v$2" % [appname, version] - var ed = initEditor(historyFile = MINIMHISTORY) - while true: - let symbols = toSeq(i.scope.symbols.keys) - ed.completionCallback = proc(ed: LineEditor): seq[string] = - return ed.getCompletions(symbols) - # evaluate prompt - i.apply(i.scope.getSymbol("prompt")) - var v: MinValue - i.reqString(v) - let prompt = v.getString() - line = ed.readLine(prompt) - i.parser.buf = $i.parser.buf & $line - i.parser.bufLen = i.parser.buf.len - discard i.parser.getToken() - try: - i.printResult i.interpret() - except: - discard - -proc minimRepl*() = - var i = newMinInterpreter() - i.minimRepl - -when isMainModule: - - var REPL = false - - let usage* = """ $1 v$2 - a tiny concatenative shell and programming language - (c) 2014-2017 Fabio Cevasco - - Usage: - minim [options] [filename] - - Arguments: - filename A $1 file to interpret (default: STDIN). - Options: - -e, --evaluate Evaluate a $1 program inline - -h, --help Print this help - -v, --version Print the program version - -i, --interactive Start $1 shell""" % [appname, version] - - var file, s: string = "" - setLogFilter(lvlNotice) - - for kind, key, val in getopt(): - case kind: - of cmdArgument: - file = key - of cmdLongOption, cmdShortOption: - case key: - of "log", "l": - var val = val - setLogLevel(val) - of "evaluate", "e": - s = val - of "help", "h": - echo usage - quit(0) - of "version", "v": - echo version - quit(0) - of "interactive", "i": - REPL = true - else: - discard - else: - discard - - if s != "": - minimString(s) - elif file != "": - minimFile file - elif REPL: - minimRepl() - quit(0) - else: - minimFile stdin, "stdin"
M minim.nimblemin.nimble

@@ -1,10 +1,10 @@

[Package] -name = "minim" +name = "min" version = "0.3.0" author = "Fabio Cevasco" description = "A tiny concatenative programming language and shell." license = "MIT" -bin = "minim" +bin = "min" [Deps] requires: "nim >= 0.15.0"
D minim.vim

@@ -1,58 +0,0 @@

-" Vim syntax file -" Language: MiNiM -" Maintainer: Fabio Cevasco -" Last Change: 11 November 2016 -" Version: 0.3.0 - -if exists("b:current_syntax") - finish -endif - -setl iskeyword=@,36-39,+,-,/,*,.,:,~,!,48-57,60-65,94-95,192-255 -setl iskeyword+=^ - -syntax keyword minimDefaultSymbol ! != $ & ' * + # - % ^ -> . .. / : < <= == => =~ > >= @ ROOT aes and append ask at atime b bind bool bool? bury1 bury2 bury3 c call call! capitalize case cd chmod choose clear-stack column-print concat confirm cons cp cpu crypto ctime datetime ddel debug decode decrypt define delete dget dictionary? dig1 dig2 dig3 dip dir? dirname div dprint dprint! dset dump-stack dup dupd encode encrypt env? error eval even? exit fappend fatal file? filename filter first float float? foreach fperms fread from-json format-error fs fsize fstats ftype fwrite gets get-stack getenv hardlink hidden? ifte import indent info inspect int int? interpolate interval io join k keys length linrec load load-symbol logic loglevel loglevel? lowercase ls ls-r map match md5 mkdir mod module mtime mv newline not notice now num number? odd? os password pop popd pred print print! prompt publish puts puts! putenv q quotation? quote quote-bind quote-define raise regex remove-symbol repeat replace rest rm rmdir run save-symbol scope scope? seal search set-stack sha1 sha224 sha256 sha384 sha512 sigils sip sleep sort source split startup stored-symbols str string string? strip succ swap swapd swons symbols symlink symlink? sys system take tformat time timeinfo times timestamp titleize to-json try unquote uppercase unzip values version warn which while with xor zip contains - - -syntax match minimDefaultSigil ;\<[:@'~!$%&$=<>#^*#+/]; contained -syntax match minimSpecialSymbols ;[:@'~!$%&$=<>#^*#+/]; contained -syntax match minimQuote ;\<[']; -syntax match minimQuotedBinding ;#; -syntax match minimBinding ;@; - -syntax keyword minimCommentTodo TODO FIXME XXX TBD contained -syntax match minimComment /;.*$/ contains=minimCommentTodo - -syntax match minimNumber ;[-+]\=\d\+\(\.\d*\)\=; -syntax keyword minimBoolean true false -syntax region minimString start=+"+ skip=+\\\\\|\\$"+ end=+"+ - -syntax region minimSigilSymbol start=;\<[:@'~!$%&$=<>^*#+/]; end=;\>; contains=minimDefaultSigil -syntax region minimQuotedSymbol start=;\<[']; end=;\>; contains=minimQuote -syntax region minimBoundSymbol start=;@; end=;\>; contains=minimBinding -syntax region minimQuotedBoundSymbol start=;#; end=;\>; contains=minimQuotedBinding -syntax match minimSymbol ;[a-zA-Z0-9+._-][a-zA-Z0-9/!?+*._-]*; - -syntax match minimParen ;(\|); - - - -" Highlighting -hi default link minimComment Comment -hi default link minimCommentTodo Todo -hi default link minimString String -hi default link minimSigilSymbol String -hi default link minimNumber Number -hi default link minimBoolean Boolean -hi default link minimDefaultSymbol Statement -hi default link minimQuote Delimiter -hi default link minimBinding Delimiter -hi default link minimQuotedBinding Delimiter -hi default link minimDefaultSigil Delimiter -hi default link minimSymbol Identifier -hi default link minimQuotedSymbol Special -hi default link minimBoundSymbol Special -hi default link minimQuotedBoundSymbol Special -hi default link minimParen Special - -let b:current_syntax = "minim"