all repos — min @ 0ac8cc0c321b06ef34b673ff67588beae06ab87a

A small but practical concatenative programming language.

refactor(OutOfBounds) Implemented bound checking.
h3rald h3rald@h3rald.com
Sun, 12 Jun 2016 12:14:03 +0200
commit

0ac8cc0c321b06ef34b673ff67588beae06ab87a

parent

06408cd2b958fccdc8937ecf03f483a820388429

5 files changed, 53 insertions(+), 29 deletions(-)

jump to
M core/types.nimcore/types.nim

@@ -85,6 +85,7 @@ MinParsingError* = ref object of ValueError

MinUndefinedError* = ref object of ValueError MinInvalidError* = ref object of ValueError MinEmptyStackError* = ref object of ValueError + MinOutOfBoundsError* = ref object of ValueError MinRuntimeError* = ref object of SystemError qVal*: seq[MinValue]
M core/utils.nimcore/utils.nim

@@ -97,6 +97,9 @@

proc raiseUndefined*(msg: string) = raise MinUndefinedError(msg: msg) +proc raiseOutOfBounds*(msg: string) = + raise MinOutOfBoundsError(msg: msg) + proc raiseRuntime*(msg: string, qVal: var seq[MinValue]) = raise MinRuntimeError(msg: msg, qVal: qVal)
M lib/lang.nimlib/lang.nim

@@ -202,12 +202,12 @@ finally:

if hasFinally: i.unquote("<try-finally>", final) - .symbol("counquote") do (i: In): + .symbol("multiunquote") do (i: In): var q: MinValue i.reqQuotation q let stack = i.copystack proc coroutine(i: MinInterpreter, c: int, results: ptr MinStack) {.routine.} = - i.unquote("<counquote>", q.qVal[c]) + i.unquote("<multiunquote>", q.qVal[c]) results[][c] = i.stack[0] var results = newSeq[MinValue](q.qVal.len) for c in 0..q.qVal.high:

@@ -253,16 +253,24 @@ .symbol("first") do (i: In):

var q: MinValue i.reqStringOrQuotation q if q.isQuotation: + if q.qVal.len == 0: + raiseOutOfBounds("Quotation is empty") i.push q.qVal[0] elif q.isString: + if q.strVal.len == 0: + raiseOutOfBounds("String is empty") i.push newVal($q.strVal[0]) .symbol("rest") do (i: In): var q: MinValue i.reqStringOrQuotation q if q.isQuotation: + if q.qVal.len == 0: + raiseOutOfBounds("Quotation is empty") i.push newVal(q.qVal[1..q.qVal.len-1]) elif q.isString: + if q.strVal.len == 0: + raiseOutOfBounds("String is empty") i.push newVal(q.strVal[1..q.strVal.len-1]) .symbol("quote") do (i: In):

@@ -291,6 +299,8 @@

.symbol("at") do (i: In): var index, q: MinValue i.reqIntAndQuotation index, q + if q.qVal.len-1 < index.intVal: + raiseOutOfBounds("Insufficient items in quotation") i.push q.qVal[index.intVal] .symbol("size") do (i: In):

@@ -320,6 +330,8 @@

.symbol("times") do (i: In): var t, prog: MinValue i.reqIntAndQuotation t, prog + if t.intVal < 1: + raiseInvalid("A non-zero natural number is required") for c in 1..t.intVal: i.unquote("<times-quotation>", prog)
M lib/prelude.minlib/prelude.min

@@ -20,31 +20,33 @@ (load) (@) sigil

(":" split call) (%) sigil ; Aliases -'define :: -'bind :. -'import :# -'exit :quit -'== :eq -'!= :noteq -'> :gt -'< :lt -'>= :gte -'<= :lte -'put :echo -'system :! -'run :& -'getenv :$ -'pop :zap -'quote :unit -'quote :' -'unquote :i -'unquote :apply -'unquote :-> -'scope :=> -'filter :select -'clear :empty -'cons :prepend -'size :length +'define :: +'bind :. +'import :# +'exit :quit +'== :eq +'!= :noteq +'> :gt +'< :lt +'>= :gte +'<= :lte +'put :echo +'system :! +'run :& +'getenv :$ +'pop :zap +'quote :unit +'quote :' +'unquote :i +'unquote :apply +'unquote :-> +'multiunquote :multiapply +'multiunquote :->> +'scope :=> +'filter :select +'clear :empty +'cons :prepend +'size :length ; Mathematical Operators (1 +) :succ
M tests/lang.mintests/lang.min

@@ -3,7 +3,7 @@ #test

"lang" describe - (symbols size 163 ==) assert + (symbols size 165 ==) assert (sigils size 10 ==) assert

@@ -101,12 +101,18 @@ (1 at)

) try "Test Message" ==) assert ( + ( + (() 1 at) + (1) + ) try 1 ==) assert + + ( ((dup 0 ==) (1 +) (dup 1 -) ( * ) linrec) :factorial ( (8 factorial) (12 factorial) (9 factorial) - ) counquote (40320 479001600 362880) ==) assert + ) ->> (40320 479001600 362880) ==) assert report ; Tidy up