Skip to content

Commit

Permalink
Merge pull request #137 from JoeStrout/v1.6.2
Browse files Browse the repository at this point in the history
Updated README with correct build instructions;
  • Loading branch information
JoeStrout authored Feb 21, 2024
2 parents 25ca9a0 + 9134d7f commit 8cb1f66
Show file tree
Hide file tree
Showing 7 changed files with 246 additions and 32 deletions.
4 changes: 2 additions & 2 deletions MiniScript-cpp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ MiniScript is built with [CMake](https://cmake.org/). You can generate your desi

3. `cmake ../..` (or on Windows, `cmake ..\..`) to generate a makefile and related files in the build directory.

4. `cmake --build .` to actually do the build.
4. `cmake --build . --config Release` to actually do the build.

If successful, you should find an executable called `miniscript` which you can install (see **Installation**, below). You'll also find a shared library (libminiscript-cpp.a) for you to link to in your own projects if you like. You can even `include()` the CMakeLists.txt of this project inside your own for clean dependency management.
If successful, you should find an executable called `miniscript` (or `miniscript.exe` on Windows) which you can install (see **Installation**, below). You'll also find a shared library (libminiscript-cpp.a, miniscript-cpp.lib, or similar) for you to link to in your own projects if you like. You can even `include()` the CMakeLists.txt of this project inside your own for clean dependency management.

If you are only interested in the C# edition of MiniScript, there is a project file provided in the respective directory.

Expand Down
118 changes: 118 additions & 0 deletions MiniScript-cpp/lib/listUtil.ms
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,21 @@ list.contains = function(item)
return self.indexOf(item) != null
end function

// lastIndexOf: returns the *last* index of the given element, optionally
// before a given index. Returns null if not found.
// Examples:
// [7,4,7,9].lastIndexOf(7) // returns 2
// [7,4,7,9].lastIndexOf(7, 2) // returns 0
list.lastIndexOf = function(element, beforeIdx=null)
if beforeIdx == null then i = self.len - 1 else i = beforeIdx - 1
while i >= 0
if self[i] == element then return i
i -= 1
end while
return null
end function


// split: similar to string.split, this splits a list into sub-lists
// by where the given delimiter element is found.
list.split = function(delimiter, maxCount=null)
Expand Down Expand Up @@ -161,13 +176,32 @@ list.apply = function(func)
end for
end function
// applied: like list.apply, but returns the result as a new list,
// without changing the list it is called on.
// Example:
// x = [1.1, 1.9, 3.45]
// y = x.applied(@round) // y is now [1, 2, 3]; x is unchanged
list.applied = function(func)
result = self[:]
result.apply @func
return result
end function
// apply1: same as apply, but takes 1 extra argument.
list.apply1 = function(func, arg1)
for i in self.indexes
self[i] = func(self[i], arg1)
end for
end function
// applied1: like list.apply1, but returns the result as a new list,
// without changing the list it is called on.
list.applied1 = function(func, arg1)
result = self[:]
result.apply1 @func, arg1
return result
end function
// mean: return the average (sum divided by number of values)
list.mean = function
return self.sum / self.len
Expand Down Expand Up @@ -273,6 +307,17 @@ list.filter = function(func)
end if
end function
// filter1: like list.filter, but takes 1 extra argument for the
// filter function. Note that func must be an actual function,
// and not just the name of a map key in this case.
list.filter1 = function(func, arg1)
i = self.len - 1
while i >= 0
if not func(self[i], arg1) then self.remove i
i = i - 1
end while
end function
// filtered: return a new list containing only the elements of self where
// the given function is true. As with filter, you may also specify the
// name of a map key to look up in each element of the self.
Expand All @@ -291,6 +336,54 @@ list.filtered = function(func)
return result
end function
// filtered1: like list.filter, but takes an additional argument
// for the filter function.
list.filtered1 = function(func, arg1)
result = []
for elem in self
if func(elem, arg1) then result.push elem
end for
return result
end function
// compress: replace each run of a given value with a single instance
// of that value (in place).
// Example:
// x = [5,7,7,9,7,7,7]; x.compress(7) // x is now [5,7,9,7]
list.compress = function(valueToCompress)
i = self.len - 1
compressing = false
while i >= 0
if self[i] == valueToCompress then
if compressing then self.remove i else compressing = true
else
compressing = false
end if
i -= 1
end while
end function
// compressed: return a new list that has run of a given value
// replaced with a single instance of that value.
// Example:
// x = [5,7,7,9,7,7,7]; x.compress(7) // x is now [5,7,9,7]
list.compressed = function(valueToCompress)
result = []
compressing = false
for value in self
if value == valueToCompress then
if not compressing then
result.push value
compressing = true
end if
else
compressing = false
result.push value
end if
end for
return result
end function
// valuesOf: operates on a list of maps (or other indexable type), and pulls
// out the value of the given index for every element in the list, returning
// theses as a new list in the same order.
Expand Down Expand Up @@ -374,6 +467,15 @@ runUnitTests = function
end if
end function
assertEqual [7,4,7,9].lastIndexOf(7), 2, "lastIndexOf"
assertEqual [7,4,7,9].lastIndexOf(7,2), 0, "lastIndexOf"
assertEqual [7,4,7,9].lastIndexOf(7,0), null, "lastIndexOf"
a = [5,7,7,9,7,7,7]
assertEqual a.compressed(7), [5,7,9,7], "compressed"
assertEqual a, [5,7,7,9,7,7,7], "compressed changed self"
a.compress(7); assertEqual a, [5,7,9,7], "compress"
a = [-1, 42, -1, 53, 87, 345, -1, 100]
assertEqual a.split(-1), [ [], [42], [53, 87, 345], [100] ]
assertEqual a.split(-1, 3), [ [], [42], [53, 87, 345, -1, 100] ]
Expand Down Expand Up @@ -410,6 +512,13 @@ runUnitTests = function
a.apply1 @round, 2
assertEqual a, [1.10, 1.90, 3.45], "apply1"
a = [1.1, 1.899, 3.452]
b = a.applied(@round)
assertEqual b, [1, 2, 3], "applied"
b = a.applied1(@round, 2)
assertEqual b, [1.10, 1.90, 3.45], "applied1"
assertEqual a, [1.1, 1.899, 3.452], "applied/applied1"
a = range(1, 10)
isEven = function(x)
return x % 2 == 0
Expand All @@ -421,6 +530,15 @@ runUnitTests = function
assertEqual a, range(1, 10), "filtered"
assertEqual b, [2, 4, 6, 8, 10], "filtered"
moreThan = function(a, b); return a > b; end function
a = range(1,10)
a.filter1 @moreThan, 7
assertEqual a, [8, 9, 10], "filter1"
a = range(1,10)
b = a.filtered1(@moreThan, 7)
assertEqual a, range(1, 10), "filtered1"
assertEqual b, [8, 9, 10], "filtered1"
a = [{"x":42, "keep":true}, {"x":123, "keep":false}, {"x":0, "keep":true}]
a.filter "keep"
assertEqual a, [{"x":42, "keep":true}, {"x":0, "keep":true}], "filter by key"
Expand Down
7 changes: 5 additions & 2 deletions MiniScript-cpp/lib/mapUtil.ms
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
map.get = function(key, defaultValue=null)
m = self
while m
if m.hasIndex(key) then return m[key]
if m.hasIndex(@key) then return m[@key]
if not m.hasIndex("__isa") then break
m = m.__isa
end while
Expand Down Expand Up @@ -119,12 +119,15 @@ runUnitTests = function
end if
end function

d = {"one":"ichi", "two":"ni", "three":"san", "four":"shi", "five":"go"}
d = {"one":"ichi", "two":"ni", "three":"san", "four":"shi", "five":"go", @print: "six"}

testing = "get"
assertEqual d.get("one", 1), "ichi"
assertEqual d.get("ten", 10), 10
assertEqual d.get("twenty"), null
assertEqual d.get(@print), "six"

d.remove @print

testing = "hasValue"
assertEqual d.hasValue("ni"), true
Expand Down
58 changes: 43 additions & 15 deletions MiniScript-cpp/lib/mathUtil.ms
Original file line number Diff line number Diff line change
Expand Up @@ -135,21 +135,43 @@ clamp = function(x, minval=0, maxval=1)
return x
end function

// max: returns the greater of two values.
// (Note: if you have more than two, consider importing listUtil
// and using list.max instead.)
max = function(a, b)
if b > a then return b else return a
end function

// min: returns the lesser of two values.
// (As above, also consider list.min from listUtil.)
min = function(a, b)
if b < a then return b else return a
end function

// numToStr: converts a number to a string, with a specified precision
// (number of digits past the decimal place). Trailing zeros will be
// added as needed to get the decimal point at the right place.
numToStr = function(n, precision=null)
if precision == null then return str(n)
s = str(round(n, precision))
if precision > 0 then
dotPos = s.indexOf(".")
if dotPos == null then
s = s + "." + "0" * precision
else if dotPos > s.len - precision - 1 then
s = s + "0" * (dotPos - s.len + precision + 1)
end if
if not n isa number or not precision isa number then
print "numToStr error: arguments must be numbers."
return
end if
return s
if precision <= 0 or n == 1/0 or n == -1/0 or n != n then return str(round(n, precision))
negative = n < 0; n = abs(n)
digits = [floor(n)]
for i in range(1, precision)
d = floor(n * 10^i) % 10
digits.push d
end for
if (n * 10^precision) % 1 >= 0.5 then
for i in range(digits.len - 1)
digits[i] += 1
if digits[i] < 10 or i == 0 then break
digits[i] = 0
end for
end if
return "-" * negative + digits.pull + "." + digits.join("")
end function

runUnitTests = function
Expand All @@ -175,12 +197,18 @@ runUnitTests = function
assertEqual mover.y, 30, "moveTowardsXY"
assertEqual moveTowardsXY(mover, target, 10), false

assertEqual numToStr(pi, 2), "3.14"
assertEqual numToStr(1.23, 3), "1.230"
assertEqual numToStr(1.23), "1.23"
assertEqual numToStr(12345.67, -2), "12300"
assertEqual numToStr(2, 3), "2.000"

assertEqual numToStr(pi, 2), "3.14", "numToStr"
assertEqual numToStr(pi, 4), "3.1416", "numToStr"
assertEqual numToStr(pi, 12), "3.141592653590", "numToStr"
assertEqual numToStr(1.23, 3), "1.230", "numToStr"
assertEqual numToStr(1.23), "1.23", "numToStr"
assertEqual numToStr(12345.67, -2), "12300", "numToStr"
assertEqual numToStr(2, 3), "2.000", "numToStr"
assertEqual numToStr(2/3, 12), "0.666666666667", "numToStr"
assertEqual numToStr(41.9999, 2), "42.00", "numToStr"
assertEqual numToStr(42 - 1E-12, 5), "42.00000", "numToStr"
assertEqual numToStr(-pi, 4), "-3.1416", "numToStr"

if errorCount == 0 then
print "All tests passed. Woot!"
else
Expand Down
32 changes: 24 additions & 8 deletions MiniScript-cpp/lib/matrixUtil.ms
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ end function
// Instance methods: call these on a Matrix instance.
//----------------------------------------------------------------------
// m.size: return [rows, columns] size of the matrix
Matrix.size = function
return [self.rows, self.columns]
end function
// m.row: return the given row of matrix m as a single-row matrix.
Matrix.row = function(zeroBasedRowNum)
return Matrix.fromList(self.elem[zeroBasedRowNum])
Expand Down Expand Up @@ -197,6 +202,11 @@ Matrix.times = function(m2)
if m2 isa Matrix then m2 = m2.elem
if m2 isa list then
// matrix multiplication
if m2.len != self.columns then
print "Matrix.times error: incompatible sizes " +
self.size + " and " + [m2.len, len(m2[0])]
exit
end if
result = Matrix.ofSize(self.rows, m2[0].len)
for r in result.rowRange
resultRow = result.elem[r]
Expand Down Expand Up @@ -246,26 +256,32 @@ Matrix.equals = function(m2)
return self.elem == m2elems
end function
// Matrix.round: rounds all numbers in the matrix.
Matrix.round = function(decimalPlaces=0)
for row in self.elem
for i in row.indexes
row[i] = round(row[i], decimalPlaces)
end for
end for
end function
// Matrix.print: prints matrix data, with some formatting options.
// fieldWidth: minimum number of characters for each element
// precision: if non-null, round each element to this many digits
// columnSep: extra string printed between elements within a row
// rowSep: extra string printed between rows; defaults to text.delimiter
Matrix.print = function(fieldWidth=10, precision=null, columnSep="", rowSep=null)
oldDelim = text.delimiter; text.delimiter = ""
if rowSep == null then rowSep = oldDelim
if rowSep == null then rowSep = text.delimiter
for row in self.elem
firstInRow = true
line = []
for elem in row
s = mathUtil.numToStr(elem, precision)
if s.len >= fieldWidth and s.indexOf(".") != null then s = s[:fieldWidth-1]
if s.len < fieldWidth then s = " "*(fieldWidth-s.len) + s
if not firstInRow then print columnSep
print s
firstInRow = false
line.push s
end for
print rowSep
print line.join(columnSep), rowSep
end for
text.delimiter = oldDelim
end function
Expand Down
12 changes: 7 additions & 5 deletions MiniScript-cpp/lib/qa.ms
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ end function
// assertEqual: abort if the first two parameters are not equal.
// Additional descriptive note is optional.
assertEqual = function(actual, expected, note)
if actual == expected then return
if @actual == @expected then return
msg = "Assert failed"
if note != null then msg = msg + " (" + note + ")"
msg = msg + ": expected `" + expected + "`, but got `" + actual + "`"
msg = msg + ": expected `" + @expected + "`, but got `" + @actual + "`"
abort msg
end function

Expand All @@ -50,7 +50,9 @@ typeOf = function(value)
if value isa map then
mapType = value
if value.hasIndex("__isa") then mapType = value.__isa
if namedMaps.hasIndex(mapType) then return namedMaps[mapType]
for kv in namedMaps
if refEquals(kv.key, mapType) then return kv.value
end for
return "map"
end if
return "unknown"
Expand All @@ -59,11 +61,11 @@ end function
// assertType: abort if the first parameter is not of the specified type.
// Additional descriptive note is optional.
assertType = function(value, type, note)
if value isa type then return
if @value isa type then return
msg = "Assert failed"
if note != null then msg = msg + " (" + note + ")"
msg = msg + ": expected type " + namedMaps[type] +
", but got a " + typeOf(value) + " (" + value + ")"
", but got a " + typeOf(@value) + " (" + @value + ")"
abort msg
end function

Expand Down
Loading

0 comments on commit 8cb1f66

Please sign in to comment.