diff --git a/src/union.jl b/src/union.jl index 3bc3406..91fbc4c 100644 --- a/src/union.jl +++ b/src/union.jl @@ -82,24 +82,49 @@ function makeUniontypes(name, records, lineNode::LineNumberNode) local block = r[2] #= Get the block. That is r[2]=# blckExprs = block.args varToDecl = Dict() - local i::Int = 0 - local exprCounter::Int = 1 + varToContainerDecl = Dict() + local i = 0 + local cti = 0 for expr in blckExprs - if typeof(expr) === LineNumberNode #= Ignore comment lines =# + #= Skip comments =# + if typeof(expr) === LineNumberNode + continue + end + #= Ignore option types=# + if @capture(expr, T_::Option{TYPE_}) + continue + end + #= Below is some better code for better type stability in uniontypes... =# + #= Check if we have a container type =# + if @capture(expr, T_::F_{TYPE_}) + #= Keep abstract type as is=# + @assert expr.head === :(::) + containerType = expr.args[2] + #= Write to {} =# + res = @capture(containerType, OUTER_{INNER_}) + #= Assert that the type is on this format =# + @assert res == true + #= containerType.args[2] = <:Any =# + local parametricType = Symbol("CT", cti) + varToContainerDecl[T] = [parametricType, INNER] + containerType.args[2] = parametricType + #= Write to the innermost type =# + cti += 1 continue end - #= Check if we have a uniontype type declaration. =# if (@capture(expr, T_::TYPE_)) - parametricType::Symbol = Symbol("T", i) - varToDecl[T] = [parametricType, TYPE] + local parametricType = Symbol("T", i) i += 1 + varToDecl[T] = [parametricType, TYPE] newExpr = expr newExpr.args[2] = parametricType end - exprCounter += 1 end local structName = r[1] - parametricTypes::Vector{Expr} = [ :($(varToDecl[i][1]) <: $(varToDecl[i][2])) for i in keys(varToDecl)] + parametricTypes::Vector = [ :($(varToDecl[i][1])) + for i in keys(varToDecl)] + parametricContainerTypes::Vector = [ :($(varToContainerDecl[i][1])) + for i in keys(varToContainerDecl)] recordNode = quote struct $(structName){$(parametricTypes...)} <: $name $(r[2]) diff --git a/test/runtimeTest.jl b/test/runtimeTest.jl index 46fcd2e..abad416 100644 --- a/test/runtimeTest.jl +++ b/test/runtimeTest.jl @@ -44,11 +44,69 @@ end @test length(arr) == 6 end +using MetaModelica +using Test +using Revise @Uniontype Complex begin @Record COMPLEX begin r::ModelicaReal i::ModelicaReal end + @Record COMPLEX_INT begin + r::ModelicaInteger + i::ModelicaInteger + end +end + +@Uniontype EvenMoreComplex begin + @Record EVENMORECOMPLEX begin + lst::List{Complex} + end +end + +@Uniontype EvenMoreComplexVector begin + @Record EVENMORECOMPLEXVECTOR begin + lst::Vector{Complex} + end +end + + +@Uniontype InnerLists begin + @Record INNERLISTS begin + a::String + lst0::List{String} + lst1::List{String} + lst2::List{String} + end +end + +@Uniontype InnerVectors begin + @Record INNERVECTORS begin + a::String + lst0::Vector{String} + lst1::Vector{String} + lst2::Vector{String} + end +end + +@Uniontype Comment begin + @Record COMMENT begin + annotation_::Option{String} + comment::Option{String} + end +end + +struct TEST2{T0 <: String} + lst0::Vector{T0} + lst1::Vector{T0} + lst2::Vector{T0} +end + +struct TEST4{T0 <: String, T1 <: String, T2 <: String, T3 <: String} + a::T0 + lst0::List{T1} + lst1::List{T2} + lst2::List{T3} end @testset "Complex structure test" begin @@ -69,6 +127,18 @@ end local L::List{Complex} = arrayList(A) @test length(L) == 5 end + @testset "Test even more complex (Uniontype with abstract containers)" begin + a = COMPLEX(1., 2.) + tst = EVENMORECOMPLEX(list(a)) + @test length(tst.lst) == 1 + tst = EVENMORECOMPLEX(list(COMPLEX(1., 2.), COMPLEX_INT(1,1))) + @test length(tst.lst) == 2 + tst = EVENMORECOMPLEXVECTOR([COMPLEX(1., 2.), COMPLEX(1., 2.)]) + @test length(tst.lst) == 2 + tst = INNERVECTORS("foo", ["FOO"], String[], String[]) + tst = INNERLISTS("foo", list("FOO"), Nil{String}(), Nil{String}()) + tst = COMMENT(NONE(), NONE()) + end end @testset "Testing array copy" begin