{"id":28209318,"url":"https://github.com/altasoft/simpra","last_synced_at":"2026-01-16T17:12:07.918Z","repository":{"id":283494472,"uuid":"951976770","full_name":"altasoft/Simpra","owner":"altasoft","description":"AltaSoft.Simpra is a lightweight expression language for .NET, enabling dynamic rule evaluation with a safe, extensible, and script-like syntax. 🚀","archived":false,"fork":false,"pushed_at":"2026-01-12T10:48:20.000Z","size":2117,"stargazers_count":13,"open_issues_count":0,"forks_count":1,"subscribers_count":5,"default_branch":"main","last_synced_at":"2026-01-12T18:59:36.581Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/altasoft.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-03-20T14:37:50.000Z","updated_at":"2026-01-12T10:47:56.000Z","dependencies_parsed_at":null,"dependency_job_id":"4e5d3729-acb2-4927-b262-9555beea3548","html_url":"https://github.com/altasoft/Simpra","commit_stats":null,"previous_names":["altasoft/simpra"],"tags_count":19,"template":false,"template_full_name":null,"purl":"pkg:github/altasoft/Simpra","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/altasoft%2FSimpra","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/altasoft%2FSimpra/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/altasoft%2FSimpra/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/altasoft%2FSimpra/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/altasoft","download_url":"https://codeload.github.com/altasoft/Simpra/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/altasoft%2FSimpra/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28480081,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-16T11:59:17.896Z","status":"ssl_error","status_checked_at":"2026-01-16T11:55:55.838Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-05-17T15:14:09.820Z","updated_at":"2026-01-16T17:12:07.912Z","avatar_url":"https://github.com/altasoft.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"﻿# AltaSoft.Simpra\n[![Version](https://img.shields.io/nuget/v/AltaSoft.Simpra?label=Version\u0026color=0c3c60\u0026style=for-the-badge\u0026logo=nuget)](https://www.nuget.org/profiles/AltaSoft)\n[![Dot NET 8+](https://img.shields.io/static/v1?label=DOTNET\u0026message=8%2B\u0026color=0c3c60\u0026style=for-the-badge)](https://dotnet.microsoft.com)\n\n**Simpra** is a powerful expression language designed for evaluating dynamic expressions in .NET applications. It enables developers to execute logic dynamically within their applications, similar to how scripting languages work but optimized for business rules.\n\n## Installation\n\nTo install **AltaSoft.Simpra**, use NuGet:\n\n```sh\ndotnet add package AltaSoft.Simpra\n```\n\nOr in your `.csproj`:\n\n```xml\n\u003cPackageReference Include=\"AltaSoft.Simpra\" Version=\"1.0.0\" /\u003e\n```\n\n## Features\n\n- **Dynamic Expression Execution**: Evaluate expressions at runtime.\n- **Rich Syntax**: Conditionals, arithmetic, lists, pattern matching, regex, membership, null checks.\n- **Mutability Control**: Toggle between immutable and mutable execution.\n- **String \u0026 List Operations**: Manipulate and aggregate data easily.\n- **Custom Functions**: Extend with user-defined or async functions.\n- **Safe Evaluation**: No loops, recursion, or external resource access.\n\n## Language Specifics\n\n### Supported Operators\n\n- **Arithmetic**  \n  `+`, `-`, `*`, `/`, `//` (integer division), postfix `%` (percent), `min`, `max`  \n  ```simpra\n  10 // 3     # 3\n  50%        # 0.5\n  5 min 2    # 2\n  ```\n\n- **Comparison**  \n  `is`, `is not`, `\u003c`, `\u003c=`, `\u003e`, `\u003e=`  \n  ```simpra\n  x is 10\n  y is not null\n  a \u003c b and \u003c c   # chained comparison\n  ```\n\n- **Logical**  \n  `and`, `or`, `not`\n\n- **Membership**  \n  `in`, `not in`, plus `any in`, `all in`, `any not in`, `all not in`  \n  ```simpra\n  x in [1, 2, 3]\n  all in [true, true, false]\n  ```\n\n- **Pattern Matching**  \n  - `matches` (regex)  \n  - `like` (SQL-like patterns)  \n  ```simpra\n  email matches \"[a-z]+@[a-z]+\\\\.[a-z]+\"\n  name like \"Jo%\"\n  ```\n\n- **Null Handling**  \n  `has value`  \n  ```simpra\n  nullable has value\n  ```\n\n---\n\n### Control Flow\n\n- **if … then … else … end**\n- **when … then … else … end**\n- **return**\n\n```simpra\nif x \u003e 10 then\n    return \"big\"\nelse\n    return \"small\"\nend\n\nwhen color then\n    \"red\"   -\u003e \"Stop\"\n    \"green\" -\u003e \"Go\"\n    else \"Unknown\"\nend\n```\n\n---\n\n### Directives\n\nSimpra supports runtime directives that influence evaluation:\n\n- **$mutable on/off** – Enables or disables mutability for **model properties** (local variables are always mutable).\n- **$case_sensitive on/off** – Controls case sensitivity in string comparisons (`is`, `like`, `matches`).\n\nExample:\n\n```simpra\nlet str = 'abc'\n$case_sensitive off\nreturn str like 'A%'    # true\n```\n\n---\n\n### Variables \u0026 Mutability\n\n- **Local variables** declared with `let` are always mutable:\n  ```simpra\n  let x = 10\n  x += 5    # 15\n  x -= 2    # 13\n  ```\n\n- **Model properties can only be reassigned if mutability is enabled with $mutable on:**\n\n  ```simpra\n  $mutable on\n  Transfer.Amount = Transfer.Amount + 50\n  ```\n\n- **By default, $mutable is off, meaning model properties are read-only.**\n---\n\n### Lists\n\n```simpra\nlet items = [1, 2, 3]\nitems[0]         # 1\nsum(items)       # 6\nlength(items)    # 3\n```\n\n---\n\n### Functions \u0026 Access\n\n- Function calls: `method(\"hi\")`\n- Properties: `obj.prop`\n- Indexers: `list[1]`\n\n---\n\n### Chained Comparisons\n\nSimpra supports chained comparison expressions without repeating the left-hand operand:\n\n```simpra\nlet x = 5\nreturn x \u003e 0 and \u003c 10    # true\n```\n\nThis allows constructs like `a \u003c b and \u003c c` for concise range checks.\n\n---\n\n### Built-in Functions\n\nSimpra provides a set of internal functions out-of-the-box:\n\n- **Math**\n  - `abs(x)` – absolute value\n  - `round(x)` – round to nearest integer\n  - `min(a, b, …)`, `max(a, b, …)` – smallest/largest value\n\n- **Lists**\n  - `sum(list)` – sum of values\n  - `length(list)` – number of elements\n  \n- **Strings**\n  - `number(str)` – converts to number\n  - `date(str)` – converts to date\n  - `substring(str, index, count)` – Retrieves part of a string starting at a **1-based position**.\n---\n\n### Extended Membership Operators\n\nIn addition to `in` and `not in`, Simpra supports `any in`, `all in`, `any not in`, and `all not in`:\n\n```simpra\nlet values = [1, 2, 3]\n\n2 any in values       # true\n[2, 4] all in values  # false\n2 any not in values   # false\n[4, 5] all not in values  # true\n```\n\n---\n\n### Percent Operator\n\nThe `%` operator in Simpra is **postfix percent**, not modulus.\n\n```simpra\n50%     # 0.5\n200%    # 2.0\n```\n\nThis makes it easy to express percentages directly inside formulas.\n\n## Usage\n\n### Evaluating Simple Expressions\n\n```csharp\nvar simpra = new Simpra();\nvar model = new TestModel { Transfer = new Transfer { Amount = 50, Currency = \"USD\" } };\n\nconst string expression = \"return Transfer.Amount * 2\";\nvar result = simpra.Execute\u003cint, TestModel\u003e(model, expression);\n\nConsole.WriteLine(result); // Output: 100\n```\n\n### Conditionals \u0026 Logical Operators\n\n```csharp\nconst string expression = \"\"\"\nlet transfer = Transfer\nreturn transfer.Amount \u003e 100 and transfer.Currency is 'USD'\n\"\"\";\n\nvar result = simpra.Execute\u003cbool, TestModel\u003e(model, expression);\nConsole.WriteLine(result); // Output: false\n```\n\n### Handling Lists \u0026 Aggregations\n\n```csharp\nconst string expression = \"\"\"\nlet values = [10, 20, 30]\nreturn sum(values) / length(values)\n\"\"\";\n\nvar result = simpra.Execute\u003cdecimal, TestModel\u003e(model, expression);\nConsole.WriteLine(result); // Output: 20\n```\n\n### Using Regular Expressions\n\n```csharp\nconst string expression = \"\"\"\nlet value = 'abc123'\nreturn value matches '[a-zA-Z_][a-zA-Z_0-9]*'\n\"\"\";\n\nvar result = simpra.Execute\u003cbool, TestModel\u003e(model, expression);\nConsole.WriteLine(result); // Output: true\n```\n\n### Safe Division with `when`\n\n```csharp\nconst string expression = \"\"\"\nlet amount = Transfer.Amount\nlet divisor = 0\nlet result = when divisor is not 0 then amount / divisor else 0 end\nreturn result\n\"\"\";\n\nvar result = simpra.Execute\u003cint, TestModel\u003e(model, expression);\nConsole.WriteLine(result); // Output: 0\n```\n\n### String Manipulation\n\n```csharp\nconst string expression = \"\"\"\nlet str = 'hello'\nreturn Upper(str) + ' WORLD'\n\"\"\";\n\nvar result = simpra.Execute\u003cstring, TestModel, TestFunctions\u003e(model, new TestFunctions(), expression);\nConsole.WriteLine(result); // Output: \"HELLO WORLD\"\n```\n\n### Arithmetic Operators (//, %, min, max)\n\n```csharp\nconst string expression = \"\"\"\nlet a = 10\nlet b = 3\nlet half = 50%\nreturn [ a // b, half, a min b, a max b ]\n\"\"\";\n\nvar result = simpra.Execute\u003cList\u003cdecimal\u003e, TestModel\u003e(model, expression);\nConsole.WriteLine(string.Join(\", \", result)); // Output: \"3, 0.5, 3, 10\"\n```\n\n## Advanced Features\n\n### Mutable vs Immutable Execution\n\nBy default, expressions in Simpra are immutable. However, you can enable mutability:\n\n```csharp\nconst string expression = \"\"\"\n$mutable on\nlet x = 10\nx = x + 5\nreturn x\n\"\"\";\n\nvar result = simpra.Execute\u003cint, TestModel\u003e(model, expression);\nConsole.WriteLine(result); // Output: 15\n```\n\n### Custom Functions\n\nYou can define custom functions and use them in expressions:\n\n```csharp\npublic class CustomFunctions\n{\n    public static string Reverse(string input) =\u003e new string(input.Reverse().ToArray());\n}\n\nconst string expression = \"return Reverse('hello')\";\nvar result = simpra.Execute\u003cstring, TestModel, CustomFunctions\u003e(model, new CustomFunctions(), expression);\nConsole.WriteLine(result); // Output: \"olleh\"\n```\n\n### Async Method Execution\n\nSimpra supports calling asynchronous methods within expressions:\n\n```csharp\npublic class AsyncFunctions\n{\n    public async Task\u003cint\u003e GetExchangeRateAsync() =\u003e await Task.FromResult(3);\n}\n\nconst string expression = \"return GetExchangeRateAsync() * 10\";\nvar result = await simpra.ExecuteAsync\u003cint, TestModel, AsyncFunctions\u003e(model, new AsyncFunctions(), expression);\n\nConsole.WriteLine(result); // Output: 30\n```\n\n### Mutability: Modifying Class Properties\n\nMutability can be enabled to allow modifying object properties:\n\n```csharp\nconst string expression = @\"\n$mutable on\nTransfer.Amount = Transfer.Amount + 50\nreturn true\n\";\n\nvar model = new TestModel { Transfer = new Transfer { Amount = 100 } };\nvar result = simpra.Execute\u003cbool, TestModel\u003e(model, expression);\n\nConsole.WriteLine(result); // Output: true\nConsole.WriteLine(model.Transfer.Amount); // Output: 150\n```\n\n## License\n\n**AltaSoft.Simpra** is licensed under the MIT License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faltasoft%2Fsimpra","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faltasoft%2Fsimpra","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faltasoft%2Fsimpra/lists"}