Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
5199e14
Initial plan
Copilot Feb 23, 2026
43f3ab8
Add BenchmarkDotNet benchmarks for RunAllTestsInPackage and AdderProgram
Copilot Feb 23, 2026
5992898
fixed release mode for benchmarking, the benchmarks still don't work …
BenjaminNitschke Feb 24, 2026
b5c2f0b
Merge branch 'master' into copilot/benchmark-slow-parts-analysis
BenjaminNitschke Feb 24, 2026
d31a137
Tried fixing running RunAllTestsInPackage twice, which caused a dicti…
BenjaminNitschke Feb 24, 2026
7f3b12c
trying to get RunAllTestsInPackageTwice working again
BenjaminNitschke Feb 25, 2026
4749795
Removed the last exception SignalReturn and instead passing the retur…
BenjaminNitschke Feb 25, 2026
a784f08
Statistics is fully working and the results are pretty good (this is …
BenjaminNitschke Feb 25, 2026
3327af4
Trying to change ValueInstance to consume less memory and do less box…
BenjaminNitschke Feb 25, 2026
09990c3
Attempt to move ValueInstance to Expressions, this is a mess, it is a…
BenjaminNitschke Feb 25, 2026
f4f6f74
Finally got ValueInstance into Expressions, lots of decissions had to…
BenjaminNitschke Feb 26, 2026
7224810
Expressions and Validators all fixed and working, next up is HighLeve…
BenjaminNitschke Feb 26, 2026
a2701ae
Still refactoring HighLevelRuntime, too many object and casting thing…
BenjaminNitschke Feb 26, 2026
0428cd7
More fixes in Executor and special Equals check in ValueInstance to m…
BenjaminNitschke Feb 26, 2026
d68982c
Minor improvement to make Strict.Compiler.Roslyn compile
BenjaminNitschke Feb 26, 2026
7487377
Moar refactoring needed, a lot of the old generated code is useless o…
BenjaminNitschke Feb 26, 2026
4413e90
Lots of changes to ValueInstance to properly use cached values instea…
BenjaminNitschke Feb 27, 2026
3a00bb9
fixed most issues in HighLevelRuntime and then worked on the Reposito…
BenjaminNitschke Feb 28, 2026
8aea9c6
Finished implementing new folder structure for all packages and remov…
BenjaminNitschke Mar 1, 2026
defdc7c
Moved all .strict files into this repository, much easier to work wit…
BenjaminNitschke Mar 1, 2026
6a556c5
Moved Base to Type to not longer have any kind of Strict.Base package…
BenjaminNitschke Mar 2, 2026
b13765d
FullName logic restored and all Language and Expressions tests working
BenjaminNitschke Mar 2, 2026
fb6fa88
Removed EqualsExtensions, not longer needed and just making compariso…
BenjaminNitschke Mar 3, 2026
08b6d60
Minor fixes for HighLevelRuntime.Tests to work, but more work required
BenjaminNitschke Mar 3, 2026
72fad89
Lots of cleanup on Package creation, naming, correct folders and some…
BenjaminNitschke Mar 4, 2026
2c371dd
Changed PackageManager to use the new logic like Repositories github …
BenjaminNitschke Mar 4, 2026
5957bf1
Lots of refactoring in HighLevelRuntime.Tests, still some tests faili…
BenjaminNitschke Mar 4, 2026
9a787ed
Just a few more tests to be fixed for for, if and methodcalls
BenjaminNitschke Mar 4, 2026
a49907e
Better debug messages for all contexts and repositories, fixed most H…
BenjaminNitschke Mar 4, 2026
bd74313
All HighLevelRuntime tests fixed and some cleanup started, still have…
BenjaminNitschke Mar 4, 2026
6483637
All code and tests fixed, starting some more cleanup now, avoid objec…
BenjaminNitschke Mar 4, 2026
2ad9eb0
removed object from Runtime.Instance, but it is not fully removed yet…
BenjaminNitschke Mar 5, 2026
51a4b87
First round of performance refactorings done, quite a lot of changes,…
BenjaminNitschke Mar 5, 2026
39ba572
Second round of performance optimizations, mostly memory related, but…
BenjaminNitschke Mar 5, 2026
f832b83
Initial plan
Copilot Mar 5, 2026
1cb9979
Reduce memory allocations in RunAllTestsInPackage iterations
Copilot Mar 5, 2026
a140f52
minor cleanup and reverting some of the stupid changes. still have to…
BenjaminNitschke Mar 5, 2026
39a784a
Added more tests for some uncovered code and cleaned up a bit more, s…
BenjaminNitschke Mar 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ resharper_co_variant_array_conversion_highlighting = suggestion
resharper_double_negation_operator_highlighting = warning
resharper_event_never_subscribed_to_global_highlighting = hint
resharper_field_can_be_made_read_only_local_highlighting = warning
resharper_for_can_be_converted_to_foreach_highlighting = warning
resharper_for_can_be_converted_to_foreach_highlighting = suggestion
resharper_function_complexity_overflow_highlighting = warning
resharper_incorrect_blank_lines_near_braces_highlighting = warning
resharper_inline_out_variable_declaration_highlighting = warning
Expand Down
5 changes: 4 additions & 1 deletion .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@
- Keep AdderProgram in the Tests project and use TestPackage (or Strict.Base) for basic types.

## Strict Semantics
- When asked about Strict semantics, derive behavior directly from README.md and TestPackage.cs examples; re-check cited examples before answering and avoid contradicting them.
- When asked about Strict semantics, derive behavior directly from README.md and Strict/TestPackage examples; re-check cited examples before answering and avoid contradicting them.

## Strict.Runtime Guidelines
- Prefer ValueInstance-backed representations and avoid object-based value/rawValue conversions where possible.

## Test-Driven Development (TDD)

Expand Down
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -127,5 +127,4 @@ ipch/
*.sap
/Strict_NCrunchResults
/.NCrunch_Strict
Base.zip
/coverage-results
5 changes: 5 additions & 0 deletions Any.strict
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from
to Type
to Text
to HashCode
is(other) Boolean
1 change: 1 addition & 0 deletions App.strict
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Run
2 changes: 1 addition & 1 deletion Strict.Base/Boolean.strict → Boolean.strict
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ is(other) Boolean
to Text
true to Text is "true"
not true to Text is "false"
value then "true" else "false"
value then "true" else "false"
22 changes: 22 additions & 0 deletions Character.strict
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
has number
constant zeroCharacter = 48
constant NewLine = Character(13)
constant Tab = Character(7)
from(text)
Character("b") is "b"
Character(7) is Tab
7 to Character is "7"
Character("ab") is Error
text.Characters(0)
to Text
Character("a") to Text is "a"
"" + value
+(other) Text
Character("1") + Character("2") is "12"
value to Text + other
to Number
Character("3") to Number is 3
constant notANumber = Error
Character("A") to Number is notANumber
let result = number - zeroCharacter
result is in Range(0, 10) then result else notANumber(value)
32 changes: 32 additions & 0 deletions Dictionary.strict
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
has keysAndValues List(key Generic, mappedValue Generic)
from
Dictionary(Number, Number).Length is 0
Dictionary(Number, Number) is Dictionary(Number, Number)
Dictionary(Number, Number) is not Dictionary(Number, Text)
Dictionary((1, 1)).Length is 1
Dictionary((1, 1), (2, 2)).Length is 2
in(key Generic) Boolean
2 is in Dictionary((1, 1), (2, 2))
3 is not in Dictionary((1, 1), (2, 2))
for keysAndValues
value.Key is key
get(key Generic) Generic
constant abbreviations = Dictionary(("A", "Apple"), ("B", "Ball"))
abbreviations("A") is "Apple"
abbreviations("B") is "Ball"
constant KeyNotFound = Error
abbreviations("C") is KeyNotFound
for keysAndValues
if value.Key is key
return value.Value
KeyNotFound
Add(key Generic, mappedValue Generic) Mutable(Dictionary)
constant DuplicateKey = Error
Dictionary((1, 1)).Add(1, 1) is DuplicateKey
Dictionary((1, 1)).Add(1, 2) is DuplicateKey
Dictionary((2, 4)).Add(4, 8) is Dictionary((2, 4), (4, 8))
Dictionary((1, 1), (2, 2)).Add(3, 3).Length is 3
in(key) then DuplicateKey else keysAndValues.Add((key, mappedValue))
Remove(key Generic) Mutable(Dictionary)
Dictionary((1, 1), (2, 2)).Remove(1).Length is 1
keysAndValues.Remove((key, get(key)))
3 changes: 3 additions & 0 deletions Directory.strict
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from(text)
GetFiles Texts
GetDirectories Texts
9 changes: 9 additions & 0 deletions Enum.strict
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
has iterator
GetName(type) Text
type.Name
GetName(member) Text
member.Name
CompareTo(member) Number
value > member.Value then 1 else value < member.Value then -1 else 0
Equals(member) Boolean
value is member.Value
2 changes: 2 additions & 0 deletions Error.strict
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
has Name
has Stacktraces
2 changes: 2 additions & 0 deletions ErrorWithValue.strict
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
has Error
has Value Generic
11 changes: 11 additions & 0 deletions Examples/ArithmeticFunction.strict
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
has numbers
Calculate(operation Text) Number
ArithmeticFunction(10, 5).Calculate("add") is 15
ArithmeticFunction(10, 5).Calculate("subtract") is 5
ArithmeticFunction(10, 5).Calculate("multiply") is 50
for numbers
if operation is
"add" then value
"subtract" then - value
"multiply" then * value
"divide" then / value
14 changes: 14 additions & 0 deletions Examples/Beeramid.strict
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
has bonus Number
has price Number
GetCompleteLevelCount Number
Beeramid(10, 3).GetCompleteLevelCount is 1
Beeramid(20, 4).GetCompleteLevelCount is 2
Beeramid(100, 5).GetCompleteLevelCount is 3
CalculateCompleteLevelCount(bonus / price, 0)
CalculateCompleteLevelCount(numberOfCans Number, levelCount Number) Number
CalculateCompleteLevelCount(3, 0) is 1
CalculateCompleteLevelCount(5, 0) is 2
CalculateCompleteLevelCount(20, 1) is 3
let remainingCans = numberOfCans - levelCount * levelCount
let nextLevelSquare = (levelCount + 1) * (levelCount + 1)
remainingCans < nextLevelSquare then levelCount else CalculateCompleteLevelCount(remainingCans, levelCount + 1)
9 changes: 9 additions & 0 deletions Examples/ConvertingNumbers.strict
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
has numbers
GetComplicatedSequenceTexts Texts
ConvertingNumbers(1, 21).GetComplicatedSequenceTexts is ("16")
for numbers
to Text
Length * Length
if value > 3
4 + value * 3
to Text
14 changes: 14 additions & 0 deletions Examples/EvenFibonacci.strict
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
has number
Sum Number
mutable first = 1
mutable second = 1
mutable sum = 0
for Range(1, number)
let next = first + second
if next >= number
return sum
if next % 2 is 0
sum.Increment(next)
first = second
second = next
sum
12 changes: 12 additions & 0 deletions Examples/ExecuteOperation.strict
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
has registers
TryOperationExecution(statement) Register
if registers.Length < 2
Error "OperandsRequired"
GetOperationResult(statement, registers(1), registers(0))
registers(1)
GetOperationResult(statement, left Register, right Register) Number
if statement.Instruction is
Instruction.Add then left + right
Instruction.Subtract then left - right
Instruction.Multiply then left * right
Instruction.Divide then left / right
11 changes: 11 additions & 0 deletions Examples/Fibonacci.strict
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
has number
GetNthFibonacci Number
Fibonacci(5).GetNthFibonacci is 5
Fibonacci(10).GetNthFibonacci is 55
mutable first = 1
mutable second = 1
for Range(2, number)
let next = first + second
first = second
second = next
second
8 changes: 8 additions & 0 deletions Examples/FindFirstNonConsecutiveNumber.strict
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
has numbers
FirstNonConsecutive Number
FindFirstNonConsecutiveNumber(1, 2, 3, 5, 6).FirstNonConsecutive is 5
FindFirstNonConsecutiveNumber(1, 2, 3).FirstNonConsecutive is 0
for numbers
if index > 0 and value is not numbers(index - 1) + 1
return value
0
5 changes: 5 additions & 0 deletions Examples/FindNumberCount.strict
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
has numbers
FindNumberCount Number
NumberCount(5, 10).FindNumberCount is 5
for Range(numbers(0), numbers(1))
1
17 changes: 17 additions & 0 deletions Examples/Instruction.strict
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
constant Set
constant Add
constant Subtract
constant Multiply
constant Divide
constant BinaryOperatorsSeparator = 100
constant GreaterThan
constant LessThan
constant Equal
constant NotEqual
constant ConditionalSeparator = 200
constant JumpIfTrue
constant JumpIfFalse
constant JumpIfNotZero
constant JumpsSeparator = 300
constant LoopIfNonZero
constant JumpBackIfNonZero
20 changes: 20 additions & 0 deletions Examples/LinkedListAnalyzer.strict
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
mutable visited Nodes
GetChainedNode(number) Node
constant head = Node
mutable current = head
for Range(1, number)
current.Next = Node
current = current.Next
current.Next = head
GetLoopLength(node) Number
mutable first = Node
mutable second = Node
first.Next = second
second.Next = first
GetLoopLength(first) is 2
mutable third = Node
second.Next = third
third.Next = first
GetLoopLength(first) is 3
visited.Add(node)
visited.Contains(node.Next) then visited.Length else GetLoopLength(node.Next)
10 changes: 10 additions & 0 deletions Examples/MatchingLoopFinder.strict
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
has instructions
GoToMatchingLoopBracket(direction Number, mutable index Number)
mutable loopDepth = direction
for Range(index + direction, instructions.Length)
if instructions(index) is
Instruction.LoopIfNonZero then loopDepth.Increase
Instruction.JumpBackIfNonZero then loopDepth.Decrease
if loopDepth is 0
return 0
loopDepth
2 changes: 2 additions & 0 deletions Examples/Node.strict
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
mutable Next Node
has unused Number
10 changes: 10 additions & 0 deletions Examples/Processor.strict
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
has progress Number
IsJobDone Boolean or Text
Processor(100).IsJobDone is true
Processor(78).IsJobDone is false
Processor(0).IsJobDone is "Work not started yet"
if progress is 100
return true
if progress > 0
return false
"Work not started yet"
2 changes: 2 additions & 0 deletions Examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Strict.Examples
This repository contains example strict programs which demonstrates the currently available features in Strict language. Little bit of a playground for katas and for testing new syntax and language features all the time.
7 changes: 7 additions & 0 deletions Examples/ReduceButGrow.strict
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
has numbers
GetMultiplicationOfNumbers Number
ReduceButGrow(2, 3, 4, 5).GetMultiplicationOfNumbers is 120
ReduceButGrow(120, 5, 40, 0).GetMultiplicationOfNumbers is 0
ReduceButGrow(2, 2, 2, 2).GetMultiplicationOfNumbers is 16
for numbers
* value
15 changes: 15 additions & 0 deletions Examples/Register.strict
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
has RZero Number
has ROne Number
has RTwo Number
+(other) Number
Register(0, 1, 2) + Register(1, 2, 3) is Register(1, 3, 5)
value + other
-(other) Number
Register(5, 5, 5) - Register(5, 5, 5) is Register(0, 0, 0)
value - other
*(other) Number
Register(0, 1, 2) * Register(1, 2, 3) is Register(0, 2, 6)
value * other
/(other) Number
Register(5, 5, 5) / Register(5, 5, 5) is Register(1, 1, 1)
value / other
8 changes: 8 additions & 0 deletions Examples/RemoveDuplicateWords.strict
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
has texts
Remove Texts
RemoveDuplicateWords("a", "b", "b").Remove is ("a", "b")
RemoveDuplicateWords("a", "b", "c").Remove is ("a", "b", "c")
RemoveDuplicateWords("hello", "hi", "hiiii", "hello").Remove is ("hello", "hi", "hiiii")
for texts
if texts.Count(value) > 1
texts.Remove(value)
8 changes: 8 additions & 0 deletions Examples/RemoveExclamation.strict
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
has text
Remove Text
RemoveExclamation("Hello There!").Remove is "Hello There"
RemoveExclamation("Hi!!!").Remove is "Hi"
RemoveExclamation("Wow! Awesome! There!").Remove is "Wow Awesome There"
for text
if value is not "!"
value
11 changes: 11 additions & 0 deletions Examples/RemoveParentheses.strict
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
has text
Remove Text
RemoveParentheses("example(unwanted thing)example").Remove is "exampleexample"
mutable parentheses = 0
for text
if value is "("
parentheses.Increase
else if value is ")"
parentheses.Decrease
else if parentheses is 0
value
5 changes: 5 additions & 0 deletions Examples/ReverseList.strict
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
has numbers
Reverse Numbers
ReverseList(1, 2, 3, 4).Reverse is (4, 3, 2, 1)
for Range(0, numbers.Length).Reverse
numbers(index)
28 changes: 28 additions & 0 deletions Examples/ShorterPath.strict
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
has target Vector2
from(path Text)
target = Vector2(path.Count("E") - path.Count("W"), path.Count("N") - path.Count("S"))
for path
if value is
"N" then target.Y.Increment
"S" then target.Y.Decrement
"E" then target.X.Increment
"W" then target.X.Decrement
GetDirections Text
ShorterPath("").GetDirections is ""
ShorterPath("NNE").GetDirections is "NNE"
ShorterPath("NNEN").GetDirections is "NNNE"
ShorterPath("SSNEWSN").GetDirections is "S"
ShorterPath("NWSE").GetDirections is ""
GetVerticalDirections + GetHorizontalDirections
GetVerticalDirections Text
ShorterPath("").GetVerticalDirections is ""
ShorterPath("NN").GetVerticalDirections is "NN"
ShorterPath("NSN").GetVerticalDirections is "N"
for target.Y
target.Y > 0 then "N" else "S"
GetHorizontalDirections Text
ShorterPath("").GetHorizontalDirections is ""
ShorterPath("EEEW").GetVerticalDirections is "EE"
ShorterPath("WWWE").GetVerticalDirections is "WW"
for target.X
target.X > 0 then "E" else "W"
2 changes: 2 additions & 0 deletions Examples/Statement.strict
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
has Instruction
has Registers
Loading