The Artima Developer Community
Sponsored Link

Weblogs Forum
Types on the Stack

11 replies on 1 page. Most recent reply: Aug 22, 2006 12:40 AM by Jules Jacobs

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 11 replies on 1 page
Christopher Diggins

Posts: 1215
Nickname: cdiggins
Registered: Feb, 2004

Types on the Stack (View in Weblogs)
Posted: Aug 16, 2006 9:19 PM
Reply to this message Reply
Summary
I am playing with the idea of allowing types to pushed onto the stack in the Cat language. Here are my ruminations on the subject
Advertisement
I want to place types on the stack in Cat.

I want this for two reasons:

  1. It simplifies the language syntax
  2. I want to be able to have dynamic type expressions and dynamic type assignments
I am not being entirely glib in providing the first answer. It is hard to justify complex syntax, just to separate the compile-time expressions and run-time expressions.

There are not many languages where types are first class values, and I want to be very careful about making this decision. I don't want to have to reimplement the compiler for the umpteenth time.

There is potential overhead in making types first-class citizens of the language, however during static analysis most of the type expressions have the potential of being evaluated away.

I am still unsure though ... am I buying something of value, or just getting into a world of hurt and pain?


Cleo Saulnier

Posts: 77
Nickname: vorlath
Registered: Dec, 2005

Re: Types on the Stack Posted: Aug 17, 2006 11:51 AM
Reply to this message Reply
Hope you don't mind my commenting. My statements usually diverge considerably from the accepted consensus. I want to post because I've actually dealt with something similar.

I'm not sure about how Cat works exactly, so I'll just mention what I've learned in my own development environment about putting types directly in the language. First, your "types" now become values as you've said. So you now need types for your types. The only way I've seen this done is to have primitive types that do not have any sub-attributes. For example, you cannot get its size or anything like that, only its value. The attributes must be assumed. Now, you can get these attributes with built-in functions, mind you. Instead of primitive types being used for ints and floats and things like that, they are now used for defining types. These types in turn define your actual values. But now this creates two separate environments for getting attributes. 1. Members for classes (or other groupings). 2. And built-in functions for primitive types (that in turn define types).

The reason for no attributes is to break the recursion. If you'll note, the recursion is broken in all language (I think). For example, You can't do int.size in C++. You use a built-in function sizeof(). You must now move this system from values over to first "class" types.

Now you must ask yourself why you need runtime types in your language. I use them so that the objects are fully independent and can be sent over the wire. I can also create new values based on other values since these values also contain their types (which is necessary for value creation). However, like I said before, you need a low level implementation of your primitive types for this exchange to take place. This low level stuff cannot be in the language proper, otherwise you get into the recursive definition again. That's where static type languages like C++ and languages that have runtime types values differ. In C++, since RTTI can only be queried (usually by comparing it to existing types), you must manually create any structure or packet information for exchanging this type information (if the software wants to deal with types). The software itself is in control. But if you put types directly in the language, then the language itself must be in control of its definition.

In other words, while it is easy to specify that an int is 32 bit, how do you specify what a type looks like? How is 'int' stored? How is 'bool' stored? These are just a set. You will need to specify how this set is stored if you want manual manipulation of it. You also need a way to create new types. I don't know if you allow subclassing or any of that, but functionality that used to be in the compiler must now be available at runtime. You must ship a good part of the compiler with the software itself unless your language is an interpreter (in that case, it would be available anyhow). The most critical functionality is being able to put other types together to form a new compound type and then create instances of this new type. In my environment, I can create new primitive types as well, but that's way more complicated than anything I could describe in one message. I also see code as an extension of a type (as it defines what [can] happens to the value). So I can also create new code. But this too is another topic.

BTW, I'm guessing you'll soon be looking at grouping types together and how to represent them and how this differs (or is similar) from regular primitive types when it comes to breaking the recursion. Without first "class" types, you can implement groupings any which way you want. Now you must expose this. Remember that groupings have properties. As such, you're going to have to find an alternative in order to break the recursion (perhaps with a built-in function). Your biggest challenge is resolving the dichotomy of types and values.

