 Felly yn gweld fawr i arhaeth yma. Mae'r rhai ddweud, ac mae'n gweithio'n gweithio'n gweithio'n gweithio. Mae'n ceisio ar gyfer Yrddras, ddweud i'ch gweithio'n gweithio'r ymlaen â yma, ond maen nhw'n ddesgrifennu ar gyfer ymlaen. Mae'n gwneud yn gweithio'n gweithio'n gweithio. Yrddras yn ei ddeiligol yn adegwyddau gyda gweithio'n gweithio'n gweithio. Ond yno'n gweithio'n gweithio yma, engineering problem is a new language, there are some things where inventing a new language lets you impose constraints that are useful for making sure the program doesn't do certain kinds of bad things . It's just fun and it helps you understand what your computer is actually doing, if you know how to do this. So if at any point you can't read the slides, they're vents slightly Cameron chicken. On all the code and I'm going to show you is online and ac mae'n gynllun i gyd yn fwy o'r gwaith. Dwi'n ffawr i'w gweithio, mae'n James. Mae'n gweithio i'r cwlau'r gwybod. Mae'n gweithio i'r gwasanaeth ar y internet. Mae'n gweithio i'r gyflym gyffredinol yn rhywbeth. Mae'n gweithio i'r gweithio i'r gwaith o'r llunio'r llunio'r llunio'r llunio'r llunio'r llunio. Mae'n gweithio i'r gweithio i'r gwaith, ac mae'n gweithio i'r llunio'r llunio. Roedd. Felly we'n gyfer Rhysau 5a, oedd gwybod gydaar pan dd nouveau. Felly mae hynny'n gweithio i gyrdd. Mae'n gweithio i'r gwaith o'r llunio sydd yn ddigonwys sy'n ddigonwys ar gyfer Rhysau, mae'n ddigonwys. Felly, mae'n gweithio i'r gwaith a'r llunio'r llunio, hynny yn gyfarfedd Cuyssaeth Rhaid, yw bod gweithio i'r gwaith, ac yda'r gwaith. Fyd yn cyfle cyfyddiant, ac ymdw i'r cyfle cyfyddiant a ddwyf am amdangos. Dyna s. 6 gyda leir y ffa ar yr ardal. Fyd yn cyfle cyfyddiant. Dyn ni'r cyffredig iawn, fel y byddech chi, mae'r cyffredig iawn dda'i, dwi'n credu hanfyg. Fyd yn cyfodd gwybod yn wych. Mae eln, o hyd dudf. Dyna ni'n gweithio. Ond dyna'n gweithio ynwedig hefyd, yn gallu ei gwynyddol i eisiau ei ffordd sydd wedi'i'r dysgu yn cael bod ni'n mynd i ddod fan ei ddrifwg nghymru sy'n gyfer edrych. Felly fan y gallwch gwrs Mother. Mae'n gweithio y byddai'n ei ddweud a'i profierydd pan fyddi'n gwybod. Mae'n gweithio mewn gweithio. Mae'r tynnu defnydd a'n cyfan. Mae'n bywyd i'n ddysgu'r ben directly'i future I apologise, roedda weithio oedd yna yn 1975 wedi undod o'r cyfan gwaith Cystol, gyda Maryl Sussman. Mae'n iddyn nhw llesbon bwysig fan hyn o'r Lisp. Mae'r rhannu a'r rhannu yn ei wneud yw'r cyd-draethau erbyn yn ysgolio'r ffordd. Mae'r rhannu yn ysgolio, mae'r rhannu yn ysgolio, mae'r dynamism, mae'r dataïpes. Mae'r rhannu yn ysgolio'r rhannu yn ysgolio'r rhannu. Mae gennych, mae'r rhannu. Mae'n ffordd. Mae'n ffordd, mae'n rhan o'r rhannu, ond mae'n ffordd gan gweithio. Mae'n gwybod ar yrhym yn gwneud, mae'n i gwybod yn cael y logiwn. felly mae'n gweithio ddau a gweithio, felly mae'n myselfwg llais yn cael y cyflwyno'i dyfu. Ond mae'n ei gweithio arwag eich ffordd o berdwyd, o fewn ni'n gweithio'r cyflwyno'r yw ddweud o gweithio amgylcheddon gweithio'r siadwyr, mae'n gweithio'r gweithio arwot a zeithno'i gweithio'r gweithio'r prif-ylwydd a phryfodd yn cyflwyno'i cyflwyno yw'r masylo'r sgolf選f oes iaith ymweld yn ysgrifftwyr. y same scoping and closure model that you have in JavaScript. So this is all going to be very familiar, slightly different syntax, but it's semantics that you're all used to. So here's what the language looks like. True looks like this, hash T. False is hash F. So it has booleans. The only other basic data type that we're going to have for now is integers. And they look like you expect. Zero looks like this. 13 like this. And 16,777,216 looks like that. All fairly standard stuff. This is a symbol. Symbols are usually used for making variables. You're allowed to use more characters in variable names in scheme than you are in JavaScript because its syntax is so minimal. So this does not mean four minus each. This is a single symbol, four dash each. You can have dashes in variable names. You can have exclamation marks in variable names. In scheme, this is typically done to indicate that a function mutates something. Like it changes the value of a variable. It changes something in a list, that sort of thing. You can have question marks in variable names, which is usually reserved for functions that return booleans. Things that ask questions. And the things that you're used to thinking of as operators because this language has almost no syntax, there aren't any operators. There are just function names. So plus is a function name. Minus is a function name. Asterisk is a function name. Slash is a function name. And equals is a function name, which implements a definition of checking if two things are equal. This is what the language looks like. This is what expressions in the language look like. If you want to add two numbers together, you call the plus function. And calling a function means making a list. Making the function you want to call be the first thing in the list. And then the arguments are the rest of the things in the list. So this is saying call the plus function with three and four as arguments and you get seven back. And you can compose these expressions into more complex forms. So this is saying this inner expression means divide eight by two, which we expect to be four. And then the outer expression says is that equal to four. So that whole expression will evaluate to true because eight over two is four. If you change the final thing to three, you get false. This is what functions look like. This is a function called square. Lambda is the scheme word for what we would call function. A lambda takes some arguments and then it has a list of expressions. So this function takes a parameter called x and then it defines a local variable called z, which is x times x, and then it returns z. There's no explicit return statement. The value of a function is whatever the value of the last expression is. And then once you've defined a function, you call it in the normal way by making a list. That is the first thing. So we expect square of five to be 25. And we have conditional logic. So the factorial function. Stand definition of factorial function. Factorial of zero is one. Factorial of anything else is that number times the factorial of that number minus one. So this is embodied here. Factorial takes parameter called x. If x is equal to zero, so the if form takes three things, it takes a condition. So it evaluates this. If it's true, we use that value. And if it's false, we use this second expression. So if x is zero, we do one. Otherwise, we multiply the factorial of x minus one by x. So we expect fact of six to be 720. And we're going to have closures. So this is a function that takes a parameter x and returns another function that takes a parameter y. And when you invoke that, you get x plus y. So we expect to be able to call add five, and that's going to return a function. And then we can call that function, that's the outer list, with another argument six. And we expect to get back the result of adding those two numbers together. This works pretty much like it does in JavaScript. So how are we going to do this? This is going to be a very, very basic interpreter. And the first thing that interpreter has to do is has to parse the program. Fortunately, there's a very small language with almost no syntax, and you can fit its grammar on a slide. This is called a parsing expression grammar. It's a formalism for defining the grammar of a language that you can then generate parser code from. So to do this, I'm using a tool called Canopy that I wrote a couple of years ago, and it takes files that look like this and it converts them into JavaScript that knows how to parse the language. So the definition of this language is that a list is a parenthesis followed by zero or more what I'm going to call cells followed by a closing parenthesis. A cell is any amount of space followed by a datum followed by any amount of space. That takes account of the space between things in the lists. A datum is any piece of data. So it can be another list because you can embed lists within lists, or it can be a boolean or an int or a symbol. A boolean is hash t or hash f, and int is either zero or the digit one to nine followed by any number of digits zero to nine. A symbol uses this slightly funky syntax. This is a negative look ahead, and that means any character. So what this whole thing says is, a symbol is one or more, the plus means one or more, of any character that is not a delimiter, and a delimiter is just a parenthesis or a space. So a symbol is you can have any characters in there unless you have a parent or a space. At that point, the symbol ends. So that's the definition of the whole language. If you feed this into a parser generator, you get code that will parse programme texts and spit out a tree, a tree structure. Like when you use a jason.parse, you give it a string and it gives you a tree structure. So how does the evaluation model work? If you see an expression like times 10x, the parser is going to go, okay, that looks like a list. We've got a parenthesis, and then we've got some stuff, and then we've got another parenthesis. And then inside of that list, we've got some cells, right? Asterisk space, 10 space, x space. That's splitting up the text inside the list into these cells. And then inside each of those cells, once you've stripped off the white space, you have actual meaningful data. So asterisk is a symbol, 10 is an integer, and x is a symbol. So you get down to the leaves of the tree and you get these bits of data that you can work with. So you take these things at the leaves and you evaluate them one by one. So to evaluate a symbol, a symbol is a variable name, right? So evaluating a symbol means looking up the value of that variable in the current scope. So say we look up asterisk and we get a procedure, we get the multiplication procedure. We evaluate 10, 10 evaluates to itself. It's always 10. It doesn't depend on context or scope or anything like that. We evaluate x. Let's say that x has the value five right now somehow. So that evaluates to five. So you evaluated all these little bits of the expression and you now have a function and some values and you can call the function with the values and you get a result out. There are some special kinds of functions that don't work quite like this. There are some special things called syntaxes. Those are things that don't evaluate all of their arguments up front. So if you take an expression like this, define, the job of define is to assign a value to the variable name x. So we don't want to evaluate what x is. We want to take a value and we want to assign it. So again, we do our usual parsing routine. We get the symbol define, the symbol x and the list plus two three. And we go through and we evaluate each of those things. So define is a symbol, it's a variable name and it refers to a syntax called define. A syntax is a special kind of procedure. We look up x, but we don't evaluate x. We just want the name x because we want to assign a value to it. We don't care what it values right now. So we leave that as it is. But we do evaluate the second thing. We evaluate plus two three and we get five. And then we do the same thing. We apply the define procedure to these things and the effect of that, it doesn't return a value but it has a side effect. It assigns the value five to the symbol x in the current scope. So there are these things. If works like this, if doesn't evaluate all of its arguments, it evaluates the first one and then it chooses one of the other ones to evaluate. Lambda is the same. So there are these forms that don't evaluate all their arguments up front and that's going to be quite important. Okay, so that is all about how the language works. So now, if there is time, let's build it. So I've a skeleton of a project here. This is just what I started out with. So let me see. So I've an executable called Lisp and then I have a directory with just some few stub files in it. So listparser.peg is that grammar file that I showed you earlier and that gets converted by Canopy into the file listparser.js. The main module for this language is Lisp and that's going to use some other bits. So there's a parser module that adds evaluation methods to the various nodes in the parse tree. There's some classes for modelling variable scope and there's going to be some classes for modelling procedures and syntaxes. So the executable, it looks like this, starts out when we run a program. It's not actually the first thing. There we go. All right, this is the executable. So very small file. It takes a past name as an argument and then runs that past name using the list module and then prints whatever the result was. So if we start this going. So this is the list module. To run a file, you take a past name, you read it, you parse the contents into a tree, you create a new top level scope to run the program and then you evaluate the tree in that scope. This is the start of the grammar file that just has some basic rules. We're going to add more rules to that as we go along. This is the parser file which contains node definitions. So these are all the different types of nodes in the parse tree and we're going to be adding behaviour to those as we go along. Scope has a couple of empty classes in it for modelling scope, the things we put variables into. There's a special one called top level, which is the scope that the program starts running in. And we've got a couple of stub files for modelling procedures and syntaxes. So syntax inherits from procedure. It's a special kind of procedure. There's no code in these classes yet, they're just stubs. So let's start writing a program. We write hash t and we want that to print true. But it doesn't, we get a parse error expected parenthesis. So we have to go and add a rule for parsing boolean values. So we know that a program is just any number of cells. A program is a list of expressions. We know that a cell is any amount of white space followed by a piece of data followed by some more white space. And a datum, all we're dealing with now is boolean. So a datum can just be a boolean. And we know that a boolean is either hash t or hash f. So just by adding these rules to the parser, it now knows how to parse boolean values. Now we also need to add rules for how to evaluate these things, right? So our interpreter actually does something useful with the parse tree. So to evaluate a program, we take a scope and we evaluate each of the program's expressions in that scope and then return the value of the last one. So that's what we're doing here. We're saying this dot elements, those are like the sub expressions in the program. We map over those, evaluate each one in the top level scope and then we pop off the last one to get the value of the last expression. So those expressions are going to be cells. So we need to evaluate those. This is a recursive procedure. So to evaluate a cell, we just evaluate the data inside the cell. So we ignore the white space on either side, we just evaluate the thing in the middle. And that thing in the middle is, so far, is just going to be a boolean. And booleans, notice, we don't take a scope there. Booleans have a fixed evaluation value. They're either true or false. You don't need to look at everything up. So it returns true if the text value is hash T and indeed when we run this, it prints true. If we change that to F, we expect to get false by this rule and indeed we do. So we know what to do with numbers, right? So write a number, it blows up. Again, expected a boolean, got a number. I don't know how to parse this. So we need to add some more parser rules. So we go in, we say that as well as a boolean, a piece of data could be an integer and we write a rule for what an integer looks like. So an integer can either be the string zero or it can be the digit one to nine followed by any number of digits zero to nine. And that's an integer. And then we also have to write an evaluation rule for that. So we go in and we onto our integer module, we're going to add an eval message. And just like boolean, integers don't care what the current scope is. They always evaluate to the same thing. And in this case, we can use JavaScript's parsing function to convert that chunk of program text into a real number. If we run that, we get three, great. If we type in another number over here, we expect to see that number pop up over there. Indeed it does. Okay, variables. So, again, we get a parser because we don't know how to parse symbols yet. We expected a number. So we go back into our parser, we go, okay, as well as boolean or an integer, we could also get a symbol. And a symbol is one or more characters that is not a delimiter. And we need to say what a delimiter is. So a delimiter is either a parenthesis or a space. And this is where it starts to get interesting. So to evaluate a symbol, you need to look up a variable in the current scope. So the eval method on symbols is going to be a function that takes a scope. And we're going to defer the logic of what this means to the scope class. So we're going to say scope.lookup, this.textValue. So that's taking a scope object and asking it what the value of that variable is right now. So scope has no method lookup. Right, we've got to go and implement that. So now we start getting into the classes that make up our runtime. So we're going to start adding code to our scope class. So a scope is a thing that stores variables. So it's going to need some way to put those variables, something that maps names to values. So we can use a JavaScript object for that. That's what the symbols thing is. And looking up a variable, it just means returning a value from here by looking up by name. So you want to say, if the symbol does have that property, then return it. Otherwise, we want to have a useful error. We don't want to just emit undefined. We want to say, you reference a variable that doesn't exist. So if the symbol doesn't have that variable, which means the variable is not defined, then we're going to throw an error, unknown variable with the name, so then you get more useful error messages. Now if we run the program, we still get an error because unknown variable X, right? X is not defined. We can go into our top level scope. This is the special scope that the program runs with at the beginning. Or we can just poke symbols into there and those should show up, right? Because now we've hooked everything together, we can poke variables into there. Okay, now we need some built-in functions, right? Plus is another variable name, but it should refer to a function that comes with the runtime. The user doesn't need to define. So into our top level scope, we're going to start defining these things, these built-in functions. So when I say define plus is a function that takes NB and returns A plus B. We'll get to what define means in a minute, but this is just a very high level system where we go, okay, we need some built-in functions, we're going to make all the arithmetic things. So minus, multiplication, division, and equality. So we need to say what define means. So what define should do is it should assign to whatever variable name is given. So these all end up being variable names. A procedure that contains this code so that if you invoke that function, the call is delegated to here. So that's what define is going to do. It's going to set a name and set is assigns values to variables. A new procedure that has no parameters at the moment, we'll get to that in a minute, and the body, which is this function. So we're just wrapping a JavaScript function up in our own procedure class. And now when we look up plus, we see that it's an object because we've hooked up all that code. And just to check that it's the right object, it should be one of these proc things. So if we take the values that we're parsing to the proc constructor and assign them as instance variables, then we should see those variables pop up. And indeed, so plus, we know that plus now refers to a procedure and we want to invoke it now, right? This is the final thing we need to add to the parser because that's going to blow up. It doesn't know how to parse a list. It expected a number, it got something else. So we need to add a rule for parsing lists. You go into our parser file and we say that a data can be a list as well as all the other things that it can be. And from before, we know that a list is an open parenthesis followed by any number of cells which I've given the label items followed by a closing parenthesis. And now we go into our set of evaluation methods and we need to write an evaluation function for lists. And from before, we know that to evaluate a list, what we do is we evaluate the first item in the list and that should give us a procedure. That's what we're doing here. So this is going over all the elements of the list and pulling out the data inside each cell so we're ignoring all the white space. So that's just getting us the meaningful little bits that are inside the list values. So to get a procedure, we evaluate the first one of those values in the list. And to get the arguments, we evaluate the rest of the values in the list. So slice one gets us everything by the first item. So map over those, we evaluate each one. And then we apply the procedure that we got to the values that we got. So this should take the plus function and apply it to the arguments three and four. But when we run that, we see object has no method apply. We haven't written an apply method for our procedure class. So we need to go and do that. So at the moment, the procedure class just takes a JavaScript function as the body. So to apply a procedure, all that we need to do is call that JavaScript function with whatever values that we were given. So you can do that using JavaScript supply method and need to correct my typo. That's fine. And now if we run the program, it does actually work. Everything is getting hooked up. Those JavaScript functions are being called behind the scenes. And because we defined all our arithmetic functions before, we can use all of them. So these are all the expressions that I showed you before. This should evaluate to true. Eight over two is four. But eight over two is not three, so we should get false from evaluating this. How do we do? OK. So now we want to get into defining variables, right? So far, the user is not able to define variables, and that's not very useful. So if we run this, we get an invariable define because we haven't said what define means. So define is one of these syntaxes, right? It's something that doesn't pre-evaluate all of its arguments. It takes bits of the program and then does something to them. In this case, it evaluates the second argument and assigns that value to the name of the first argument. So we're going to make a syntax called define that takes the current scope and the cells from the list. And what define is going to do is it's going to take the name, which is the text value of the first thing, and it's going to take a value, which it gets by evaluating the second thing, and then it's going to assign that name with that value in the current scope. So we need to say what this syntax thing means. Syntax is just like define. Only instead of creating a proc, it's going to create a syntax, and a syntax is a special type of proc, as you saw earlier. So that's exactly the same code. It's just making a syntax instead of a procedure. So now we need to go into our syntax class, and it needs its own specialized apply method because syntaxes don't work in quite the same way that normal procedures do. So it's going to take the current scope and the cells from the list, and it's just going to call its internal JavaScript function. With those values. Pretty straightforward. But now we have a problem because we have two different kinds of procedure, and their apply methods take different things. One of them expects its arguments to be pre-evaluated, and the other one doesn't. So instead, what we're going to do is whenever we call a procedure, we don't pre-evaluate its arguments, so we're going to let the procedure itself decide what it wants to evaluate. So we go back into our list evaluation method, chop out the thing that evaluates all the values beforehand, and instead we're just going to pass everything in the current scope and all those bits of the program into the function. And then procedure can decide, I'm a normal procedure, I want everything to be evaluated, so I'm going to do that. But it lets syntax work on bits of the program before they've been evaluated. So now if we run this, indeed, we get 12. And we can take those variable names and put them in expressions because all of the evaluation function should all be working together harmoniously. So 12 minus 9 is 3. And now we want to be able to define functions. We're getting into some seriously useful stuff now. So we have a new thing called lambda. Lambda makes functions. Lambda takes a list of parameters and then a list of expressions. So we expect this to evaluate to 25. But it's going to blow up because we don't know what lambda is. So lambda is another syntax. It doesn't pre-evaluate its arguments. It stores the names of the parameters and the values in the body, and it lets them be evaluated later with different arguments. So we're going to make a syntax called lambda, which, like other syntaxes, takes the current scope and the set of cells from the list. It needs the parameter names for the function, and it's going to get those by looking at the first argument that it's given. That's this thing over here and getting the text values of the symbols inside there. So it has the parameter names. And then we're going to return a new procedure with those parameter names and the rest of the cells. So that will be this defined thing and this z expression. So now, instead of using a JavaScript function to make a procedure, we're using bits of the program, like bits of scheme code. And this is now going to blow up because we've tried to call apply on bits of the program. We're expecting a JavaScript function that we can call apply on, but we don't have one. So we need to make a distinction. There are functions that are built into the language that define a JavaScript and there are functions that are defined by the user that are in a scheme. So what we need to do is say if the body of a function is a JavaScript function, then we can just call it. Otherwise, we need to do the scheme function evaluation procedure, which is much like evaluating a program. We go over each expression in the body, we map over those, evaluate each one in inner, which is a new scope. Every function has a new scope that it evaluates in and pop the last value off the end to get the return value. Now inner is a new scope. When you call a function, you get a new scope so you can have local variables. So we're going to say inner equals scope.fork. We'll get to what fork means in a minute. And then we need to bind the arguments of the function to the parameter names of the function. And in this new scope that we've created, we assign the name the value of one of the arguments. And then we can run everything in the function. And it blows up because we haven't defined what scope fork means. This is going to be a little bit more complicated later. This is why I've put it in a method on scope. But essentially, scope.fork just creates a new scope. It creates a blank canvas so the function can put variables in there and they don't pollute the global environment. So we try running our program again. And then we have unknown variable define. So we've created a new scope, a new blank canvas. Define is at the top level. It isn't in here. So we need some way of a scope if it doesn't know something delegating to a parent scope. So to do that, we give each scope a parent. And when you make a new scope I've gone the wrong way. Having a parent scope means that what you can do is if you don't know the current value of a variable you can ask your parent. This is how scope works in JavaScript. If a function doesn't have a local variable it looks in the enclosing function. If that doesn't look in the enclosing function until you reach the top level scope. Once you've done that, everything just works. We've got a scoping mechanism so we can use things to find out the top level inside of functions. But we can also make variables inside of functions that don't pollute the global scope by leaking. We want to do conditional evaluation. So a factorial function from earlier makes a decision. It says if x is 0 then return 1, otherwise return factorial of x-1 times x. And this is going to blow up because we haven't defined what if means. Undefined variable if. So if is another syntax. It evaluates the first expression and then if that's true it evaluates the second expression or if it's false it evaluates the third expression. So we're going to write a syntax that does that. So if is a syntax, like all syntaxes takes the current scope and the cells and then it's going to evaluate the first expression and then use that to pick the index of which of the other cells it's going to do. So that's picking which of the expression to evaluate based on the result of the first one. It's pretty straightforward. If we run that we get 720 as we expected. We plug some other numbers into there. We should see that it behaves as we would expect. So final piece of the puzzle, closures. So just like in JavaScript we can make a function that takes parameter x and returns another function that takes parameter y that actually does the computation. So we expect add5 to return a procedure. And indeed it does. It's a procedure. It has the body plus xy. That's what we expected. But if we try and call it, it's going to blow up. It blows up. Unown variable x. So why is that? Because of the way that we've implemented scoping this x reference here doesn't get resolved to this one here. X gets resolved to the scope where the function was called from not where the function was defined. So what we need to do is we need to make each function remember the scope that it was defined in so that when it's called it can refer to variables from that scope. So everywhere we create a procedure we pass in the current scope as an argument. That's what we're doing up there. When we make a lambda we pass in the current scope. So now our procedure constructor is going to take an additional argument which we're going to poke into here. It's going to store that. So this is a reference to the scope where the function was defined. And that's going to mean that when we create a new scope to call that function in the definition scope not from its calling scope. What we had before was called dynamic scoping. This is now lexical scoping. And if we do that then it works as expected. We ran the expression and we got 11. We can assign the functions we get from here to variables. We can refer to them like that. Everything just works. So we're done. We've made a new language. It didn't take very long. JavaScript was done in 10 days. We did this in 20 minutes. It does basically the same stuff. I say we're done. We're not really done. I'm done. You're not done. This language has all sorts of stuff missing. It works. It's churn complete. It's not practical. It doesn't have floats. It doesn't have strings. It doesn't have all sorts of useful features. So in particular it doesn't have a lot of stuff that's even in the scheme standard. I don't have to add any more stuff. It doesn't have to be a subset. Stuff you would probably want to add to this. You probably want to add syntax checking. For example, lambda doesn't check that the first thing you give to it is actually a list of symbols. That could be anything. You could get parameter names that were lists or numbers. We haven't checked anything. We haven't checked that if you define a function with a certain number of arguments and then call it with a different number of arguments that you get an arrow. But JavaScript doesn't do that anyways. There's nothing that checks your program makes sense before you run it. There's no type inference. There's nothing that you get in these nice functional languages that give you high-level abstractions like that. There's no macros. Macros are a really useful thing in list. They're functions that take bits of the program, the source tree, and rewrite them into other forms. That lets you take a language of very minimal syntax and build new stuff out of it really easily because the program is made out of the same data structures that you use when you're writing programs. Scheme has tail call optimisation. We haven't built that. It's quite a fun exercise to do if you want to try that yourself. It doesn't have continuations. I tried explaining continuations to someone at the bar last night and sort of failed. Google it. It's a bit weird. There's all stuff that's in the scheme standard that you could probably have a go at making yourself. So now you know how to get started. You can start making languages. You can try out your own ideas. You can try making all this stuff. You can see what works and what doesn't. You can understand the languages you use better by trying to replicate what they do. So material for the slides are online there. The code is on github at this address. Canopy, the positive generator that I used is there. There's a bigger language that I made with some more full-featured version of Scheme called Fargo, which, instead of having continuations, has fibers which I stole out of Ruby. That's that address. You can play around with it, look at its code. I think I've pretty much run out of time. So thank you very much. I'm sorry. I just missed something. I will get the slides. The point, the connection between the parser, I hear myself, the connection with the parser and the definition of the syntax. You had a list of definition of syntax. What is a symbol? What is a datum? What is a cell? I couldn't see where the connection was to get this definition to a JavaScript regX or something like that. I skipped over that, but I will go over to my code. So I was running make. You can't see it on the screen. That's fine. It's a make file. It's running a program called Canopy. At the start, I showed you there was ListParser.peg and ListParser.js. It's a program that you run it against the peg file and it generates the JavaScript file. Every time I ran make, it was running back to regenerate the parser. That was happening a bit implicitly. Next question. Over here on my left, you're right. There's a microphone coming over here. It's a little bit silly question, but why haven't you used prototypes to implement the scope inheritance? That's a good question, actually, because that is exactly how prototypes work. It's how delegation works. It's like, I don't have this property. I'm going to ask my prototype for it. You could do that. It's more the fact that I wanted the scope class to actually have some of its own methods that weren't just things... There's a separation between variables in the program environment and methods that are part of the runtime, things like look up and defining things. Those are all methods on the scope class and they're separated from variable bindings in the user's program. You could do it just with better prototypes, but you just have to put all the methods that were hanging off it somewhere else. Thank you. Next question. One over here at the front. Two microphones to send the issues which run you on. Thanks. You obviously like least-plike languages. What would be your opinion of a language that gives you least-plike capabilities in the sense of macros, but Ruby likes syntax in practice? With a uniform AST, of course, otherwise. That's the thing. The AST has to be part of the public API. You see this... There's a macro system for JavaScript. I know, I know. The thing is about defining macros, if your language doesn't look least-plike, is that the macros are a bit harder to understand, because there's this kind of indirection. Macros don't talk about things that are directly visible in the program. They talk about things that are hidden in the parser. You can't look at your program and go, oh, I see how that transforms into that. Those bits of your program. That bit is called an if statement. That bit is called a variable assignment. There's a bit of extra indirect knowledge to use a macro system like that. But people have picked them up. There's quite a lot of interesting stuff happening with them. Have I got the name right? Is it called SweetJS? Yes, it's SweetJS. Personally, this is more stuff that I find interesting, but I don't necessarily want to write big programs out of it. I actually prefer writing big programs out of Ruby than in JavaScript, because I find Ruby more expressive and it's easier to tell what someone meant when they were doing something. JavaScript has the function keyword is overloaded with about four or five different meanings. When someone uses it, it's hard to know, do you mean a class or a function or a method or a procedure? What's your intention? So, there's a sort of gulf there between things that I like playing with and things that I find easy to understand and actually write software with. I sort of keep them a bit compartmentalised in my head, but you should ask some people who actually use LIP for a living. Is there a situation where you imagine building your own language on top of this and actually using it in production? Have you done that in the past? Is there a time where you see yourself doing that? I have used this and I actually do really evil things. There was a really, really stupid things. I originally did this in Ruby and because of some gotchas in our Cucumber tests where I was working, I did some stuff to rewrite Cucumber AST. For example, if you would have a scenario outline but no examples, it would turn that into a syntax error somehow and just doing that by taking the gherkin AST, turning it into LISP data, then using the LISP macro system and then rewriting it back. It was really, really horrible. That never went into production, but as in I just have fun sometimes just going like, what could I do with this? There's all sorts of stuff you can build. If you want to make a language, it doesn't have to be a LISP but LISP is just a convenient way for you to see what the parse tree looks like. If you have something like that, it makes it easy to understand the internals but then you can build a whole thing on top of it. Thanks. One last question? No hands going up. Okay, that's great. Thank you very much, James.