Showing with 60 additions and 72 deletions.
  1. +1 −1 .ruby-version
  2. +19 −19 ast.rb
  3. +0 −2 ast_parser.rb
  4. +20 −10 float.rb
  5. +1 −20 helpers.rb
  6. +3 −3 test.sh
  7. +16 −17 wasminna.rb
2 changes: 1 addition & 1 deletion .ruby-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.1
3.2.0
38 changes: 19 additions & 19 deletions ast.rb
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
module AST
Return = Struct.new(nil)
LocalGet = Struct.new(:index, keyword_init: true)
LocalSet = Struct.new(:index, keyword_init: true)
LocalTee = Struct.new(:index, keyword_init: true)
BrIf = Struct.new(:index, keyword_init: true)
Select = Struct.new(nil)
Nop = Struct.new(nil)
Call = Struct.new(:index, keyword_init: true)
Drop = Struct.new(nil)
Block = Struct.new(:label, :body, keyword_init: true)
Loop = Struct.new(:label, :body, keyword_init: true)
If = Struct.new(:label, :consequent, :alternative, keyword_init: true)
Const = Struct.new(:type, :bits, :number, keyword_init: true)
Load = Struct.new(:type, :bits, :offset, keyword_init: true)
Store = Struct.new(:type, :bits, :offset, keyword_init: true)
UnaryOp = Struct.new(:type, :bits, :operation, keyword_init: true)
BinaryOp = Struct.new(:type, :bits, :operation, keyword_init: true)
Unreachable = Struct.new(nil)
BrTable = Struct.new(:target_indexes, :default_index, keyword_init: true)
Return = Data.define
LocalGet = Data.define(:index)
LocalSet = Data.define(:index)
LocalTee = Data.define(:index)
BrIf = Data.define(:index)
Select = Data.define
Nop = Data.define
Call = Data.define(:index)
Drop = Data.define
Block = Data.define(:label, :body)
Loop = Data.define(:label, :body)
If = Data.define(:label, :consequent, :alternative)
Const = Data.define(:type, :bits, :number)
Load = Data.define(:type, :bits, :offset)
Store = Data.define(:type, :bits, :offset)
UnaryOp = Data.define(:type, :bits, :operation)
BinaryOp = Data.define(:type, :bits, :operation)
Unreachable = Data.define
BrTable = Data.define(:target_indexes, :default_index)
end
2 changes: 0 additions & 2 deletions ast_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,6 @@ def unfold(s_expression)
\z
}x

using Helpers::MatchPattern

def parse_expression(terminated_by:)
with_input(read_until(terminated_by:)) do
[].tap do |expression|
Expand Down
30 changes: 20 additions & 10 deletions float.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

module Wasminna
module Float
class Format < Struct.new(:exponent_bits, :significand_bits, keyword_init: true)
class Format < Data.define(:exponent_bits, :significand_bits)
include Helpers::Mask

ALL = [
Expand Down Expand Up @@ -141,8 +141,6 @@ def decode(encoded, format:)
\z
}x

using Helpers::MatchPattern

