Type cannot hold a variable of its own Type - AppGameKit/BASIC - basic

Background: Im attempting to create an XML parser for AppGameKit using tier 1 (the engines own version of BASIC).
The problem: The tier 1 language has "Types" (similar to C structs), they contain no functions and cannot hold a variable of the same "Type"
Example
TYPE XMLNode
name as String
value as String
children as XMLNode[]
parent as XMLNode
attributes as String[]
ENDTYPE
Is not valid because XMLNode cannot have a variable of type XMLNode.
Question:
Is there a known way around a language that is structured/limited like this that would allow the same result?

Related

How to use EncodedObjectAsID?

I'm trying to understand get_instance_id()
and I came across this line in the documentation:
This ID can be saved in EncodedObjectAsID, and can be used to retrieve
the object instance with #GDScript.instance_from_id.
I can't seem to understand what this statement means exaclty and how to use EncodedObjectAsID, could someone please provide a working example?
The EncodedObjectAsID follows a pattern called Boxing. Boxing is where you put a primitive value, like an int, into an object. This boxed primitive can now be used in an object oriented way. For example, you can pass the boxed int to a function that only takes objects (i.e. it applies Polymorphism):
func only_takes_object(obj: Object)
only_takes_object(123) # Error
var box = EncodedObjectAsID.new()
box.object_id = 123
only_takes_object(box) # Valid
This is how parts of the editor use the EncodedObjectAsId object.
In marshalls.cpp we can see that an encoded Object may be an integer ID or the whole object. When it is flagged as only an integer ID a EncodedObjectAsID object is created. This object is then converted to a Variant.
When adding a stack variable in editor_debugger_inspector.cpp a variant with a type of object is assumed to be and converted to an EncodedObjectAsID to fetch the referenced object's id.
Here's two more links that follow a similar pattern:
array_property_edit.cpp
scene_debugger.cpp
Note that Variant can be implicitly converted to an Object and Object::cast_to() only takes Objects.
This ID can be saved in EncodedObjectAsID, and can be used to retrieve the object instance with #GDScript.instance_from_id.
This sentence should be split into two independent clauses. It should read as
"The instance ID can be saved in an EncodedObjectAsID."
"The instance ID can be used to retrieve the object instance with #GDScript.instance_from_id()."
Note: You should not store an object's id in storage memory. There is no guarantee that an object's id will remain the same after restart.

In Groovy, casting between collection implementations copies source instead

The following code
void testReference() {
List<String> source = new ArrayList<>()
source.add("element")
List reference = (ArrayList)source // all ok, creates reference as types match
assertSame(source,reference)
List copyNotReference = (LinkedList)source // should fail on GroovyCastException, creates copy instead
assertNotSame(source,copyNotReference) // this works, copy is a different object
copyNotReference.add("second element")
println source
println copyNotReference
}
only works in Groovy. In Java it fails on attempt to cast ArrayList to LinkedList.
In Groovy it creates a LinkedList instance, calling constructor
public LinkedList(Collection<? extends E> c)
and copying source data to the new instance.
The test outputs
[element]
[element, second element]
That behaviour only occurs when casting types that are subtypes of collections.
Question
What Groovy mechanism is responsible for this unexpected behaviour?
Groovy allows coercion of objects via casting them (asType). This is implemented for collections.
See the source
Converts the given collection to another type. A default concrete
type is used for List, Set, or SortedSet. If the given type has
a constructor taking a collection, that is used. Otherwise, the
call is deferred to {#link #asType(Object,Class)}. If this
collection is already of the given type, the same instance is
returned.

Casting to types that are know only at Runtime by their string names. C#

I've got a problem here. (C#)
There's a collection in another assembly (I cannot change it) that takes a string as parameter and returns an object.
Like:
object Value = ThatCollection.GetValue("ParameterName");
The problem is, for each parameter string, it returns a DIFFERENT type as object.
What I want is to cast those objects to their respective types, knowing the types only at runtime by their string names.
I need to do some operations with those returned values.
And for that I need to cast them properly in order to access their members and so.
Limitations:
I cannot use "dynamic" since my code needs to be done in an older framework: 3.5 (because of interop issues).
I need to do operations with MANY returned values of different types (no common interfaces nor base classes, except "object", of course)
All I have is a table (containing string values) correlating the parameter names with their returned types.
Yes, I could transform that table into a biiig "switch" statement, not very nice, don't want that.
Any hints??
You want to look into reflection, something like the following should work to cast an object to type T. Set up a simple cast method:
public static T CastToType<T>(object o)
{
return (T)o;
}
Invoke this using reflection:
Type t = Type.GetType(stringName)
MethodInfo castTypeMethod = this.GetType().GetMethod("CastToType").MakeGenericMethod(t);
object castedObject = castTypeMethod .Invoke(null, new object[] { obj });

convert string data into Type for List<>

I'd like to take a string and create a typed List based on the
"Type" documented in the string. For example, suppose str is "System.string". I'd
like the method to create a List for me. Of course, the string could contain text
that "references" any object in the assembly. I've unsuccessfully tried the following:
Type classType = Type.GetType(str);
List<classType> wgList = new List<classType>();
I get a message stating that "classType is a field but is used like a type"..
How do I fix this up to get what I need ?
The following code provided a nice solution:
Type ty = Type.GetType(ItemType);
wgList = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(ty));
You can not do that or i don't understand what is your purpose?
Use List< object > instead.
You may use Extension method is Cast< T>() in System.Linq namespace to convert your List< object > to List< T >.
List<Entry> entries = wgList.Cast<Entry>().ToList()

Groovy type conversion

In Groovy you can do surprising type conversions using either the as operator or the asType method. Examples include
Short s = new Integer(6) as Short
List collection = new HashSet().asType(List)
I'm surprised that I can convert from an Integer to a Short and from a Set to a List, because there is no "is a" relationship between these types, although they do share a common ancestor.
For example, the following code is equivalent to the Integer/Short example in terms of the
relationship between the types involved in the conversion
class Parent {}
class Child1 extends Parent {}
class Child2 extends Parent {}
def c = new Child1() as Child2
But of course this example fails. What exactly are the type conversion rules behind the as operator and the asType method?
I believe the default asType behaviour can be found in: org.codehaus.groovy.runtime.DefaultGroovyMethods.java
org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.java.
Starting from DefaultGroovyMethods it is quite easy to follow the behavior of asType for a specific object type and requested type combination.
According to what Ruben has already pointed out the end result of:
Set collection = new HashSet().asType(List)
is
Set collection = new ArrayList( new HashSet() )
The asType method recognizes you are wanting a List and being the fact HashSet is a Collection, it just uses ArrayList's constructor which takes a Collection.
As for the numbers one, it converts the Integer into a Number, then calls the shortValue method.
I didn't realize there was so much logic in converting references/values like this, my sincere gratitude to Ruben for pointing out the source, I'll be making quite a few blog posts over this topic.

Resources