Skip to content

Commit

Permalink
Macro definitions within enum declarations
Browse files Browse the repository at this point in the history
closes #15
  • Loading branch information
ysbaddaden committed Mar 11, 2016
1 parent 8cf2aef commit 57f3e64
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 8 deletions.
7 changes: 7 additions & 0 deletions spec/headers/simple.h
Expand Up @@ -52,6 +52,13 @@ enum some_enum_3 {
};
enum some_enum_3 just_some_enum_3();

enum {
SOCK_STREAM = 1,
#define SOCK_STREAM SOCK_STREAM
SOCK_DGRAM = 2,
#define SOCK_DGRAM SOCK_DGRAM
};

typedef struct { int x; } some_struct_1;
some_struct_1 just_some_struct_1();

Expand Down
15 changes: 11 additions & 4 deletions spec/lib_body_transformer_spec.cr
Expand Up @@ -119,11 +119,18 @@ describe LibBodyTransformer do
)

assert_transform "simple",
"fun just_some_struct_1", %(
struct SomeStruct1
x : LibC::Int
"fun just_some_enum_3", %(
enum SomeEnum3
NodePara = 1
NodeLink = 2
end
fun just_some_struct_1 : SomeStruct1
fun just_some_enum_3 : SomeEnum3
)

assert_transform "simple",
"SOCK_STREAM = SOCK_STREAM\nSOCK_DGRAM = SOCK_DGRAM", %(
SOCK_STREAM = 1
SOCK_DGRAM = 2
)

assert_transform "simple",
Expand Down
26 changes: 22 additions & 4 deletions src/crystal_lib/lib_body_transformer.cr
Expand Up @@ -5,7 +5,7 @@ require "compiler/crystal/semantic/*"

class CrystalLib::LibBodyTransformer < Crystal::Transformer
def initialize(nodes : Array(CrystalLib::ASTNode))
@nodes = nodes.index_by &.name
@nodes = nodes
@mapper = TypeMapper.new
end

Expand All @@ -32,15 +32,33 @@ class CrystalLib::LibBodyTransformer < Crystal::Transformer
name = node.value.to_s
match = find_node(name)
raise "can't find constant #{name}" unless match.is_a?(Define)
value = match.value

if name == match.value
# macro definition references an enum value
if enum_value = find_enum_value(name)
value = enum_value.value.to_s
end
end

begin
node.value = Crystal::Parser.parse(match.value)
node.value = Crystal::Parser.parse(value)
rescue ex : Crystal::Exception
raise "can't parse value of constant #{name}: #{match.value}"
raise "can't parse value of constant #{name}: #{value}"
end
node
end

private def find_enum_value(name)
@nodes.each do |node|
next unless node.is_a?(CrystalLib::Enum)
node.values.each do |enum_value|
return enum_value if enum_value.name == name
end
end
nil
end

def transform(node : Crystal::ExternalVar)
name = node.real_name || node.name

Expand All @@ -56,7 +74,7 @@ class CrystalLib::LibBodyTransformer < Crystal::Transformer
end

def find_node(name)
@nodes[name]?
@nodes.find { |node| node.name == name }
end

def check_pending_definitions(node)
Expand Down

0 comments on commit 57f3e64

Please sign in to comment.