Opened 9 years ago
Closed 8 years ago
#3867 closed enhancement (fixed)
Add alternative to array<T> for mutable variables
Reported by: | Martin Sjölund | Owned by: | Martin Sjölund |
---|---|---|---|
Priority: | high | Milestone: | 1.12.0 |
Component: | MetaModelica | Version: | |
Keywords: | Cc: | Adrian Pop, Peter Fritzson, Per Östlund |
Description
Currently, a fair deal of code in OMC uses a pattern using array<T>
with arrays of size 1 in order to make data types mutable. This leads to using arrayGet(something, 1)
in many places.
It would be nice if we could simply declare variables mutable<T>
, which would either be translated to arrays of size 1 in the run-time system, or to an immediate pointer (set lowest 2 bits to 1 or something in the header; actual pointer is ptr xor 3), or it is a special type (array1 or mutable). These options would allow to assign a mutable<T>
to some field in a structure that has a mutable<T>
(sharing the same variable). It could also be possible that mutable<T>
was not possible to share (0 additional memory allocations). Or a mixture with pointer<T>
and mutable<T>
...
Note that these language features would perhaps not be nice and declarative, but we already have array<T>
and it is used. This would just make code that uses this feature more maintainable.
Change History (5)
comment:1 by , 8 years ago
comment:2 by , 8 years ago
One question is also if we should implement it simply as external "C" and not let the compiler know or care about this datatype (similar to implementing SOME/NONE as a uniontype with type variables except here it would be an opaque uniontype I suppose).
comment:3 by , 8 years ago
Thinking about how to tag things in the run-time, I suppose just treat it similar to SOME(x)
, using the tag+mutable data (size: 2 pointers) in order to not truncate Integer further and make the run-time simple for this. This would make it the same size as an array of size 1 and we could even re-use the same types for this, but if we create just these 3 functions to access mutable data, we don't do bounds checking.
comment:4 by , 8 years ago
If we wanted something less built into MetaModelica, we could use a size of 3 pointers:
uniontype Reference<T> record REF T data; end REF; function create input T data; output Reference<T> ref; algorithm ref := Reference.REF(data); end create; function dereference input Reference<T> ref; output T data; algorithm data := ref.data; end dereference; function update input Reference<T> ref; input T data; external "C"; // Or add something to MetaModelicaBuiltin.mo to force setting the data... Or store it as a cons-cell. end update; end Reference;
I think this one pretty much just works as it is. (Although doing ref.data := newData;
would perhaps unexpectedly create a new reference and not update the old one)
comment:5 by , 8 years ago
Milestone: | Future → 1.12.0 |
---|---|
Resolution: | → fixed |
Status: | new → closed |
Summary: | Investigate alternative to array<T> → Add alternative to array<T> for mutable variables |
Type: | defect → enhancement |
Fixed in PR1636. There are now two new types implemented as opaque uniontypes. The type system is the normal one, but the uniontype contains no records. Instead, external functions create either a tuple of size 1 or a SOME(x)
object (boxes with ctor=0 or ctor=1). The types are Mutable<T>
(only mutable) and Pointer<T>
(also includes immutable references, which cannot be updated; the update function fails if trying to update an immutable reference). Pointer<T>
can be used to create immutable package constants (as used for example in NFFunction). Neither version can be used to create mutable package constants.
Note: listArray({1,2,3})
can today be used in package constants (but does not create a literal; a new object is created at each access). It should have simply been forbidden and not work (it is listed as impure), but bugs made it work...
Some starts on the syntax for this:
sort!
and simply allows you to change values... It does not have pass-by reference or pointers as far as I can tell (basically what we have now with the XXXDangerous functions)This is something like what I wanted to do. It basically just has 3 operators:
And would work something like this:
We could of course have a more OCaml-like syntax if we wanted: