Skip to content

Commit

Permalink
Updated channel handling for specified direction (send or receive)
Browse files Browse the repository at this point in the history
  • Loading branch information
ritchiecarroll committed Dec 30, 2024
1 parent 3d87f14 commit e0a3e62
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 19 deletions.
11 changes: 9 additions & 2 deletions src/Tests/Behavioral/SelectStatement/SelectStatement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,21 @@ private static void fibonacci(channel<nint> f, channel<nint> quit) {
nint x = 0;
nint y = 1;
while () {
switch (WhenAny(f.ᐸꟷ(x), quit.Receiving)) {
switch (WhenAny(f.ᐸꟷ(x, ), quit.Receiving)) {
case 0:
(x, y) = (y, x + y);
break;
case 1 when ᐸꟷ(quit, OK).ok:
case 1 when ᐸꟷ(quit, ).ok:
fmt.Println("quit");
return;
}
}
}

private static void sendOnly(channel/*<-*/<@string> s) {
s.ᐸꟷ("output"u8);
}

private static void Main() {
var ch = new channel<nint>(2);
ch.ᐸꟷ(1);
Expand Down Expand Up @@ -71,6 +75,9 @@ private static void Main() {
quit.ᐸꟷ(0);
});
fibonacci(f, quit);
var mychanl = new channel<@string>(1);
goǃ(_ => sendOnly(mychanl));
fmt.Println(ᐸꟷ(mychanl));
}

} // end main_package
11 changes: 11 additions & 0 deletions src/Tests/Behavioral/SelectStatement/SelectStatement.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ func fibonacci(f, quit chan int) {
}
}

func sendOnly(s chan<- string) {
s <- "output"
}

