Skip to content

Commit

Permalink
Merge pull request #428 from matthewmcgarvey/mm/destructuring-1
Browse files Browse the repository at this point in the history
  • Loading branch information
gdotdesign authored May 23, 2021
2 parents d752f5c + f079ff0 commit 22b1933
Show file tree
Hide file tree
Showing 10 changed files with 130 additions and 106 deletions.
2 changes: 1 addition & 1 deletion src/ast/enum_destructuring.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module Mint
class EnumDestructuring < Node
getter name, option, parameters

def initialize(@parameters : Array(TypeVariable),
def initialize(@parameters : Array(Node),
@option : String,
@name : String,
@input : Data,
Expand Down
2 changes: 1 addition & 1 deletion src/ast/tuple_destructuring.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module Mint
class TupleDestructuring < Node
getter parameters

def initialize(@parameters : Array(Variable),
def initialize(@parameters : Array(Node),
@input : Data,
@from : Int32,
@to : Int32)
Expand Down
21 changes: 15 additions & 6 deletions src/compilers/array_destructuring.cr
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
module Mint
class Compiler
def _compile(node : Ast::ArrayDestructuring, value)
def _compile(node : Ast::ArrayDestructuring, variable : String) : Tuple(String, Array(String))
statements = [] of String
if node.spread?
statements = [
"const __ = Array.from(#{value})",
]
statements << "const __ = Array.from(#{variable})"

node
.items
Expand All @@ -22,15 +21,25 @@ module Mint
end

statements << "const #{js.variable_of(node.items.select(Ast::Spread).first.variable)} = __"
statements
else
variables =
node
.items
.join(',') { |param| js.variable_of(param) }

["const [#{variables}] = #{value}"]
statements << "const [#{variables}] = #{variable}"
end
condition =
if node.spread?
"Array.isArray(#{variable}) && #{variable}.length >= #{node.items.size - 1}"
else
"Array.isArray(#{variable}) && #{variable}.length === #{node.items.size}"
end

{
condition,
statements,
}
end
end
end
51 changes: 5 additions & 46 deletions src/compilers/case_branch.cr
Original file line number Diff line number Diff line change
Expand Up @@ -21,55 +21,14 @@ module Mint

if match = node.match
case match
when Ast::ArrayDestructuring
statements =
when Ast::ArrayDestructuring, Ast::TupleDestructuring, Ast::EnumDestructuring
compiled =
_compile(match, variable)

statements << expression

if match.spread?
{
"Array.isArray(#{variable}) && #{variable}.length >= #{match.items.size - 1}",
js.statements(statements),
}
else
{
"Array.isArray(#{variable}) && #{variable}.length === #{match.items.size}",
js.statements(statements),
}
end
when Ast::TupleDestructuring
variables =
match
.parameters
.join(',') { |param| js.variable_of(param) }

{
"Array.isArray(#{variable})",
js.statements([
"const [#{variables}] = #{variable}",
expression,
]),
}
when Ast::EnumDestructuring
variables =
case lookups[match].as(Ast::EnumOption).parameters[0]?
when Ast::EnumRecordDefinition
match.parameters.map do |param|
"const #{js.variable_of(param)} = #{variable}._0.#{param.value}"
end
else
match.parameters.map_with_index do |param, index1|
"const #{js.variable_of(param)} = #{variable}._#{index1}"
end
end

name =
js.class_of(lookups[match])

compiled[1] << expression
{
"#{variable} instanceof #{name}",
js.statements(variables + [expression]),
compiled[0],
js.statements(compiled[1]),
}
else
compiled =
Expand Down
28 changes: 28 additions & 0 deletions src/compilers/enum_destructuring.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module Mint
class Compiler
def _compile(node : Ast::EnumDestructuring, variable : String) : Tuple(String, Array(String))
variables =
case lookups[node].as(Ast::EnumOption).parameters[0]?
when Ast::EnumRecordDefinition
node.parameters.compact_map do |param|
case param
when Ast::TypeVariable
"const #{js.variable_of(param)} = #{variable}._0.#{param.value}"
end
end
else
node.parameters.map_with_index do |param, index1|
"const #{js.variable_of(param)} = #{variable}._#{index1}"
end
end

name =
js.class_of(lookups[node])

{
"#{variable} instanceof #{name}",
variables,
}
end
end
end
15 changes: 15 additions & 0 deletions src/compilers/tuple_destructuring.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module Mint
class Compiler
def _compile(node : Ast::TupleDestructuring, variable : String) : Tuple(String, Array(String))
variables =
node
.parameters
.join(',') { |param| js.variable_of(param) }

{
"Array.isArray(#{variable})",
["const [#{variables}] = #{variable}"],
}
end
end
end
2 changes: 1 addition & 1 deletion src/parsers/enum_destructuring.cr
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ module Mint

option = type_id! EnumDestructuringExpectedOption

parameters = [] of Ast::TypeVariable
parameters = [] of Ast::Node

if char! '('
parameters.concat list(
Expand Down
5 changes: 3 additions & 2 deletions src/parsers/tuple_destructuring.cr
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ module Mint

skip unless head

parameters = [head].concat(
list(terminator: '}', separator: ',') { variable })
parameters = [] of Ast::Node
parameters << head
parameters.concat(list(terminator: '}', separator: ',') { variable })

whitespace

Expand Down
106 changes: 59 additions & 47 deletions src/type_checkers/case_branch.cr
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,7 @@ module Mint
"node" => node,
} if spreads > 1

variables =
item.items.compact_map do |variable|
case variable
when Ast::Variable
{variable.value, condition.parameters[0], variable}
when Ast::Spread
{variable.variable.value, condition, variable.variable}
end
end

scope(variables) do
scope(destructuring_variables(item, condition)) do
resolve_expression(node)
end
when Ast::TupleDestructuring
Expand All @@ -70,57 +60,79 @@ module Mint
"node" => item,
} if item.parameters.size > condition.parameters.size

variables =
item.parameters.map_with_index do |variable, index|
{variable.value, condition.parameters[index], variable}
end

scope(variables) do
scope(destructuring_variables(item, condition)) do
resolve_expression(node)
end
when Ast::EnumDestructuring
check_match(item, condition)

entity =
ast.enums.find(&.name.==(item.name)).not_nil!

option =
entity.options.find(&.value.==(item.option)).not_nil!
scope(destructuring_variables(item, condition)) do
resolve_expression(node)
end
else
check_match(item, condition)
end
end || resolve_expression(node)
end

variables =
case option_param = option.parameters[0]?
when Ast::EnumRecordDefinition
item.parameters.map do |param|
record =
resolve(option_param).as(Record)
private def destructuring_variables(item : Ast::EnumDestructuring, condition)
entity =
ast.enums.find(&.name.==(item.name)).not_nil!

{param.value, record.fields[param.value], param}
end
else
item.parameters.map_with_index do |param, index|
option_type =
resolve(option.parameters[index]).not_nil!
option =
entity.options.find(&.value.==(item.option)).not_nil!

mapping = {} of String => Checkable
case option_param = option.parameters[0]?
when Ast::EnumRecordDefinition
item.parameters.compact_map do |param|
case param
when Ast::TypeVariable
record =
resolve(option_param).as(Record)

entity.parameters.each_with_index do |param2, index2|
mapping[param2.value] = condition.parameters[index2]
end
{param.value, record.fields[param.value], param}
end
end
else
item.parameters.map_with_index do |param, index|
case param
when Ast::TypeVariable
option_type =
resolve(option.parameters[index]).not_nil!

resolved_type =
Comparer.fill(option_type, mapping)
mapping = {} of String => Checkable

{param.value, resolved_type.not_nil!, param}
end
entity.parameters.each_with_index do |param2, index2|
mapping[param2.value] = condition.parameters[index2]
end

scope(variables) do
resolve_expression(node)
resolved_type =
Comparer.fill(option_type, mapping)

{param.value, resolved_type.not_nil!, param}
end
else
check_match(item, condition)
end.compact
end
end

private def destructuring_variables(item : Ast::TupleDestructuring, condition)
item.parameters.map_with_index do |variable, index|
case variable
when Ast::Variable
{variable.value, condition.parameters[index], variable}
end
end || resolve_expression(node)
end.compact
end

private def destructuring_variables(item : Ast::ArrayDestructuring, condition)
item.items.compact_map do |variable|
case variable
when Ast::Variable
{variable.value, condition.parameters[0], variable}
when Ast::Spread
{variable.variable.value, condition, variable.variable}
end
end
end
end
end
4 changes: 2 additions & 2 deletions src/type_checkers/scope.cr
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ module Mint
when Ast::Variable
node if target.value == variable
when Ast::TupleDestructuring
target.parameters.find(&.value.==(variable)).try do |item|
target.parameters.select(Ast::Variable).find(&.value.==(variable)).try do |item|
{node, target.parameters.index(item).not_nil!}
end
end
Expand All @@ -131,7 +131,7 @@ module Mint
when Ast::Variable
node if target.value == variable
when Ast::TupleDestructuring
target.parameters.find(&.value.==(variable)).try do |item|
target.parameters.select(Ast::Variable).find(&.value.==(variable)).try do |item|
{node, target.parameters.index(item).not_nil!}
end
end
Expand Down

0 comments on commit 22b1933

Please sign in to comment.