Skip to content

Commit

Permalink
semitypes
Browse files Browse the repository at this point in the history
  • Loading branch information
maniospas committed Oct 21, 2024
1 parent 615d204 commit 27ce2fe
Show file tree
Hide file tree
Showing 19 changed files with 347 additions and 80 deletions.
21 changes: 20 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,25 @@
"typeindex": "cpp",
"valarray": "cpp",
"filesystem": "cpp",
"*.ipp": "cpp"
"*.ipp": "cpp",
"*.inc": "cpp",
"__bit_reference": "cpp",
"__hash_table": "cpp",
"__locale": "cpp",
"__node_handle": "cpp",
"__split_buffer": "cpp",
"__threading_support": "cpp",
"__tree": "cpp",
"__verbose_abort": "cpp",
"execution": "cpp",
"propagate_const": "cpp",
"ios": "cpp",
"locale": "cpp",
"print": "cpp",
"queue": "cpp",
"stack": "cpp",
"strstream": "cpp",
"hash_map": "cpp",
"hash_set": "cpp"
}
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Unzip the folder in a directory and create a file `main.bb` (or any name but wit

```cpp
name = read("What's your name?");
print("Hello " + name + "!");
print("Hello {name} !");
```
Run `blombly.exe main.bb`, where the executable and main files can be any path, and check that everything is working properly.
Expand Down
Binary file modified blombly.exe
Binary file not shown.
82 changes: 82 additions & 0 deletions docs/advanced/semitypes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Semi-types

The last aspect of the blombly language is dynamic typecasting that reinterprets
data as different formats. The purpose of this mechanism is to ensure that variables contain
or are transformed to appropriate data, therefore introducing type correctness guarantees
for subsequent code. At its core, this is equivalent to expressing
method calls of one argument. However, code writting is drastically simplified:

- Conversions are easily chained using much fewer symbols.
- Conversions are read as variable type semantics, which we dub semi-types.

## Type conversion

The main notation is a vertical slash per `expression | convertion`,
which in a vacuum is equivalent to calling `conversion(list(expression))`.
This has lower priority than commas to denote lists because the goal is
to apply conversion to speficic variables being accessed. Here is an example that converts an integer
to a float by leveraging the builtin typecasting mechanisms:

```java
// main.bb
x = 1|float;
print(x);
```

```bash
>blombly main.bb
1.000000
```

Observant readers may have already noted the lack of executable code in the arguments
(recall that this is a generalization of the concencept of keyword arguments). There is also a lack of automatic unpacking
to make the conversion mechanism callable with our notation by accepting only one argument.
To add parameters to the conversion create is as a callable struct, like below:

```java
final fmt_generator(specs) = {
return new{
specs = specs|str; // ensure str type for specs while bringing them within new
\call(x) = { // make the returned struct a callable
return x[this.specs]; // apply the numeric formatting pattern
}
}
}

print(1.2345 | fmt_generator(".3f"));
```


## Implicit types

Similarly to numeric operations, the expression `variable |= convertion;` reassigns to a variable
after applying the convertion. All reassignment operators replace source code tokens and
that leftwise convertions are performed first, which in this case enables `variable |= convertion1|convertion2|...;`
This notation is intentionally similar to
[double turnstile](https://en.wikipedia.org/wiki/Double_turnstile) and may be thought as
variable modeling some property.

Given the automatic conversion of casted variables,
create methods that transform their arguments to a format they can parse.
Here is an example:

```java
final nonzero(x) = {
if(x==0)
fail("Zero not allowed");
return x;
}

final safediv(x, y) = {
x |= float;
y |= float|nonzero;
return x / y;
}

print(safediv("1", 2));
```

```bash
>blombly main.bb
0.5
```
58 changes: 51 additions & 7 deletions docs/basics/builtins.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ in which subsequent code can overwrite variable values. Each program starts from

There are several builtin data types that are directly incorporated in the language.
Exhaustively, these are `int`, `float`, `bool`, `str`, `list`, `vector`, `map`, `iter`, `code`, `struct`, `server`.
Here we start with the first four, and split the rest to dedicated pages like the one describing [iterables](iterables.md).
Here we start with the first four, and split the rest to dedicated pages, like the one describing [iterables](iterables.md).

```java
// main.bb
Expand All @@ -35,16 +35,18 @@ s = "this is a string literal";
```

Some well-known operations on the above types are listed below. These are computed as one might have come to learn from other programming
languages.
languages. Only difference to usual practices is that the `not` operation has higher priority than assignment.

| **Category** | **Operation** | **Description** |
| **Category** | **Operations** | **Description** |
|--------------------------|----------------------------------------|----------------------------------------------------------|
| **Assignment** | `(expression)` | Compute the expression first. Also used in method calls later. |
| **Assignment** | `y=x`, `y as x` | The `as` assignment is covered below. |
| **Typecasting** | `typename(x)` | Everything can be converted from and to `str`. |
| **Elements** | `a[i]`, `a[i]=x` | Element get and set for strings. |
| **Arithmetics** | `+`, `-`, `*`, `/` <br> `^` <br> `%` | Basic arithmetics (division is floating-point). <br> Exponentiation. <br> Modulo for integers. |
| **Comparisons** | `<`, `>`, `<=`, `>=` <br> `==`, `!=` | Inequality comparisons. <br> Equality and inequality comparisons. |
| **Boolean operations** | `and`, `or` <br> `not` | Logical operations for booleans. <br> Negation of any boolean value it prepends. |
| **String operations** | `+` | Concatenation. |
| **Convertion** | Type names. | Everything can be converted from and to a string. |
| **Elements** | `a[i]`, `a[i]=x` | Element get and set for strings. Multiple elements may be obtained for list inputs. |
| **Comparisons** | `<`, `>`, `<=`, `>=` <br> `==`, `!=` | Inequality comparisons. <br> Equality comparisons. |
| **Boolean operations** | `and`, `or` <br> `not` | Logical operations for booleans. <br> Negation of any boolean value it prepends. |


Here is an example that contains some of these operations:
Expand All @@ -61,6 +63,48 @@ print("Sum is " + str(x+y)); // there is no implicit typecasting
Sum is 1.500000
```

## String formatting

Blombly supports string literals in which expressions enclosed in brackets
are replaced with their evaluation and converted to `str`. For safety,
expression terminating symbols (like brackets, inlining colons, or semicolons)
are not allowed within literals during parsing. However, you may still have
simple control flow as long as you avoid such symbols, like
for example `try if(x<0) return -1 else return 1` that is discussed later in this section.
With string literals, the previous paragraph's example may be rewritten as:

```java
// main.bb
x = int("1");
y = float("0.5");
print("Sum is {x+y}");
```

Format numbers using the element access notation by providing a string specification. Formatted numbers
returns a string and looks like this:

```java
//main.bb
x = 1.3456;
print("Here is a number: " + x[".3f"]);
```

```bash
> Blombly main.bb
Here is a number: 1.346
```

Formatting numbers within literals is discussed alongside advanced typecasting [here](../advanced/typecasting.md).
For now, we provide a first taste that the recommended syntax looks like below. Very briefly, a callable formatter is defined
and then applied within the literal with typecast notation `x | fmt`, which is equivalent to `fmt(x)`.

```java
fmt(x) = {return x[".3f"]}
x = 1;
print("This is a number {x | fmt}");
```


## Final variables

Variable values are made immutable by prepending the `final` keyword to their assignment. This prevents subsequent code from overwriting values
Expand Down
12 changes: 6 additions & 6 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,25 @@

[Get started](setup.md) | [Download](https://github.com/maniospas/Blombly/releases/latest) | [GitHub](https://github.com/maniospas/Blombly)

There are many programming languages for writing dynamic yet safe code. You might already have a favorite one! However, safety often comes at the cost of reduced expressiveness, like mutability restrictions, or may rely on non-infallible programmers. Blombly addresses these issues with a small instruction set that is easy to learn and use but which promises code and memory safety. It also focuses on programming logic by automating details of how algorithms execute, like parallelization.
There are many programming languages for writing dynamic yet safe code. You might already have a favorite one! However, safety often reduces expressiveness or relies on non-infallible programmers. Blombly addresses these issues with a small instruction set that is easy to learn and use. It also focuses on programming logic by automating details of how algorithms execute, like parallelization.

Blombly compiles into an intermediate representation that is interpreted by the **BLO**ck ase**MBLY** **V**irtual **M**achine (blomblyVM). This replaces jump-based statements to calling code blocks and supports dynamic code inlining as a major language feature. Control flow is managed via conditions, loops, inlining, method calling, return statements for results, and errors on failure.

So, who is Blombly for? It might be a good choice if you are looking a language with these features:
So, who is Blombly for? It might be a good choice if you are looking for a language that is:


## 🚀 Expressive

Focus on writing algorithms, and leave details like parallelization to the virtual machine. Enjoy comprehensive explanations and suggestions for syntax or runtime errors.
Focus on writing algorithms, and leave details like parallelization to the virtual machine.

## 🦆 Dynamic

Take advantage of features like duck typing, automatic garbage collection, and changing which code blocks are inlined. Use `try` to intercept algorithm results (errors and returns).
Take advantage of features like duck typing, automatic garbage collection, and changing which code blocks are inlined. Use `try` to intercept and handle algorithm results, namely errors and returns.

## 💻 Safe

Write memory-safe code with atomic struct access and "one-best-way" to do things. Safety is imposed on edge cases by preventing ambiguity.
Write memory-safe code with atomic resource acquisition that nonetheless never hangs.

## 💡Simple

All interfaces follow an "one solution" principle, meaning that there is usually only one obvious implementation. For example, there is only one loop structure (`while`) but other basic functionality lets it iterate over list elements or break prematurely.
The language explicitly hardcodes a preferred alternative when there are multiples. For example, there is only one loop structure (`while`) but other basic functionality lets it iterate over list elements or break prematurely.
33 changes: 19 additions & 14 deletions docs/setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ print("Hello world!");
```

To run this file, download Blombly's latest [release](https://github.com/maniospas/Blombly/releases/latest). Extract that into a folder
and add the latter to your filepath to let your operating system know where `blombly.exe` is located. Alternatively, you may
use the full path to the executable everywhere. Instructions to build the library from source for your environment are provided in repository's
and add the latter to your filepath to let your operating system know where `blombly.exe` is located. Alternatively,
use the full path to the executable everywhere. Instructions to build the library from source are in the
[GitHub](https://github.com/maniospas/Blombly) page.


Once you set things up, run the following console command.
If a message that starts with `( ERROR )` appears, everything properly but there was some syntax or logic error.
If a message starting with `( ERROR )` appears, everything runs properly but there was some syntax or logic issue.
For example, brackets may have closed with a semicolon, or there could be some other type of infraction. More on errors below.

```bash
Expand All @@ -32,8 +32,7 @@ Hello world!

Compilation converts code to a BlomlyVM intermediate representation.
This looks like assembly code and is stored win files with the `.bbvm` extension.
It is also self-contained by packing all dependencies inside the intermediate files,
which can can be shared with others and run directly.
These are self-contained by packing all dependencies inside, and so can be shared with others and run directly.
The following file is generated when you run`main.bb` above.

```asm
Expand All @@ -47,25 +46,28 @@ print # _bb0
Hello world!
```

To get a sense of internal commands, each one is a tuple of virtual machine command and its arguments
To get a sense for internal commands, each one is a tuple of virtual machine instruction and its arguments
are separated by spaces. The first argument is always a variable to assign to, where `#` indicates
assignment to nothing. Temporary variables start with `_bb`,
and code blocks are started by `BEGIN` and completing at `END`.
and code blocks start by `BEGIN` or `BEGINFINAL` and end at `END`.

Compilation optimizes the code for faster execution,
for example by creating unused variables that let the virtual machine reduce memory reallocation.
for example by removing unused variables.
To convert back the compilation outcome to semi-readable Blombly,
run the Python script `bbreader.py` (this is intensionally written in a different language
to also help with development debugging).


## Errors

Before jumping into actual coding, let us peek at errors that Blombly may create. Broadly, there are syntax errors, which are identified by the compiler and make it halt, and logical errors
that occur at runtime and can be caught with appropriate try clauses to avoid program termination.
Before jumping into actual coding, let us peek at errors that Blombly may create. There are two types:

To see what a syntax error looks like, let us try to execute the following invalid code.
We get an error telling us that the + operation for string concatenation has no right-hand side. The compiler shows the exact position of the missing expression within the source code.
- Syntax errors are identified by the compiler and make it halt.
- Logical errors occur at runtime and can be intercepted and handled with `try` and `catch` respectively.

To see what a syntax error looks like, execute the following invalid code.
We get an error telling us that the + operation for string concatenation has no right-hand side.
The compiler shows the exact position of the missing expression within the source code.

```java
// main.bb
Expand All @@ -82,11 +84,14 @@ print("Hello"+); // CREATES AN ERROR
Look at a logical error looks like by printing a variable that does not exist.
This creates an error during runtime that points to the stack trace of compiled code and the original source.
You will see full traces, regardless of which computations are internally delegated to threads.
Runtime errors can be caught to create self-healing code,
but this is a more advanced concept that we talk about [later](success-fail.md).
Such errors can be handled are runtime, but this is a more advanced concept that we talk about [later](success-fail.md).


```java
// main.bb
print(x); // CREATES AN ERROR
```

## What's next?

Continue going through the language's description by clicking the navigation bar's "Next" button at the top.
2 changes: 1 addition & 1 deletion include/BMemory.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class BMemory {
Data* getOrNullShallow(int item);
void unsafeSet(BMemory* handler, int item, Data* value, Data* prev);
void unsafeSet(int item, Data* value, Data* prev);
Data* unsafeSet(int item, Data* value);
void unsafeSet(int item, Data* value);
int size() const;
void removeWithoutDelete(int item);
void setFinal(int item);
Expand Down
14 changes: 9 additions & 5 deletions main.bb
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
i = 0;
while(i<10) {
i = i + 1;
print(i);
}
final fmt_generator(specs) = {
fmt = new{
specs |= str; // ensure str type for specs, make them
\call(x) = {return x[this.specs];}
}
return fmt;
}

print(1.2345 | fmt_generator(".3f"));
36 changes: 27 additions & 9 deletions main.bbvm
Original file line number Diff line number Diff line change
@@ -1,11 +1,29 @@
BUILTIN i I0
BUILTIN _bb2 I10
lt _bb1 i _bb2
BEGIN _bb0
next specs args
BEGIN _bb3
BUILTIN _bb5 I1
add i i _bb5
print # i
BUILTIN _bb2 I10
lt _bb1 i _bb2
str specs specs
BEGIN _bb5
next x args
get _bb7 this specs
at _bb6 x _bb7
return # _bb6
END
while # _bb1 _bb3
IS \call _bb5
return # this
END
new fmt _bb3
return # fmt
END
IS fmt_generator _bb0
final # fmt_generator
BEGIN _bb9
BUILTIN _bb11 F1.2345
list args _bb11
END
BEGIN _bb13
BUILTIN _bb14 ".3f"
list args _bb14
END
call _bb12 _bb13 fmt_generator
call _bb8 _bb9 _bb12
print # _bb8
1 change: 1 addition & 0 deletions mkdocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ nav:
- Signals: advanced/signals.md
- Servers: advanced/servers.md
- Prepacked libraries: advanced/libraries.md
- Semi-types: advanced/semitypes.md
theme:
name: united

Expand Down
Loading

0 comments on commit 27ce2fe

Please sign in to comment.