-
Notifications
You must be signed in to change notification settings - Fork 5
/
dangerous.jl
191 lines (163 loc) · 5.32 KB
/
dangerous.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
#=
The MetaModelica.Dangerous module.
Most things here are stubs
=#
module Dangerous
import ExportAll
using ..MetaModelica
""" O(1) """
function arrayGetNoBoundsChecking(arr::Vector{A}, index::ModelicaInteger) where {A}
@inbounds arr[index]
end
""" O(1) """
function arrayUpdateNoBoundsChecking(arr::Vector{A},
index::ModelicaInteger,
newValue::A) where {A}
local newArray = arr
@inbounds newArray[index] = newValue
return newArray
end
""" Creates a new array where the elements are *not* initialized!. Any attempt to
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.
"""
function arrayCreateNoInit(size::ModelicaInteger, dummy::A)::Array{A} where {A}
local arr::Array{A} = fill(dummy, size)
arr
end
""" O(1) """
function stringGetNoBoundsChecking(str::String, index::ModelicaInteger)
local ch::ModelicaInteger
ch = @inbounds str[index]
end
""" Not possible unless we write a C list impl for Julia """
function listReverseInPlace(inList::List{T})::List{T} where {T}
MetaModelica.listReverse(inList)
end
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::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
function listReverseInPlace(inList::List{T}) where {T}
MetaModelica.listReverse(inList)
end
""" O(1). A destructive operation changing the \"first\" part of a cons-cell. """
function listSetFirst(inConsCell::Cons{A}, inNewContent::A) where {A} #= A non-empty list =#
@assign inConsCell.head = inNewConent
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::Cons{T}, inNewRest::List{T}) where {T} #= A non-empty list =#
@assign inConsCell.tail = inNewRest
end
""" O(n) """
function listArrayLiteral(lst::List{A})::Array{A} where {A}
local arr::Array{A} = listArray(lst)
arr
end
"""
```
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 =#