qamp/Qrakhen.Qamp.Core
Qrakhen db68d9e9ce fix the stack issue for now by simply peeking the stack rather than popping it for global assignments. 2025-12-04 14:46:35 +01:00
..
Abstractions fix formatting everywhere and make operation resolving faster 2025-11-23 07:38:22 +01:00
Collections fix formatting everywhere and make operation resolving faster 2025-11-23 07:38:22 +01:00
Compilation fix the stack issue for now by simply peeking the stack rather than popping it for global assignments. 2025-12-04 14:46:35 +01:00
Execution fix the stack issue for now by simply peeking the stack rather than popping it for global assignments. 2025-12-04 14:46:35 +01:00
Logging make editor editing and running 2025-11-25 23:09:15 +01:00
Tokenization add incremental operators but fuck up the stack in the process 2025-12-04 13:49:56 +01:00
Values changes 2025-12-04 14:19:31 +01:00
Assert.cs fix formatting everywhere and make operation resolving faster 2025-11-23 07:38:22 +01:00
Benchmark.cs make editor editing and running 2025-11-25 23:09:15 +01:00
Console.cs make editor editing and running 2025-11-25 23:09:15 +01:00
Exceptions.cs fix formatting everywhere and make operation resolving faster 2025-11-23 07:38:22 +01:00
Extensions.cs remove tiling frames for now and add a more solid approach to extensions with fast compiled linq expressions 2025-12-03 14:53:31 +01:00
Injector.cs fix formatting everywhere and make operation resolving faster 2025-11-23 07:38:22 +01:00
Qrakhen.Qamp.Core.csproj add incremental operators but fuck up the stack in the process 2025-12-04 13:49:56 +01:00
Qrakhen.Qamp.Core.csproj.Backup.tmp initial commit 2025-11-06 14:36:38 +01:00
README.md add incremental operators but fuck up the stack in the process 2025-12-04 13:49:56 +01:00

README.md

Q&

About

A single-pass byte code interpreter with the ability to pre-compile executables into a format that can be efficiently executed by the runtime. It serves many features, which are listed a bit further down below.

This would have officially been the fourth iteration of my language (sqript4), but I thought I'd stop with the numbers as people would ask what happened to the previous three languages.

Q& (or Qamp for Q Ampersand) was originally made for my contributions to the Advent Of Code 2025, but I thought it's a nice and stable enough concept to be sharing it to the public anyway.

Usage

To build Q&, you need nothing more than a C# compiler that supports .NET10. There are .NET8 compatible versions available, but they are not recommended, as Q& utilizes all of the performance optimizations .NET10 has to offer.

After cloning, a simple dotnet build ./ in the root directory will suffice.

You can execute pre-compiled .sqi files using qamp.runtime.exe <filepath> [parameters], or the REPL/CLI using qamp.cli.exe [parameters]. If you want to build your own source into pre-compiled instruction files, use qamp.digest.exe <dirpath> - the digester will look for an Init() function declared in any of the files, and build the instructions from there.

Language & Syntax

You are free to choose between the classic sqript-style dialect *~ q <~ 0xf; or the standard dialect, which is strongly inspired by the C# standard: var q = 0xf;.

All of the following examples are written in the classic dialect --dialect=sqr or -d=q.

Syntax

Most basic Usage:

                                            # this is a comment.
*~ q <~ 12;                                 # q == 12
*~ f <~ (n) <: n < 2 ? n : f(n-1) + f(n-2); # fibonacci
f(12);                                      # 233
*~ a <~ [1, 2, 3];                          # a = [1, 2, 3]
*~ x <~ a:0 + a:2;                          # x == 4

Assignments

Q& has two distinct ways to assign a value to a variable:

  • By reference <&, or
  • By value <=.

Using the auto-assignment operator <~, Q& will choose the correct assignment based on what type the right-hand expression consists of. Primitive types will be assigned by value, any object values will be assigned by reference. This is strongly inspired by the behaviour that most interpeters implement.

What happens if...

I assign an object by value?

The entire object will be deep-copied and transfered to the new location. See it as a free clone method on basically anything that is considered an object.

I assign a primitive by reference?

So, assuming that x is a primitive (value type), given the instruction *~ y <& x;, y will be assigned as a reference value pointing to the location of x - somewhat like a pointer in C, but a little smarter.

I do not praise the god emperor of mankind?

You will be duly punished.

Variable Declaration

*~ q <~ 0xf;

Variable Declaration

Types

sig a; signed
uns b; unsigned
dec c; decimal
str d; string
chr e; character
bin f; boolean or binary, you can declare bitfields with:
bin:16 bits; custom bitfield type with 16 bits.
ref g; reference type, can be explicitely declared: 
ref:sig aRef <& a;
ptr p; pointer, essentially the same as a ref, but in Q& ptr is the base type of all objects.
CustomType yourObject; self-explanatory
any type may be declared as [] array,
{} dictionary, or [:] list. (non-fixed collection)

Operators, Keywords & their aliases

*~ var
:~ const
<: return
:> continue
<+ increment / add
<- subtract / remove
:: print
?: typeof
<& assign reference
^~ base
.~ this
~( function

Customization & Extras

Some more information about extending and customizing Q& to your needs.

Writing Extension Methods

asdasd

Implementing external Libraries

Implementation is easy. Q& is written in C#, and supports basically anything you can wrap in C#. All you have to do in order to implement a library is referencing the SDK dll which should be located within your ./Build/ folder after building as described above.

Here's a quick example of how you would implement virtually any library:

using Qrakhen.Qamp.Core;
using System.Math;

Value Sqrt(Value number) 
{
  Assert.IsNumber(number);

  if (number.IsDecimal)
    return Math.Sqrt(number.AsDecimal);
  if (number.IsSigned)
    return Math.Sqrt(number.AsSigned);
  if (number.IsUnsigned)
    return Math.Sqrt(number.Unsigned);
  throw new Qrakhen.Qamp.Core.QampException($"Unsupported value type {value}");
}

Injector injector = new();
injector.Register(scope: Scope.Global, name: "sqrt", params: [ ("number", ValueType.Number) ], returns: ValueType.Number);
injector.Export("desiredPath.sqi");

That's it - although this being a very simple example, more is possible. I will add a few basic implementations of very common libraries in a separate repository soon.