Skip to content

Commit

Permalink
Add channel send and receive implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
rama-pang committed Apr 4, 2024
1 parent 688c570 commit 5082931
Show file tree
Hide file tree
Showing 14 changed files with 444 additions and 57 deletions.
81 changes: 76 additions & 5 deletions src/go/ece/microcode/concurrent/channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@ import { Heap } from "../../../heap";
import { auto_cast } from "../../../heap/types/auto_cast";
import { ContextScheduler } from "../../../heap/types/context/scheduler";
import { ContextThread } from "../../../heap/types/context/thread";
import { ControlChanReceive } from "../../../heap/types/control/chan_receive";
import { ControlChanReceiveI } from "../../../heap/types/control/chan_receive_i";
import { ControlChanReceiveStmt } from "../../../heap/types/control/chan_receive_stmt";
import { ControlChanSend } from "../../../heap/types/control/chan_send";
import { ControlChanSendI } from "../../../heap/types/control/chan_send_i";
import { ControlName } from "../../../heap/types/control/name";
import { ControlNameAddress } from "../../../heap/types/control/name_address";
import { PrimitiveNil } from "../../../heap/types/primitive/nil";
import { UserChannel } from "../../../heap/types/user/channel";
import { UserVariable } from "../../../heap/types/user/variable";
Expand All @@ -15,14 +20,17 @@ function evaluate_chan_send(
scheduler: ContextScheduler
) {
const cmd_object = auto_cast(heap, cmd) as ControlChanSend;
const name = cmd_object.get_name_address();
const name = cmd_object.get_name_address() as ControlName;
const value = cmd_object.get_value_address();

const chan_send_i = ControlChanSendI.allocate(heap);
thread.control().push(chan_send_i);
heap.free_object(chan_send_i);

thread.control().push(name.address);
const name_address = ControlNameAddress.allocate(heap, name.get_name());
thread.control().push(name_address);
heap.free_object(name_address);

thread.control().push(value.address);

scheduler.enqueue(thread);
Expand All @@ -37,8 +45,6 @@ function evaluate_chan_send_i(
const name = auto_cast(heap, thread.stash().pop()) as UserVariable;
const value = auto_cast(heap, thread.stash().pop());

console.log(name.stringify())

if (name.get_value().is_nil()) {
throw new Error("evaluate_chan_send_i: nil channel");
}
Expand All @@ -55,4 +61,69 @@ function evaluate_chan_send_i(
value.free();
}

export { evaluate_chan_send, evaluate_chan_send_i };
function evaluate_chan_receive(
cmd: number,
heap: Heap,
thread: ContextThread,
scheduler: ContextScheduler
) {
const cmd_object = auto_cast(heap, cmd) as ControlChanReceive;
const name = cmd_object.get_name_address() as ControlName;

const chan_receive_i = ControlChanReceiveI.allocate(heap);
thread.control().push(chan_receive_i);
heap.free_object(chan_receive_i);

const name_address = ControlNameAddress.allocate(heap, name.get_name());
thread.control().push(name_address);
heap.free_object(name_address);

scheduler.enqueue(thread);
}

function evaluate_chan_receive_stmt(
cmd: number,
heap: Heap,
thread: ContextThread,
scheduler: ContextScheduler
) {
const cmd_object = auto_cast(heap, cmd) as ControlChanReceiveStmt;
const pop_i_cmd = heap.allocate_any({ tag: "pop_i" });

thread.control().push(pop_i_cmd);
thread.control().push(cmd_object.get_body_address().address);

heap.free_object(pop_i_cmd);

scheduler.enqueue(thread);
}

function evaluate_chan_receive_i(
cmd: number,
heap: Heap,
thread: ContextThread,
scheduler: ContextScheduler
) {
const name = auto_cast(heap, thread.stash().pop()) as UserVariable;

if (name.get_value().is_nil()) {
throw new Error("evaluate_chan_receive_i: nil channel");
}

// Note: receive() is responsible for enqueueing the thread.
(name.get_value() as UserChannel).recv(
thread,
scheduler,
PrimitiveNil.allocate_default(heap)
);

name.free();
}

export {
evaluate_chan_send,
evaluate_chan_send_i,
evaluate_chan_receive,
evaluate_chan_receive_stmt,
evaluate_chan_receive_i,
};
56 changes: 55 additions & 1 deletion src/go/ece/microcode/constructor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ContextEnv } from '../../heap/types/context/env';
import { ContextStash } from '../../heap/types/context/stash';
import { Heap } from '../../heap';
import { auto_cast } from '../../heap/types/auto_cast';
import { TAG_USER_type_array, TAG_USER_type_channel, TAG_USER_type_function, TAG_USER_type_struct_decl } from '../../heap/types/tags';
import { TAG_USER_type_array, TAG_USER_type_channel, TAG_USER_type_function, TAG_USER_type_slice, TAG_USER_type_struct_decl } from '../../heap/types/tags';
import { ComplexArray } from '../../heap/types/complex/array';
import { UserTypeArray } from '../../heap/types/user/type/array';
import { UserVariable } from '../../heap/types/user/variable';
Expand All @@ -12,6 +12,10 @@ import { UserTypeStructDecl } from '../../heap/types/user/type/struct_decl';
import { UserTypeStruct } from '../../heap/types/user/type/struct';
import { UserStruct } from '../../heap/types/user/struct';
import { ControlDefaultMake } from '../../heap/types/control/default_make';
import { ControlMake } from '../../heap/types/control/make';
import { ControlMakeI } from '../../heap/types/control/make_i';
import { PrimitiveInt32 } from '../../heap/types/primitive/int32';
import { UserChannel } from '../../heap/types/user/channel';

function evaluate_default_make(cmd: number, heap: Heap, C: ContextControl, S: ContextStash, E: ContextEnv): void {
const make_cmd = auto_cast(heap, cmd) as ControlDefaultMake;
Expand Down Expand Up @@ -51,6 +55,54 @@ function evaluate_default_make(cmd: number, heap: Heap, C: ContextControl, S: Co
heap.free_object(nil_address);
break;
}
default: {
throw new Error("evaluate_default_make: Invalid type");
}
}
}

