Skip to content

Commit f9420c1

Browse files
committed
Add function declaration macro
Shares code with function expressions. These are necessary to be able to write also, due to various interesting differences: https://javascriptweblog.wordpress.com/2010/07/06/function-declarations-vs-function-expressions/ Fixes #21.
1 parent a503a26 commit f9420c1

File tree

3 files changed

+77
-47
lines changed

3 files changed

+77
-47
lines changed

doc/basics-reference.markdown

Lines changed: 42 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -149,31 +149,32 @@ generate arbitrary JavaScript are built in to eslisp.
149149

150150
### General
151151

152-
| name | description |
153-
| ---------- | ---------------------------- |
154-
| `array` | array literal |
155-
| `object` | object literal |
156-
| `regex` | regular expression literal |
157-
| `var` | variable declaration |
158-
| `.` | member expression |
159-
| `get` | *computed* member expression |
160-
| `switch` | switch statement |
161-
| `if` | conditional statement |
162-
| `?:` | ternary expression |
163-
| `while` | while loop |
164-
| `dowhile` | do-while loop |
165-
| `for` | for loop |
166-
| `forin` | for-in loop |
167-
| `break` | break statement |
168-
| `continue` | continue statement |
169-
| `label` | labeled statement |
170-
| `label` | labeled statement |
171-
| `function` | function expression |
172-
| `return` | return statement |
173-
| `new` | new-expression |
174-
| `debugger` | debugger statement |
175-
| `throw` | throw statement |
176-
| `try` | try-catch statement |
152+
| name | description |
153+
| ----------------- | ---------------------------- |
154+
| `array` | array literal |
155+
| `object` | object literal |
156+
| `regex` | regular expression literal |
157+
| `var` | variable declaration |
158+
| `.` | member expression |
159+
| `get` | *computed* member expression |
160+
| `switch` | switch statement |
161+
| `if` | conditional statement |
162+
| `?:` | ternary expression |
163+
| `while` | while loop |
164+
| `dowhile` | do-while loop |
165+
| `for` | for loop |
166+
| `forin` | for-in loop |
167+
| `break` | break statement |
168+
| `continue` | continue statement |
169+
| `label` | labeled statement |
170+
| `label` | labeled statement |
171+
| `function` | function expression |
172+
| `declarefunction` | function declaration |
173+
| `return` | return statement |
174+
| `new` | new-expression |
175+
| `debugger` | debugger statement |
176+
| `throw` | throw statement |
177+
| `try` | try-catch statement |
177178

178179
#### Structural
179180

@@ -414,6 +415,8 @@ the `default`-case clause.
414415

415416
### Functions
416417

418+
#### Function expressions
419+
417420
The `function` macro creates function expressions. Its first argument becomes
418421
the argument list, and the rest become statements in its body. The `return`
419422
macro compiles to a return-statement.
@@ -429,7 +432,6 @@ macro compiles to a return-statement.
429432
return 5 * (a * b);
430433
};
431434

432-
433435
You can also give a name to a function expression as the optional first
434436
argument, if you so wish.
435437

@@ -443,6 +445,20 @@ argument, if you so wish.
443445
return 'T';
444446
};
445447

448+
#### Function declarations
449+
450+
These work much like function expressions above, but require a name.
451+
452+
<!-- !test in function declaration -->
453+
454+
(declarefunction tea () (return "T"))
455+
456+
<!-- !test out function declaration -->
457+
458+
function tea() {
459+
return 'T';
460+
}
461+
446462
### Loops
447463

448464
While-loops (with the `while` macro) take the first argument to be the loop

src/built-in-macros.ls

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,31 @@ optionally-implicit-block-statement = ({compile, compile-many}, body) ->
8181
type : \BlockStatement
8282
body : compile-many body .map statementify
8383

84+
# Here's a helper that extracts the common parts to macros for
85+
# FunctionExpressions and FunctionDeclarations since they're so similar.
86+
function-type = (type) ->
87+
({compile, compile-many}:env, ...args) ->
88+
# The first optional atom argument gives the id that should be attached to
89+
# the function expression. The next argument is the function's argument
90+
# list. All further arguments are statements for the body.
91+
92+
var id, params
93+
94+
arg1 = args.shift!
95+
96+
if arg1 instanceof atom
97+
id := type : \Identifier name : arg1.text!
98+
params := args.shift! .contents!map compile
99+
else
100+
# Let's assume it's a list then
101+
id := null
102+
params := arg1.contents!map compile
103+
104+
type : type
105+
id : id
106+
params : params
107+
body : optionally-implicit-block-statement env, args
108+
84109
contents =
85110
\+ : n-ary-expr \+
86111
\- : n-ary-expr \-
@@ -298,28 +323,9 @@ contents =
298323
throw Error "dot called with no arguments"
299324

300325

301-
\function : ({compile, compile-many}:env, ...args) ->
326+
\function : function-type \FunctionExpression
302327

303-
# The first optional atom argument gives the id that should be attached to
304-
# the function expression. The next argument is the function's argument
305-
# list. All further arguments are statements for the body.
306-
307-
var id, params
308-
309-
arg1 = args.shift!
310-
311-
if arg1 instanceof atom
312-
id := type : \Identifier name : arg1.text!
313-
params := args.shift! .contents!map compile
314-
else
315-
# Let's assume it's a list then
316-
id := null
317-
params := arg1.contents!map compile
318-
319-
type : \FunctionExpression
320-
id : id
321-
params : params
322-
body : optionally-implicit-block-statement env, args
328+
\declarefunction : function-type \FunctionDeclaration
323329

324330
\new : ({compile}, ...args) ->
325331
[ newTarget, ...newArgs ] = args

test.ls

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,14 @@ test "function expression with name" ->
170170
esl "(function f (x) (return (+ x 1)))"
171171
..`@equals` "(function f(x) {\n return x + 1;\n});"
172172

173+
test "function declaration" ->
174+
esl "(declarefunction f (x) (return (+ x 1)))"
175+
..`@equals` "function f(x) {\n return x + 1;\n}"
176+
177+
test "function declaration without name throws error" ->
178+
-> esl "(declarefunction (x) (return (+ x 1)))"
179+
..`@throws` Error
180+
173181
test "function with no arguments" ->
174182
esl "(function () (return 1))"
175183
..`@equals` "(function () {\n return 1;\n});"

0 commit comments

Comments
 (0)