Skip to content

Commit

Permalink
Fibers refactored
Browse files Browse the repository at this point in the history
  • Loading branch information
vtereshkov committed Jul 29, 2024
1 parent 40bffaa commit 937157b
Show file tree
Hide file tree
Showing 11 changed files with 157 additions and 165 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,18 +200,18 @@ for i, x in g {
### Multitasking
```
a := new(int)
child := fiberspawn(|a| {
child := make(fiber, |a| {
for i := 0; i < 5; i++ {
std::println("Child : i=" + std::itoa(i) + " buf=" + std::itoa(a^))
a^ = i * 3
fibercall(parent)
resume(parent)
}
})
for i := 0; i < 10; i++ {
std::println("Parent: i=" + std::itoa(i) + " buf=" + std::itoa(a^))
a^ = i * 7
if fiberalive(child) {
fibercall(child)
if valid(child) {
resume(child)
}
}
```
Expand Down
2 changes: 1 addition & 1 deletion Umka.sublime-syntax
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ file_extensions:
- um
scope: source.umka
variables:
builtin: (append|atan|atan2|cap|ceil|copy|cos|delete|exit|exp|fabs|fiberalive|fibercall|fiberspawn|floor|fprintf|fscanf|insert|keys|len|log|make|memusage|new|printf|round|scanf|selfhasptr|selftypeeq|sin|sizeof|sizeofself|slice|sprintf|sqrt|sscanf|trunc|typeptr|valid|validkey)
builtin: (append|atan|atan2|cap|ceil|copy|cos|delete|exit|exp|fabs|floor|fprintf|fscanf|insert|keys|len|log|make|memusage|new|printf|resume|round|scanf|selfhasptr|selftypeeq|sin|sizeof|sizeofself|slice|sprintf|sqrt|sscanf|trunc|typeptr|valid|validkey)
ident: '[A-Za-z_][A-Za-z_0-9]*'
typeident: '_*[A-Z][A-Za-z_0-9]*'
space: '\s*'
Expand Down
25 changes: 8 additions & 17 deletions doc/lang.md
Original file line number Diff line number Diff line change
Expand Up @@ -702,13 +702,16 @@ fn new(T [, x: T]): ^T
Allocates memory for a variable of type `T`, initializes it with zeros (or with the value `x` if specified) and returns a pointer to it.

```
fn make([]T, length: int): []T // (1)
fn make(map[K]T): map[K]T // (2)
fn make([]T, length: int): []T // (1)
fn make(map[K]T): map[K]T // (2)
fn make(fiber, f: fn(parent: fiber)): fiber // (3)
```

(1) Constructs a dynamic array of `length` items of type `T` initialized with zeroes.

(2) Constructs an empty map with item type `T` indexed by keys of type `K`.
(2) Constructs an empty map with item type `T` indexed by keys of type `K`.

(3) Constructs a fiber and prepares it for calling the function `f`. This function receives the current fiber as `parent`. The actual execution starts on the first call to `resume`.

```
fn copy(a: []T): []T // (1)
Expand Down Expand Up @@ -820,22 +823,10 @@ Returns a dynamic array of the keys that index the items of the map `m`.
##### Multitasking functions

```
fn fiberspawn(childFunc: fn(parent: fiber)): fiber
```

Creates a new fiber and assigns `childFunc` as the fiber function.

```
fn fibercall(child: fiber)
```

Resumes the execution of the `child` fiber.

```
fn fiberalive(child: fiber)
fn resume(fib: fiber)
```

Checks whether the `child` fiber function has not yet returned.
Starts or resumes the execution of the fiber `fib`.

##### Miscellaneous functions

Expand Down
8 changes: 4 additions & 4 deletions examples/raytracer/raytracer.um
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ fn main() {
stopHeight := height / numRenderers * (i + 1)

// Spawn fiber
renderer^ = fiberspawn(|startHeight, stopHeight, numRays, pos, azimuth, focal, antialiasing, scene, pixels| {
renderer^ = make(fiber, |startHeight, stopHeight, numRays, pos, azimuth, focal, antialiasing, scene, pixels| {
sinAz, cosAz := sin(azimuth), cos(azimuth)

for i := startHeight; i < stopHeight; i++ {
Expand All @@ -255,7 +255,7 @@ fn main() {
pixels[i][j] = {round(color[0]), round(color[1]), round(color[2])}
}
printf("%3lld/%3lld\n", i + 1, height)
fibercall(parent)
resume(parent)
}
})
}
Expand All @@ -266,8 +266,8 @@ fn main() {
for true {
working := false
for _, renderer in renderers {
if fiberalive(renderer) {
fibercall(renderer)
if valid(renderer) {
resume(renderer)
working = true
}
}
Expand Down
2 changes: 1 addition & 1 deletion playground/umka.js

Large diffs are not rendered by default.

4 changes: 1 addition & 3 deletions src/umka_compiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,7 @@ static void compilerDeclareBuiltinIdents(Compiler *comp)
identAddBuiltinFunc(&comp->idents, &comp->modules, &comp->blocks, "keys", comp->ptrVoidType, BUILTIN_KEYS);

// Fibers
identAddBuiltinFunc(&comp->idents, &comp->modules, &comp->blocks, "fiberspawn", comp->ptrVoidType, BUILTIN_FIBERSPAWN);
identAddBuiltinFunc(&comp->idents, &comp->modules, &comp->blocks, "fibercall", comp->voidType, BUILTIN_FIBERCALL);
identAddBuiltinFunc(&comp->idents, &comp->modules, &comp->blocks, "fiberalive", comp->boolType, BUILTIN_FIBERALIVE);
identAddBuiltinFunc(&comp->idents, &comp->modules, &comp->blocks, "resume", comp->voidType, BUILTIN_RESUME);

// Misc
identAddBuiltinFunc(&comp->idents, &comp->modules, &comp->blocks, "memusage", comp->intType, BUILTIN_MEMUSAGE);
Expand Down
101 changes: 50 additions & 51 deletions src/umka_expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -925,33 +925,65 @@ static void parseBuiltinNewCall(Compiler *comp, Type **type, Const *constant)
}


// fn make(type: Type [, len: int]): type
// fn make(type: Type, len: int): type
// fn make(type: Type): type
// fn make(type: Type, childFunc: fn(parent: fiber)): type
static void parseBuiltinMakeCall(Compiler *comp, Type **type, Const *constant)
{
if (constant)
comp->error.handler(comp->error.context, "Function is not allowed in constant expressions");

// Dynamic array type
*type = parseType(comp, NULL);
typeAssertCompatibleBuiltin(&comp->types, *type, BUILTIN_MAKE, (*type)->kind == TYPE_DYNARRAY || (*type)->kind == TYPE_MAP);

genPushGlobalPtr(&comp->gen, *type);
typeAssertCompatibleBuiltin(&comp->types, *type, BUILTIN_MAKE, (*type)->kind == TYPE_DYNARRAY || (*type)->kind == TYPE_MAP || (*type)->kind == TYPE_FIBER);

if ((*type)->kind == TYPE_DYNARRAY)
{
// Dynamic array length
lexEat(&comp->lex, TOK_COMMA);

// Dynamic array type
genPushGlobalPtr(&comp->gen, *type);

// Dynamic array length
Type *lenType = comp->intType;
parseExpr(comp, &lenType, NULL);
typeAssertCompatible(&comp->types, comp->intType, lenType);

// Pointer to result (hidden parameter)
int resultOffset = identAllocStack(&comp->idents, &comp->types, &comp->blocks, *type);
genPushLocalPtr(&comp->gen, resultOffset);
}
else // TYPE_MAP
genPushIntConst(&comp->gen, 0);
else if ((*type)->kind == TYPE_MAP)
{
// Map type
genPushGlobalPtr(&comp->gen, *type);

// Pointer to result (hidden parameter)
int resultOffset = identAllocStack(&comp->idents, &comp->types, &comp->blocks, *type);
genPushLocalPtr(&comp->gen, resultOffset);
// Pointer to result (hidden parameter)
int resultOffset = identAllocStack(&comp->idents, &comp->types, &comp->blocks, *type);
genPushLocalPtr(&comp->gen, resultOffset);
}
else if ((*type)->kind == TYPE_FIBER)
{
lexEat(&comp->lex, TOK_COMMA);

// Child fiber closure
Type *fnType = typeAdd(&comp->types, &comp->blocks, TYPE_FN);
typeAddParam(&comp->types, &fnType->sig, comp->anyType, "__upvalues");
typeAddParam(&comp->types, &fnType->sig, comp->fiberType, "parent");
fnType->sig.resultType = comp->voidType;

Type *expectedFiberClosureType = typeAdd(&comp->types, &comp->blocks, TYPE_CLOSURE);
typeAddField(&comp->types, expectedFiberClosureType, fnType, "__fn");
typeAddField(&comp->types, expectedFiberClosureType, comp->anyType, "__upvalues");

Type *fiberClosureType = expectedFiberClosureType;
parseExpr(comp, &fiberClosureType, constant);
doAssertImplicitTypeConv(comp, expectedFiberClosureType, &fiberClosureType, NULL);

// Child fiber closure type (hidden parameter)
genPushGlobalPtr(&comp->gen, fiberClosureType);
}
else
comp->error.handler(comp->error.context, "Illegal type");

genCallBuiltin(&comp->gen, (*type)->kind, BUILTIN_MAKE);
}
Expand Down Expand Up @@ -1460,47 +1492,17 @@ static void parseBuiltinKeysCall(Compiler *comp, Type **type, Const *constant)
}


// fn fiberspawn(childFunc: fn(parent: fiber)): fiber
// fn fibercall(child: fiber)
// fn fiberalive(child: fiber)
static void parseBuiltinFiberCall(Compiler *comp, Type **type, Const *constant, BuiltinFunc builtin)
// fn resume(child: fiber)
static void parseBuiltinResumeCall(Compiler *comp, Type **type, Const *constant)
{
if (constant)
comp->error.handler(comp->error.context, "Function is not allowed in constant expressions");

if (builtin == BUILTIN_FIBERSPAWN)
{
// Child fiber closure
Type *fnType = typeAdd(&comp->types, &comp->blocks, TYPE_FN);
typeAddParam(&comp->types, &fnType->sig, comp->anyType, "__upvalues");
typeAddParam(&comp->types, &fnType->sig, comp->fiberType, "parent");
fnType->sig.resultType = comp->voidType;

Type *expectedFiberClosureType = typeAdd(&comp->types, &comp->blocks, TYPE_CLOSURE);
typeAddField(&comp->types, expectedFiberClosureType, fnType, "__fn");
typeAddField(&comp->types, expectedFiberClosureType, comp->anyType, "__upvalues");

Type *fiberClosureType = expectedFiberClosureType;
parseExpr(comp, &fiberClosureType, constant);
doAssertImplicitTypeConv(comp, expectedFiberClosureType, &fiberClosureType, NULL);

// Child fiber closure type (hidden parameter)
genPushGlobalPtr(&comp->gen, fiberClosureType);

*type = comp->fiberType;
}
else // BUILTIN_FIBERCALL, BUILTIN_FIBERALIVE
{
parseExpr(comp, type, constant);
doAssertImplicitTypeConv(comp, comp->fiberType, type, constant);

if (builtin == BUILTIN_FIBERALIVE)
*type = comp->boolType;
else
*type = comp->voidType;
}
parseExpr(comp, type, constant);
doAssertImplicitTypeConv(comp, comp->fiberType, type, constant);

genCallBuiltin(&comp->gen, TYPE_NONE, builtin);
genCallBuiltin(&comp->gen, TYPE_NONE, BUILTIN_RESUME);
*type = comp->voidType;
}


Expand Down Expand Up @@ -1594,9 +1596,7 @@ static void parseBuiltinCall(Compiler *comp, Type **type, Const *constant, Built
case BUILTIN_KEYS: parseBuiltinKeysCall(comp, type, constant); break;

// Fibers
case BUILTIN_FIBERSPAWN:
case BUILTIN_FIBERCALL:
case BUILTIN_FIBERALIVE: parseBuiltinFiberCall(comp, type, constant, builtin); break;
case BUILTIN_RESUME: parseBuiltinResumeCall(comp, type, constant); break;

// Misc
case BUILTIN_MEMUSAGE: parseBuiltinMemusageCall(comp, type, constant); break;
Expand Down Expand Up @@ -2057,7 +2057,6 @@ static void parseMapLiteral(Compiler *comp, Type **type, Const *constant)
doZeroVar(comp, mapIdent);

genPushGlobalPtr(&comp->gen, *type);
genPushIntConst(&comp->gen, 0);
doPushVarPtr(comp, mapIdent);
genCallBuiltin(&comp->gen, (*type)->kind, BUILTIN_MAKE);

Expand Down
Loading

0 comments on commit 937157b

Please sign in to comment.