def parse(string)
if finite_regexp_match(string) in [
{ sign:, whole:, fractional:, exponent_sign:, exponent: },
Expand Down Expand Up @@ -186,11 +184,15 @@ def finite_regexp_match(string)
end
end

Infinite = Struct.new(:sign, keyword_init: true) do
Infinite = Data.define(:sign) do
def to_f
::Float::INFINITY * sign
end

def with_sign(sign)
self.class.new(**to_h, sign:)
end

def encode(format:)
format.pack \
sign:,
Expand All @@ -199,13 +201,17 @@ def encode(format:)
end
end

Nan = Struct.new(:payload, :sign, keyword_init: true) do
Nan = Data.define(:payload, :sign) do
include Helpers::Mask

def to_f
::Float::NAN
end

def with_sign(sign)
self.class.new(**to_h, sign:)
end

def encode(format:)
fraction = mask(payload, bits: format.fraction_bits)
fraction |= 1 << (format.fraction_bits - 1) if fraction.zero?
Expand All @@ -217,11 +223,15 @@ def encode(format:)
end
end

Zero = Struct.new(:sign, keyword_init: true) do
Zero = Data.define(:sign) do
def to_f
0.0 * sign
end

def with_sign(sign)
self.class.new(**to_h, sign:)
end

def encode(format:)
format.pack \
sign:,
Expand All @@ -230,7 +240,7 @@ def encode(format:)
end
end

Finite = Struct.new(:rational, keyword_init: true) do
Finite = Data.define(:rational) do
include Helpers::Mask

def to_f
Expand All @@ -241,8 +251,8 @@ def sign
rational.sign
end

def sign=(sign)
self.rational = rational.abs * sign
def with_sign(sign)
self.class.new(**to_h, rational: rational.abs * sign)
end

def encode(format:)
Expand Down Expand Up @@ -274,7 +284,7 @@ def approximate_within(format:)
end
end

Approximation = Struct.new(:rational, :exponent, keyword_init: true) do
Approximation = Struct.new(:rational, :exponent) do
def fit_within(quotients:, exponents:)
scale_within(quotients:, exponents:)
round_within(quotients:, exponents:)
Expand Down
21 changes: 1 addition & 20 deletions helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,7 @@ module SizeOf
private

def size_of(value, **kwargs)
quotient, remainder = value.divmod(kwargs.fetch(:in))
if remainder.zero?
quotient
else
quotient + 1
end
end
end

module MatchPattern
refine MatchData do
def deconstruct_keys(keys)
named_captures.transform_keys(&:to_sym).then do |captures|
if keys
captures.slice(*keys)
else
captures
end
end
end
value.ceildiv(kwargs.fetch(:in))
end
end
end
6 changes: 3 additions & 3 deletions test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,21 @@ for test in s_expression_parser_test float_test
do
file=$test.rb
printf "\e[1m%s\e[0m: " "$file"
ruby -W:no-experimental -I"$WASMINNA_PATH" "$WASMINNA_PATH"/$file
ruby -I"$WASMINNA_PATH" "$WASMINNA_PATH"/$file
done

for script in int_literals i32 i64 int_exprs float_literals conversions f32 f32_bitwise f32_cmp f64 f64_bitwise f64_cmp float_memory float_exprs float_misc const
do
file=$script.wast
printf "\e[1m%s\e[0m: " "$file"
ruby -W:no-experimental -I"$WASMINNA_PATH" "$WASMINNA_PATH"/wasminna.rb "$WASM_SPEC_PATH"/test/core/$file
ruby -I"$WASMINNA_PATH" "$WASMINNA_PATH"/wasminna.rb "$WASM_SPEC_PATH"/test/core/$file
done

for pending in
do
file=$pending.wast
printf "\e[1m%s\e[0m (pending): " "$file"
if ruby -W:no-experimental -I"$WASMINNA_PATH" "$WASMINNA_PATH"/wasminna.rb "$WASM_SPEC_PATH"/test/core/$file; then
if ruby -I"$WASMINNA_PATH" "$WASMINNA_PATH"/wasminna.rb "$WASM_SPEC_PATH"/test/core/$file; then
printf "\e[31merror: pending test passed\e[0m\n"
exit 1
else
Expand Down
33 changes: 16 additions & 17 deletions wasminna.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ class Interpreter
include AST
include Helpers::Mask

Parameter = Struct.new(:name, keyword_init: true)
Local = Struct.new(:name, keyword_init: true)
Function = Struct.new(:name, :parameters, :locals, :body, keyword_init: true)
Parameter = Data.define(:name)
Local = Data.define(:name)
Function = Data.define(:name, :parameters, :locals, :body)

class Memory < Struct.new(:bytes, keyword_init: true)
class Memory < Data.define(:bytes)
include Helpers::Mask
include Helpers::SizeOf
extend Helpers::SizeOf
Expand Down Expand Up @@ -150,26 +150,28 @@ def interpret_script(script)
using Sign::Conversion

def define_function(expressions:)
Function.new(parameters: [], locals: [], body: []).tap do |function|
{ name: nil, parameters: [], locals: [], body: [] }.tap do |function|
expressions.each do |expression|
case expression
in ['export', name]
function.name = name
function[:name] = name
in ['param', %r{\A\$} => name, _]
function.parameters << Parameter.new(name:)
function[:parameters] << Parameter.new(name:)
in ['param', *types]
function.parameters.concat(types.map { Parameter.new })
function[:parameters].concat(types.map { Parameter.new(name: nil) })
in ['result', *]
in ['local', %r{\A\$} => name, _]
function.locals << Local.new(name:)
function[:locals] << Local.new(name:)
in ['local', *types]
types.each do
function.locals << Local.new
function[:locals] << Local.new(name: nil)
end
else
function.body << expression
function[:body] << expression
end
end
end.then do |attributes|
Function.new(**attributes)
end
end

Expand Down Expand Up @@ -477,8 +479,7 @@ def evaluate_float_instruction(instruction)
in 'copysign'
left, right =
[left, right].map { Wasminna::Float.decode(_1, format:) }
left.sign = right.sign
left.encode(format:)
left.with_sign(right.sign).encode(format:)
in 'eq' | 'ne' | 'lt' | 'le' | 'gt' | 'ge'
left, right =
[left, right].map { Wasminna::Float.decode(_1, format:).to_f }
Expand Down Expand Up @@ -530,12 +531,10 @@ def evaluate_float_instruction(instruction)
end
in 'abs'
value = Wasminna::Float.decode(value, format:)
value.sign = Sign::PLUS
value.encode(format:)
value.with_sign(Sign::PLUS).encode(format:)
in 'neg'
value = Wasminna::Float.decode(value, format:)
value.sign = !value.sign
value.encode(format:)
value.with_sign(!value.sign).encode(format:)
in 'convert_i32_s' | 'convert_i64_s'
integer_bits = operation.slice(%r{\d+}).to_i(10)
integer = signed(value, bits: integer_bits)
Expand Down