func main() {
ch := make(chan int, 2)

Expand Down Expand Up @@ -76,4 +80,11 @@ func main() {
quit <- 0
}()
fibonacci(f, quit)

mychanl := make(chan string)

// function converts bidirectional channel to send only channel
go sendOnly(mychanl)

fmt.Println(<-mychanl)
}
2 changes: 1 addition & 1 deletion src/go2cs2/ToDo.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
b) Handle `case a[f()] = <-c4: // same as: case t := <-c4 { a[f()] = t }`
c) Handle multi-valued assignment form of (with OK to test for closed channel).
d) Test `nil` channel which is never ready for communication
e) Handle channels with specified direction (send or receive)
e) ~~Handle channels with specified direction (send or receive)~~
11) ~~Complete send statement implementation (`visitSendStmt`)~~
12) Complete struct interfaces and embedding (will need C# GoType code converter work)
13) Complete interface inheritance (will need C# GoType code converter work)
Expand Down
8 changes: 8 additions & 0 deletions src/go2cs2/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ const ShadowVarMarker = "\u0394" // Variants: Δ Ʌ ꞥ
const CapturedVarMarker = "\u0297" // Variants: ʗ ɔ ᴄ
const TempVarMarker = "\u1D1B" // Variants: ᴛ Ŧ ᵀ
const TrueMarker = "\u1427" // Variants: ᐧ true
const OverloadDiscriminator = "\uA7F7" // Variants: ꟷ false
const ElipsisOperator = "\uA4F8\uA4F8\uA4F8" // Variants: ꓸꓸꓸ ᐧᐧᐧ
const ChannelLeftOp = "\u1438\uA7F7" // Example: `ch.ᐸꟷ(val)` for `ch <- val`
const ChannelRightOp = "\uA7F7\u1433" // Example: `ch.ꟷᐳ(out var val)` for `val := <-ch`
Expand Down Expand Up @@ -860,6 +861,13 @@ func convertToCSFullTypeName(typeName string) string {
return fmt.Sprintf("%s.channel<%s>", RootNamespace, convertToCSTypeName(typeName[5:]))
}

if strings.HasPrefix(typeName, "chan<- ") {
return fmt.Sprintf("%s.channel/*<-*/<%s>", RootNamespace, convertToCSTypeName(typeName[7:]))
}

if strings.HasPrefix(typeName, "<-chan ") {
return fmt.Sprintf("%s./*<-*/channel<%s>", RootNamespace, convertToCSTypeName(typeName[7:]))
}
if typeName == "func()" {
return "System.Action"
}
Expand Down
10 changes: 9 additions & 1 deletion src/go2cs2/visitSelectStmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ func (v *Visitor) visitSelectStmt(selectStmt *ast.SelectStmt, source ParentBlock

v.targetFile.WriteRune('(')
v.targetFile.WriteString(v.convExpr(sendStmt.Value, nil))

if v.options.useChannelOperators {
v.targetFile.WriteString(", ")
v.targetFile.WriteString(OverloadDiscriminator)
}

v.targetFile.WriteRune(')')
handled = true
} else if exprStmt, ok := comClause.Comm.(*ast.ExprStmt); ok {
Expand Down Expand Up @@ -149,7 +155,9 @@ func (v *Visitor) visitSelectStmt(selectStmt *ast.SelectStmt, source ParentBlock
v.targetFile.WriteString(ChannelLeftOp)
v.targetFile.WriteRune('(')
v.targetFile.WriteString(v.convExpr(unaryExpr.X, nil))
v.targetFile.WriteString(", OK).ok")
v.targetFile.WriteString(", ")
v.targetFile.WriteString(OverloadDiscriminator)
v.targetFile.WriteString(").ok")
} else {
v.targetFile.WriteString(v.convExpr(unaryExpr.X, nil))
v.targetFile.WriteString(".Received(out _)")
Expand Down
15 changes: 3 additions & 12 deletions src/gocore/golib/builtin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,19 +66,10 @@ private static class Zero<T>
public const bool = true;

/// <summary>
/// Defines a constant to return a tuple that includes a boolean success indicator.
/// Defines a constant used as a discriminator for accessing overloads with
/// different return types.
/// </summary>
public const bool OK = false;

/// <summary>
/// Defines a constant to return a tuple that includes an error indicator.
/// </summary>
public const bool ERR = false;

/// <summary>
/// Defines a constant to return a tuple that includes a value.
/// </summary>
public const bool VAL = false;
public const bool = false;

/// <summary>
/// nil is a predeclared identifier representing the zero value for a pointer, channel,
Expand Down
23 changes: 20 additions & 3 deletions src/gocore/golib/channel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -220,14 +220,30 @@ public bool TrySend(in T value, CancellationToken cancellationToken)
/// </summary>
/// <param name="value">Value to send.</param>
/// <remarks>
/// For a buffered channel, method will block the current thread
/// if channel is full.
/// For a buffered channel, method will block the current thread if channel is full.
/// </remarks>
public void Send(in T value)
{
Send(value, CancellationToken.None);
}

/// <summary>
/// Sends an item to channel.
/// </summary>
/// <param name="value">Value to send.</param>
/// <remarks>
/// <para>
/// For a buffered channel, method will block the current thread if channel is full.
/// </para>
/// <para>
/// Defines a Go style channel Send operation.
/// </para>
/// </remarks>
public void ᐸꟷ(in T value)
{
Send(value, CancellationToken.None);
}

/// <summary>
/// Queues an item to channel for sending during select operation returning
/// a wait handle that is set when the send operation is complete.
Expand Down Expand Up @@ -255,11 +271,12 @@ private void ProcessSendQueue(object? state)
/// a wait handle that is set when the send operation is complete.
/// </summary>
/// <param name="value">Value to send.</param>
/// <param name="_">Overload discriminator for different return type.</param>
/// <returns>Wait handle for queued send operation.</returns>
/// <remarks>
/// Defines a Go style channel Send operation.
/// </remarks>
public WaitHandle ᐸꟷ(in T value)
public WaitHandle ᐸꟷ(in T value, bool _)
{
return Sending(value);
}
Expand Down
2 changes: 2 additions & 0 deletions src/gocore/golib/golib.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@
<Using Include="System.Numerics.Complex" Alias="complex128" />
<Using Include="System.Int32" Alias="rune" />
<Using Include="System.UIntPtr" Alias="uintptr" />
<Using Include="System.Numerics.BigInteger" Alias="GoUntyped" />
<Using Include="System.ComponentModel.DescriptionAttribute" Alias="GoTag" />

<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
</ItemGroup>
Expand Down

0 comments on commit e0a3e62

Please sign in to comment.