Skip to content

Instantly share code, notes, and snippets.

@emcake
Created April 30, 2020 21:00
Show Gist options
  • Save emcake/4d03b60dc506a677e544f3cb4e9a96e9 to your computer and use it in GitHub Desktop.
Save emcake/4d03b60dc506a677e544f3cb4e9a96e9 to your computer and use it in GitHub Desktop.
using System;
interface Generator<A,Y,R>
where Y : struct
where R : struct
{
unsafe bool Resume(A a, System.Span<Y> y, System.Span<R> r);
}
struct None {
public static None Value = new None();
}
class FibTo : Generator<None, int, None> {
public int n;
public int pos;
public int n1;
public int n2;
public unsafe bool Resume(None _none, System.Span<int> y, System.Span<None> _r) {
if (this.pos == this.n) {
return true;
}
var next = n1 + n2;
this.n2 = n1;
this.n1 = next;
this.pos++;
y[0] = next;
return false;
}
public static FibTo To(int n) {
return new FibTo(){n = n, pos = 0, n1 = 1, n2 = 0};
}
}
static class Generator {
public static void Run<Y, R,G>(G gen)
where G : class, Generator<None, Y, R>
where R : struct
where Y : struct
{
unsafe {
Span<byte> yb = stackalloc byte[System.Runtime.InteropServices.Marshal.SizeOf(typeof(Y))];
Span<byte> yr = stackalloc byte[System.Runtime.InteropServices.Marshal.SizeOf(typeof(R))];
Span<Y> y = System.Runtime.InteropServices.MemoryMarshal.Cast<byte, Y>(yb);
Span<R> r = System.Runtime.InteropServices.MemoryMarshal.Cast<byte, R>(yr);
bool finished;
do
{
finished = gen.Resume(None.Value, y, r);
if (!finished){
Console.WriteLine($"yield: {y[0]}");
}
}
while (!finished);
Console.WriteLine($"return: {r[0]}");
}
}
}
static class Program {
public static int Main(string[] args) {
Generator.Run<int, None, FibTo>(FibTo.To(10));
}
}
@emcake
Copy link
Author

emcake commented Apr 30, 2020

yield: 1
yield: 2
yield: 3
yield: 5
yield: 8
yield: 13
yield: 21
yield: 34
yield: 55
yield: 89
return: Submission#2+None

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment