Re: Added the "as" parser and tests

5 views
Skip to first unread message

Russ

unread,
Oct 9, 2007, 2:31:03 AM10/9/07
to Milescript
I'm posting my last response to this up here on the google group.
These types of discussions should go here so others who might be
interested can see what we're up to, and even chime in if they like.
--

I really like the use of parenthesis! I think that'll fix it - it's
plenty to disambiguate between

public external class Foo at declared

and

public external class Foo at (declared)

In addition, typing a string literal might give the coder the
impression that they could type any old crap there, while having it in
parentheses sort of gives the impression to the coder that the
compiler is going to pick over it with a fine-toothed comb.

So how about this:

Good:
external class Foo at root : at the root of the JavaScript namespace
external class Foo at declared: at the same namespace as the package
declaration for the class.
external class Foo at (root) : at the JavaScript namespace named
'root'
external class Foo at (declared) : at the JavaScript namespace named
'declared'
external class Foo at (google.feeds) : at the JavaScript namespace
named 'google.feeds'

Error (not exact parser output, but you get the drift):
external class Foo at {} : error - expecting 'root', 'declared', or
'(', found '{'
external class Foo at () {} : error - empty JavaScript namespace
declaration
external class Foo at (.) {} : error - expected identifier, found '.'
external class Foo at (.blah) : error - expected identifier, found '.'
external class Foo at (blah.) : error - expected identifier, found '.'
external class Foo at (blah..baz) : error - expected identifier, found
'.'
external class Foo at blah : error - expected 'root', 'declared', or
'(', found identifier

Portions up in the linker area would have to enforce 'at' and
'nameless' usage only being used on external classes, but they'd issue
compiler errors as well if code ran afoul of them, of course.

I think that'll look good enough in code, and won't disallow
namespaces with the same name as those two keywords.