You're in for a ride. It can be fun, but can be damaging to your sanity. BTW, I've said it before that all of computing community, including yourself, are all going toward the same destination. However, whenever anyone gets close to the goal, they steer clear. Good luck!

Also note that this is stuff I learned on my own. Much of this may already be solved, but since you're posting here, I'm guessing you haven't found any concrete solution, so I thought my comments may be of some value.

Max Lybbert

Posts: 314
Nickname: mlybbert
Registered: Apr, 2005

Types as first class values Posted: Aug 17, 2006 1:18 PM
Reply to this message Reply
I know the common way to handle that is to store the type information inside the object. You can either make that read-only information for static typing, or read-write for dynamic typing. This gives the benefit that types never get separated from objects.

However, I can imagine a command "change all of these objects to type X" (or maybe, "change the inheritance tree for all of these objects to include type X") and to do that you would either need an empty object of type X or a type as a first class citizen.

Jules Jacobs

Posts: 119
Nickname: jules2
Registered: Mar, 2006

Re: Types on the Stack Posted: Aug 18, 2006 2:30 AM
Reply to this message Reply
You could make typeof 4 => int, typeof "foo" => string, typeof int => type, typeof type => type. There is really no problem. In Ruby, for example, the class of 4 is Integer, and the class of Integer is Class. The class of Class is Class.

Cleo Saulnier

Posts: 77
Nickname: vorlath
Registered: Dec, 2005

Re: Types on the Stack Posted: Aug 19, 2006 12:27 PM
Reply to this message Reply
> You could make typeof 4 => int, typeof "foo" => string,
> typeof int => type, typeof type => type. There is really
> no problem. In Ruby, for example, the class of 4 is
> Integer, and the class of Integer is Class. The class of
> Class is Class.

Type of Class is Class. That's self-referential. That's what I was talking about. You're going to have to pick what your primitive type is to break the recursion. In this case, it's "Class".


You're going to have to decide if you want Class to be treated as a regular type or if it is a super type.
i.e. where Class is to Integer what Integer is to 5. This would mean that taking the class of Class would make no sense though as there's no higher type. Self referetial is ok, but you have to make sure that Class is not a type, but a super type. It all depends on what Christopher wants to do and how he wants to separate levels of types.

I just want to point out that in my system, I can build more primitive types from my "super type". In the above system, you can't do that. If you're ok with that, then yeah, it should be simple enough, except maybe for implementing type creation and manipulation and then knowing how to apply operators on those types and how to call methods that weren't available before.

I guess if you can see how to implement something like this, you're all set to go. This is like C++ though. This version uses compound containter types. A Class can contain a value of Integer. But since Integers can contain values, you can use two levels of inderection to obtain the value from a Class.

void func()
{
Class t = Float;
t = inc5(t,100);
print(t); // Prints Class
print([t]); // Prints Float
print([[t]]); // Prints 105.0
}

Class inc5(Class mytype, Integer inc)
{
Class var = mytype;
[var] = (mytype)5; // Using brackets like in asm for contents.
[var] += (mytype)inc;
print var; // Prints Float;
print [var]; // Prints 105.0
print typeof(var); // Prints Class
print typeof([var]); // Prints Float
print typeof(typeof(var)); // What is the class of Class???
return var;
}


typeof is overloaded here as it operates on values as well as types. You'll have to decide what the type of a Class is as well.

OR if you don't want types and values to share the same object...

void func()
{
Class t = Float;
t t1 = inc5(t,100);
print(t); // Prints Float
print(t1); // Prints 105.0
}

mytype inc5(Class mytype, Integer inc)
{
mytype var = (mytype)5;
var += (mytype)inc;
print var; // Prints 105.0;
print typeof(var); // Prints Float
print typeof(typeof(var)); // Prints Class
print typeof(typeof(typeof(var))); // What is the class of Class???
return var;
}

