Skip to content

Commit

Permalink
Allow iterating through a range
Browse files Browse the repository at this point in the history
  • Loading branch information
RoyalIcing committed Dec 15, 2023
1 parent a4ba207 commit bf343ab
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 29 deletions.
5 changes: 3 additions & 2 deletions lib/orb.ex
Original file line number Diff line number Diff line change
Expand Up @@ -579,8 +579,9 @@ defmodule Orb do
%__MODULE__{global_or_local: :local, identifier: identifier, type: type}
end

def as_set(%__MODULE__{global_or_local: :local, identifier: identifier}) do
{:local_set, identifier}
def as_set(%__MODULE__{global_or_local: :local, identifier: identifier, type: type}) do
Orb.Instruction.local_set(type, identifier, :pop)
# {:local_set, identifier}
end

@behaviour Access
Expand Down
82 changes: 66 additions & 16 deletions lib/orb/dsl.ex
Original file line number Diff line number Diff line change
Expand Up @@ -174,19 +174,32 @@ defmodule Orb.DSL do
block_items = runtime_checks ++ block_items

quote do
%Orb.Func{
name:
case {@wasm_func_prefix, unquote(name)} do
{nil, name} -> name
{prefix, name} -> "#{prefix}.#{name}"
end,
params: unquote(params),
result: unquote(result_type),
local_types: unquote(local_types),
body: unquote(block_items) |> Orb.InstructionSequence.new(),
exported_names: unquote(exported_names)
}
|> Orb.Func.narrow_if_needed()
with do
block_items = unquote(block_items)

body_local_types =
for %{locals: statement_locals} <- block_items do
statement_locals |> IO.inspect(label: "statement_locals")
end
|> List.flatten()

# |> Keyword.new()
local_types = unquote(local_types) ++ body_local_types

%Orb.Func{
name:
case {@wasm_func_prefix, unquote(name)} do
{nil, name} -> name
{prefix, name} -> "#{prefix}.#{name}"
end,
params: unquote(params),
result: unquote(result_type),
local_types: local_types,
body: block_items |> Orb.InstructionSequence.new(),
exported_names: unquote(exported_names)
}
|> Orb.Func.narrow_if_needed()
end
end
end

Expand Down Expand Up @@ -408,6 +421,43 @@ defmodule Orb.DSL do
@doc """
Declare a loop that iterates through a source.
"""
defmacro loop({:<-, _, [{identifier, _, nil} = var, source]}, do: block)
when is_atom(identifier) do
alias Orb.I32

Check warning on line 426 in lib/orb/dsl.ex

View workflow job for this annotation

GitHub Actions / Build and test (26.0.2, 1.15.2)

unused alias I32

Check warning on line 426 in lib/orb/dsl.ex

View workflow job for this annotation

GitHub Actions / Build and test (25.3.2, 1.15.2)

unused alias I32

quote do
with do
var!(unquote(var)) = Orb.VariableReference.local(unquote(identifier), Orb.I32)
%Range{first: first, last: last, step: 1} = unquote(source)

Orb.InstructionSequence.new(
:unknown_effect,
[
Orb.Instruction.local_set(Orb.I32, unquote(identifier), first),
%Orb.Loop{
identifier: unquote(identifier),
body:
Orb.InstructionSequence.new(:unknown_effect, [
unquote(__get_block_items(block)),
Orb.Instruction.local_set(
Orb.I32,
unquote(identifier),
Orb.I32.add(Orb.Instruction.local_get(Orb.I32, unquote(identifier)), 1)
),
%Orb.Loop.Branch{
identifier: unquote(identifier),
if:
Orb.I32.le_u(Orb.Instruction.local_get(Orb.I32, unquote(identifier)), last)
}
])
}
],
locals: [{unquote(identifier), Orb.I32}]
)
end
end
end

defmacro loop({:<-, _, [item, source]}, do: block) do
result_type = nil

Expand All @@ -425,7 +475,7 @@ defmodule Orb.DSL do
), quote(do: unquote(item).identifier)}
end

block_items =
body =
quote(
do:
Orb.IfElse.new(
Expand All @@ -445,7 +495,7 @@ defmodule Orb.DSL do
%Orb.Loop{
identifier: unquote(identifier),
result: unquote(result_type),
body: unquote(block_items)
body: unquote(body)
}
end
end
Expand Down Expand Up @@ -483,7 +533,7 @@ defmodule Orb.DSL do
block_items =
case while do
nil ->
block_items
quote do: Orb.InstructionSequence.new(unquote(block_items))

condition ->
quote do:
Expand Down
26 changes: 18 additions & 8 deletions lib/orb/instruction_sequence.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ defmodule Orb.InstructionSequence do
i64: false,
f32: false,
f64: false
}
},
locals: []

