From 2717d4095b304e832d88e4db46bde80ed16a7f63 Mon Sep 17 00:00:00 2001 From: Bartek Nowotarski Date: Wed, 5 Jun 2019 14:26:43 +0200 Subject: [PATCH] Support for standard type union discriminant with constant value (#44) `Union.resolved_case` doesn't support unions with standard type discriminant and constant (`const`) values, ex: ```xdr enum StellarValueType { STELLAR_VALUE_BASIC = 0, STELLAR_VALUE_SIGNED = 1 }; union switch (int v) { case STELLAR_VALUE_BASIC: void; ... ``` To fix this, we are searching for identifier in namespace's enum constants if discriminant type has not been found. --- lib/xdrgen/ast/definitions/union.rb | 23 +++++++++++++++++++++-- lib/xdrgen/generators/go.rb | 6 +++++- lib/xdrgen/generators/java.rb | 14 ++++++++++++-- lib/xdrgen/generators/javascript.rb | 7 ++++++- 4 files changed, 44 insertions(+), 6 deletions(-) diff --git a/lib/xdrgen/ast/definitions/union.rb b/lib/xdrgen/ast/definitions/union.rb index 11a9a104f..83f9fea09 100644 --- a/lib/xdrgen/ast/definitions/union.rb +++ b/lib/xdrgen/ast/definitions/union.rb @@ -19,8 +19,27 @@ class Union < Base end def resolved_case(kase) - found = discriminant_type.members.find{|m| m.name == kase.value_s} - raise "Case error: #{kase} is not a member of #{discriminant_type.name}" if found.nil? + if discriminant_type.nil? then + # discriminant_type has not been found we need to search for the value in namespace's enum constants. + # It's a case where union discriminant is a standard type (like `int`): + # + # enum StellarValueType + # { + # STELLAR_VALUE_BASIC = 0, + # STELLAR_VALUE_SIGNED = 1 + # }; + # + # union switch (int v) + # { + # case STELLAR_VALUE_BASIC: + # void; + # ... + found = namespace.find_enum_value(kase.value_s) + raise "Case error: #{kase} (#{kase.value_s}) constant not found" if found.nil? + else + found = discriminant_type.members.find{|m| m.name == kase.value_s} + raise "Case error: #{kase} is not a member of #{discriminant_type.name}" if found.nil? + end found end diff --git a/lib/xdrgen/generators/go.rb b/lib/xdrgen/generators/go.rb index d8c4a61fd..ed3e4b84c 100644 --- a/lib/xdrgen/generators/go.rb +++ b/lib/xdrgen/generators/go.rb @@ -534,7 +534,11 @@ def switch_for(out, union, ident) value = if c.value.is_a?(AST::Identifier) member = union.resolved_case(c) - "#{name union.discriminant_type}#{name member}" + if union.discriminant_type.nil? then + "int32(#{name member.enum}#{name member})" + else + "#{name union.discriminant_type}#{name member}" + end else c.value.text_value end diff --git a/lib/xdrgen/generators/java.rb b/lib/xdrgen/generators/java.rb index cd36b4291..1e9973f4f 100644 --- a/lib/xdrgen/generators/java.rb +++ b/lib/xdrgen/generators/java.rb @@ -251,7 +251,12 @@ def render_union(union, out) else arm.cases.each do |kase| if kase.value.is_a?(AST::Identifier) - out.puts "case #{kase.value.name}:" + if type_string(union.discriminant.type) == "Integer" + member = union.resolved_case(kase) + out.puts "case #{member.value}:" + else + out.puts "case #{kase.value.name}:" + end else out.puts "case #{kase.value.value}:" end @@ -285,7 +290,12 @@ def render_union(union, out) else arm.cases.each do |kase| if kase.value.is_a?(AST::Identifier) - out.puts "case #{kase.value.name}:" + if type_string(union.discriminant.type) == "Integer" + member = union.resolved_case(kase) + out.puts "case #{member.value}:" + else + out.puts "case #{kase.value.name}:" + end else out.puts "case #{kase.value.value}:" end diff --git a/lib/xdrgen/generators/javascript.rb b/lib/xdrgen/generators/javascript.rb index eb1e090ac..6e4508622 100644 --- a/lib/xdrgen/generators/javascript.rb +++ b/lib/xdrgen/generators/javascript.rb @@ -128,7 +128,12 @@ def render_union(out, union) arm.cases.each do |acase| switch = if acase.value.is_a?(AST::Identifier) - '"' + member_name(acase.value) + '"' + if union.discriminant.type.is_a?(AST::Typespecs::Int) + member = union.resolved_case(acase) + "#{member.value}" + else + '"' + member_name(acase.value) + '"' + end else acase.value.text_value end