Skip to content

Commit

Permalink
Merge branch 'types_work'
Browse files Browse the repository at this point in the history
  • Loading branch information
lucteo committed Jul 8, 2019
2 parents cb8b6e3 + bbcc915 commit 276f0a5
Show file tree
Hide file tree
Showing 293 changed files with 19,289 additions and 22,393 deletions.
1 change: 0 additions & 1 deletion .travis/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,4 @@ echo "---------- Testing ----------"
cd ../tests

python test.py StdLib/RangesTest.spr --returnError
python test.py ../tools/formatTool.spr --returnError
python test.py --returnError
34 changes: 18 additions & 16 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ option(BOOTSTRAP_SPARROW "Use system-wide SparrowCompiler to compile Sparrow fil
message(STATUS "BOOTSTRAP_SPARROW: ${BOOTSTRAP_SPARROW}")
option(SPARROW_PROFILING "Enable Tracy integration into Sparrow compiler" OFF)
message(STATUS "SPARROW_PROFILING: ${SPARROW_PROFILING}")
option(ENABLE_TIDY "Enable clang-tidy checks when building" OFF)
message(STATUS "ENABLE_TIDY: ${ENABLE_TIDY}")

# Where to output the results of the compilation
set(OutDir ${CMAKE_CURRENT_SOURCE_DIR}/build/bin)
Expand Down Expand Up @@ -121,39 +123,39 @@ endif()

# Add target for clang-tidy
set(TIDY_CHECKS
#-*, # Disable for non-debug builds
-*, # Disable for non-debug builds

modernize-*,
bugprone-*,
cppcoreguidelines-*,
-cppcoreguidelines-owning-memory, # not met, requires gsl
-cppcoreguidelines-pro-bounds-array-to-pointer-decay, # not met, requires gsl
-cppcoreguidelines-pro-bounds-constant-array-index, # not met, requires gsl
-cppcoreguidelines-pro-bounds-pointer-arithmetic, # not met, requires gsl
-cppcoreguidelines-pro-type-union-access, # not met (we use some unions)
-cppcoreguidelines-pro-type-vararg, # not met (we are using printf)
)
string (REPLACE ";" " " TIDY_CHECKS "${TIDY_CHECKS}")

find_program(CLANG_TIDY_SCRIPT "run-clang-tidy.py" HINTS ${LLVM_TOOLS_BINARY_DIR}/../share/clang)
if(CLANG_TIDY_SCRIPT)
if(ENABLE_TIDY)
# Search for clang-tidy and clang-apply-replacements
find_program(CLANG_TIDY "clang-tidy" HINTS ${LLVM_TOOLS_BINARY_DIR})
find_program(CLANG_APPLY_REPLACEMENTS "clang-apply-replacements" HINTS ${LLVM_TOOLS_BINARY_DIR})

message(STATUS "Tidy checks: ${TIDY_CHECKS}")

set(TIDY_HEADER_FILTER ${CMAKE_SOURCE_DIR}/*)

# Set extra arguments
set(TIDY_FIX 0)
set(TIDY_EXTRA_ARGS -quiet -format -style file)
set(TIDY_FIX 1)
set(TIDY_EXTRA_ARGS -quiet;-format-style=file)
if (TIDY_FIX)
set(TIDY_EXTRA_ARGS ${TIDY_EXTRA_ARGS} -j 1 -fix)
set(TIDY_EXTRA_ARGS ${TIDY_EXTRA_ARGS};-fix)
endif()

# Actually add the target
add_custom_target(
clang-tidy
COMMAND
${CLANG_TIDY_SCRIPT} -header-filter='\.\.\/src\/.*\.hpp' -checks='${TIDY_CHECKS}'
-clang-tidy-binary ${CLANG_TIDY}
-clang-apply-replacements-binary ${CLANG_APPLY_REPLACEMENTS}
${TIDY_EXTRA_ARGS}
)
set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY};-checks=\"${TIDY_CHECKS}\";-header-filter='${TIDY_HEADER_FILTER}';${TIDY_EXTRA_ARGS}"
CACHE STRING "" FORCE)
else()
set(CMAKE_CXX_CLANG_TIDY "")
endif()

# Ensure generation of compile_commands.json; needed for clang-tidy
Expand Down
37 changes: 19 additions & 18 deletions SparrowImplicitLib/assert.spr
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ import std.vector, std.algorithms, std.string
/// Macro that creates the expansion of the assert/verify
fun _assertMacroBody(cond, message: AstNode): AstNode
// Extract information about the assert condition
var loc = cond location
var filename = loc.sourceCode filename
var lineNum: Int = loc.start.line
let loc = cond location
let filename = loc.sourceCode filename
let lineNum: Int = loc.start.line

// Extract the list of variables directly appearing the the expression
var varsList: Vector(AstNode)
Expand All @@ -60,38 +60,38 @@ import std.vector, std.algorithms, std.string
// Build the annotated expression string
// Walk over the list of variables, and if possible add the var value
// Print all the expression string in between
var expr: String = loc getCorrespondingCode
let expr: String = loc getCorrespondingCode
var lastIdx = 0
for i = 0..varsList.size
var v = varsList(i)
var vl = v location
let v = varsList(i)
let vl = v location
if vl.end.line != loc.start.line
break // Stop expanding variables when we are going on another line

var endPos = vl.end.col - loc.start.col
let endPos = vl.end.col - loc.start.col
if endPos != lastIdx
// Print the expression sting up until (and containing) the var
var exprPart = expr.subrange(lastIdx, endPos-lastIdx)
let exprPart = expr.subrange(lastIdx, endPos-lastIdx)
_addPrint(loc, prints, mkStringLiteral(loc, exprPart))

// Add a block for printing the value of the write
// Ensure that this is printable
var argsToEval = mkNodeList(loc)
addToNodeList(argsToEval, mkInfixOp(loc, "<<", mkIdentifier(loc, "cout"), v clone))
var cond = mkFunApplication(loc, mkIdentifier(loc, "isValid"), argsToEval)
let cond = mkFunApplication(loc, mkIdentifier(loc, "isValid"), argsToEval)
// if body
var varPrints: AstNode Vector
_addPrint(loc, varPrints, mkStringLiteral(loc, "[="))
_addPrint(loc, varPrints, v clone)
_addPrint(loc, varPrints, mkStringLiteral(loc, "]"))
var varPrintsBlock = mkLocalSpace(loc, varPrints.all)
let varPrintsBlock = mkLocalSpace(loc, varPrints.all)
// if statement
prints += mkIf(loc, cond, varPrintsBlock, AstNode(), true)
lastIdx = Int(endPos)
// Write the last part of the expression (if any)
var sz = expr size
let sz = expr size
if lastIdx < sz
var exprPart = expr.subrange(lastIdx, sz-lastIdx)
let exprPart = expr.subrange(lastIdx, sz-lastIdx)
_addPrint(loc, prints, mkStringLiteral(loc, exprPart))

// Now, the last part of the printing
Expand All @@ -101,22 +101,23 @@ import std.vector, std.algorithms, std.string
_addPrint(loc, prints, message)
_addPrint(loc, prints, mkStringLiteral(loc, "\n"))

var printsBlock = mkLocalSpace(loc, prints.all)
let printsBlock = mkLocalSpace(loc, prints.all)

// Build the resulting code:
// if !cond <printsBlock>
var res = mkIf(loc, mkPrefixOp(loc, "!", mkParenthesisExp(loc, cond)), printsBlock, AstNode())
let res = mkIf(loc, mkPrefixOp(loc, "!", mkParenthesisExp(loc, cond)), printsBlock, AstNode())
return res

/// Adds a print statement node to the destination vector
fun _addPrint(loc: Location, dest: @Vector(AstNode), toPrint: AstNode)
fun _addPrint(loc: Location, dest: !Vector(AstNode), toPrint: AstNode)
dest += mkInfixOp(loc, "<<", mkIdentifier(loc, "cout"), toPrint)

/// Extract all the variables from the given node
fun _extractVars(node: AstNode, varsList: @Vector(AstNode))
var nk = node nodeKind
fun _extractVars(node: AstNode, varsList: !Vector(AstNode))
let nk = node nodeKind
if nk == nkSparrowExpIdentifier
var exp = node explanation
node semanticCheck
let exp = node explanation
if (exp isSet) && (exp nodeKind) == nkFeatherExpVarRef
varsList += node
else
Expand Down
87 changes: 45 additions & 42 deletions SparrowImplicitLib/check.spr
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ datatype Gen(t: Type)
using ValueType = t
_generator: Function(t, UInt)

fun mkGen(t: Type, generator: @AnyType): Gen(t) if isValid(generator(UInt(0)))
concept _Generator(x) if isValid(x(UInt(0)))

fun mkGen(t: Type, generator: _Generator): Gen(t)
using FunType = Function(t, UInt)
return Gen(t)(FunType(generator))

fun ()(this: @Gen, sizeHint: UInt): ValueType = _generator(sizeHint)
fun ()(this: !Gen, sizeHint: UInt): ValueType = _generator(sizeHint)

fun isValid(this: @Gen): Bool = _generator isSet
fun isValid(this: Gen): Bool = _generator isSet

concept GenType(x) \
if typeOf(x.ValueType) == Type \
Expand All @@ -35,7 +37,7 @@ fun arbitrary(t: Type): t Gen if Integer(#$t)
datatype CheckConfig
numTests, maxAttempts: UInt
isVerbose: Bool
fun ctor(this: @CheckConfig)
fun ctor(this: !CheckConfig)
numTests = 100
maxAttempts = 5*numTests
isVerbose = false
Expand All @@ -50,7 +52,7 @@ datatype TestableValue(t: Type)
isTrivial: Bool
classifier: String

fun ctor(this: @TestableValue, value: @this.ValueType)
fun ctor(this: !TestableValue, value: this.ValueType)
this.value ctor value
this.isTrivial ctor false
this.classifier ctor ""
Expand All @@ -66,13 +68,13 @@ concept TestableValuesRange(x: Range) if (
//! This will extract values from the input range and applies the predicate on
//! them. Makes sure that the predicate holds for all these values. Reports the
//! statistics of running the tests.
fun check(values: TestableValuesRange, pred: @AnyType): Bool \
fun check(values: TestableValuesRange, pred: AnyType): Bool \
= check(values, pred, "") \
if !isValid(pred.v1)
fun check(values: TestableValuesRange, predMsg: @AnyType): Bool \
fun check(values: TestableValuesRange, predMsg: AnyType): Bool \
= check(values, predMsg.v1, predMsg.v2) \
if isValid(predMsg.v1)
fun check(values: TestableValuesRange, pred: @AnyType, msg: StringRef, config: CheckConfig = CheckConfig()): Bool
fun check(values: TestableValuesRange, pred: AnyType, msg: StringRef, config: CheckConfig = CheckConfig()): Bool
cout << "* Checking " << msg << endl
var classes: Map(String, UInt)

Expand Down Expand Up @@ -107,7 +109,7 @@ fun check(values: TestableValuesRange, pred: @AnyType, msg: StringRef, config: C
classes.remove("")
if !classes.isEmpty
for c = classes.keys
var percent = classes(c)*100/n
let percent = classes(c)*100/n
cout << percent << "% : " << c << endl
// TODO: sort the classes before displaying them

Expand All @@ -121,12 +123,12 @@ fun forAll(gen: GenType) = _Impl.ForAllGenerator(gen.ValueType)(gen)
fun forAll(r: Range) = _Impl.ForAllRangeGenerator(typeOf(r))(r)

//! Filter functionality - filters the testable values against the given predicate
fun forWhich(r: TestableValuesRange, pred: @AnyType) = _Impl.ForWhichRange(typeOf(r), typeOf(pred))(r, pred)
fun forWhich(r: TestableValuesRange, pred: AnyType) = _Impl.ForWhichRange(typeOf(r), typeOf(pred))(r, pred)

//! Sets the triviality of the testable values according to the result of the predicate
fun withTrivials(r: TestableValuesRange, pred: @AnyType) = _Impl.TrivialsRange(typeOf(r), typeOf(pred))(r, pred)
fun withTrivials(r: TestableValuesRange, pred: AnyType) = _Impl.TrivialsRange(typeOf(r), typeOf(pred))(r, pred)
//! Sets the classifier of the testable values according to the result of the predicate
fun withClassifier(r: TestableValuesRange, pred: @AnyType) = _Impl.ClassifierRange(typeOf(r), typeOf(pred))(r, pred)
fun withClassifier(r: TestableValuesRange, pred: AnyType) = _Impl.ClassifierRange(typeOf(r), typeOf(pred))(r, pred)

////////////////////////////////////////////////////////////////////////////////
// Combinators
Expand All @@ -143,8 +145,9 @@ fun elements(r: Range): r.RetType Gen = _Impl.ElementsGen(typeOf(r))(r).gen
//! Given a set of generators, this will randomly chose one of them
fun oneOf(gens: Range): gens.RetType if GenType(#$gens.RetType)
if gens.isEmpty return gens.RetType()
gens advance randBetween(0, (gens rangeSize))
return gens.front
var gensc = gens
gensc advance randBetween(0, (gens rangeSize))
return gensc.front

//! Same as oneOf, but for each generator we also have its frequency
fun frequency(gens: Range): typeOf((#$gens.RetType).v2) if FreqGenType(#$gens.RetType)
Expand All @@ -157,7 +160,7 @@ fun frequency(gens: Range): typeOf((#$gens.RetType).v2) if FreqGenType(#$gens.Re
if sum == 0 return typeOf((#$gens.RetType).v2)()

// Select a random number in the total sum of frequencies
var toSelect = randBetween(0, sum)
let toSelect = randBetween(0, sum)
// Select the right generator from the distribution
var curAcc = 0
for fg = gens
Expand All @@ -169,7 +172,7 @@ fun frequency(gens: Range): typeOf((#$gens.RetType).v2) if FreqGenType(#$gens.Re
fun randBetween(min, max: Integer): commonType(typeOf(min), typeOf(max))
using T = commonType(typeOf(min), typeOf(max))
using RAND_MAX = 0x7fffffff
var offset: T = T(Double(_Impl.rand()) / RAND_MAX * Double(max - min))
let offset: T = T(Double(_Impl.rand()) / RAND_MAX * Double(max - min))
return T(min) + offset

package _Impl
Expand All @@ -181,7 +184,7 @@ package _Impl

package NumericGen(t: Type) if SignedInteger(#$t)
fun gen(sizeHint: UInt): t
var h: Int = sizeHint + 3
let h: Int = sizeHint + 3
return t(randBetween(-h, h+1))

datatype ForAllGenerator(t: Type)
Expand All @@ -191,27 +194,27 @@ package _Impl
_gen: Gen(t)
_count: UInt

fun ctor(this, other: @ForAllGenerator)
fun ctor(this, other: !ForAllGenerator)
this._gen ctor other._gen
this._count ctor other._count

fun ctor(this: @ForAllGenerator, gen: @Gen(this._T))
fun ctor(this: !ForAllGenerator, gen: Gen(this._T))
this._gen ctor gen
this._count = 0

fun isEmpty(this: @ForAllGenerator) = !_gen.isValid
fun front(this: @ForAllGenerator): RetType = RetType(_gen(_count))
fun popFront(this: @ForAllGenerator) { ++_count }
fun isEmpty(this: ForAllGenerator) = !_gen.isValid
fun front(this: !ForAllGenerator): RetType = RetType(_gen(_count))
fun popFront(this: !ForAllGenerator) { ++_count }

[initCtor]
datatype ForAllRangeGenerator(rangeType: Type)
using RetType = TestableValue(rangeType.RetType)

_range: rangeType

fun isEmpty(this: @ForAllRangeGenerator) = _range.isEmpty
fun front(this: @ForAllRangeGenerator): RetType = RetType(_range.front)
fun popFront(this: @ForAllRangeGenerator) { _range.popFront }
fun isEmpty(this: ForAllRangeGenerator) = _range.isEmpty
fun front(this: !ForAllRangeGenerator): RetType = RetType(_range.front)
fun popFront(this: !ForAllRangeGenerator) { _range.popFront }

datatype ForWhichRange(rangeType, predType: Type) \
if typeOf((#$predType)((#$rangeType front).value)) == Bool
Expand All @@ -223,17 +226,17 @@ package _Impl
using _RangeType = rangeType
using _PredType = predType

fun ctor(this: @ForWhichRange, range: this._RangeType, pred: this._PredType)
fun ctor(this: !ForWhichRange, range: this._RangeType, pred: this._PredType)
this._range ctor range
this._pred ctor pred
this._lastVal ctor
this._popUntilValid

fun isEmpty(this: @ForWhichRange) = _range.isEmpty()
fun front(this: @ForWhichRange): RetType = _lastVal
fun popFront(this: @ForWhichRange) { _range.popFront(); this._popUntilValid }
fun isEmpty(this: ForWhichRange) = _range.isEmpty()
fun front(this: ForWhichRange): RetType = _lastVal
fun popFront(this: !ForWhichRange) { _range.popFront(); this._popUntilValid }

fun _popUntilValid(this: @ForWhichRange)
fun _popUntilValid(this: !ForWhichRange)
while !_range.isEmpty
_lastVal = _range.front()
if _pred(_lastVal.value)
Expand All @@ -248,10 +251,10 @@ package _Impl
_range: rangeType
_pred: predType

fun isEmpty(this: @TrivialsRange) = _range.isEmpty()
fun popFront(this: @TrivialsRange) { _range.popFront() }
fun front(this: @TrivialsRange): RetType
var res = _range.front
fun isEmpty(this: TrivialsRange) = _range.isEmpty()
fun popFront(this: !TrivialsRange) { _range.popFront() }
fun front(this: !TrivialsRange): RetType
let res = _range.front
res.isTrivial = _pred(res.value)
return res

Expand All @@ -263,10 +266,10 @@ package _Impl
_range: rangeType
_pred: predType

fun isEmpty(this: @ClassifierRange) = _range.isEmpty()
fun popFront(this: @ClassifierRange) { _range.popFront() }
fun front(this: @ClassifierRange): RetType
var res = _range.front
fun isEmpty(this: ClassifierRange) = _range.isEmpty()
fun popFront(this: !ClassifierRange) { _range.popFront() }
fun front(this: !ClassifierRange): RetType
let res = _range.front
res.classifier = _pred(res.value)
return res

Expand All @@ -277,13 +280,13 @@ package _Impl
_range: rangeType
_count: SizeType

fun ctor(this: @ElementsGen, range: this._RangeType)
fun ctor(this: !ElementsGen, range: this._RangeType)
this._range ctor range
this._count ctor (range rangeSize)

fun ()(this: @ElementsGen, sizeHint: UInt): ElementType
var r = _range
fun ()(this: !ElementsGen, sizeHint: UInt): ElementType
let r = _range
r advance randBetween(0, Int(_count))
return r.front

fun gen(this: @ElementsGen): Gen(ElementType) = ife(_count>0, mkGen(ElementType, this), Gen(ElementType)())
fun gen(this: !ElementsGen): Gen(ElementType) = ife(_count>0, mkGen(ElementType, this), Gen(ElementType)())
Loading

0 comments on commit 276f0a5

Please sign in to comment.