alias Orb.Ops
alias Orb.Constants
Expand All @@ -24,25 +25,28 @@ defmodule Orb.InstructionSequence do
# raise "Inference of result type via reduce is unimplemented for now."
end

def new(type, instructions) when is_list(instructions) do
def new(type, instructions, opts \\ []) when is_list(instructions) do
%__MODULE__{
type: type,
body: instructions
body: instructions,
locals: Keyword.get(opts, :locals, [])
}
end

def do_get_type(type, instructions)
def do_get_type(nil, []), do: :nop
def do_get_type(type, []), do: type
def do_get_type(nil, [head | rest]), do: Ops.typeof(head) |> do_get_type(rest)

def do_get_type(type, [head | rest]) do
type = cond do
head |> Ops.typeof() |> Ops.types_compatible?(type) ->
type
type =
cond do
head |> Ops.typeof() |> Ops.types_compatible?(type) ->
type

true ->
:unknown_effect
end
end

do_get_type(type, rest)
end
Expand All @@ -60,7 +64,13 @@ defmodule Orb.InstructionSequence do
indent
) do
for instruction <- instructions do
[Instructions.do_wat(instruction, indent), "\n"]
case instruction do
%Orb.InstructionSequence{} ->
to_wat(instruction, indent)

_ ->
[Instructions.do_wat(instruction, indent), "\n"]
end
end
end
end
Expand Down
4 changes: 2 additions & 2 deletions lib/orb/loop.ex
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
defmodule Orb.Loop do
@moduledoc false

defstruct [:identifier, :result, :body]
defstruct identifier: nil, result: nil, body: nil

defimpl Orb.ToWat do
alias Orb.ToWat.Instructions

Check warning on line 7 in lib/orb/loop.ex

View workflow job for this annotation

GitHub Actions / Build and test (26.0.2, 1.15.2)

unused alias Instructions

Check warning on line 7 in lib/orb/loop.ex

View workflow job for this annotation

GitHub Actions / Build and test (25.3.2, 1.15.2)

unused alias Instructions
Expand All @@ -19,7 +19,7 @@ defmodule Orb.Loop do
if(result, do: [" (result ", do_type(result), ")"], else: []),
"\n"
],
Enum.map(body, &[Instructions.do_wat(&1, " " <> indent), "\n"]),
Orb.ToWat.to_wat(body, " " <> indent),
[indent, ")"]
]
end
Expand Down
39 changes: 38 additions & 1 deletion test/loop_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ defmodule LoopTest do

import Orb, only: [to_wat: 1]

test "loop" do
test "loop through chars manually" do
defmodule FileNameSafe do
use Orb

Expand Down Expand Up @@ -64,4 +64,41 @@ defmodule LoopTest do
assert wasm_source == to_wat(FileNameSafe)
# assert Wasm.call(FileNameSafe, "body") == 100
end

test "loop 1..10" do
defmodule Loop1To10 do
use Orb

defw sum1to10(), I32, sum: I32 do
loop i <- 1..10 do

Check warning on line 73 in test/loop_test.exs

View workflow job for this annotation

GitHub Actions / Build and test (26.0.2, 1.15.2)

variable "i" is unused (if the variable is not meant to be used, prefix it with an underscore)

Check warning on line 73 in test/loop_test.exs

View workflow job for this annotation

GitHub Actions / Build and test (25.3.2, 1.15.2)

variable "i" is unused (if the variable is not meant to be used, prefix it with an underscore)
sum = sum
end

sum
end
end

wasm_source = """
(module $Loop1To10
(func $sum1to10 (export "sum1to10") (result i32)
(local $sum i32)
(local $i i32)
(i32.const 1)
(local.set $i)
(loop $i
(local.get $sum)
(local.set $sum)
(i32.add (local.get $i) (i32.const 1))
(local.set $i)
(i32.le_u (local.get $i) (i32.const 10))
(br_if $i)
)
(local.get $sum)
)
)
"""

assert wasm_source == to_wat(Loop1To10)
# assert Wasm.call(FileNameSafe, "body") == 100
end
end

0 comments on commit bf343ab

Please sign in to comment.