Skip to content

Commit

Permalink
Updates to MetaModelica.jö
Browse files Browse the repository at this point in the history
  • Loading branch information
JKRT committed Aug 13, 2023
1 parent 6c32939 commit 19f7c8a
Show file tree
Hide file tree
Showing 7 changed files with 208 additions and 43 deletions.
1 change: 1 addition & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ version = "0.0.2"
[deps]
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
ExportAll = "ad2082ca-a69e-11e9-38fa-e96309a31fe4"
FastClosures = "9aa1b823-49e4-5ca5-8b0f-3971ec8bab6a"
ImmutableList = "4a558cac-c1ed-11e9-20da-3584bcd8709a"
MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
Setfield = "efcf1570-3423-57d1-acb7-fd33fddbac46"
Expand Down
2 changes: 1 addition & 1 deletion src/MetaModelica.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export @match, @matchcontinue, MatchFailure, ModelicaReal, ModelicaInteger
export @Uniontype, @Record, @UniontypeDecl, @ExtendedFunction, @ExtendedAnonFunction
export List, list, Nil, nil, Cons, cons, =>, Option, SOME, NONE, SourceInfo, SOURCEINFO
export @do_threaded_for, <|, @shouldFail, sourceInfo, _cons, @importDBG
export @assign
export @assign, @Mutable_Uniontype, @closure

include("exportmetaRuntime.jl")
include("dangerous.jl")
Expand Down
126 changes: 119 additions & 7 deletions src/dangerous.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ end
access an uninitialized elements may cause segmentation faults if you're
lucky, and pretty much anything else if you're not. Do not use unless you will
immediately fill the whole array with data. The dummy variable is used to fix
the type of the array. """
the type of the array.
"""
function arrayCreateNoInit(size::ModelicaInteger, dummy::A)::Array{A} where {A}
local arr::Array{A} = fill(dummy, size)
arr
Expand All @@ -43,23 +44,134 @@ function listReverseInPlace(inList::List{T})::List{T} where {T}
MetaModelica.listReverse(inList)
end

""" O(1). A destructive operation changing the \"first\" part of a cons-cell. """
function listSetFirst(inConsCell::List{A}, inNewContent::A) where {A} #= A non-empty list =#
@error "Not listSetFirst defined in the runtime"

function listReverseInPlace2(inList::Nil)
return inList#MetaModelica.listReverse(inList)
end

"""
Unsafe implementation of list reverse in place.
Instead of creating new cons cells we swap pointers...
"""
function listReverseInPlace2(lst::Cons{T}) where {T}
local prev = nil
#= Declare an unsafe pointer to the list =#
local oldCdrPtr::Ptr{List{T}}
GC.@preserve while (!(lst isa Nil))
println("prev at the iteration:")
println(prev)
println("lst at the iteration:")
println(lst)
println("before oldCdr = $(lst.tail)")
oldCdr = deepcopy(lst.tail)
println("Before listSetRest($lst, $prev)")
listSetRest(lst, prev)
println("Before prev = $lst")
prev = lst
println("Before lst = $(oldCdr) //oldCdr")
lst = oldCdr
end
println("After loop")
return prev
end


"""
O(1). A destructive operation changing the \"first\" part of a cons-cell.
TODO: Not implemented
"""
function listSetFirst(inConsCell::Cons{A}, inNewContent::A) where {A} #= A non-empty list =#
firstPtr::Ptr{A} = unsafe_getListAsPtr(inConsCell)
#local newHead = Cons{T}(inNewContent, inConsCell.tail)
# unsafe_store!(firstPtr, inNewContent)
end

""" O(1). A destructive operation changing the rest part of a cons-cell """
#= NOTE: Make sure you do NOT create cycles as infinite lists are not handled well in the compiler. =#
function listSetRest(inConsCell::List{A}, inNewRest::List{A}) where {A} #= A non-empty list =#
@error "Not listSetRest defined in the runtime"
function listSetRest(inConsCell::Cons{A}, inNewRest::Cons{A}) where {A} #= A non-empty list =#
newTailPtr::Ptr{Cons{A}} = unsafe_getListAsPtr(inNewRest)
inConsCellTailPtr::Ptr{Cons{A}} = unsafe_getListTailAsPtr(inConsCell)
inConsCellTailPtr2::Ptr{Cons{A}} = unsafe_getListAsPtr(inConsCell)
GC.@preserve(unsafe_store!(inConsCellTailPtr, unsafe_load(newTailPtr)))
return inConsCell
end