This has its own set of problem although much cleaner. How do you specify the return type of inc5 from the class of a parameter? If you can't change the return type, you're limiting what you can do with types. And I have no clue how you would do that.

Good luck!

Cleo Saulnier

Posts: 77
Nickname: vorlath
Registered: Dec, 2005

Re: Types on the Stack Posted: Aug 19, 2006 12:35 PM
Reply to this message Reply
Correction: The first func() should read

void func()
{
Class t = Float;
t = inc5(t,100);
print(typeof(t)); Prints Class
print(t); // Prints Float
print([t]); // Prints 105.0
}

Jules Jacobs

Posts: 119
Nickname: jules2
Registered: Mar, 2006

Re: Types on the Stack Posted: Aug 20, 2006 4:26 AM
Reply to this message Reply
The Class of Class is Class. It's self-referential. All values contain two things: (1) a pointer to it's type (2) the data of the value.

A Class doesn't contain Integer and Integer doesn't contain 5, it's the other way around:

The type field of 5 is a pointer to Integer.
Integer's type field is a pointer to Class.
Class's type field is a pointer to Class.

So:

5.class => Integer
5.class.class => Class
5.class.class.class...class => Class

something.class is the same as typeof(something)

Class doesn't have to be a super type, there is no difference between types, values and super-types.

Cleo Saulnier

Posts: 77
Nickname: vorlath
Registered: Dec, 2005

Re: Types on the Stack Posted: Aug 21, 2006 1:01 PM
Reply to this message Reply
The only problem with that system is that it can't work with multiple members.

Cleo Saulnier

Posts: 77
Nickname: vorlath
Registered: Dec, 2005

Re: Types on the Stack Posted: Aug 21, 2006 1:27 PM
Reply to this message Reply
Maybe I should clarify. When you have a type, a useful property is reflection. If you don't want that and just want a tag, that's fine, but we already have RTTI systems and this problem has already been solved. But it's pretty useless if say, you grab the type of a compound class, but its type has no such information from which to build the new instance.

That's why Class of Integer is a Class is pretty useless. What are you going to do with a Class type? You can't recreate the Integer type. This is also why I said you have to figure out how to break the recursion.

I think it's pointless to discuss implementations without really knowing what C.D. wants to do. What is the purpose behind this? List the advantages and disadvantages. What functionality do you want this to provide?

Jules Jacobs

Posts: 119
Nickname: jules2
Registered: Mar, 2006

Re: Types on the Stack Posted: Aug 21, 2006 1:51 PM
Reply to this message Reply
You can create a new Integer:

Integer = (the representation you want) Class set-type

The purpose is that this is cool ;-).

Christopher Diggins

Posts: 1215
Nickname: cdiggins
Registered: Feb, 2004

Re: Types on the Stack Posted: Aug 21, 2006 10:25 PM
Reply to this message Reply
> I think it's pointless to discuss implementations without
> really knowing what C.D. wants to do. What is the purpose
> behind this? List the advantages and disadvantages. What
> functionality do you want this to provide?

What I am looking to do is extend the type system so that types can potentially have characteristics which can not be determined until runtime.

Imagine for instance a type which was locale dependant, based on where the software was being run. Or another type, which depended on the size of the word on the target architecture.

Jules Jacobs

Posts: 119
Nickname: jules2
Registered: Mar, 2006

Re: Types on the Stack Posted: Aug 22, 2006 12:40 AM
Reply to this message Reply
Tag every value (at runtime) with a type? If you can write types to values and read them there should be no problem.

def foo = the-value-wichs-type-depends-on-the-locale [locale 'us' ==] [USType set-type] [OtherType set-type] if

Flat View: This topic has 11 replies on 1 page
Topic: Types on the Stack Previous Topic   Next Topic Topic: Cameron Purdy on Dealing with Failure

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use