function evaluate_make(cmd: number, heap: Heap, C: ContextControl, S: ContextStash, E: ContextEnv): void {
const make_cmd = auto_cast(heap, cmd) as ControlMake;

const make_i_cmd = heap.allocate_any({
tag: "make_i",
type: make_cmd.get_type(),
num_args: make_cmd.get_number_of_args(),
});
C.push(make_i_cmd);
heap.free_object(make_i_cmd);

for (let i = 0; i < make_cmd.get_number_of_args(); i++) {
C.push(make_cmd.get_arg_address(i).address);
}
}

function evaluate_make_i(cmd: number, heap: Heap, C: ContextControl, S: ContextStash, E: ContextEnv): void {
const make_cmd = auto_cast(heap, cmd) as ControlMakeI;
const type = make_cmd.get_type();
const num_args = make_cmd.get_number_of_arguments();

switch (type.get_tag()) {
case TAG_USER_type_channel: {
if (num_args > 1) {
throw new Error("evaluate_make: channel expects 1 or 2 arguments");
}
let buffer_size: number;
if (num_args === 0) {
buffer_size = 0;
} else {
const buffer_size_value = auto_cast(heap, S.pop()) as PrimitiveInt32;
buffer_size = buffer_size_value.get_value();
buffer_size_value.free();
}
const channel = new UserChannel(heap, UserChannel.allocate(heap, buffer_size, type));
S.push(channel.address);
channel.free();
break;
}
case TAG_USER_type_slice: {
throw new Error("evaluate_make: Not implemented");
}
default: {
throw new Error("evaluate_make: Invalid type");
}
Expand Down Expand Up @@ -104,6 +156,8 @@ function evaluate_constructor_i(cmd: number, heap: Heap, C: ContextControl, S: C

export {
evaluate_default_make,
evaluate_make,
evaluate_make_i,
evaluate_constructor,
evaluate_constructor_i,
};
10 changes: 10 additions & 0 deletions src/go/ece/microcode/lookup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ function lookup_microcode_sequential(tag: number): Function {
return control_var.evaluate_name_address;
case tags.TAG_CONTROL_default_make:
return constructor.evaluate_default_make;
case tags.TAG_CONTROL_make:
return constructor.evaluate_make;
case tags.TAG_CONTROL_make_i:
return constructor.evaluate_make_i;
case tags.TAG_CONTROL_index:
return array.evaluate_index;
case tags.TAG_CONTROL_index_i:
Expand Down Expand Up @@ -125,6 +129,12 @@ function lookup_microcode(tag: number): Function {
return concurrent_channel.evaluate_chan_send;
case tags.TAG_CONTROL_chan_send_i:
return concurrent_channel.evaluate_chan_send_i;
case tags.TAG_CONTROL_chan_receive:
return concurrent_channel.evaluate_chan_receive;
case tags.TAG_CONTROL_chan_receive_stmt:
return concurrent_channel.evaluate_chan_receive_stmt;
case tags.TAG_CONTROL_chan_receive_i:
return concurrent_channel.evaluate_chan_receive_i;
default:
return (
cmd: number,
Expand Down
36 changes: 33 additions & 3 deletions src/go/heap/heap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ import { ControlIndexI } from "./types/control/index_i";
import { ControlLiteral } from "./types/control/literal";
import { ControlLogicalI } from "./types/control/logical_i";
import { ControlLogicalImmI } from "./types/control/logical_imm_i";
import { ControlMake } from "./types/control/make";
import { ControlMakeI } from "./types/control/make_i";
import { ControlMember } from "./types/control/member";
import { ControlMemberAddress } from "./types/control/member_address";
import { ControlMemberAddressI } from "./types/control/member_address_i";
Expand Down Expand Up @@ -169,7 +171,9 @@ import {
TAGSTRING_CONTROL_method_member,
TAGSTRING_CONTROL_member_address_i,
TAGSTRING_CONTROL_push_i,
TAGSTRING_CONTROL_default_make
TAGSTRING_CONTROL_default_make,
TAGSTRING_CONTROL_make_i,
TAGSTRING_CONTROL_make
} from "./types/tags";
import { UserType } from "./types/user/type";
import { UserTypeArray } from "./types/user/type/array";
Expand Down Expand Up @@ -937,6 +941,28 @@ class Heap {
return ControlDefaultMake.allocate(this, obj.type, obj.args);
}

/**
* CONTROL_make
* Fields : number of children
* Children :
* - 4 bytes address of the type (type)
* - 4 bytes * num_arguments address of the arguments (expression)
*/
public allocate_CONTROL_make(obj: { tag: string, type: any, args: any[] }): number {
return ControlMake.allocate(this, obj.type, obj.args);
}

/**
* CONTROL_make_i
* Fields : number of children
* Children :
* - 4 bytes address of the type (USER_type)
* - 4 bytes number of arguments (PRIMITIVE_int32)
*/
public allocate_CONTROL_make_i(obj: { tag: string, type: UserType, num_args: number }): number {
return ControlMakeI.allocate(this, obj.type, obj.num_args);
}

/**
* CONTROL_index
* Fields : number of children
Expand Down Expand Up @@ -1024,8 +1050,8 @@ class Heap {
* Children :
* - 4 bytes address of the name of the channel (COMPLEX_string)
*/
public allocate_CONTROL_chan_receive_stmt(obj: { tag: string, name: any }): number {
return ControlChanReceiveStmt.allocate(this, obj.name);
public allocate_CONTROL_chan_receive_stmt(obj: { tag: string, body: any }): number {
return ControlChanReceiveStmt.allocate(this, obj.body);
}

/**
Expand Down Expand Up @@ -1320,6 +1346,8 @@ class Heap {
return this.allocate_CONTROL_name_address(obj);
case TAGSTRING_CONTROL_default_make:
return this.allocate_CONTROL_default_make(obj);
case TAGSTRING_CONTROL_make:
return this.allocate_CONTROL_make(obj);
case TAGSTRING_CONTROL_index:
return this.allocate_CONTROL_index(obj);
case TAGSTRING_CONTROL_index_i:
Expand All @@ -1332,6 +1360,8 @@ class Heap {
return this.allocate_CONTROL_constructor(obj);
case TAGSTRING_CONTROL_constructor_i:
return this.allocate_CONTROL_constructor_i(obj);
case TAGSTRING_CONTROL_make_i:
return this.allocate_CONTROL_make_i(obj);
case TAGSTRING_CONTROL_chan_send:
return this.allocate_CONTROL_chan_send(obj);
case TAGSTRING_CONTROL_chan_receive:
Expand Down
28 changes: 28 additions & 0 deletions src/go/heap/types/auto_cast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ import { ComplexPointer } from "./complex/pointer";
import { ComplexString } from "./complex/string";
import { ContextControl } from "./context/control";
import { ContextEnv } from "./context/env";
import { ContextScheduler } from "./context/scheduler";
import { ContextStash } from "./context/stash";
import { ContextThread } from "./context/thread";
import { ContextWaitingInstance } from "./context/waiting_instance";
import { ContextWaker } from "./context/waker";
import { ControlIndex } from "./control";
import { ControlAssign } from "./control/assign";
import { ControlAssignI } from "./control/assign_i";
Expand All @@ -21,6 +24,7 @@ import { ControlCall } from "./control/call";
import { ControlCallI } from "./control/call_i";
import { ControlCallStmt } from "./control/call_stmt";
import { ControlChanReceive } from "./control/chan_receive";
import { ControlChanReceiveI } from "./control/chan_receive_i";
import { ControlChanReceiveStmt } from "./control/chan_receive_stmt";
import { ControlChanSend } from "./control/chan_send";
import { ControlChanSendI } from "./control/chan_send_i";
Expand All @@ -40,6 +44,8 @@ import { ControlIndexAddressI } from "./control/index_address_i";
import { ControlIndexI } from "./control/index_i";
import { ControlLogicalI } from "./control/logical_i";
import { ControlLogicalImmI } from "./control/logical_imm_i";
import { ControlMake } from "./control/make";
import { ControlMakeI } from "./control/make_i";
import { ControlMember } from "./control/member";
import { ControlMemberAddress } from "./control/member_address";
import { ControlMemberAddressI } from "./control/member_address_i";
Expand Down Expand Up @@ -155,7 +161,15 @@ import {
TAG_CONTROL_push_i,
TAG_CONTROL_chan_send_i,
TAG_CONTROL_default_make,
TAG_CONTROL_make,
TAG_CONTROL_make_i,
TAG_USER_channel,
TAG_CONTEXT_scheduler,
TAG_CONTEXT_waker,
TAG_CONTEXT_waiting_instance,
TAG_CONTROL_chan_receive_i,
} from "./tags"
import { UserChannel } from "./user/channel";
import { UserStruct } from "./user/struct";
import { UserTypeArray } from "./user/type/array";
import { UserTypeBool } from "./user/type/bool";
Expand Down Expand Up @@ -272,6 +286,10 @@ function auto_cast(heap: Heap, address: number): HeapObject {
return new ControlNameAddress(heap, address);
case TAG_CONTROL_default_make:
return new ControlDefaultMake(heap, address);
case TAG_CONTROL_make:
return new ControlMake(heap, address);
case TAG_CONTROL_make_i:
return new ControlMakeI(heap, address);
case TAG_CONTROL_index:
return new ControlIndex(heap, address);
case TAG_CONTROL_index_i:
Expand All @@ -290,6 +308,8 @@ function auto_cast(heap: Heap, address: number): HeapObject {
return new ControlChanSendI(heap, address);
case TAG_CONTROL_chan_receive:
return new ControlChanReceive(heap, address);
case TAG_CONTROL_chan_receive_i:
return new ControlChanReceiveI(heap, address);
case TAG_CONTROL_chan_receive_stmt:
return new ControlChanReceiveStmt(heap, address);
case TAG_CONTROL_struct:
Expand All @@ -316,10 +336,18 @@ function auto_cast(heap: Heap, address: number): HeapObject {
return new ContextStash(heap, address);
case TAG_CONTEXT_env:
return new ContextEnv(heap, address);
case TAG_CONTEXT_scheduler:
return new ContextScheduler(heap, address);
case TAG_CONTEXT_waker:
return new ContextWaker(heap, address);
case TAG_CONTEXT_waiting_instance:
return new ContextWaitingInstance(heap, address);
case TAG_USER_variable:
return new UserVariable(heap, address);
case TAG_USER_struct:
return new UserStruct(heap, address);
case TAG_USER_channel:
return new UserChannel(heap, address);
case TAG_USER_type_array:
return new UserTypeArray(heap, address);
case TAG_USER_type_bool:
Expand Down
Loading

0 comments on commit 5082931

Please sign in to comment.