"""
We create one cons cell when the tail we are setting is a nil...
"""
function listSetRest(inConsCell::Cons{A}, inNewRest::Nil) where {A} #= A non-empty list =#
local lstPtr::Ptr{Cons{A}} = unsafe_getListAsPtr(inConsCell)
local val = inConsCell.head
GC.@preserve unsafe_store!(lstPtr, Cons{A}(inConsCell.head, inNewRest))
return inConsCell
end


""" O(n) """
function listArrayLiteral(lst::List{A})::Array{A} where {A}
local arr::Array{A} = listArray(lst)
arr
end

@exportAll()
"""
```
listGetFirstAsPtr(lst::Cons{T})::Ptr{T}
```
Dangerous function.
Gets the first element of the list as a pointer of type T.
Unless it is nil then we get a NULL pointer
"""
function unsafe_getListHeadAsPtr(lst::Cons{T}) where{T}
convert(Ptr{T}, unsafe_pointer_from_objref(lst.head))
end

"""
``` listGetFirstAsPtr(nil)::Ptr{Nothing}```
Returns a null pointer
"""
function unsafe_getListHeadAsPtr(lst::Nil)
unsafe_pointer_from_objref(nil)
end

"""
Fetches the pointer to the tail of the list
```
unsafe_listGetTailAsPtr{lst::List{T}}::Ptr{Cons{T}}
```
"""
function unsafe_getListTailAsPtr(lst::List{T}) where {T}
if lst.tail === nil
return unsafe_pointer_from_objref(nil)
else
convert(Ptr{Cons{T}}, unsafe_pointer_from_objref(lst.tail))
end
end

"""
Unsafley get a pointer to a list.
"""
function unsafe_getListAsPtr(lst::List{T}) where {T}
if lst === nil
ptrToNil::Ptr{Nil{Any}} = unsafe_pointer_from_objref(nil)
return ptrToNil
else
convert(Ptr{Cons{T}}, unsafe_pointer_from_objref(lst))
end
end




"""
Unsafe function to get pointers from immutable struct.
Use with !care!
"""
function unsafe_pointer_from_objref(@nospecialize(x))
ccall(:jl_value_ptr, Ptr{Cvoid}, (Any,), x)
end


ExportAll.@exportAll()

end #=End dangerous =#
4 changes: 2 additions & 2 deletions src/matchcontinue.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
See the License for the specific language governing permissions and
limitations under the License.
The code is based on https://github.com/RelationalAI-oss/Rematch.jl with
changes to allow keyword argument matching on structs along with
The code is originally based on https://github.com/RelationalAI-oss/Rematch.jl with
changes to allow keyword argument matching on structs along with
matching on the immutable list construct accompanying MetaModelica + some other improvements and bug fixes.
It also provides @matchcontinue macro (try the next case when any exception is thrown).
"""
Expand Down
60 changes: 43 additions & 17 deletions src/metaRuntime.jl
Original file line number Diff line number Diff line change
Expand Up @@ -369,15 +369,17 @@ end
Example: stringDelimitList({\"x\",\"y\",\"z\"}, \", \") => \"x, y, z\"
"""
function stringDelimitList(strs::List{String}, delimiter::String)::String
local str::String = ""
for n in strs
if isempty(str)
str = n
buffer = IOBuffer()
for (i,n) in enumerate(strs)
if i == 1
print(buffer, n)
else
str = str + delimiter + n
print(buffer, delimiter)
print(buffer, n)
#str = str + delimiter + n
end
end
str
return String(take!(buffer))#str
end

function stringDelimitList(strs::List, delimiter::String)::String
Expand Down Expand Up @@ -516,7 +518,7 @@ function arrayCreate(size::ModelicaInteger, initialValue::A)::Array{A} where {A}
end

""" O(N) """
function arrayList(arr::Array{T})::List{T} where {T}
function arrayList(arr::Array{T}) where {T}
local lst::List{T} = nil
for i = length(arr):-1:1
lst = Cons{T}(arr[i], lst)
Expand All @@ -525,19 +527,43 @@ function arrayList(arr::Array{T})::List{T} where {T}
end

""" O(n) """
function listArray(lst::Cons{T})::Array{T} where {T}
local arr::Vector{T} = T[]
for i in lst
push!(arr, i)
function listArray(lst::Cons{T}) where {T}
local N = length(lst)
local arr::Vector{T} = Vector{T}(undef, N)
i = 1
while lst !== nil
arr[i] = lst.head
i += 1
lst = lst.tail
end
arr
return arr
end

""" O(1) """
function listArray(lst::Nil)
[]
end

"""
O(n)
Same as listArray but with a dummy argument to specify the type.
"""
function listArray(lst::Cons{T}, ty) where {T}
local arr = Vector{ty}(undef, length(lst))
for i in lst
arr[i]
end
return arr
end

