1

advertisement
1
>> Sebastian Burckhardt: Hello, welcome to this session. It's my pleasure to
introduce Eelco Visser from Delft University of Technology. Eelco is an
associate professor, and I met him at a PC meeting for Splash. And at the
time, I was just starting to get interested into mobile programming and
research problems and it was a shock to discover his paper, which essentially
looked to me like he did everything already.
So in the meantime, I've relaxed a little so there's plenty of research left to
do. But he's here today to tell us about his special research on mobile
development, but also on general background in program languages and on how to
build domain specific languages.
>> Eelco Visser: Thanks. Thanks for having me. Right, so the title of this
talk is software language design and engineering, which is sort of the mission
statement of my research group in Delft. And so I wasn't quite sure what
audience I would get here. And I'll be here today and tomorrow morning. So I
wanted to give a sort of introduction to the sort of work we do in my group, as
we give you an impression of what we're doing so that we can -- well, as a
starting point for talking and seeing if there's leads for collaboration. And
one of them is this mobile, work on mobile.
So the general problem I'm addressing is this. We are only software
engineering, and the problem there is how to get from problem domains to code
[indiscernible] on the machine, and we have to bridge this gap and so as a
community, we've been developing high level programming languages that reduce
that group so we don't have to [indiscernible] assembly code anymore. And this
works very well, pretty well, but there are still some gap left there.
And the idea is that with between domain specific languages, we can further
reduce that gap, a lot of them saying well, we design languages that are
designed for arbitrary applications. We design languages that are specialized
for a particular problem domain so that we can better, well, reduce accidental
complexity. So sort of the background of my work.
And then our mission is to, or our research is to enable software engineers to
effectively design, implement and apply domain specific languages in software
engineering. And that falls into two categories.
So traditionally, I've been working in compiler construction tools.
That's
2
sort of my background. So what we try to do is if you want to make domain
specific languages or linguistic abstraction as sort of an engineering methods,
then you should have good tools to make DSLs. And so making DSLs should be as
easy as making [indiscernible] general programming. That's the goal.
So anyway, to do that, what we need is declarative language definitions that
allow us to automatically derive efficient, scaleable, incrementable compilers
and also, these days, usable IDEs so that we can get good productivity. So
that is the aim and we are getting pretty good at it now. But there's still
lots of work to do.
And so one of the domain results of this is the Spoofax language workbench
which is an eclipse log in for making languages. So you can define languages
in the sort of syntax and semantics of your language using DSLs for language
for language definition. And from that, you compile and built to get a new
[indiscernible] plug-in that is special for your language and it has all the
usual IDE features and so on. I'll talk about it in the second part of this
talk.
And so I've been doing that work on making tools for making languages for a
pretty long time, and we're actually getting somewhere with that, and we now
have tools where you can actually make languages. So now if you can do that,
then the question becomes, well, how do you actually do this, making a new
language.
So at the beginning, we used to try our tools on well-known programming
languages. Said, well, can we make a compiler for Haskell or source to source
transformations for Haskell programs or that sort of stuff. But it's much more
interesting to make new DSLs, and then the question becomes given some domain,
how do I systematically and effectively design a language for that domain that
will allow me to have better productivity in programming that domain.
And there's much less technical stuff like here's a syntax -- here's a grammar
and [indiscernible]. It's more about language design and how to do that.
So we started studying systematic design of domain specific languages where you
have to find a good trade-off in these different properties of languages.
Expressivity, so how easy it is to express something in language. The
completeness, how well do you -- I mean, do you generate complete codes, or do
you generate a bit of code and then you do the program some other stuff in your
3
target language.
Portability, can you actually address, generate code for different platforms.
Coverage, how well do you cover the domain. Can you express everything that
you want. And maintainability. If your target platforms move, can you quickly
move your compiler to also address those changes without changing the models in
your DSLs.
And since I moved to Delft in 2006, I've been starting to do work in this
domain, which is case studies in DSL design. In particular, so my students do
lots of little languages, but in particular, we'd be looking in the domain of
web programming, and we've designed and built two languages. One is called
WebDSL, which is a web programming on the server, so a web application where
you generate pages that people interact with via browser.
And but most of the action happens on the server. So this is one of the
applications. So once you build a language, you also have to build
applications with it so this application is [indiscernible] with your digital
library application. It has over a million and a half publication records, and
you can actually use. So that has become another interest of mine that I'm
interested to talk about with people.
And more recently, we've been looking at the mobile web, and so nowadays when
you have a web application, you also need to have an application that runs on
your mobile phone, and for that we have developed Mobl, which is a client side
stateful web application. And that's what I'm going to talk about now.
So this talk is really two talks. In the first part of the talk I'm going to
talk about languages on case study Mobl. So declaratively programming the
mobile web with Mobl. And second half of the talk I'm going to talk about the
Spoofax, language workbench. How do you make languages technically with ->>:
Can you tell me where Spoofax comes from?
>> Eelco Visser: Yeah, so it has been invented by engineers, by Karl
[indiscernible], who was a Norwegian Ph.D. student who worked with me for a
year, and he actually came up with the name, and he engineered it so it was
Google unique at the time. So there was no hits in Google. And that wasn't
the main criteria. I didn't think about it so much at the time. Spoof, maybe
that's -- I'm not sure the connotations are actually right. But it has stuck.
4
So that's -- yeah, so there's no meaning, basically.
So this is sort of an [indiscernible] for giving talks and it may be a bit
longish. Also, not going very deep in both topics so I'd welcome questions you
may have about any of these things. I know that these guys are very interested
in the Mobl side of things and services. You may want to have that discussion
now or later. We'll see. I'm flexible.
All right. So first talk. Declaratively programming the mobile web with Mobl.
So this is joint work with Zef Hemel, who actually -- this is work by Zef
Hemel. He's my graduate student who has just submitted his Ph.D. thesis and
design and implementation is mostly his work.
So it may very well be that there are questions that I'm not able to answer
about, especially about the programming model, the deeper details there.
All right. So what is the domain? So we had been developing this web
programming language, and I will become interested in also making applications
for mobile phones and tablets. And Zef had actually been doing some work on
PIL, which stands for platform independent language, and the goal was to have
portability for DSLs. So if you make a high-level program, you would like to
be able to port it to multiple different platforms, and we, at the time we were
interested, we were doing web DSL. We had a Java [indiscernible], the Google
app engine came up and it had [indiscernible] program so we thought, well, we
have two back ends for web DSL. It would be pressing to have a single
intermediate language from which we could generate all those things.
We developed PIL as an example, and that works fine. So I mean, these target
languages are very similar. So actually, you can abstract the tiny syntactic
details. So we had approve concept, implementation that works.
It turned out there were some pretty deep problems afterwards. So one of the
problems was called hibernate, on the Java platform we use hibernate for object
ratio mapping, and that sort of determines the semantics for our data models.
There was no hibernate, there were other frame works for doing operational
mapping, but they had quite a defendant semantic. So you had to do explicit
saves to save objects, which you didn't have to do in the hibernate platform.
So it turned out that this -- so although the languages that we targeted were
pretty similar semantically, the language itself wasn't the real problem. It's
5
the platform. So all the APIs that you program against. And they we thought
again about this web domain which doesn't really matter that you can
[indiscernible] your web program. On a server, as a developer, you control the
server and it doesn't really matter, you can determine what platform you're
running on.
So we thought, well, so there's two developments we would like to have an
example of portability and, well, there's smart phones were coming up and this
was a pretty interesting domain itself.
And so this looked like a pretty good area for studying portability, right. So
there's all these different mobile platforms and if you are developing for
these platforms, you make an iPhone application that you provide in Objective-C
and then for Android, you have to program Java, and there are other platforms
as well. So that means you have to do a lot of double work.
So that was sort of the background of this work. We're going to make a
language for mobile applications and targeting different programming languages.
Then I came across a book on mobile web, and it said, well, actually, you
should program mobile applications with client side web applications. It was
actually many of these platforms have very powerful browsers that run HTML 5,
the universal user interface engine that actually runs on all these platforms.
And it's much more than HTML.
That's why we have -- so the architecture, you have the standard HTML and Java
script, and CSS and you connect with the web service to transport data. But
now there's also to access things in HTML 5, you have a local database in the
[indiscernible] device that you can store data in. You have access to GPS, and
while there's all sorts of other APIs that you can access. So there's local
information, you have a canvas you can paint on. There's multitouch support,
offline support. You can run these things in full screen so you don't actually
see the browser.
And if you then capture your [indiscernible] application Phone Gap, then you
can even have access to the native phone specific APIs if you're off the
platform.
>>:
What is it called again?
6
>> Eelco Visser: It's a tool that's -- and that's a web application, so a
client-side web application as a native application. So you can, for instance,
for iPhone, you can sell it in the Apple app store, and it looks like a native
application.
>>:
[inaudible].
>> Eelco Visser: And since you're running as a native application, you then
have access to these APIs. Which if you're just running in the browser, you
don't have access to all of these things. And it's not just -- I mean, it
works on many platforms. So you actually get portability.
So the platform here, we have HTML 5, it actually gives you a very rich
platform for building client-side phone applications. But, well, what does
that mean? You have to program a HTML 5. So it gives you sort of a platform
for doing this, but how you do it is pretty gruesome, right.
So you have to write the HTML in Javascript. So Javascript is the language
there. And so there are some frameworks for doing this, but, well, they use
this model view controller paradigm. Very little integration. No F-sections
and a lot of accidental complexity.
And then so this looks very much like the web programming on the server that we
looked at before. So for studying WebDSL, we looked at a bunch of different
web frameworks. We looked at Java, Seam, Ruby on Rails, and [indiscernible]
Lift so quite different styles of programs. And we looked at how they behave
if you make programming errors.
So even in the [indiscernible] time fonts like Lift and Java, it turns out that
many programming problems are reported as very late. So they appear at run
time and often in a very unclear way. And so the problem is that you have, in
addition to the general purpose programming language that you're programming
in, there's these other languages that you're programming in.
There's HTML and Javascript that is stuff that runs in the clients and you are
probably doing some sort of SQL, which is often embedded as strings in your
general purpose programming language. So it's [indiscernible] programming in a
bunch of different languages that are glued together in a not very well way.
So you get -- and our programming environments don't provide support about the
7
integration of these languages and they perform pretty poorly.
So with WebDSL, the slogan that we came up with was separation of concerns,
which is provided by all these different languages, right. So HTML is good for
presentation, SQL is good for database queries. But linguistically integrated.
You want to integrate these languages and let your programming environments be
aware of these languages and their integration.
And so Mobl is another -- grew from that experience with WebDSL, but it targets
this different domain of client-side applications. So rather than the untyped
environment of Javascript, it's statically typed. Rather than having these
separate languages for separate concerns which are not integrated, we have
different languages for different concerns, but they're integrated into a
single language, and it's declarative and concise, as I hope you'll agree with
me after this talk.
And just the results, you can program web applications for touch, right. So
these are all screen shots from applications built with Mobl that's run in a
phone and you can -- well, they have the usual touch interface, and they feel
like native applications.
And they can actually run on different devices so they can run on Androids and
tablets and they can use different form factors as well.
So, yeah, so the platform gives us portability and the language gives us a nice
way to perform this platform.
As far as the architecture, we have an IDE in which you write Mobl programs.
These Mobl programs are compiled to a combination of HTML, CSS and Javascript,
mainly a lot of Javascript. You deploy that as an HTML file on your server.
The Mobl device fetches the HTML file and as a result all the Javascript files,
which may be cached on the device so you should be able to use it offline.
Locally, the application can use the local database and other APIs, and it
typically then talks to a web server to JSON serves to transport data. Okay?
So this is the [indiscernible] world Mobl. Let me say, so this is a complete
application. And, well, I should -- you should first look at the code, because
it's very complicated.
8
So we say well, there's an application called tipcalculator that imports the
Mobl library and the application is a single screen, it's a root screen, that's
the thing that opens the IDE folder when you open the application, and we have
two local variables, amount and percentage, and this is a bit of [inaudible].
There's a header titled tipcalculator. And there's a group with three items.
The first shows the value of the amount variable. The second shows the value
of the percentage variable, and third is a complicated mathematical formula
that performs a computation based on these two.
And now these num fields actually is an edit interface so you can edit these
values. And whenever you edit one of these values, then the computed value
changes. So let me -- I should actually be able to show that. I think it's
15% here, right? So you see that whenever I change the percentage, the
calculated value changes automatically.
>>:
Not necessarily to the right value.
>> Eelco Visser:
I'm sorry?
>>: 1% of 245 is 287?
>> Eelco Visser:
17%.
Change that to 1% again.
It's a total.
>>:
The printing is only printing 24 and not 30.
>>:
I see.
[multiple people speaking]
>> Eelco Visser: I don't necessarily understand this.
total, you have to pay, that's the --
This is math.
The
>>: So one way to understand this screen root is it's a little bit -- so it's
declaring the user interface and but it's also binding data to code?
>> Eelco Visser:
>>:
Yeah, so it does data binding.
Does data binding?
>> Eelco Visser:
Yeah, so there's data bonding from the UI to variables.
So
9
that's all that's going on here. Also, there's a number field that says show
that value, but it's also num field is also an edit field. It's like an input
field in a web forum that you can edit. And as soon as you edit, change the
value, then that changed value is bound to the available and it's propagated to
wherever that variable is used.
>>:
If things are circular, your compiler gives an error?
>> Eelco Visser:
>>:
No.
[indiscernible].
Okay.
>> Eelco Visser: That's another question I got in a previous talk and we don't
do that currently. That would be interesting. But it's reactive programming
so this value reacts to changes of the model, and we could do interesting
analogies there. And I'm not sure, we haven't looked into that yet.
>>: But you use it to compute a fixed, point, though? If you know that's the
value, it doesn't actually change the value. Does it continue propagate?
[inaudible].
>> Eelco Visser:
>>:
If it's circular, yeah.
I think it loops.
So how do you deal with more complex expressions [inaudible].
>> Eelco Visser: So the idea is that this should be [indiscernible] values.
It's very straightforward, reactive programming. Yes.
>>:
Are these styles the UI have CSS-like support?
>> Eelco Visser: Yeah, so there's a styling language that allows you to style
these things. The library has default style attached to it, ask. You can
change that, and it does use CSS to do styling, but you can do it dynamically
and compute it, actually. And there are some [indiscernible] sections for
doing this.
All right. So let's move on. So what we use is the model-view pattern, as
we've called it. Normally, use a model-view controller pattern. And the
controller is something in web programming that takes the changes. In the
view, you make the changes and you send it to the controller. It analyzes the
10
changes and it updates them all and then you update the view.
And we found that that's often the controller is responsible for a lot of the
accidental complexity in programming. And here, you can see that it is absent,
right. So we just say the Mobl is these two variables. We have a presentation
of these variables that shows, well, given these values, show this on the
screen, but it also takes care of data binding. If an event happens to the UI,
we take care of taking it back to the model, updating the model, and, as a
consequence, updating the view.
And so we get rid of this intermediate controller. And, of course, the model
can be a bit more complex than a bunch of number variables so we have data
models, entities and logic. And in view, we have event handling and
presentation. So let's look at a more complex example.
So to-do list, we have a list of tasks that you can check. So what we have is
this task model. So tasks have a name and a dom a done field, a due date, and
we have categories and tags. And so in -- so in our language in Mobl, you can
represent this where it's an entity language where you can say we have an
entity task, which is a name, and a done field and due dates and a category
which is a single category and we have a tags, which is a collection of tags
and then we have entities for category and tags. And you see here that these
are inverse, which means that the properties are automatically synchronized.
So if you add a tag to a task, then automatically the task is added to the
tasks of the tag.
You see the name field is annotated as searchable, which means that we maintain
automatic search index in the device so we can do search. And so these data
models are all that you need to represent data, structure data in your
application, and persistence of that data in a local database is done
automatically for you. So if you create objects and they're automatically
added to the database, and you make changes to them, they're also recorded in
the database. So you don't have to think about persistence in your
programming.
>>: I'm sorry. Could you go back?
are we [inaudible]?
>> Eelco Visser:
So this is all, it's all value based?
So these are references to objects.
Or
11
>>:
And what's the inverse?
>> Eelco Visser: That makes sure that you have an automatic dual binding. So
if you add a -- if you say I have a category object and I add a task to it, so
category, task, adds a task, then the category field of the task is set to that
category. So you get an automatic ->>:
I see.
>>: So what if you added two different categories.
second one?
Then you gonna clear the
>> Eelco Visser: That's right, so since category one too many, you can only
add one category.
>>:
[inaudible].
>> Eelco Visser:
>>:
It is still going to be in the other category, right?
>> Eelco Visser:
>>:
Okay.
That's what the --
Remove it?
>> Eelco Visser:
Yeah.
So when you --
>>: So if I take the task and add it to Category 1, right, and then I add it
to Category 2, that second add will automatically remove it from Category 1?
>>:
[indiscernible].
>> Eelco Visser:
>>:
That's [indiscernible].
You can think of [indiscernible] just one data piece.
>> Eelco Visser: Basically, in the database, there's a single relation that
represents these.
>>:
And what if you have a category and you remove a task from a tasks field,
12
what happens with the task?
>> Eelco Visser:
>>:
The category field, though, the task becomes null?
>> Eelco Visser:
>>:
Yes.
So these things can be null or have values?
>> Eelco Visser:
>>:
It becomes null.
Right.
Are all the values nullable, or only --
>> Eelco Visser: Only the data references. Well, in WebDSL, we do the same
thing, where we're -- it depends, basically. Yeah, whether -- typically, if
you carried a new object, then value fields are initialized to default values.
So an empty string or zero or fold or something. But you can actually set them
to null as well. Whether you want that, you may want to configure in your data
model as well.
>>:
I see.
>> Eelco Visser: You could say some fields are not nullable and that's always
have a value. Yeah, so always a discussion whether you want that or not. It's
application dependent.
Yeah, so these are sort of things that you really would like to have in regular
programming languages as well. I mean, a lot of accidental complexity in
object or in programming comes in maintaining these sorts of relations.
All right. So you can add methods to entities. So basically, it's simple
[indiscernible] language, and, yeah, simple imperative language inspired by
Javascript. Details are not so important.
But the important thing is it's statically typed so we have a data model and we
check the functions or [indiscernible] for the data model and so on, which you
don't get in Javascript. Yeah?
>>:
So it looks like you've got some daytime in here.
Are you, like,
13
leveraging the Javascript built-in library and adding annotations to that, or
did you create your own?
>> Eelco Visser: No, this is really -- no, so underneath, things are mapped to
Javascript and the language is actually, you can directly import Javascript
libraries and you can also embed Javascript and then encapsulate that as a
function, as a Mobl function. So in those parts, we don't have static talking,
of course. But the idea is in the code that you write yourself, so this is
real Mobl codes and that is checked statically.
>>: But did you have to write get full year [indiscernible] yourself around
the Javascript.
>>:
The only thing that was annotated was the typed, right?
>> Eelco Visser:
>>:
No, you have to make those [indiscernible], yes.
So the day times were [indiscernible]?
>> Eelco Visser:
I suppose, yes.
>>: So what about the [indiscernible].
asynchronous thing, right?
>> Eelco Visser:
>>:
Obviously, that's going to be some
Um-hmm.
So how do you deal with asynchrony in this?
>> Eelco Visser: Well, so we do an automatic [indiscernible] transform. And
the only pattern in Javascript that's problematic is that you have to write
everything in [indiscernible] style. Writing sequential codes, you write a
function that wraps everything and takes the code back and then you get this
terribly [indiscernible] codes. We do that transformation automatically. So
you write sequential codes and for those things that are marked as
asynchronous, it turns into ->>: An example, basically between the initial request and the [indiscernible],
anything can happen, right?
>> Eelco Visser:
Yeah, so basically you turn it into a function with a call
14
back that caused the results.
>>: So what I'm asking, it's imperative to be [indiscernible], right? The
system is imperative. We have no clue as a programmer what data can be changed
[inaudible]. That's not a concern?
>> Eelco Visser: No, so this really takes, I mean, this is part of the
call-back. So this is turned into a function that takes the rest of the code
as a function as code when you get the results.
>>: Other events can happen in between, right?
between those.
So the state can change
>> Eelco Visser: Right. Okay, then well we saw the reactive UI so this is a
bit more complex example. So again we have a root screen with a local phrase
variable that we're going to use for searching. We have a header which has a
button and if we click it, we will go to a normal screen. We see that on the
next slide. We have a search box that passed the phrase variable, that passed
the reference. And we have group where we list the results of searching for
this phrase.
So we're searching for phrases for tasks that have the name that match this
phrase. I mean, and 20 of those. And we show a check box and a label. So
what happens if we type something in the search box, then the value of the
phrase variable is updated. So this phrase is passed by reference. So if
search is like the number field we saw before, it's like a normal user
interface element that you can with data binding. It's bound to the variable,
this phrase, and again the value of the search depends on the value of the
phrase. So as soon as phrase is updated, then the results of this search is
updated, and the list is specialized to list off things you're searching for.
Yeah?
>>: So do you do some incrementalization, or do you just re-run the entire
code?
>> Eelco Visser: Well so what we do here is we say that these -- it's a
[indiscernible] model so we note which variables are depending on which
variables and if they change, we recompute those things.
And there may be room for doing that more in batches.
So this is done locally,
15
but if you would go to the server, then you may want to do this on every key
stroke with [indiscernible] bits. So there may be different policies you want
to apply in different circumstances.
So now if you click the adds button, what we do is call an auto screen so add
task is defined as another screen and it's, again, it creates a new task object
and which you can edit and when you're done, there's a done button over here
which, actually, I say that is automatic, but if you want to add an object to
the database, you have to do that explicitly. Otherwise, you might not want to
save this particular object and all these [indiscernible] objects in the
database.
So only for creating new objects, you have to expressly say this should be
added.
And then you do a screen return, which is like a return, but then it also does
a UI return. So we go back to the previous screen and the nice thing here is
it's a stack model so you don't have to remember what auto screen this things
was culled from. Usually in web programming, you have this continuation
passing style where you explicitly need to know what context you are so that
you can return there. Here, we maintain a stack.
And the nice thing here, we can do this in this domain because it's all
stateful, and it's client side. In normal web programming, you have to go from
the client to the server and then back. Since here we can maintain a stack of
screens that you have visited and rewind that screen, that stack.
Okay. And, in fact, you can -- screens can return a value like normal
functions so you can have a button that's calls screen to ask for results and
returns that result as a result of the screen. So it does local data binding,
right, so the screen is a local variable that is bound in the text fields and
the value of the field is returned on the return stack, and so you can have
expressions that call for multiple new screens.
So one thing we learned from the WebDSL experience is in WebDSL, we made too
many things as primitives, and the philosophy of the design of Mobl is that it
should be growable and you should be able to define as much as possible in the
library of the language. Which means that in Mobl you can define things like
tabs and these sort of UI, which is as library definitions. A lot of nice
primitives in the language. So you can make them reusable controls.
16
So here we see a tab set so what is a tab? It has two thingies, it has a row
of labels that you can select tabs with, and then given a particular tab, you
want to show different contents. So we see here that the tab sets have a list
of controls, so pairs of labels and controls and a current tab. And then each
tab is just a normal control. So control is like a screen, but you can define
controls to build up more complex screens.
And you can pass these to the tab sets control. So the tab set control is
defined in Mobl itself so it takes a list of pairs of strings and controls and
an active tab so the currently active tab, which is a string. And then it has
two lists, one to create the tab index at the top. [indiscernible] over the
list of tabs, where we match each tab to a tab name and tab control, and we
create a block where we -- that is clickable so when you click it, we change
the value of the active tab variable to the name of the current tab that you
control, and we change the style from -- to active, and we display the name of
the label.
And then in the contents of the tab sets, we also iterate the tab.
the tab control for the active tab.
So we call
>>: Seems like declaring some new structure, right, as a code that you laid
out in a certain way, that as you show here, you call, basically, a code. So
what sort of -- I have a hard time understanding exactly the model of this type
of call here. Is that just think of it as streamlining the declarations for
the tab control in there, or what does that mean, exactly?
>> Eelco Visser: Yes, you see what is a control? It's a bit of UI, a bit of
rendering. So you've given some values of its parameters. It shows some text
and structure on the screen and it has data binding so it can handle events.
And, while that's a bit off code that you're abstracting from, that you make a
reusable abstraction of.
And basically, you're realigning that, but [indiscernible]. That's the idea.
So rather than having to define each page completely, you can make abstractions
over smaller bits of a page, of a screen, and you can make a library of those
things and compose complex library pages from screens from ->>: So you know in Mobl that this is a call to something that's just UI?
not -- it doesn't actually compute something? It's not --
It's
17
>> Eelco Visser: It's a control. The control is the abstraction here.
screens and the controls are the UI ->>:
So the
Typing takes care of knowing what this all means?
>> Eelco Visser: That's right, yes. So you hear me saying that
[indiscernible] set, we're expecting that there is a control, and controls are,
well, things like tab sets itself. It produces something of control. Those
things can be passed in these, yes.
And these things are complex things. That's what domain is about. So in
WebDSL, we have this motion of templates, which is similar. It is rendering
some data, reacting to events that are passed to the UI. And that is the thing
we are abstracting about, sort of one of the strengths of this language, that
we have this -- that the abstracts are a combination of rendering and behavior.
>>:
Could you [inaudible] twice, tab control, tab control?
>> Eelco Visser:
>>:
Yes.
And you just get two instances [inaudible].
>> Eelco Visser:
Yes, so you would see the contents twice.
>>: But would it be sharing the underlying data binding, or would it be
[inaudible] independent?
>> Eelco Visser: I suppose if the tab control has references to data, those
references would be shared. Let's say if you would say here, we could call
search box phrase twice, thine get two search boxes.
>>: But the tab control, the tabs that you're passing on the next page have
their own ->> Eelco Visser: But that's the same thing. So the point here is that if you
duplicate the search box, then you get two search boxes. And if you type in
one, the value of the other should be updated to the other.
>>:
[indiscernible] control, yeah, control -- one of those variables in the
18
control tab locally ->> Eelco Visser:
tab sets, then -somewhere. Here,
say this variable
page, as control,
be close.
Right. Local variables, those are local. If you have two
where was a local variable? We had a local variable
for instance. So this -- okay, so it's not a control. But
is local to this screen, and if you would call it twice on a
then each would have its own local variable and, yeah, would
Yeah, so I also detail other example of higher order controls, where you say,
well, we want to have this pattern where you have a list of items and when you
click on a particular item, your get the details of that. And in that pattern,
you can define as well. And again, the same sort of higher level, higher order
control where we pass -- we have a number of items in collection that we want
to display, and we have the master item control and the detail control for each
of those. So we call for each item.
So in the list we call the master item for each item and then you click on it
and you call the detail screen, I suppose, that should be detail rather than
detail screen. Oh, right, that's over here.
>>:
A question [indiscernible].
>> Eelco Visser:
>>:
Yeah, so this is for --
[indiscernible].
>> Eelco Visser: Here, you can have value one, but you can in general have
more. Well, so this is not really typed over the generic variable.
>>:
[inaudible].
>> Eelco Visser:
it.
>>:
You can write T instead of the question mark, and --
>> Eelco Visser:
>>:
Well, so we don't give it a name so we don't actually match
That's right.
And then use or maybe task or you know.
19
>> Eelco Visser: Yeah. And so then you can actually implement this master
detail thingy in this way, so if you have a small screen, it's a single list.
And if you click it, you go to the details. But if you have a device with more
screen real estate, you can have a list and the details on the side as you
click it and it changes to the -- and this can be done automatically, right.
So without changing the implementation, it will adapt to the particular
application or to the device that you're running this on.
So this actually has been used by a bunch of people outside our group, and so
people from companies are developing all sorts of interesting applications with
it, and even music player application and a wellness application. So they have
really adapted the style.
>>:
So they just messed with the CSS?
>> Eelco Visser: Right. So you can make -- so the nice thing is the widgets,
you can make your own library and implement and, yeah, and provide it a
completely different look and feel.
So at the bottom, Mobl doesn't provide any building widgets, so it's all the
library defines these higher order controls. And at the bottom, implements
these things in terms of data binding, abstraction and HTML fragments and
Javascript goes. And so it's really flexible, but it's also leak in the sense
that there you have the leak to -- you can do anything in Javascript, but we
don't have control over it either. So we cannot penalize it.
So I'm always a bit ambivalent about it. I like DSLs that are closed and you
control the whole language. The problem with that is that there's no escape,
and if you want to make new features, you have to add it to the language that
makes your extension process very slow. And ->>: That's always the big problem, right, the DSL? You find a DSL.
[indiscernible] may not have thought about the big, like the [indiscernible].
>> Eelco Visser: Yeah, so it's a trade-off between coverage and -- so in Mobl,
you have very good coverage. You can write any web application codes that you
can write in HTML and Javascript and embed it in an application, but you lose
portability in the sense that now if you decide, well, actually, rather than
generating web code, you would like to generate native IOS codes, then, well,
20
all those libraries are not portable.
We actually did have a student who did write a back end for Mobl to IOS, also
generating objective-C and what he did is take the library and did the library
interface and make implementations of all those over a certain number of
widgets in objective-C directly and then you can actually do generate native
cause.
If you decide to stick to a certain API, then you can still get portability,
yeah.
All right. So high level overview of Mobl. And so a couple of things to point
out. This idea of linguistic integration, so we integrate data modeling, which
you would normally do with RM or SQL. User interface, abstraction style, I
didn't show that, and application logic. And they're all different aspects
which have their own linguistic support, but they're integrated and the type
checker knows about them and compiler knows about them and can do interesting
stuff with them.
And there are more interesting things to do, like actually analyzing the
reactive programming model that you have.
It really makes writing these applications a lot easier. So there have been
many people from outside who have played with this and really like the
programming model.
So some points are data binding, where you write a field and it's automatically
tried to combine displaying the value and binding changes to the value. The
reactive programming model and these reusable higher order controls. We also
find that it is model view better and works very well. So getting rid of this
controller that you have to do the program yourself to -- how you have to react
to the two events.
And another strong point of Mobl is that it's IDE, which in -- well does all
this checking for you. And it's highlighting and it does check these variants
and has code completion and, well, all the things you would expect from a
[indiscernible].
And yeah. So and that brings me automatically to the second talk, if you still
have the energy for it. Well, so maybe there are some questions about the Mobl
21
part first.
>>: So the whole user interface part seemed -- I haven't seen a previous talk
where the user interfaces are designed using [indiscernible] syntactically and
semantically very similar to function calls, yet they are not actually
functions. Did you come up with that yourself, or was there prior ->> Eelco Visser: No, that sort of emerged in WebDSL, basically. So there we
had this idea of page definitions for web pages and navigates that are links to
pages. And in WebDSL, you can write these things and then so you build up a
page with the vendors and does data binding as well. And there is indeed the
analogy where the page definition is like a function call. To navigate a link
is like the function definition, and navigate is like a function call.
And if you declare these things explicitly in your language, rather than doing
URL or arithmetic, which you normally do in web programming, where you create a
URL by string compositions, much like pointer arithmetic in C, you can
actually, we have this [indiscernible] where you can navigate to a page. That
page is declared these arguments where you pass objects to this thing. You can
statically check that the link you are generating to a page that actually
exists and it has the right types of arguments and it automatically does
binding of -- knows how to pass an account object to another page. Lots of
stuff you can abstract from and have nice properties.
And then the screen is like a page and it's the full, the full page and control
in WebDSL is a template that says well if you divide it and make a play,
there's actually often patterns that you want to reuse, and we want to make
abstractions for those so that we can, in many places in your application, you
can use the same pattern. You can compose pages from smaller building blocks,
basically.
>>:
What's the difference between a page and a control?
>> Eelco Visser: Well, it's like in Mobl, it's a screen and a control. A
screen is always the full screen. And a control is a part, a part of a screen.
>>: But I guess you could think of a control, you could just go to a control
if you want to go to a control that has a screen.
>> Eelco Visser:
No, the idea is that you need to make a screen.
22
>>: Do you have first class functions too, or are they hidden in your
[indiscernible], or is there some way to make it land on [inaudible].
>> Eelco Visser:
>>:
It's in controls.
>> Eelco Visser:
>>:
So we have higher order controls, right, which are --
Oh, but do you have [indiscernible] controls?
Yeah.
>> Eelco Visser:
I haven't seen them, actually.
>>: If you don't need them, that's fine, right?
wondered.
>> Eelco Visser:
I don't care.
I just
It should be easy to do, but I have to admit I don't know.
>>: I'm more interested, because in Javascript, like it's first and foremost,
right? You have to have all these things all the time. You've now in a way
made it so you don't really need them, right? Which is easier.
>>:
I don't think it would be very easy either.
>> Eelco Visser: No, but you have closures. And so with WebDSL, we were
targeting Java, and there we don't have the higher order templates, for
instance, because mapping to Java is much harder. Mapping to Javascript, we
have much more power there and it's easier to do define higher order
abstractions than those with Java.
So if you have a few minutes, I'd like to talk about this.
ask.
>>:
But maybe I should
[indiscernible].
>> Eelco Visser:
No, I should be done by 12:00.
>> Sebastian Burckhardt: So anybody who wants to meet with Eelco, send me an
e-mail. He's here today and tomorrow morning.
23
>> Eelco Visser:
But feel free to.
>> Sebastian Burckhardt:
the talk is up.
I'm just saying that now so if people leave before
>> Eelco Visser: Okay. So yeah, so we've made this -- we have made Mobl with
Spoofax, which is a language workbench. In the past we would could this a
programming environment for creating programming environments.
So this is the other part of the challenge, automatically deriving language
implementations from declarative language definitions. And so if you're -- so
who is a compiler writer here? I know you are, right? Written -- well, you
have written compilers, I suppose. But you know this. So, I mean, traditional
compilers, you need the grammar for the syntax or at least the [indiscernible]
to text your strings to an ASD. You need to define the static semantics, to do
error checking and name resolution and type analysis. You may have some
model-to-model transformation, where you transform your ISD that you can put in
your code generator and a code generator that's [indiscernible] some final
codes.
So these days, languages are not accepted if they don't have a proper IDE to
support them, so IDEs give a lot of extra productivity over the language
abstractions that you have. See things like all sorts of editor services, like
syntax checking and bracket matching and syntax highlighting, code folding and
outline view.
And semantic editor services that show a long list of errors in your terminal.
You get in-line errors and you get reference resolving so if you click on an
identifier, you jump to the declaration. Code completion and refactoring and
so on.
So if you want to make a language, you want to make your traditional compiler
and also make an IDE. And what we want to do is make those things from a
single language definition. So rather than having [indiscernible] batched on
top of your compiler, we want to make them in one go.
So we do that in two parts. We have a language for grammars, called SDF for
syntax definition formalism, and a language called [indiscernible] for program
transformation that rebuilds languages within Spoofax.
24
So SDF is a fairly typical grammar formulaism, but what it does, it integrates
-- it's a character level grammar so it integrates lexical syntax in the
[indiscernible] rather than defining a separate lexical syntax with regular
expressions. We have a gel grammar that defines both the tokens and the
characters. We still mark things as lexical syntax and context-free syntax but
the production that we use are actually the same.
The difference is that symbols that occur in context-free syntax can be
separated by layout. So we can have wide space increments between these places
in context-free syntax and it's implicitly declared humorous, and in lexical
syntax, these things should be concatenated with the intermediate layouts.
What we also do here is declare constructers for the extra syntax, so given a
syntax, we get a mapping to an ASD.
And, well, so given the grammar you already get a lot. You get a syntax aware
editor and the nice thing about Spoofax is you can develop those things in the
same environment. So in eclipse, you develop a grammar, you develop your
language, you build it in the same eclipse instance you, get an editor for your
language with highlighting and so on.
Actually, the grammar I showed you was ambiguous, if you would type ->>: So when I give a grammar, I get this editor.
project?
>> Eelco Visser:
>>:
A project?
Like a language project?
>> Eelco Visser:
>>:
Do I also get like a
Yes, you do.
Okay.
>> Eelco Visser: So, yeah, well, you define these things in an eclipse
project. In that project, you create a grammar and you have transformations
and so on. What do you mean? Like a project for your language?
>>:
Yeah, like do you generate some, you know, where I can see my language
25
files and stuff.
>> Eelco Visser:
show in files ->>:
In eclipse that's jen rake so you can just make projects and
Digital studio, like [indiscernible] hidden fields.
>> Eelco Visser: Yeah, yeah, but you can add. So, for instance, Mobl has
buildable safe, which is built into the language so if you save a file in a
Mobl file, it will automatically compile that ->>:
You get like separate descriptions, like --
>> Eelco Visser:
>>:
Part of the language definition.
Okay.
>> Eelco Visser: Actually, SDF can deal with ambiguous grammar so you can
[indiscernible] grammar is an issue. You don't get an error, but you can each
get -- debug those ambiguities by inspecting the resulting tree. So here we
have X equal Y times Z, and we didn't specify priorities so what you get is a
tree that has bugs, protections. So rather than having to debug conflicts in a
parse table, you can inspect the ambiguities and resolve them at that level.
We have declarative disambiguation for things like priorities that you can now
use to resolve these ambiguities. And then if you have resolved them, you get
the proper results.
So a nice detail, while I'm here, is that this idea of showing -- so what's
happening here, I selected a part of my programming in my language, and I
clicked the show ISD item in my transform menu and I get the term that
represents ISD here and it was inspired by the Oslo project which has project
which had this -- you know Oslo, right? Yeah. It had this thing where you
typed the program and you got the ISD on the right side. I thought that was a
nice feature so I added it to the Spoofax.
All right. So something we added is error recovery for generalized parsing so
SDF is based on [indiscernible] generalized [indiscernible] parsing, which
allows you to pars any kind of arbitrary [indiscernible] grammars. In the
past, that wasn't supported by -- we didn't have error recovery for that.
26
Recently, we added that. So now you can write programs that have syntax errors
in them. So here we have a missing closing parenthesis and here this screen,
keyword is not finished. And because of this error recovery, we can actually
continue parsing and we get an ISD. And based on the ISD, we can provide
semantic services. So we still see error messages and we can do resolution
even in the face of syntactic errors.
And if anyone would be interested in this, I can have more to say about it.
So that's the syntactic part. And for the semantic parts, we do
transformations with the Stratego transformation language, which we use for all
sorts of semantic operations. So typical normalization. So syntactic
normalization, let's say we have a special case of the if statement without an
else statement. Yes?
>>: So this used to have another rewriting formula, ASL. Is Stratego like a
replacement for that, the next generation? Is that how to think of it?
>> Eelco Visser: If you want the history, I used to be a Ph.D. student in a
group of [indiscernible] in Amsterdam where we developed [indiscernible] for
SDF. I worked in SDF while I was there. Got this extension of SDF, and ASF
was a pure rewriting language so it only has rewrite rules. I became
frustrated with this, and so after my Ph.D., I went to Portland and developed
Stratego there.
Stratego has rewrite rules, but it also has programmable rewriting strategies,
so you can define your own -- rather than just having, say, give an
[indiscernible] strategy that takes all the rules in your whole program and
applies all of them exhaustively, you can say, well, now I want to apply -- I
want to take these rules and apply [indiscernible] reduction to this tree.
>>:
Okay.
So you can control the --
>> Eelco Visser:
>>:
Yes.
Okay, thanks.
>> Eelco Visser: So it's a rewriting language and it has strategies to control
those. So we do, well, typical desugaring and syntactic normalization, CPS
transform, type analysis. Given an AST, rewrite it to an -- an AST that
27
represents a type. So we have a string, the type of that is simple type with
the qualified ID Mobl string. We can do type checking, so given type analysis,
we can say, well, a simple type should, if you use a type somewhere, it also
has a type of a property and a declaration, for instance, or a type of an
argument so it should be declared. So if we fail to look up that type, then we
want to give an error message on that type expression that says that the type
is not defined.
Or if we have a property expressed of expression dot fields, and of the
expression has a certain type, but the whole thing doesn't have a type, that
means, well, that type doesn't have that property, and we want to give an error
message. And we can see here that we -- and these constraint errors are
interpreted by the IDE, and displayed by us in line errors. So here we get an
error message. If we hover it, it says type is not defined.
And then the next thing is in our language definition, we don't have to deal
with the binding of these error messages to the IDE. We automatically get file
origin tracking. We say the error message should be placed on this AST, and
the editor of the environment knows where to place the -- put the squiggly
lines in the IDE.
And then we can bind these analyses to semantic error editor services. So, for
instance, the editor analysis says, well, analyze my program and we turn a list
of errors and warnings and notes. And then true origin tracking displays those
in the editor. We can do completion. And so given a typing, the term that
we're typing, propose -- so, for instance, here if we -- so this is the Mobl
editor. If I say, you know, so propose some value or propose a type, then it
will look into the current program and propose valid types.
And it does reference resolving. So if I control click on an item, it will
jump to the declaration and that sort of stuff.
And if we make errors, then it will still continue in -- well, it will give
error messages based on that and it will still do that in the face of syntactic
errors as well.
So I can, if I approve this, I will still be able to do reference resolution
even if we have syntactic errors.
And so the nice thing here is that we have a very thin interface between the
28
semantic analysis and the IDE framework. You just write your analyses in
transformation Stratego and then using an interface like this, you can bind
that to the IDE. So the interface for this editor analysis is that we can AST
and a bat and after we [indiscernible] with these things, then it knows how to
deal with those and is not concerned with the actual analysis.
And we have some languages for declaring these services so you can declare
binds, a combination of syntax definition and transformations to an IDE using
so-called billers and that's on the interface between the IDE implementation
and your language definition.
And so as a regular language developer, you have very little concerns about
details of eclipse implementations.
Recently, we added a testing language. You can actually express tests for the
language you built. Typically, you test these things by making programs and
clicking around them, seeing if everything works. Now you can make these tests
in a unit testing style where you quote a small piece of program and define
what it should, should it test syntax but also reference resolution and type
checking and so on.
And the nice thing is, you can do this in an editor and get syntax highlighting
for the language that you're developing in the testing language as well.
All right. That's it. So couple of ideas. Linguistic abstraction and this
idea of linguistic integration is important, and we have a nice workbench for
creating DSLs. Okay. Thanks.
Download