macros & sweet · 2017. 11. 13. · •text substitution macros –text is converted to text....
TRANSCRIPT
![Page 1: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/1.jpg)
CS 252:Advanced Programming Language Principles
Prof. Tom AustinSan José State University
Macros & Sweet.js
![Page 2: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/2.jpg)
Let's say we want to add classes to JavaScript…
![Page 3: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/3.jpg)
We'd like to have something like:
class Person {constructor(name) {
this.name = name;}
say(msg) {console.log(this.name +
" says: " + msg);}
}
![Page 4: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/4.jpg)
But what we have to type is:
function Person(name) {
this.name = name;}
Person.prototype.say = function(msg) {
console.log(this.name +
" says: " + msg);}
![Page 5: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/5.jpg)
We want to expand our code with classes to a version of JavaScript understood by the interpreter.
Introducing macros…
![Page 6: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/6.jpg)
What is a macro?
• Short for macroinstruction.• Rule specifies how input sequence
maps to a replacement sequence.
![Page 7: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/7.jpg)
A Review of Compilers
Lexer/ Tokenizer
Parsersource code
tokens
AbstractSyntax Tree
(AST)
Compiler
Machine code
Interpreter
Commands
![Page 8: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/8.jpg)
Macros in C
• C preprocessor• Text substitution macros–text is converted to text.
• Embedded languages are similar– PHP, Ruby's erb, etc.
![Page 9: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/9.jpg)
Lexer/Tokenizer Parsersource
codetokens
AbstractSyntax Tree
(AST)
Compiler
Machine code
Interpreter
Commands
Pre-processor
expandedcode
Some variants work at the token level, but the
concept is the same.
![Page 10: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/10.jpg)
C preprocessor example#define PI 3.14159
#define SWAP(a,b) {int tmp=a;a=b;b=tmp;}
int main(void) {
int x=4, y=5, diam=7, circum=diam*PI;
SWAP(x,y);
}
![Page 11: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/11.jpg)
int main(void) {
int x=4, y=5, diam=7, circum=diam*PI;
SWAP(x,y);
}
int main(void) {
int x=4, y=5, diam=7,
circum=diam*3.14159;
{int tmp=x;x=y;y=tmp;};
}
![Page 12: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/12.jpg)
Problems with C macros(in class)
![Page 13: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/13.jpg)
Many macro systems suffer frominadvertent variable capture.
Let's look at an example…
![Page 14: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/14.jpg)
Hygiene
Hygienic macros are macros whose expansion is guaranteed not to cause the accidental capture of identifiers.
![Page 15: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/15.jpg)
//macro should be on one line
#define SWAP(a,b) { int tmp=a;
a=b; b=tmp; }int main(void) {
int x=4, y=5, tmp=7;
SWAP(x,y); // Swaps x&y
SWAP(x,tmp); // tmp unchanged
}Why?
![Page 16: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/16.jpg)
Syntactic macros
• Work at the level of abstract syntax trees• From the Lisp family–Why Lisp? Because Lisp programs are
ASTs• Powerful, but expensive• Hygiene is still a major concern, but is
perhaps easier to address at that level
![Page 17: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/17.jpg)
Macro expansion process
AbstractSyntax Tree
(AST)
AbstractSyntax Tree
(AST)Macro
Expander
Essentially this is a source-to-source
compiler
![Page 18: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/18.jpg)
(define-syntax-rule (swap x y)
(let ([tmp x])(set! x y)
(set! y tmp)))
Macros in Racket
![Page 19: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/19.jpg)
(define-syntax-rule (swap x y)(let ([tmp x])(set! x y)
(set! y tmp)))
Macros in Racket
Pattern
![Page 20: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/20.jpg)
(define-syntax-rule (swap x y)
(let ([tmp x])(set! x y)(set! y tmp)))
Macros in Racket
Template
![Page 21: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/21.jpg)
(define-syntax-rule (swap x y)
(let ([tmp x])(set! x y)
(set! y tmp)))
(let ([a 7][b 3])
(swap a b)(displayln a)(displayln b))
Macros in Racket
![Page 22: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/22.jpg)
(define-syntax-rule (swap x y)
(let ([tmp x])(set! x y)
(set! y tmp)))
(let ([a 7][b 3])
(let ([tmp a])(set! a b)(set! b tmp))
(displayln a)
(displayln b))
Expanded code
![Page 23: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/23.jpg)
Macros for JavaScript
• No standard macrosystem for JavaScript.
• Sweet.js has beengaining interest.
• Recent redesign.• http://sweetjs.org/• https://www.sweetjs.org/doc/tutorial.html
![Page 24: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/24.jpg)
Sweet.js high-level
• Source-to-source compiler for JavaScript.–Other s2s compilers for JS:• TypeScript• CoffeeScript• Dart (though also has a VM)
• Project backed by Mozilla• Concepts borrowed from Racket
![Page 25: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/25.jpg)
Prototypal Inheritance
var Droid = {speak: function() {console.log(">>Beep, boop<<, " +
"I am " + this.name);},create: function(name) {var clone = Object.create(this);clone.name = name;return clone;
},};
![Page 26: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/26.jpg)
var areToo =Droid.create('R2-D2');
but we are used to calling:
var bb8 = new Droid('BB8');
We create new droids like so:
![Page 27: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/27.jpg)
Macro
syntax new = function (ctx) {
let ident = ctx.next().value;let params = ctx.next().value;
return #`${ident}.create ${params}`;}
var bb8 = new Droid('BB8');
![Page 28: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/28.jpg)
Translated versionvar Droid_0 = { speak: function speak() {
console.log(">>Beep, boop<<, I am "+ this.name);
}, create: function create(name_8) {var clone_9 = Object.create(this);clone_9.name = name_8;return clone_9;
} };var bb8_7 = Droid_0.create("BB8");
![Page 29: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/29.jpg)
Installing Sweet.js
From a Unix/Dos command line:
$npm install -g @sweet-js/cli$npm install @sweet-js/helpers
![Page 30: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/30.jpg)
Invoking Sweet.js
• Compile your code:$sjs myfile.js -d out/
• Then you may run the output file normally:$node out/myfile.js
![Page 31: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/31.jpg)
syntax swap = function (ctx) {
var a = ctx.next().value;
var b = ctx.next().value;
return #`var tmp =${a}; ${a}=${b}; ${b}=tmp;`;
}
var a = 10; var b = 20;
console.log("a:" + a + " b:" + b);
swap a b;console.log("a:" + a + " b:" + b);
![Page 32: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/32.jpg)
Iterating over syntax
![Page 33: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/33.jpg)
syntax square = function (ctx) {
var inCtx = ctx.contextify(ctx.next().value);
var result = #``;
var stx;
for (stx of inCtx) {
result = result.concat(
#`${stx} = ${stx}*${stx};`);
inCtx.next(); // Eating comma
}
return result;
}
var a = 1; var b = 2; var c = 3;
square(a, b, c);
console.log("a:"+a+" b:"+b+" c:"+c);
![Page 34: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/34.jpg)
Output
var a_5 = 1;var b_6 = 2;var c_7 = 3;a_5 = a_5 * a_5;b_6 = b_6 * b_6;c_7 = c_7 * c_7;console.log("a:" + a_5 + " b:" +
b_6 + " c:" + c_7);
![Page 35: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/35.jpg)
Sweet.js helper functions
import { isStringLiteral }from '@sweet-js/helpers' for syntax;
syntax m = function(ctx) {if (isStringLiteral(ctx.next().value))
return #`'a string'`;else
return #`'not a string'`;}m 'foo';m 42;var s = "hello";m s;
![Page 36: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/36.jpg)
Adding classes to JavaScript.(in class)
![Page 37: Macros & Sweet · 2017. 11. 13. · •Text substitution macros –text is converted to text. •Embedded languages are similar –PHP, Ruby's erb, etc. Lexer/ Tokenizer Parser source](https://reader035.vdocuments.mx/reader035/viewer/2022071514/613655e10ad5d2067647f51b/html5/thumbnails/37.jpg)
Lab
Create a rotate macro in Sweet.jsthat works like the swap macro, except that it takes an arbitrary number of arguments.
There is no starter code for this lab.