"""
Same as listArray but with a dummy argument to specify the type.
"""
function listArray(lst::Nil, ty)
ty[]
end

""" O(1) """
function arrayUpdate(arr::Array{A}, index::ModelicaInteger,
newValue::B)::Array{A} where {A,B}
Expand All @@ -556,9 +582,8 @@ end
Note that this operation is *not* destructive, i.e. a new array is created. """
function arrayAppend(arr1::Array{A}, arr2::Array{A})::Array{A} where {A}
local arr::Array{A}

#= Defined in the runtime =#
arr
@error "Defined in the runtime"
fail()
end

""" Returns the string representation of any value.
Expand Down Expand Up @@ -603,7 +628,7 @@ end
This is a global mutable value and should be used sparingly.
You are recommended not to use "missing" the runtime system treats this values as uninitialized and fail getGlobalRoot later on.
"""
global globalRoots = Array{Any,1}(missing, 1024)
const global globalRoots::Vector{Any} = Vector{Any}(missing, 1024)

function setGlobalRoot(index::ModelicaInteger, value::T) where {T}
if index > 1023 || index < 0
Expand Down Expand Up @@ -733,7 +758,8 @@ function referenceDebugString(functionSymbol::A)::String where {A}
name
end

""" TODO: I am far from sure that this will fly.. in Julia. The code generated from the transpiler is correct however"""
""" TODO: I am far from sure that this will fly.. in Julia.
The code generated from the transpiler is correct however"""
function isPresent(ident::T)::Bool where {T}
local b::Bool
b = true
Expand Down
32 changes: 24 additions & 8 deletions src/union.jl
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,23 @@ end

function replaceLineNum(a::Any, lines::LineNumberNode) end

function makeUniontypes(name, records, lineNode::LineNumberNode)
function makeUniontypes(name, records, lineNode::LineNumberNode; mutable = false)
recordsArray1 = Array.(records)
recordsArray2 = recordsArray1[1]
constructedRecords = []
for r in recordsArray2
for r in recordsArray2
structName = r[1]
recordNode = quote
struct $(structName) <: $name
$(r[2])
recordNode = if ! mutable
quote
struct $(structName) <: $name
$(r[2])
end
end
else
quote
mutable struct $(structName) <: $name
$(r[2])
end
end
end
replaceLineNum(recordNode, isa(r[3], Nothing) ? lineNode : r[3])
Expand All @@ -99,13 +107,21 @@ function makeUniontypes(name, records, lineNode::LineNumberNode)
return res
end

#= Creates a uniontype consisting of 0...N records =#
""" Creates a uniontype consisting of 0...N records """
macro Uniontype(name, records...)
recordCollection = [makeRecord(r) for r in records]
esc(makeUniontypes(name, recordCollection, __source__))
end

#= Creates a record belonging to a Uniontype =#
"""
Creates a mutable uniontype constisting of 0...N records
"""
macro Mutable_Uniontype(name, records...)
recordCollection = [makeRecord(r) for r in records]
esc(makeUniontypes(name, recordCollection, __source__; mutable = true))
end

""" Creates a record belonging to a Uniontype """
macro Record(name, fields...)
makeTuple(name, fields)
end
Expand All @@ -117,6 +133,6 @@ macro UniontypeDecl(uDecl)
end)
end

export @Uniontype, @Record, @UniontypeDecl
export @Uniontype, @Record, @UniontypeDecl, @Mutable_Uniontype

end
26 changes: 18 additions & 8 deletions src/utilityMacros.jl
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
import Setfield
import FastClosures
"""
Helper function for the assignmacro, see @assign
We have one case where we assign a immutable structure to an immutable structure or something to a primitive variable.
If it is not a primitive we assign to a subcomponent of that structure. We then clone the structure with that particular field changed.
"""
function assignFunc(expr)
res = if @capture(expr, lhs_._ = rhs_)
if !isprimitivetype(typeof(lhs))
Setfield.setmacro(identity, expr, overwrite=true)
res =
if @capture(expr, lhs_._ = rhs_)
if !isprimitivetype(typeof(lhs))
Setfield.setmacro(identity, expr, overwrite=true)
else
quote
$(esc(expr))
end
end
else
quote
$(esc(expr))
end
end
else
quote
$(esc(expr))
end
end
return res
end

Expand All @@ -33,3 +35,11 @@ E.g.:
macro assign(expr)
assignFunc(expr)
end

"""
Wraps the @closure macro of FastClosures.
See the FastClosure package for more information.
"""
macro closure(expr)
esc(FastClosures.wrap_closure(__module__, expr))
end

0 comments on commit 19f7c8a

Please sign in to comment.