William Youree wrote:
> That's a good point. I hadn't thought of that. We could approach this is a couple ways.
>
> We could use the StringLiteral.
>
> public external class APILoader at "google.feeds" { }
>
> We could allow KeyWord's to appear in the DotExpression which comes after the "at" KeyWord.
>
> public external class APILoader at google.feeds { }
>
> Or we could wrap the DotExpression in some kind of function-esque syntax like we discussed for the bind KeyWord. That would indicate more clearly the purpose of the code.
>
> public external class APILoader at namespace("google.feeds") { }
>
> or
>
> public external class APILoader at namespace(some.namespace) { }
>
> We can use the DotExpressionProcessor to parse the String in any case, so we can have any of those options working quickly. Any thoughts on the other approaches?
>
> - Greg
>
> On 10/9/07, *Russell Morris* <rus...@russellsprojects.com <mailto:rus...@russellsprojects.com>> wrote:
>
> I agree with you completely that the String Literal looks messy,
> but if
> we don't use a string literal, we would never be able to wrap
> classes or
> functions in external namespaces named 'root' or 'declared'. In
> terms
> of backwards-compatibility, I didn't think that was viable. I'd
> hate to
> have someone run up against needing to do that, and have our only
> response be "you're SOL". Can you think of a way that we could use a
> normal dotted reference and still be able to distinguish between the
> 'declared' keyword and wanting to emit code that uses the JavaScript
> namespace named "declared". i.e.
>
> function declared() {
> function foo() {}
> function bar() {}
> function Baz() {
> function bot();
> }
> }
>
> We couldn't write "external class Baz at declared", because the
> compiler
> would confuse 'declared' for the keyword, when we intended to use
> it as
> the existing JavaScript namespace. The same goes for writing
> "external
> nameless FunctionsInDeclared at declared" to access foo() and
> bar() from
> within Milescript. I couldn't think of any what around this,
> except to
> use a string literal to declare an explicit namespace.
>
> As for the modifier collection - I agree that we should make it so
> that
> multiple modifiers can be attached to classes. For this specific
> instance, we'll only want 'nameless' to appear alongside 'external',
> because at its guts it's an interop hack, not a proper language
> feature
> that'd be necessary if we weren't compiling to
> JavaScript. However, if
> we eventually do need extra class modifiers (I can't think of any
> at the
> moment), we'd have the infrastructure in place.
>
> William Youree wrote:
> > Wow man, that looks great. I'll make those changes tomorrow
> morning to
> > the parser and the NST. It should be very quick. I think the
> > identification of the JavaScript namespace which follows the "at"
> > keyword should be a regular DotExpression rather than a
> StringLiteral,
> > just because the only thing allowed in the StringLiteral is a
> > DotExpression and we already have the parser setup to parse
> those. I
> > could use the DotExpressionProcessor to process the value of the
> > StringLiteral though, so we could do it either way. I kind of
> think it
> > would be cleaner without the quotes. Other than that I think it's
> > perfect. Since the default is to do what we do already, we
> won't have
> > to change any library classes unless we want to take advantage
> of the
> > new feature to make certain external functions and classes
> behave better.
> >
> > Another thing that I thought of while reading the specs, what if we
> > made "nameless" a modifier and placed it in the same Collection
> > attribute as the "external" modifier in the NST
> ClassNode. Should any
> > other types of classes be allowed to have more than one
> modifier? If
> > not, maybe we should still architect it this way so we have that
> > option in the future.
> >
> > - Greg
> >
> > On 10/8/07, *Russell Morris* <rus...@russellsprojects.com
> <mailto:rus...@russellsprojects.com>
> > <mailto: rus...@russellsprojects.com
> <mailto:rus...@russellsprojects.com>>> wrote:
> >
> > Josh and Ray: Greg and I came up with some language
> additions that'll
> > allow us to create external Milescript classes to refer to
> existing
> > JavaScript classes and functions not declared at the root of the
> > JavaScript namespace. This email is a reference to that - I've
> > included
> > you guys so you could see it as well.
> >
> > Greg:
> > Sweet - that was quick.
> >
> > Unfortunately, I think we'll need to make a few minor
> changes. I was
> > writing up the docs explaining "as" for the wiki, and in
> writing the
> > code samples using "as" it started to look a bit unclear
> when put in
> > code. I've written up a doc explaining the modifications I
> think we
> > should make, as well as why. I've attached it to this email
> - we can
> > talk about it tomorrow to finalize things. I'm willing to
> be that
> > it's
> > only a few tweaks to your parser, and a few extra things
> we'll need to
> > do in the linker layer to enforce intended usage.
> >
> > Long story short:
> >
> > Change "as" to "at", and require the following to come
> immediately
> > after
> > it and before the opening brace of the class definition:
> > "root" : keyword indicating the root namespace
> > "declared" : keyword indicating the package declared in the
> "package"
> > statement in the class being compiled.
> > [String Literal]: A string literal that is a dotted reference
> > chain like
> > " google.feeds". Cannot start or end with '.'
> >
> > "at root" means the external class is at the root of the
> JavaScript
> > namespace
> > "at declared" means the external class's package declaration is
> > the same
> > as the external JavaScript class's location in the JavaScript
> > namespace.
> > "at "google.feeds"" means the external class is at the
> JavaScript
> > location "google.feeds", regardless of the package
> declaration of the
> > external class. Allowing this will allow us to essentially
> > re-organize
> > existing code into packages structure like
> "com.company.blah.foo"
> > without requiring the existing JavaScript code be re-organized
> > itself.
> >
> > In addition, I've suggested a class modifier "nameless"
> which can
> > optionally be applied to external class declarations. If this
> > modifier
> > is present, the generator does not use the class's name when
> > generating
> > calls to the class's functions, but DOES use the prefix as
> > specified by
> > the external class's "at" declaration.
> >
> > Put these two things together, and we can use Milescript
> classes and
> > packages to safely reference new-able and non-newable
> JavaScript
> > functions wherever they've been declared in the JavaScript
> > namespace, as
> > long as we have the information at compile-time. And we can
> keep them
> > in any package structure we like.
> >
> > I've included example Milescript code -> Generated
> Javascript for
> > clarity in the attached document. I think this stuff will
> really open
> > Milescript up to cleanly interoperating with damn near any
> JavaScript
> > code out there. I think it'll be key to any JSON-interop
> library we
> > create, as well. I was initially worried that it was a bit too
> > complicated, and could encourage bad habits, but I think
> we're heading
> > that off at-the-pass by constraining "nameless" and "at" to only
> > external classes, whose sole purpose is to interact with
> > non-Milescript
> > code.
> >
> > Russ
> >
> > William Youree wrote:
> > > Hey man,
> > >
> > > I added the "as" parser to the ClassDefinition parser and also
> > added
> > > the tests and modified the specs in all four formats. If
> you want to
> > > make a wiki page describing the usage of "as" and "bind" that
> > would be
> > > great, and we could add that to the Developer Log on the front
> > page.
> > > See ya tomorrow.
> > >
> > > --
> > > - Greg Youree
> > > Point5u, LLC
> > > Co-founder
> > > (404) 227-3500
> > > wgyo...@gmail.com <mailto:wgyo...@gmail.com>
> <mailto:wgyo...@gmail.com <mailto:wgyo...@gmail.com>> <mailto:
> > wgyo...@gmail.com <mailto:wgyo...@gmail.com> <mailto:
> wgyo...@gmail.com <mailto:wgyo...@gmail.com>>>
> >
> > The "at" and "nameless" modifiers for external classes.
> >
> > The purpose of the "at" and "nameless" modifiers are to
> instruct
> > the JavaScript
> > generator where an external class and its member functions
> should
> > be found in
> > the JavaScript environment. The generator will generate the
> code
> > to access the
> > class and/or function based upon these modifiers.
> >
> > "nameless" tells the compiler that the external class's name
> > should not be
> > used to access its member functions in JavaScript.
> >
> > "at" tells the compiler where in the JavaScript environment it
> > should expect
> > the implementation of the external class to exist.
> >
> > "nameless"
> > ----------
> > Nameless external classes are essentialy anonymous function
> > containers in
> > JavaScript. The nameless class's class name is not used by the
> > generator
> > when it generates code to use the external functions it defines.
> >
> > Constraints on nameless classes:
> > --------------------------------
> > Nameless classes must be external, and must not have
> constructors,
> > as they
> > cannot be created with the new operator.
> >
> > Default behavior if not specified:
> > ----------------------------------
> > Default behavior (the generator's current behavior) is used
> if the
> > nameless
> > modifier is not specified for a class.
> >
> >
> > "at"
> > ----
> > The "at" keyword can be appended to the intial class
> declaration,
> > before the
> > class body, to declare to the code generator where the given
> class
> > (or its
> > functions, if the class is nameless) should be located in
> the external
> > JavaScript environment.
> >
> > Valid "at" declarations:
> > ------------------------
> >
> > "at root":
> > The generator locates the class at the root of the JavaScript
> > environment.
> >
> > "at declared":
> > The generator locates the class in the JavaScript environment
> > using the
> > exact same namespace as that declared with the "package"
> keyword
> > for the
> > class.
> >
> > "at "path.to.class""
> > The generator locates the class in the JavaScript
> environment by
> > appending
> > its name to the reference chain path.to.class. The reference
> > chain must contain
> > at least one element, must have only valid identifier names
> > separated by
> > exactly one '.', and may not start nor end with a '.'.
> >
> > Constraints on "at" declarations:
> > ---------------------------------
> > The "at" declaration may only be applied to external classes.
> >
> > Default behavior if not specified:
> > ----------------------------------
> > If not specified, the default behavior is to act as though "at
> > root" was
> > specified.
> >
> >
> > Generator interpretation of "nameless" and "at" combinations:
> > -------------------------------------------------------------
> >
> > [Milescript snippet] -> [Generated JavaScript snippet]
> >
> > package com.milescript.test;
> > public class Foo at root {} -> Foo
> >
> > package com.milescript.test;
> > public class Foo at declared {} -> com.milescript.test.Foo
> >
> > package com.milescript.test;
> > public class Foo at " other.place.to.be
> <http://other.place.to.be> <http://other.place.to.be>"
> > -> other.place.to.be.Foo
> >
> >
> > [Milescript snippet] -> [Generated JavaScript snippet for
> calling
> > function bar() defined in class Foo]
> > package com.milescript.test;
> > public nameless class Foo at root {} -> bar();
> >
> > package com.milescript.test;
> > public nameless class Foo at declared {} ->
> com.milescript.test.bar();
> >
> > package com.milescript.test ;
> > public nameless class Foo at "other.place.to.be
> <http://other.place.to.be>
> > < http://other.place.to.be>" -> other.place.to.be.bar();
> >
> >
> > Usage examples along with generator output.
> > First, a few classes using "nameless" and "at" declarations to
> > properly
> > wrap Google's AJAX API loader and Feeds AJAX API
> > ===============================================================================
> > package wrap.google.ajaxapi;
> >
> > public external nameless class APILoader at "google" {
> > public external void load(String apiName, String
> apiVersion);
> > }
> >
> > ----
> > Milescript code: APILoader.load("feeds", "1");
> > becomes
> > JavaScript code: google.load("feeds", "1");
> >
> > ===============================================================================
>
> > package wrap.google.feeds;
> >
> > public external class Feed at "google.feeds" {
> > public external Feed(String feedUrl);
> > public external void load(FeedLoadDelegate callback);
> > }
> >
> > ----
> > Milescript code: = new Feed("http://some/url");
> > becomes
> > JavaScript code: = new google.feeds.Feed (" http://some/url");
> > ===============================================================================
> >
> > package wrap.google.feeds;
> >
> > public external nameless class FeedsHelpers at " google.feeds" {
> > public external void findFeeds(String query,
> > FindFeedsDelegate callback);
> > }
> > ----
> > Milescript code: FeedHelpers.findFeeds("Foo", new
> > FindFeedsDelegate(callback));
> > becomes
> > JavaScript code: google.feeds.findFeeds("Foo", [delegate
> creation
> > code...]);
> > ===============================================================================
>
> >
> >
> > The following example should, I think , become the core
> Milescript
> > library's
> > method of declaring the various intrinsically available
> functions.
> > ===============================================================================
>
> > package core;
> >
> > public external nameless class Intrinsics at root {
> > public external int parseInt(String str);
> > public external Object eval(String expression);
> > }
> > ----
> > Milescript code: Intrinsics.parseInt(123);
> > becomes
> > JavaScript code: parseInt(123);
> >
> >
> >
> >
> > --
> > - Greg Youree
> > Point5u, LLC
> > Co-founder
> > (404) 227-3500
> > wgyo...@gmail.com <mailto:wgyo...@gmail.com>
> <mailto:wgyo...@gmail.com <mailto:wgyo...@gmail.com>>
>
>
>
>
> --
> - Greg Youree
> Point5u, LLC
> Co-founder
> (404) 227-3500
> wgyo...@gmail.com <mailto:wgyo...@gmail.com>

William Youree

unread,
Oct 9, 2007, 12:27:48 PM10/9/07
to miles...@googlegroups.com
That sounds good, Ray liked the paren syntax also. I've got the Parser parsing the new syntax already, I've added the keywords "nameless", "root" and "declared" and setup the Implements parser to handle the "at" keyword syntax, which will require the "at" syntax to appear immediately before the opening brace of the ClassBody. Right now I'm working with the Assemblers and NST and creating more elaborate unit tests to cover the new scenarios. I should have that done in a few minutes. Also, any keyword can appear in the DotExpression contained in the parens, so we can still work with external javascript namespaces that happen to use one of our keywords. The attribute which stores the at Reference chain is now called atReference rather than asReference.

- Greg

William Youree

unread,
Oct 9, 2007, 12:35:11 PM10/9/07
to miles...@googlegroups.com
Also, "nameless" is now a modifier which can only appear in class declarations. So if nameless is used, it will be in the Modifiers Collection in the ClassNode.

- Greg
Reply all
Reply to author
Forward
0 new messages