FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

MiniD 2...
Goto page 1, 2  Next
 
Post new topic   Reply to topic     Forum Index -> MiniD
View previous topic :: View next topic  
Author Message
JarrettBillingsley



Joined: 20 Jun 2006
Posts: 457
Location: Pennsylvania!

PostPosted: Thu Dec 06, 2007 11:53 pm    Post subject: MiniD 2... Reply with quote

MD2, MD2.... it's coming, it's coming, it's coming.

(cookie to anyone who catches that reference)

MiniD 2 is coming. Relatively soon, I guess. It's been accumulating features over the past few months and here's a rundown of some features that are already implemented:

Code:
// Optional semicolons
module test

writefln("o hai!")
writeln()

// Ability to get the number of varargs (#vararg), index varargs (x = vararg[i];
// vararg[i] = x;), and slice varargs (vararg[1 ..]) without having to create arrays.

function vargs(vararg)
{
   writefln("vargs got {} varargs.", #vararg)
   
   for(i: 0 .. #vararg)
   {
      writefln("\targ {}: {}", i, vararg[i])
      vararg[i] = toString(vararg[i])
   }
   
   if(#vararg > 0)
      writefln("\tOMG: ", vararg[1 ..]);
}

vargs()
vargs(1, 2, 3)

writeln()

// Ability to use the length operator on the left-hand side of an assignment, and an
// opLengthAssign metamethod to go along with it.

local a = [1, 2, 3]
#a = 2
writefln(a)

writeln()

// Separation of indexing (a["x"]) and field access (a.x) into two separate operations
// for speed and more granularity when writing metamethods. Field access uses the opField
// and opFieldAssign metamethods instead of opIndex and opIndexAssign. For tables, there
// is only indexing, and field access uses opIndex and opIndexAssign.

// The ability to intercept method calls using something like "opMethod", to allow for
// things like mock objects and RPC to be implemented easily.

// To go with those, new syntax for accessing fields and methods with dynamically-
// generated names: a.(someExpression) and a.(someExpression)(params).

class C
{
   function opField(name)
   {
      writefln("getting field '{}'", name)
      return 0
   }

   function opFieldAssign(name, value)
   {
      writefln("setting field '{}' to {}", name, value)
   }
   
   function opMethod(name, vararg)
   {
      writefln("calling method '{}'", name)
      
      for(i: 0 .. #vararg)
         writefln("\targ {}: {}", i, vararg[i])
   }
}

local c = C()
c.x = 5
writefln(c.x)
c.foo(1, 2, 3)

writefln(c.("x"))
c.("foo")("hi!")

writeln()

// Attribute tables -- attach an arbitrary table to classes, functions and namespaces
// for things like documentation, extra reflection info, etc.

</
   doc = "This is a stupid class.",
   hasFoo = true,
   hasBar = false
/>
class Foo
{
   mX
   mY

   this(x, y)
   {
      mX = x
      mY = y
   }

   function foo() {}
}

foreach(k, v; attributesOf(Foo))
   writefln("{}: {}", k, v)


The output:

Code:
o hai!

vargs got 0 varargs.
vargs got 3 varargs.
        arg 0: 1
        arg 1: 2
        arg 2: 3
        OMG: 23

[1, 2]

setting field 'x' to 5
getting field 'x'
0
calling method 'foo'
        arg 0: 1
        arg 1: 2
        arg 2: 3
getting field 'x'
0
calling method 'foo'
        arg 0: hi!

hasFoo: true
doc: This is a stupid class.
hasBar: false


So yeah. There are some more potential features listed on the Language Introduction wiki page, don't know how many of those will/won't be implemented, or if there will be any other features. There'll also probably be some new goodies in the stdlib, which will most likely be backported to MD1 for good measure.

So, that's that. If you have any more ideas, even if they're for the native API, please feel free to voice them Smile


Last edited by JarrettBillingsley on Sat Oct 04, 2008 3:26 pm; edited 1 time in total
Back to top
View user's profile Send private message
Ligustah



Joined: 21 Oct 2007
Posts: 45
Location: Berlin, Germany

PostPosted: Fri Dec 07, 2007 6:41 pm    Post subject: Reply with quote

Wooo! Cool!
Great work, especially the attribute tables seem to be very useful to me, though i think they should be attachable to fields, too, which would be nice for documentation. Moreover i love the optional semicolons (and commas ?). They make tables look much nicer, just like in Lua.
Nice!!

Mfg Ligustah
Back to top
View user's profile Send private message
doob



Joined: 06 Jan 2007
Posts: 367

PostPosted: Sat Dec 08, 2007 12:22 pm    Post subject: Reply with quote

Very nice, I like the optional semicolon. I have a couple of other ideas, some taken from Ruby.

Drop the need for a local keyword, it should be local as default and it would be nice to not have to type anything before a variable name when you declare it (ruby).

Why only one constructor?

Open classes like in ruby. Meaning, you can always open an already existing class and add more things to it.

Properties (if not already exists). Introduce two new keywords "get" and "set". Then if you add them in front of a method it would become a property. Example:
Code:

class A
{
    private length_ = 0

    // Property, write
    public function set length (value)
    {
        return length_ = value
    }

    // Property, read
    public function get length
    {
        return length_
    }
}

class B
{
    // Property shortcut (ruby like), read and write, same as in class A, public is here applied to the functions, the variable will be private
    public get set length = 0
}

class C
{
    // Property shortcut, read and write, the functions will be private and also the variables
    private get set
    {
        length = 0
        size = 0
    }

    // Property shortcut, read only
    get:
        height = 0
        width = 0
}


Or you could to the D way, or both
Is there any protection(public, private) for classes by the way?

Always return the last thing in a function so you don't have to type "return" (ruby)

Drop need for braces in functions only containing one row, like if and for statements

Quote:
Code:
for(i: 0 .. #vararg)
   {
      writefln("\targ {}: {}", i, vararg[i])
      vararg[i] = toString(vararg[i])
   } 


Doesn't it seem more logical to have a semicolon in the above for statement than a colon?

Maybe drop the need for parentheses in function calls, when you create a new class instance etc.(ruby)

That is what I could think of for now. I haven't used minid that much but I will when I get more time.
Back to top
View user's profile Send private message
JarrettBillingsley



Joined: 20 Jun 2006
Posts: 457
Location: Pennsylvania!

PostPosted: Sat Dec 08, 2007 8:01 pm    Post subject: Reply with quote

Pardon me while I shoot down most of your ideas :\

Quote:
Drop the need for a local keyword, it should be local as default and it would be nice to not have to type anything before a variable name when you declare it (ruby).


Implicit variable declaration? No thanks. When basing MiniD off Lua, I actually introduced the 'global' keyword because of all the problems you can have by "accidentally" declaring global variables in Lua by making a typo. Having used languages that let you implicitly declare local variables (Python, various Basics), I know that's something I most certainly do not want.

Quote:
Why only one constructor?


For the same reason you can only have one function by the same name: they are just variables holding a reference to a function closure. You can, however, have multiple control paths within the constructor (or any function) based on the number and types of arguments.

Quote:
Open classes like in ruby. Meaning, you can always open an already existing class and add more things to it.


You already can modify existing classes, but there's no sugar for it as in Ruby. Just field-assign into a class, like "A.someNewMethod = function() ...".

Quote:
Properties (if not already exists). Introduce two new keywords "get" and "set". Then if you add them in front of a method it would become a property.


You can do properties with the new opField and opFieldAssign metamethods. It's one of the main reasons I introduced them Smile

Quote:
Is there any protection(public, private) for classes by the way?


No. I've been thinking about it and it probably wouldn't be too incredibly difficult to implement though. It can be somewhat emulated by doing something like:

Code:

// Introduce an anonymous scope to keep locals private
{
   local function bar()
   {
      writefln("I'm bar, x is {}", mX)
   }

   global class A
   {
      mX

      this(x)
      {
         writefln("A ctor")
         mX = x
      }

      function foo()
      {
         writefln("foo!")
         bar(with this)
      }
   }
}


Now you can access "a.foo()" but not "a.bar()". Of course, this isn't a perfect substitute since bar isn't really part of the class and can't participate in polymorphism.

I doubt protection will make it into MD2 but it's definitely something I'll consider for MD3 (which will probably be quite a departure from MD1 and 2..).

Quote:
Always return the last thing in a function so you don't have to type "return" (ruby)


Mm. That's possible, especially when considering the next point:

Quote:
Drop need for braces in functions only containing one row, like if and for statements


I've been strongly considering adding this Smile It's a natural extension of the existing function literal "lambda" syntax ("function(x) x * x"). If it contains a statement, parse that; else, parse it as an expression.

Quote:
Doesn't it seem more logical to have a semicolon in the above for statement than a colon?


I dunno. Does it? Maybe I'll make it optional, either colon or semicolon. It's unambiguous either way. (D2 uses a semicolon after the index for numeric for loops, right? I actually came up with the MiniD syntax before Walter came up with his..)

Quote:
Doesn't it seem more logical to have a semicolon in the above for statement than a colon?


No way, no how. Functions are just variables, and as such, using a function's name without parameters (1) already has a well-defined meaning -- it's how you get the "address" of the function, and (2) determining whether to make a function call or just get the value in the variable would require a runtime check every time you used a variable to see whether it contained a function (or any callable type, which is any type in fact, as long as it defines opCall). No no no.

FWIW Ruby is one of the slowest scripting languages out there, as well as being almost as difficult as C++ to compile and implement. It's an example of what too much syntactic sugar combined with extremely flexible runtime semantics can do. Many of the features I'd like to have for MiniD would be either prohibitively expensive or just plain impossible to implement given its dynamic nature.

[edit]Ligustah! Missed your post.

Quote:
attribute tables seem to be very useful to me, though i think they should be attachable to fields, too


Attribute tables are attached not to symbols, but to the class, function, and namespace objects themselves. Attaching them to fields in a class would be tricky. What it could do, though, is just be syntactic sugar for sub-attribute tables of the class's attribute table, or you could just write those yourself directly in the attribute table for the class if there's no special syntax introduced.
Back to top
View user's profile Send private message
doob



Joined: 06 Jan 2007
Posts: 367

PostPosted: Mon Dec 10, 2007 10:43 am    Post subject: Reply with quote

Quote:
I actually introduced the 'global' keyword because of all the problems you can have by "accidentally" declaring global variables in Lua by making a typo.


I've never used lua. I read at lua.org that "Any variable is assumed to be global unless explicitly declared as a local". I thought you could do it the other way, Any variable is assumed to be local unless explicitly declared as a global, I don't see how you can accidentally declare global variables if they are local as default. And is there any problem with accidentally declare a variable as local.

Quote:
I dunno. Does it? Maybe I'll make it optional, either colon or semicolon. It's unambiguous either way. (D2 uses a semicolon after the index for numeric for loops, right? I actually came up with the MiniD syntax before Walter came up with his..)


The D foreach loop uses semicolon and all "C style" language I know about uses semicolons in for loops. Only Java uses colon in it's "foreach" loop.

I came up with an other thing that you probably don't like. Add "embedded code in HTML" parser or what to call it as bobef did
(http://www.dsource.org/forums/viewtopic.php?t=3172)
Back to top
View user's profile Send private message
JarrettBillingsley



Joined: 20 Jun 2006
Posts: 457
Location: Pennsylvania!

PostPosted: Mon Dec 10, 2007 11:45 am    Post subject: Reply with quote

Quote:
Any variable is assumed to be local unless explicitly declared as a global, I don't see how you can accidentally declare global variables if they are local as default. And is there any problem with accidentally declare a variable as local.


What I was getting at is that Lua allows implicit declaration of variables, global in its case. I don't like implicit variable declaration, so I introduced the 'global' keyword. Removing the 'local' keyword would be against my own desires and also just moving the problem from global scope to local scope. I can't tell you how many bugs I had in Basic languages that let you implicitly declare locals because I typed an assignment wrong. It's the same idea, whether the implicit declaration makes a global or a local.

Quote:
I came up with an other thing that you probably don't like. Add "embedded code in HTML" parser or what to call it as bobef did


I certainly like it, and think people would like to be able to do it, but I don't think it should be part of the core language. Lua does quite well for itself by having "patches" -- bits of code that modify a vanilla install of Lua to make it behave differently. There are tons of them, see this page from the Lua-Users wiki for a list. Something similar for MiniD would be great Smile
Back to top
View user's profile Send private message
r.lph50



Joined: 27 Nov 2006
Posts: 21
Location: New Zealand

PostPosted: Fri Dec 14, 2007 11:04 pm    Post subject: Reply with quote

Cool. I like the attribute tables and opMethod additions.

JarrettBillingsley wrote:
You can do properties with the new opField and opFieldAssign metamethods. It's one of the main reasons I introduced them Smile

What about python style 'class' properties? That is, a class has a field which is another object. When that object's value is changed a meta method is called which gives the object a reference to itself (python's explicit self which I guess corresponds to MiniD's function context), the object it is a field in (this is really important to me) and the value. When the value is requested a meta method is called with similar arguments. This way you don't slow down all field accesses, and can do cool magic to the object which has the property (like the python ORMs Storm and Dejavu do). (You're also allowed to create a property for a field by passing in set, get, and optional delete functions to the property function).

JarrettBillingsley wrote:
Ruby is one of the slowest scripting languages out there, as well as being almost as difficult as C++ to compile and implement. It's an example of what too much syntactic sugar combined with extremely flexible runtime semantics can do. Many of the features I'd like to have for MiniD would be either prohibitively expensive or just plain impossible to implement given its dynamic nature.

Yes, Ruby is very difficult to parse, and has no spec/grammar (unlike MiniD Smile ). But as I understand it Ruby is so slow chiefly because of its implementation (one example: the interpreter runs off an AST rather than bytecodes). Smalltalk is just as dynamic and has implementations faster than python, which is faster than ruby.

All I have on my wishlist is:
  • access to the parse tree from within MiniD or the native API
  • separate meta-methods for all the stuff opCmp does
  • loading from file (for binary modules) to use mmap
  • unload/reload of modules (maybe a bit much, instead I guess I could just use a new MDContext every time I want to reload modules)
Back to top
View user's profile Send private message AIM Address
JarrettBillingsley



Joined: 20 Jun 2006
Posts: 457
Location: Pennsylvania!

PostPosted: Sat Dec 15, 2007 9:32 am    Post subject: Reply with quote

Quote:
What about python style 'class' properties? That is, a class has a field which is another object. When that object's value is changed a meta method is called which gives the object a reference to itself (python's explicit self which I guess corresponds to MiniD's function context), the object it is a field in (this is really important to me) and the value. When the value is requested a meta method is called with similar arguments. This way you don't slow down all field accesses, and can do cool magic to the object which has the property (like the python ORMs Storm and Dejavu do). (You're also allowed to create a property for a field by passing in set, get, and optional delete functions to the property function).


Looking at the Python property() function, it seems that this kind of thing could be implemented atop opField and opFieldAssign. In fact, I know that it can, since the mixinProperties function in sample.md basically does exactly this. You register a bunch of properties, each with its own setter and getter, and when you access a field that doesn't exist in the class, it goes to opField or opFieldAssign, which look up the properties in a property table, and call the appropriate getter or setter.

Quote:
But as I understand it Ruby is so slow chiefly because of its implementation (one example: the interpreter runs off an AST rather than bytecodes).


Surprised

Quote:
access to the parse tree from within MiniD or the native API


I was thinking about this Very Happy If I were to separate the lexer/parser out of the compiler, it could be used (1) for AST manipulation, (2) for writing source analysis/manipulation tools (integration with IDEs etc.), and (3) for writing a more robust interactive interpreter, which wouldn't be "stupid" and lose everything you've typed in i.e. a class if you make a single error. I'm going to look into how Python does it and see what I can come up with. I'll also be looking at MetaLua, God that is hot.

Quote:
separate meta-methods for all the stuff opCmp does


You mean, i.e. opLess, opLessEqual, opEqual, etc.? Ugh... might I ask why?

Quote:
loading from file (for binary modules) to use mmap


This I don't quite get. What's the advantage here?

Quote:
unload/reload of modules (maybe a bit much, instead I guess I could just use a new MDContext every time I want to reload modules)


As I explained in this thread, it's possible, but tricky. Basically the problem is that namespaces can be modified at runtime, and you can never know exactly what to unload or reload. [edit]hehe, I just read the Python "reload" function description, and they say basically the same thing :_ So now I know I'm not alone. Seems like it wouldn't be too hard to do.
Back to top
View user's profile Send private message
r.lph50



Joined: 27 Nov 2006
Posts: 21
Location: New Zealand

PostPosted: Mon Dec 17, 2007 12:33 am    Post subject: Reply with quote

Cheers for the reply

JarrettBillingsley wrote:
Looking at the Python property() function

I should probably never have mentioned it, because its not really what I'm after. Turns out I am after 'descriptor classes'. Sorry.

The attraction of python descriptors to me is how automatic it is. You create a class with a __set__ and __get__ function and then use it in any other class as a field. No need to overload a function that's going to get called on every property access, no need to do a mixin etc. There is a how-to which shows how descriptors interact with __getattribute__ (basically MiniD 2's opField).

JarrettBillingsley wrote:
You mean, i.e. opLess, opLessEqual, opEqual, etc.? Ugh... might I ask why?

Ok, stupid example:
Code:

class DatabaseTable : MagicSQLBase
{
   table = 'custom_table'
   field = MagicIntegerProperty();
}
results = DatabaseTable.select(function(tbl) { tbl.field > 1 & tbl.field <= 5 });

If field had access to what type of comparison, the DatabaseTable (as per python descriptors), and its variable name (again as per python descriptors __init__) then we could turn that anonymous function into SQL:
Code:
SELECT * FROM custom_table WHERE field > 1 AND field <= 5;

Alternative is to use the parse tree..

JarrettBillingsley wrote:
This I don't quite get. What's the advantage here?

I haven't tested it but I understand that using a readonly mmap'd file will involve less user space buffers and therefore less memory copying. Especially when running multiple interpreter processes, like in a web server situation. I should probably check how MiniD parses a .mdw file though, and test if mmap makes any difference especially on such small files. When I have mmap'd larger files with Tango it has made a noticable difference.
Back to top
View user's profile Send private message AIM Address
JarrettBillingsley



Joined: 20 Jun 2006
Posts: 457
Location: Pennsylvania!

PostPosted: Mon Dec 17, 2007 9:00 am    Post subject: Reply with quote

Quote:
The attraction of python descriptors to me is how automatic it is. You create a class with a __set__ and __get__ function and then use it in any other class as a field. No need to overload a function that's going to get called on every property access, no need to do a mixin etc.


Ahh, now I see what they are. They are pretty cool.. although the entire class model would have to be changed to work around them like in Python. Which, after having designed the MiniD class model to work the way it does, I'm not sure I want to do. I mean, it could still be in the cards, but I wouldn't bank on it.

Quote:
If field had access to what type of comparison, the DatabaseTable (as per python descriptors), and its variable name (again as per python descriptors __init__) then we could turn that anonymous function into SQL


Surprised That seems terribly hackish, don't you think? As you mentioned it, I think the parse tree would be the way to go here..

Quote:
I haven't tested it but I understand that using a readonly mmap'd file will involve less user space buffers and therefore less memory copying. Especially when running multiple interpreter processes, like in a web server situation. I should probably check how MiniD parses a .mdw file though, and test if mmap makes any difference especially on such small files. When I have mmap'd larger files with Tango it has made a noticable difference.


It just uses a plain old FileConduit right now.
Back to top
View user's profile Send private message
Ligustah



Joined: 21 Oct 2007
Posts: 45
Location: Berlin, Germany

PostPosted: Tue Dec 18, 2007 10:35 am    Post subject: Reply with quote

Hi,
It seems that there is no optional comma? I think it would be quite cool if something like this was possible:
Code:
local blubb =
{
    test="value1"
    blabla=value2
    lalala=5
    number=63
}

You see my point? I think allowing that cool optional semicolon (in this case obviosly 'comma') to be used in tables and arrays would make everything much more intuitive.

Mfg Ligustah
Back to top
View user's profile Send private message
JarrettBillingsley



Joined: 20 Jun 2006
Posts: 457
Location: Pennsylvania!

PostPosted: Tue Dec 18, 2007 2:11 pm    Post subject: Reply with quote

Optional comma in tables and arrays.. doesn't introduce any ambiguity, I think I'll do it.
Back to top
View user's profile Send private message
Ligustah



Joined: 21 Oct 2007
Posts: 45
Location: Berlin, Germany

PostPosted: Tue Dec 18, 2007 2:22 pm    Post subject: Reply with quote

Cool Very Happy
Back to top
View user's profile Send private message
dhasenan



Joined: 03 Feb 2005
Posts: 73
Location: New York

PostPosted: Thu Feb 28, 2008 11:15 am    Post subject: Reply with quote

Hey, can you use varargs in opFieldAssign?
Then you'd get stuff like:
foo.bar = 1, 2, 3

Difficult to parse, I'm sure.
Back to top
View user's profile Send private message AIM Address
Ligustah



Joined: 21 Oct 2007
Posts: 45
Location: Berlin, Germany

PostPosted: Thu Feb 28, 2008 12:21 pm    Post subject: Reply with quote

dhasenan wrote:
Hey, can you use varargs in opFieldAssign?
Then you'd get stuff like:
foo.bar = 1, 2, 3

Difficult to parse, I'm sure.


Hi,

couldnt you just do:
Code:
foo.bar = [1, 2, 3]
?

Of course you had to check if the parameter of opFieldAssign is an array.

Ligustah
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic     Forum Index -> MiniD All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group